[
  {
    "path": ".claude/commands/revise-agents-md.md",
    "content": "Review this session for learnings about working with Agents in this codebase. Update AGENTS.md with context that would help future Agent sessions be more effective.\n\n## Step 1: Reflect\n\nWhat context was missing that would have helped Agents work more effectively?\n\n- Bash commands that were used or discovered\n- Code style patterns followed\n- Testing approaches that worked\n- Environment/configuration quirks\n- Warnings or gotchas encountered\n\n## Step 2: Find AGENTS.md Files\n\n```bash\nfind . -name \"AGENTS.md\" 2>/dev/null | head -20\n```\n\n## Step 3: Draft Additions\n\n**Keep it concise** - one line per concept. AGENTS.md is part of the prompt, so brevity matters.\n\nFormat: `<command or pattern>` - `<brief description>`\n\nAvoid:\n\n- Verbose explanations\n- Obvious information\n- One-off fixes unlikely to recur\n\n## Step 4: Show Proposed Changes\n\nFor each addition:\n\n```\n### Update: ./AGENTS.md\n\n**Why:** [one-line reason]\n\n\\`\\`\\`diff\n+ [the addition - keep it brief]\n\\`\\`\\`\n```\n\n## Step 5: Apply with Approval\n\nAsk if the user wants to apply the changes. Only edit files they approve.\n"
  },
  {
    "path": ".claude/settings.json",
    "content": "{\n  \"permissions\": {\n    \"allow\": [\"Bash(yarn dev-server:*)\", \"Bash(agent-browser:*)\"]\n  }\n}\n"
  },
  {
    "path": ".claude/skills/manual-testing/SKILL.md",
    "content": "---\nname: manual-testing\ndescription: Run a manual test of the current change end-to-end and output reproducible test instructions for the PR \"Test instructions\" section.\n---\n\n## Step 1: Understand the change\n\nReview the current diff to identify what SDK behavior changed and what events/fields need to be verified.\n\n## Step 2: Start the dev server\n\nThe dev server serves the `sandbox/` directory and proxies intake requests locally. Use `yarn dev-server --help` to list all available commands.\n\n```bash\nyarn dev-server start\n```\n\n## Step 3: Create a temporary sandbox page\n\nCreate `sandbox/test-<topic>.html`. See `sandbox/index.html` for a minimal example. Include only the elements needed to exercise the change. Always use `proxy: '/proxy'`.\n\n```bash\ncat > sandbox/test-<topic>.html << 'EOF'\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Test <topic></title>\n    <script src=\"/datadog-rum.js\"></script>\n    <script>\n      DD_RUM.init({ clientToken: 'xxx', applicationId: 'xxx', proxy: '/proxy', trackUserInteractions: true })\n    </script>\n  </head>\n  <body>\n    <!-- elements needed to exercise the change -->\n  </body>\n</html>\nEOF\n```\n\n## Step 4: Run the test flow\n\nGet the dev server URL from `yarn dev-server status`. Clear any previous intake data, open the page, interact with it using CSS selectors, flush events by opening a new tab or reloading, then inspect the intake:\n\n```bash\nyarn dev-server intake clear\nagent-browser open <dev-server-url>/test-<topic>.html\nagent-browser click '#...'\nagent-browser tab new\nyarn dev-server intake <selector> | jq '<field>'\n```\n\nUse `yarn dev-server intake --help` to find the right selector.\n\n## Step 5: Verify the output matches expectations, then present the test instructions\n\nOutput a self-contained bash snippet with the exact commands run and the expected output. This goes directly into the PR \"Test instructions\" section.\n\n## Step 6: Clean up\n\n```bash\nyarn dev-server stop\nrm sandbox/test-<topic>.html\n```\n"
  },
  {
    "path": ".cursor/rules/test-driven-development.mdc",
    "content": "---\ndescription: Standards for Test-Driven Development in the Browser SDK project\nglobs:\ntags:\n  - jasmine\n  - karma\nalwaysApply: true\n---\n\n# Test-Driven Development (TDD) Rule\n\n## 1. RED-GREEN-REFACTOR Cycle\n\n**ALWAYS follow this sequence:**\n1. 🔴 **RED**: Write failing test first\n2. 🟢 **GREEN**: Write minimal code to make test pass\n3. 🔵 **REFACTOR**: Improve code while keeping tests green\n\n## 2. Spec First, Code Second\n\n**Before writing ANY implementation:**\n```bash\n# Check for existing spec file\nls packages/some-package/src/path/to/feature.spec.ts\n\n# If missing, create spec file first\ntouch packages/some-package/src/path/to/feature.spec.ts\n```\n\n**Spec file must exist BEFORE implementation file**\n\n## 3. Spec Structure (Jasmine/Karma)\n\n```typescript\ndescribe('FeatureName', () => {\n// Setup variables\nlet feature: FeatureType\nlet mockDependency: MockType\n\nbeforeEach(() => {\n    // Setup for each test\n    mockDependency = jasmine.createSpy()\n    feature = new FeatureName(mockDependency)\n\n    // Use registerCleanupTask for cleanup\n    registerCleanupTask(() => {\n    feature.dispose()\n    })\n})\n\ndescribe('when condition', () => {\n    it('should behave correctly', () => {\n    // Arrange\n    const input = 'test-input'\n\n    // Act\n    const result = feature.process(input)\n\n    // Assert\n    expect(result).toBe(expectedOutput)\n    expect(mockDependency).toHaveBeenCalledWith(input)\n    })\n\n    it('should handle edge cases', () => {\n    // Test edge cases, errors, boundaries\n    })\n})\n})\n```\n\n## 4. Implementation Process\n\n**Step-by-step workflow:**\n\n1. **Analyze Requirements**\n    - Understand the feature/bug\n    - Identify acceptance criteria\n    - Consider edge cases\n\n2. **Create/Review Spec**\n\n3. **Run Tests (Should Fail)**\n    ```bash\n    yarn test:unit\n    # Verify test fails for the right reason\n    ```\n\n4. **Implement Minimal Code**\n\n5. **Run Tests (Should Pass)**\n    ```bash\n    yarn test:unit\n    # Verify test passes\n    ```\n\n6. **Refactor & Add More Tests**\n    - Improve implementation\n    - Add edge case tests\n    - Ensure all tests still pass\n\n## 5. Browser SDK Specific Patterns\n\n**Use established test utilities:**\n[unit-test.mdc](mdc:.cursor/rules/unit-test.mdc)\n\n**Follow co-location pattern:**\n```\nsrc/\n├── domain/\n│   ├── feature.ts          ← Implementation\n│   ├── feature.spec.ts     ← Tests (co-located)\n│   └── anotherFeature.ts\n```\n\n## 8. Error Prevention Rules\n\n**❌ NEVER do this:**\n- Write implementation without tests\n- Skip edge case testing\n- Leave failing tests\n- Forget cleanup tasks\n- Use real timers in tests\n- Test multiple behaviors in one test\n\n**✅ ALWAYS do this:**\n- Write test first\n- Use `registerCleanupTask` for cleanup\n- Mock external dependencies\n- Test both success and failure paths\n- Use descriptive test names\n- Follow existing patterns in codebase\n\nRemember: **Tests are documentation**. Write them as if explaining the feature to a new team member.\n"
  },
  {
    "path": ".cursor/rules/unit-test-best-practices.mdc",
    "content": "---\ndescription: \nglobs: **/*.spec.ts\nalwaysApply: false\n---\n## Running Unit Tests\n\n### Basic Commands\n\n- **Run all unit tests**: `yarn test:unit`\n- **Run a specific spec file**: `yarn test:unit --spec <file-path>`\n- **Focus on specific tests**: Prepend `f` to `describe` and `it` (e.g., `fdescribe`, `fit`)\n\n### Examples\n\n#### Run All Tests\n```bash\nyarn test:unit\n```\n\n#### Run Single File\n```bash\n# Full path\nyarn test:unit --spec packages/core/src/browser/addEventListener.spec.ts\n\n# Pattern matching (if filename is unique)\nyarn test:unit --spec \"packages/**/addEventListener.spec.ts\"\n\n# Multiple files with wildcards\nyarn test:unit --spec \"packages/core/**/browser/*.spec.ts\"\n```\n\n#### Focus on Specific Tests\n```typescript\n// Run only this describe block\nfdescribe('addEventListener', () => {\n  // All tests in this block will run\n  it('should add event listener', () => {})\n  it('should remove event listener', () => {})\n})\n\n// Run only this single test\ndescribe('addEventListener', () => {\n  fit('should add event listener', () => {\n    // Only this test will run\n  })\n\n  it('should remove event listener', () => {\n    // This test will be skipped\n  })\n})\n```\n\n#### Test observable/callback cleanup\n- **Subscription Management**: Testing that event subscriptions are properly cleaned up\n- **DOM Event Cleanup**: Ensuring event listeners are removed from DOM elements\n- **Timer Cleanup**: Verifying that intervals and timeouts are cleared\n- **Async Operation Cancellation**: Testing that pending promises/callbacks are cancelled\n- **Observable**: Ensuring observers are unsubscribed and streams are completed\n- **Memory Leak Detection**: Patterns for detecting memory leaks in tests\n\n## Debugging Flaky Tests\n\n```bash\n# 1. Check test output for randomization seed\nyarn test:unit\n# Look for: \"Randomized with seed 65781\"\n\n# 2. Set seed in karma configuration\n# Edit test/unit/karma.base.conf.js:\nmodule.exports = {\n  // ... other config\n  client: {\n    jasmine: {\n      // ... other jasmine config\n      seed: 65781  // Use the seed from step 1\n    }\n  }\n}\n\n# 3. Run tests with the same order\nyarn test:unit\n\n# 4. Remove seed after debugging\n```\n\n### File Organization\n- **Co-location**: Test files use `.spec.ts` extension and are placed next to source files\n- **Naming pattern**: `sourceFile.ts` → `sourceFile.spec.ts`\n- **Auto-discovery**: Tests are found via glob: `packages/*/@(src|test)/**/*.spec.@(ts|tsx)`\n\n## Common Anti-Patterns to Avoid\n\n### ❌ Don't Do This\n\n```typescript\n// DON'T: Use afterEach for cleanup - may not run if test fails\nafterEach(() => {\n  subscription.unsubscribe()  // Might not execute\n  element.remove()           // Memory leak potential\n})\n\n// DON'T: Create DOM manually\nit('should test DOM interaction', () => {\n  const element = document.createElement('div')\n  document.body.appendChild(element)\n  // Missing cleanup - memory leak!\n  // use appendElement helper!\n})\n\n// DON'T: Use real timers - makes tests slow and flaky\nit('should handle delayed action', (done) => {\n  setTimeout(() => {\n    expect(something).toBeTruthy()\n    done()\n  }, 1000) // Real 1-second delay!\n})\n\n// DON'T: Test multiple unrelated behaviors\nit('should do everything', () => {\n  // Setup user\n  const user = createUser()\n  expect(user.id).toBeDefined()\n\n  // Test login\n  user.login()\n  expect(user.isLoggedIn).toBeTruthy()\n\n  // Test permissions\n  expect(user.hasPermission('admin')).toBeFalsy()\n\n  // Test logout\n  user.logout()\n  expect(user.isLoggedIn).toBeFalsy()\n  // Hard to debug when one part fails!\n})\n\n// DON'T: Use vague test names\nit('should work', () => {\n  // What should work? How?\n})\n\nit('should test the function', () => {\n  // Which function? What aspect?\n})\n```\n\n### ✅ Do This Instead\n\n```typescript\n// DO: Use registerCleanupTask for reliable cleanup\nbeforeEach(() => {\n  const subscription = observable.subscribe(handler)\n  registerCleanupTask(() => subscription.unsubscribe())\n\n  const element = document.createElement('div')\n  document.body.appendChild(element)\n  registerCleanupTask(() => element.parentNode?.removeChild(element))\n})\n\n// DO: use existing helpers\n  it('should add DOM with appendElement helper', () => {\n  appendElement('<input type=\"checkbox\" id=\"test-checkbox\" />')\n  const label = appendElement('<label for=\"test-checkbox\">Check me</label>')\n})\n\n// DO: Use mocked clock for time-based tests\nbeforeEach(() => {\n  clock = mockClock()\n})\nit('should handle delayed operations', () => {\n  const callback = jasmine.createSpy()\n  setTimeout(callback, 1000)\n\n  clock.tick(1000) // Instant!\n  expect(callback).toHaveBeenCalled()\n})\n\n// DO: One focused assertion per test\ndescribe('User', () => {\n  it('should generate unique ID on creation', () => {\n    const user = createUser()\n    expect(user.id).toMatch(/^user-\\d+$/)\n  })\n\n  it('should start in logged-out state', () => {\n    const user = createUser()\n    expect(user.isLoggedIn).toBeFalsy()\n  })\n\n  it('should allow login with valid credentials', () => {\n    const user = createUser()\n    user.login('valid@email.com', 'password')\n    expect(user.isLoggedIn).toBeTruthy()\n  })\n\n  it('should deny admin permissions to regular user', () => {\n    const user = createUser()\n    expect(user.hasPermission('admin')).toBeFalsy()\n  })\n})\n\n// DO: Use descriptive, specific test names\nit('should generate SHA-256 hash for user password', () => {\n  // Clear what's being tested\n})\n\nit('should throw ValidationError when email format is invalid', () => {\n  // Clear behavior and expected outcome\n})\n```\n"
  },
  {
    "path": ".env.example",
    "content": "# BROWSERSTACK CREDENTIALS\nBS_USERNAME=xxx\nBS_ACCESS_KEY=xxx\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "# Order is important, the last matching pattern takes the most precedence.\n\n# Default\n*    @Datadog/rum-browser\n\n# Global\npackages/rum/src/domain/record/**               @Datadog/rum-browser @Datadog/session-replay-sdk\npackages/rum/src/domain/segmentCollection/**    @Datadog/rum-browser @Datadog/session-replay-sdk\npackages/rum/src/domain/*.ts                    @Datadog/rum-browser @Datadog/session-replay-sdk\npackages/rum/test/record/**                     @Datadog/rum-browser @Datadog/session-replay-sdk\ntest/e2e/scenario/recorder/**                   @Datadog/rum-browser @Datadog/session-replay-sdk\n\n# Docs\n/README.md    @Datadog/rum-browser @DataDog/documentation\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"\\U0001F41B My bug title\"\nlabels: bug\nassignees: ''\n---\n\n<!-- Guidelines -->\n<!-- Please check if an issue does not exist already for it: https://github.com/DataDog/browser-sdk/issues -->\n<!-- Please check if the issue happens with latest version -->\n\n**Describe the bug**\nA clear and concise description of what the bug is and on which product (`rum`, `logs`).\n\n**To Reproduce**\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"\\U0001F4A1 My feature title\"\nlabels: enhancement\nassignees: ''\n---\n\nPlease contact [support](https://www.datadoghq.com/support/) to open a feature request.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/support-needed.md",
    "content": "---\nname: Support needed\nabout: Request some support related to this project\ntitle: \"\\U0001F64F My support need\"\nlabels: ''\nassignees: ''\n---\n\n<!-- Guidelines -->\n<!-- Please check if an issue does not exist already for it: https://github.com/DataDog/browser-sdk/issues -->\n<!-- Please check if the issue happens with latest version -->\n\n**What are you trying to achieve and what is your issue? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Motivation\n\n<!-- Why are you making this change, what problem does it solve? Include links to relevant tickets. -->\n\n## Changes\n\n<!-- What does this change exactly? Who will be affected? Include relevant screenshots, videos, links. Please highlight all the changes that you are not sure about (ex: AI agent generated) -->\n\n## Test instructions\n\n<!-- How can the reviewer test this change? Include relevant steps to reproduce the issue, if any. -->\n\n## Checklist\n\n<!-- By submitting this test, you confirm the following: -->\n\n- [ ] Tested locally\n- [ ] Tested on staging\n- [ ] Added unit tests for this change.\n- [ ] Added e2e/integration tests for this change.\n- [ ] Updated documentation and/or relevant AGENTS.md file\n\n<!-- Also, please read the contribution guidelines: https://github.com/DataDog/browser-sdk/blob/main/CONTRIBUTING.md -->\n"
  },
  {
    "path": ".github/chainguard/self.gitlab.pull_request.sts.yaml",
    "content": "issuer: https://gitlab.ddbuild.io\n\nsubject_pattern: 'project_path:DataDog/browser-sdk:ref_type:branch:ref:main'\n\nclaim_pattern:\n  project_path: 'DataDog/browser-sdk'\n  ref_type: 'branch'\n  ref: 'main'\n\npermissions:\n  pull_requests: write\n"
  },
  {
    "path": ".github/chainguard/self.gitlab.read.sts.yaml",
    "content": "issuer: https://gitlab.ddbuild.io\n\nsubject_pattern: 'project_path:DataDog/browser-sdk:.*'\n\nclaim_pattern:\n  project_path: 'DataDog/browser-sdk'\n\npermissions:\n  contents: read\n"
  },
  {
    "path": ".github/chainguard/self.gitlab.release.sts.yaml",
    "content": "issuer: https://gitlab.ddbuild.io\n\nsubject_pattern: 'project_path:DataDog/browser-sdk:ref_type:tag.*'\n\nclaim_pattern:\n  project_path: 'DataDog/browser-sdk'\n  ref_type: 'tag'\n\npermissions:\n  contents: write\n"
  },
  {
    "path": ".github/codeql-config.yml",
    "content": "name: 'CodeQL config'\n\npaths:\n  - packages/core/src\n  - packages/logs/src\n  - packages/rum/src\n  - packages/rum-core/src\n  - packages/rum-slim/src\n  - packages/worker/src\npaths-ignore:\n  - '**/*.spec.ts'\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Note: While we mainly use Renovate, Dependabot is used for security updates\n\nversion: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: 'daily'\n    open-pull-requests-limit: 0\n    commit-message:\n      prefix: '👷'\n\n  - package-ecosystem: npm\n    directory: /\n    schedule:\n      interval: 'daily'\n    open-pull-requests-limit: 0\n    commit-message:\n      prefix: '👷'\n    ignore:\n      # update karma-webpack: RUM-3130\n      - dependency-name: 'karma-webpack'\n"
  },
  {
    "path": ".github/workflows/changelog-to-confluence.yml",
    "content": "name: Publish Changelog to Confluence\npermissions:\n  contents: read\non:\n  push:\n    tags:\n      - 'v*.*.*' # Matches version tags like v1.0.0, v6.7.0, etc.\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Prepare Only Changelog\n        run: |\n          mkdir -p publish_folder\n          cp CHANGELOG.md publish_folder/browser-sdk-changelog.md\n          echo \"Publishing only CHANGELOG.md\"\n\n      - name: Publish Markdown to Confluence\n        uses: markdown-confluence/publish-action@7767a0a7f438bb1497ee7ffd7d3d685b81dfe700 # v5\n        with:\n          confluenceBaseUrl: ${{ secrets.DATADOG_CONFLUENCE_BASE_URL }}\n          confluenceParentId: ${{ secrets.CONFLUENCE_PARENT_ID }}\n          atlassianUserName: ${{ secrets.CONFLUENCE_ROBOT_RUM_EMAIL }}\n          atlassianApiToken: ${{ secrets.CONFLUENCE_ROBOT_RUM_API_KEY }}\n          contentRoot: '.'\n          folderToPublish: 'publish_folder'\n"
  },
  {
    "path": ".github/workflows/cla.yml",
    "content": "name: 'CLA Assistant'\non:\n  issue_comment:\n    types: [created]\n  pull_request_target:\n    types: [opened, closed, synchronize]\n  merge_group:\n    types: [checks_requested]\n\npermissions:\n  contents: read\n  pull-requests: write\n  id-token: write # Needed to federate tokens.\n  actions: write\n\njobs:\n  CLAAssistant:\n    runs-on: ubuntu-latest\n    steps:\n      - name: CLA already verified on PR\n        if: github.event_name == 'merge_group'\n        run: echo \"CLA verification not needed for merge queue - already checked on PR\"\n\n      - uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4\n        if: github.event_name != 'merge_group'\n        id: octo-sts\n        with:\n          scope: DataDog/cla-signatures\n          policy: self.write-signatures-browser-sdk\n\n      - name: 'CLA Assistant'\n        if: github.event_name != 'merge_group' && ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target')\n        uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PERSONAL_ACCESS_TOKEN: ${{ steps.octo-sts.outputs.token }}\n        with:\n          path-to-signatures: 'browser-sdk.json'\n          path-to-document: 'https://gist.github.com/bits-bot/55bdc97a4fdad52d97feb4d6c3d1d618' # Datadog CLA Document\n          branch: 'browser-sdk'\n          remote-repository-name: cla-signatures\n          remote-organization-name: DataDog\n          allowlist: renovate,renovate[bot],campaigner-prod,gh-worker-dd-devflow-*,dd-devflow[bot],ci.browser-sdk\n\n          # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken\n          #allowlist: user1,bot*\n          #create-file-commit-message: 'For example: Creating file for storing CLA Signatures'\n          #signed-commit-message: 'For example: $contributorName has signed the CLA in $owner/$repo#$pullRequestNo'\n          #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign'\n          #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA'\n          #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.'\n          #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true)\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "name: 'CodeQL'\n\non:\n  push:\n    branches: ['main']\n  pull_request:\n    branches: ['main']\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1\n        with:\n          languages: javascript\n          config-file: .github/codeql-config.yml\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1\n"
  },
  {
    "path": ".github/workflows/deploy-generated-docs.yml",
    "content": "name: Deploy docs on tag\n\non:\n  push:\n    tags:\n      - 'v*.*.*'\n\n  workflow_dispatch:\n\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\nconcurrency:\n  group: 'pages'\n  cancel-in-progress: false\n\njobs:\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Check out code at tag\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          fetch-depth: 0\n\n      - name: Setup Node.js\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0\n        with:\n          node-version: '23'\n          cache: 'yarn'\n\n      - name: Install dependencies\n        run: yarn install --immutable\n\n      - name: Build SDK\n        run: yarn build\n\n      - name: Build documentation\n        run: yarn build:docs:html\n\n      - name: Setup Pages\n        uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0\n\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0\n        with:\n          path: './generated-docs'\n\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5\n"
  },
  {
    "path": ".github/workflows/shadow-review.yml",
    "content": "# shadow-review.yml — Shadow Reviewer workflow\n# Source: https://github.com/DataDog/rum-ai-toolkit\nname: Shadow Review\n\non:\n  pull_request:\n    types: [opened, synchronize, ready_for_review]\n\njobs:\n  # Mirror PR to shadow fork (review + post-close disabled for now)\n  # Fork sync not needed — each shadow PR targets its own base ref\n  shadow-mirror:\n    if: >-\n      github.event_name == 'pull_request'\n      && github.event.pull_request.draft != true\n      && github.event.pull_request.user.type != 'Bot'\n    runs-on: ubuntu-latest\n    steps:\n      - name: Mirror PR to shadow fork\n        env:\n          GITHUB_TOKEN: ${{ github.token }}\n          SHADOW_FORK_TOKEN: ${{ secrets.SHADOW_FORK_TOKEN }}\n          SOURCE_REPO: ${{ github.repository }}\n          SHADOW_FORK: ${{ vars.SHADOW_FORK }}\n          PR_NUMBER: ${{ github.event.pull_request.number }}\n          PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n          PR_BASE_REF: ${{ github.event.pull_request.base.ref }}\n          PR_TITLE: ${{ github.event.pull_request.title }}\n          PR_BODY: ${{ github.event.pull_request.body }}\n        run: |\n          set -euo pipefail\n          # Mask tokens in trace output\n          echo \"::add-mask::${SHADOW_FORK_TOKEN}\"\n          echo \"::add-mask::${GITHUB_TOKEN}\"\n          set -x\n\n          WORK_DIR=$(mktemp -d)\n          trap 'rm -rf \"${WORK_DIR}\"' EXIT\n\n          echo \"=== Pre-flight checks ===\"\n          echo \"SOURCE_REPO: ${SOURCE_REPO}\"\n          echo \"SHADOW_FORK: ${SHADOW_FORK}\"\n          echo \"PR_NUMBER: ${PR_NUMBER}\"\n          echo \"PR_HEAD_SHA: ${PR_HEAD_SHA}\"\n          echo \"PR_BASE_REF: ${PR_BASE_REF}\"\n\n          # Verify shadow fork access (using shadow fork token)\n          echo \"Verifying access to shadow fork...\"\n          if ! GITHUB_TOKEN=\"${SHADOW_FORK_TOKEN}\" gh repo view \"${SHADOW_FORK}\" > /dev/null 2>&1; then\n            echo \"ERROR: Cannot access shadow fork ${SHADOW_FORK}\"\n            echo \"Ensure SHADOW_FORK_TOKEN has repo access and SHADOW_FORK variable is set correctly\"\n            exit 1\n          fi\n          echo \"Shadow fork accessible\"\n\n          # Verify source repo access (using default token)\n          echo \"Verifying access to source repo...\"\n          if ! gh repo view \"${SOURCE_REPO}\" > /dev/null 2>&1; then\n            echo \"ERROR: Cannot access source repo ${SOURCE_REPO}\"\n            exit 1\n          fi\n          echo \"Source repo accessible\"\n\n          echo \"=== Mirroring PR #${PR_NUMBER} (${PR_HEAD_SHA}) to ${SHADOW_FORK} ===\"\n\n          # Determine version number by counting existing shadow branches (exclude -base)\n          VERSION=$(git ls-remote --heads \"https://x-access-token:${SHADOW_FORK_TOKEN}@github.com/${SHADOW_FORK}.git\" \"shadow/${PR_NUMBER}/v*\" 2>/dev/null \\\n            | { grep -v '\\-base$' || true; } | wc -l | tr -d ' ')\n          VERSION=$((VERSION + 1))\n          echo \"Version: v${VERSION}\"\n\n          SHADOW_BRANCH=\"shadow/${PR_NUMBER}/v${VERSION}\"\n          BASE_BRANCH=\"shadow/${PR_NUMBER}/v${VERSION}-base\"\n\n          # Clone source repo and fetch PR ref\n          echo \"Cloning source repo...\"\n          git clone --no-checkout \"https://x-access-token:${GITHUB_TOKEN}@github.com/${SOURCE_REPO}.git\" \"${WORK_DIR}/repo\"\n          cd \"${WORK_DIR}/repo\"\n          echo \"Fetching PR head...\"\n          git fetch origin \"pull/${PR_NUMBER}/head:pr-head\"\n          echo \"Fetching base ref...\"\n          git fetch origin \"${PR_BASE_REF}:base-ref\"\n\n          # Compute merge base\n          MERGE_BASE=$(git merge-base pr-head base-ref)\n          echo \"Merge base: ${MERGE_BASE}\"\n\n          # Push base and head branches to shadow fork\n          git remote add shadow \"https://x-access-token:${SHADOW_FORK_TOKEN}@github.com/${SHADOW_FORK}.git\"\n\n          echo \"Pushing base branch...\"\n          git push shadow \"${MERGE_BASE}:refs/heads/${BASE_BRANCH}\" 2>&1 || {\n            echo \"Push failed — retrying with incremented version...\"\n            VERSION=$((VERSION + 1))\n            SHADOW_BRANCH=\"shadow/${PR_NUMBER}/v${VERSION}\"\n            BASE_BRANCH=\"shadow/${PR_NUMBER}/v${VERSION}-base\"\n            git push shadow \"${MERGE_BASE}:refs/heads/${BASE_BRANCH}\" 2>&1\n          }\n\n          echo \"Pushing head branch...\"\n          git push shadow \"${PR_HEAD_SHA}:refs/heads/${SHADOW_BRANCH}\" 2>&1\n\n          # Create shadow PR\n          # Escape #123-style references to prevent GitHub cross-linking\n          ESCAPED_PR_BODY=$(echo \"${PR_BODY}\" | sed -E 's/#([0-9]+)/`#\\1`/g')\n\n          echo \"Creating shadow PR...\"\n          SHADOW_PR_URL=$(GITHUB_TOKEN=\"${SHADOW_FORK_TOKEN}\" gh pr create \\\n            --repo \"${SHADOW_FORK}\" \\\n            --base \"${BASE_BRANCH}\" \\\n            --head \"${SHADOW_BRANCH}\" \\\n            --title \"Shadow: ${PR_TITLE} (v${VERSION})\" \\\n            --body \"## Shadow Review — PR \\`#${PR_NUMBER}\\` v${VERSION}\n\n          **Source:** \\`${SOURCE_REPO}#${PR_NUMBER}\\`\n          **Commit:** \\`${PR_HEAD_SHA}\\`\n          **Timestamp:** $(date -u +%Y-%m-%dT%H:%M:%SZ)\n\n          ---\n\n          ## Original PR Description\n\n          ${ESCAPED_PR_BODY}\")\n\n          echo \"Shadow PR created: ${SHADOW_PR_URL}\"\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: 'Automatically close stale issues'\n\non:\n  schedule:\n    # Runs every day at 8:00 AM CET\n    - cron: '0 7 * * *'\n  workflow_dispatch:\n\npermissions:\n  issues: write\n  pull-requests: write\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0\n        with:\n          # See documentation at https://github.com/actions/stale?tab=readme-ov-file#all-options\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n\n          stale-issue-message: |\n            This issue has been automatically marked as stale because it has not had recent activity and has the `need-info` label.\n\n            It will be closed if no further activity occurs within 3 days.\n\n          stale-pr-message: |\n            This pull request has been automatically marked as stale because it has not had recent activity and has the `need-info` label.\n\n            It will be closed if no further activity occurs within 3 days.\n\n          stale-issue-label: 'stale'\n          close-issue-label: 'automatically closed'\n          only-labels: 'need-info'\n          days-before-issue-stale: 14\n          days-before-issue-close: 3\n"
  },
  {
    "path": ".gitignore",
    "content": "bundle\ncjs\nesm\nnode_modules\ncoverage\ntunnel.log\nlocal.log\n.dev-server/\nspecs.log\n/test-report/\nbrowserstack.err\npackage.tgz\ngenerated-docs/\n*.tsbuildinfo\n/developer-extension/dist\n/developer-extension/.wxt\n.env*\n!.env.example\n.rum-ai-toolkit/\n\n# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored\n.pnp.*\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n/blob-report/\n/playwright/.cache/\ntest-results/\nplaywright-report/\n.vscode\n\n# Claude Code local files\n*.local.md\n.claude/settings.local.json\n"
  },
  {
    "path": ".gitlab/deploy-auto.yml",
    "content": "stages:\n  - pre-notify\n  - deploy\n  - post-notify\n\n.base-configuration:\n  tags:\n    - 'arch:amd64'\n  image: $CI_IMAGE\n  id_tokens:\n    DDOCTOSTS_ID_TOKEN:\n      aud: dd-octo-sts\n\n.deploy-prod:\n  stage: deploy\n  script:\n    - export BUILD_MODE=release\n    - VERSION=$(node -p -e \"require('./package.json').version\")\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy-prod-dc.ts v${VERSION%%.*} $DATACENTER --check-telemetry-errors\n\nstep-1_deploy-prod-minor-dcs:\n  when: manual\n  allow_failure: false\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: minor-dcs\n\nstep-2_deploy-prod-private-regions:\n  needs:\n    - step-1_deploy-prod-minor-dcs\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: private-regions\n\nstep-3_deploy-prod-eu1:\n  needs:\n    - step-2_deploy-prod-private-regions\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: eu1\n\nstep-4_deploy-prod-us1:\n  needs:\n    - step-3_deploy-prod-eu1\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: us1\n\nstep-5_deploy-prod-gov:\n  needs:\n    - step-4_deploy-prod-us1\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: gov\n\nstep-6_publish-npm:\n  needs:\n    - step-5_deploy-prod-gov\n  stage: deploy\n  extends:\n    - .base-configuration\n  allow_failure: false\n  script:\n    - yarn\n    - node ./scripts/deploy/publish-npm.ts\n\nstep-7_publish-developer-extension:\n  needs:\n    - step-6_publish-npm\n  stage: deploy\n  extends:\n    - .base-configuration\n  allow_failure: false\n  script:\n    - yarn\n    - node ./scripts/deploy/publish-developer-extension.ts\n\nstep-8_create-github-release:\n  needs:\n    - step-7_publish-developer-extension\n  stage: deploy\n  extends:\n    - .base-configuration\n  allow_failure: false\n  script:\n    - yarn\n    - node scripts/release/create-github-release.ts\n\n########################################################################################################################\n# Notify\n########################################################################################################################\n\ninclude: 'https://gitlab-templates.ddbuild.io/slack-notifier/v3-sdm/template.yml'\n\n.prepare_notification:\n  extends: .slack-notifier-base\n  before_script:\n    - COMMIT_MESSAGE=`git show-branch --no-name HEAD`\n    - BUILD_URL=\"$CI_PROJECT_URL/pipelines/$CI_PIPELINE_ID\"\n    - COMMIT_URL=\"$CI_PROJECT_URL/commits/$CI_COMMIT_SHA\"\n\nnotify-deploy-ready:\n  stage: pre-notify\n  extends:\n    - .prepare_notification\n  script:\n    - 'MESSAGE_TEXT=\":i: $CI_PROJECT_NAME <$BUILD_URL|$COMMIT_MESSAGE> ready to be deployed *automatically* to :datadog:\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n\nnotify-deploy-success:\n  stage: post-notify\n  needs:\n    - step-8_create-github-release\n  extends:\n    - .prepare_notification\n  script:\n    - 'MESSAGE_TEXT=\":rocket: $CI_PROJECT_NAME <$COMMIT_URL|$COMMIT_MESSAGE> *automatically* deployed to :earth_americas:.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n    - postmessage \"#rum-browser-sdk-ops\" \"$MESSAGE_TEXT\"\n\nnotify-deploy-failure:\n  stage: post-notify\n  extends:\n    - .prepare_notification\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":host-red: $CI_PROJECT_NAME *automatic* deployment of <$BUILD_URL|$COMMIT_MESSAGE> failed.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n"
  },
  {
    "path": ".gitlab/deploy-manual.yml",
    "content": "stages:\n  - pre-notify\n  - deploy\n  - post-notify\n\n.base-configuration:\n  tags:\n    - 'arch:amd64'\n  image: $CI_IMAGE\n  id_tokens:\n    DDOCTOSTS_ID_TOKEN:\n      aud: dd-octo-sts\n\n.deploy-prod:\n  stage: deploy\n  when: manual\n  allow_failure: false\n  script:\n    - export BUILD_MODE=release\n    - VERSION=$(node -p -e \"require('./package.json').version\")\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy-prod-dc.ts v${VERSION%%.*} $DATACENTER --no-check-telemetry-errors\n\nstep-1_deploy-prod-minor-dcs:\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: minor-dcs\n\nstep-2_deploy-prod-private-regions:\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: private-regions\n\nstep-3_deploy-prod-eu1:\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: eu1\n\nstep-4_deploy-prod-us1:\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: us1\n\nstep-5_deploy-prod-gov:\n  extends:\n    - .base-configuration\n    - .deploy-prod\n  variables:\n    DATACENTER: gov\n\nstep-6_publish-npm:\n  stage: deploy\n  extends:\n    - .base-configuration\n  when: manual\n  allow_failure: false\n  script:\n    - yarn\n    - node ./scripts/deploy/publish-npm.ts\n\nstep-7_publish-developer-extension:\n  stage: deploy\n  extends:\n    - .base-configuration\n  when: manual\n  allow_failure: false\n  script:\n    - yarn\n    - node ./scripts/deploy/publish-developer-extension.ts\n\nstep-8_create-github-release:\n  stage: deploy\n  extends:\n    - .base-configuration\n  when: manual\n  allow_failure: false\n  script:\n    - yarn\n    - node scripts/release/create-github-release.ts\n\n# This step is used to deploy the SDK to a new datacenter.\n# the `DATACENTER` variable needs to be provided as an argument when starting the manual job\noptional_step-deploy-to-new-datacenter:\n  extends:\n    - .base-configuration\n    - .deploy-prod\n\n########################################################################################################################\n# Notify\n########################################################################################################################\n\ninclude: 'https://gitlab-templates.ddbuild.io/slack-notifier/v3-sdm/template.yml'\n\n.prepare_notification:\n  extends: .slack-notifier-base\n  before_script:\n    - COMMIT_MESSAGE=`git show-branch --no-name HEAD`\n    - BUILD_URL=\"$CI_PROJECT_URL/pipelines/$CI_PIPELINE_ID\"\n    - COMMIT_URL=\"$CI_PROJECT_URL/commits/$CI_COMMIT_SHA\"\n\nnotify-deploy-ready:\n  stage: pre-notify\n  extends:\n    - .prepare_notification\n  script:\n    - 'MESSAGE_TEXT=\":i: $CI_PROJECT_NAME <$BUILD_URL|$COMMIT_MESSAGE> ready to be deployed *manually* to :datadog:\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n\nnotify-deploy-success:\n  stage: post-notify\n  extends:\n    - .prepare_notification\n  script:\n    - 'MESSAGE_TEXT=\":rocket: $CI_PROJECT_NAME <$COMMIT_URL|$COMMIT_MESSAGE> *manually* deployed to :earth_americas:.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n    - postmessage \"#rum-browser-sdk-ops\" \"$MESSAGE_TEXT\"\n\nnotify-deploy-failure:\n  stage: post-notify\n  extends:\n    - .prepare_notification\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":host-red: $CI_PROJECT_NAME *manual* deployment of <$BUILD_URL|$COMMIT_MESSAGE> failed.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "content": "variables:\n  CURRENT_STAGING: staging-17\n  APP: 'browser-sdk'\n  CURRENT_CI_IMAGE: 103\n  BUILD_STABLE_REGISTRY: 'registry.ddbuild.io'\n  CI_IMAGE: '$BUILD_STABLE_REGISTRY/ci/$APP:$CURRENT_CI_IMAGE'\n  GIT_REPOSITORY: 'git@github.com:DataDog/browser-sdk.git'\n  MAIN_BRANCH: 'main'\n  NEXT_MAJOR_BRANCH: 'v7'\n  CHROME_PACKAGE_VERSION: 146.0.7680.71-1\n  FF_TIMESTAMPS: 'true' # Enable timestamps for gitlab-ci logs\n\ncache:\n  key:\n    files:\n      - yarn.lock\n  paths:\n    - .yarn/cache\n\nstages:\n  - task\n  - ci-image\n  - test\n  - after-tests\n  - browserstack\n  - pre-deploy\n  - deploy:canary\n  - notify:canary\n  - deploy\n  - notify\n\n.base-configuration:\n  tags:\n    - 'arch:amd64'\n  image: $CI_IMAGE\n  id_tokens:\n    DDOCTOSTS_ID_TOKEN:\n      aud: dd-octo-sts\n  retry:\n    max: 2\n    when:\n      - runner_system_failure\n\n########################################################################################################################\n# Branch selection helpers\n########################################################################################################################\n\n.test-allowed-branches:\n  except:\n    refs:\n      - /^release\\//\n      - schedules\n\n.bs-allowed-branches:\n  except:\n    refs:\n      - main\n      - /^mq-working-branch-staging-[0-9]+-[a-z0-9]+$/\n      - /^staging-[0-9]+$/\n      - /^release\\//\n      - schedules\n    variables:\n      - $CI_COMMIT_REF_NAME == $NEXT_MAJOR_BRANCH\n\n.feature-branches:\n  except:\n    refs:\n      - main\n      - tags\n      - /^staging-[0-9]+$/\n      - /^release\\//\n      - schedules\n    variables:\n      - $CI_COMMIT_REF_NAME == $NEXT_MAJOR_BRANCH\n\n.next-major-branch:\n  only:\n    variables:\n      - $CI_COMMIT_REF_NAME == $NEXT_MAJOR_BRANCH\n\n.staging:\n  only:\n    variables:\n      - $CI_COMMIT_REF_NAME == $CURRENT_STAGING\n\n.main:\n  only:\n    refs:\n      - main\n  except:\n    refs:\n      - schedules\n    variables:\n      - $CI_COMMIT_TITLE =~ /^v[0-9.]+/\n\n.tags:\n  only:\n    refs:\n      - tags\n\n###########################################################################################################################\n# Resource allocation\n###########################################################################################################################\n.resource-allocation-4-cpus:\n  variables:\n    WORKERS: 2\n    KUBERNETES_CPU_REQUEST: 4\n    KUBERNETES_CPU_LIMIT: 4\n    KUBERNETES_MEMORY_REQUEST: 16Gi\n    KUBERNETES_MEMORY_LIMIT: 16Gi\n    NODE_OPTIONS: '--max-old-space-size=16000'\n\n########################################################################################################################\n# CI image\n########################################################################################################################\n\nci-image:\n  stage: ci-image\n  extends:\n    - .base-configuration\n    - .feature-branches\n  when: manual\n  tags: ['arch:amd64']\n  image: $BUILD_STABLE_REGISTRY/images/docker:27.3.1\n  id_tokens:\n    DDSIGN_ID_TOKEN:\n      aud: image-integrity\n  script:\n    - METADATA_FILE=$(mktemp)\n    - docker buildx build --platform linux/amd64 --build-arg CHROME_PACKAGE_VERSION=$CHROME_PACKAGE_VERSION --tag $CI_IMAGE --push --metadata-file $METADATA_FILE .\n    - ddsign sign $CI_IMAGE --docker-metadata-file $METADATA_FILE\n\n########################################################################################################################\n# Tests\n########################################################################################################################\n\nformat:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn format\n\nwoke:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn woke\n\ntypecheck:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn build\n    - yarn typecheck\n    - scripts/cli typecheck test/apps/vanilla\n    - scripts/cli typecheck test/e2e\n\nbuild-and-lint:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn build\n    - yarn lint\n    - node scripts/check-packages.ts\n\ntest-performance:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  except:\n    variables:\n      - $CI_COMMIT_REF_NAME == $CURRENT_STAGING\n  interruptible: true\n  allow_failure: true\n  script:\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy.ts staging pull-request pull-request\n    - node ./scripts/performance/index.ts\n\nbuild-bundle:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn build:bundle\n\ncompatibility:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn test:compat:tsc\n    - yarn test:compat:ssr\n\nunit:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  artifacts:\n    reports:\n      junit: test-report/unit/*.xml\n  script:\n    - yarn\n    - yarn test:unit\n  after_script:\n    - node ./scripts/test/export-test-result.ts unit\n\ne2e:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  artifacts:\n    when: always\n    reports:\n      junit: test-report/e2e/*.xml\n  script:\n    - yarn\n    - FORCE_COLOR=1 yarn test:e2e:ci\n  after_script:\n    - node ./scripts/test/export-test-result.ts e2e\n\ncheck-licenses:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - node scripts/check-licenses.ts\n\ncheck-node-version:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - node scripts/check-node-version.ts\n\ncheck-release:\n  extends:\n    - .base-configuration\n    - .tags\n  interruptible: true\n  script:\n    - yarn\n    - BUILD_MODE=release yarn build\n    - node scripts/release/check-release.ts\n\ncheck-schemas:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - node scripts/check-schemas.ts\n\nunit-bs:\n  stage: browserstack\n  needs: ['unit']\n  extends:\n    - .base-configuration\n    - .bs-allowed-branches\n  interruptible: true\n  resource_group: browserstack\n  artifacts:\n    reports:\n      junit: test-report/unit-bs/*.xml\n  script:\n    - yarn\n    - node scripts/test/ci-bs.ts test:unit\n  after_script:\n    - node ./scripts/test/export-test-result.ts unit-bs\n\ne2e-bs:\n  stage: browserstack\n  needs: ['e2e']\n  extends:\n    - .base-configuration\n    - .bs-allowed-branches\n    - .resource-allocation-4-cpus\n  interruptible: true\n  resource_group: browserstack\n  timeout: 35 minutes\n  artifacts:\n    when: always\n    reports:\n      junit: test-report/e2e-bs/*.xml\n  script:\n    - yarn\n    - FORCE_COLOR=1 node scripts/test/ci-bs.ts test:e2e:ci\n  after_script:\n    - node ./scripts/test/export-test-result.ts e2e-bs\n\nscript-tests:\n  extends:\n    - .base-configuration\n    - .test-allowed-branches\n  interruptible: true\n  script:\n    - yarn\n    - yarn build:bundle\n    - yarn test:script\n########################################################################################################################\n# Deploy\n########################################################################################################################\n\ndeploy-feature:\n  stage: deploy\n  when: manual\n  variables:\n    SUFFIX: 'my-feature' #/datadog-[product]-${SUFFIX}.js\n  extends:\n    - .base-configuration\n    - .feature-branches\n  script:\n    - export BUILD_MODE=canary\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy.ts staging $SUFFIX root\n\ndeploy-staging:\n  stage: deploy\n  extends:\n    - .base-configuration\n    - .staging\n  script:\n    - export BUILD_MODE=canary\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy.ts staging staging root\n    - node ./scripts/deploy/upload-source-maps.ts staging root\n\ndeploy-prod-canary:\n  stage: deploy:canary\n  extends:\n    - .base-configuration\n    - .main\n  script:\n    - export BUILD_MODE=canary\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy.ts prod canary root\n    - node ./scripts/deploy/upload-source-maps.ts canary root\n\ndeploy-next-major-canary:\n  stage: deploy\n  extends:\n    - .base-configuration\n    - .next-major-branch\n  script:\n    - export BUILD_MODE=canary\n    - VERSION=$(node -p -e \"require('./package.json').version\")\n    - yarn\n    - yarn build:bundle\n    - node ./scripts/deploy/deploy.ts prod v${VERSION%%.*}-canary root\n    - node ./scripts/deploy/upload-source-maps.ts v${VERSION%%.*}-canary root\n\ndeploy-manual:\n  stage: deploy\n  extends:\n    - .tags\n  trigger:\n    include:\n      - local: .gitlab/deploy-manual.yml\n\ndeploy-auto:\n  stage: deploy\n  extends:\n    - .tags\n  trigger:\n    include:\n      - local: .gitlab/deploy-auto.yml\n\n########################################################################################################################\n# Notify\n########################################################################################################################\n\ninclude: 'https://gitlab-templates.ddbuild.io/slack-notifier/v3-sdm/template.yml'\n\nnotify-feature-branch-failure:\n  extends:\n    - .slack-notifier.on-failure\n    - .feature-branches\n\n.prepare_notification:\n  extends: .slack-notifier-base\n  before_script:\n    - COMMIT_MESSAGE=`git show-branch --no-name HEAD`\n    - BUILD_URL=\"$CI_PROJECT_URL/pipelines/$CI_PIPELINE_ID\"\n    - COMMIT_URL=\"$CI_PROJECT_URL/commits/$CI_COMMIT_SHA\"\n\nnotify-staging-failure:\n  extends:\n    - .prepare_notification\n    - .staging\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":host-red: $CI_PROJECT_NAME main pipeline for <$BUILD_URL|$COMMIT_MESSAGE> failed.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n\nnotify-prod-canary-success:\n  stage: notify:canary\n  extends:\n    - .prepare_notification\n    - .main\n  script:\n    - 'MESSAGE_TEXT=\":rocket: $CI_PROJECT_NAME <$COMMIT_URL|$COMMIT_MESSAGE> deployed to :datadog:.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n    - postmessage \"#rum-browser-sdk-ops\" \"$MESSAGE_TEXT\"\n\nnotify-prod-canary-failure:\n  stage: notify:canary\n  extends:\n    - .prepare_notification\n    - .main\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":host-red: $CI_PROJECT_NAME release pipeline <$BUILD_URL|$COMMIT_MESSAGE> failed.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n\n########################################################################################################################\n# To staging CI\n########################################################################################################################\n\nstaging-reset-scheduled:\n  stage: task\n  extends: .base-configuration\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"staging-reset-scheduled\"\n  before_script:\n    - eval $(ssh-agent -s)\n  script:\n    - yarn\n    - node scripts/staging-ci/staging-reset.ts\n  artifacts:\n    reports:\n      dotenv: build.env\n\nstaging-reset-scheduled-success:\n  extends: .prepare_notification\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"staging-reset-scheduled\"\n  script:\n    - 'MESSAGE_TEXT=\":white_check_mark: [*$CI_PROJECT_NAME*] Staging has been reset from *${CURRENT_STAGING}* to *${NEW_STAGING}* on pipeline <$BUILD_URL|$COMMIT_MESSAGE>.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n  dependencies:\n    - staging-reset-scheduled\n\nstaging-reset-scheduled-failure:\n  extends: .prepare_notification\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"staging-reset-scheduled\"\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":x: [*$CI_PROJECT_NAME*] Staging failed to reset from *${CURRENT_STAGING}* to *${NEW_STAGING}* on pipeline <$BUILD_URL|$COMMIT_MESSAGE>.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n  dependencies:\n    - staging-reset-scheduled\n\nmerge-into-staging:\n  stage: pre-deploy\n  allow_failure: true\n  extends:\n    - .base-configuration\n    - .main\n  before_script:\n    - eval $(ssh-agent -s)\n  script:\n    - yarn\n    - node scripts/update-branch.ts $CURRENT_STAGING\n\nmerge-into-next-major:\n  stage: pre-deploy\n  allow_failure: true\n  extends:\n    - .base-configuration\n  only:\n    refs:\n      - main\n    variables:\n      - $NEXT_MAJOR_BRANCH\n  except:\n    refs:\n      - schedules\n  before_script:\n    - eval $(ssh-agent -s)\n  script:\n    - yarn\n    - node scripts/update-branch.ts $NEXT_MAJOR_BRANCH\n\ncheck-staging-merge:\n  stage: test\n  extends:\n    - .base-configuration\n    - .feature-branches\n  interruptible: true\n  before_script:\n    - eval $(ssh-agent -s)\n  script:\n    - yarn\n    - node scripts/staging-ci/check-staging-merge.ts\n\n# A noop job that's used to signal to `to-staging` that it can merge to the\n# staging branch, even though the pipeline is still running\ntests-passed:\n  stage: after-tests\n  extends:\n    - .base-configuration\n    - .feature-branches\n  interruptible: true\n  script:\n    - 'true'\n\n# in after-tests to not block `to-staging` merge\ncheck-squash-into-staging:\n  stage: after-tests\n  allow_failure: true\n  extends:\n    - .base-configuration\n    - .feature-branches\n  interruptible: true\n  before_script:\n    - eval $(ssh-agent -s)\n  script:\n    - yarn\n    - node scripts/staging-ci/check-squash-into-staging.ts\n\n########################################################################################################################\n# Bump e2e chrome version\n########################################################################################################################\n\nbump-chrome-version-scheduled:\n  stage: task\n  extends: .base-configuration\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"bump-chrome-version-scheduled\"\n  before_script:\n    - eval $(ssh-agent -s)\n  script:\n    - yarn\n    - node scripts/test/bump-chrome-version.ts\n  artifacts:\n    reports:\n      dotenv: build.env\n\nbump-chrome-version-scheduled-success:\n  extends: .prepare_notification\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"bump-chrome-version-scheduled\"\n  before_script:\n    - '[ -z \"$BUMP_CHROME_PULL_REQUEST_URL\" ] && exit'\n  script:\n    - 'MESSAGE_TEXT=\":chrome: [*$CI_PROJECT_NAME*] New Chrome version available on <$BUMP_CHROME_PULL_REQUEST_URL|PR>.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n  dependencies:\n    - bump-chrome-version-scheduled\n\nbump-chrome-version-scheduled-failure:\n  extends: .prepare_notification\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"bump-chrome-version-scheduled\"\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":x: [*$CI_PROJECT_NAME*] Chrome version bumped failed on pipeline <$BUILD_URL|$COMMIT_MESSAGE>.\"'\n    - postmessage \"#browser-sdk-deploy\" \"$MESSAGE_TEXT\"\n  dependencies:\n    - bump-chrome-version-scheduled\n\n########################################################################################################################\n# Performance benchmark\n########################################################################################################################\n\nperformance-benchmark:\n  stage: task\n  extends: .base-configuration\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"performance-benchmark-scheduled\"\n  script:\n    - yarn\n    - yarn test:performance\n\n########################################################################################################################\n# Check expired telemetry\n########################################################################################################################\n\ncheck-expired-telemetry-scheduled:\n  stage: task\n  extends: .base-configuration\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"check-expired-telemetry\"\n  script:\n    - yarn\n    - yarn build\n    - MONITOR_UNTIL_COMMENT_EXPIRED_LEVEL=error yarn lint\n\ncheck-expired-telemetry-scheduled-failure:\n  extends: .prepare_notification\n  only:\n    variables:\n      - $TARGET_TASK_NAME == \"check-expired-telemetry\"\n  when: on_failure\n  script:\n    - 'MESSAGE_TEXT=\":fire: [*$CI_PROJECT_NAME*] <$BUILD_URL|Expired telemetry detected> :fire:\"'\n    - postmessage \"#rum-browser-sdk-ops\" \"$MESSAGE_TEXT\"\n  dependencies:\n    - check-expired-telemetry-scheduled\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"rum-events-format\"]\n\tpath = rum-events-format\n\turl = https://github.com/DataDog/rum-events-format\n\tbranch = master\n"
  },
  {
    "path": ".prettierignore",
    "content": "bundle\ncjs\nesm\ncoverage\nrum-events-format\n.yarn\ntest/**/dist\ntest/**/.next\ntest/**/.nuxt\ntest/**/.output\ntest/apps/nextjs/next-env.d.ts\nyarn.lock\n/generated-docs\n/developer-extension/.output\n/developer-extension/.wxt\n"
  },
  {
    "path": ".prettierrc.yml",
    "content": "arrowParens: 'always'\nprintWidth: 120\nsemi: false\nsingleQuote: true\ntabWidth: 2\ntrailingComma: 'es5'\noverrides:\n  - files: '*.json'\n    options:\n      trailingComma: 'none'\n"
  },
  {
    "path": ".wokeignore",
    "content": "**/dist/**\nyarn.lock\n.yarn/releases\ngenerated-docs\n\n# code import\npackages/worker/src/domain/deflate.js\n"
  },
  {
    "path": ".yarn/releases/yarn-4.13.0.cjs",
    "content": "#!/usr/bin/env node\n/* eslint-disable */\n//prettier-ignore\n(()=>{var gje=Object.create;var tU=Object.defineProperty;var dje=Object.getOwnPropertyDescriptor;var mje=Object.getOwnPropertyNames;var yje=Object.getPrototypeOf,Eje=Object.prototype.hasOwnProperty;var Ie=(e=>typeof require<\"u\"?require:typeof Proxy<\"u\"?new Proxy(e,{get:(t,r)=>(typeof require<\"u\"?require:t)[r]}):e)(function(e){if(typeof require<\"u\")return require.apply(this,arguments);throw Error('Dynamic require of \"'+e+'\" is not supported')});var Ze=(e,t)=>()=>(e&&(t=e(e=0)),t);var G=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Yt=(e,t)=>{for(var r in t)tU(e,r,{get:t[r],enumerable:!0})},Ije=(e,t,r,s)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let a of mje(t))!Eje.call(e,a)&&a!==r&&tU(e,a,{get:()=>t[a],enumerable:!(s=dje(t,a))||s.enumerable});return e};var et=(e,t,r)=>(r=e!=null?gje(yje(e)):{},Ije(t||!e||!e.__esModule?tU(r,\"default\",{value:e,enumerable:!0}):r,e));var Ai={};Yt(Ai,{SAFE_TIME:()=>lX,S_IFDIR:()=>KP,S_IFLNK:()=>JP,S_IFMT:()=>_f,S_IFREG:()=>bB});var _f,KP,bB,JP,lX,cX=Ze(()=>{_f=61440,KP=16384,bB=32768,JP=40960,lX=456789e3});var or={};Yt(or,{EBADF:()=>Go,EBUSY:()=>Cje,EEXIST:()=>bje,EINVAL:()=>Bje,EISDIR:()=>Dje,ENOENT:()=>vje,ENOSYS:()=>wje,ENOTDIR:()=>Sje,ENOTEMPTY:()=>xje,EOPNOTSUPP:()=>kje,EROFS:()=>Pje,ERR_DIR_CLOSED:()=>rU});function wc(e,t){return Object.assign(new Error(`${e}: ${t}`),{code:e})}function Cje(e){return wc(\"EBUSY\",e)}function wje(e,t){return wc(\"ENOSYS\",`${e}, ${t}`)}function Bje(e){return wc(\"EINVAL\",`invalid argument, ${e}`)}function Go(e){return wc(\"EBADF\",`bad file descriptor, ${e}`)}function vje(e){return wc(\"ENOENT\",`no such file or directory, ${e}`)}function Sje(e){return wc(\"ENOTDIR\",`not a directory, ${e}`)}function Dje(e){return wc(\"EISDIR\",`illegal operation on a directory, ${e}`)}function bje(e){return wc(\"EEXIST\",`file already exists, ${e}`)}function Pje(e){return wc(\"EROFS\",`read-only filesystem, ${e}`)}function xje(e){return wc(\"ENOTEMPTY\",`directory not empty, ${e}`)}function kje(e){return wc(\"EOPNOTSUPP\",`operation not supported, ${e}`)}function rU(){return wc(\"ERR_DIR_CLOSED\",\"Directory handle was closed\")}var zP=Ze(()=>{});var sl={};Yt(sl,{BigIntStatsEntry:()=>aE,DEFAULT_MODE:()=>sU,DirEntry:()=>nU,StatEntry:()=>oE,areStatsEqual:()=>oU,clearStats:()=>ZP,convertToBigIntStats:()=>Rje,makeDefaultStats:()=>uX,makeEmptyStats:()=>Qje});function uX(){return new oE}function Qje(){return ZP(uX())}function ZP(e){for(let t in e)if(Object.hasOwn(e,t)){let r=e[t];typeof r==\"number\"?e[t]=0:typeof r==\"bigint\"?e[t]=BigInt(0):iU.types.isDate(r)&&(e[t]=new Date(0))}return e}function Rje(e){let t=new aE;for(let r in e)if(Object.hasOwn(e,r)){let s=e[r];typeof s==\"number\"?t[r]=BigInt(Math.floor(s)):iU.types.isDate(s)&&(t[r]=new Date(s))}return t.atimeNs=t.atimeMs*BigInt(1e6)+BigInt(Math.floor(e.atimeMs%1*1e3))*BigInt(1e3),t.mtimeNs=t.mtimeMs*BigInt(1e6)+BigInt(Math.floor(e.mtimeMs%1*1e3))*BigInt(1e3),t.ctimeNs=t.ctimeMs*BigInt(1e6)+BigInt(Math.floor(e.ctimeMs%1*1e3))*BigInt(1e3),t.birthtimeNs=t.birthtimeMs*BigInt(1e6)+BigInt(Math.floor(e.birthtimeMs%1*1e3))*BigInt(1e3),t}function oU(e,t){if(e.atimeMs!==t.atimeMs||e.birthtimeMs!==t.birthtimeMs||e.blksize!==t.blksize||e.blocks!==t.blocks||e.ctimeMs!==t.ctimeMs||e.dev!==t.dev||e.gid!==t.gid||e.ino!==t.ino||e.isBlockDevice()!==t.isBlockDevice()||e.isCharacterDevice()!==t.isCharacterDevice()||e.isDirectory()!==t.isDirectory()||e.isFIFO()!==t.isFIFO()||e.isFile()!==t.isFile()||e.isSocket()!==t.isSocket()||e.isSymbolicLink()!==t.isSymbolicLink()||e.mode!==t.mode||e.mtimeMs!==t.mtimeMs||e.nlink!==t.nlink||e.rdev!==t.rdev||e.size!==t.size||e.uid!==t.uid)return!1;let r=e,s=t;return!(r.atimeNs!==s.atimeNs||r.mtimeNs!==s.mtimeNs||r.ctimeNs!==s.ctimeNs||r.birthtimeNs!==s.birthtimeNs)}var iU,sU,nU,oE,aE,aU=Ze(()=>{iU=et(Ie(\"util\")),sU=33188,nU=class{constructor(){this.name=\"\";this.path=\"\";this.mode=0}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},oE=class{constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atimeMs=0;this.mtimeMs=0;this.ctimeMs=0;this.birthtimeMs=0;this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=0;this.ino=0;this.mode=sU;this.nlink=1;this.rdev=0;this.blocks=1}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},aE=class{constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);this.blksize=BigInt(0);this.atimeMs=BigInt(0);this.mtimeMs=BigInt(0);this.ctimeMs=BigInt(0);this.birthtimeMs=BigInt(0);this.atimeNs=BigInt(0);this.mtimeNs=BigInt(0);this.ctimeNs=BigInt(0);this.birthtimeNs=BigInt(0);this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=BigInt(0);this.ino=BigInt(0);this.mode=BigInt(sU);this.nlink=BigInt(1);this.rdev=BigInt(0);this.blocks=BigInt(1)}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&BigInt(61440))===BigInt(16384)}isFIFO(){return!1}isFile(){return(this.mode&BigInt(61440))===BigInt(32768)}isSocket(){return!1}isSymbolicLink(){return(this.mode&BigInt(61440))===BigInt(40960)}}});function Lje(e){let t,r;if(t=e.match(Nje))e=t[1];else if(r=e.match(Oje))e=`\\\\\\\\${r[1]?\".\\\\\":\"\"}${r[2]}`;else return e;return e.replace(/\\//g,\"\\\\\")}function Mje(e){e=e.replace(/\\\\/g,\"/\");let t,r;return(t=e.match(Tje))?e=`/${t[1]}`:(r=e.match(Fje))&&(e=`/unc/${r[1]?\".dot/\":\"\"}${r[2]}`),e}function XP(e,t){return e===fe?AX(t):lU(t)}var PB,vt,Er,fe,K,fX,Tje,Fje,Nje,Oje,lU,AX,ol=Ze(()=>{PB=et(Ie(\"path\")),vt={root:\"/\",dot:\".\",parent:\"..\"},Er={home:\"~\",nodeModules:\"node_modules\",manifest:\"package.json\",lockfile:\"yarn.lock\",virtual:\"__virtual__\",pnpJs:\".pnp.js\",pnpCjs:\".pnp.cjs\",pnpData:\".pnp.data.json\",pnpEsmLoader:\".pnp.loader.mjs\",rc:\".yarnrc.yml\",env:\".env\"},fe=Object.create(PB.default),K=Object.create(PB.default.posix);fe.cwd=()=>process.cwd();K.cwd=process.platform===\"win32\"?()=>lU(process.cwd()):process.cwd;process.platform===\"win32\"&&(K.resolve=(...e)=>e.length>0&&K.isAbsolute(e[0])?PB.default.posix.resolve(...e):PB.default.posix.resolve(K.cwd(),...e));fX=function(e,t,r){return t=e.normalize(t),r=e.normalize(r),t===r?\".\":(t.endsWith(e.sep)||(t=t+e.sep),r.startsWith(t)?r.slice(t.length):null)};fe.contains=(e,t)=>fX(fe,e,t);K.contains=(e,t)=>fX(K,e,t);Tje=/^([a-zA-Z]:.*)$/,Fje=/^\\/\\/(\\.\\/)?(.*)$/,Nje=/^\\/([a-zA-Z]:.*)$/,Oje=/^\\/unc\\/(\\.dot\\/)?(.*)$/;lU=process.platform===\"win32\"?Mje:e=>e,AX=process.platform===\"win32\"?Lje:e=>e;fe.fromPortablePath=AX;fe.toPortablePath=lU});async function $P(e,t){let r=\"0123456789abcdef\";await e.mkdirPromise(t.indexPath,{recursive:!0});let s=[];for(let a of r)for(let n of r)s.push(e.mkdirPromise(e.pathUtils.join(t.indexPath,`${a}${n}`),{recursive:!0}));return await Promise.all(s),t.indexPath}async function pX(e,t,r,s,a){let n=e.pathUtils.normalize(t),c=r.pathUtils.normalize(s),f=[],p=[],{atime:h,mtime:E}=a.stableTime?{atime:hd,mtime:hd}:await r.lstatPromise(c);await e.mkdirpPromise(e.pathUtils.dirname(t),{utimes:[h,E]}),await cU(f,p,e,n,r,c,{...a,didParentExist:!0});for(let C of f)await C();await Promise.all(p.map(C=>C()))}async function cU(e,t,r,s,a,n,c){let f=c.didParentExist?await hX(r,s):null,p=await a.lstatPromise(n),{atime:h,mtime:E}=c.stableTime?{atime:hd,mtime:hd}:p,C;switch(!0){case p.isDirectory():C=await _je(e,t,r,s,f,a,n,p,c);break;case p.isFile():C=await Gje(e,t,r,s,f,a,n,p,c);break;case p.isSymbolicLink():C=await qje(e,t,r,s,f,a,n,p,c);break;default:throw new Error(`Unsupported file type (${p.mode})`)}return(c.linkStrategy?.type!==\"HardlinkFromIndex\"||!p.isFile())&&((C||f?.mtime?.getTime()!==E.getTime()||f?.atime?.getTime()!==h.getTime())&&(t.push(()=>r.lutimesPromise(s,h,E)),C=!0),(f===null||(f.mode&511)!==(p.mode&511))&&(t.push(()=>r.chmodPromise(s,p.mode&511)),C=!0)),C}async function hX(e,t){try{return await e.lstatPromise(t)}catch{return null}}async function _je(e,t,r,s,a,n,c,f,p){if(a!==null&&!a.isDirectory())if(p.overwrite)e.push(async()=>r.removePromise(s)),a=null;else return!1;let h=!1;a===null&&(e.push(async()=>{try{await r.mkdirPromise(s,{mode:f.mode})}catch(S){if(S.code!==\"EEXIST\")throw S}}),h=!0);let E=await n.readdirPromise(c),C=p.didParentExist&&!a?{...p,didParentExist:!1}:p;if(p.stableSort)for(let S of E.sort())await cU(e,t,r,r.pathUtils.join(s,S),n,n.pathUtils.join(c,S),C)&&(h=!0);else(await Promise.all(E.map(async x=>{await cU(e,t,r,r.pathUtils.join(s,x),n,n.pathUtils.join(c,x),C)}))).some(x=>x)&&(h=!0);return h}async function Hje(e,t,r,s,a,n,c,f,p,h){let E=await n.checksumFilePromise(c,{algorithm:\"sha1\"}),C=420,S=f.mode&511,x=`${E}${S!==C?S.toString(8):\"\"}`,I=r.pathUtils.join(h.indexPath,E.slice(0,2),`${x}.dat`),T;(ae=>(ae[ae.Lock=0]=\"Lock\",ae[ae.Rename=1]=\"Rename\"))(T||={});let O=1,U=await hX(r,I);if(a){let ie=U&&a.dev===U.dev&&a.ino===U.ino,ue=U?.mtimeMs!==Uje;if(ie&&ue&&h.autoRepair&&(O=0,U=null),!ie)if(p.overwrite)e.push(async()=>r.removePromise(s)),a=null;else return!1}let Y=!U&&O===1?`${I}.${Math.floor(Math.random()*4294967296).toString(16).padStart(8,\"0\")}`:null,te=!1;return e.push(async()=>{if(!U&&(O===0&&await r.lockPromise(I,async()=>{let ie=await n.readFilePromise(c);await r.writeFilePromise(I,ie)}),O===1&&Y)){let ie=await n.readFilePromise(c);await r.writeFilePromise(Y,ie);try{await r.linkPromise(Y,I)}catch(ue){if(ue.code===\"EEXIST\")te=!0,await r.unlinkPromise(Y);else throw ue}}a||await r.linkPromise(I,s)}),t.push(async()=>{U||(await r.lutimesPromise(I,hd,hd),S!==C&&await r.chmodPromise(I,S)),Y&&!te&&await r.unlinkPromise(Y)}),!1}async function jje(e,t,r,s,a,n,c,f,p){if(a!==null)if(p.overwrite)e.push(async()=>r.removePromise(s)),a=null;else return!1;return e.push(async()=>{let h=await n.readFilePromise(c);await r.writeFilePromise(s,h)}),!0}async function Gje(e,t,r,s,a,n,c,f,p){return p.linkStrategy?.type===\"HardlinkFromIndex\"?Hje(e,t,r,s,a,n,c,f,p,p.linkStrategy):jje(e,t,r,s,a,n,c,f,p)}async function qje(e,t,r,s,a,n,c,f,p){if(a!==null)if(p.overwrite)e.push(async()=>r.removePromise(s)),a=null;else return!1;return e.push(async()=>{await r.symlinkPromise(XP(r.pathUtils,await n.readlinkPromise(c)),s)}),!0}var hd,Uje,uU=Ze(()=>{ol();hd=new Date(456789e3*1e3),Uje=hd.getTime()});function ex(e,t,r,s){let a=()=>{let n=r.shift();if(typeof n>\"u\")return null;let c=e.pathUtils.join(t,n);return Object.assign(e.statSync(c),{name:n,path:void 0})};return new xB(t,a,s)}var xB,gX=Ze(()=>{zP();xB=class{constructor(t,r,s={}){this.path=t;this.nextDirent=r;this.opts=s;this.closed=!1}throwIfClosed(){if(this.closed)throw rU()}async*[Symbol.asyncIterator](){try{let t;for(;(t=await this.read())!==null;)yield t}finally{await this.close()}}read(t){let r=this.readSync();return typeof t<\"u\"?t(null,r):Promise.resolve(r)}readSync(){return this.throwIfClosed(),this.nextDirent()}close(t){return this.closeSync(),typeof t<\"u\"?t(null):Promise.resolve()}closeSync(){this.throwIfClosed(),this.opts.onClose?.(),this.closed=!0}}});function dX(e,t){if(e!==t)throw new Error(`Invalid StatWatcher status: expected '${t}', got '${e}'`)}var mX,tx,yX=Ze(()=>{mX=Ie(\"events\");aU();tx=class e extends mX.EventEmitter{constructor(r,s,{bigint:a=!1}={}){super();this.status=\"ready\";this.changeListeners=new Map;this.startTimeout=null;this.fakeFs=r,this.path=s,this.bigint=a,this.lastStats=this.stat()}static create(r,s,a){let n=new e(r,s,a);return n.start(),n}start(){dX(this.status,\"ready\"),this.status=\"running\",this.startTimeout=setTimeout(()=>{this.startTimeout=null,this.fakeFs.existsSync(this.path)||this.emit(\"change\",this.lastStats,this.lastStats)},3)}stop(){dX(this.status,\"running\"),this.status=\"stopped\",this.startTimeout!==null&&(clearTimeout(this.startTimeout),this.startTimeout=null),this.emit(\"stop\")}stat(){try{return this.fakeFs.statSync(this.path,{bigint:this.bigint})}catch{let r=this.bigint?new aE:new oE;return ZP(r)}}makeInterval(r){let s=setInterval(()=>{let a=this.stat(),n=this.lastStats;oU(a,n)||(this.lastStats=a,this.emit(\"change\",a,n))},r.interval);return r.persistent?s:s.unref()}registerChangeListener(r,s){this.addListener(\"change\",r),this.changeListeners.set(r,this.makeInterval(s))}unregisterChangeListener(r){this.removeListener(\"change\",r);let s=this.changeListeners.get(r);typeof s<\"u\"&&clearInterval(s),this.changeListeners.delete(r)}unregisterAllChangeListeners(){for(let r of this.changeListeners.keys())this.unregisterChangeListener(r)}hasChangeListeners(){return this.changeListeners.size>0}ref(){for(let r of this.changeListeners.values())r.ref();return this}unref(){for(let r of this.changeListeners.values())r.unref();return this}}});function lE(e,t,r,s){let a,n,c,f;switch(typeof r){case\"function\":a=!1,n=!0,c=5007,f=r;break;default:({bigint:a=!1,persistent:n=!0,interval:c=5007}=r),f=s;break}let p=rx.get(e);typeof p>\"u\"&&rx.set(e,p=new Map);let h=p.get(t);return typeof h>\"u\"&&(h=tx.create(e,t,{bigint:a}),p.set(t,h)),h.registerChangeListener(f,{persistent:n,interval:c}),h}function gd(e,t,r){let s=rx.get(e);if(typeof s>\"u\")return;let a=s.get(t);typeof a>\"u\"||(typeof r>\"u\"?a.unregisterAllChangeListeners():a.unregisterChangeListener(r),a.hasChangeListeners()||(a.stop(),s.delete(t)))}function dd(e){let t=rx.get(e);if(!(typeof t>\"u\"))for(let r of t.keys())gd(e,r)}var rx,fU=Ze(()=>{yX();rx=new WeakMap});function Wje(e){let t=e.match(/\\r?\\n/g);if(t===null)return IX.EOL;let r=t.filter(a=>a===`\\r\n`).length,s=t.length-r;return r>s?`\\r\n`:`\n`}function md(e,t){return t.replace(/\\r?\\n/g,Wje(e))}var EX,IX,yp,Hf,yd=Ze(()=>{EX=Ie(\"crypto\"),IX=Ie(\"os\");uU();ol();yp=class{constructor(t){this.pathUtils=t}async*genTraversePromise(t,{stableSort:r=!1}={}){let s=[t];for(;s.length>0;){let a=s.shift();if((await this.lstatPromise(a)).isDirectory()){let c=await this.readdirPromise(a);if(r)for(let f of c.sort())s.push(this.pathUtils.join(a,f));else throw new Error(\"Not supported\")}else yield a}}async checksumFilePromise(t,{algorithm:r=\"sha512\"}={}){let s=await this.openPromise(t,\"r\");try{let n=Buffer.allocUnsafeSlow(65536),c=(0,EX.createHash)(r),f=0;for(;(f=await this.readPromise(s,n,0,65536))!==0;)c.update(f===65536?n:n.slice(0,f));return c.digest(\"hex\")}finally{await this.closePromise(s)}}async removePromise(t,{recursive:r=!0,maxRetries:s=5}={}){let a;try{a=await this.lstatPromise(t)}catch(n){if(n.code===\"ENOENT\")return;throw n}if(a.isDirectory()){if(r){let n=await this.readdirPromise(t);await Promise.all(n.map(c=>this.removePromise(this.pathUtils.resolve(t,c))))}for(let n=0;n<=s;n++)try{await this.rmdirPromise(t);break}catch(c){if(c.code!==\"EBUSY\"&&c.code!==\"ENOTEMPTY\")throw c;n<s&&await new Promise(f=>setTimeout(f,n*100))}}else await this.unlinkPromise(t)}removeSync(t,{recursive:r=!0}={}){let s;try{s=this.lstatSync(t)}catch(a){if(a.code===\"ENOENT\")return;throw a}if(s.isDirectory()){if(r)for(let a of this.readdirSync(t))this.removeSync(this.pathUtils.resolve(t,a));this.rmdirSync(t)}else this.unlinkSync(t)}async mkdirpPromise(t,{chmod:r,utimes:s}={}){if(t=this.resolve(t),t===this.pathUtils.dirname(t))return;let a=t.split(this.pathUtils.sep),n;for(let c=2;c<=a.length;++c){let f=a.slice(0,c).join(this.pathUtils.sep);if(!this.existsSync(f)){try{await this.mkdirPromise(f)}catch(p){if(p.code===\"EEXIST\")continue;throw p}if(n??=f,r!=null&&await this.chmodPromise(f,r),s!=null)await this.utimesPromise(f,s[0],s[1]);else{let p=await this.statPromise(this.pathUtils.dirname(f));await this.utimesPromise(f,p.atime,p.mtime)}}}return n}mkdirpSync(t,{chmod:r,utimes:s}={}){if(t=this.resolve(t),t===this.pathUtils.dirname(t))return;let a=t.split(this.pathUtils.sep),n;for(let c=2;c<=a.length;++c){let f=a.slice(0,c).join(this.pathUtils.sep);if(!this.existsSync(f)){try{this.mkdirSync(f)}catch(p){if(p.code===\"EEXIST\")continue;throw p}if(n??=f,r!=null&&this.chmodSync(f,r),s!=null)this.utimesSync(f,s[0],s[1]);else{let p=this.statSync(this.pathUtils.dirname(f));this.utimesSync(f,p.atime,p.mtime)}}}return n}async copyPromise(t,r,{baseFs:s=this,overwrite:a=!0,stableSort:n=!1,stableTime:c=!1,linkStrategy:f=null}={}){return await pX(this,t,s,r,{overwrite:a,stableSort:n,stableTime:c,linkStrategy:f})}copySync(t,r,{baseFs:s=this,overwrite:a=!0}={}){let n=s.lstatSync(r),c=this.existsSync(t);if(n.isDirectory()){this.mkdirpSync(t);let p=s.readdirSync(r);for(let h of p)this.copySync(this.pathUtils.join(t,h),s.pathUtils.join(r,h),{baseFs:s,overwrite:a})}else if(n.isFile()){if(!c||a){c&&this.removeSync(t);let p=s.readFileSync(r);this.writeFileSync(t,p)}}else if(n.isSymbolicLink()){if(!c||a){c&&this.removeSync(t);let p=s.readlinkSync(r);this.symlinkSync(XP(this.pathUtils,p),t)}}else throw new Error(`Unsupported file type (file: ${r}, mode: 0o${n.mode.toString(8).padStart(6,\"0\")})`);let f=n.mode&511;this.chmodSync(t,f)}async changeFilePromise(t,r,s={}){return Buffer.isBuffer(r)?this.changeFileBufferPromise(t,r,s):this.changeFileTextPromise(t,r,s)}async changeFileBufferPromise(t,r,{mode:s}={}){let a=Buffer.alloc(0);try{a=await this.readFilePromise(t)}catch{}Buffer.compare(a,r)!==0&&await this.writeFilePromise(t,r,{mode:s})}async changeFileTextPromise(t,r,{automaticNewlines:s,mode:a}={}){let n=\"\";try{n=await this.readFilePromise(t,\"utf8\")}catch{}let c=s?md(n,r):r;n!==c&&await this.writeFilePromise(t,c,{mode:a})}changeFileSync(t,r,s={}){return Buffer.isBuffer(r)?this.changeFileBufferSync(t,r,s):this.changeFileTextSync(t,r,s)}changeFileBufferSync(t,r,{mode:s}={}){let a=Buffer.alloc(0);try{a=this.readFileSync(t)}catch{}Buffer.compare(a,r)!==0&&this.writeFileSync(t,r,{mode:s})}changeFileTextSync(t,r,{automaticNewlines:s=!1,mode:a}={}){let n=\"\";try{n=this.readFileSync(t,\"utf8\")}catch{}let c=s?md(n,r):r;n!==c&&this.writeFileSync(t,c,{mode:a})}async movePromise(t,r){try{await this.renamePromise(t,r)}catch(s){if(s.code===\"EXDEV\")await this.copyPromise(r,t),await this.removePromise(t);else throw s}}moveSync(t,r){try{this.renameSync(t,r)}catch(s){if(s.code===\"EXDEV\")this.copySync(r,t),this.removeSync(t);else throw s}}async lockPromise(t,r){let s=`${t}.flock`,a=1e3/60,n=Date.now(),c=null,f=async()=>{let p;try{[p]=await this.readJsonPromise(s)}catch{return Date.now()-n<500}try{return process.kill(p,0),!0}catch{return!1}};for(;c===null;)try{c=await this.openPromise(s,\"wx\")}catch(p){if(p.code===\"EEXIST\"){if(!await f())try{await this.unlinkPromise(s);continue}catch{}if(Date.now()-n<60*1e3)await new Promise(h=>setTimeout(h,a));else throw new Error(`Couldn't acquire a lock in a reasonable time (via ${s})`)}else throw p}await this.writePromise(c,JSON.stringify([process.pid]));try{return await r()}finally{try{await this.closePromise(c),await this.unlinkPromise(s)}catch{}}}async readJsonPromise(t){let r=await this.readFilePromise(t,\"utf8\");try{return JSON.parse(r)}catch(s){throw s.message+=` (in ${t})`,s}}readJsonSync(t){let r=this.readFileSync(t,\"utf8\");try{return JSON.parse(r)}catch(s){throw s.message+=` (in ${t})`,s}}async writeJsonPromise(t,r,{compact:s=!1}={}){let a=s?0:2;return await this.writeFilePromise(t,`${JSON.stringify(r,null,a)}\n`)}writeJsonSync(t,r,{compact:s=!1}={}){let a=s?0:2;return this.writeFileSync(t,`${JSON.stringify(r,null,a)}\n`)}async preserveTimePromise(t,r){let s=await this.lstatPromise(t),a=await r();typeof a<\"u\"&&(t=a),await this.lutimesPromise(t,s.atime,s.mtime)}async preserveTimeSync(t,r){let s=this.lstatSync(t),a=r();typeof a<\"u\"&&(t=a),this.lutimesSync(t,s.atime,s.mtime)}},Hf=class extends yp{constructor(){super(K)}}});var Gs,Ep=Ze(()=>{yd();Gs=class extends yp{getExtractHint(t){return this.baseFs.getExtractHint(t)}resolve(t){return this.mapFromBase(this.baseFs.resolve(this.mapToBase(t)))}getRealPath(){return this.mapFromBase(this.baseFs.getRealPath())}async openPromise(t,r,s){return this.baseFs.openPromise(this.mapToBase(t),r,s)}openSync(t,r,s){return this.baseFs.openSync(this.mapToBase(t),r,s)}async opendirPromise(t,r){return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(t),r),{path:t})}opendirSync(t,r){return Object.assign(this.baseFs.opendirSync(this.mapToBase(t),r),{path:t})}async readPromise(t,r,s,a,n){return await this.baseFs.readPromise(t,r,s,a,n)}readSync(t,r,s,a,n){return this.baseFs.readSync(t,r,s,a,n)}async writePromise(t,r,s,a,n){return typeof r==\"string\"?await this.baseFs.writePromise(t,r,s):await this.baseFs.writePromise(t,r,s,a,n)}writeSync(t,r,s,a,n){return typeof r==\"string\"?this.baseFs.writeSync(t,r,s):this.baseFs.writeSync(t,r,s,a,n)}async closePromise(t){return this.baseFs.closePromise(t)}closeSync(t){this.baseFs.closeSync(t)}createReadStream(t,r){return this.baseFs.createReadStream(t!==null?this.mapToBase(t):t,r)}createWriteStream(t,r){return this.baseFs.createWriteStream(t!==null?this.mapToBase(t):t,r)}async realpathPromise(t){return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(t)))}realpathSync(t){return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(t)))}async existsPromise(t){return this.baseFs.existsPromise(this.mapToBase(t))}existsSync(t){return this.baseFs.existsSync(this.mapToBase(t))}accessSync(t,r){return this.baseFs.accessSync(this.mapToBase(t),r)}async accessPromise(t,r){return this.baseFs.accessPromise(this.mapToBase(t),r)}async statPromise(t,r){return this.baseFs.statPromise(this.mapToBase(t),r)}statSync(t,r){return this.baseFs.statSync(this.mapToBase(t),r)}async fstatPromise(t,r){return this.baseFs.fstatPromise(t,r)}fstatSync(t,r){return this.baseFs.fstatSync(t,r)}lstatPromise(t,r){return this.baseFs.lstatPromise(this.mapToBase(t),r)}lstatSync(t,r){return this.baseFs.lstatSync(this.mapToBase(t),r)}async fchmodPromise(t,r){return this.baseFs.fchmodPromise(t,r)}fchmodSync(t,r){return this.baseFs.fchmodSync(t,r)}async chmodPromise(t,r){return this.baseFs.chmodPromise(this.mapToBase(t),r)}chmodSync(t,r){return this.baseFs.chmodSync(this.mapToBase(t),r)}async fchownPromise(t,r,s){return this.baseFs.fchownPromise(t,r,s)}fchownSync(t,r,s){return this.baseFs.fchownSync(t,r,s)}async chownPromise(t,r,s){return this.baseFs.chownPromise(this.mapToBase(t),r,s)}chownSync(t,r,s){return this.baseFs.chownSync(this.mapToBase(t),r,s)}async renamePromise(t,r){return this.baseFs.renamePromise(this.mapToBase(t),this.mapToBase(r))}renameSync(t,r){return this.baseFs.renameSync(this.mapToBase(t),this.mapToBase(r))}async copyFilePromise(t,r,s=0){return this.baseFs.copyFilePromise(this.mapToBase(t),this.mapToBase(r),s)}copyFileSync(t,r,s=0){return this.baseFs.copyFileSync(this.mapToBase(t),this.mapToBase(r),s)}async appendFilePromise(t,r,s){return this.baseFs.appendFilePromise(this.fsMapToBase(t),r,s)}appendFileSync(t,r,s){return this.baseFs.appendFileSync(this.fsMapToBase(t),r,s)}async writeFilePromise(t,r,s){return this.baseFs.writeFilePromise(this.fsMapToBase(t),r,s)}writeFileSync(t,r,s){return this.baseFs.writeFileSync(this.fsMapToBase(t),r,s)}async unlinkPromise(t){return this.baseFs.unlinkPromise(this.mapToBase(t))}unlinkSync(t){return this.baseFs.unlinkSync(this.mapToBase(t))}async utimesPromise(t,r,s){return this.baseFs.utimesPromise(this.mapToBase(t),r,s)}utimesSync(t,r,s){return this.baseFs.utimesSync(this.mapToBase(t),r,s)}async lutimesPromise(t,r,s){return this.baseFs.lutimesPromise(this.mapToBase(t),r,s)}lutimesSync(t,r,s){return this.baseFs.lutimesSync(this.mapToBase(t),r,s)}async mkdirPromise(t,r){return this.baseFs.mkdirPromise(this.mapToBase(t),r)}mkdirSync(t,r){return this.baseFs.mkdirSync(this.mapToBase(t),r)}async rmdirPromise(t,r){return this.baseFs.rmdirPromise(this.mapToBase(t),r)}rmdirSync(t,r){return this.baseFs.rmdirSync(this.mapToBase(t),r)}async rmPromise(t,r){return this.baseFs.rmPromise(this.mapToBase(t),r)}rmSync(t,r){return this.baseFs.rmSync(this.mapToBase(t),r)}async linkPromise(t,r){return this.baseFs.linkPromise(this.mapToBase(t),this.mapToBase(r))}linkSync(t,r){return this.baseFs.linkSync(this.mapToBase(t),this.mapToBase(r))}async symlinkPromise(t,r,s){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(t))return this.baseFs.symlinkPromise(this.mapToBase(t),a,s);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),t)),c=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkPromise(c,a,s)}symlinkSync(t,r,s){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(t))return this.baseFs.symlinkSync(this.mapToBase(t),a,s);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),t)),c=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkSync(c,a,s)}async readFilePromise(t,r){return this.baseFs.readFilePromise(this.fsMapToBase(t),r)}readFileSync(t,r){return this.baseFs.readFileSync(this.fsMapToBase(t),r)}readdirPromise(t,r){return this.baseFs.readdirPromise(this.mapToBase(t),r)}readdirSync(t,r){return this.baseFs.readdirSync(this.mapToBase(t),r)}async readlinkPromise(t){return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(t)))}readlinkSync(t){return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(t)))}async truncatePromise(t,r){return this.baseFs.truncatePromise(this.mapToBase(t),r)}truncateSync(t,r){return this.baseFs.truncateSync(this.mapToBase(t),r)}async ftruncatePromise(t,r){return this.baseFs.ftruncatePromise(t,r)}ftruncateSync(t,r){return this.baseFs.ftruncateSync(t,r)}watch(t,r,s){return this.baseFs.watch(this.mapToBase(t),r,s)}watchFile(t,r,s){return this.baseFs.watchFile(this.mapToBase(t),r,s)}unwatchFile(t,r){return this.baseFs.unwatchFile(this.mapToBase(t),r)}fsMapToBase(t){return typeof t==\"number\"?t:this.mapToBase(t)}}});var jf,CX=Ze(()=>{Ep();jf=class extends Gs{constructor(t,{baseFs:r,pathUtils:s}){super(s),this.target=t,this.baseFs=r}getRealPath(){return this.target}getBaseFs(){return this.baseFs}mapFromBase(t){return t}mapToBase(t){return t}}});function wX(e){let t=e;return typeof e.path==\"string\"&&(t.path=fe.toPortablePath(e.path)),t}var BX,Yn,Ed=Ze(()=>{BX=et(Ie(\"fs\"));yd();ol();Yn=class extends Hf{constructor(t=BX.default){super(),this.realFs=t}getExtractHint(){return!1}getRealPath(){return vt.root}resolve(t){return K.resolve(t)}async openPromise(t,r,s){return await new Promise((a,n)=>{this.realFs.open(fe.fromPortablePath(t),r,s,this.makeCallback(a,n))})}openSync(t,r,s){return this.realFs.openSync(fe.fromPortablePath(t),r,s)}async opendirPromise(t,r){return await new Promise((s,a)=>{typeof r<\"u\"?this.realFs.opendir(fe.fromPortablePath(t),r,this.makeCallback(s,a)):this.realFs.opendir(fe.fromPortablePath(t),this.makeCallback(s,a))}).then(s=>{let a=s;return Object.defineProperty(a,\"path\",{value:t,configurable:!0,writable:!0}),a})}opendirSync(t,r){let a=typeof r<\"u\"?this.realFs.opendirSync(fe.fromPortablePath(t),r):this.realFs.opendirSync(fe.fromPortablePath(t));return Object.defineProperty(a,\"path\",{value:t,configurable:!0,writable:!0}),a}async readPromise(t,r,s=0,a=0,n=-1){return await new Promise((c,f)=>{this.realFs.read(t,r,s,a,n,(p,h)=>{p?f(p):c(h)})})}readSync(t,r,s,a,n){return this.realFs.readSync(t,r,s,a,n)}async writePromise(t,r,s,a,n){return await new Promise((c,f)=>typeof r==\"string\"?this.realFs.write(t,r,s,this.makeCallback(c,f)):this.realFs.write(t,r,s,a,n,this.makeCallback(c,f)))}writeSync(t,r,s,a,n){return typeof r==\"string\"?this.realFs.writeSync(t,r,s):this.realFs.writeSync(t,r,s,a,n)}async closePromise(t){await new Promise((r,s)=>{this.realFs.close(t,this.makeCallback(r,s))})}closeSync(t){this.realFs.closeSync(t)}createReadStream(t,r){let s=t!==null?fe.fromPortablePath(t):t;return this.realFs.createReadStream(s,r)}createWriteStream(t,r){let s=t!==null?fe.fromPortablePath(t):t;return this.realFs.createWriteStream(s,r)}async realpathPromise(t){return await new Promise((r,s)=>{this.realFs.realpath(fe.fromPortablePath(t),{},this.makeCallback(r,s))}).then(r=>fe.toPortablePath(r))}realpathSync(t){return fe.toPortablePath(this.realFs.realpathSync(fe.fromPortablePath(t),{}))}async existsPromise(t){return await new Promise(r=>{this.realFs.exists(fe.fromPortablePath(t),r)})}accessSync(t,r){return this.realFs.accessSync(fe.fromPortablePath(t),r)}async accessPromise(t,r){return await new Promise((s,a)=>{this.realFs.access(fe.fromPortablePath(t),r,this.makeCallback(s,a))})}existsSync(t){return this.realFs.existsSync(fe.fromPortablePath(t))}async statPromise(t,r){return await new Promise((s,a)=>{r?this.realFs.stat(fe.fromPortablePath(t),r,this.makeCallback(s,a)):this.realFs.stat(fe.fromPortablePath(t),this.makeCallback(s,a))})}statSync(t,r){return r?this.realFs.statSync(fe.fromPortablePath(t),r):this.realFs.statSync(fe.fromPortablePath(t))}async fstatPromise(t,r){return await new Promise((s,a)=>{r?this.realFs.fstat(t,r,this.makeCallback(s,a)):this.realFs.fstat(t,this.makeCallback(s,a))})}fstatSync(t,r){return r?this.realFs.fstatSync(t,r):this.realFs.fstatSync(t)}async lstatPromise(t,r){return await new Promise((s,a)=>{r?this.realFs.lstat(fe.fromPortablePath(t),r,this.makeCallback(s,a)):this.realFs.lstat(fe.fromPortablePath(t),this.makeCallback(s,a))})}lstatSync(t,r){return r?this.realFs.lstatSync(fe.fromPortablePath(t),r):this.realFs.lstatSync(fe.fromPortablePath(t))}async fchmodPromise(t,r){return await new Promise((s,a)=>{this.realFs.fchmod(t,r,this.makeCallback(s,a))})}fchmodSync(t,r){return this.realFs.fchmodSync(t,r)}async chmodPromise(t,r){return await new Promise((s,a)=>{this.realFs.chmod(fe.fromPortablePath(t),r,this.makeCallback(s,a))})}chmodSync(t,r){return this.realFs.chmodSync(fe.fromPortablePath(t),r)}async fchownPromise(t,r,s){return await new Promise((a,n)=>{this.realFs.fchown(t,r,s,this.makeCallback(a,n))})}fchownSync(t,r,s){return this.realFs.fchownSync(t,r,s)}async chownPromise(t,r,s){return await new Promise((a,n)=>{this.realFs.chown(fe.fromPortablePath(t),r,s,this.makeCallback(a,n))})}chownSync(t,r,s){return this.realFs.chownSync(fe.fromPortablePath(t),r,s)}async renamePromise(t,r){return await new Promise((s,a)=>{this.realFs.rename(fe.fromPortablePath(t),fe.fromPortablePath(r),this.makeCallback(s,a))})}renameSync(t,r){return this.realFs.renameSync(fe.fromPortablePath(t),fe.fromPortablePath(r))}async copyFilePromise(t,r,s=0){return await new Promise((a,n)=>{this.realFs.copyFile(fe.fromPortablePath(t),fe.fromPortablePath(r),s,this.makeCallback(a,n))})}copyFileSync(t,r,s=0){return this.realFs.copyFileSync(fe.fromPortablePath(t),fe.fromPortablePath(r),s)}async appendFilePromise(t,r,s){return await new Promise((a,n)=>{let c=typeof t==\"string\"?fe.fromPortablePath(t):t;s?this.realFs.appendFile(c,r,s,this.makeCallback(a,n)):this.realFs.appendFile(c,r,this.makeCallback(a,n))})}appendFileSync(t,r,s){let a=typeof t==\"string\"?fe.fromPortablePath(t):t;s?this.realFs.appendFileSync(a,r,s):this.realFs.appendFileSync(a,r)}async writeFilePromise(t,r,s){return await new Promise((a,n)=>{let c=typeof t==\"string\"?fe.fromPortablePath(t):t;s?this.realFs.writeFile(c,r,s,this.makeCallback(a,n)):this.realFs.writeFile(c,r,this.makeCallback(a,n))})}writeFileSync(t,r,s){let a=typeof t==\"string\"?fe.fromPortablePath(t):t;s?this.realFs.writeFileSync(a,r,s):this.realFs.writeFileSync(a,r)}async unlinkPromise(t){return await new Promise((r,s)=>{this.realFs.unlink(fe.fromPortablePath(t),this.makeCallback(r,s))})}unlinkSync(t){return this.realFs.unlinkSync(fe.fromPortablePath(t))}async utimesPromise(t,r,s){return await new Promise((a,n)=>{this.realFs.utimes(fe.fromPortablePath(t),r,s,this.makeCallback(a,n))})}utimesSync(t,r,s){this.realFs.utimesSync(fe.fromPortablePath(t),r,s)}async lutimesPromise(t,r,s){return await new Promise((a,n)=>{this.realFs.lutimes(fe.fromPortablePath(t),r,s,this.makeCallback(a,n))})}lutimesSync(t,r,s){this.realFs.lutimesSync(fe.fromPortablePath(t),r,s)}async mkdirPromise(t,r){return await new Promise((s,a)=>{this.realFs.mkdir(fe.fromPortablePath(t),r,this.makeCallback(s,a))})}mkdirSync(t,r){return this.realFs.mkdirSync(fe.fromPortablePath(t),r)}async rmdirPromise(t,r){return await new Promise((s,a)=>{r?this.realFs.rmdir(fe.fromPortablePath(t),r,this.makeCallback(s,a)):this.realFs.rmdir(fe.fromPortablePath(t),this.makeCallback(s,a))})}rmdirSync(t,r){return this.realFs.rmdirSync(fe.fromPortablePath(t),r)}async rmPromise(t,r){return await new Promise((s,a)=>{r?this.realFs.rm(fe.fromPortablePath(t),r,this.makeCallback(s,a)):this.realFs.rm(fe.fromPortablePath(t),this.makeCallback(s,a))})}rmSync(t,r){return this.realFs.rmSync(fe.fromPortablePath(t),r)}async linkPromise(t,r){return await new Promise((s,a)=>{this.realFs.link(fe.fromPortablePath(t),fe.fromPortablePath(r),this.makeCallback(s,a))})}linkSync(t,r){return this.realFs.linkSync(fe.fromPortablePath(t),fe.fromPortablePath(r))}async symlinkPromise(t,r,s){return await new Promise((a,n)=>{this.realFs.symlink(fe.fromPortablePath(t.replace(/\\/+$/,\"\")),fe.fromPortablePath(r),s,this.makeCallback(a,n))})}symlinkSync(t,r,s){return this.realFs.symlinkSync(fe.fromPortablePath(t.replace(/\\/+$/,\"\")),fe.fromPortablePath(r),s)}async readFilePromise(t,r){return await new Promise((s,a)=>{let n=typeof t==\"string\"?fe.fromPortablePath(t):t;this.realFs.readFile(n,r,this.makeCallback(s,a))})}readFileSync(t,r){let s=typeof t==\"string\"?fe.fromPortablePath(t):t;return this.realFs.readFileSync(s,r)}async readdirPromise(t,r){return await new Promise((s,a)=>{r?r.recursive&&process.platform===\"win32\"?r.withFileTypes?this.realFs.readdir(fe.fromPortablePath(t),r,this.makeCallback(n=>s(n.map(wX)),a)):this.realFs.readdir(fe.fromPortablePath(t),r,this.makeCallback(n=>s(n.map(fe.toPortablePath)),a)):this.realFs.readdir(fe.fromPortablePath(t),r,this.makeCallback(s,a)):this.realFs.readdir(fe.fromPortablePath(t),this.makeCallback(s,a))})}readdirSync(t,r){return r?r.recursive&&process.platform===\"win32\"?r.withFileTypes?this.realFs.readdirSync(fe.fromPortablePath(t),r).map(wX):this.realFs.readdirSync(fe.fromPortablePath(t),r).map(fe.toPortablePath):this.realFs.readdirSync(fe.fromPortablePath(t),r):this.realFs.readdirSync(fe.fromPortablePath(t))}async readlinkPromise(t){return await new Promise((r,s)=>{this.realFs.readlink(fe.fromPortablePath(t),this.makeCallback(r,s))}).then(r=>fe.toPortablePath(r))}readlinkSync(t){return fe.toPortablePath(this.realFs.readlinkSync(fe.fromPortablePath(t)))}async truncatePromise(t,r){return await new Promise((s,a)=>{this.realFs.truncate(fe.fromPortablePath(t),r,this.makeCallback(s,a))})}truncateSync(t,r){return this.realFs.truncateSync(fe.fromPortablePath(t),r)}async ftruncatePromise(t,r){return await new Promise((s,a)=>{this.realFs.ftruncate(t,r,this.makeCallback(s,a))})}ftruncateSync(t,r){return this.realFs.ftruncateSync(t,r)}watch(t,r,s){return this.realFs.watch(fe.fromPortablePath(t),r,s)}watchFile(t,r,s){return this.realFs.watchFile(fe.fromPortablePath(t),r,s)}unwatchFile(t,r){return this.realFs.unwatchFile(fe.fromPortablePath(t),r)}makeCallback(t,r){return(s,a)=>{s?r(s):t(a)}}}});var bn,vX=Ze(()=>{Ed();Ep();ol();bn=class extends Gs{constructor(t,{baseFs:r=new Yn}={}){super(K),this.target=this.pathUtils.normalize(t),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.target)}resolve(t){return this.pathUtils.isAbsolute(t)?K.normalize(t):this.baseFs.resolve(K.join(this.target,t))}mapFromBase(t){return t}mapToBase(t){return this.pathUtils.isAbsolute(t)?t:this.pathUtils.join(this.target,t)}}});var SX,Gf,DX=Ze(()=>{Ed();Ep();ol();SX=vt.root,Gf=class extends Gs{constructor(t,{baseFs:r=new Yn}={}){super(K),this.target=this.pathUtils.resolve(vt.root,t),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.pathUtils.relative(vt.root,this.target))}getTarget(){return this.target}getBaseFs(){return this.baseFs}mapToBase(t){let r=this.pathUtils.normalize(t);if(this.pathUtils.isAbsolute(t))return this.pathUtils.resolve(this.target,this.pathUtils.relative(SX,t));if(r.match(/^\\.\\.\\/?/))throw new Error(`Resolving this path (${t}) would escape the jail`);return this.pathUtils.resolve(this.target,t)}mapFromBase(t){return this.pathUtils.resolve(SX,this.pathUtils.relative(this.target,t))}}});var cE,bX=Ze(()=>{Ep();cE=class extends Gs{constructor(r,s){super(s);this.instance=null;this.factory=r}get baseFs(){return this.instance||(this.instance=this.factory()),this.instance}set baseFs(r){this.instance=r}mapFromBase(r){return r}mapToBase(r){return r}}});var Id,al,Xh,PX=Ze(()=>{Id=Ie(\"fs\");yd();Ed();fU();zP();ol();al=4278190080,Xh=class extends Hf{constructor({baseFs:r=new Yn,filter:s=null,magicByte:a=42,maxOpenFiles:n=1/0,useCache:c=!0,maxAge:f=5e3,typeCheck:p=Id.constants.S_IFREG,getMountPoint:h,factoryPromise:E,factorySync:C}){if(Math.floor(a)!==a||!(a>1&&a<=127))throw new Error(\"The magic byte must be set to a round value between 1 and 127 included\");super();this.fdMap=new Map;this.nextFd=3;this.isMount=new Set;this.notMount=new Set;this.realPaths=new Map;this.limitOpenFilesTimeout=null;this.baseFs=r,this.mountInstances=c?new Map:null,this.factoryPromise=E,this.factorySync=C,this.filter=s,this.getMountPoint=h,this.magic=a<<24,this.maxAge=f,this.maxOpenFiles=n,this.typeCheck=p}getExtractHint(r){return this.baseFs.getExtractHint(r)}getRealPath(){return this.baseFs.getRealPath()}saveAndClose(){if(dd(this),this.mountInstances)for(let[r,{childFs:s}]of this.mountInstances.entries())s.saveAndClose?.(),this.mountInstances.delete(r)}discardAndClose(){if(dd(this),this.mountInstances)for(let[r,{childFs:s}]of this.mountInstances.entries())s.discardAndClose?.(),this.mountInstances.delete(r)}resolve(r){return this.baseFs.resolve(r)}remapFd(r,s){let a=this.nextFd++|this.magic;return this.fdMap.set(a,[r,s]),a}async openPromise(r,s,a){return await this.makeCallPromise(r,async()=>await this.baseFs.openPromise(r,s,a),async(n,{subPath:c})=>this.remapFd(n,await n.openPromise(c,s,a)))}openSync(r,s,a){return this.makeCallSync(r,()=>this.baseFs.openSync(r,s,a),(n,{subPath:c})=>this.remapFd(n,n.openSync(c,s,a)))}async opendirPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.opendirPromise(r,s),async(a,{subPath:n})=>await a.opendirPromise(n,s),{requireSubpath:!1})}opendirSync(r,s){return this.makeCallSync(r,()=>this.baseFs.opendirSync(r,s),(a,{subPath:n})=>a.opendirSync(n,s),{requireSubpath:!1})}async readPromise(r,s,a,n,c){if((r&al)!==this.magic)return await this.baseFs.readPromise(r,s,a,n,c);let f=this.fdMap.get(r);if(typeof f>\"u\")throw Go(\"read\");let[p,h]=f;return await p.readPromise(h,s,a,n,c)}readSync(r,s,a,n,c){if((r&al)!==this.magic)return this.baseFs.readSync(r,s,a,n,c);let f=this.fdMap.get(r);if(typeof f>\"u\")throw Go(\"readSync\");let[p,h]=f;return p.readSync(h,s,a,n,c)}async writePromise(r,s,a,n,c){if((r&al)!==this.magic)return typeof s==\"string\"?await this.baseFs.writePromise(r,s,a):await this.baseFs.writePromise(r,s,a,n,c);let f=this.fdMap.get(r);if(typeof f>\"u\")throw Go(\"write\");let[p,h]=f;return typeof s==\"string\"?await p.writePromise(h,s,a):await p.writePromise(h,s,a,n,c)}writeSync(r,s,a,n,c){if((r&al)!==this.magic)return typeof s==\"string\"?this.baseFs.writeSync(r,s,a):this.baseFs.writeSync(r,s,a,n,c);let f=this.fdMap.get(r);if(typeof f>\"u\")throw Go(\"writeSync\");let[p,h]=f;return typeof s==\"string\"?p.writeSync(h,s,a):p.writeSync(h,s,a,n,c)}async closePromise(r){if((r&al)!==this.magic)return await this.baseFs.closePromise(r);let s=this.fdMap.get(r);if(typeof s>\"u\")throw Go(\"close\");this.fdMap.delete(r);let[a,n]=s;return await a.closePromise(n)}closeSync(r){if((r&al)!==this.magic)return this.baseFs.closeSync(r);let s=this.fdMap.get(r);if(typeof s>\"u\")throw Go(\"closeSync\");this.fdMap.delete(r);let[a,n]=s;return a.closeSync(n)}createReadStream(r,s){return r===null?this.baseFs.createReadStream(r,s):this.makeCallSync(r,()=>this.baseFs.createReadStream(r,s),(a,{archivePath:n,subPath:c})=>{let f=a.createReadStream(c,s);return f.path=fe.fromPortablePath(this.pathUtils.join(n,c)),f})}createWriteStream(r,s){return r===null?this.baseFs.createWriteStream(r,s):this.makeCallSync(r,()=>this.baseFs.createWriteStream(r,s),(a,{subPath:n})=>a.createWriteStream(n,s))}async realpathPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.realpathPromise(r),async(s,{archivePath:a,subPath:n})=>{let c=this.realPaths.get(a);return typeof c>\"u\"&&(c=await this.baseFs.realpathPromise(a),this.realPaths.set(a,c)),this.pathUtils.join(c,this.pathUtils.relative(vt.root,await s.realpathPromise(n)))})}realpathSync(r){return this.makeCallSync(r,()=>this.baseFs.realpathSync(r),(s,{archivePath:a,subPath:n})=>{let c=this.realPaths.get(a);return typeof c>\"u\"&&(c=this.baseFs.realpathSync(a),this.realPaths.set(a,c)),this.pathUtils.join(c,this.pathUtils.relative(vt.root,s.realpathSync(n)))})}async existsPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.existsPromise(r),async(s,{subPath:a})=>await s.existsPromise(a))}existsSync(r){return this.makeCallSync(r,()=>this.baseFs.existsSync(r),(s,{subPath:a})=>s.existsSync(a))}async accessPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.accessPromise(r,s),async(a,{subPath:n})=>await a.accessPromise(n,s))}accessSync(r,s){return this.makeCallSync(r,()=>this.baseFs.accessSync(r,s),(a,{subPath:n})=>a.accessSync(n,s))}async statPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.statPromise(r,s),async(a,{subPath:n})=>await a.statPromise(n,s))}statSync(r,s){return this.makeCallSync(r,()=>this.baseFs.statSync(r,s),(a,{subPath:n})=>a.statSync(n,s))}async fstatPromise(r,s){if((r&al)!==this.magic)return this.baseFs.fstatPromise(r,s);let a=this.fdMap.get(r);if(typeof a>\"u\")throw Go(\"fstat\");let[n,c]=a;return n.fstatPromise(c,s)}fstatSync(r,s){if((r&al)!==this.magic)return this.baseFs.fstatSync(r,s);let a=this.fdMap.get(r);if(typeof a>\"u\")throw Go(\"fstatSync\");let[n,c]=a;return n.fstatSync(c,s)}async lstatPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.lstatPromise(r,s),async(a,{subPath:n})=>await a.lstatPromise(n,s))}lstatSync(r,s){return this.makeCallSync(r,()=>this.baseFs.lstatSync(r,s),(a,{subPath:n})=>a.lstatSync(n,s))}async fchmodPromise(r,s){if((r&al)!==this.magic)return this.baseFs.fchmodPromise(r,s);let a=this.fdMap.get(r);if(typeof a>\"u\")throw Go(\"fchmod\");let[n,c]=a;return n.fchmodPromise(c,s)}fchmodSync(r,s){if((r&al)!==this.magic)return this.baseFs.fchmodSync(r,s);let a=this.fdMap.get(r);if(typeof a>\"u\")throw Go(\"fchmodSync\");let[n,c]=a;return n.fchmodSync(c,s)}async chmodPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.chmodPromise(r,s),async(a,{subPath:n})=>await a.chmodPromise(n,s))}chmodSync(r,s){return this.makeCallSync(r,()=>this.baseFs.chmodSync(r,s),(a,{subPath:n})=>a.chmodSync(n,s))}async fchownPromise(r,s,a){if((r&al)!==this.magic)return this.baseFs.fchownPromise(r,s,a);let n=this.fdMap.get(r);if(typeof n>\"u\")throw Go(\"fchown\");let[c,f]=n;return c.fchownPromise(f,s,a)}fchownSync(r,s,a){if((r&al)!==this.magic)return this.baseFs.fchownSync(r,s,a);let n=this.fdMap.get(r);if(typeof n>\"u\")throw Go(\"fchownSync\");let[c,f]=n;return c.fchownSync(f,s,a)}async chownPromise(r,s,a){return await this.makeCallPromise(r,async()=>await this.baseFs.chownPromise(r,s,a),async(n,{subPath:c})=>await n.chownPromise(c,s,a))}chownSync(r,s,a){return this.makeCallSync(r,()=>this.baseFs.chownSync(r,s,a),(n,{subPath:c})=>n.chownSync(c,s,a))}async renamePromise(r,s){return await this.makeCallPromise(r,async()=>await this.makeCallPromise(s,async()=>await this.baseFs.renamePromise(r,s),async()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})}),async(a,{subPath:n})=>await this.makeCallPromise(s,async()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})},async(c,{subPath:f})=>{if(a!==c)throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"});return await a.renamePromise(n,f)}))}renameSync(r,s){return this.makeCallSync(r,()=>this.makeCallSync(s,()=>this.baseFs.renameSync(r,s),()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})}),(a,{subPath:n})=>this.makeCallSync(s,()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})},(c,{subPath:f})=>{if(a!==c)throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"});return a.renameSync(n,f)}))}async copyFilePromise(r,s,a=0){let n=async(c,f,p,h)=>{if(a&Id.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${f}' -> ${h}'`),{code:\"EXDEV\"});if(a&Id.constants.COPYFILE_EXCL&&await this.existsPromise(f))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${f}' -> '${h}'`),{code:\"EEXIST\"});let E;try{E=await c.readFilePromise(f)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${f}' -> '${h}'`),{code:\"EINVAL\"})}await p.writeFilePromise(h,E)};return await this.makeCallPromise(r,async()=>await this.makeCallPromise(s,async()=>await this.baseFs.copyFilePromise(r,s,a),async(c,{subPath:f})=>await n(this.baseFs,r,c,f)),async(c,{subPath:f})=>await this.makeCallPromise(s,async()=>await n(c,f,this.baseFs,s),async(p,{subPath:h})=>c!==p?await n(c,f,p,h):await c.copyFilePromise(f,h,a)))}copyFileSync(r,s,a=0){let n=(c,f,p,h)=>{if(a&Id.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${f}' -> ${h}'`),{code:\"EXDEV\"});if(a&Id.constants.COPYFILE_EXCL&&this.existsSync(f))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${f}' -> '${h}'`),{code:\"EEXIST\"});let E;try{E=c.readFileSync(f)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${f}' -> '${h}'`),{code:\"EINVAL\"})}p.writeFileSync(h,E)};return this.makeCallSync(r,()=>this.makeCallSync(s,()=>this.baseFs.copyFileSync(r,s,a),(c,{subPath:f})=>n(this.baseFs,r,c,f)),(c,{subPath:f})=>this.makeCallSync(s,()=>n(c,f,this.baseFs,s),(p,{subPath:h})=>c!==p?n(c,f,p,h):c.copyFileSync(f,h,a)))}async appendFilePromise(r,s,a){return await this.makeCallPromise(r,async()=>await this.baseFs.appendFilePromise(r,s,a),async(n,{subPath:c})=>await n.appendFilePromise(c,s,a))}appendFileSync(r,s,a){return this.makeCallSync(r,()=>this.baseFs.appendFileSync(r,s,a),(n,{subPath:c})=>n.appendFileSync(c,s,a))}async writeFilePromise(r,s,a){return await this.makeCallPromise(r,async()=>await this.baseFs.writeFilePromise(r,s,a),async(n,{subPath:c})=>await n.writeFilePromise(c,s,a))}writeFileSync(r,s,a){return this.makeCallSync(r,()=>this.baseFs.writeFileSync(r,s,a),(n,{subPath:c})=>n.writeFileSync(c,s,a))}async unlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.unlinkPromise(r),async(s,{subPath:a})=>await s.unlinkPromise(a))}unlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.unlinkSync(r),(s,{subPath:a})=>s.unlinkSync(a))}async utimesPromise(r,s,a){return await this.makeCallPromise(r,async()=>await this.baseFs.utimesPromise(r,s,a),async(n,{subPath:c})=>await n.utimesPromise(c,s,a))}utimesSync(r,s,a){return this.makeCallSync(r,()=>this.baseFs.utimesSync(r,s,a),(n,{subPath:c})=>n.utimesSync(c,s,a))}async lutimesPromise(r,s,a){return await this.makeCallPromise(r,async()=>await this.baseFs.lutimesPromise(r,s,a),async(n,{subPath:c})=>await n.lutimesPromise(c,s,a))}lutimesSync(r,s,a){return this.makeCallSync(r,()=>this.baseFs.lutimesSync(r,s,a),(n,{subPath:c})=>n.lutimesSync(c,s,a))}async mkdirPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.mkdirPromise(r,s),async(a,{subPath:n})=>await a.mkdirPromise(n,s))}mkdirSync(r,s){return this.makeCallSync(r,()=>this.baseFs.mkdirSync(r,s),(a,{subPath:n})=>a.mkdirSync(n,s))}async rmdirPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.rmdirPromise(r,s),async(a,{subPath:n})=>await a.rmdirPromise(n,s))}rmdirSync(r,s){return this.makeCallSync(r,()=>this.baseFs.rmdirSync(r,s),(a,{subPath:n})=>a.rmdirSync(n,s))}async rmPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.rmPromise(r,s),async(a,{subPath:n})=>await a.rmPromise(n,s))}rmSync(r,s){return this.makeCallSync(r,()=>this.baseFs.rmSync(r,s),(a,{subPath:n})=>a.rmSync(n,s))}async linkPromise(r,s){return await this.makeCallPromise(s,async()=>await this.baseFs.linkPromise(r,s),async(a,{subPath:n})=>await a.linkPromise(r,n))}linkSync(r,s){return this.makeCallSync(s,()=>this.baseFs.linkSync(r,s),(a,{subPath:n})=>a.linkSync(r,n))}async symlinkPromise(r,s,a){return await this.makeCallPromise(s,async()=>await this.baseFs.symlinkPromise(r,s,a),async(n,{subPath:c})=>await n.symlinkPromise(r,c))}symlinkSync(r,s,a){return this.makeCallSync(s,()=>this.baseFs.symlinkSync(r,s,a),(n,{subPath:c})=>n.symlinkSync(r,c))}async readFilePromise(r,s){return this.makeCallPromise(r,async()=>await this.baseFs.readFilePromise(r,s),async(a,{subPath:n})=>await a.readFilePromise(n,s))}readFileSync(r,s){return this.makeCallSync(r,()=>this.baseFs.readFileSync(r,s),(a,{subPath:n})=>a.readFileSync(n,s))}async readdirPromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.readdirPromise(r,s),async(a,{subPath:n})=>await a.readdirPromise(n,s),{requireSubpath:!1})}readdirSync(r,s){return this.makeCallSync(r,()=>this.baseFs.readdirSync(r,s),(a,{subPath:n})=>a.readdirSync(n,s),{requireSubpath:!1})}async readlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.readlinkPromise(r),async(s,{subPath:a})=>await s.readlinkPromise(a))}readlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.readlinkSync(r),(s,{subPath:a})=>s.readlinkSync(a))}async truncatePromise(r,s){return await this.makeCallPromise(r,async()=>await this.baseFs.truncatePromise(r,s),async(a,{subPath:n})=>await a.truncatePromise(n,s))}truncateSync(r,s){return this.makeCallSync(r,()=>this.baseFs.truncateSync(r,s),(a,{subPath:n})=>a.truncateSync(n,s))}async ftruncatePromise(r,s){if((r&al)!==this.magic)return this.baseFs.ftruncatePromise(r,s);let a=this.fdMap.get(r);if(typeof a>\"u\")throw Go(\"ftruncate\");let[n,c]=a;return n.ftruncatePromise(c,s)}ftruncateSync(r,s){if((r&al)!==this.magic)return this.baseFs.ftruncateSync(r,s);let a=this.fdMap.get(r);if(typeof a>\"u\")throw Go(\"ftruncateSync\");let[n,c]=a;return n.ftruncateSync(c,s)}watch(r,s,a){return this.makeCallSync(r,()=>this.baseFs.watch(r,s,a),(n,{subPath:c})=>n.watch(c,s,a))}watchFile(r,s,a){return this.makeCallSync(r,()=>this.baseFs.watchFile(r,s,a),()=>lE(this,r,s,a))}unwatchFile(r,s){return this.makeCallSync(r,()=>this.baseFs.unwatchFile(r,s),()=>gd(this,r,s))}async makeCallPromise(r,s,a,{requireSubpath:n=!0}={}){if(typeof r!=\"string\")return await s();let c=this.resolve(r),f=this.findMount(c);return f?n&&f.subPath===\"/\"?await s():await this.getMountPromise(f.archivePath,async p=>await a(p,f)):await s()}makeCallSync(r,s,a,{requireSubpath:n=!0}={}){if(typeof r!=\"string\")return s();let c=this.resolve(r),f=this.findMount(c);return!f||n&&f.subPath===\"/\"?s():this.getMountSync(f.archivePath,p=>a(p,f))}findMount(r){if(this.filter&&!this.filter.test(r))return null;let s=\"\";for(;;){let a=r.substring(s.length),n=this.getMountPoint(a,s);if(!n)return null;if(s=this.pathUtils.join(s,n),!this.isMount.has(s)){if(this.notMount.has(s))continue;try{if(this.typeCheck!==null&&(this.baseFs.statSync(s).mode&Id.constants.S_IFMT)!==this.typeCheck){this.notMount.add(s);continue}}catch{return null}this.isMount.add(s)}return{archivePath:s,subPath:this.pathUtils.join(vt.root,r.substring(s.length))}}}limitOpenFiles(r){if(this.mountInstances===null)return;let s=Date.now(),a=s+this.maxAge,n=r===null?0:this.mountInstances.size-r;for(let[c,{childFs:f,expiresAt:p,refCount:h}]of this.mountInstances.entries())if(!(h!==0||f.hasOpenFileHandles?.())){if(s>=p){f.saveAndClose?.(),this.mountInstances.delete(c),n-=1;continue}else if(r===null||n<=0){a=p;break}f.saveAndClose?.(),this.mountInstances.delete(c),n-=1}this.limitOpenFilesTimeout===null&&(r===null&&this.mountInstances.size>0||r!==null)&&isFinite(a)&&(this.limitOpenFilesTimeout=setTimeout(()=>{this.limitOpenFilesTimeout=null,this.limitOpenFiles(null)},a-s).unref())}async getMountPromise(r,s){if(this.mountInstances){let a=this.mountInstances.get(r);if(!a){let n=await this.factoryPromise(this.baseFs,r);a=this.mountInstances.get(r),a||(a={childFs:n(),expiresAt:0,refCount:0})}this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,a.refCount+=1;try{return await s(a.childFs)}finally{a.refCount-=1}}else{let a=(await this.factoryPromise(this.baseFs,r))();try{return await s(a)}finally{a.saveAndClose?.()}}}getMountSync(r,s){if(this.mountInstances){let a=this.mountInstances.get(r);return a||(a={childFs:this.factorySync(this.baseFs,r),expiresAt:0,refCount:0}),this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,s(a.childFs)}else{let a=this.factorySync(this.baseFs,r);try{return s(a)}finally{a.saveAndClose?.()}}}}});var er,nx,xX=Ze(()=>{yd();ol();er=()=>Object.assign(new Error(\"ENOSYS: unsupported filesystem access\"),{code:\"ENOSYS\"}),nx=class e extends yp{static{this.instance=new e}constructor(){super(K)}getExtractHint(){throw er()}getRealPath(){throw er()}resolve(){throw er()}async openPromise(){throw er()}openSync(){throw er()}async opendirPromise(){throw er()}opendirSync(){throw er()}async readPromise(){throw er()}readSync(){throw er()}async writePromise(){throw er()}writeSync(){throw er()}async closePromise(){throw er()}closeSync(){throw er()}createWriteStream(){throw er()}createReadStream(){throw er()}async realpathPromise(){throw er()}realpathSync(){throw er()}async readdirPromise(){throw er()}readdirSync(){throw er()}async existsPromise(t){throw er()}existsSync(t){throw er()}async accessPromise(){throw er()}accessSync(){throw er()}async statPromise(){throw er()}statSync(){throw er()}async fstatPromise(t){throw er()}fstatSync(t){throw er()}async lstatPromise(t){throw er()}lstatSync(t){throw er()}async fchmodPromise(){throw er()}fchmodSync(){throw er()}async chmodPromise(){throw er()}chmodSync(){throw er()}async fchownPromise(){throw er()}fchownSync(){throw er()}async chownPromise(){throw er()}chownSync(){throw er()}async mkdirPromise(){throw er()}mkdirSync(){throw er()}async rmdirPromise(){throw er()}rmdirSync(){throw er()}async rmPromise(){throw er()}rmSync(){throw er()}async linkPromise(){throw er()}linkSync(){throw er()}async symlinkPromise(){throw er()}symlinkSync(){throw er()}async renamePromise(){throw er()}renameSync(){throw er()}async copyFilePromise(){throw er()}copyFileSync(){throw er()}async appendFilePromise(){throw er()}appendFileSync(){throw er()}async writeFilePromise(){throw er()}writeFileSync(){throw er()}async unlinkPromise(){throw er()}unlinkSync(){throw er()}async utimesPromise(){throw er()}utimesSync(){throw er()}async lutimesPromise(){throw er()}lutimesSync(){throw er()}async readFilePromise(){throw er()}readFileSync(){throw er()}async readlinkPromise(){throw er()}readlinkSync(){throw er()}async truncatePromise(){throw er()}truncateSync(){throw er()}async ftruncatePromise(t,r){throw er()}ftruncateSync(t,r){throw er()}watch(){throw er()}watchFile(){throw er()}unwatchFile(){throw er()}}});var $h,kX=Ze(()=>{Ep();ol();$h=class extends Gs{constructor(t){super(fe),this.baseFs=t}mapFromBase(t){return fe.fromPortablePath(t)}mapToBase(t){return fe.toPortablePath(t)}}});var Vje,AU,Yje,mo,QX=Ze(()=>{Ed();Ep();ol();Vje=/^[0-9]+$/,AU=/^(\\/(?:[^/]+\\/)*?(?:\\$\\$virtual|__virtual__))((?:\\/((?:[^/]+-)?[a-f0-9]+)(?:\\/([^/]+))?)?((?:\\/.*)?))$/,Yje=/^([^/]+-)?[a-f0-9]+$/,mo=class e extends Gs{static makeVirtualPath(t,r,s){if(K.basename(t)!==\"__virtual__\")throw new Error('Assertion failed: Virtual folders must be named \"__virtual__\"');if(!K.basename(r).match(Yje))throw new Error(\"Assertion failed: Virtual components must be ended by an hexadecimal hash\");let n=K.relative(K.dirname(t),s).split(\"/\"),c=0;for(;c<n.length&&n[c]===\"..\";)c+=1;let f=n.slice(c);return K.join(t,r,String(c),...f)}static resolveVirtual(t){let r=t.match(AU);if(!r||!r[3]&&r[5])return t;let s=K.dirname(r[1]);if(!r[3]||!r[4])return s;if(!Vje.test(r[4]))return t;let n=Number(r[4]),c=\"../\".repeat(n),f=r[5]||\".\";return e.resolveVirtual(K.join(s,c,f))}constructor({baseFs:t=new Yn}={}){super(K),this.baseFs=t}getExtractHint(t){return this.baseFs.getExtractHint(t)}getRealPath(){return this.baseFs.getRealPath()}realpathSync(t){let r=t.match(AU);if(!r)return this.baseFs.realpathSync(t);if(!r[5])return t;let s=this.baseFs.realpathSync(this.mapToBase(t));return e.makeVirtualPath(r[1],r[3],s)}async realpathPromise(t){let r=t.match(AU);if(!r)return await this.baseFs.realpathPromise(t);if(!r[5])return t;let s=await this.baseFs.realpathPromise(this.mapToBase(t));return e.makeVirtualPath(r[1],r[3],s)}mapToBase(t){if(t===\"\")return t;if(this.pathUtils.isAbsolute(t))return e.resolveVirtual(t);let r=e.resolveVirtual(this.baseFs.resolve(vt.dot)),s=e.resolveVirtual(this.baseFs.resolve(t));return K.relative(r,s)||vt.dot}mapFromBase(t){return t}}});function Kje(e,t){return typeof pU.default.isUtf8<\"u\"?pU.default.isUtf8(e):Buffer.byteLength(t)===e.byteLength}var pU,RX,TX,ix,FX=Ze(()=>{pU=et(Ie(\"buffer\")),RX=Ie(\"url\"),TX=Ie(\"util\");Ep();ol();ix=class extends Gs{constructor(t){super(fe),this.baseFs=t}mapFromBase(t){return t}mapToBase(t){if(typeof t==\"string\")return t;if(t instanceof URL)return(0,RX.fileURLToPath)(t);if(Buffer.isBuffer(t)){let r=t.toString();if(!Kje(t,r))throw new Error(\"Non-utf8 buffers are not supported at the moment. Please upvote the following issue if you encounter this error: https://github.com/yarnpkg/berry/issues/4942\");return r}throw new Error(`Unsupported path type: ${(0,TX.inspect)(t)}`)}}});var UX,qo,Ip,e0,sx,ox,uE,Qu,Ru,NX,OX,LX,MX,kB,_X=Ze(()=>{UX=Ie(\"readline\"),qo=Symbol(\"kBaseFs\"),Ip=Symbol(\"kFd\"),e0=Symbol(\"kClosePromise\"),sx=Symbol(\"kCloseResolve\"),ox=Symbol(\"kCloseReject\"),uE=Symbol(\"kRefs\"),Qu=Symbol(\"kRef\"),Ru=Symbol(\"kUnref\"),kB=class{constructor(t,r){this[MX]=1;this[LX]=void 0;this[OX]=void 0;this[NX]=void 0;this[qo]=r,this[Ip]=t}get fd(){return this[Ip]}async appendFile(t,r){try{this[Qu](this.appendFile);let s=(typeof r==\"string\"?r:r?.encoding)??void 0;return await this[qo].appendFilePromise(this.fd,t,s?{encoding:s}:void 0)}finally{this[Ru]()}}async chown(t,r){try{return this[Qu](this.chown),await this[qo].fchownPromise(this.fd,t,r)}finally{this[Ru]()}}async chmod(t){try{return this[Qu](this.chmod),await this[qo].fchmodPromise(this.fd,t)}finally{this[Ru]()}}createReadStream(t){return this[qo].createReadStream(null,{...t,fd:this.fd})}createWriteStream(t){return this[qo].createWriteStream(null,{...t,fd:this.fd})}datasync(){throw new Error(\"Method not implemented.\")}sync(){throw new Error(\"Method not implemented.\")}async read(t,r,s,a){try{this[Qu](this.read);let n,c;return ArrayBuffer.isView(t)?typeof r==\"object\"&&r!==null?(n=t,c=r?.offset??0,s=r?.length??n.byteLength-c,a=r?.position??null):(n=t,c=r??0,s??=0):(n=t?.buffer??Buffer.alloc(16384),c=t?.offset??0,s=t?.length??n.byteLength-c,a=t?.position??null),s===0?{bytesRead:s,buffer:n}:{bytesRead:await this[qo].readPromise(this.fd,Buffer.isBuffer(n)?n:Buffer.from(n.buffer,n.byteOffset,n.byteLength),c,s,a),buffer:n}}finally{this[Ru]()}}async readFile(t){try{this[Qu](this.readFile);let r=(typeof t==\"string\"?t:t?.encoding)??void 0;return await this[qo].readFilePromise(this.fd,r)}finally{this[Ru]()}}readLines(t){return(0,UX.createInterface)({input:this.createReadStream(t),crlfDelay:1/0})}async stat(t){try{return this[Qu](this.stat),await this[qo].fstatPromise(this.fd,t)}finally{this[Ru]()}}async truncate(t){try{return this[Qu](this.truncate),await this[qo].ftruncatePromise(this.fd,t)}finally{this[Ru]()}}utimes(t,r){throw new Error(\"Method not implemented.\")}async writeFile(t,r){try{this[Qu](this.writeFile);let s=(typeof r==\"string\"?r:r?.encoding)??void 0;await this[qo].writeFilePromise(this.fd,t,s)}finally{this[Ru]()}}async write(...t){try{if(this[Qu](this.write),ArrayBuffer.isView(t[0])){let[r,s,a,n]=t;return{bytesWritten:await this[qo].writePromise(this.fd,r,s??void 0,a??void 0,n??void 0),buffer:r}}else{let[r,s,a]=t;return{bytesWritten:await this[qo].writePromise(this.fd,r,s,a),buffer:r}}}finally{this[Ru]()}}async writev(t,r){try{this[Qu](this.writev);let s=0;if(typeof r<\"u\")for(let a of t){let n=await this.write(a,void 0,void 0,r);s+=n.bytesWritten,r+=n.bytesWritten}else for(let a of t){let n=await this.write(a);s+=n.bytesWritten}return{buffers:t,bytesWritten:s}}finally{this[Ru]()}}readv(t,r){throw new Error(\"Method not implemented.\")}close(){if(this[Ip]===-1)return Promise.resolve();if(this[e0])return this[e0];if(this[uE]--,this[uE]===0){let t=this[Ip];this[Ip]=-1,this[e0]=this[qo].closePromise(t).finally(()=>{this[e0]=void 0})}else this[e0]=new Promise((t,r)=>{this[sx]=t,this[ox]=r}).finally(()=>{this[e0]=void 0,this[ox]=void 0,this[sx]=void 0});return this[e0]}[(qo,Ip,MX=uE,LX=e0,OX=sx,NX=ox,Qu)](t){if(this[Ip]===-1){let r=new Error(\"file closed\");throw r.code=\"EBADF\",r.syscall=t.name,r}this[uE]++}[Ru](){if(this[uE]--,this[uE]===0){let t=this[Ip];this[Ip]=-1,this[qo].closePromise(t).then(this[sx],this[ox])}}}});function QB(e,t){t=new ix(t);let r=(s,a,n)=>{let c=s[a];s[a]=n,typeof c?.[fE.promisify.custom]<\"u\"&&(n[fE.promisify.custom]=c[fE.promisify.custom])};{r(e,\"exists\",(s,...a)=>{let c=typeof a[a.length-1]==\"function\"?a.pop():()=>{};process.nextTick(()=>{t.existsPromise(s).then(f=>{c(f)},()=>{c(!1)})})}),r(e,\"read\",(...s)=>{let[a,n,c,f,p,h]=s;if(s.length<=3){let E={};s.length<3?h=s[1]:(E=s[1],h=s[2]),{buffer:n=Buffer.alloc(16384),offset:c=0,length:f=n.byteLength,position:p}=E}if(c==null&&(c=0),f|=0,f===0){process.nextTick(()=>{h(null,0,n)});return}p==null&&(p=-1),process.nextTick(()=>{t.readPromise(a,n,c,f,p).then(E=>{h(null,E,n)},E=>{h(E,0,n)})})});for(let s of HX){let a=s.replace(/Promise$/,\"\");if(typeof e[a]>\"u\")continue;let n=t[s];if(typeof n>\"u\")continue;r(e,a,(...f)=>{let h=typeof f[f.length-1]==\"function\"?f.pop():()=>{};process.nextTick(()=>{n.apply(t,f).then(E=>{h(null,E)},E=>{h(E)})})})}e.realpath.native=e.realpath}{r(e,\"existsSync\",s=>{try{return t.existsSync(s)}catch{return!1}}),r(e,\"readSync\",(...s)=>{let[a,n,c,f,p]=s;return s.length<=3&&({offset:c=0,length:f=n.byteLength,position:p}=s[2]||{}),c==null&&(c=0),f|=0,f===0?0:(p==null&&(p=-1),t.readSync(a,n,c,f,p))});for(let s of Jje){let a=s;if(typeof e[a]>\"u\")continue;let n=t[s];typeof n>\"u\"||r(e,a,n.bind(t))}e.realpathSync.native=e.realpathSync}{let s=e.promises;for(let a of HX){let n=a.replace(/Promise$/,\"\");if(typeof s[n]>\"u\")continue;let c=t[a];typeof c>\"u\"||a!==\"open\"&&r(s,n,(f,...p)=>f instanceof kB?f[n].apply(f,p):c.call(t,f,...p))}r(s,\"open\",async(...a)=>{let n=await t.openPromise(...a);return new kB(n,t)})}e.read[fE.promisify.custom]=async(s,a,...n)=>({bytesRead:await t.readPromise(s,a,...n),buffer:a}),e.write[fE.promisify.custom]=async(s,a,...n)=>({bytesWritten:await t.writePromise(s,a,...n),buffer:a})}function ax(e,t){let r=Object.create(e);return QB(r,t),r}var fE,Jje,HX,jX=Ze(()=>{fE=Ie(\"util\");FX();_X();Jje=new Set([\"accessSync\",\"appendFileSync\",\"createReadStream\",\"createWriteStream\",\"chmodSync\",\"fchmodSync\",\"chownSync\",\"fchownSync\",\"closeSync\",\"copyFileSync\",\"linkSync\",\"lstatSync\",\"fstatSync\",\"lutimesSync\",\"mkdirSync\",\"openSync\",\"opendirSync\",\"readlinkSync\",\"readFileSync\",\"readdirSync\",\"readlinkSync\",\"realpathSync\",\"renameSync\",\"rmdirSync\",\"rmSync\",\"statSync\",\"symlinkSync\",\"truncateSync\",\"ftruncateSync\",\"unlinkSync\",\"unwatchFile\",\"utimesSync\",\"watch\",\"watchFile\",\"writeFileSync\",\"writeSync\"]),HX=new Set([\"accessPromise\",\"appendFilePromise\",\"fchmodPromise\",\"chmodPromise\",\"fchownPromise\",\"chownPromise\",\"closePromise\",\"copyFilePromise\",\"linkPromise\",\"fstatPromise\",\"lstatPromise\",\"lutimesPromise\",\"mkdirPromise\",\"openPromise\",\"opendirPromise\",\"readdirPromise\",\"realpathPromise\",\"readFilePromise\",\"readdirPromise\",\"readlinkPromise\",\"renamePromise\",\"rmdirPromise\",\"rmPromise\",\"statPromise\",\"symlinkPromise\",\"truncatePromise\",\"ftruncatePromise\",\"unlinkPromise\",\"utimesPromise\",\"writeFilePromise\",\"writeSync\"])});function GX(e){let t=Math.ceil(Math.random()*4294967296).toString(16).padStart(8,\"0\");return`${e}${t}`}function qX(){if(hU)return hU;let e=fe.toPortablePath(WX.default.tmpdir()),t=le.realpathSync(e);return process.once(\"exit\",()=>{le.rmtempSync()}),hU={tmpdir:e,realTmpdir:t}}var WX,Tu,hU,le,VX=Ze(()=>{WX=et(Ie(\"os\"));Ed();ol();Tu=new Set,hU=null;le=Object.assign(new Yn,{detachTemp(e){Tu.delete(e)},mktempSync(e){let{tmpdir:t,realTmpdir:r}=qX();for(;;){let s=GX(\"xfs-\");try{this.mkdirSync(K.join(t,s))}catch(n){if(n.code===\"EEXIST\")continue;throw n}let a=K.join(r,s);if(Tu.add(a),typeof e>\"u\")return a;try{return e(a)}finally{if(Tu.has(a)){Tu.delete(a);try{this.removeSync(a)}catch{}}}}},async mktempPromise(e){let{tmpdir:t,realTmpdir:r}=qX();for(;;){let s=GX(\"xfs-\");try{await this.mkdirPromise(K.join(t,s))}catch(n){if(n.code===\"EEXIST\")continue;throw n}let a=K.join(r,s);if(Tu.add(a),typeof e>\"u\")return a;try{return await e(a)}finally{if(Tu.has(a)){Tu.delete(a);try{await this.removePromise(a)}catch{}}}}},async rmtempPromise(){await Promise.all(Array.from(Tu.values()).map(async e=>{try{await le.removePromise(e,{maxRetries:0}),Tu.delete(e)}catch{}}))},rmtempSync(){for(let e of Tu)try{le.removeSync(e),Tu.delete(e)}catch{}}})});var RB={};Yt(RB,{AliasFS:()=>jf,BasePortableFakeFS:()=>Hf,CustomDir:()=>xB,CwdFS:()=>bn,FakeFS:()=>yp,Filename:()=>Er,JailFS:()=>Gf,LazyFS:()=>cE,MountFS:()=>Xh,NoFS:()=>nx,NodeFS:()=>Yn,PortablePath:()=>vt,PosixFS:()=>$h,ProxiedFS:()=>Gs,VirtualFS:()=>mo,constants:()=>Ai,errors:()=>or,extendFs:()=>ax,normalizeLineEndings:()=>md,npath:()=>fe,opendir:()=>ex,patchFs:()=>QB,ppath:()=>K,setupCopyIndex:()=>$P,statUtils:()=>sl,unwatchAllFiles:()=>dd,unwatchFile:()=>gd,watchFile:()=>lE,xfs:()=>le});var Dt=Ze(()=>{cX();zP();aU();uU();gX();fU();yd();ol();ol();CX();yd();vX();DX();bX();PX();xX();Ed();kX();Ep();QX();jX();VX()});var ZX=G((_bt,zX)=>{zX.exports=JX;JX.sync=Zje;var YX=Ie(\"fs\");function zje(e,t){var r=t.pathExt!==void 0?t.pathExt:process.env.PATHEXT;if(!r||(r=r.split(\";\"),r.indexOf(\"\")!==-1))return!0;for(var s=0;s<r.length;s++){var a=r[s].toLowerCase();if(a&&e.substr(-a.length).toLowerCase()===a)return!0}return!1}function KX(e,t,r){return!e.isSymbolicLink()&&!e.isFile()?!1:zje(t,r)}function JX(e,t,r){YX.stat(e,function(s,a){r(s,s?!1:KX(a,e,t))})}function Zje(e,t){return KX(YX.statSync(e),e,t)}});var r$=G((Hbt,t$)=>{t$.exports=$X;$X.sync=Xje;var XX=Ie(\"fs\");function $X(e,t,r){XX.stat(e,function(s,a){r(s,s?!1:e$(a,t))})}function Xje(e,t){return e$(XX.statSync(e),t)}function e$(e,t){return e.isFile()&&$je(e,t)}function $je(e,t){var r=e.mode,s=e.uid,a=e.gid,n=t.uid!==void 0?t.uid:process.getuid&&process.getuid(),c=t.gid!==void 0?t.gid:process.getgid&&process.getgid(),f=parseInt(\"100\",8),p=parseInt(\"010\",8),h=parseInt(\"001\",8),E=f|p,C=r&h||r&p&&a===c||r&f&&s===n||r&E&&n===0;return C}});var i$=G((Gbt,n$)=>{var jbt=Ie(\"fs\"),lx;process.platform===\"win32\"||global.TESTING_WINDOWS?lx=ZX():lx=r$();n$.exports=gU;gU.sync=e6e;function gU(e,t,r){if(typeof t==\"function\"&&(r=t,t={}),!r){if(typeof Promise!=\"function\")throw new TypeError(\"callback not provided\");return new Promise(function(s,a){gU(e,t||{},function(n,c){n?a(n):s(c)})})}lx(e,t||{},function(s,a){s&&(s.code===\"EACCES\"||t&&t.ignoreErrors)&&(s=null,a=!1),r(s,a)})}function e6e(e,t){try{return lx.sync(e,t||{})}catch(r){if(t&&t.ignoreErrors||r.code===\"EACCES\")return!1;throw r}}});var f$=G((qbt,u$)=>{var AE=process.platform===\"win32\"||process.env.OSTYPE===\"cygwin\"||process.env.OSTYPE===\"msys\",s$=Ie(\"path\"),t6e=AE?\";\":\":\",o$=i$(),a$=e=>Object.assign(new Error(`not found: ${e}`),{code:\"ENOENT\"}),l$=(e,t)=>{let r=t.colon||t6e,s=e.match(/\\//)||AE&&e.match(/\\\\/)?[\"\"]:[...AE?[process.cwd()]:[],...(t.path||process.env.PATH||\"\").split(r)],a=AE?t.pathExt||process.env.PATHEXT||\".EXE;.CMD;.BAT;.COM\":\"\",n=AE?a.split(r):[\"\"];return AE&&e.indexOf(\".\")!==-1&&n[0]!==\"\"&&n.unshift(\"\"),{pathEnv:s,pathExt:n,pathExtExe:a}},c$=(e,t,r)=>{typeof t==\"function\"&&(r=t,t={}),t||(t={});let{pathEnv:s,pathExt:a,pathExtExe:n}=l$(e,t),c=[],f=h=>new Promise((E,C)=>{if(h===s.length)return t.all&&c.length?E(c):C(a$(e));let S=s[h],x=/^\".*\"$/.test(S)?S.slice(1,-1):S,I=s$.join(x,e),T=!x&&/^\\.[\\\\\\/]/.test(e)?e.slice(0,2)+I:I;E(p(T,h,0))}),p=(h,E,C)=>new Promise((S,x)=>{if(C===a.length)return S(f(E+1));let I=a[C];o$(h+I,{pathExt:n},(T,O)=>{if(!T&&O)if(t.all)c.push(h+I);else return S(h+I);return S(p(h,E,C+1))})});return r?f(0).then(h=>r(null,h),r):f(0)},r6e=(e,t)=>{t=t||{};let{pathEnv:r,pathExt:s,pathExtExe:a}=l$(e,t),n=[];for(let c=0;c<r.length;c++){let f=r[c],p=/^\".*\"$/.test(f)?f.slice(1,-1):f,h=s$.join(p,e),E=!p&&/^\\.[\\\\\\/]/.test(e)?e.slice(0,2)+h:h;for(let C=0;C<s.length;C++){let S=E+s[C];try{if(o$.sync(S,{pathExt:a}))if(t.all)n.push(S);else return S}catch{}}}if(t.all&&n.length)return n;if(t.nothrow)return null;throw a$(e)};u$.exports=c$;c$.sync=r6e});var p$=G((Wbt,dU)=>{\"use strict\";var A$=(e={})=>{let t=e.env||process.env;return(e.platform||process.platform)!==\"win32\"?\"PATH\":Object.keys(t).reverse().find(s=>s.toUpperCase()===\"PATH\")||\"Path\"};dU.exports=A$;dU.exports.default=A$});var m$=G((Vbt,d$)=>{\"use strict\";var h$=Ie(\"path\"),n6e=f$(),i6e=p$();function g$(e,t){let r=e.options.env||process.env,s=process.cwd(),a=e.options.cwd!=null,n=a&&process.chdir!==void 0&&!process.chdir.disabled;if(n)try{process.chdir(e.options.cwd)}catch{}let c;try{c=n6e.sync(e.command,{path:r[i6e({env:r})],pathExt:t?h$.delimiter:void 0})}catch{}finally{n&&process.chdir(s)}return c&&(c=h$.resolve(a?e.options.cwd:\"\",c)),c}function s6e(e){return g$(e)||g$(e,!0)}d$.exports=s6e});var y$=G((Ybt,yU)=>{\"use strict\";var mU=/([()\\][%!^\"`<>&|;, *?])/g;function o6e(e){return e=e.replace(mU,\"^$1\"),e}function a6e(e,t){return e=`${e}`,e=e.replace(/(?=(\\\\+?)?)\\1\"/g,'$1$1\\\\\"'),e=e.replace(/(?=(\\\\+?)?)\\1$/,\"$1$1\"),e=`\"${e}\"`,e=e.replace(mU,\"^$1\"),t&&(e=e.replace(mU,\"^$1\")),e}yU.exports.command=o6e;yU.exports.argument=a6e});var I$=G((Kbt,E$)=>{\"use strict\";E$.exports=/^#!(.*)/});var w$=G((Jbt,C$)=>{\"use strict\";var l6e=I$();C$.exports=(e=\"\")=>{let t=e.match(l6e);if(!t)return null;let[r,s]=t[0].replace(/#! ?/,\"\").split(\" \"),a=r.split(\"/\").pop();return a===\"env\"?s:s?`${a} ${s}`:a}});var v$=G((zbt,B$)=>{\"use strict\";var EU=Ie(\"fs\"),c6e=w$();function u6e(e){let r=Buffer.alloc(150),s;try{s=EU.openSync(e,\"r\"),EU.readSync(s,r,0,150,0),EU.closeSync(s)}catch{}return c6e(r.toString())}B$.exports=u6e});var P$=G((Zbt,b$)=>{\"use strict\";var f6e=Ie(\"path\"),S$=m$(),D$=y$(),A6e=v$(),p6e=process.platform===\"win32\",h6e=/\\.(?:com|exe)$/i,g6e=/node_modules[\\\\/].bin[\\\\/][^\\\\/]+\\.cmd$/i;function d6e(e){e.file=S$(e);let t=e.file&&A6e(e.file);return t?(e.args.unshift(e.file),e.command=t,S$(e)):e.file}function m6e(e){if(!p6e)return e;let t=d6e(e),r=!h6e.test(t);if(e.options.forceShell||r){let s=g6e.test(t);e.command=f6e.normalize(e.command),e.command=D$.command(e.command),e.args=e.args.map(n=>D$.argument(n,s));let a=[e.command].concat(e.args).join(\" \");e.args=[\"/d\",\"/s\",\"/c\",`\"${a}\"`],e.command=process.env.comspec||\"cmd.exe\",e.options.windowsVerbatimArguments=!0}return e}function y6e(e,t,r){t&&!Array.isArray(t)&&(r=t,t=null),t=t?t.slice(0):[],r=Object.assign({},r);let s={command:e,args:t,options:r,file:void 0,original:{command:e,args:t}};return r.shell?s:m6e(s)}b$.exports=y6e});var Q$=G((Xbt,k$)=>{\"use strict\";var IU=process.platform===\"win32\";function CU(e,t){return Object.assign(new Error(`${t} ${e.command} ENOENT`),{code:\"ENOENT\",errno:\"ENOENT\",syscall:`${t} ${e.command}`,path:e.command,spawnargs:e.args})}function E6e(e,t){if(!IU)return;let r=e.emit;e.emit=function(s,a){if(s===\"exit\"){let n=x$(a,t);if(n)return r.call(e,\"error\",n)}return r.apply(e,arguments)}}function x$(e,t){return IU&&e===1&&!t.file?CU(t.original,\"spawn\"):null}function I6e(e,t){return IU&&e===1&&!t.file?CU(t.original,\"spawnSync\"):null}k$.exports={hookChildProcess:E6e,verifyENOENT:x$,verifyENOENTSync:I6e,notFoundError:CU}});var vU=G(($bt,pE)=>{\"use strict\";var R$=Ie(\"child_process\"),wU=P$(),BU=Q$();function T$(e,t,r){let s=wU(e,t,r),a=R$.spawn(s.command,s.args,s.options);return BU.hookChildProcess(a,s),a}function C6e(e,t,r){let s=wU(e,t,r),a=R$.spawnSync(s.command,s.args,s.options);return a.error=a.error||BU.verifyENOENTSync(a.status,s),a}pE.exports=T$;pE.exports.spawn=T$;pE.exports.sync=C6e;pE.exports._parse=wU;pE.exports._enoent=BU});var N$=G((ePt,F$)=>{\"use strict\";function w6e(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}function Cd(e,t,r,s){this.message=e,this.expected=t,this.found=r,this.location=s,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,Cd)}w6e(Cd,Error);Cd.buildMessage=function(e,t){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",C;for(C=0;C<h.parts.length;C++)E+=h.parts[C]instanceof Array?n(h.parts[C][0])+\"-\"+n(h.parts[C][1]):n(h.parts[C]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function s(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function c(h){return r[h.type](h)}function f(h){var E=new Array(h.length),C,S;for(C=0;C<h.length;C++)E[C]=c(h[C]);if(E.sort(),E.length>0){for(C=1,S=1;C<E.length;C++)E[C-1]!==E[C]&&(E[S]=E[C],S++);E.length=S}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+f(e)+\" but \"+p(t)+\" found.\"};function B6e(e,t){t=t!==void 0?t:{};var r={},s={Start:Za},a=Za,n=function(N){return N||[]},c=function(N,J,re){return[{command:N,type:J}].concat(re||[])},f=function(N,J){return[{command:N,type:J||\";\"}]},p=function(N){return N},h=\";\",E=ur(\";\",!1),C=\"&\",S=ur(\"&\",!1),x=function(N,J){return J?{chain:N,then:J}:{chain:N}},I=function(N,J){return{type:N,line:J}},T=\"&&\",O=ur(\"&&\",!1),U=\"||\",Y=ur(\"||\",!1),te=function(N,J){return J?{...N,then:J}:N},ie=function(N,J){return{type:N,chain:J}},ue=\"|&\",ae=ur(\"|&\",!1),de=\"|\",Ae=ur(\"|\",!1),Ce=\"=\",Ee=ur(\"=\",!1),g=function(N,J){return{name:N,args:[J]}},Se=function(N){return{name:N,args:[]}},Be=\"(\",me=ur(\"(\",!1),ce=\")\",X=ur(\")\",!1),De=function(N,J){return{type:\"subshell\",subshell:N,args:J}},Qe=\"{\",it=ur(\"{\",!1),_=\"}\",tt=ur(\"}\",!1),Ne=function(N,J){return{type:\"group\",group:N,args:J}},ke=function(N,J){return{type:\"command\",args:J,envs:N}},be=function(N){return{type:\"envs\",envs:N}},je=function(N){return N},Re=function(N){return N},ct=/^[0-9]/,Me=zi([[\"0\",\"9\"]],!1,!1),P=function(N,J,re){return{type:\"redirection\",subtype:J,fd:N!==null?parseInt(N):null,args:[re]}},w=\">>\",b=ur(\">>\",!1),y=\">&\",F=ur(\">&\",!1),z=\">\",Z=ur(\">\",!1),$=\"<<<\",se=ur(\"<<<\",!1),xe=\"<&\",Fe=ur(\"<&\",!1),ut=\"<\",Ct=ur(\"<\",!1),qt=function(N){return{type:\"argument\",segments:[].concat(...N)}},ir=function(N){return N},Pt=\"$'\",dn=ur(\"$'\",!1),Pr=\"'\",Ir=ur(\"'\",!1),Or=function(N){return[{type:\"text\",text:N}]},on='\"\"',li=ur('\"\"',!1),So=function(){return{type:\"text\",text:\"\"}},ns='\"',so=ur('\"',!1),Do=function(N){return N},ji=function(N){return{type:\"arithmetic\",arithmetic:N,quoted:!0}},oo=function(N){return{type:\"shell\",shell:N,quoted:!0}},bo=function(N){return{type:\"variable\",...N,quoted:!0}},RA=function(N){return{type:\"text\",text:N}},hf=function(N){return{type:\"arithmetic\",arithmetic:N,quoted:!1}},hh=function(N){return{type:\"shell\",shell:N,quoted:!1}},gh=function(N){return{type:\"variable\",...N,quoted:!1}},ao=function(N){return{type:\"glob\",pattern:N}},Gn=/^[^']/,Ns=zi([\"'\"],!0,!1),lo=function(N){return N.join(\"\")},iu=/^[^$\"]/,su=zi([\"$\",'\"'],!0,!1),ou=`\\\\\n`,TA=ur(`\\\\\n`,!1),FA=function(){return\"\"},ua=\"\\\\\",fa=ur(\"\\\\\",!1),NA=/^[\\\\$\"`]/,gr=zi([\"\\\\\",\"$\",'\"',\"`\"],!1,!1),Po=function(N){return N},Ue=\"\\\\a\",au=ur(\"\\\\a\",!1),Cr=function(){return\"a\"},gf=\"\\\\b\",OA=ur(\"\\\\b\",!1),LA=function(){return\"\\b\"},lu=/^[Ee]/,cu=zi([\"E\",\"e\"],!1,!1),ac=function(){return\"\\x1B\"},we=\"\\\\f\",Nt=ur(\"\\\\f\",!1),lc=function(){return\"\\f\"},Oi=\"\\\\n\",co=ur(\"\\\\n\",!1),Tt=function(){return`\n`},Qn=\"\\\\r\",Aa=ur(\"\\\\r\",!1),Gi=function(){return\"\\r\"},Li=\"\\\\t\",ja=ur(\"\\\\t\",!1),mn=function(){return\"\t\"},Zn=\"\\\\v\",uu=ur(\"\\\\v\",!1),dh=function(){return\"\\v\"},Ga=/^[\\\\'\"?]/,qa=zi([\"\\\\\",\"'\",'\"',\"?\"],!1,!1),Wa=function(N){return String.fromCharCode(parseInt(N,16))},$e=\"\\\\x\",Va=ur(\"\\\\x\",!1),df=\"\\\\u\",cc=ur(\"\\\\u\",!1),vn=\"\\\\U\",pa=ur(\"\\\\U\",!1),MA=function(N){return String.fromCodePoint(parseInt(N,16))},UA=/^[0-7]/,ha=zi([[\"0\",\"7\"]],!1,!1),xl=/^[0-9a-fA-f]/,Mt=zi([[\"0\",\"9\"],[\"a\",\"f\"],[\"A\",\"f\"]],!1,!1),Rn=If(),ga=\"{}\",Ya=ur(\"{}\",!1),is=function(){return\"{}\"},uc=\"-\",fu=ur(\"-\",!1),fc=\"+\",Ka=ur(\"+\",!1),Mi=\".\",Bs=ur(\".\",!1),kl=function(N,J,re){return{type:\"number\",value:(N===\"-\"?-1:1)*parseFloat(J.join(\"\")+\".\"+re.join(\"\"))}},mf=function(N,J){return{type:\"number\",value:(N===\"-\"?-1:1)*parseInt(J.join(\"\"))}},Ac=function(N){return{type:\"variable\",...N}},Bi=function(N){return{type:\"variable\",name:N}},Tn=function(N){return N},pc=\"*\",Je=ur(\"*\",!1),ot=\"/\",St=ur(\"/\",!1),lr=function(N,J,re){return{type:J===\"*\"?\"multiplication\":\"division\",right:re}},ee=function(N,J){return J.reduce((re,ge)=>({left:re,...ge}),N)},ye=function(N,J,re){return{type:J===\"+\"?\"addition\":\"subtraction\",right:re}},Oe=\"$((\",mt=ur(\"$((\",!1),Et=\"))\",bt=ur(\"))\",!1),tr=function(N){return N},pn=\"$(\",ci=ur(\"$(\",!1),qi=function(N){return N},Fn=\"${\",Ja=ur(\"${\",!1),Iy=\":-\",q1=ur(\":-\",!1),xo=function(N,J){return{name:N,defaultValue:J}},Cy=\":-}\",mh=ur(\":-}\",!1),W1=function(N){return{name:N,defaultValue:[]}},ko=\":+\",yh=ur(\":+\",!1),Eh=function(N,J){return{name:N,alternativeValue:J}},Au=\":+}\",Ih=ur(\":+}\",!1),Rg=function(N){return{name:N,alternativeValue:[]}},Tg=function(N){return{name:N}},Fg=\"$\",wy=ur(\"$\",!1),yf=function(N){return t.isGlobPattern(N)},Qo=function(N){return N},Ql=/^[a-zA-Z0-9_]/,Ch=zi([[\"a\",\"z\"],[\"A\",\"Z\"],[\"0\",\"9\"],\"_\"],!1,!1),Ng=function(){return Dy()},Rl=/^[$@*?#a-zA-Z0-9_\\-]/,Tl=zi([\"$\",\"@\",\"*\",\"?\",\"#\",[\"a\",\"z\"],[\"A\",\"Z\"],[\"0\",\"9\"],\"_\",\"-\"],!1,!1),By=/^[()}<>$|&; \\t\"']/,_A=zi([\"(\",\")\",\"}\",\"<\",\">\",\"$\",\"|\",\"&\",\";\",\" \",\"\t\",'\"',\"'\"],!1,!1),vy=/^[<>&; \\t\"']/,Sy=zi([\"<\",\">\",\"&\",\";\",\" \",\"\t\",'\"',\"'\"],!1,!1),HA=/^[ \\t]/,jA=zi([\" \",\"\t\"],!1,!1),W=0,xt=0,GA=[{line:1,column:1}],Ro=0,Ef=[],yt=0,pu;if(\"startRule\"in t){if(!(t.startRule in s))throw new Error(`Can't start parsing from rule \"`+t.startRule+'\".');a=s[t.startRule]}function Dy(){return e.substring(xt,W)}function Og(){return Cf(xt,W)}function V1(N,J){throw J=J!==void 0?J:Cf(xt,W),qA([Lg(N)],e.substring(xt,W),J)}function wh(N,J){throw J=J!==void 0?J:Cf(xt,W),mi(N,J)}function ur(N,J){return{type:\"literal\",text:N,ignoreCase:J}}function zi(N,J,re){return{type:\"class\",parts:N,inverted:J,ignoreCase:re}}function If(){return{type:\"any\"}}function za(){return{type:\"end\"}}function Lg(N){return{type:\"other\",description:N}}function hu(N){var J=GA[N],re;if(J)return J;for(re=N-1;!GA[re];)re--;for(J=GA[re],J={line:J.line,column:J.column};re<N;)e.charCodeAt(re)===10?(J.line++,J.column=1):J.column++,re++;return GA[N]=J,J}function Cf(N,J){var re=hu(N),ge=hu(J);return{start:{offset:N,line:re.line,column:re.column},end:{offset:J,line:ge.line,column:ge.column}}}function wt(N){W<Ro||(W>Ro&&(Ro=W,Ef=[]),Ef.push(N))}function mi(N,J){return new Cd(N,null,null,J)}function qA(N,J,re){return new Cd(Cd.buildMessage(N,J),N,J,re)}function Za(){var N,J,re;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();return J!==r?(re=da(),re===r&&(re=null),re!==r?(xt=N,J=n(re),N=J):(W=N,N=r)):(W=N,N=r),N}function da(){var N,J,re,ge,Ke;if(N=W,J=Bh(),J!==r){for(re=[],ge=kt();ge!==r;)re.push(ge),ge=kt();re!==r?(ge=Mg(),ge!==r?(Ke=Xa(),Ke===r&&(Ke=null),Ke!==r?(xt=N,J=c(J,ge,Ke),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r)}else W=N,N=r;if(N===r)if(N=W,J=Bh(),J!==r){for(re=[],ge=kt();ge!==r;)re.push(ge),ge=kt();re!==r?(ge=Mg(),ge===r&&(ge=null),ge!==r?(xt=N,J=f(J,ge),N=J):(W=N,N=r)):(W=N,N=r)}else W=N,N=r;return N}function Xa(){var N,J,re,ge,Ke;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r)if(re=da(),re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();ge!==r?(xt=N,J=p(re),N=J):(W=N,N=r)}else W=N,N=r;else W=N,N=r;return N}function Mg(){var N;return e.charCodeAt(W)===59?(N=h,W++):(N=r,yt===0&&wt(E)),N===r&&(e.charCodeAt(W)===38?(N=C,W++):(N=r,yt===0&&wt(S))),N}function Bh(){var N,J,re;return N=W,J=WA(),J!==r?(re=Ug(),re===r&&(re=null),re!==r?(xt=N,J=x(J,re),N=J):(W=N,N=r)):(W=N,N=r),N}function Ug(){var N,J,re,ge,Ke,pt,dr;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r)if(re=by(),re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();if(ge!==r)if(Ke=Bh(),Ke!==r){for(pt=[],dr=kt();dr!==r;)pt.push(dr),dr=kt();pt!==r?(xt=N,J=I(re,Ke),N=J):(W=N,N=r)}else W=N,N=r;else W=N,N=r}else W=N,N=r;else W=N,N=r;return N}function by(){var N;return e.substr(W,2)===T?(N=T,W+=2):(N=r,yt===0&&wt(O)),N===r&&(e.substr(W,2)===U?(N=U,W+=2):(N=r,yt===0&&wt(Y))),N}function WA(){var N,J,re;return N=W,J=wf(),J!==r?(re=_g(),re===r&&(re=null),re!==r?(xt=N,J=te(J,re),N=J):(W=N,N=r)):(W=N,N=r),N}function _g(){var N,J,re,ge,Ke,pt,dr;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r)if(re=gu(),re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();if(ge!==r)if(Ke=WA(),Ke!==r){for(pt=[],dr=kt();dr!==r;)pt.push(dr),dr=kt();pt!==r?(xt=N,J=ie(re,Ke),N=J):(W=N,N=r)}else W=N,N=r;else W=N,N=r}else W=N,N=r;else W=N,N=r;return N}function gu(){var N;return e.substr(W,2)===ue?(N=ue,W+=2):(N=r,yt===0&&wt(ae)),N===r&&(e.charCodeAt(W)===124?(N=de,W++):(N=r,yt===0&&wt(Ae))),N}function du(){var N,J,re,ge,Ke,pt;if(N=W,J=Dh(),J!==r)if(e.charCodeAt(W)===61?(re=Ce,W++):(re=r,yt===0&&wt(Ee)),re!==r)if(ge=VA(),ge!==r){for(Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();Ke!==r?(xt=N,J=g(J,ge),N=J):(W=N,N=r)}else W=N,N=r;else W=N,N=r;else W=N,N=r;if(N===r)if(N=W,J=Dh(),J!==r)if(e.charCodeAt(W)===61?(re=Ce,W++):(re=r,yt===0&&wt(Ee)),re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();ge!==r?(xt=N,J=Se(J),N=J):(W=N,N=r)}else W=N,N=r;else W=N,N=r;return N}function wf(){var N,J,re,ge,Ke,pt,dr,vr,_n,yi,vs;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r)if(e.charCodeAt(W)===40?(re=Be,W++):(re=r,yt===0&&wt(me)),re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();if(ge!==r)if(Ke=da(),Ke!==r){for(pt=[],dr=kt();dr!==r;)pt.push(dr),dr=kt();if(pt!==r)if(e.charCodeAt(W)===41?(dr=ce,W++):(dr=r,yt===0&&wt(X)),dr!==r){for(vr=[],_n=kt();_n!==r;)vr.push(_n),_n=kt();if(vr!==r){for(_n=[],yi=qn();yi!==r;)_n.push(yi),yi=qn();if(_n!==r){for(yi=[],vs=kt();vs!==r;)yi.push(vs),vs=kt();yi!==r?(xt=N,J=De(Ke,_n),N=J):(W=N,N=r)}else W=N,N=r}else W=N,N=r}else W=N,N=r;else W=N,N=r}else W=N,N=r;else W=N,N=r}else W=N,N=r;else W=N,N=r;if(N===r){for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r)if(e.charCodeAt(W)===123?(re=Qe,W++):(re=r,yt===0&&wt(it)),re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();if(ge!==r)if(Ke=da(),Ke!==r){for(pt=[],dr=kt();dr!==r;)pt.push(dr),dr=kt();if(pt!==r)if(e.charCodeAt(W)===125?(dr=_,W++):(dr=r,yt===0&&wt(tt)),dr!==r){for(vr=[],_n=kt();_n!==r;)vr.push(_n),_n=kt();if(vr!==r){for(_n=[],yi=qn();yi!==r;)_n.push(yi),yi=qn();if(_n!==r){for(yi=[],vs=kt();vs!==r;)yi.push(vs),vs=kt();yi!==r?(xt=N,J=Ne(Ke,_n),N=J):(W=N,N=r)}else W=N,N=r}else W=N,N=r}else W=N,N=r;else W=N,N=r}else W=N,N=r;else W=N,N=r}else W=N,N=r;else W=N,N=r;if(N===r){for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r){for(re=[],ge=du();ge!==r;)re.push(ge),ge=du();if(re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();if(ge!==r){if(Ke=[],pt=mu(),pt!==r)for(;pt!==r;)Ke.push(pt),pt=mu();else Ke=r;if(Ke!==r){for(pt=[],dr=kt();dr!==r;)pt.push(dr),dr=kt();pt!==r?(xt=N,J=ke(re,Ke),N=J):(W=N,N=r)}else W=N,N=r}else W=N,N=r}else W=N,N=r}else W=N,N=r;if(N===r){for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r){if(re=[],ge=du(),ge!==r)for(;ge!==r;)re.push(ge),ge=du();else re=r;if(re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();ge!==r?(xt=N,J=be(re),N=J):(W=N,N=r)}else W=N,N=r}else W=N,N=r}}}return N}function Os(){var N,J,re,ge,Ke;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r){if(re=[],ge=Pi(),ge!==r)for(;ge!==r;)re.push(ge),ge=Pi();else re=r;if(re!==r){for(ge=[],Ke=kt();Ke!==r;)ge.push(Ke),Ke=kt();ge!==r?(xt=N,J=je(re),N=J):(W=N,N=r)}else W=N,N=r}else W=N,N=r;return N}function mu(){var N,J,re;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();if(J!==r?(re=qn(),re!==r?(xt=N,J=Re(re),N=J):(W=N,N=r)):(W=N,N=r),N===r){for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();J!==r?(re=Pi(),re!==r?(xt=N,J=Re(re),N=J):(W=N,N=r)):(W=N,N=r)}return N}function qn(){var N,J,re,ge,Ke;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();return J!==r?(ct.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Me)),re===r&&(re=null),re!==r?(ge=ss(),ge!==r?(Ke=Pi(),Ke!==r?(xt=N,J=P(re,ge,Ke),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N}function ss(){var N;return e.substr(W,2)===w?(N=w,W+=2):(N=r,yt===0&&wt(b)),N===r&&(e.substr(W,2)===y?(N=y,W+=2):(N=r,yt===0&&wt(F)),N===r&&(e.charCodeAt(W)===62?(N=z,W++):(N=r,yt===0&&wt(Z)),N===r&&(e.substr(W,3)===$?(N=$,W+=3):(N=r,yt===0&&wt(se)),N===r&&(e.substr(W,2)===xe?(N=xe,W+=2):(N=r,yt===0&&wt(Fe)),N===r&&(e.charCodeAt(W)===60?(N=ut,W++):(N=r,yt===0&&wt(Ct))))))),N}function Pi(){var N,J,re;for(N=W,J=[],re=kt();re!==r;)J.push(re),re=kt();return J!==r?(re=VA(),re!==r?(xt=N,J=Re(re),N=J):(W=N,N=r)):(W=N,N=r),N}function VA(){var N,J,re;if(N=W,J=[],re=Bf(),re!==r)for(;re!==r;)J.push(re),re=Bf();else J=r;return J!==r&&(xt=N,J=qt(J)),N=J,N}function Bf(){var N,J;return N=W,J=yn(),J!==r&&(xt=N,J=ir(J)),N=J,N===r&&(N=W,J=Hg(),J!==r&&(xt=N,J=ir(J)),N=J,N===r&&(N=W,J=jg(),J!==r&&(xt=N,J=ir(J)),N=J,N===r&&(N=W,J=os(),J!==r&&(xt=N,J=ir(J)),N=J))),N}function yn(){var N,J,re,ge;return N=W,e.substr(W,2)===Pt?(J=Pt,W+=2):(J=r,yt===0&&wt(dn)),J!==r?(re=En(),re!==r?(e.charCodeAt(W)===39?(ge=Pr,W++):(ge=r,yt===0&&wt(Ir)),ge!==r?(xt=N,J=Or(re),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N}function Hg(){var N,J,re,ge;return N=W,e.charCodeAt(W)===39?(J=Pr,W++):(J=r,yt===0&&wt(Ir)),J!==r?(re=vf(),re!==r?(e.charCodeAt(W)===39?(ge=Pr,W++):(ge=r,yt===0&&wt(Ir)),ge!==r?(xt=N,J=Or(re),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N}function jg(){var N,J,re,ge;if(N=W,e.substr(W,2)===on?(J=on,W+=2):(J=r,yt===0&&wt(li)),J!==r&&(xt=N,J=So()),N=J,N===r)if(N=W,e.charCodeAt(W)===34?(J=ns,W++):(J=r,yt===0&&wt(so)),J!==r){for(re=[],ge=Fl();ge!==r;)re.push(ge),ge=Fl();re!==r?(e.charCodeAt(W)===34?(ge=ns,W++):(ge=r,yt===0&&wt(so)),ge!==r?(xt=N,J=Do(re),N=J):(W=N,N=r)):(W=N,N=r)}else W=N,N=r;return N}function os(){var N,J,re;if(N=W,J=[],re=To(),re!==r)for(;re!==r;)J.push(re),re=To();else J=r;return J!==r&&(xt=N,J=Do(J)),N=J,N}function Fl(){var N,J;return N=W,J=Xr(),J!==r&&(xt=N,J=ji(J)),N=J,N===r&&(N=W,J=Sh(),J!==r&&(xt=N,J=oo(J)),N=J,N===r&&(N=W,J=KA(),J!==r&&(xt=N,J=bo(J)),N=J,N===r&&(N=W,J=Sf(),J!==r&&(xt=N,J=RA(J)),N=J))),N}function To(){var N,J;return N=W,J=Xr(),J!==r&&(xt=N,J=hf(J)),N=J,N===r&&(N=W,J=Sh(),J!==r&&(xt=N,J=hh(J)),N=J,N===r&&(N=W,J=KA(),J!==r&&(xt=N,J=gh(J)),N=J,N===r&&(N=W,J=Py(),J!==r&&(xt=N,J=ao(J)),N=J,N===r&&(N=W,J=vh(),J!==r&&(xt=N,J=RA(J)),N=J)))),N}function vf(){var N,J,re;for(N=W,J=[],Gn.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Ns));re!==r;)J.push(re),Gn.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Ns));return J!==r&&(xt=N,J=lo(J)),N=J,N}function Sf(){var N,J,re;if(N=W,J=[],re=Nl(),re===r&&(iu.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(su))),re!==r)for(;re!==r;)J.push(re),re=Nl(),re===r&&(iu.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(su)));else J=r;return J!==r&&(xt=N,J=lo(J)),N=J,N}function Nl(){var N,J,re;return N=W,e.substr(W,2)===ou?(J=ou,W+=2):(J=r,yt===0&&wt(TA)),J!==r&&(xt=N,J=FA()),N=J,N===r&&(N=W,e.charCodeAt(W)===92?(J=ua,W++):(J=r,yt===0&&wt(fa)),J!==r?(NA.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(gr)),re!==r?(xt=N,J=Po(re),N=J):(W=N,N=r)):(W=N,N=r)),N}function En(){var N,J,re;for(N=W,J=[],re=Fo(),re===r&&(Gn.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Ns)));re!==r;)J.push(re),re=Fo(),re===r&&(Gn.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Ns)));return J!==r&&(xt=N,J=lo(J)),N=J,N}function Fo(){var N,J,re;return N=W,e.substr(W,2)===Ue?(J=Ue,W+=2):(J=r,yt===0&&wt(au)),J!==r&&(xt=N,J=Cr()),N=J,N===r&&(N=W,e.substr(W,2)===gf?(J=gf,W+=2):(J=r,yt===0&&wt(OA)),J!==r&&(xt=N,J=LA()),N=J,N===r&&(N=W,e.charCodeAt(W)===92?(J=ua,W++):(J=r,yt===0&&wt(fa)),J!==r?(lu.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(cu)),re!==r?(xt=N,J=ac(),N=J):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===we?(J=we,W+=2):(J=r,yt===0&&wt(Nt)),J!==r&&(xt=N,J=lc()),N=J,N===r&&(N=W,e.substr(W,2)===Oi?(J=Oi,W+=2):(J=r,yt===0&&wt(co)),J!==r&&(xt=N,J=Tt()),N=J,N===r&&(N=W,e.substr(W,2)===Qn?(J=Qn,W+=2):(J=r,yt===0&&wt(Aa)),J!==r&&(xt=N,J=Gi()),N=J,N===r&&(N=W,e.substr(W,2)===Li?(J=Li,W+=2):(J=r,yt===0&&wt(ja)),J!==r&&(xt=N,J=mn()),N=J,N===r&&(N=W,e.substr(W,2)===Zn?(J=Zn,W+=2):(J=r,yt===0&&wt(uu)),J!==r&&(xt=N,J=dh()),N=J,N===r&&(N=W,e.charCodeAt(W)===92?(J=ua,W++):(J=r,yt===0&&wt(fa)),J!==r?(Ga.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(qa)),re!==r?(xt=N,J=Po(re),N=J):(W=N,N=r)):(W=N,N=r),N===r&&(N=yu()))))))))),N}function yu(){var N,J,re,ge,Ke,pt,dr,vr,_n,yi,vs,JA;return N=W,e.charCodeAt(W)===92?(J=ua,W++):(J=r,yt===0&&wt(fa)),J!==r?(re=ma(),re!==r?(xt=N,J=Wa(re),N=J):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===$e?(J=$e,W+=2):(J=r,yt===0&&wt(Va)),J!==r?(re=W,ge=W,Ke=ma(),Ke!==r?(pt=Ls(),pt!==r?(Ke=[Ke,pt],ge=Ke):(W=ge,ge=r)):(W=ge,ge=r),ge===r&&(ge=ma()),ge!==r?re=e.substring(re,W):re=ge,re!==r?(xt=N,J=Wa(re),N=J):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===df?(J=df,W+=2):(J=r,yt===0&&wt(cc)),J!==r?(re=W,ge=W,Ke=Ls(),Ke!==r?(pt=Ls(),pt!==r?(dr=Ls(),dr!==r?(vr=Ls(),vr!==r?(Ke=[Ke,pt,dr,vr],ge=Ke):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r),ge!==r?re=e.substring(re,W):re=ge,re!==r?(xt=N,J=Wa(re),N=J):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===vn?(J=vn,W+=2):(J=r,yt===0&&wt(pa)),J!==r?(re=W,ge=W,Ke=Ls(),Ke!==r?(pt=Ls(),pt!==r?(dr=Ls(),dr!==r?(vr=Ls(),vr!==r?(_n=Ls(),_n!==r?(yi=Ls(),yi!==r?(vs=Ls(),vs!==r?(JA=Ls(),JA!==r?(Ke=[Ke,pt,dr,vr,_n,yi,vs,JA],ge=Ke):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r),ge!==r?re=e.substring(re,W):re=ge,re!==r?(xt=N,J=MA(re),N=J):(W=N,N=r)):(W=N,N=r)))),N}function ma(){var N;return UA.test(e.charAt(W))?(N=e.charAt(W),W++):(N=r,yt===0&&wt(ha)),N}function Ls(){var N;return xl.test(e.charAt(W))?(N=e.charAt(W),W++):(N=r,yt===0&&wt(Mt)),N}function vh(){var N,J,re,ge,Ke;if(N=W,J=[],re=W,e.charCodeAt(W)===92?(ge=ua,W++):(ge=r,yt===0&&wt(fa)),ge!==r?(e.length>W?(Ke=e.charAt(W),W++):(Ke=r,yt===0&&wt(Rn)),Ke!==r?(xt=re,ge=Po(Ke),re=ge):(W=re,re=r)):(W=re,re=r),re===r&&(re=W,e.substr(W,2)===ga?(ge=ga,W+=2):(ge=r,yt===0&&wt(Ya)),ge!==r&&(xt=re,ge=is()),re=ge,re===r&&(re=W,ge=W,yt++,Ke=xy(),yt--,Ke===r?ge=void 0:(W=ge,ge=r),ge!==r?(e.length>W?(Ke=e.charAt(W),W++):(Ke=r,yt===0&&wt(Rn)),Ke!==r?(xt=re,ge=Po(Ke),re=ge):(W=re,re=r)):(W=re,re=r))),re!==r)for(;re!==r;)J.push(re),re=W,e.charCodeAt(W)===92?(ge=ua,W++):(ge=r,yt===0&&wt(fa)),ge!==r?(e.length>W?(Ke=e.charAt(W),W++):(Ke=r,yt===0&&wt(Rn)),Ke!==r?(xt=re,ge=Po(Ke),re=ge):(W=re,re=r)):(W=re,re=r),re===r&&(re=W,e.substr(W,2)===ga?(ge=ga,W+=2):(ge=r,yt===0&&wt(Ya)),ge!==r&&(xt=re,ge=is()),re=ge,re===r&&(re=W,ge=W,yt++,Ke=xy(),yt--,Ke===r?ge=void 0:(W=ge,ge=r),ge!==r?(e.length>W?(Ke=e.charAt(W),W++):(Ke=r,yt===0&&wt(Rn)),Ke!==r?(xt=re,ge=Po(Ke),re=ge):(W=re,re=r)):(W=re,re=r)));else J=r;return J!==r&&(xt=N,J=lo(J)),N=J,N}function YA(){var N,J,re,ge,Ke,pt;if(N=W,e.charCodeAt(W)===45?(J=uc,W++):(J=r,yt===0&&wt(fu)),J===r&&(e.charCodeAt(W)===43?(J=fc,W++):(J=r,yt===0&&wt(Ka))),J===r&&(J=null),J!==r){if(re=[],ct.test(e.charAt(W))?(ge=e.charAt(W),W++):(ge=r,yt===0&&wt(Me)),ge!==r)for(;ge!==r;)re.push(ge),ct.test(e.charAt(W))?(ge=e.charAt(W),W++):(ge=r,yt===0&&wt(Me));else re=r;if(re!==r)if(e.charCodeAt(W)===46?(ge=Mi,W++):(ge=r,yt===0&&wt(Bs)),ge!==r){if(Ke=[],ct.test(e.charAt(W))?(pt=e.charAt(W),W++):(pt=r,yt===0&&wt(Me)),pt!==r)for(;pt!==r;)Ke.push(pt),ct.test(e.charAt(W))?(pt=e.charAt(W),W++):(pt=r,yt===0&&wt(Me));else Ke=r;Ke!==r?(xt=N,J=kl(J,re,Ke),N=J):(W=N,N=r)}else W=N,N=r;else W=N,N=r}else W=N,N=r;if(N===r){if(N=W,e.charCodeAt(W)===45?(J=uc,W++):(J=r,yt===0&&wt(fu)),J===r&&(e.charCodeAt(W)===43?(J=fc,W++):(J=r,yt===0&&wt(Ka))),J===r&&(J=null),J!==r){if(re=[],ct.test(e.charAt(W))?(ge=e.charAt(W),W++):(ge=r,yt===0&&wt(Me)),ge!==r)for(;ge!==r;)re.push(ge),ct.test(e.charAt(W))?(ge=e.charAt(W),W++):(ge=r,yt===0&&wt(Me));else re=r;re!==r?(xt=N,J=mf(J,re),N=J):(W=N,N=r)}else W=N,N=r;if(N===r&&(N=W,J=KA(),J!==r&&(xt=N,J=Ac(J)),N=J,N===r&&(N=W,J=hc(),J!==r&&(xt=N,J=Bi(J)),N=J,N===r)))if(N=W,e.charCodeAt(W)===40?(J=Be,W++):(J=r,yt===0&&wt(me)),J!==r){for(re=[],ge=kt();ge!==r;)re.push(ge),ge=kt();if(re!==r)if(ge=uo(),ge!==r){for(Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();Ke!==r?(e.charCodeAt(W)===41?(pt=ce,W++):(pt=r,yt===0&&wt(X)),pt!==r?(xt=N,J=Tn(ge),N=J):(W=N,N=r)):(W=N,N=r)}else W=N,N=r;else W=N,N=r}else W=N,N=r}return N}function Df(){var N,J,re,ge,Ke,pt,dr,vr;if(N=W,J=YA(),J!==r){for(re=[],ge=W,Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();if(Ke!==r)if(e.charCodeAt(W)===42?(pt=pc,W++):(pt=r,yt===0&&wt(Je)),pt===r&&(e.charCodeAt(W)===47?(pt=ot,W++):(pt=r,yt===0&&wt(St))),pt!==r){for(dr=[],vr=kt();vr!==r;)dr.push(vr),vr=kt();dr!==r?(vr=YA(),vr!==r?(xt=ge,Ke=lr(J,pt,vr),ge=Ke):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r;for(;ge!==r;){for(re.push(ge),ge=W,Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();if(Ke!==r)if(e.charCodeAt(W)===42?(pt=pc,W++):(pt=r,yt===0&&wt(Je)),pt===r&&(e.charCodeAt(W)===47?(pt=ot,W++):(pt=r,yt===0&&wt(St))),pt!==r){for(dr=[],vr=kt();vr!==r;)dr.push(vr),vr=kt();dr!==r?(vr=YA(),vr!==r?(xt=ge,Ke=lr(J,pt,vr),ge=Ke):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r}re!==r?(xt=N,J=ee(J,re),N=J):(W=N,N=r)}else W=N,N=r;return N}function uo(){var N,J,re,ge,Ke,pt,dr,vr;if(N=W,J=Df(),J!==r){for(re=[],ge=W,Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();if(Ke!==r)if(e.charCodeAt(W)===43?(pt=fc,W++):(pt=r,yt===0&&wt(Ka)),pt===r&&(e.charCodeAt(W)===45?(pt=uc,W++):(pt=r,yt===0&&wt(fu))),pt!==r){for(dr=[],vr=kt();vr!==r;)dr.push(vr),vr=kt();dr!==r?(vr=Df(),vr!==r?(xt=ge,Ke=ye(J,pt,vr),ge=Ke):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r;for(;ge!==r;){for(re.push(ge),ge=W,Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();if(Ke!==r)if(e.charCodeAt(W)===43?(pt=fc,W++):(pt=r,yt===0&&wt(Ka)),pt===r&&(e.charCodeAt(W)===45?(pt=uc,W++):(pt=r,yt===0&&wt(fu))),pt!==r){for(dr=[],vr=kt();vr!==r;)dr.push(vr),vr=kt();dr!==r?(vr=Df(),vr!==r?(xt=ge,Ke=ye(J,pt,vr),ge=Ke):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r}re!==r?(xt=N,J=ee(J,re),N=J):(W=N,N=r)}else W=N,N=r;return N}function Xr(){var N,J,re,ge,Ke,pt;if(N=W,e.substr(W,3)===Oe?(J=Oe,W+=3):(J=r,yt===0&&wt(mt)),J!==r){for(re=[],ge=kt();ge!==r;)re.push(ge),ge=kt();if(re!==r)if(ge=uo(),ge!==r){for(Ke=[],pt=kt();pt!==r;)Ke.push(pt),pt=kt();Ke!==r?(e.substr(W,2)===Et?(pt=Et,W+=2):(pt=r,yt===0&&wt(bt)),pt!==r?(xt=N,J=tr(ge),N=J):(W=N,N=r)):(W=N,N=r)}else W=N,N=r;else W=N,N=r}else W=N,N=r;return N}function Sh(){var N,J,re,ge;return N=W,e.substr(W,2)===pn?(J=pn,W+=2):(J=r,yt===0&&wt(ci)),J!==r?(re=da(),re!==r?(e.charCodeAt(W)===41?(ge=ce,W++):(ge=r,yt===0&&wt(X)),ge!==r?(xt=N,J=qi(re),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N}function KA(){var N,J,re,ge,Ke,pt;return N=W,e.substr(W,2)===Fn?(J=Fn,W+=2):(J=r,yt===0&&wt(Ja)),J!==r?(re=hc(),re!==r?(e.substr(W,2)===Iy?(ge=Iy,W+=2):(ge=r,yt===0&&wt(q1)),ge!==r?(Ke=Os(),Ke!==r?(e.charCodeAt(W)===125?(pt=_,W++):(pt=r,yt===0&&wt(tt)),pt!==r?(xt=N,J=xo(re,Ke),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===Fn?(J=Fn,W+=2):(J=r,yt===0&&wt(Ja)),J!==r?(re=hc(),re!==r?(e.substr(W,3)===Cy?(ge=Cy,W+=3):(ge=r,yt===0&&wt(mh)),ge!==r?(xt=N,J=W1(re),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===Fn?(J=Fn,W+=2):(J=r,yt===0&&wt(Ja)),J!==r?(re=hc(),re!==r?(e.substr(W,2)===ko?(ge=ko,W+=2):(ge=r,yt===0&&wt(yh)),ge!==r?(Ke=Os(),Ke!==r?(e.charCodeAt(W)===125?(pt=_,W++):(pt=r,yt===0&&wt(tt)),pt!==r?(xt=N,J=Eh(re,Ke),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===Fn?(J=Fn,W+=2):(J=r,yt===0&&wt(Ja)),J!==r?(re=hc(),re!==r?(e.substr(W,3)===Au?(ge=Au,W+=3):(ge=r,yt===0&&wt(Ih)),ge!==r?(xt=N,J=Rg(re),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.substr(W,2)===Fn?(J=Fn,W+=2):(J=r,yt===0&&wt(Ja)),J!==r?(re=hc(),re!==r?(e.charCodeAt(W)===125?(ge=_,W++):(ge=r,yt===0&&wt(tt)),ge!==r?(xt=N,J=Tg(re),N=J):(W=N,N=r)):(W=N,N=r)):(W=N,N=r),N===r&&(N=W,e.charCodeAt(W)===36?(J=Fg,W++):(J=r,yt===0&&wt(wy)),J!==r?(re=hc(),re!==r?(xt=N,J=Tg(re),N=J):(W=N,N=r)):(W=N,N=r)))))),N}function Py(){var N,J,re;return N=W,J=Gg(),J!==r?(xt=W,re=yf(J),re?re=void 0:re=r,re!==r?(xt=N,J=Qo(J),N=J):(W=N,N=r)):(W=N,N=r),N}function Gg(){var N,J,re,ge,Ke;if(N=W,J=[],re=W,ge=W,yt++,Ke=bh(),yt--,Ke===r?ge=void 0:(W=ge,ge=r),ge!==r?(e.length>W?(Ke=e.charAt(W),W++):(Ke=r,yt===0&&wt(Rn)),Ke!==r?(xt=re,ge=Po(Ke),re=ge):(W=re,re=r)):(W=re,re=r),re!==r)for(;re!==r;)J.push(re),re=W,ge=W,yt++,Ke=bh(),yt--,Ke===r?ge=void 0:(W=ge,ge=r),ge!==r?(e.length>W?(Ke=e.charAt(W),W++):(Ke=r,yt===0&&wt(Rn)),Ke!==r?(xt=re,ge=Po(Ke),re=ge):(W=re,re=r)):(W=re,re=r);else J=r;return J!==r&&(xt=N,J=lo(J)),N=J,N}function Dh(){var N,J,re;if(N=W,J=[],Ql.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Ch)),re!==r)for(;re!==r;)J.push(re),Ql.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Ch));else J=r;return J!==r&&(xt=N,J=Ng()),N=J,N}function hc(){var N,J,re;if(N=W,J=[],Rl.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Tl)),re!==r)for(;re!==r;)J.push(re),Rl.test(e.charAt(W))?(re=e.charAt(W),W++):(re=r,yt===0&&wt(Tl));else J=r;return J!==r&&(xt=N,J=Ng()),N=J,N}function xy(){var N;return By.test(e.charAt(W))?(N=e.charAt(W),W++):(N=r,yt===0&&wt(_A)),N}function bh(){var N;return vy.test(e.charAt(W))?(N=e.charAt(W),W++):(N=r,yt===0&&wt(Sy)),N}function kt(){var N,J;if(N=[],HA.test(e.charAt(W))?(J=e.charAt(W),W++):(J=r,yt===0&&wt(jA)),J!==r)for(;J!==r;)N.push(J),HA.test(e.charAt(W))?(J=e.charAt(W),W++):(J=r,yt===0&&wt(jA));else N=r;return N}if(pu=a(),pu!==r&&W===e.length)return pu;throw pu!==r&&W<e.length&&wt(za()),qA(Ef,Ro<e.length?e.charAt(Ro):null,Ro<e.length?Cf(Ro,Ro+1):Cf(Ro,Ro))}F$.exports={SyntaxError:Cd,parse:B6e}});function ux(e,t={isGlobPattern:()=>!1}){try{return(0,O$.parse)(e,t)}catch(r){throw r.location&&(r.message=r.message.replace(/(\\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function hE(e,{endSemicolon:t=!1}={}){return e.map(({command:r,type:s},a)=>`${fx(r)}${s===\";\"?a!==e.length-1||t?\";\":\"\":\" &\"}`).join(\" \")}function fx(e){return`${gE(e.chain)}${e.then?` ${SU(e.then)}`:\"\"}`}function SU(e){return`${e.type} ${fx(e.line)}`}function gE(e){return`${bU(e)}${e.then?` ${DU(e.then)}`:\"\"}`}function DU(e){return`${e.type} ${gE(e.chain)}`}function bU(e){switch(e.type){case\"command\":return`${e.envs.length>0?`${e.envs.map(t=>cx(t)).join(\" \")} `:\"\"}${e.args.map(t=>PU(t)).join(\" \")}`;case\"subshell\":return`(${hE(e.subshell)})${e.args.length>0?` ${e.args.map(t=>TB(t)).join(\" \")}`:\"\"}`;case\"group\":return`{ ${hE(e.group,{endSemicolon:!0})} }${e.args.length>0?` ${e.args.map(t=>TB(t)).join(\" \")}`:\"\"}`;case\"envs\":return e.envs.map(t=>cx(t)).join(\" \");default:throw new Error(`Unsupported command type:  \"${e.type}\"`)}}function cx(e){return`${e.name}=${e.args[0]?wd(e.args[0]):\"\"}`}function PU(e){switch(e.type){case\"redirection\":return TB(e);case\"argument\":return wd(e);default:throw new Error(`Unsupported argument type: \"${e.type}\"`)}}function TB(e){return`${e.subtype} ${e.args.map(t=>wd(t)).join(\" \")}`}function wd(e){return e.segments.map(t=>xU(t)).join(\"\")}function xU(e){let t=(s,a)=>a?`\"${s}\"`:s,r=s=>s===\"\"?\"''\":s.match(/[()}<>$|&;\"'\\n\\t ]/)?s.match(/['\\t\\p{C}]/u)?s.match(/'/)?`\"${s.replace(/[\"$\\t\\p{C}]/u,S6e)}\"`:`$'${s.replace(/[\\t\\p{C}]/u,M$)}'`:`'${s}'`:s;switch(e.type){case\"text\":return r(e.text);case\"glob\":return e.pattern;case\"shell\":return t(`$(${hE(e.shell)})`,e.quoted);case\"variable\":return t(typeof e.defaultValue>\"u\"?typeof e.alternativeValue>\"u\"?`\\${${e.name}}`:e.alternativeValue.length===0?`\\${${e.name}:+}`:`\\${${e.name}:+${e.alternativeValue.map(s=>wd(s)).join(\" \")}}`:e.defaultValue.length===0?`\\${${e.name}:-}`:`\\${${e.name}:-${e.defaultValue.map(s=>wd(s)).join(\" \")}}`,e.quoted);case\"arithmetic\":return`$(( ${Ax(e.arithmetic)} ))`;default:throw new Error(`Unsupported argument segment type: \"${e.type}\"`)}}function Ax(e){let t=a=>{switch(a){case\"addition\":return\"+\";case\"subtraction\":return\"-\";case\"multiplication\":return\"*\";case\"division\":return\"/\";default:throw new Error(`Can't extract operator from arithmetic expression of type \"${a}\"`)}},r=(a,n)=>n?`( ${a} )`:a,s=a=>r(Ax(a),![\"number\",\"variable\"].includes(a.type));switch(e.type){case\"number\":return String(e.value);case\"variable\":return e.name;default:return`${s(e.left)} ${t(e.type)} ${s(e.right)}`}}var O$,L$,v6e,M$,S6e,U$=Ze(()=>{O$=et(N$());L$=new Map([[\"\\f\",\"\\\\f\"],[`\n`,\"\\\\n\"],[\"\\r\",\"\\\\r\"],[\"\t\",\"\\\\t\"],[\"\\v\",\"\\\\v\"],[\"\\0\",\"\\\\0\"]]),v6e=new Map([[\"\\\\\",\"\\\\\\\\\"],[\"$\",\"\\\\$\"],['\"','\\\\\"'],...Array.from(L$,([e,t])=>[e,`\"$'${t}'\"`])]),M$=e=>L$.get(e)??`\\\\x${e.charCodeAt(0).toString(16).padStart(2,\"0\")}`,S6e=e=>v6e.get(e)??`\"$'${M$(e)}'\"`});var H$=G((hPt,_$)=>{\"use strict\";function D6e(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}function Bd(e,t,r,s){this.message=e,this.expected=t,this.found=r,this.location=s,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,Bd)}D6e(Bd,Error);Bd.buildMessage=function(e,t){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",C;for(C=0;C<h.parts.length;C++)E+=h.parts[C]instanceof Array?n(h.parts[C][0])+\"-\"+n(h.parts[C][1]):n(h.parts[C]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function s(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function c(h){return r[h.type](h)}function f(h){var E=new Array(h.length),C,S;for(C=0;C<h.length;C++)E[C]=c(h[C]);if(E.sort(),E.length>0){for(C=1,S=1;C<E.length;C++)E[C-1]!==E[C]&&(E[S]=E[C],S++);E.length=S}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+f(e)+\" but \"+p(t)+\" found.\"};function b6e(e,t){t=t!==void 0?t:{};var r={},s={resolution:ke},a=ke,n=\"/\",c=Be(\"/\",!1),f=function(Me,P){return{from:Me,descriptor:P}},p=function(Me){return{descriptor:Me}},h=\"@\",E=Be(\"@\",!1),C=function(Me,P){return{fullName:Me,description:P}},S=function(Me){return{fullName:Me}},x=function(){return Ce()},I=/^[^\\/@]/,T=me([\"/\",\"@\"],!0,!1),O=/^[^\\/]/,U=me([\"/\"],!0,!1),Y=0,te=0,ie=[{line:1,column:1}],ue=0,ae=[],de=0,Ae;if(\"startRule\"in t){if(!(t.startRule in s))throw new Error(`Can't start parsing from rule \"`+t.startRule+'\".');a=s[t.startRule]}function Ce(){return e.substring(te,Y)}function Ee(){return it(te,Y)}function g(Me,P){throw P=P!==void 0?P:it(te,Y),Ne([De(Me)],e.substring(te,Y),P)}function Se(Me,P){throw P=P!==void 0?P:it(te,Y),tt(Me,P)}function Be(Me,P){return{type:\"literal\",text:Me,ignoreCase:P}}function me(Me,P,w){return{type:\"class\",parts:Me,inverted:P,ignoreCase:w}}function ce(){return{type:\"any\"}}function X(){return{type:\"end\"}}function De(Me){return{type:\"other\",description:Me}}function Qe(Me){var P=ie[Me],w;if(P)return P;for(w=Me-1;!ie[w];)w--;for(P=ie[w],P={line:P.line,column:P.column};w<Me;)e.charCodeAt(w)===10?(P.line++,P.column=1):P.column++,w++;return ie[Me]=P,P}function it(Me,P){var w=Qe(Me),b=Qe(P);return{start:{offset:Me,line:w.line,column:w.column},end:{offset:P,line:b.line,column:b.column}}}function _(Me){Y<ue||(Y>ue&&(ue=Y,ae=[]),ae.push(Me))}function tt(Me,P){return new Bd(Me,null,null,P)}function Ne(Me,P,w){return new Bd(Bd.buildMessage(Me,P),Me,P,w)}function ke(){var Me,P,w,b;return Me=Y,P=be(),P!==r?(e.charCodeAt(Y)===47?(w=n,Y++):(w=r,de===0&&_(c)),w!==r?(b=be(),b!==r?(te=Me,P=f(P,b),Me=P):(Y=Me,Me=r)):(Y=Me,Me=r)):(Y=Me,Me=r),Me===r&&(Me=Y,P=be(),P!==r&&(te=Me,P=p(P)),Me=P),Me}function be(){var Me,P,w,b;return Me=Y,P=je(),P!==r?(e.charCodeAt(Y)===64?(w=h,Y++):(w=r,de===0&&_(E)),w!==r?(b=ct(),b!==r?(te=Me,P=C(P,b),Me=P):(Y=Me,Me=r)):(Y=Me,Me=r)):(Y=Me,Me=r),Me===r&&(Me=Y,P=je(),P!==r&&(te=Me,P=S(P)),Me=P),Me}function je(){var Me,P,w,b,y;return Me=Y,e.charCodeAt(Y)===64?(P=h,Y++):(P=r,de===0&&_(E)),P!==r?(w=Re(),w!==r?(e.charCodeAt(Y)===47?(b=n,Y++):(b=r,de===0&&_(c)),b!==r?(y=Re(),y!==r?(te=Me,P=x(),Me=P):(Y=Me,Me=r)):(Y=Me,Me=r)):(Y=Me,Me=r)):(Y=Me,Me=r),Me===r&&(Me=Y,P=Re(),P!==r&&(te=Me,P=x()),Me=P),Me}function Re(){var Me,P,w;if(Me=Y,P=[],I.test(e.charAt(Y))?(w=e.charAt(Y),Y++):(w=r,de===0&&_(T)),w!==r)for(;w!==r;)P.push(w),I.test(e.charAt(Y))?(w=e.charAt(Y),Y++):(w=r,de===0&&_(T));else P=r;return P!==r&&(te=Me,P=x()),Me=P,Me}function ct(){var Me,P,w;if(Me=Y,P=[],O.test(e.charAt(Y))?(w=e.charAt(Y),Y++):(w=r,de===0&&_(U)),w!==r)for(;w!==r;)P.push(w),O.test(e.charAt(Y))?(w=e.charAt(Y),Y++):(w=r,de===0&&_(U));else P=r;return P!==r&&(te=Me,P=x()),Me=P,Me}if(Ae=a(),Ae!==r&&Y===e.length)return Ae;throw Ae!==r&&Y<e.length&&_(X()),Ne(ae,ue<e.length?e.charAt(ue):null,ue<e.length?it(ue,ue+1):it(ue,ue))}_$.exports={SyntaxError:Bd,parse:b6e}});function px(e){let t=e.match(/^\\*{1,2}\\/(.*)/);if(t)throw new Error(`The override for '${e}' includes a glob pattern. Glob patterns have been removed since their behaviours don't match what you'd expect. Set the override to '${t[1]}' instead.`);try{return(0,j$.parse)(e)}catch(r){throw r.location&&(r.message=r.message.replace(/(\\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function hx(e){let t=\"\";return e.from&&(t+=e.from.fullName,e.from.description&&(t+=`@${e.from.description}`),t+=\"/\"),t+=e.descriptor.fullName,e.descriptor.description&&(t+=`@${e.descriptor.description}`),t}var j$,G$=Ze(()=>{j$=et(H$())});var Sd=G((dPt,vd)=>{\"use strict\";function q$(e){return typeof e>\"u\"||e===null}function P6e(e){return typeof e==\"object\"&&e!==null}function x6e(e){return Array.isArray(e)?e:q$(e)?[]:[e]}function k6e(e,t){var r,s,a,n;if(t)for(n=Object.keys(t),r=0,s=n.length;r<s;r+=1)a=n[r],e[a]=t[a];return e}function Q6e(e,t){var r=\"\",s;for(s=0;s<t;s+=1)r+=e;return r}function R6e(e){return e===0&&Number.NEGATIVE_INFINITY===1/e}vd.exports.isNothing=q$;vd.exports.isObject=P6e;vd.exports.toArray=x6e;vd.exports.repeat=Q6e;vd.exports.isNegativeZero=R6e;vd.exports.extend=k6e});var dE=G((mPt,W$)=>{\"use strict\";function FB(e,t){Error.call(this),this.name=\"YAMLException\",this.reason=e,this.mark=t,this.message=(this.reason||\"(unknown reason)\")+(this.mark?\" \"+this.mark.toString():\"\"),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||\"\"}FB.prototype=Object.create(Error.prototype);FB.prototype.constructor=FB;FB.prototype.toString=function(t){var r=this.name+\": \";return r+=this.reason||\"(unknown reason)\",!t&&this.mark&&(r+=\" \"+this.mark.toString()),r};W$.exports=FB});var K$=G((yPt,Y$)=>{\"use strict\";var V$=Sd();function kU(e,t,r,s,a){this.name=e,this.buffer=t,this.position=r,this.line=s,this.column=a}kU.prototype.getSnippet=function(t,r){var s,a,n,c,f;if(!this.buffer)return null;for(t=t||4,r=r||75,s=\"\",a=this.position;a>0&&`\\0\\r\n\\x85\\u2028\\u2029`.indexOf(this.buffer.charAt(a-1))===-1;)if(a-=1,this.position-a>r/2-1){s=\" ... \",a+=5;break}for(n=\"\",c=this.position;c<this.buffer.length&&`\\0\\r\n\\x85\\u2028\\u2029`.indexOf(this.buffer.charAt(c))===-1;)if(c+=1,c-this.position>r/2-1){n=\" ... \",c-=5;break}return f=this.buffer.slice(a,c),V$.repeat(\" \",t)+s+f+n+`\n`+V$.repeat(\" \",t+this.position-a+s.length)+\"^\"};kU.prototype.toString=function(t){var r,s=\"\";return this.name&&(s+='in \"'+this.name+'\" '),s+=\"at line \"+(this.line+1)+\", column \"+(this.column+1),t||(r=this.getSnippet(),r&&(s+=`:\n`+r)),s};Y$.exports=kU});var Ps=G((EPt,z$)=>{\"use strict\";var J$=dE(),T6e=[\"kind\",\"resolve\",\"construct\",\"instanceOf\",\"predicate\",\"represent\",\"defaultStyle\",\"styleAliases\"],F6e=[\"scalar\",\"sequence\",\"mapping\"];function N6e(e){var t={};return e!==null&&Object.keys(e).forEach(function(r){e[r].forEach(function(s){t[String(s)]=r})}),t}function O6e(e,t){if(t=t||{},Object.keys(t).forEach(function(r){if(T6e.indexOf(r)===-1)throw new J$('Unknown option \"'+r+'\" is met in definition of \"'+e+'\" YAML type.')}),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(r){return r},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.defaultStyle=t.defaultStyle||null,this.styleAliases=N6e(t.styleAliases||null),F6e.indexOf(this.kind)===-1)throw new J$('Unknown kind \"'+this.kind+'\" is specified for \"'+e+'\" YAML type.')}z$.exports=O6e});var Dd=G((IPt,X$)=>{\"use strict\";var Z$=Sd(),gx=dE(),L6e=Ps();function QU(e,t,r){var s=[];return e.include.forEach(function(a){r=QU(a,t,r)}),e[t].forEach(function(a){r.forEach(function(n,c){n.tag===a.tag&&n.kind===a.kind&&s.push(c)}),r.push(a)}),r.filter(function(a,n){return s.indexOf(n)===-1})}function M6e(){var e={scalar:{},sequence:{},mapping:{},fallback:{}},t,r;function s(a){e[a.kind][a.tag]=e.fallback[a.tag]=a}for(t=0,r=arguments.length;t<r;t+=1)arguments[t].forEach(s);return e}function mE(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach(function(t){if(t.loadKind&&t.loadKind!==\"scalar\")throw new gx(\"There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.\")}),this.compiledImplicit=QU(this,\"implicit\",[]),this.compiledExplicit=QU(this,\"explicit\",[]),this.compiledTypeMap=M6e(this.compiledImplicit,this.compiledExplicit)}mE.DEFAULT=null;mE.create=function(){var t,r;switch(arguments.length){case 1:t=mE.DEFAULT,r=arguments[0];break;case 2:t=arguments[0],r=arguments[1];break;default:throw new gx(\"Wrong number of arguments for Schema.create function\")}if(t=Z$.toArray(t),r=Z$.toArray(r),!t.every(function(s){return s instanceof mE}))throw new gx(\"Specified list of super schemas (or a single Schema object) contains a non-Schema object.\");if(!r.every(function(s){return s instanceof L6e}))throw new gx(\"Specified list of YAML types (or a single Type object) contains a non-Type object.\");return new mE({include:t,explicit:r})};X$.exports=mE});var eee=G((CPt,$$)=>{\"use strict\";var U6e=Ps();$$.exports=new U6e(\"tag:yaml.org,2002:str\",{kind:\"scalar\",construct:function(e){return e!==null?e:\"\"}})});var ree=G((wPt,tee)=>{\"use strict\";var _6e=Ps();tee.exports=new _6e(\"tag:yaml.org,2002:seq\",{kind:\"sequence\",construct:function(e){return e!==null?e:[]}})});var iee=G((BPt,nee)=>{\"use strict\";var H6e=Ps();nee.exports=new H6e(\"tag:yaml.org,2002:map\",{kind:\"mapping\",construct:function(e){return e!==null?e:{}}})});var dx=G((vPt,see)=>{\"use strict\";var j6e=Dd();see.exports=new j6e({explicit:[eee(),ree(),iee()]})});var aee=G((SPt,oee)=>{\"use strict\";var G6e=Ps();function q6e(e){if(e===null)return!0;var t=e.length;return t===1&&e===\"~\"||t===4&&(e===\"null\"||e===\"Null\"||e===\"NULL\")}function W6e(){return null}function V6e(e){return e===null}oee.exports=new G6e(\"tag:yaml.org,2002:null\",{kind:\"scalar\",resolve:q6e,construct:W6e,predicate:V6e,represent:{canonical:function(){return\"~\"},lowercase:function(){return\"null\"},uppercase:function(){return\"NULL\"},camelcase:function(){return\"Null\"}},defaultStyle:\"lowercase\"})});var cee=G((DPt,lee)=>{\"use strict\";var Y6e=Ps();function K6e(e){if(e===null)return!1;var t=e.length;return t===4&&(e===\"true\"||e===\"True\"||e===\"TRUE\")||t===5&&(e===\"false\"||e===\"False\"||e===\"FALSE\")}function J6e(e){return e===\"true\"||e===\"True\"||e===\"TRUE\"}function z6e(e){return Object.prototype.toString.call(e)===\"[object Boolean]\"}lee.exports=new Y6e(\"tag:yaml.org,2002:bool\",{kind:\"scalar\",resolve:K6e,construct:J6e,predicate:z6e,represent:{lowercase:function(e){return e?\"true\":\"false\"},uppercase:function(e){return e?\"TRUE\":\"FALSE\"},camelcase:function(e){return e?\"True\":\"False\"}},defaultStyle:\"lowercase\"})});var fee=G((bPt,uee)=>{\"use strict\";var Z6e=Sd(),X6e=Ps();function $6e(e){return 48<=e&&e<=57||65<=e&&e<=70||97<=e&&e<=102}function eGe(e){return 48<=e&&e<=55}function tGe(e){return 48<=e&&e<=57}function rGe(e){if(e===null)return!1;var t=e.length,r=0,s=!1,a;if(!t)return!1;if(a=e[r],(a===\"-\"||a===\"+\")&&(a=e[++r]),a===\"0\"){if(r+1===t)return!0;if(a=e[++r],a===\"b\"){for(r++;r<t;r++)if(a=e[r],a!==\"_\"){if(a!==\"0\"&&a!==\"1\")return!1;s=!0}return s&&a!==\"_\"}if(a===\"x\"){for(r++;r<t;r++)if(a=e[r],a!==\"_\"){if(!$6e(e.charCodeAt(r)))return!1;s=!0}return s&&a!==\"_\"}for(;r<t;r++)if(a=e[r],a!==\"_\"){if(!eGe(e.charCodeAt(r)))return!1;s=!0}return s&&a!==\"_\"}if(a===\"_\")return!1;for(;r<t;r++)if(a=e[r],a!==\"_\"){if(a===\":\")break;if(!tGe(e.charCodeAt(r)))return!1;s=!0}return!s||a===\"_\"?!1:a!==\":\"?!0:/^(:[0-5]?[0-9])+$/.test(e.slice(r))}function nGe(e){var t=e,r=1,s,a,n=[];return t.indexOf(\"_\")!==-1&&(t=t.replace(/_/g,\"\")),s=t[0],(s===\"-\"||s===\"+\")&&(s===\"-\"&&(r=-1),t=t.slice(1),s=t[0]),t===\"0\"?0:s===\"0\"?t[1]===\"b\"?r*parseInt(t.slice(2),2):t[1]===\"x\"?r*parseInt(t,16):r*parseInt(t,8):t.indexOf(\":\")!==-1?(t.split(\":\").forEach(function(c){n.unshift(parseInt(c,10))}),t=0,a=1,n.forEach(function(c){t+=c*a,a*=60}),r*t):r*parseInt(t,10)}function iGe(e){return Object.prototype.toString.call(e)===\"[object Number]\"&&e%1===0&&!Z6e.isNegativeZero(e)}uee.exports=new X6e(\"tag:yaml.org,2002:int\",{kind:\"scalar\",resolve:rGe,construct:nGe,predicate:iGe,represent:{binary:function(e){return e>=0?\"0b\"+e.toString(2):\"-0b\"+e.toString(2).slice(1)},octal:function(e){return e>=0?\"0\"+e.toString(8):\"-0\"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?\"0x\"+e.toString(16).toUpperCase():\"-0x\"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:\"decimal\",styleAliases:{binary:[2,\"bin\"],octal:[8,\"oct\"],decimal:[10,\"dec\"],hexadecimal:[16,\"hex\"]}})});var hee=G((PPt,pee)=>{\"use strict\";var Aee=Sd(),sGe=Ps(),oGe=new RegExp(\"^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\\\.[0-9_]*|[-+]?\\\\.(?:inf|Inf|INF)|\\\\.(?:nan|NaN|NAN))$\");function aGe(e){return!(e===null||!oGe.test(e)||e[e.length-1]===\"_\")}function lGe(e){var t,r,s,a;return t=e.replace(/_/g,\"\").toLowerCase(),r=t[0]===\"-\"?-1:1,a=[],\"+-\".indexOf(t[0])>=0&&(t=t.slice(1)),t===\".inf\"?r===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:t===\".nan\"?NaN:t.indexOf(\":\")>=0?(t.split(\":\").forEach(function(n){a.unshift(parseFloat(n,10))}),t=0,s=1,a.forEach(function(n){t+=n*s,s*=60}),r*t):r*parseFloat(t,10)}var cGe=/^[-+]?[0-9]+e/;function uGe(e,t){var r;if(isNaN(e))switch(t){case\"lowercase\":return\".nan\";case\"uppercase\":return\".NAN\";case\"camelcase\":return\".NaN\"}else if(Number.POSITIVE_INFINITY===e)switch(t){case\"lowercase\":return\".inf\";case\"uppercase\":return\".INF\";case\"camelcase\":return\".Inf\"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case\"lowercase\":return\"-.inf\";case\"uppercase\":return\"-.INF\";case\"camelcase\":return\"-.Inf\"}else if(Aee.isNegativeZero(e))return\"-0.0\";return r=e.toString(10),cGe.test(r)?r.replace(\"e\",\".e\"):r}function fGe(e){return Object.prototype.toString.call(e)===\"[object Number]\"&&(e%1!==0||Aee.isNegativeZero(e))}pee.exports=new sGe(\"tag:yaml.org,2002:float\",{kind:\"scalar\",resolve:aGe,construct:lGe,predicate:fGe,represent:uGe,defaultStyle:\"lowercase\"})});var RU=G((xPt,gee)=>{\"use strict\";var AGe=Dd();gee.exports=new AGe({include:[dx()],implicit:[aee(),cee(),fee(),hee()]})});var TU=G((kPt,dee)=>{\"use strict\";var pGe=Dd();dee.exports=new pGe({include:[RU()]})});var Iee=G((QPt,Eee)=>{\"use strict\";var hGe=Ps(),mee=new RegExp(\"^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$\"),yee=new RegExp(\"^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\\\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\\\.([0-9]*))?(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$\");function gGe(e){return e===null?!1:mee.exec(e)!==null||yee.exec(e)!==null}function dGe(e){var t,r,s,a,n,c,f,p=0,h=null,E,C,S;if(t=mee.exec(e),t===null&&(t=yee.exec(e)),t===null)throw new Error(\"Date resolve error\");if(r=+t[1],s=+t[2]-1,a=+t[3],!t[4])return new Date(Date.UTC(r,s,a));if(n=+t[4],c=+t[5],f=+t[6],t[7]){for(p=t[7].slice(0,3);p.length<3;)p+=\"0\";p=+p}return t[9]&&(E=+t[10],C=+(t[11]||0),h=(E*60+C)*6e4,t[9]===\"-\"&&(h=-h)),S=new Date(Date.UTC(r,s,a,n,c,f,p)),h&&S.setTime(S.getTime()-h),S}function mGe(e){return e.toISOString()}Eee.exports=new hGe(\"tag:yaml.org,2002:timestamp\",{kind:\"scalar\",resolve:gGe,construct:dGe,instanceOf:Date,represent:mGe})});var wee=G((RPt,Cee)=>{\"use strict\";var yGe=Ps();function EGe(e){return e===\"<<\"||e===null}Cee.exports=new yGe(\"tag:yaml.org,2002:merge\",{kind:\"scalar\",resolve:EGe})});var See=G((TPt,vee)=>{\"use strict\";var bd;try{Bee=Ie,bd=Bee(\"buffer\").Buffer}catch{}var Bee,IGe=Ps(),FU=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\\r`;function CGe(e){if(e===null)return!1;var t,r,s=0,a=e.length,n=FU;for(r=0;r<a;r++)if(t=n.indexOf(e.charAt(r)),!(t>64)){if(t<0)return!1;s+=6}return s%8===0}function wGe(e){var t,r,s=e.replace(/[\\r\\n=]/g,\"\"),a=s.length,n=FU,c=0,f=[];for(t=0;t<a;t++)t%4===0&&t&&(f.push(c>>16&255),f.push(c>>8&255),f.push(c&255)),c=c<<6|n.indexOf(s.charAt(t));return r=a%4*6,r===0?(f.push(c>>16&255),f.push(c>>8&255),f.push(c&255)):r===18?(f.push(c>>10&255),f.push(c>>2&255)):r===12&&f.push(c>>4&255),bd?bd.from?bd.from(f):new bd(f):f}function BGe(e){var t=\"\",r=0,s,a,n=e.length,c=FU;for(s=0;s<n;s++)s%3===0&&s&&(t+=c[r>>18&63],t+=c[r>>12&63],t+=c[r>>6&63],t+=c[r&63]),r=(r<<8)+e[s];return a=n%3,a===0?(t+=c[r>>18&63],t+=c[r>>12&63],t+=c[r>>6&63],t+=c[r&63]):a===2?(t+=c[r>>10&63],t+=c[r>>4&63],t+=c[r<<2&63],t+=c[64]):a===1&&(t+=c[r>>2&63],t+=c[r<<4&63],t+=c[64],t+=c[64]),t}function vGe(e){return bd&&bd.isBuffer(e)}vee.exports=new IGe(\"tag:yaml.org,2002:binary\",{kind:\"scalar\",resolve:CGe,construct:wGe,predicate:vGe,represent:BGe})});var bee=G((NPt,Dee)=>{\"use strict\";var SGe=Ps(),DGe=Object.prototype.hasOwnProperty,bGe=Object.prototype.toString;function PGe(e){if(e===null)return!0;var t=[],r,s,a,n,c,f=e;for(r=0,s=f.length;r<s;r+=1){if(a=f[r],c=!1,bGe.call(a)!==\"[object Object]\")return!1;for(n in a)if(DGe.call(a,n))if(!c)c=!0;else return!1;if(!c)return!1;if(t.indexOf(n)===-1)t.push(n);else return!1}return!0}function xGe(e){return e!==null?e:[]}Dee.exports=new SGe(\"tag:yaml.org,2002:omap\",{kind:\"sequence\",resolve:PGe,construct:xGe})});var xee=G((OPt,Pee)=>{\"use strict\";var kGe=Ps(),QGe=Object.prototype.toString;function RGe(e){if(e===null)return!0;var t,r,s,a,n,c=e;for(n=new Array(c.length),t=0,r=c.length;t<r;t+=1){if(s=c[t],QGe.call(s)!==\"[object Object]\"||(a=Object.keys(s),a.length!==1))return!1;n[t]=[a[0],s[a[0]]]}return!0}function TGe(e){if(e===null)return[];var t,r,s,a,n,c=e;for(n=new Array(c.length),t=0,r=c.length;t<r;t+=1)s=c[t],a=Object.keys(s),n[t]=[a[0],s[a[0]]];return n}Pee.exports=new kGe(\"tag:yaml.org,2002:pairs\",{kind:\"sequence\",resolve:RGe,construct:TGe})});var Qee=G((LPt,kee)=>{\"use strict\";var FGe=Ps(),NGe=Object.prototype.hasOwnProperty;function OGe(e){if(e===null)return!0;var t,r=e;for(t in r)if(NGe.call(r,t)&&r[t]!==null)return!1;return!0}function LGe(e){return e!==null?e:{}}kee.exports=new FGe(\"tag:yaml.org,2002:set\",{kind:\"mapping\",resolve:OGe,construct:LGe})});var yE=G((MPt,Ree)=>{\"use strict\";var MGe=Dd();Ree.exports=new MGe({include:[TU()],implicit:[Iee(),wee()],explicit:[See(),bee(),xee(),Qee()]})});var Fee=G((UPt,Tee)=>{\"use strict\";var UGe=Ps();function _Ge(){return!0}function HGe(){}function jGe(){return\"\"}function GGe(e){return typeof e>\"u\"}Tee.exports=new UGe(\"tag:yaml.org,2002:js/undefined\",{kind:\"scalar\",resolve:_Ge,construct:HGe,predicate:GGe,represent:jGe})});var Oee=G((_Pt,Nee)=>{\"use strict\";var qGe=Ps();function WGe(e){if(e===null||e.length===0)return!1;var t=e,r=/\\/([gim]*)$/.exec(e),s=\"\";return!(t[0]===\"/\"&&(r&&(s=r[1]),s.length>3||t[t.length-s.length-1]!==\"/\"))}function VGe(e){var t=e,r=/\\/([gim]*)$/.exec(e),s=\"\";return t[0]===\"/\"&&(r&&(s=r[1]),t=t.slice(1,t.length-s.length-1)),new RegExp(t,s)}function YGe(e){var t=\"/\"+e.source+\"/\";return e.global&&(t+=\"g\"),e.multiline&&(t+=\"m\"),e.ignoreCase&&(t+=\"i\"),t}function KGe(e){return Object.prototype.toString.call(e)===\"[object RegExp]\"}Nee.exports=new qGe(\"tag:yaml.org,2002:js/regexp\",{kind:\"scalar\",resolve:WGe,construct:VGe,predicate:KGe,represent:YGe})});var Uee=G((HPt,Mee)=>{\"use strict\";var mx;try{Lee=Ie,mx=Lee(\"esprima\")}catch{typeof window<\"u\"&&(mx=window.esprima)}var Lee,JGe=Ps();function zGe(e){if(e===null)return!1;try{var t=\"(\"+e+\")\",r=mx.parse(t,{range:!0});return!(r.type!==\"Program\"||r.body.length!==1||r.body[0].type!==\"ExpressionStatement\"||r.body[0].expression.type!==\"ArrowFunctionExpression\"&&r.body[0].expression.type!==\"FunctionExpression\")}catch{return!1}}function ZGe(e){var t=\"(\"+e+\")\",r=mx.parse(t,{range:!0}),s=[],a;if(r.type!==\"Program\"||r.body.length!==1||r.body[0].type!==\"ExpressionStatement\"||r.body[0].expression.type!==\"ArrowFunctionExpression\"&&r.body[0].expression.type!==\"FunctionExpression\")throw new Error(\"Failed to resolve function\");return r.body[0].expression.params.forEach(function(n){s.push(n.name)}),a=r.body[0].expression.body.range,r.body[0].expression.body.type===\"BlockStatement\"?new Function(s,t.slice(a[0]+1,a[1]-1)):new Function(s,\"return \"+t.slice(a[0],a[1]))}function XGe(e){return e.toString()}function $Ge(e){return Object.prototype.toString.call(e)===\"[object Function]\"}Mee.exports=new JGe(\"tag:yaml.org,2002:js/function\",{kind:\"scalar\",resolve:zGe,construct:ZGe,predicate:$Ge,represent:XGe})});var NB=G((GPt,Hee)=>{\"use strict\";var _ee=Dd();Hee.exports=_ee.DEFAULT=new _ee({include:[yE()],explicit:[Fee(),Oee(),Uee()]})});var ote=G((qPt,OB)=>{\"use strict\";var Cp=Sd(),Kee=dE(),e5e=K$(),Jee=yE(),t5e=NB(),r0=Object.prototype.hasOwnProperty,yx=1,zee=2,Zee=3,Ex=4,NU=1,r5e=2,jee=3,n5e=/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/,i5e=/[\\x85\\u2028\\u2029]/,s5e=/[,\\[\\]\\{\\}]/,Xee=/^(?:!|!!|![a-z\\-]+!)$/i,$ee=/^(?:!|[^,\\[\\]\\{\\}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;\\/\\?:@&=\\+\\$,_\\.!~\\*'\\(\\)\\[\\]])*$/i;function Gee(e){return Object.prototype.toString.call(e)}function qf(e){return e===10||e===13}function xd(e){return e===9||e===32}function ll(e){return e===9||e===32||e===10||e===13}function EE(e){return e===44||e===91||e===93||e===123||e===125}function o5e(e){var t;return 48<=e&&e<=57?e-48:(t=e|32,97<=t&&t<=102?t-97+10:-1)}function a5e(e){return e===120?2:e===117?4:e===85?8:0}function l5e(e){return 48<=e&&e<=57?e-48:-1}function qee(e){return e===48?\"\\0\":e===97?\"\\x07\":e===98?\"\\b\":e===116||e===9?\"\t\":e===110?`\n`:e===118?\"\\v\":e===102?\"\\f\":e===114?\"\\r\":e===101?\"\\x1B\":e===32?\" \":e===34?'\"':e===47?\"/\":e===92?\"\\\\\":e===78?\"\\x85\":e===95?\"\\xA0\":e===76?\"\\u2028\":e===80?\"\\u2029\":\"\"}function c5e(e){return e<=65535?String.fromCharCode(e):String.fromCharCode((e-65536>>10)+55296,(e-65536&1023)+56320)}var ete=new Array(256),tte=new Array(256);for(Pd=0;Pd<256;Pd++)ete[Pd]=qee(Pd)?1:0,tte[Pd]=qee(Pd);var Pd;function u5e(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||t5e,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function rte(e,t){return new Kee(t,new e5e(e.filename,e.input,e.position,e.line,e.position-e.lineStart))}function Tr(e,t){throw rte(e,t)}function Ix(e,t){e.onWarning&&e.onWarning.call(null,rte(e,t))}var Wee={YAML:function(t,r,s){var a,n,c;t.version!==null&&Tr(t,\"duplication of %YAML directive\"),s.length!==1&&Tr(t,\"YAML directive accepts exactly one argument\"),a=/^([0-9]+)\\.([0-9]+)$/.exec(s[0]),a===null&&Tr(t,\"ill-formed argument of the YAML directive\"),n=parseInt(a[1],10),c=parseInt(a[2],10),n!==1&&Tr(t,\"unacceptable YAML version of the document\"),t.version=s[0],t.checkLineBreaks=c<2,c!==1&&c!==2&&Ix(t,\"unsupported YAML version of the document\")},TAG:function(t,r,s){var a,n;s.length!==2&&Tr(t,\"TAG directive accepts exactly two arguments\"),a=s[0],n=s[1],Xee.test(a)||Tr(t,\"ill-formed tag handle (first argument) of the TAG directive\"),r0.call(t.tagMap,a)&&Tr(t,'there is a previously declared suffix for \"'+a+'\" tag handle'),$ee.test(n)||Tr(t,\"ill-formed tag prefix (second argument) of the TAG directive\"),t.tagMap[a]=n}};function t0(e,t,r,s){var a,n,c,f;if(t<r){if(f=e.input.slice(t,r),s)for(a=0,n=f.length;a<n;a+=1)c=f.charCodeAt(a),c===9||32<=c&&c<=1114111||Tr(e,\"expected valid JSON character\");else n5e.test(f)&&Tr(e,\"the stream contains non-printable characters\");e.result+=f}}function Vee(e,t,r,s){var a,n,c,f;for(Cp.isObject(r)||Tr(e,\"cannot merge mappings; the provided source object is unacceptable\"),a=Object.keys(r),c=0,f=a.length;c<f;c+=1)n=a[c],r0.call(t,n)||(t[n]=r[n],s[n]=!0)}function IE(e,t,r,s,a,n,c,f){var p,h;if(Array.isArray(a))for(a=Array.prototype.slice.call(a),p=0,h=a.length;p<h;p+=1)Array.isArray(a[p])&&Tr(e,\"nested arrays are not supported inside keys\"),typeof a==\"object\"&&Gee(a[p])===\"[object Object]\"&&(a[p]=\"[object Object]\");if(typeof a==\"object\"&&Gee(a)===\"[object Object]\"&&(a=\"[object Object]\"),a=String(a),t===null&&(t={}),s===\"tag:yaml.org,2002:merge\")if(Array.isArray(n))for(p=0,h=n.length;p<h;p+=1)Vee(e,t,n[p],r);else Vee(e,t,n,r);else!e.json&&!r0.call(r,a)&&r0.call(t,a)&&(e.line=c||e.line,e.position=f||e.position,Tr(e,\"duplicated mapping key\")),t[a]=n,delete r[a];return t}function OU(e){var t;t=e.input.charCodeAt(e.position),t===10?e.position++:t===13?(e.position++,e.input.charCodeAt(e.position)===10&&e.position++):Tr(e,\"a line break is expected\"),e.line+=1,e.lineStart=e.position}function ls(e,t,r){for(var s=0,a=e.input.charCodeAt(e.position);a!==0;){for(;xd(a);)a=e.input.charCodeAt(++e.position);if(t&&a===35)do a=e.input.charCodeAt(++e.position);while(a!==10&&a!==13&&a!==0);if(qf(a))for(OU(e),a=e.input.charCodeAt(e.position),s++,e.lineIndent=0;a===32;)e.lineIndent++,a=e.input.charCodeAt(++e.position);else break}return r!==-1&&s!==0&&e.lineIndent<r&&Ix(e,\"deficient indentation\"),s}function Cx(e){var t=e.position,r;return r=e.input.charCodeAt(t),!!((r===45||r===46)&&r===e.input.charCodeAt(t+1)&&r===e.input.charCodeAt(t+2)&&(t+=3,r=e.input.charCodeAt(t),r===0||ll(r)))}function LU(e,t){t===1?e.result+=\" \":t>1&&(e.result+=Cp.repeat(`\n`,t-1))}function f5e(e,t,r){var s,a,n,c,f,p,h,E,C=e.kind,S=e.result,x;if(x=e.input.charCodeAt(e.position),ll(x)||EE(x)||x===35||x===38||x===42||x===33||x===124||x===62||x===39||x===34||x===37||x===64||x===96||(x===63||x===45)&&(a=e.input.charCodeAt(e.position+1),ll(a)||r&&EE(a)))return!1;for(e.kind=\"scalar\",e.result=\"\",n=c=e.position,f=!1;x!==0;){if(x===58){if(a=e.input.charCodeAt(e.position+1),ll(a)||r&&EE(a))break}else if(x===35){if(s=e.input.charCodeAt(e.position-1),ll(s))break}else{if(e.position===e.lineStart&&Cx(e)||r&&EE(x))break;if(qf(x))if(p=e.line,h=e.lineStart,E=e.lineIndent,ls(e,!1,-1),e.lineIndent>=t){f=!0,x=e.input.charCodeAt(e.position);continue}else{e.position=c,e.line=p,e.lineStart=h,e.lineIndent=E;break}}f&&(t0(e,n,c,!1),LU(e,e.line-p),n=c=e.position,f=!1),xd(x)||(c=e.position+1),x=e.input.charCodeAt(++e.position)}return t0(e,n,c,!1),e.result?!0:(e.kind=C,e.result=S,!1)}function A5e(e,t){var r,s,a;if(r=e.input.charCodeAt(e.position),r!==39)return!1;for(e.kind=\"scalar\",e.result=\"\",e.position++,s=a=e.position;(r=e.input.charCodeAt(e.position))!==0;)if(r===39)if(t0(e,s,e.position,!0),r=e.input.charCodeAt(++e.position),r===39)s=e.position,e.position++,a=e.position;else return!0;else qf(r)?(t0(e,s,a,!0),LU(e,ls(e,!1,t)),s=a=e.position):e.position===e.lineStart&&Cx(e)?Tr(e,\"unexpected end of the document within a single quoted scalar\"):(e.position++,a=e.position);Tr(e,\"unexpected end of the stream within a single quoted scalar\")}function p5e(e,t){var r,s,a,n,c,f;if(f=e.input.charCodeAt(e.position),f!==34)return!1;for(e.kind=\"scalar\",e.result=\"\",e.position++,r=s=e.position;(f=e.input.charCodeAt(e.position))!==0;){if(f===34)return t0(e,r,e.position,!0),e.position++,!0;if(f===92){if(t0(e,r,e.position,!0),f=e.input.charCodeAt(++e.position),qf(f))ls(e,!1,t);else if(f<256&&ete[f])e.result+=tte[f],e.position++;else if((c=a5e(f))>0){for(a=c,n=0;a>0;a--)f=e.input.charCodeAt(++e.position),(c=o5e(f))>=0?n=(n<<4)+c:Tr(e,\"expected hexadecimal character\");e.result+=c5e(n),e.position++}else Tr(e,\"unknown escape sequence\");r=s=e.position}else qf(f)?(t0(e,r,s,!0),LU(e,ls(e,!1,t)),r=s=e.position):e.position===e.lineStart&&Cx(e)?Tr(e,\"unexpected end of the document within a double quoted scalar\"):(e.position++,s=e.position)}Tr(e,\"unexpected end of the stream within a double quoted scalar\")}function h5e(e,t){var r=!0,s,a=e.tag,n,c=e.anchor,f,p,h,E,C,S={},x,I,T,O;if(O=e.input.charCodeAt(e.position),O===91)p=93,C=!1,n=[];else if(O===123)p=125,C=!0,n={};else return!1;for(e.anchor!==null&&(e.anchorMap[e.anchor]=n),O=e.input.charCodeAt(++e.position);O!==0;){if(ls(e,!0,t),O=e.input.charCodeAt(e.position),O===p)return e.position++,e.tag=a,e.anchor=c,e.kind=C?\"mapping\":\"sequence\",e.result=n,!0;r||Tr(e,\"missed comma between flow collection entries\"),I=x=T=null,h=E=!1,O===63&&(f=e.input.charCodeAt(e.position+1),ll(f)&&(h=E=!0,e.position++,ls(e,!0,t))),s=e.line,CE(e,t,yx,!1,!0),I=e.tag,x=e.result,ls(e,!0,t),O=e.input.charCodeAt(e.position),(E||e.line===s)&&O===58&&(h=!0,O=e.input.charCodeAt(++e.position),ls(e,!0,t),CE(e,t,yx,!1,!0),T=e.result),C?IE(e,n,S,I,x,T):h?n.push(IE(e,null,S,I,x,T)):n.push(x),ls(e,!0,t),O=e.input.charCodeAt(e.position),O===44?(r=!0,O=e.input.charCodeAt(++e.position)):r=!1}Tr(e,\"unexpected end of the stream within a flow collection\")}function g5e(e,t){var r,s,a=NU,n=!1,c=!1,f=t,p=0,h=!1,E,C;if(C=e.input.charCodeAt(e.position),C===124)s=!1;else if(C===62)s=!0;else return!1;for(e.kind=\"scalar\",e.result=\"\";C!==0;)if(C=e.input.charCodeAt(++e.position),C===43||C===45)NU===a?a=C===43?jee:r5e:Tr(e,\"repeat of a chomping mode identifier\");else if((E=l5e(C))>=0)E===0?Tr(e,\"bad explicit indentation width of a block scalar; it cannot be less than one\"):c?Tr(e,\"repeat of an indentation width identifier\"):(f=t+E-1,c=!0);else break;if(xd(C)){do C=e.input.charCodeAt(++e.position);while(xd(C));if(C===35)do C=e.input.charCodeAt(++e.position);while(!qf(C)&&C!==0)}for(;C!==0;){for(OU(e),e.lineIndent=0,C=e.input.charCodeAt(e.position);(!c||e.lineIndent<f)&&C===32;)e.lineIndent++,C=e.input.charCodeAt(++e.position);if(!c&&e.lineIndent>f&&(f=e.lineIndent),qf(C)){p++;continue}if(e.lineIndent<f){a===jee?e.result+=Cp.repeat(`\n`,n?1+p:p):a===NU&&n&&(e.result+=`\n`);break}for(s?xd(C)?(h=!0,e.result+=Cp.repeat(`\n`,n?1+p:p)):h?(h=!1,e.result+=Cp.repeat(`\n`,p+1)):p===0?n&&(e.result+=\" \"):e.result+=Cp.repeat(`\n`,p):e.result+=Cp.repeat(`\n`,n?1+p:p),n=!0,c=!0,p=0,r=e.position;!qf(C)&&C!==0;)C=e.input.charCodeAt(++e.position);t0(e,r,e.position,!1)}return!0}function Yee(e,t){var r,s=e.tag,a=e.anchor,n=[],c,f=!1,p;for(e.anchor!==null&&(e.anchorMap[e.anchor]=n),p=e.input.charCodeAt(e.position);p!==0&&!(p!==45||(c=e.input.charCodeAt(e.position+1),!ll(c)));){if(f=!0,e.position++,ls(e,!0,-1)&&e.lineIndent<=t){n.push(null),p=e.input.charCodeAt(e.position);continue}if(r=e.line,CE(e,t,Zee,!1,!0),n.push(e.result),ls(e,!0,-1),p=e.input.charCodeAt(e.position),(e.line===r||e.lineIndent>t)&&p!==0)Tr(e,\"bad indentation of a sequence entry\");else if(e.lineIndent<t)break}return f?(e.tag=s,e.anchor=a,e.kind=\"sequence\",e.result=n,!0):!1}function d5e(e,t,r){var s,a,n,c,f=e.tag,p=e.anchor,h={},E={},C=null,S=null,x=null,I=!1,T=!1,O;for(e.anchor!==null&&(e.anchorMap[e.anchor]=h),O=e.input.charCodeAt(e.position);O!==0;){if(s=e.input.charCodeAt(e.position+1),n=e.line,c=e.position,(O===63||O===58)&&ll(s))O===63?(I&&(IE(e,h,E,C,S,null),C=S=x=null),T=!0,I=!0,a=!0):I?(I=!1,a=!0):Tr(e,\"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line\"),e.position+=1,O=s;else if(CE(e,r,zee,!1,!0))if(e.line===n){for(O=e.input.charCodeAt(e.position);xd(O);)O=e.input.charCodeAt(++e.position);if(O===58)O=e.input.charCodeAt(++e.position),ll(O)||Tr(e,\"a whitespace character is expected after the key-value separator within a block mapping\"),I&&(IE(e,h,E,C,S,null),C=S=x=null),T=!0,I=!1,a=!1,C=e.tag,S=e.result;else if(T)Tr(e,\"can not read an implicit mapping pair; a colon is missed\");else return e.tag=f,e.anchor=p,!0}else if(T)Tr(e,\"can not read a block mapping entry; a multiline key may not be an implicit key\");else return e.tag=f,e.anchor=p,!0;else break;if((e.line===n||e.lineIndent>t)&&(CE(e,t,Ex,!0,a)&&(I?S=e.result:x=e.result),I||(IE(e,h,E,C,S,x,n,c),C=S=x=null),ls(e,!0,-1),O=e.input.charCodeAt(e.position)),e.lineIndent>t&&O!==0)Tr(e,\"bad indentation of a mapping entry\");else if(e.lineIndent<t)break}return I&&IE(e,h,E,C,S,null),T&&(e.tag=f,e.anchor=p,e.kind=\"mapping\",e.result=h),T}function m5e(e){var t,r=!1,s=!1,a,n,c;if(c=e.input.charCodeAt(e.position),c!==33)return!1;if(e.tag!==null&&Tr(e,\"duplication of a tag property\"),c=e.input.charCodeAt(++e.position),c===60?(r=!0,c=e.input.charCodeAt(++e.position)):c===33?(s=!0,a=\"!!\",c=e.input.charCodeAt(++e.position)):a=\"!\",t=e.position,r){do c=e.input.charCodeAt(++e.position);while(c!==0&&c!==62);e.position<e.length?(n=e.input.slice(t,e.position),c=e.input.charCodeAt(++e.position)):Tr(e,\"unexpected end of the stream within a verbatim tag\")}else{for(;c!==0&&!ll(c);)c===33&&(s?Tr(e,\"tag suffix cannot contain exclamation marks\"):(a=e.input.slice(t-1,e.position+1),Xee.test(a)||Tr(e,\"named tag handle cannot contain such characters\"),s=!0,t=e.position+1)),c=e.input.charCodeAt(++e.position);n=e.input.slice(t,e.position),s5e.test(n)&&Tr(e,\"tag suffix cannot contain flow indicator characters\")}return n&&!$ee.test(n)&&Tr(e,\"tag name cannot contain such characters: \"+n),r?e.tag=n:r0.call(e.tagMap,a)?e.tag=e.tagMap[a]+n:a===\"!\"?e.tag=\"!\"+n:a===\"!!\"?e.tag=\"tag:yaml.org,2002:\"+n:Tr(e,'undeclared tag handle \"'+a+'\"'),!0}function y5e(e){var t,r;if(r=e.input.charCodeAt(e.position),r!==38)return!1;for(e.anchor!==null&&Tr(e,\"duplication of an anchor property\"),r=e.input.charCodeAt(++e.position),t=e.position;r!==0&&!ll(r)&&!EE(r);)r=e.input.charCodeAt(++e.position);return e.position===t&&Tr(e,\"name of an anchor node must contain at least one character\"),e.anchor=e.input.slice(t,e.position),!0}function E5e(e){var t,r,s;if(s=e.input.charCodeAt(e.position),s!==42)return!1;for(s=e.input.charCodeAt(++e.position),t=e.position;s!==0&&!ll(s)&&!EE(s);)s=e.input.charCodeAt(++e.position);return e.position===t&&Tr(e,\"name of an alias node must contain at least one character\"),r=e.input.slice(t,e.position),r0.call(e.anchorMap,r)||Tr(e,'unidentified alias \"'+r+'\"'),e.result=e.anchorMap[r],ls(e,!0,-1),!0}function CE(e,t,r,s,a){var n,c,f,p=1,h=!1,E=!1,C,S,x,I,T;if(e.listener!==null&&e.listener(\"open\",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null,n=c=f=Ex===r||Zee===r,s&&ls(e,!0,-1)&&(h=!0,e.lineIndent>t?p=1:e.lineIndent===t?p=0:e.lineIndent<t&&(p=-1)),p===1)for(;m5e(e)||y5e(e);)ls(e,!0,-1)?(h=!0,f=n,e.lineIndent>t?p=1:e.lineIndent===t?p=0:e.lineIndent<t&&(p=-1)):f=!1;if(f&&(f=h||a),(p===1||Ex===r)&&(yx===r||zee===r?I=t:I=t+1,T=e.position-e.lineStart,p===1?f&&(Yee(e,T)||d5e(e,T,I))||h5e(e,I)?E=!0:(c&&g5e(e,I)||A5e(e,I)||p5e(e,I)?E=!0:E5e(e)?(E=!0,(e.tag!==null||e.anchor!==null)&&Tr(e,\"alias node should not have any properties\")):f5e(e,I,yx===r)&&(E=!0,e.tag===null&&(e.tag=\"?\")),e.anchor!==null&&(e.anchorMap[e.anchor]=e.result)):p===0&&(E=f&&Yee(e,T))),e.tag!==null&&e.tag!==\"!\")if(e.tag===\"?\"){for(e.result!==null&&e.kind!==\"scalar\"&&Tr(e,'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"'+e.kind+'\"'),C=0,S=e.implicitTypes.length;C<S;C+=1)if(x=e.implicitTypes[C],x.resolve(e.result)){e.result=x.construct(e.result),e.tag=x.tag,e.anchor!==null&&(e.anchorMap[e.anchor]=e.result);break}}else r0.call(e.typeMap[e.kind||\"fallback\"],e.tag)?(x=e.typeMap[e.kind||\"fallback\"][e.tag],e.result!==null&&x.kind!==e.kind&&Tr(e,\"unacceptable node kind for !<\"+e.tag+'> tag; it should be \"'+x.kind+'\", not \"'+e.kind+'\"'),x.resolve(e.result)?(e.result=x.construct(e.result),e.anchor!==null&&(e.anchorMap[e.anchor]=e.result)):Tr(e,\"cannot resolve a node with !<\"+e.tag+\"> explicit tag\")):Tr(e,\"unknown tag !<\"+e.tag+\">\");return e.listener!==null&&e.listener(\"close\",e),e.tag!==null||e.anchor!==null||E}function I5e(e){var t=e.position,r,s,a,n=!1,c;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap={},e.anchorMap={};(c=e.input.charCodeAt(e.position))!==0&&(ls(e,!0,-1),c=e.input.charCodeAt(e.position),!(e.lineIndent>0||c!==37));){for(n=!0,c=e.input.charCodeAt(++e.position),r=e.position;c!==0&&!ll(c);)c=e.input.charCodeAt(++e.position);for(s=e.input.slice(r,e.position),a=[],s.length<1&&Tr(e,\"directive name must not be less than one character in length\");c!==0;){for(;xd(c);)c=e.input.charCodeAt(++e.position);if(c===35){do c=e.input.charCodeAt(++e.position);while(c!==0&&!qf(c));break}if(qf(c))break;for(r=e.position;c!==0&&!ll(c);)c=e.input.charCodeAt(++e.position);a.push(e.input.slice(r,e.position))}c!==0&&OU(e),r0.call(Wee,s)?Wee[s](e,s,a):Ix(e,'unknown document directive \"'+s+'\"')}if(ls(e,!0,-1),e.lineIndent===0&&e.input.charCodeAt(e.position)===45&&e.input.charCodeAt(e.position+1)===45&&e.input.charCodeAt(e.position+2)===45?(e.position+=3,ls(e,!0,-1)):n&&Tr(e,\"directives end mark is expected\"),CE(e,e.lineIndent-1,Ex,!1,!0),ls(e,!0,-1),e.checkLineBreaks&&i5e.test(e.input.slice(t,e.position))&&Ix(e,\"non-ASCII line breaks are interpreted as content\"),e.documents.push(e.result),e.position===e.lineStart&&Cx(e)){e.input.charCodeAt(e.position)===46&&(e.position+=3,ls(e,!0,-1));return}if(e.position<e.length-1)Tr(e,\"end of the stream or a document separator is expected\");else return}function nte(e,t){e=String(e),t=t||{},e.length!==0&&(e.charCodeAt(e.length-1)!==10&&e.charCodeAt(e.length-1)!==13&&(e+=`\n`),e.charCodeAt(0)===65279&&(e=e.slice(1)));var r=new u5e(e,t),s=e.indexOf(\"\\0\");for(s!==-1&&(r.position=s,Tr(r,\"null byte is not allowed in input\")),r.input+=\"\\0\";r.input.charCodeAt(r.position)===32;)r.lineIndent+=1,r.position+=1;for(;r.position<r.length-1;)I5e(r);return r.documents}function ite(e,t,r){t!==null&&typeof t==\"object\"&&typeof r>\"u\"&&(r=t,t=null);var s=nte(e,r);if(typeof t!=\"function\")return s;for(var a=0,n=s.length;a<n;a+=1)t(s[a])}function ste(e,t){var r=nte(e,t);if(r.length!==0){if(r.length===1)return r[0];throw new Kee(\"expected a single document in the stream, but found more\")}}function C5e(e,t,r){return typeof t==\"object\"&&t!==null&&typeof r>\"u\"&&(r=t,t=null),ite(e,t,Cp.extend({schema:Jee},r))}function w5e(e,t){return ste(e,Cp.extend({schema:Jee},t))}OB.exports.loadAll=ite;OB.exports.load=ste;OB.exports.safeLoadAll=C5e;OB.exports.safeLoad=w5e});var xte=G((WPt,HU)=>{\"use strict\";var MB=Sd(),UB=dE(),B5e=NB(),v5e=yE(),hte=Object.prototype.toString,gte=Object.prototype.hasOwnProperty,S5e=9,LB=10,D5e=13,b5e=32,P5e=33,x5e=34,dte=35,k5e=37,Q5e=38,R5e=39,T5e=42,mte=44,F5e=45,yte=58,N5e=61,O5e=62,L5e=63,M5e=64,Ete=91,Ite=93,U5e=96,Cte=123,_5e=124,wte=125,Wo={};Wo[0]=\"\\\\0\";Wo[7]=\"\\\\a\";Wo[8]=\"\\\\b\";Wo[9]=\"\\\\t\";Wo[10]=\"\\\\n\";Wo[11]=\"\\\\v\";Wo[12]=\"\\\\f\";Wo[13]=\"\\\\r\";Wo[27]=\"\\\\e\";Wo[34]='\\\\\"';Wo[92]=\"\\\\\\\\\";Wo[133]=\"\\\\N\";Wo[160]=\"\\\\_\";Wo[8232]=\"\\\\L\";Wo[8233]=\"\\\\P\";var H5e=[\"y\",\"Y\",\"yes\",\"Yes\",\"YES\",\"on\",\"On\",\"ON\",\"n\",\"N\",\"no\",\"No\",\"NO\",\"off\",\"Off\",\"OFF\"];function j5e(e,t){var r,s,a,n,c,f,p;if(t===null)return{};for(r={},s=Object.keys(t),a=0,n=s.length;a<n;a+=1)c=s[a],f=String(t[c]),c.slice(0,2)===\"!!\"&&(c=\"tag:yaml.org,2002:\"+c.slice(2)),p=e.compiledTypeMap.fallback[c],p&&gte.call(p.styleAliases,f)&&(f=p.styleAliases[f]),r[c]=f;return r}function ate(e){var t,r,s;if(t=e.toString(16).toUpperCase(),e<=255)r=\"x\",s=2;else if(e<=65535)r=\"u\",s=4;else if(e<=4294967295)r=\"U\",s=8;else throw new UB(\"code point within a string may not be greater than 0xFFFFFFFF\");return\"\\\\\"+r+MB.repeat(\"0\",s-t.length)+t}function G5e(e){this.schema=e.schema||B5e,this.indent=Math.max(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=MB.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=j5e(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result=\"\",this.duplicates=[],this.usedDuplicates=null}function lte(e,t){for(var r=MB.repeat(\" \",t),s=0,a=-1,n=\"\",c,f=e.length;s<f;)a=e.indexOf(`\n`,s),a===-1?(c=e.slice(s),s=f):(c=e.slice(s,a+1),s=a+1),c.length&&c!==`\n`&&(n+=r),n+=c;return n}function MU(e,t){return`\n`+MB.repeat(\" \",e.indent*t)}function q5e(e,t){var r,s,a;for(r=0,s=e.implicitTypes.length;r<s;r+=1)if(a=e.implicitTypes[r],a.resolve(t))return!0;return!1}function _U(e){return e===b5e||e===S5e}function wE(e){return 32<=e&&e<=126||161<=e&&e<=55295&&e!==8232&&e!==8233||57344<=e&&e<=65533&&e!==65279||65536<=e&&e<=1114111}function W5e(e){return wE(e)&&!_U(e)&&e!==65279&&e!==D5e&&e!==LB}function cte(e,t){return wE(e)&&e!==65279&&e!==mte&&e!==Ete&&e!==Ite&&e!==Cte&&e!==wte&&e!==yte&&(e!==dte||t&&W5e(t))}function V5e(e){return wE(e)&&e!==65279&&!_U(e)&&e!==F5e&&e!==L5e&&e!==yte&&e!==mte&&e!==Ete&&e!==Ite&&e!==Cte&&e!==wte&&e!==dte&&e!==Q5e&&e!==T5e&&e!==P5e&&e!==_5e&&e!==N5e&&e!==O5e&&e!==R5e&&e!==x5e&&e!==k5e&&e!==M5e&&e!==U5e}function Bte(e){var t=/^\\n* /;return t.test(e)}var vte=1,Ste=2,Dte=3,bte=4,wx=5;function Y5e(e,t,r,s,a){var n,c,f,p=!1,h=!1,E=s!==-1,C=-1,S=V5e(e.charCodeAt(0))&&!_U(e.charCodeAt(e.length-1));if(t)for(n=0;n<e.length;n++){if(c=e.charCodeAt(n),!wE(c))return wx;f=n>0?e.charCodeAt(n-1):null,S=S&&cte(c,f)}else{for(n=0;n<e.length;n++){if(c=e.charCodeAt(n),c===LB)p=!0,E&&(h=h||n-C-1>s&&e[C+1]!==\" \",C=n);else if(!wE(c))return wx;f=n>0?e.charCodeAt(n-1):null,S=S&&cte(c,f)}h=h||E&&n-C-1>s&&e[C+1]!==\" \"}return!p&&!h?S&&!a(e)?vte:Ste:r>9&&Bte(e)?wx:h?bte:Dte}function K5e(e,t,r,s){e.dump=function(){if(t.length===0)return\"''\";if(!e.noCompatMode&&H5e.indexOf(t)!==-1)return\"'\"+t+\"'\";var a=e.indent*Math.max(1,r),n=e.lineWidth===-1?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-a),c=s||e.flowLevel>-1&&r>=e.flowLevel;function f(p){return q5e(e,p)}switch(Y5e(t,c,e.indent,n,f)){case vte:return t;case Ste:return\"'\"+t.replace(/'/g,\"''\")+\"'\";case Dte:return\"|\"+ute(t,e.indent)+fte(lte(t,a));case bte:return\">\"+ute(t,e.indent)+fte(lte(J5e(t,n),a));case wx:return'\"'+z5e(t,n)+'\"';default:throw new UB(\"impossible error: invalid scalar style\")}}()}function ute(e,t){var r=Bte(e)?String(t):\"\",s=e[e.length-1]===`\n`,a=s&&(e[e.length-2]===`\n`||e===`\n`),n=a?\"+\":s?\"\":\"-\";return r+n+`\n`}function fte(e){return e[e.length-1]===`\n`?e.slice(0,-1):e}function J5e(e,t){for(var r=/(\\n+)([^\\n]*)/g,s=function(){var h=e.indexOf(`\n`);return h=h!==-1?h:e.length,r.lastIndex=h,Ate(e.slice(0,h),t)}(),a=e[0]===`\n`||e[0]===\" \",n,c;c=r.exec(e);){var f=c[1],p=c[2];n=p[0]===\" \",s+=f+(!a&&!n&&p!==\"\"?`\n`:\"\")+Ate(p,t),a=n}return s}function Ate(e,t){if(e===\"\"||e[0]===\" \")return e;for(var r=/ [^ ]/g,s,a=0,n,c=0,f=0,p=\"\";s=r.exec(e);)f=s.index,f-a>t&&(n=c>a?c:f,p+=`\n`+e.slice(a,n),a=n+1),c=f;return p+=`\n`,e.length-a>t&&c>a?p+=e.slice(a,c)+`\n`+e.slice(c+1):p+=e.slice(a),p.slice(1)}function z5e(e){for(var t=\"\",r,s,a,n=0;n<e.length;n++){if(r=e.charCodeAt(n),r>=55296&&r<=56319&&(s=e.charCodeAt(n+1),s>=56320&&s<=57343)){t+=ate((r-55296)*1024+s-56320+65536),n++;continue}a=Wo[r],t+=!a&&wE(r)?e[n]:a||ate(r)}return t}function Z5e(e,t,r){var s=\"\",a=e.tag,n,c;for(n=0,c=r.length;n<c;n+=1)kd(e,t,r[n],!1,!1)&&(n!==0&&(s+=\",\"+(e.condenseFlow?\"\":\" \")),s+=e.dump);e.tag=a,e.dump=\"[\"+s+\"]\"}function X5e(e,t,r,s){var a=\"\",n=e.tag,c,f;for(c=0,f=r.length;c<f;c+=1)kd(e,t+1,r[c],!0,!0)&&((!s||c!==0)&&(a+=MU(e,t)),e.dump&&LB===e.dump.charCodeAt(0)?a+=\"-\":a+=\"- \",a+=e.dump);e.tag=n,e.dump=a||\"[]\"}function $5e(e,t,r){var s=\"\",a=e.tag,n=Object.keys(r),c,f,p,h,E;for(c=0,f=n.length;c<f;c+=1)E=\"\",c!==0&&(E+=\", \"),e.condenseFlow&&(E+='\"'),p=n[c],h=r[p],kd(e,t,p,!1,!1)&&(e.dump.length>1024&&(E+=\"? \"),E+=e.dump+(e.condenseFlow?'\"':\"\")+\":\"+(e.condenseFlow?\"\":\" \"),kd(e,t,h,!1,!1)&&(E+=e.dump,s+=E));e.tag=a,e.dump=\"{\"+s+\"}\"}function eqe(e,t,r,s){var a=\"\",n=e.tag,c=Object.keys(r),f,p,h,E,C,S;if(e.sortKeys===!0)c.sort();else if(typeof e.sortKeys==\"function\")c.sort(e.sortKeys);else if(e.sortKeys)throw new UB(\"sortKeys must be a boolean or a function\");for(f=0,p=c.length;f<p;f+=1)S=\"\",(!s||f!==0)&&(S+=MU(e,t)),h=c[f],E=r[h],kd(e,t+1,h,!0,!0,!0)&&(C=e.tag!==null&&e.tag!==\"?\"||e.dump&&e.dump.length>1024,C&&(e.dump&&LB===e.dump.charCodeAt(0)?S+=\"?\":S+=\"? \"),S+=e.dump,C&&(S+=MU(e,t)),kd(e,t+1,E,!0,C)&&(e.dump&&LB===e.dump.charCodeAt(0)?S+=\":\":S+=\": \",S+=e.dump,a+=S));e.tag=n,e.dump=a||\"{}\"}function pte(e,t,r){var s,a,n,c,f,p;for(a=r?e.explicitTypes:e.implicitTypes,n=0,c=a.length;n<c;n+=1)if(f=a[n],(f.instanceOf||f.predicate)&&(!f.instanceOf||typeof t==\"object\"&&t instanceof f.instanceOf)&&(!f.predicate||f.predicate(t))){if(e.tag=r?f.tag:\"?\",f.represent){if(p=e.styleMap[f.tag]||f.defaultStyle,hte.call(f.represent)===\"[object Function]\")s=f.represent(t,p);else if(gte.call(f.represent,p))s=f.represent[p](t,p);else throw new UB(\"!<\"+f.tag+'> tag resolver accepts not \"'+p+'\" style');e.dump=s}return!0}return!1}function kd(e,t,r,s,a,n){e.tag=null,e.dump=r,pte(e,r,!1)||pte(e,r,!0);var c=hte.call(e.dump);s&&(s=e.flowLevel<0||e.flowLevel>t);var f=c===\"[object Object]\"||c===\"[object Array]\",p,h;if(f&&(p=e.duplicates.indexOf(r),h=p!==-1),(e.tag!==null&&e.tag!==\"?\"||h||e.indent!==2&&t>0)&&(a=!1),h&&e.usedDuplicates[p])e.dump=\"*ref_\"+p;else{if(f&&h&&!e.usedDuplicates[p]&&(e.usedDuplicates[p]=!0),c===\"[object Object]\")s&&Object.keys(e.dump).length!==0?(eqe(e,t,e.dump,a),h&&(e.dump=\"&ref_\"+p+e.dump)):($5e(e,t,e.dump),h&&(e.dump=\"&ref_\"+p+\" \"+e.dump));else if(c===\"[object Array]\"){var E=e.noArrayIndent&&t>0?t-1:t;s&&e.dump.length!==0?(X5e(e,E,e.dump,a),h&&(e.dump=\"&ref_\"+p+e.dump)):(Z5e(e,E,e.dump),h&&(e.dump=\"&ref_\"+p+\" \"+e.dump))}else if(c===\"[object String]\")e.tag!==\"?\"&&K5e(e,e.dump,t,n);else{if(e.skipInvalid)return!1;throw new UB(\"unacceptable kind of an object to dump \"+c)}e.tag!==null&&e.tag!==\"?\"&&(e.dump=\"!<\"+e.tag+\"> \"+e.dump)}return!0}function tqe(e,t){var r=[],s=[],a,n;for(UU(e,r,s),a=0,n=s.length;a<n;a+=1)t.duplicates.push(r[s[a]]);t.usedDuplicates=new Array(n)}function UU(e,t,r){var s,a,n;if(e!==null&&typeof e==\"object\")if(a=t.indexOf(e),a!==-1)r.indexOf(a)===-1&&r.push(a);else if(t.push(e),Array.isArray(e))for(a=0,n=e.length;a<n;a+=1)UU(e[a],t,r);else for(s=Object.keys(e),a=0,n=s.length;a<n;a+=1)UU(e[s[a]],t,r)}function Pte(e,t){t=t||{};var r=new G5e(t);return r.noRefs||tqe(e,r),kd(r,0,e,!0,!0)?r.dump+`\n`:\"\"}function rqe(e,t){return Pte(e,MB.extend({schema:v5e},t))}HU.exports.dump=Pte;HU.exports.safeDump=rqe});var Qte=G((VPt,Wi)=>{\"use strict\";var Bx=ote(),kte=xte();function vx(e){return function(){throw new Error(\"Function \"+e+\" is deprecated and cannot be used.\")}}Wi.exports.Type=Ps();Wi.exports.Schema=Dd();Wi.exports.FAILSAFE_SCHEMA=dx();Wi.exports.JSON_SCHEMA=RU();Wi.exports.CORE_SCHEMA=TU();Wi.exports.DEFAULT_SAFE_SCHEMA=yE();Wi.exports.DEFAULT_FULL_SCHEMA=NB();Wi.exports.load=Bx.load;Wi.exports.loadAll=Bx.loadAll;Wi.exports.safeLoad=Bx.safeLoad;Wi.exports.safeLoadAll=Bx.safeLoadAll;Wi.exports.dump=kte.dump;Wi.exports.safeDump=kte.safeDump;Wi.exports.YAMLException=dE();Wi.exports.MINIMAL_SCHEMA=dx();Wi.exports.SAFE_SCHEMA=yE();Wi.exports.DEFAULT_SCHEMA=NB();Wi.exports.scan=vx(\"scan\");Wi.exports.parse=vx(\"parse\");Wi.exports.compose=vx(\"compose\");Wi.exports.addConstructor=vx(\"addConstructor\")});var Tte=G((YPt,Rte)=>{\"use strict\";var nqe=Qte();Rte.exports=nqe});var Nte=G((KPt,Fte)=>{\"use strict\";function iqe(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}function Qd(e,t,r,s){this.message=e,this.expected=t,this.found=r,this.location=s,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,Qd)}iqe(Qd,Error);Qd.buildMessage=function(e,t){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",C;for(C=0;C<h.parts.length;C++)E+=h.parts[C]instanceof Array?n(h.parts[C][0])+\"-\"+n(h.parts[C][1]):n(h.parts[C]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function s(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function c(h){return r[h.type](h)}function f(h){var E=new Array(h.length),C,S;for(C=0;C<h.length;C++)E[C]=c(h[C]);if(E.sort(),E.length>0){for(C=1,S=1;C<E.length;C++)E[C-1]!==E[C]&&(E[S]=E[C],S++);E.length=S}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+f(e)+\" but \"+p(t)+\" found.\"};function sqe(e,t){t=t!==void 0?t:{};var r={},s={Start:cc},a=cc,n=function(ee){return[].concat(...ee)},c=\"-\",f=mn(\"-\",!1),p=function(ee){return ee},h=function(ee){return Object.assign({},...ee)},E=\"#\",C=mn(\"#\",!1),S=uu(),x=function(){return{}},I=\":\",T=mn(\":\",!1),O=function(ee,ye){return{[ee]:ye}},U=\",\",Y=mn(\",\",!1),te=function(ee,ye){return ye},ie=function(ee,ye,Oe){return Object.assign({},...[ee].concat(ye).map(mt=>({[mt]:Oe})))},ue=function(ee){return ee},ae=function(ee){return ee},de=Ga(\"correct indentation\"),Ae=\" \",Ce=mn(\" \",!1),Ee=function(ee){return ee.length===lr*St},g=function(ee){return ee.length===(lr+1)*St},Se=function(){return lr++,!0},Be=function(){return lr--,!0},me=function(){return Aa()},ce=Ga(\"pseudostring\"),X=/^[^\\r\\n\\t ?:,\\][{}#&*!|>'\"%@`\\-]/,De=Zn([\"\\r\",`\n`,\"\t\",\" \",\"?\",\":\",\",\",\"]\",\"[\",\"{\",\"}\",\"#\",\"&\",\"*\",\"!\",\"|\",\">\",\"'\",'\"',\"%\",\"@\",\"`\",\"-\"],!0,!1),Qe=/^[^\\r\\n\\t ,\\][{}:#\"']/,it=Zn([\"\\r\",`\n`,\"\t\",\" \",\",\",\"]\",\"[\",\"{\",\"}\",\":\",\"#\",'\"',\"'\"],!0,!1),_=function(){return Aa().replace(/^ *| *$/g,\"\")},tt=\"--\",Ne=mn(\"--\",!1),ke=/^[a-zA-Z\\/0-9]/,be=Zn([[\"a\",\"z\"],[\"A\",\"Z\"],\"/\",[\"0\",\"9\"]],!1,!1),je=/^[^\\r\\n\\t :,]/,Re=Zn([\"\\r\",`\n`,\"\t\",\" \",\":\",\",\"],!0,!1),ct=\"null\",Me=mn(\"null\",!1),P=function(){return null},w=\"true\",b=mn(\"true\",!1),y=function(){return!0},F=\"false\",z=mn(\"false\",!1),Z=function(){return!1},$=Ga(\"string\"),se='\"',xe=mn('\"',!1),Fe=function(){return\"\"},ut=function(ee){return ee},Ct=function(ee){return ee.join(\"\")},qt=/^[^\"\\\\\\0-\\x1F\\x7F]/,ir=Zn(['\"',\"\\\\\",[\"\\0\",\"\u001f\"],\"\\x7F\"],!0,!1),Pt='\\\\\"',dn=mn('\\\\\"',!1),Pr=function(){return'\"'},Ir=\"\\\\\\\\\",Or=mn(\"\\\\\\\\\",!1),on=function(){return\"\\\\\"},li=\"\\\\/\",So=mn(\"\\\\/\",!1),ns=function(){return\"/\"},so=\"\\\\b\",Do=mn(\"\\\\b\",!1),ji=function(){return\"\\b\"},oo=\"\\\\f\",bo=mn(\"\\\\f\",!1),RA=function(){return\"\\f\"},hf=\"\\\\n\",hh=mn(\"\\\\n\",!1),gh=function(){return`\n`},ao=\"\\\\r\",Gn=mn(\"\\\\r\",!1),Ns=function(){return\"\\r\"},lo=\"\\\\t\",iu=mn(\"\\\\t\",!1),su=function(){return\"\t\"},ou=\"\\\\u\",TA=mn(\"\\\\u\",!1),FA=function(ee,ye,Oe,mt){return String.fromCharCode(parseInt(`0x${ee}${ye}${Oe}${mt}`))},ua=/^[0-9a-fA-F]/,fa=Zn([[\"0\",\"9\"],[\"a\",\"f\"],[\"A\",\"F\"]],!1,!1),NA=Ga(\"blank space\"),gr=/^[ \\t]/,Po=Zn([\" \",\"\t\"],!1,!1),Ue=Ga(\"white space\"),au=/^[ \\t\\n\\r]/,Cr=Zn([\" \",\"\t\",`\n`,\"\\r\"],!1,!1),gf=`\\r\n`,OA=mn(`\\r\n`,!1),LA=`\n`,lu=mn(`\n`,!1),cu=\"\\r\",ac=mn(\"\\r\",!1),we=0,Nt=0,lc=[{line:1,column:1}],Oi=0,co=[],Tt=0,Qn;if(\"startRule\"in t){if(!(t.startRule in s))throw new Error(`Can't start parsing from rule \"`+t.startRule+'\".');a=s[t.startRule]}function Aa(){return e.substring(Nt,we)}function Gi(){return Wa(Nt,we)}function Li(ee,ye){throw ye=ye!==void 0?ye:Wa(Nt,we),df([Ga(ee)],e.substring(Nt,we),ye)}function ja(ee,ye){throw ye=ye!==void 0?ye:Wa(Nt,we),Va(ee,ye)}function mn(ee,ye){return{type:\"literal\",text:ee,ignoreCase:ye}}function Zn(ee,ye,Oe){return{type:\"class\",parts:ee,inverted:ye,ignoreCase:Oe}}function uu(){return{type:\"any\"}}function dh(){return{type:\"end\"}}function Ga(ee){return{type:\"other\",description:ee}}function qa(ee){var ye=lc[ee],Oe;if(ye)return ye;for(Oe=ee-1;!lc[Oe];)Oe--;for(ye=lc[Oe],ye={line:ye.line,column:ye.column};Oe<ee;)e.charCodeAt(Oe)===10?(ye.line++,ye.column=1):ye.column++,Oe++;return lc[ee]=ye,ye}function Wa(ee,ye){var Oe=qa(ee),mt=qa(ye);return{start:{offset:ee,line:Oe.line,column:Oe.column},end:{offset:ye,line:mt.line,column:mt.column}}}function $e(ee){we<Oi||(we>Oi&&(Oi=we,co=[]),co.push(ee))}function Va(ee,ye){return new Qd(ee,null,null,ye)}function df(ee,ye,Oe){return new Qd(Qd.buildMessage(ee,ye),ee,ye,Oe)}function cc(){var ee;return ee=MA(),ee}function vn(){var ee,ye,Oe;for(ee=we,ye=[],Oe=pa();Oe!==r;)ye.push(Oe),Oe=pa();return ye!==r&&(Nt=ee,ye=n(ye)),ee=ye,ee}function pa(){var ee,ye,Oe,mt,Et;return ee=we,ye=xl(),ye!==r?(e.charCodeAt(we)===45?(Oe=c,we++):(Oe=r,Tt===0&&$e(f)),Oe!==r?(mt=Tn(),mt!==r?(Et=ha(),Et!==r?(Nt=ee,ye=p(Et),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee}function MA(){var ee,ye,Oe;for(ee=we,ye=[],Oe=UA();Oe!==r;)ye.push(Oe),Oe=UA();return ye!==r&&(Nt=ee,ye=h(ye)),ee=ye,ee}function UA(){var ee,ye,Oe,mt,Et,bt,tr,pn,ci;if(ee=we,ye=Tn(),ye===r&&(ye=null),ye!==r){if(Oe=we,e.charCodeAt(we)===35?(mt=E,we++):(mt=r,Tt===0&&$e(C)),mt!==r){if(Et=[],bt=we,tr=we,Tt++,pn=ot(),Tt--,pn===r?tr=void 0:(we=tr,tr=r),tr!==r?(e.length>we?(pn=e.charAt(we),we++):(pn=r,Tt===0&&$e(S)),pn!==r?(tr=[tr,pn],bt=tr):(we=bt,bt=r)):(we=bt,bt=r),bt!==r)for(;bt!==r;)Et.push(bt),bt=we,tr=we,Tt++,pn=ot(),Tt--,pn===r?tr=void 0:(we=tr,tr=r),tr!==r?(e.length>we?(pn=e.charAt(we),we++):(pn=r,Tt===0&&$e(S)),pn!==r?(tr=[tr,pn],bt=tr):(we=bt,bt=r)):(we=bt,bt=r);else Et=r;Et!==r?(mt=[mt,Et],Oe=mt):(we=Oe,Oe=r)}else we=Oe,Oe=r;if(Oe===r&&(Oe=null),Oe!==r){if(mt=[],Et=Je(),Et!==r)for(;Et!==r;)mt.push(Et),Et=Je();else mt=r;mt!==r?(Nt=ee,ye=x(),ee=ye):(we=ee,ee=r)}else we=ee,ee=r}else we=ee,ee=r;if(ee===r&&(ee=we,ye=xl(),ye!==r?(Oe=Ya(),Oe!==r?(mt=Tn(),mt===r&&(mt=null),mt!==r?(e.charCodeAt(we)===58?(Et=I,we++):(Et=r,Tt===0&&$e(T)),Et!==r?(bt=Tn(),bt===r&&(bt=null),bt!==r?(tr=ha(),tr!==r?(Nt=ee,ye=O(Oe,tr),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r&&(ee=we,ye=xl(),ye!==r?(Oe=is(),Oe!==r?(mt=Tn(),mt===r&&(mt=null),mt!==r?(e.charCodeAt(we)===58?(Et=I,we++):(Et=r,Tt===0&&$e(T)),Et!==r?(bt=Tn(),bt===r&&(bt=null),bt!==r?(tr=ha(),tr!==r?(Nt=ee,ye=O(Oe,tr),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r))){if(ee=we,ye=xl(),ye!==r)if(Oe=is(),Oe!==r)if(mt=Tn(),mt!==r)if(Et=fu(),Et!==r){if(bt=[],tr=Je(),tr!==r)for(;tr!==r;)bt.push(tr),tr=Je();else bt=r;bt!==r?(Nt=ee,ye=O(Oe,Et),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;else we=ee,ee=r;else we=ee,ee=r;else we=ee,ee=r;if(ee===r)if(ee=we,ye=xl(),ye!==r)if(Oe=is(),Oe!==r){if(mt=[],Et=we,bt=Tn(),bt===r&&(bt=null),bt!==r?(e.charCodeAt(we)===44?(tr=U,we++):(tr=r,Tt===0&&$e(Y)),tr!==r?(pn=Tn(),pn===r&&(pn=null),pn!==r?(ci=is(),ci!==r?(Nt=Et,bt=te(Oe,ci),Et=bt):(we=Et,Et=r)):(we=Et,Et=r)):(we=Et,Et=r)):(we=Et,Et=r),Et!==r)for(;Et!==r;)mt.push(Et),Et=we,bt=Tn(),bt===r&&(bt=null),bt!==r?(e.charCodeAt(we)===44?(tr=U,we++):(tr=r,Tt===0&&$e(Y)),tr!==r?(pn=Tn(),pn===r&&(pn=null),pn!==r?(ci=is(),ci!==r?(Nt=Et,bt=te(Oe,ci),Et=bt):(we=Et,Et=r)):(we=Et,Et=r)):(we=Et,Et=r)):(we=Et,Et=r);else mt=r;mt!==r?(Et=Tn(),Et===r&&(Et=null),Et!==r?(e.charCodeAt(we)===58?(bt=I,we++):(bt=r,Tt===0&&$e(T)),bt!==r?(tr=Tn(),tr===r&&(tr=null),tr!==r?(pn=ha(),pn!==r?(Nt=ee,ye=ie(Oe,mt,pn),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)}else we=ee,ee=r;else we=ee,ee=r}return ee}function ha(){var ee,ye,Oe,mt,Et,bt,tr;if(ee=we,ye=we,Tt++,Oe=we,mt=ot(),mt!==r?(Et=Mt(),Et!==r?(e.charCodeAt(we)===45?(bt=c,we++):(bt=r,Tt===0&&$e(f)),bt!==r?(tr=Tn(),tr!==r?(mt=[mt,Et,bt,tr],Oe=mt):(we=Oe,Oe=r)):(we=Oe,Oe=r)):(we=Oe,Oe=r)):(we=Oe,Oe=r),Tt--,Oe!==r?(we=ye,ye=void 0):ye=r,ye!==r?(Oe=Je(),Oe!==r?(mt=Rn(),mt!==r?(Et=vn(),Et!==r?(bt=ga(),bt!==r?(Nt=ee,ye=ue(Et),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r&&(ee=we,ye=ot(),ye!==r?(Oe=Rn(),Oe!==r?(mt=MA(),mt!==r?(Et=ga(),Et!==r?(Nt=ee,ye=ue(mt),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r))if(ee=we,ye=uc(),ye!==r){if(Oe=[],mt=Je(),mt!==r)for(;mt!==r;)Oe.push(mt),mt=Je();else Oe=r;Oe!==r?(Nt=ee,ye=ae(ye),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;return ee}function xl(){var ee,ye,Oe;for(Tt++,ee=we,ye=[],e.charCodeAt(we)===32?(Oe=Ae,we++):(Oe=r,Tt===0&&$e(Ce));Oe!==r;)ye.push(Oe),e.charCodeAt(we)===32?(Oe=Ae,we++):(Oe=r,Tt===0&&$e(Ce));return ye!==r?(Nt=we,Oe=Ee(ye),Oe?Oe=void 0:Oe=r,Oe!==r?(ye=[ye,Oe],ee=ye):(we=ee,ee=r)):(we=ee,ee=r),Tt--,ee===r&&(ye=r,Tt===0&&$e(de)),ee}function Mt(){var ee,ye,Oe;for(ee=we,ye=[],e.charCodeAt(we)===32?(Oe=Ae,we++):(Oe=r,Tt===0&&$e(Ce));Oe!==r;)ye.push(Oe),e.charCodeAt(we)===32?(Oe=Ae,we++):(Oe=r,Tt===0&&$e(Ce));return ye!==r?(Nt=we,Oe=g(ye),Oe?Oe=void 0:Oe=r,Oe!==r?(ye=[ye,Oe],ee=ye):(we=ee,ee=r)):(we=ee,ee=r),ee}function Rn(){var ee;return Nt=we,ee=Se(),ee?ee=void 0:ee=r,ee}function ga(){var ee;return Nt=we,ee=Be(),ee?ee=void 0:ee=r,ee}function Ya(){var ee;return ee=kl(),ee===r&&(ee=fc()),ee}function is(){var ee,ye,Oe;if(ee=kl(),ee===r){if(ee=we,ye=[],Oe=Ka(),Oe!==r)for(;Oe!==r;)ye.push(Oe),Oe=Ka();else ye=r;ye!==r&&(Nt=ee,ye=me()),ee=ye}return ee}function uc(){var ee;return ee=Mi(),ee===r&&(ee=Bs(),ee===r&&(ee=kl(),ee===r&&(ee=fc()))),ee}function fu(){var ee;return ee=Mi(),ee===r&&(ee=kl(),ee===r&&(ee=Ka())),ee}function fc(){var ee,ye,Oe,mt,Et,bt;if(Tt++,ee=we,X.test(e.charAt(we))?(ye=e.charAt(we),we++):(ye=r,Tt===0&&$e(De)),ye!==r){for(Oe=[],mt=we,Et=Tn(),Et===r&&(Et=null),Et!==r?(Qe.test(e.charAt(we))?(bt=e.charAt(we),we++):(bt=r,Tt===0&&$e(it)),bt!==r?(Et=[Et,bt],mt=Et):(we=mt,mt=r)):(we=mt,mt=r);mt!==r;)Oe.push(mt),mt=we,Et=Tn(),Et===r&&(Et=null),Et!==r?(Qe.test(e.charAt(we))?(bt=e.charAt(we),we++):(bt=r,Tt===0&&$e(it)),bt!==r?(Et=[Et,bt],mt=Et):(we=mt,mt=r)):(we=mt,mt=r);Oe!==r?(Nt=ee,ye=_(),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;return Tt--,ee===r&&(ye=r,Tt===0&&$e(ce)),ee}function Ka(){var ee,ye,Oe,mt,Et;if(ee=we,e.substr(we,2)===tt?(ye=tt,we+=2):(ye=r,Tt===0&&$e(Ne)),ye===r&&(ye=null),ye!==r)if(ke.test(e.charAt(we))?(Oe=e.charAt(we),we++):(Oe=r,Tt===0&&$e(be)),Oe!==r){for(mt=[],je.test(e.charAt(we))?(Et=e.charAt(we),we++):(Et=r,Tt===0&&$e(Re));Et!==r;)mt.push(Et),je.test(e.charAt(we))?(Et=e.charAt(we),we++):(Et=r,Tt===0&&$e(Re));mt!==r?(Nt=ee,ye=_(),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;else we=ee,ee=r;return ee}function Mi(){var ee,ye;return ee=we,e.substr(we,4)===ct?(ye=ct,we+=4):(ye=r,Tt===0&&$e(Me)),ye!==r&&(Nt=ee,ye=P()),ee=ye,ee}function Bs(){var ee,ye;return ee=we,e.substr(we,4)===w?(ye=w,we+=4):(ye=r,Tt===0&&$e(b)),ye!==r&&(Nt=ee,ye=y()),ee=ye,ee===r&&(ee=we,e.substr(we,5)===F?(ye=F,we+=5):(ye=r,Tt===0&&$e(z)),ye!==r&&(Nt=ee,ye=Z()),ee=ye),ee}function kl(){var ee,ye,Oe,mt;return Tt++,ee=we,e.charCodeAt(we)===34?(ye=se,we++):(ye=r,Tt===0&&$e(xe)),ye!==r?(e.charCodeAt(we)===34?(Oe=se,we++):(Oe=r,Tt===0&&$e(xe)),Oe!==r?(Nt=ee,ye=Fe(),ee=ye):(we=ee,ee=r)):(we=ee,ee=r),ee===r&&(ee=we,e.charCodeAt(we)===34?(ye=se,we++):(ye=r,Tt===0&&$e(xe)),ye!==r?(Oe=mf(),Oe!==r?(e.charCodeAt(we)===34?(mt=se,we++):(mt=r,Tt===0&&$e(xe)),mt!==r?(Nt=ee,ye=ut(Oe),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)),Tt--,ee===r&&(ye=r,Tt===0&&$e($)),ee}function mf(){var ee,ye,Oe;if(ee=we,ye=[],Oe=Ac(),Oe!==r)for(;Oe!==r;)ye.push(Oe),Oe=Ac();else ye=r;return ye!==r&&(Nt=ee,ye=Ct(ye)),ee=ye,ee}function Ac(){var ee,ye,Oe,mt,Et,bt;return qt.test(e.charAt(we))?(ee=e.charAt(we),we++):(ee=r,Tt===0&&$e(ir)),ee===r&&(ee=we,e.substr(we,2)===Pt?(ye=Pt,we+=2):(ye=r,Tt===0&&$e(dn)),ye!==r&&(Nt=ee,ye=Pr()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===Ir?(ye=Ir,we+=2):(ye=r,Tt===0&&$e(Or)),ye!==r&&(Nt=ee,ye=on()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===li?(ye=li,we+=2):(ye=r,Tt===0&&$e(So)),ye!==r&&(Nt=ee,ye=ns()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===so?(ye=so,we+=2):(ye=r,Tt===0&&$e(Do)),ye!==r&&(Nt=ee,ye=ji()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===oo?(ye=oo,we+=2):(ye=r,Tt===0&&$e(bo)),ye!==r&&(Nt=ee,ye=RA()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===hf?(ye=hf,we+=2):(ye=r,Tt===0&&$e(hh)),ye!==r&&(Nt=ee,ye=gh()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===ao?(ye=ao,we+=2):(ye=r,Tt===0&&$e(Gn)),ye!==r&&(Nt=ee,ye=Ns()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===lo?(ye=lo,we+=2):(ye=r,Tt===0&&$e(iu)),ye!==r&&(Nt=ee,ye=su()),ee=ye,ee===r&&(ee=we,e.substr(we,2)===ou?(ye=ou,we+=2):(ye=r,Tt===0&&$e(TA)),ye!==r?(Oe=Bi(),Oe!==r?(mt=Bi(),mt!==r?(Et=Bi(),Et!==r?(bt=Bi(),bt!==r?(Nt=ee,ye=FA(Oe,mt,Et,bt),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)))))))))),ee}function Bi(){var ee;return ua.test(e.charAt(we))?(ee=e.charAt(we),we++):(ee=r,Tt===0&&$e(fa)),ee}function Tn(){var ee,ye;if(Tt++,ee=[],gr.test(e.charAt(we))?(ye=e.charAt(we),we++):(ye=r,Tt===0&&$e(Po)),ye!==r)for(;ye!==r;)ee.push(ye),gr.test(e.charAt(we))?(ye=e.charAt(we),we++):(ye=r,Tt===0&&$e(Po));else ee=r;return Tt--,ee===r&&(ye=r,Tt===0&&$e(NA)),ee}function pc(){var ee,ye;if(Tt++,ee=[],au.test(e.charAt(we))?(ye=e.charAt(we),we++):(ye=r,Tt===0&&$e(Cr)),ye!==r)for(;ye!==r;)ee.push(ye),au.test(e.charAt(we))?(ye=e.charAt(we),we++):(ye=r,Tt===0&&$e(Cr));else ee=r;return Tt--,ee===r&&(ye=r,Tt===0&&$e(Ue)),ee}function Je(){var ee,ye,Oe,mt,Et,bt;if(ee=we,ye=ot(),ye!==r){for(Oe=[],mt=we,Et=Tn(),Et===r&&(Et=null),Et!==r?(bt=ot(),bt!==r?(Et=[Et,bt],mt=Et):(we=mt,mt=r)):(we=mt,mt=r);mt!==r;)Oe.push(mt),mt=we,Et=Tn(),Et===r&&(Et=null),Et!==r?(bt=ot(),bt!==r?(Et=[Et,bt],mt=Et):(we=mt,mt=r)):(we=mt,mt=r);Oe!==r?(ye=[ye,Oe],ee=ye):(we=ee,ee=r)}else we=ee,ee=r;return ee}function ot(){var ee;return e.substr(we,2)===gf?(ee=gf,we+=2):(ee=r,Tt===0&&$e(OA)),ee===r&&(e.charCodeAt(we)===10?(ee=LA,we++):(ee=r,Tt===0&&$e(lu)),ee===r&&(e.charCodeAt(we)===13?(ee=cu,we++):(ee=r,Tt===0&&$e(ac)))),ee}let St=2,lr=0;if(Qn=a(),Qn!==r&&we===e.length)return Qn;throw Qn!==r&&we<e.length&&$e(dh()),df(co,Oi<e.length?e.charAt(Oi):null,Oi<e.length?Wa(Oi,Oi+1):Wa(Oi,Oi))}Fte.exports={SyntaxError:Qd,parse:sqe}});function Lte(e){return e.match(oqe)?e:JSON.stringify(e)}function Ute(e){return typeof e>\"u\"?!0:typeof e==\"object\"&&e!==null&&!Array.isArray(e)?Object.keys(e).every(t=>Ute(e[t])):!1}function jU(e,t,r){if(e===null)return`null\n`;if(typeof e==\"number\"||typeof e==\"boolean\")return`${e.toString()}\n`;if(typeof e==\"string\")return`${Lte(e)}\n`;if(Array.isArray(e)){if(e.length===0)return`[]\n`;let s=\"  \".repeat(t);return`\n${e.map(n=>`${s}- ${jU(n,t+1,!1)}`).join(\"\")}`}if(typeof e==\"object\"&&e){let[s,a]=e instanceof Sx?[e.data,!1]:[e,!0],n=\"  \".repeat(t),c=Object.keys(s);a&&c.sort((p,h)=>{let E=Ote.indexOf(p),C=Ote.indexOf(h);return E===-1&&C===-1?p<h?-1:p>h?1:0:E!==-1&&C===-1?-1:E===-1&&C!==-1?1:E-C});let f=c.filter(p=>!Ute(s[p])).map((p,h)=>{let E=s[p],C=Lte(p),S=jU(E,t+1,!0),x=h>0||r?n:\"\",I=C.length>1024?`? ${C}\n${x}:`:`${C}:`,T=S.startsWith(`\n`)?S:` ${S}`;return`${x}${I}${T}`}).join(t===0?`\n`:\"\")||`\n`;return r?`\n${f}`:`${f}`}throw new Error(`Unsupported value type (${e})`)}function cl(e){try{let t=jU(e,0,!1);return t!==`\n`?t:\"\"}catch(t){throw t.location&&(t.message=t.message.replace(/(\\.)?$/,` (line ${t.location.start.line}, column ${t.location.start.column})$1`)),t}}function aqe(e){return e.endsWith(`\n`)||(e+=`\n`),(0,Mte.parse)(e)}function cqe(e){if(lqe.test(e))return aqe(e);let t=(0,Dx.safeLoad)(e,{schema:Dx.FAILSAFE_SCHEMA,json:!0});if(t==null)return{};if(typeof t!=\"object\")throw new Error(`Expected an indexed object, got a ${typeof t} instead. Does your file follow Yaml's rules?`);if(Array.isArray(t))throw new Error(\"Expected an indexed object, got an array instead. Does your file follow Yaml's rules?\");return t}function cs(e){return cqe(e)}var Dx,Mte,oqe,Ote,Sx,lqe,_te=Ze(()=>{Dx=et(Tte()),Mte=et(Nte()),oqe=/^(?![-?:,\\][{}#&*!|>'\"%@` \\t\\r\\n]).([ \\t]*(?![,\\][{}:# \\t\\r\\n]).)*$/,Ote=[\"__metadata\",\"version\",\"resolution\",\"dependencies\",\"peerDependencies\",\"dependenciesMeta\",\"peerDependenciesMeta\",\"binaries\"],Sx=class{constructor(t){this.data=t}};cl.PreserveOrdering=Sx;lqe=/^(#.*(\\r?\\n))*?#\\s+yarn\\s+lockfile\\s+v1\\r?\\n/i});var _B={};Yt(_B,{parseResolution:()=>px,parseShell:()=>ux,parseSyml:()=>cs,stringifyArgument:()=>PU,stringifyArgumentSegment:()=>xU,stringifyArithmeticExpression:()=>Ax,stringifyCommand:()=>bU,stringifyCommandChain:()=>gE,stringifyCommandChainThen:()=>DU,stringifyCommandLine:()=>fx,stringifyCommandLineThen:()=>SU,stringifyEnvSegment:()=>cx,stringifyRedirectArgument:()=>TB,stringifyResolution:()=>hx,stringifyShell:()=>hE,stringifyShellLine:()=>hE,stringifySyml:()=>cl,stringifyValueArgument:()=>wd});var Bc=Ze(()=>{U$();G$();_te()});var jte=G(($Pt,GU)=>{\"use strict\";var uqe=e=>{let t=!1,r=!1,s=!1;for(let a=0;a<e.length;a++){let n=e[a];t&&/[a-zA-Z]/.test(n)&&n.toUpperCase()===n?(e=e.slice(0,a)+\"-\"+e.slice(a),t=!1,s=r,r=!0,a++):r&&s&&/[a-zA-Z]/.test(n)&&n.toLowerCase()===n?(e=e.slice(0,a-1)+\"-\"+e.slice(a-1),s=r,r=!1,t=!0):(t=n.toLowerCase()===n&&n.toUpperCase()!==n,s=r,r=n.toUpperCase()===n&&n.toLowerCase()!==n)}return e},Hte=(e,t)=>{if(!(typeof e==\"string\"||Array.isArray(e)))throw new TypeError(\"Expected the input to be `string | string[]`\");t=Object.assign({pascalCase:!1},t);let r=a=>t.pascalCase?a.charAt(0).toUpperCase()+a.slice(1):a;return Array.isArray(e)?e=e.map(a=>a.trim()).filter(a=>a.length).join(\"-\"):e=e.trim(),e.length===0?\"\":e.length===1?t.pascalCase?e.toUpperCase():e.toLowerCase():(e!==e.toLowerCase()&&(e=uqe(e)),e=e.replace(/^[_.\\- ]+/,\"\").toLowerCase().replace(/[_.\\- ]+(\\w|$)/g,(a,n)=>n.toUpperCase()).replace(/\\d+(\\w|$)/g,a=>a.toUpperCase()),r(e))};GU.exports=Hte;GU.exports.default=Hte});var Gte=G((ext,fqe)=>{fqe.exports=[{name:\"Agola CI\",constant:\"AGOLA\",env:\"AGOLA_GIT_REF\",pr:\"AGOLA_PULL_REQUEST_ID\"},{name:\"Appcircle\",constant:\"APPCIRCLE\",env:\"AC_APPCIRCLE\"},{name:\"AppVeyor\",constant:\"APPVEYOR\",env:\"APPVEYOR\",pr:\"APPVEYOR_PULL_REQUEST_NUMBER\"},{name:\"AWS CodeBuild\",constant:\"CODEBUILD\",env:\"CODEBUILD_BUILD_ARN\"},{name:\"Azure Pipelines\",constant:\"AZURE_PIPELINES\",env:\"TF_BUILD\",pr:{BUILD_REASON:\"PullRequest\"}},{name:\"Bamboo\",constant:\"BAMBOO\",env:\"bamboo_planKey\"},{name:\"Bitbucket Pipelines\",constant:\"BITBUCKET\",env:\"BITBUCKET_COMMIT\",pr:\"BITBUCKET_PR_ID\"},{name:\"Bitrise\",constant:\"BITRISE\",env:\"BITRISE_IO\",pr:\"BITRISE_PULL_REQUEST\"},{name:\"Buddy\",constant:\"BUDDY\",env:\"BUDDY_WORKSPACE_ID\",pr:\"BUDDY_EXECUTION_PULL_REQUEST_ID\"},{name:\"Buildkite\",constant:\"BUILDKITE\",env:\"BUILDKITE\",pr:{env:\"BUILDKITE_PULL_REQUEST\",ne:\"false\"}},{name:\"CircleCI\",constant:\"CIRCLE\",env:\"CIRCLECI\",pr:\"CIRCLE_PULL_REQUEST\"},{name:\"Cirrus CI\",constant:\"CIRRUS\",env:\"CIRRUS_CI\",pr:\"CIRRUS_PR\"},{name:\"Codefresh\",constant:\"CODEFRESH\",env:\"CF_BUILD_ID\",pr:{any:[\"CF_PULL_REQUEST_NUMBER\",\"CF_PULL_REQUEST_ID\"]}},{name:\"Codemagic\",constant:\"CODEMAGIC\",env:\"CM_BUILD_ID\",pr:\"CM_PULL_REQUEST\"},{name:\"Codeship\",constant:\"CODESHIP\",env:{CI_NAME:\"codeship\"}},{name:\"Drone\",constant:\"DRONE\",env:\"DRONE\",pr:{DRONE_BUILD_EVENT:\"pull_request\"}},{name:\"dsari\",constant:\"DSARI\",env:\"DSARI\"},{name:\"Earthly\",constant:\"EARTHLY\",env:\"EARTHLY_CI\"},{name:\"Expo Application Services\",constant:\"EAS\",env:\"EAS_BUILD\"},{name:\"Gerrit\",constant:\"GERRIT\",env:\"GERRIT_PROJECT\"},{name:\"Gitea Actions\",constant:\"GITEA_ACTIONS\",env:\"GITEA_ACTIONS\"},{name:\"GitHub Actions\",constant:\"GITHUB_ACTIONS\",env:\"GITHUB_ACTIONS\",pr:{GITHUB_EVENT_NAME:\"pull_request\"}},{name:\"GitLab CI\",constant:\"GITLAB\",env:\"GITLAB_CI\",pr:\"CI_MERGE_REQUEST_ID\"},{name:\"GoCD\",constant:\"GOCD\",env:\"GO_PIPELINE_LABEL\"},{name:\"Google Cloud Build\",constant:\"GOOGLE_CLOUD_BUILD\",env:\"BUILDER_OUTPUT\"},{name:\"Harness CI\",constant:\"HARNESS\",env:\"HARNESS_BUILD_ID\"},{name:\"Heroku\",constant:\"HEROKU\",env:{env:\"NODE\",includes:\"/app/.heroku/node/bin/node\"}},{name:\"Hudson\",constant:\"HUDSON\",env:\"HUDSON_URL\"},{name:\"Jenkins\",constant:\"JENKINS\",env:[\"JENKINS_URL\",\"BUILD_ID\"],pr:{any:[\"ghprbPullId\",\"CHANGE_ID\"]}},{name:\"LayerCI\",constant:\"LAYERCI\",env:\"LAYERCI\",pr:\"LAYERCI_PULL_REQUEST\"},{name:\"Magnum CI\",constant:\"MAGNUM\",env:\"MAGNUM\"},{name:\"Netlify CI\",constant:\"NETLIFY\",env:\"NETLIFY\",pr:{env:\"PULL_REQUEST\",ne:\"false\"}},{name:\"Nevercode\",constant:\"NEVERCODE\",env:\"NEVERCODE\",pr:{env:\"NEVERCODE_PULL_REQUEST\",ne:\"false\"}},{name:\"Prow\",constant:\"PROW\",env:\"PROW_JOB_ID\"},{name:\"ReleaseHub\",constant:\"RELEASEHUB\",env:\"RELEASE_BUILD_ID\"},{name:\"Render\",constant:\"RENDER\",env:\"RENDER\",pr:{IS_PULL_REQUEST:\"true\"}},{name:\"Sail CI\",constant:\"SAIL\",env:\"SAILCI\",pr:\"SAIL_PULL_REQUEST_NUMBER\"},{name:\"Screwdriver\",constant:\"SCREWDRIVER\",env:\"SCREWDRIVER\",pr:{env:\"SD_PULL_REQUEST\",ne:\"false\"}},{name:\"Semaphore\",constant:\"SEMAPHORE\",env:\"SEMAPHORE\",pr:\"PULL_REQUEST_NUMBER\"},{name:\"Sourcehut\",constant:\"SOURCEHUT\",env:{CI_NAME:\"sourcehut\"}},{name:\"Strider CD\",constant:\"STRIDER\",env:\"STRIDER\"},{name:\"TaskCluster\",constant:\"TASKCLUSTER\",env:[\"TASK_ID\",\"RUN_ID\"]},{name:\"TeamCity\",constant:\"TEAMCITY\",env:\"TEAMCITY_VERSION\"},{name:\"Travis CI\",constant:\"TRAVIS\",env:\"TRAVIS\",pr:{env:\"TRAVIS_PULL_REQUEST\",ne:\"false\"}},{name:\"Vela\",constant:\"VELA\",env:\"VELA\",pr:{VELA_PULL_REQUEST:\"1\"}},{name:\"Vercel\",constant:\"VERCEL\",env:{any:[\"NOW_BUILDER\",\"VERCEL\"]},pr:\"VERCEL_GIT_PULL_REQUEST_ID\"},{name:\"Visual Studio App Center\",constant:\"APPCENTER\",env:\"APPCENTER_BUILD_ID\"},{name:\"Woodpecker\",constant:\"WOODPECKER\",env:{CI:\"woodpecker\"},pr:{CI_BUILD_EVENT:\"pull_request\"}},{name:\"Xcode Cloud\",constant:\"XCODE_CLOUD\",env:\"CI_XCODE_PROJECT\",pr:\"CI_PULL_REQUEST_NUMBER\"},{name:\"Xcode Server\",constant:\"XCODE_SERVER\",env:\"XCS\"}]});var Rd=G(ql=>{\"use strict\";var Wte=Gte(),xs=process.env;Object.defineProperty(ql,\"_vendors\",{value:Wte.map(function(e){return e.constant})});ql.name=null;ql.isPR=null;Wte.forEach(function(e){let r=(Array.isArray(e.env)?e.env:[e.env]).every(function(s){return qte(s)});if(ql[e.constant]=r,!!r)switch(ql.name=e.name,typeof e.pr){case\"string\":ql.isPR=!!xs[e.pr];break;case\"object\":\"env\"in e.pr?ql.isPR=e.pr.env in xs&&xs[e.pr.env]!==e.pr.ne:\"any\"in e.pr?ql.isPR=e.pr.any.some(function(s){return!!xs[s]}):ql.isPR=qte(e.pr);break;default:ql.isPR=null}});ql.isCI=!!(xs.CI!==\"false\"&&(xs.BUILD_ID||xs.BUILD_NUMBER||xs.CI||xs.CI_APP_ID||xs.CI_BUILD_ID||xs.CI_BUILD_NUMBER||xs.CI_NAME||xs.CONTINUOUS_INTEGRATION||xs.RUN_ID||ql.name));function qte(e){return typeof e==\"string\"?!!xs[e]:\"env\"in e?xs[e.env]&&xs[e.env].includes(e.includes):\"any\"in e?e.any.some(function(t){return!!xs[t]}):Object.keys(e).every(function(t){return xs[t]===e[t]})}});var ni,In,Td,qU,bx,Vte,WU,VU,Px=Ze(()=>{(function(e){e.StartOfInput=\"\\0\",e.EndOfInput=\"\u0001\",e.EndOfPartialInput=\"\u0002\"})(ni||(ni={}));(function(e){e[e.InitialNode=0]=\"InitialNode\",e[e.SuccessNode=1]=\"SuccessNode\",e[e.ErrorNode=2]=\"ErrorNode\",e[e.CustomNode=3]=\"CustomNode\"})(In||(In={}));Td=-1,qU=/^(-h|--help)(?:=([0-9]+))?$/,bx=/^(--[a-z]+(?:-[a-z]+)*|-[a-zA-Z]+)$/,Vte=/^-[a-zA-Z]{2,}$/,WU=/^([^=]+)=([\\s\\S]*)$/,VU=process.env.DEBUG_CLI===\"1\"});var st,BE,xx,YU,kx=Ze(()=>{Px();st=class extends Error{constructor(t){super(t),this.clipanion={type:\"usage\"},this.name=\"UsageError\"}},BE=class extends Error{constructor(t,r){if(super(),this.input=t,this.candidates=r,this.clipanion={type:\"none\"},this.name=\"UnknownSyntaxError\",this.candidates.length===0)this.message=\"Command not found, but we're not sure what's the alternative.\";else if(this.candidates.every(s=>s.reason!==null&&s.reason===r[0].reason)){let[{reason:s}]=this.candidates;this.message=`${s}\n\n${this.candidates.map(({usage:a})=>`$ ${a}`).join(`\n`)}`}else if(this.candidates.length===1){let[{usage:s}]=this.candidates;this.message=`Command not found; did you mean:\n\n$ ${s}\n${YU(t)}`}else this.message=`Command not found; did you mean one of:\n\n${this.candidates.map(({usage:s},a)=>`${`${a}.`.padStart(4)} ${s}`).join(`\n`)}\n\n${YU(t)}`}},xx=class extends Error{constructor(t,r){super(),this.input=t,this.usages=r,this.clipanion={type:\"none\"},this.name=\"AmbiguousSyntaxError\",this.message=`Cannot find which to pick amongst the following alternatives:\n\n${this.usages.map((s,a)=>`${`${a}.`.padStart(4)} ${s}`).join(`\n`)}\n\n${YU(t)}`}},YU=e=>`While running ${e.filter(t=>t!==ni.EndOfInput&&t!==ni.EndOfPartialInput).map(t=>{let r=JSON.stringify(t);return t.match(/\\s/)||t.length===0||r!==`\"${t}\"`?r:t}).join(\" \")}`});function Aqe(e){let t=e.split(`\n`),r=t.filter(a=>a.match(/\\S/)),s=r.length>0?r.reduce((a,n)=>Math.min(a,n.length-n.trimStart().length),Number.MAX_VALUE):0;return t.map(a=>a.slice(s).trimRight()).join(`\n`)}function Vo(e,{format:t,paragraphs:r}){return e=e.replace(/\\r\\n?/g,`\n`),e=Aqe(e),e=e.replace(/^\\n+|\\n+$/g,\"\"),e=e.replace(/^(\\s*)-([^\\n]*?)\\n+/gm,`$1-$2\n\n`),e=e.replace(/\\n(\\n)?\\n*/g,(s,a)=>a||\" \"),r&&(e=e.split(/\\n/).map(s=>{let a=s.match(/^\\s*[*-][\\t ]+(.*)/);if(!a)return s.match(/(.{1,80})(?: |$)/g).join(`\n`);let n=s.length-s.trimStart().length;return a[1].match(new RegExp(`(.{1,${78-n}})(?: |$)`,\"g\")).map((c,f)=>\" \".repeat(n)+(f===0?\"- \":\"  \")+c).join(`\n`)}).join(`\n\n`)),e=e.replace(/(`+)((?:.|[\\n])*?)\\1/g,(s,a,n)=>t.code(a+n+a)),e=e.replace(/(\\*\\*)((?:.|[\\n])*?)\\1/g,(s,a,n)=>t.bold(a+n+a)),e?`${e}\n`:\"\"}var KU,Yte,Kte,JU=Ze(()=>{KU=Array(80).fill(\"\\u2501\");for(let e=0;e<=24;++e)KU[KU.length-e]=`\\x1B[38;5;${232+e}m\\u2501`;Yte={header:e=>`\\x1B[1m\\u2501\\u2501\\u2501 ${e}${e.length<75?` ${KU.slice(e.length+5).join(\"\")}`:\":\"}\\x1B[0m`,bold:e=>`\\x1B[1m${e}\\x1B[22m`,error:e=>`\\x1B[31m\\x1B[1m${e}\\x1B[22m\\x1B[39m`,code:e=>`\\x1B[36m${e}\\x1B[39m`},Kte={header:e=>e,bold:e=>e,error:e=>e,code:e=>e}});function wa(e){return{...e,[HB]:!0}}function Wf(e,t){return typeof e>\"u\"?[e,t]:typeof e==\"object\"&&e!==null&&!Array.isArray(e)?[void 0,e]:[e,t]}function Qx(e,{mergeName:t=!1}={}){let r=e.match(/^([^:]+): (.*)$/m);if(!r)return\"validation failed\";let[,s,a]=r;return t&&(a=a[0].toLowerCase()+a.slice(1)),a=s!==\".\"||!t?`${s.replace(/^\\.(\\[|$)/,\"$1\")}: ${a}`:`: ${a}`,a}function jB(e,t){return t.length===1?new st(`${e}${Qx(t[0],{mergeName:!0})}`):new st(`${e}:\n${t.map(r=>`\n- ${Qx(r)}`).join(\"\")}`)}function Fd(e,t,r){if(typeof r>\"u\")return t;let s=[],a=[],n=f=>{let p=t;return t=f,n.bind(null,p)};if(!r(t,{errors:s,coercions:a,coercion:n}))throw jB(`Invalid value for ${e}`,s);for(let[,f]of a)f();return t}var HB,wp=Ze(()=>{kx();HB=Symbol(\"clipanion/isOption\")});var Yo={};Yt(Yo,{KeyRelationship:()=>Vf,TypeAssertionError:()=>i0,applyCascade:()=>WB,as:()=>Qqe,assert:()=>Pqe,assertWithErrors:()=>xqe,cascade:()=>Nx,fn:()=>Rqe,hasAtLeastOneKey:()=>r_,hasExactLength:()=>$te,hasForbiddenKeys:()=>Zqe,hasKeyRelationship:()=>YB,hasMaxLength:()=>Fqe,hasMinLength:()=>Tqe,hasMutuallyExclusiveKeys:()=>Xqe,hasRequiredKeys:()=>zqe,hasUniqueItems:()=>Nqe,isArray:()=>Rx,isAtLeast:()=>e_,isAtMost:()=>Mqe,isBase64:()=>Vqe,isBoolean:()=>Iqe,isDate:()=>wqe,isDict:()=>Sqe,isEnum:()=>ks,isHexColor:()=>Wqe,isISO8601:()=>qqe,isInExclusiveRange:()=>_qe,isInInclusiveRange:()=>Uqe,isInstanceOf:()=>bqe,isInteger:()=>t_,isJSON:()=>Yqe,isLiteral:()=>zte,isLowerCase:()=>Hqe,isMap:()=>vqe,isNegative:()=>Oqe,isNullable:()=>Jqe,isNumber:()=>XU,isObject:()=>Zte,isOneOf:()=>$U,isOptional:()=>Kqe,isPartial:()=>Dqe,isPayload:()=>Cqe,isPositive:()=>Lqe,isRecord:()=>Fx,isSet:()=>Bqe,isString:()=>SE,isTuple:()=>Tx,isUUID4:()=>Gqe,isUnknown:()=>ZU,isUpperCase:()=>jqe,makeTrait:()=>Xte,makeValidator:()=>Wr,matchesRegExp:()=>qB,softAssert:()=>kqe});function ii(e){return e===null?\"null\":e===void 0?\"undefined\":e===\"\"?\"an empty string\":typeof e==\"symbol\"?`<${e.toString()}>`:Array.isArray(e)?\"an array\":JSON.stringify(e)}function vE(e,t){if(e.length===0)return\"nothing\";if(e.length===1)return ii(e[0]);let r=e.slice(0,-1),s=e[e.length-1],a=e.length>2?`, ${t} `:` ${t} `;return`${r.map(n=>ii(n)).join(\", \")}${a}${ii(s)}`}function n0(e,t){var r,s,a;return typeof t==\"number\"?`${(r=e?.p)!==null&&r!==void 0?r:\".\"}[${t}]`:pqe.test(t)?`${(s=e?.p)!==null&&s!==void 0?s:\"\"}.${t}`:`${(a=e?.p)!==null&&a!==void 0?a:\".\"}[${JSON.stringify(t)}]`}function zU(e,t,r){return e===1?t:r}function mr({errors:e,p:t}={},r){return e?.push(`${t??\".\"}: ${r}`),!1}function yqe(e,t){return r=>{e[t]=r}}function Yf(e,t){return r=>{let s=e[t];return e[t]=r,Yf(e,t).bind(null,s)}}function GB(e,t,r){let s=()=>(e(r()),a),a=()=>(e(t),s);return s}function ZU(){return Wr({test:(e,t)=>!0})}function zte(e){return Wr({test:(t,r)=>t!==e?mr(r,`Expected ${ii(e)} (got ${ii(t)})`):!0})}function SE(){return Wr({test:(e,t)=>typeof e!=\"string\"?mr(t,`Expected a string (got ${ii(e)})`):!0})}function ks(e){let t=Array.isArray(e)?e:Object.values(e),r=t.every(a=>typeof a==\"string\"||typeof a==\"number\"),s=new Set(t);return s.size===1?zte([...s][0]):Wr({test:(a,n)=>s.has(a)?!0:r?mr(n,`Expected one of ${vE(t,\"or\")} (got ${ii(a)})`):mr(n,`Expected a valid enumeration value (got ${ii(a)})`)})}function Iqe(){return Wr({test:(e,t)=>{var r;if(typeof e!=\"boolean\"){if(typeof t?.coercions<\"u\"){if(typeof t?.coercion>\"u\")return mr(t,\"Unbound coercion result\");let s=Eqe.get(e);if(typeof s<\"u\")return t.coercions.push([(r=t.p)!==null&&r!==void 0?r:\".\",t.coercion.bind(null,s)]),!0}return mr(t,`Expected a boolean (got ${ii(e)})`)}return!0}})}function XU(){return Wr({test:(e,t)=>{var r;if(typeof e!=\"number\"){if(typeof t?.coercions<\"u\"){if(typeof t?.coercion>\"u\")return mr(t,\"Unbound coercion result\");let s;if(typeof e==\"string\"){let a;try{a=JSON.parse(e)}catch{}if(typeof a==\"number\")if(JSON.stringify(a)===e)s=a;else return mr(t,`Received a number that can't be safely represented by the runtime (${e})`)}if(typeof s<\"u\")return t.coercions.push([(r=t.p)!==null&&r!==void 0?r:\".\",t.coercion.bind(null,s)]),!0}return mr(t,`Expected a number (got ${ii(e)})`)}return!0}})}function Cqe(e){return Wr({test:(t,r)=>{var s;if(typeof r?.coercions>\"u\")return mr(r,\"The isPayload predicate can only be used with coercion enabled\");if(typeof r.coercion>\"u\")return mr(r,\"Unbound coercion result\");if(typeof t!=\"string\")return mr(r,`Expected a string (got ${ii(t)})`);let a;try{a=JSON.parse(t)}catch{return mr(r,`Expected a JSON string (got ${ii(t)})`)}let n={value:a};return e(a,Object.assign(Object.assign({},r),{coercion:Yf(n,\"value\")}))?(r.coercions.push([(s=r.p)!==null&&s!==void 0?s:\".\",r.coercion.bind(null,n.value)]),!0):!1}})}function wqe(){return Wr({test:(e,t)=>{var r;if(!(e instanceof Date)){if(typeof t?.coercions<\"u\"){if(typeof t?.coercion>\"u\")return mr(t,\"Unbound coercion result\");let s;if(typeof e==\"string\"&&Jte.test(e))s=new Date(e);else{let a;if(typeof e==\"string\"){let n;try{n=JSON.parse(e)}catch{}typeof n==\"number\"&&(a=n)}else typeof e==\"number\"&&(a=e);if(typeof a<\"u\")if(Number.isSafeInteger(a)||!Number.isSafeInteger(a*1e3))s=new Date(a*1e3);else return mr(t,`Received a timestamp that can't be safely represented by the runtime (${e})`)}if(typeof s<\"u\")return t.coercions.push([(r=t.p)!==null&&r!==void 0?r:\".\",t.coercion.bind(null,s)]),!0}return mr(t,`Expected a date (got ${ii(e)})`)}return!0}})}function Rx(e,{delimiter:t}={}){return Wr({test:(r,s)=>{var a;let n=r;if(typeof r==\"string\"&&typeof t<\"u\"&&typeof s?.coercions<\"u\"){if(typeof s?.coercion>\"u\")return mr(s,\"Unbound coercion result\");r=r.split(t)}if(!Array.isArray(r))return mr(s,`Expected an array (got ${ii(r)})`);let c=!0;for(let f=0,p=r.length;f<p&&(c=e(r[f],Object.assign(Object.assign({},s),{p:n0(s,f),coercion:Yf(r,f)}))&&c,!(!c&&s?.errors==null));++f);return r!==n&&s.coercions.push([(a=s.p)!==null&&a!==void 0?a:\".\",s.coercion.bind(null,r)]),c}})}function Bqe(e,{delimiter:t}={}){let r=Rx(e,{delimiter:t});return Wr({test:(s,a)=>{var n,c;if(Object.getPrototypeOf(s).toString()===\"[object Set]\")if(typeof a?.coercions<\"u\"){if(typeof a?.coercion>\"u\")return mr(a,\"Unbound coercion result\");let f=[...s],p=[...s];if(!r(p,Object.assign(Object.assign({},a),{coercion:void 0})))return!1;let h=()=>p.some((E,C)=>E!==f[C])?new Set(p):s;return a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",GB(a.coercion,s,h)]),!0}else{let f=!0;for(let p of s)if(f=e(p,Object.assign({},a))&&f,!f&&a?.errors==null)break;return f}if(typeof a?.coercions<\"u\"){if(typeof a?.coercion>\"u\")return mr(a,\"Unbound coercion result\");let f={value:s};return r(s,Object.assign(Object.assign({},a),{coercion:Yf(f,\"value\")}))?(a.coercions.push([(c=a.p)!==null&&c!==void 0?c:\".\",GB(a.coercion,s,()=>new Set(f.value))]),!0):!1}return mr(a,`Expected a set (got ${ii(s)})`)}})}function vqe(e,t){let r=Rx(Tx([e,t])),s=Fx(t,{keys:e});return Wr({test:(a,n)=>{var c,f,p;if(Object.getPrototypeOf(a).toString()===\"[object Map]\")if(typeof n?.coercions<\"u\"){if(typeof n?.coercion>\"u\")return mr(n,\"Unbound coercion result\");let h=[...a],E=[...a];if(!r(E,Object.assign(Object.assign({},n),{coercion:void 0})))return!1;let C=()=>E.some((S,x)=>S[0]!==h[x][0]||S[1]!==h[x][1])?new Map(E):a;return n.coercions.push([(c=n.p)!==null&&c!==void 0?c:\".\",GB(n.coercion,a,C)]),!0}else{let h=!0;for(let[E,C]of a)if(h=e(E,Object.assign({},n))&&h,!h&&n?.errors==null||(h=t(C,Object.assign(Object.assign({},n),{p:n0(n,E)}))&&h,!h&&n?.errors==null))break;return h}if(typeof n?.coercions<\"u\"){if(typeof n?.coercion>\"u\")return mr(n,\"Unbound coercion result\");let h={value:a};return Array.isArray(a)?r(a,Object.assign(Object.assign({},n),{coercion:void 0}))?(n.coercions.push([(f=n.p)!==null&&f!==void 0?f:\".\",GB(n.coercion,a,()=>new Map(h.value))]),!0):!1:s(a,Object.assign(Object.assign({},n),{coercion:Yf(h,\"value\")}))?(n.coercions.push([(p=n.p)!==null&&p!==void 0?p:\".\",GB(n.coercion,a,()=>new Map(Object.entries(h.value)))]),!0):!1}return mr(n,`Expected a map (got ${ii(a)})`)}})}function Tx(e,{delimiter:t}={}){let r=$te(e.length);return Wr({test:(s,a)=>{var n;if(typeof s==\"string\"&&typeof t<\"u\"&&typeof a?.coercions<\"u\"){if(typeof a?.coercion>\"u\")return mr(a,\"Unbound coercion result\");s=s.split(t),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",a.coercion.bind(null,s)])}if(!Array.isArray(s))return mr(a,`Expected a tuple (got ${ii(s)})`);let c=r(s,Object.assign({},a));for(let f=0,p=s.length;f<p&&f<e.length&&(c=e[f](s[f],Object.assign(Object.assign({},a),{p:n0(a,f),coercion:Yf(s,f)}))&&c,!(!c&&a?.errors==null));++f);return c}})}function Fx(e,{keys:t=null}={}){let r=Rx(Tx([t??SE(),e]));return Wr({test:(s,a)=>{var n;if(Array.isArray(s)&&typeof a?.coercions<\"u\")return typeof a?.coercion>\"u\"?mr(a,\"Unbound coercion result\"):r(s,Object.assign(Object.assign({},a),{coercion:void 0}))?(s=Object.fromEntries(s),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",a.coercion.bind(null,s)]),!0):!1;if(typeof s!=\"object\"||s===null)return mr(a,`Expected an object (got ${ii(s)})`);let c=Object.keys(s),f=!0;for(let p=0,h=c.length;p<h&&(f||a?.errors!=null);++p){let E=c[p],C=s[E];if(E===\"__proto__\"||E===\"constructor\"){f=mr(Object.assign(Object.assign({},a),{p:n0(a,E)}),\"Unsafe property name\");continue}if(t!==null&&!t(E,a)){f=!1;continue}if(!e(C,Object.assign(Object.assign({},a),{p:n0(a,E),coercion:Yf(s,E)}))){f=!1;continue}}return f}})}function Sqe(e,t={}){return Fx(e,t)}function Zte(e,{extra:t=null}={}){let r=Object.keys(e),s=Wr({test:(a,n)=>{if(typeof a!=\"object\"||a===null)return mr(n,`Expected an object (got ${ii(a)})`);let c=new Set([...r,...Object.keys(a)]),f={},p=!0;for(let h of c){if(h===\"constructor\"||h===\"__proto__\")p=mr(Object.assign(Object.assign({},n),{p:n0(n,h)}),\"Unsafe property name\");else{let E=Object.prototype.hasOwnProperty.call(e,h)?e[h]:void 0,C=Object.prototype.hasOwnProperty.call(a,h)?a[h]:void 0;typeof E<\"u\"?p=E(C,Object.assign(Object.assign({},n),{p:n0(n,h),coercion:Yf(a,h)}))&&p:t===null?p=mr(Object.assign(Object.assign({},n),{p:n0(n,h)}),`Extraneous property (got ${ii(C)})`):Object.defineProperty(f,h,{enumerable:!0,get:()=>C,set:yqe(a,h)})}if(!p&&n?.errors==null)break}return t!==null&&(p||n?.errors!=null)&&(p=t(f,n)&&p),p}});return Object.assign(s,{properties:e})}function Dqe(e){return Zte(e,{extra:Fx(ZU())})}function Xte(e){return()=>e}function Wr({test:e}){return Xte(e)()}function Pqe(e,t){if(!t(e))throw new i0}function xqe(e,t){let r=[];if(!t(e,{errors:r}))throw new i0({errors:r})}function kqe(e,t){}function Qqe(e,t,{coerce:r=!1,errors:s,throw:a}={}){let n=s?[]:void 0;if(!r){if(t(e,{errors:n}))return a?e:{value:e,errors:void 0};if(a)throw new i0({errors:n});return{value:void 0,errors:n??!0}}let c={value:e},f=Yf(c,\"value\"),p=[];if(!t(e,{errors:n,coercion:f,coercions:p})){if(a)throw new i0({errors:n});return{value:void 0,errors:n??!0}}for(let[,h]of p)h();return a?c.value:{value:c.value,errors:void 0}}function Rqe(e,t){let r=Tx(e);return(...s)=>{if(!r(s))throw new i0;return t(...s)}}function Tqe(e){return Wr({test:(t,r)=>t.length>=e?!0:mr(r,`Expected to have a length of at least ${e} elements (got ${t.length})`)})}function Fqe(e){return Wr({test:(t,r)=>t.length<=e?!0:mr(r,`Expected to have a length of at most ${e} elements (got ${t.length})`)})}function $te(e){return Wr({test:(t,r)=>t.length!==e?mr(r,`Expected to have a length of exactly ${e} elements (got ${t.length})`):!0})}function Nqe({map:e}={}){return Wr({test:(t,r)=>{let s=new Set,a=new Set;for(let n=0,c=t.length;n<c;++n){let f=t[n],p=typeof e<\"u\"?e(f):f;if(s.has(p)){if(a.has(p))continue;mr(r,`Expected to contain unique elements; got a duplicate with ${ii(t)}`),a.add(p)}else s.add(p)}return a.size===0}})}function Oqe(){return Wr({test:(e,t)=>e<=0?!0:mr(t,`Expected to be negative (got ${e})`)})}function Lqe(){return Wr({test:(e,t)=>e>=0?!0:mr(t,`Expected to be positive (got ${e})`)})}function e_(e){return Wr({test:(t,r)=>t>=e?!0:mr(r,`Expected to be at least ${e} (got ${t})`)})}function Mqe(e){return Wr({test:(t,r)=>t<=e?!0:mr(r,`Expected to be at most ${e} (got ${t})`)})}function Uqe(e,t){return Wr({test:(r,s)=>r>=e&&r<=t?!0:mr(s,`Expected to be in the [${e}; ${t}] range (got ${r})`)})}function _qe(e,t){return Wr({test:(r,s)=>r>=e&&r<t?!0:mr(s,`Expected to be in the [${e}; ${t}[ range (got ${r})`)})}function t_({unsafe:e=!1}={}){return Wr({test:(t,r)=>t!==Math.round(t)?mr(r,`Expected to be an integer (got ${t})`):!e&&!Number.isSafeInteger(t)?mr(r,`Expected to be a safe integer (got ${t})`):!0})}function qB(e){return Wr({test:(t,r)=>e.test(t)?!0:mr(r,`Expected to match the pattern ${e.toString()} (got ${ii(t)})`)})}function Hqe(){return Wr({test:(e,t)=>e!==e.toLowerCase()?mr(t,`Expected to be all-lowercase (got ${e})`):!0})}function jqe(){return Wr({test:(e,t)=>e!==e.toUpperCase()?mr(t,`Expected to be all-uppercase (got ${e})`):!0})}function Gqe(){return Wr({test:(e,t)=>mqe.test(e)?!0:mr(t,`Expected to be a valid UUID v4 (got ${ii(e)})`)})}function qqe(){return Wr({test:(e,t)=>Jte.test(e)?!0:mr(t,`Expected to be a valid ISO 8601 date string (got ${ii(e)})`)})}function Wqe({alpha:e=!1}){return Wr({test:(t,r)=>(e?hqe.test(t):gqe.test(t))?!0:mr(r,`Expected to be a valid hexadecimal color string (got ${ii(t)})`)})}function Vqe(){return Wr({test:(e,t)=>dqe.test(e)?!0:mr(t,`Expected to be a valid base 64 string (got ${ii(e)})`)})}function Yqe(e=ZU()){return Wr({test:(t,r)=>{let s;try{s=JSON.parse(t)}catch{return mr(r,`Expected to be a valid JSON string (got ${ii(t)})`)}return e(s,r)}})}function Nx(e,...t){let r=Array.isArray(t[0])?t[0]:t;return Wr({test:(s,a)=>{var n,c;let f={value:s},p=typeof a?.coercions<\"u\"?Yf(f,\"value\"):void 0,h=typeof a?.coercions<\"u\"?[]:void 0;if(!e(s,Object.assign(Object.assign({},a),{coercion:p,coercions:h})))return!1;let E=[];if(typeof h<\"u\")for(let[,C]of h)E.push(C());try{if(typeof a?.coercions<\"u\"){if(f.value!==s){if(typeof a?.coercion>\"u\")return mr(a,\"Unbound coercion result\");a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",a.coercion.bind(null,f.value)])}(c=a?.coercions)===null||c===void 0||c.push(...h)}return r.every(C=>C(f.value,a))}finally{for(let C of E)C()}}})}function WB(e,...t){let r=Array.isArray(t[0])?t[0]:t;return Nx(e,r)}function Kqe(e){return Wr({test:(t,r)=>typeof t>\"u\"?!0:e(t,r)})}function Jqe(e){return Wr({test:(t,r)=>t===null?!0:e(t,r)})}function zqe(e,t){var r;let s=new Set(e),a=VB[(r=t?.missingIf)!==null&&r!==void 0?r:\"missing\"];return Wr({test:(n,c)=>{let f=new Set(Object.keys(n)),p=[];for(let h of s)a(f,h,n)||p.push(h);return p.length>0?mr(c,`Missing required ${zU(p.length,\"property\",\"properties\")} ${vE(p,\"and\")}`):!0}})}function r_(e,t){var r;let s=new Set(e),a=VB[(r=t?.missingIf)!==null&&r!==void 0?r:\"missing\"];return Wr({test:(n,c)=>Object.keys(n).some(h=>a(s,h,n))?!0:mr(c,`Missing at least one property from ${vE(Array.from(s),\"or\")}`)})}function Zqe(e,t){var r;let s=new Set(e),a=VB[(r=t?.missingIf)!==null&&r!==void 0?r:\"missing\"];return Wr({test:(n,c)=>{let f=new Set(Object.keys(n)),p=[];for(let h of s)a(f,h,n)&&p.push(h);return p.length>0?mr(c,`Forbidden ${zU(p.length,\"property\",\"properties\")} ${vE(p,\"and\")}`):!0}})}function Xqe(e,t){var r;let s=new Set(e),a=VB[(r=t?.missingIf)!==null&&r!==void 0?r:\"missing\"];return Wr({test:(n,c)=>{let f=new Set(Object.keys(n)),p=[];for(let h of s)a(f,h,n)&&p.push(h);return p.length>1?mr(c,`Mutually exclusive properties ${vE(p,\"and\")}`):!0}})}function YB(e,t,r,s){var a,n;let c=new Set((a=s?.ignore)!==null&&a!==void 0?a:[]),f=VB[(n=s?.missingIf)!==null&&n!==void 0?n:\"missing\"],p=new Set(r),h=$qe[t],E=t===Vf.Forbids?\"or\":\"and\";return Wr({test:(C,S)=>{let x=new Set(Object.keys(C));if(!f(x,e,C)||c.has(C[e]))return!0;let I=[];for(let T of p)(f(x,T,C)&&!c.has(C[T]))!==h.expect&&I.push(T);return I.length>=1?mr(S,`Property \"${e}\" ${h.message} ${zU(I.length,\"property\",\"properties\")} ${vE(I,E)}`):!0}})}var pqe,hqe,gqe,dqe,mqe,Jte,Eqe,bqe,$U,i0,VB,Vf,$qe,ul=Ze(()=>{pqe=/^[a-zA-Z_][a-zA-Z0-9_]*$/;hqe=/^#[0-9a-f]{6}$/i,gqe=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,dqe=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,mqe=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,Jte=/^(?:[1-9]\\d{3}(-?)(?:(?:0[1-9]|1[0-2])\\1(?:0[1-9]|1\\d|2[0-8])|(?:0[13-9]|1[0-2])\\1(?:29|30)|(?:0[13578]|1[02])(?:\\1)31|00[1-9]|0[1-9]\\d|[12]\\d{2}|3(?:[0-5]\\d|6[0-5]))|(?:[1-9]\\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\\2)29|-?366))T(?:[01]\\d|2[0-3])(:?)[0-5]\\d(?:\\3[0-5]\\d)?(?:Z|[+-][01]\\d(?:\\3[0-5]\\d)?)$/;Eqe=new Map([[\"true\",!0],[\"True\",!0],[\"1\",!0],[1,!0],[\"false\",!1],[\"False\",!1],[\"0\",!1],[0,!1]]);bqe=e=>Wr({test:(t,r)=>t instanceof e?!0:mr(r,`Expected an instance of ${e.name} (got ${ii(t)})`)}),$U=(e,{exclusive:t=!1}={})=>Wr({test:(r,s)=>{var a,n,c;let f=[],p=typeof s?.errors<\"u\"?[]:void 0;for(let h=0,E=e.length;h<E;++h){let C=typeof s?.errors<\"u\"?[]:void 0,S=typeof s?.coercions<\"u\"?[]:void 0;if(e[h](r,Object.assign(Object.assign({},s),{errors:C,coercions:S,p:`${(a=s?.p)!==null&&a!==void 0?a:\".\"}#${h+1}`}))){if(f.push([`#${h+1}`,S]),!t)break}else p?.push(C[0])}if(f.length===1){let[,h]=f[0];return typeof h<\"u\"&&((n=s?.coercions)===null||n===void 0||n.push(...h)),!0}return f.length>1?mr(s,`Expected to match exactly a single predicate (matched ${f.join(\", \")})`):(c=s?.errors)===null||c===void 0||c.push(...p),!1}});i0=class extends Error{constructor({errors:t}={}){let r=\"Type mismatch\";if(t&&t.length>0){r+=`\n`;for(let s of t)r+=`\n- ${s}`}super(r)}};VB={missing:(e,t)=>e.has(t),undefined:(e,t,r)=>e.has(t)&&typeof r[t]<\"u\",nil:(e,t,r)=>e.has(t)&&r[t]!=null,falsy:(e,t,r)=>e.has(t)&&!!r[t]};(function(e){e.Forbids=\"Forbids\",e.Requires=\"Requires\"})(Vf||(Vf={}));$qe={[Vf.Forbids]:{expect:!1,message:\"forbids using\"},[Vf.Requires]:{expect:!0,message:\"requires using\"}}});var at,s0=Ze(()=>{wp();at=class{constructor(){this.help=!1}static Usage(t){return t}async catch(t){throw t}async validateAndExecute(){let r=this.constructor.schema;if(Array.isArray(r)){let{isDict:a,isUnknown:n,applyCascade:c}=await Promise.resolve().then(()=>(ul(),Yo)),f=c(a(n()),r),p=[],h=[];if(!f(this,{errors:p,coercions:h}))throw jB(\"Invalid option schema\",p);for(let[,C]of h)C()}else if(r!=null)throw new Error(\"Invalid command schema\");let s=await this.execute();return typeof s<\"u\"?s:0}};at.isOption=HB;at.Default=[]});function fl(e){VU&&console.log(e)}function tre(){let e={nodes:[]};for(let t=0;t<In.CustomNode;++t)e.nodes.push(Wl());return e}function e9e(e){let t=tre(),r=[],s=t.nodes.length;for(let a of e){r.push(s);for(let n=0;n<a.nodes.length;++n)nre(n)||t.nodes.push(l9e(a.nodes[n],s));s+=a.nodes.length-In.CustomNode+1}for(let a of r)DE(t,In.InitialNode,a);return t}function Fu(e,t){return e.nodes.push(t),e.nodes.length-1}function t9e(e){let t=new Set,r=s=>{if(t.has(s))return;t.add(s);let a=e.nodes[s];for(let c of Object.values(a.statics))for(let{to:f}of c)r(f);for(let[,{to:c}]of a.dynamics)r(c);for(let{to:c}of a.shortcuts)r(c);let n=new Set(a.shortcuts.map(({to:c})=>c));for(;a.shortcuts.length>0;){let{to:c}=a.shortcuts.shift(),f=e.nodes[c];for(let[p,h]of Object.entries(f.statics)){let E=Object.prototype.hasOwnProperty.call(a.statics,p)?a.statics[p]:a.statics[p]=[];for(let C of h)E.some(({to:S})=>C.to===S)||E.push(C)}for(let[p,h]of f.dynamics)a.dynamics.some(([E,{to:C}])=>p===E&&h.to===C)||a.dynamics.push([p,h]);for(let p of f.shortcuts)n.has(p.to)||(a.shortcuts.push(p),n.add(p.to))}};r(In.InitialNode)}function r9e(e,{prefix:t=\"\"}={}){if(VU){fl(`${t}Nodes are:`);for(let r=0;r<e.nodes.length;++r)fl(`${t}  ${r}: ${JSON.stringify(e.nodes[r])}`)}}function n9e(e,t,r=!1){fl(`Running a vm on ${JSON.stringify(t)}`);let s=[{node:In.InitialNode,state:{candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,options:[],path:[],positionals:[],remainder:null,selectedIndex:null,partial:!1,tokens:[]}}];r9e(e,{prefix:\"  \"});let a=[ni.StartOfInput,...t];for(let n=0;n<a.length;++n){let c=a[n],f=c===ni.EndOfInput||c===ni.EndOfPartialInput,p=n-1;fl(`  Processing ${JSON.stringify(c)}`);let h=[];for(let{node:E,state:C}of s){fl(`    Current node is ${E}`);let S=e.nodes[E];if(E===In.ErrorNode){h.push({node:E,state:C});continue}console.assert(S.shortcuts.length===0,\"Shortcuts should have been eliminated by now\");let x=Object.prototype.hasOwnProperty.call(S.statics,c);if(!r||n<a.length-1||x)if(x){let I=S.statics[c];for(let{to:T,reducer:O}of I)h.push({node:T,state:typeof O<\"u\"?Ox(i_,O,C,c,p):C}),fl(`      Static transition to ${T} found`)}else fl(\"      No static transition found\");else{let I=!1;for(let T of Object.keys(S.statics))if(T.startsWith(c)){if(c===T)for(let{to:O,reducer:U}of S.statics[T])h.push({node:O,state:typeof U<\"u\"?Ox(i_,U,C,c,p):C}),fl(`      Static transition to ${O} found`);else for(let{to:O}of S.statics[T])h.push({node:O,state:{...C,remainder:T.slice(c.length)}}),fl(`      Static transition to ${O} found (partial match)`);I=!0}I||fl(\"      No partial static transition found\")}if(!f)for(let[I,{to:T,reducer:O}]of S.dynamics)Ox(c9e,I,C,c,p)&&(h.push({node:T,state:typeof O<\"u\"?Ox(i_,O,C,c,p):C}),fl(`      Dynamic transition to ${T} found (via ${I})`))}if(h.length===0&&f&&t.length===1)return[{node:In.InitialNode,state:ere}];if(h.length===0)throw new BE(t,s.filter(({node:E})=>E!==In.ErrorNode).map(({state:E})=>({usage:E.candidateUsage,reason:null})));if(h.every(({node:E})=>E===In.ErrorNode))throw new BE(t,h.map(({state:E})=>({usage:E.candidateUsage,reason:E.errorMessage})));s=s9e(h)}if(s.length>0){fl(\"  Results:\");for(let n of s)fl(`    - ${n.node} -> ${JSON.stringify(n.state)}`)}else fl(\"  No results\");return s}function i9e(e,t,{endToken:r=ni.EndOfInput}={}){let s=n9e(e,[...t,r]);return o9e(t,s.map(({state:a})=>a))}function s9e(e){let t=0;for(let{state:r}of e)r.path.length>t&&(t=r.path.length);return e.filter(({state:r})=>r.path.length===t)}function o9e(e,t){let r=t.filter(S=>S.selectedIndex!==null),s=r.filter(S=>!S.partial);if(s.length>0&&(r=s),r.length===0)throw new Error;let a=r.filter(S=>S.selectedIndex===Td||S.requiredOptions.every(x=>x.some(I=>S.options.find(T=>T.name===I))));if(a.length===0)throw new BE(e,r.map(S=>({usage:S.candidateUsage,reason:null})));let n=0;for(let S of a)S.path.length>n&&(n=S.path.length);let c=a.filter(S=>S.path.length===n),f=S=>S.positionals.filter(({extra:x})=>!x).length+S.options.length,p=c.map(S=>({state:S,positionalCount:f(S)})),h=0;for(let{positionalCount:S}of p)S>h&&(h=S);let E=p.filter(({positionalCount:S})=>S===h).map(({state:S})=>S),C=a9e(E);if(C.length>1)throw new xx(e,C.map(S=>S.candidateUsage));return C[0]}function a9e(e){let t=[],r=[];for(let s of e)s.selectedIndex===Td?r.push(s):t.push(s);return r.length>0&&t.push({...ere,path:rre(...r.map(s=>s.path)),options:r.reduce((s,a)=>s.concat(a.options),[])}),t}function rre(e,t,...r){return t===void 0?Array.from(e):rre(e.filter((s,a)=>s===t[a]),...r)}function Wl(){return{dynamics:[],shortcuts:[],statics:{}}}function nre(e){return e===In.SuccessNode||e===In.ErrorNode}function n_(e,t=0){return{to:nre(e.to)?e.to:e.to>=In.CustomNode?e.to+t-In.CustomNode+1:e.to+t,reducer:e.reducer}}function l9e(e,t=0){let r=Wl();for(let[s,a]of e.dynamics)r.dynamics.push([s,n_(a,t)]);for(let s of e.shortcuts)r.shortcuts.push(n_(s,t));for(let[s,a]of Object.entries(e.statics))r.statics[s]=a.map(n=>n_(n,t));return r}function qs(e,t,r,s,a){e.nodes[t].dynamics.push([r,{to:s,reducer:a}])}function DE(e,t,r,s){e.nodes[t].shortcuts.push({to:r,reducer:s})}function Ba(e,t,r,s,a){(Object.prototype.hasOwnProperty.call(e.nodes[t].statics,r)?e.nodes[t].statics[r]:e.nodes[t].statics[r]=[]).push({to:s,reducer:a})}function Ox(e,t,r,s,a){if(Array.isArray(t)){let[n,...c]=t;return e[n](r,s,a,...c)}else return e[t](r,s,a)}var ere,c9e,i_,Vl,s_,Lx,Mx=Ze(()=>{Px();kx();ere={candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,path:[],positionals:[],options:[],remainder:null,selectedIndex:Td,partial:!1,tokens:[]};c9e={always:()=>!0,isOptionLike:(e,t)=>!e.ignoreOptions&&t!==\"-\"&&t.startsWith(\"-\"),isNotOptionLike:(e,t)=>e.ignoreOptions||t===\"-\"||!t.startsWith(\"-\"),isOption:(e,t,r,s)=>!e.ignoreOptions&&t===s,isBatchOption:(e,t,r,s)=>!e.ignoreOptions&&Vte.test(t)&&[...t.slice(1)].every(a=>s.has(`-${a}`)),isBoundOption:(e,t,r,s,a)=>{let n=t.match(WU);return!e.ignoreOptions&&!!n&&bx.test(n[1])&&s.has(n[1])&&a.filter(c=>c.nameSet.includes(n[1])).every(c=>c.allowBinding)},isNegatedOption:(e,t,r,s)=>!e.ignoreOptions&&t===`--no-${s.slice(2)}`,isHelp:(e,t)=>!e.ignoreOptions&&qU.test(t),isUnsupportedOption:(e,t,r,s)=>!e.ignoreOptions&&t.startsWith(\"-\")&&bx.test(t)&&!s.has(t),isInvalidOption:(e,t)=>!e.ignoreOptions&&t.startsWith(\"-\")&&!bx.test(t)},i_={setCandidateState:(e,t,r,s)=>({...e,...s}),setSelectedIndex:(e,t,r,s)=>({...e,selectedIndex:s}),setPartialIndex:(e,t,r,s)=>({...e,selectedIndex:s,partial:!0}),pushBatch:(e,t,r,s)=>{let a=e.options.slice(),n=e.tokens.slice();for(let c=1;c<t.length;++c){let f=s.get(`-${t[c]}`),p=c===1?[0,2]:[c,c+1];a.push({name:f,value:!0}),n.push({segmentIndex:r,type:\"option\",option:f,slice:p})}return{...e,options:a,tokens:n}},pushBound:(e,t,r)=>{let[,s,a]=t.match(WU),n=e.options.concat({name:s,value:a}),c=e.tokens.concat([{segmentIndex:r,type:\"option\",slice:[0,s.length],option:s},{segmentIndex:r,type:\"assign\",slice:[s.length,s.length+1]},{segmentIndex:r,type:\"value\",slice:[s.length+1,s.length+a.length+1]}]);return{...e,options:n,tokens:c}},pushPath:(e,t,r)=>{let s=e.path.concat(t),a=e.tokens.concat({segmentIndex:r,type:\"path\"});return{...e,path:s,tokens:a}},pushPositional:(e,t,r)=>{let s=e.positionals.concat({value:t,extra:!1}),a=e.tokens.concat({segmentIndex:r,type:\"positional\"});return{...e,positionals:s,tokens:a}},pushExtra:(e,t,r)=>{let s=e.positionals.concat({value:t,extra:!0}),a=e.tokens.concat({segmentIndex:r,type:\"positional\"});return{...e,positionals:s,tokens:a}},pushExtraNoLimits:(e,t,r)=>{let s=e.positionals.concat({value:t,extra:Vl}),a=e.tokens.concat({segmentIndex:r,type:\"positional\"});return{...e,positionals:s,tokens:a}},pushTrue:(e,t,r,s)=>{let a=e.options.concat({name:s,value:!0}),n=e.tokens.concat({segmentIndex:r,type:\"option\",option:s});return{...e,options:a,tokens:n}},pushFalse:(e,t,r,s)=>{let a=e.options.concat({name:s,value:!1}),n=e.tokens.concat({segmentIndex:r,type:\"option\",option:s});return{...e,options:a,tokens:n}},pushUndefined:(e,t,r,s)=>{let a=e.options.concat({name:t,value:void 0}),n=e.tokens.concat({segmentIndex:r,type:\"option\",option:t});return{...e,options:a,tokens:n}},pushStringValue:(e,t,r)=>{var s;let a=e.options[e.options.length-1],n=e.options.slice(),c=e.tokens.concat({segmentIndex:r,type:\"value\"});return a.value=((s=a.value)!==null&&s!==void 0?s:[]).concat([t]),{...e,options:n,tokens:c}},setStringValue:(e,t,r)=>{let s=e.options[e.options.length-1],a=e.options.slice(),n=e.tokens.concat({segmentIndex:r,type:\"value\"});return s.value=t,{...e,options:a,tokens:n}},inhibateOptions:e=>({...e,ignoreOptions:!0}),useHelp:(e,t,r,s)=>{let[,,a]=t.match(qU);return typeof a<\"u\"?{...e,options:[{name:\"-c\",value:String(s)},{name:\"-i\",value:a}]}:{...e,options:[{name:\"-c\",value:String(s)}]}},setError:(e,t,r,s)=>t===ni.EndOfInput||t===ni.EndOfPartialInput?{...e,errorMessage:`${s}.`}:{...e,errorMessage:`${s} (\"${t}\").`},setOptionArityError:(e,t)=>{let r=e.options[e.options.length-1];return{...e,errorMessage:`Not enough arguments to option ${r.name}.`}}},Vl=Symbol(),s_=class{constructor(t,r){this.allOptionNames=new Map,this.arity={leading:[],trailing:[],extra:[],proxy:!1},this.options=[],this.paths=[],this.cliIndex=t,this.cliOpts=r}addPath(t){this.paths.push(t)}setArity({leading:t=this.arity.leading,trailing:r=this.arity.trailing,extra:s=this.arity.extra,proxy:a=this.arity.proxy}){Object.assign(this.arity,{leading:t,trailing:r,extra:s,proxy:a})}addPositional({name:t=\"arg\",required:r=!0}={}){if(!r&&this.arity.extra===Vl)throw new Error(\"Optional parameters cannot be declared when using .rest() or .proxy()\");if(!r&&this.arity.trailing.length>0)throw new Error(\"Optional parameters cannot be declared after the required trailing positional arguments\");!r&&this.arity.extra!==Vl?this.arity.extra.push(t):this.arity.extra!==Vl&&this.arity.extra.length===0?this.arity.leading.push(t):this.arity.trailing.push(t)}addRest({name:t=\"arg\",required:r=0}={}){if(this.arity.extra===Vl)throw new Error(\"Infinite lists cannot be declared multiple times in the same command\");if(this.arity.trailing.length>0)throw new Error(\"Infinite lists cannot be declared after the required trailing positional arguments\");for(let s=0;s<r;++s)this.addPositional({name:t});this.arity.extra=Vl}addProxy({required:t=0}={}){this.addRest({required:t}),this.arity.proxy=!0}addOption({names:t,description:r,arity:s=0,hidden:a=!1,required:n=!1,allowBinding:c=!0}){if(!c&&s>1)throw new Error(\"The arity cannot be higher than 1 when the option only supports the --arg=value syntax\");if(!Number.isInteger(s))throw new Error(`The arity must be an integer, got ${s}`);if(s<0)throw new Error(`The arity must be positive, got ${s}`);let f=t.reduce((p,h)=>h.length>p.length?h:p,\"\");for(let p of t)this.allOptionNames.set(p,f);this.options.push({preferredName:f,nameSet:t,description:r,arity:s,hidden:a,required:n,allowBinding:c})}setContext(t){this.context=t}usage({detailed:t=!0,inlineOptions:r=!0}={}){let s=[this.cliOpts.binaryName],a=[];if(this.paths.length>0&&s.push(...this.paths[0]),t){for(let{preferredName:c,nameSet:f,arity:p,hidden:h,description:E,required:C}of this.options){if(h)continue;let S=[];for(let I=0;I<p;++I)S.push(` #${I}`);let x=`${f.join(\",\")}${S.join(\"\")}`;!r&&E?a.push({preferredName:c,nameSet:f,definition:x,description:E,required:C}):s.push(C?`<${x}>`:`[${x}]`)}s.push(...this.arity.leading.map(c=>`<${c}>`)),this.arity.extra===Vl?s.push(\"...\"):s.push(...this.arity.extra.map(c=>`[${c}]`)),s.push(...this.arity.trailing.map(c=>`<${c}>`))}return{usage:s.join(\" \"),options:a}}compile(){if(typeof this.context>\"u\")throw new Error(\"Assertion failed: No context attached\");let t=tre(),r=In.InitialNode,s=this.usage().usage,a=this.options.filter(f=>f.required).map(f=>f.nameSet);r=Fu(t,Wl()),Ba(t,In.InitialNode,ni.StartOfInput,r,[\"setCandidateState\",{candidateUsage:s,requiredOptions:a}]);let n=this.arity.proxy?\"always\":\"isNotOptionLike\",c=this.paths.length>0?this.paths:[[]];for(let f of c){let p=r;if(f.length>0){let S=Fu(t,Wl());DE(t,p,S),this.registerOptions(t,S),p=S}for(let S=0;S<f.length;++S){let x=Fu(t,Wl());Ba(t,p,f[S],x,\"pushPath\"),p=x}if(this.arity.leading.length>0||!this.arity.proxy){let S=Fu(t,Wl());qs(t,p,\"isHelp\",S,[\"useHelp\",this.cliIndex]),qs(t,S,\"always\",S,\"pushExtra\"),Ba(t,S,ni.EndOfInput,In.SuccessNode,[\"setSelectedIndex\",Td]),this.registerOptions(t,p)}this.arity.leading.length>0&&(Ba(t,p,ni.EndOfInput,In.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ba(t,p,ni.EndOfPartialInput,In.SuccessNode,[\"setPartialIndex\",this.cliIndex]));let h=p;for(let S=0;S<this.arity.leading.length;++S){let x=Fu(t,Wl());(!this.arity.proxy||S+1!==this.arity.leading.length)&&this.registerOptions(t,x),(this.arity.trailing.length>0||S+1!==this.arity.leading.length)&&(Ba(t,x,ni.EndOfInput,In.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ba(t,x,ni.EndOfPartialInput,In.SuccessNode,[\"setPartialIndex\",this.cliIndex])),qs(t,h,\"isNotOptionLike\",x,\"pushPositional\"),h=x}let E=h;if(this.arity.extra===Vl||this.arity.extra.length>0){let S=Fu(t,Wl());if(DE(t,h,S),this.arity.extra===Vl){let x=Fu(t,Wl());this.arity.proxy||this.registerOptions(t,x),qs(t,h,n,x,\"pushExtraNoLimits\"),qs(t,x,n,x,\"pushExtraNoLimits\"),DE(t,x,S)}else for(let x=0;x<this.arity.extra.length;++x){let I=Fu(t,Wl());(!this.arity.proxy||x>0)&&this.registerOptions(t,I),qs(t,E,n,I,\"pushExtra\"),DE(t,I,S),E=I}E=S}this.arity.trailing.length>0&&(Ba(t,E,ni.EndOfInput,In.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ba(t,E,ni.EndOfPartialInput,In.SuccessNode,[\"setPartialIndex\",this.cliIndex]));let C=E;for(let S=0;S<this.arity.trailing.length;++S){let x=Fu(t,Wl());this.arity.proxy||this.registerOptions(t,x),S+1<this.arity.trailing.length&&(Ba(t,x,ni.EndOfInput,In.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ba(t,x,ni.EndOfPartialInput,In.SuccessNode,[\"setPartialIndex\",this.cliIndex])),qs(t,C,\"isNotOptionLike\",x,\"pushPositional\"),C=x}qs(t,C,n,In.ErrorNode,[\"setError\",\"Extraneous positional argument\"]),Ba(t,C,ni.EndOfInput,In.SuccessNode,[\"setSelectedIndex\",this.cliIndex]),Ba(t,C,ni.EndOfPartialInput,In.SuccessNode,[\"setSelectedIndex\",this.cliIndex])}return{machine:t,context:this.context}}registerOptions(t,r){qs(t,r,[\"isOption\",\"--\"],r,\"inhibateOptions\"),qs(t,r,[\"isBatchOption\",this.allOptionNames],r,[\"pushBatch\",this.allOptionNames]),qs(t,r,[\"isBoundOption\",this.allOptionNames,this.options],r,\"pushBound\"),qs(t,r,[\"isUnsupportedOption\",this.allOptionNames],In.ErrorNode,[\"setError\",\"Unsupported option name\"]),qs(t,r,[\"isInvalidOption\"],In.ErrorNode,[\"setError\",\"Invalid option name\"]);for(let s of this.options)if(s.arity===0)for(let a of s.nameSet)qs(t,r,[\"isOption\",a],r,[\"pushTrue\",s.preferredName]),a.startsWith(\"--\")&&!a.startsWith(\"--no-\")&&qs(t,r,[\"isNegatedOption\",a],r,[\"pushFalse\",s.preferredName]);else{let a=Fu(t,Wl());for(let n of s.nameSet)qs(t,r,[\"isOption\",n],a,[\"pushUndefined\",s.preferredName]);for(let n=0;n<s.arity;++n){let c=Fu(t,Wl());Ba(t,a,ni.EndOfInput,In.ErrorNode,\"setOptionArityError\"),Ba(t,a,ni.EndOfPartialInput,In.ErrorNode,\"setOptionArityError\"),qs(t,a,\"isOptionLike\",In.ErrorNode,\"setOptionArityError\");let f=s.arity===1?\"setStringValue\":\"pushStringValue\";qs(t,a,\"isNotOptionLike\",c,f),a=c}DE(t,a,r)}}},Lx=class e{constructor({binaryName:t=\"...\"}={}){this.builders=[],this.opts={binaryName:t}}static build(t,r={}){return new e(r).commands(t).compile()}getBuilderByIndex(t){if(!(t>=0&&t<this.builders.length))throw new Error(`Assertion failed: Out-of-bound command index (${t})`);return this.builders[t]}commands(t){for(let r of t)r(this.command());return this}command(){let t=new s_(this.builders.length,this.opts);return this.builders.push(t),t}compile(){let t=[],r=[];for(let a of this.builders){let{machine:n,context:c}=a.compile();t.push(n),r.push(c)}let s=e9e(t);return t9e(s),{machine:s,contexts:r,process:(a,{partial:n}={})=>{let c=n?ni.EndOfPartialInput:ni.EndOfInput;return i9e(s,a,{endToken:c})}}}}});function sre(){return Ux.default&&\"getColorDepth\"in Ux.default.WriteStream.prototype?Ux.default.WriteStream.prototype.getColorDepth():process.env.FORCE_COLOR===\"0\"?1:process.env.FORCE_COLOR===\"1\"||typeof process.stdout<\"u\"&&process.stdout.isTTY?8:1}function ore(e){let t=ire;if(typeof t>\"u\"){if(e.stdout===process.stdout&&e.stderr===process.stderr)return null;let{AsyncLocalStorage:r}=Ie(\"async_hooks\");t=ire=new r;let s=process.stdout._write;process.stdout._write=function(n,c,f){let p=t.getStore();return typeof p>\"u\"?s.call(this,n,c,f):p.stdout.write(n,c,f)};let a=process.stderr._write;process.stderr._write=function(n,c,f){let p=t.getStore();return typeof p>\"u\"?a.call(this,n,c,f):p.stderr.write(n,c,f)}}return r=>t.run(e,r)}var Ux,ire,are=Ze(()=>{Ux=et(Ie(\"tty\"),1)});var _x,lre=Ze(()=>{s0();_x=class e extends at{constructor(t){super(),this.contexts=t,this.commands=[]}static from(t,r){let s=new e(r);s.path=t.path;for(let a of t.options)switch(a.name){case\"-c\":s.commands.push(Number(a.value));break;case\"-i\":s.index=Number(a.value);break}return s}async execute(){let t=this.commands;if(typeof this.index<\"u\"&&this.index>=0&&this.index<t.length&&(t=[t[this.index]]),t.length===0)this.context.stdout.write(this.cli.usage());else if(t.length===1)this.context.stdout.write(this.cli.usage(this.contexts[t[0]].commandClass,{detailed:!0}));else if(t.length>1){this.context.stdout.write(`Multiple commands match your selection:\n`),this.context.stdout.write(`\n`);let r=0;for(let s of this.commands)this.context.stdout.write(this.cli.usage(this.contexts[s].commandClass,{prefix:`${r++}. `.padStart(5)}));this.context.stdout.write(`\n`),this.context.stdout.write(`Run again with -h=<index> to see the longer details of any of those commands.\n`)}}}});async function fre(...e){let{resolvedOptions:t,resolvedCommandClasses:r,resolvedArgv:s,resolvedContext:a}=pre(e);return va.from(r,t).runExit(s,a)}async function Are(...e){let{resolvedOptions:t,resolvedCommandClasses:r,resolvedArgv:s,resolvedContext:a}=pre(e);return va.from(r,t).run(s,a)}function pre(e){let t,r,s,a;switch(typeof process<\"u\"&&typeof process.argv<\"u\"&&(s=process.argv.slice(2)),e.length){case 1:r=e[0];break;case 2:e[0]&&e[0].prototype instanceof at||Array.isArray(e[0])?(r=e[0],Array.isArray(e[1])?s=e[1]:a=e[1]):(t=e[0],r=e[1]);break;case 3:Array.isArray(e[2])?(t=e[0],r=e[1],s=e[2]):e[0]&&e[0].prototype instanceof at||Array.isArray(e[0])?(r=e[0],s=e[1],a=e[2]):(t=e[0],r=e[1],a=e[2]);break;default:t=e[0],r=e[1],s=e[2],a=e[3];break}if(typeof s>\"u\")throw new Error(\"The argv parameter must be provided when running Clipanion outside of a Node context\");return{resolvedOptions:t,resolvedCommandClasses:r,resolvedArgv:s,resolvedContext:a}}function ure(e){return e()}var cre,va,hre=Ze(()=>{Px();Mx();JU();are();s0();lre();cre=Symbol(\"clipanion/errorCommand\");va=class e{constructor({binaryLabel:t,binaryName:r=\"...\",binaryVersion:s,enableCapture:a=!1,enableColors:n}={}){this.registrations=new Map,this.builder=new Lx({binaryName:r}),this.binaryLabel=t,this.binaryName=r,this.binaryVersion=s,this.enableCapture=a,this.enableColors=n}static from(t,r={}){let s=new e(r),a=Array.isArray(t)?t:[t];for(let n of a)s.register(n);return s}register(t){var r;let s=new Map,a=new t;for(let p in a){let h=a[p];typeof h==\"object\"&&h!==null&&h[at.isOption]&&s.set(p,h)}let n=this.builder.command(),c=n.cliIndex,f=(r=t.paths)!==null&&r!==void 0?r:a.paths;if(typeof f<\"u\")for(let p of f)n.addPath(p);this.registrations.set(t,{specs:s,builder:n,index:c});for(let[p,{definition:h}]of s.entries())h(n,p);n.setContext({commandClass:t})}process(t,r){let{input:s,context:a,partial:n}=typeof t==\"object\"&&Array.isArray(t)?{input:t,context:r}:t,{contexts:c,process:f}=this.builder.compile(),p=f(s,{partial:n}),h={...e.defaultContext,...a};switch(p.selectedIndex){case Td:{let E=_x.from(p,c);return E.context=h,E.tokens=p.tokens,E}default:{let{commandClass:E}=c[p.selectedIndex],C=this.registrations.get(E);if(typeof C>\"u\")throw new Error(\"Assertion failed: Expected the command class to have been registered.\");let S=new E;S.context=h,S.tokens=p.tokens,S.path=p.path;try{for(let[x,{transformer:I}]of C.specs.entries())S[x]=I(C.builder,x,p,h);return S}catch(x){throw x[cre]=S,x}}break}}async run(t,r){var s,a;let n,c={...e.defaultContext,...r},f=(s=this.enableColors)!==null&&s!==void 0?s:c.colorDepth>1;if(!Array.isArray(t))n=t;else try{n=this.process(t,c)}catch(E){return c.stdout.write(this.error(E,{colored:f})),1}if(n.help)return c.stdout.write(this.usage(n,{colored:f,detailed:!0})),0;n.context=c,n.cli={binaryLabel:this.binaryLabel,binaryName:this.binaryName,binaryVersion:this.binaryVersion,enableCapture:this.enableCapture,enableColors:this.enableColors,definitions:()=>this.definitions(),definition:E=>this.definition(E),error:(E,C)=>this.error(E,C),format:E=>this.format(E),process:(E,C)=>this.process(E,{...c,...C}),run:(E,C)=>this.run(E,{...c,...C}),usage:(E,C)=>this.usage(E,C)};let p=this.enableCapture&&(a=ore(c))!==null&&a!==void 0?a:ure,h;try{h=await p(()=>n.validateAndExecute().catch(E=>n.catch(E).then(()=>0)))}catch(E){return c.stdout.write(this.error(E,{colored:f,command:n})),1}return h}async runExit(t,r){process.exitCode=await this.run(t,r)}definition(t,{colored:r=!1}={}){if(!t.usage)return null;let{usage:s}=this.getUsageByRegistration(t,{detailed:!1}),{usage:a,options:n}=this.getUsageByRegistration(t,{detailed:!0,inlineOptions:!1}),c=typeof t.usage.category<\"u\"?Vo(t.usage.category,{format:this.format(r),paragraphs:!1}):void 0,f=typeof t.usage.description<\"u\"?Vo(t.usage.description,{format:this.format(r),paragraphs:!1}):void 0,p=typeof t.usage.details<\"u\"?Vo(t.usage.details,{format:this.format(r),paragraphs:!0}):void 0,h=typeof t.usage.examples<\"u\"?t.usage.examples.map(([E,C])=>[Vo(E,{format:this.format(r),paragraphs:!1}),C.replace(/\\$0/g,this.binaryName)]):void 0;return{path:s,usage:a,category:c,description:f,details:p,examples:h,options:n}}definitions({colored:t=!1}={}){let r=[];for(let s of this.registrations.keys()){let a=this.definition(s,{colored:t});a&&r.push(a)}return r}usage(t=null,{colored:r,detailed:s=!1,prefix:a=\"$ \"}={}){var n;if(t===null){for(let p of this.registrations.keys()){let h=p.paths,E=typeof p.usage<\"u\";if(!h||h.length===0||h.length===1&&h[0].length===0||((n=h?.some(x=>x.length===0))!==null&&n!==void 0?n:!1))if(t){t=null;break}else t=p;else if(E){t=null;continue}}t&&(s=!0)}let c=t!==null&&t instanceof at?t.constructor:t,f=\"\";if(c)if(s){let{description:p=\"\",details:h=\"\",examples:E=[]}=c.usage||{};p!==\"\"&&(f+=Vo(p,{format:this.format(r),paragraphs:!1}).replace(/^./,x=>x.toUpperCase()),f+=`\n`),(h!==\"\"||E.length>0)&&(f+=`${this.format(r).header(\"Usage\")}\n`,f+=`\n`);let{usage:C,options:S}=this.getUsageByRegistration(c,{inlineOptions:!1});if(f+=`${this.format(r).bold(a)}${C}\n`,S.length>0){f+=`\n`,f+=`${this.format(r).header(\"Options\")}\n`;let x=S.reduce((I,T)=>Math.max(I,T.definition.length),0);f+=`\n`;for(let{definition:I,description:T}of S)f+=`  ${this.format(r).bold(I.padEnd(x))}    ${Vo(T,{format:this.format(r),paragraphs:!1})}`}if(h!==\"\"&&(f+=`\n`,f+=`${this.format(r).header(\"Details\")}\n`,f+=`\n`,f+=Vo(h,{format:this.format(r),paragraphs:!0})),E.length>0){f+=`\n`,f+=`${this.format(r).header(\"Examples\")}\n`;for(let[x,I]of E)f+=`\n`,f+=Vo(x,{format:this.format(r),paragraphs:!1}),f+=`${I.replace(/^/m,`  ${this.format(r).bold(a)}`).replace(/\\$0/g,this.binaryName)}\n`}}else{let{usage:p}=this.getUsageByRegistration(c);f+=`${this.format(r).bold(a)}${p}\n`}else{let p=new Map;for(let[S,{index:x}]of this.registrations.entries()){if(typeof S.usage>\"u\")continue;let I=typeof S.usage.category<\"u\"?Vo(S.usage.category,{format:this.format(r),paragraphs:!1}):null,T=p.get(I);typeof T>\"u\"&&p.set(I,T=[]);let{usage:O}=this.getUsageByIndex(x);T.push({commandClass:S,usage:O})}let h=Array.from(p.keys()).sort((S,x)=>S===null?-1:x===null?1:S.localeCompare(x,\"en\",{usage:\"sort\",caseFirst:\"upper\"})),E=typeof this.binaryLabel<\"u\",C=typeof this.binaryVersion<\"u\";E||C?(E&&C?f+=`${this.format(r).header(`${this.binaryLabel} - ${this.binaryVersion}`)}\n\n`:E?f+=`${this.format(r).header(`${this.binaryLabel}`)}\n`:f+=`${this.format(r).header(`${this.binaryVersion}`)}\n`,f+=`  ${this.format(r).bold(a)}${this.binaryName} <command>\n`):f+=`${this.format(r).bold(a)}${this.binaryName} <command>\n`;for(let S of h){let x=p.get(S).slice().sort((T,O)=>T.usage.localeCompare(O.usage,\"en\",{usage:\"sort\",caseFirst:\"upper\"})),I=S!==null?S.trim():\"General commands\";f+=`\n`,f+=`${this.format(r).header(`${I}`)}\n`;for(let{commandClass:T,usage:O}of x){let U=T.usage.description||\"undocumented\";f+=`\n`,f+=`  ${this.format(r).bold(O)}\n`,f+=`    ${Vo(U,{format:this.format(r),paragraphs:!1})}`}}f+=`\n`,f+=Vo(\"You can also print more details about any of these commands by calling them with the `-h,--help` flag right after the command name.\",{format:this.format(r),paragraphs:!0})}return f}error(t,r){var s,{colored:a,command:n=(s=t[cre])!==null&&s!==void 0?s:null}=r===void 0?{}:r;(!t||typeof t!=\"object\"||!(\"stack\"in t))&&(t=new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(t)})`));let c=\"\",f=t.name.replace(/([a-z])([A-Z])/g,\"$1 $2\");f===\"Error\"&&(f=\"Internal Error\"),c+=`${this.format(a).error(f)}: ${t.message}\n`;let p=t.clipanion;return typeof p<\"u\"?p.type===\"usage\"&&(c+=`\n`,c+=this.usage(n)):t.stack&&(c+=`${t.stack.replace(/^.*\\n/,\"\")}\n`),c}format(t){var r;return((r=t??this.enableColors)!==null&&r!==void 0?r:e.defaultContext.colorDepth>1)?Yte:Kte}getUsageByRegistration(t,r){let s=this.registrations.get(t);if(typeof s>\"u\")throw new Error(\"Assertion failed: Unregistered command\");return this.getUsageByIndex(s.index,r)}getUsageByIndex(t,r){return this.builder.getBuilderByIndex(t).usage(r)}};va.defaultContext={env:process.env,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr,colorDepth:sre()}});var KB,gre=Ze(()=>{s0();KB=class extends at{async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.definitions(),null,2)}\n`)}};KB.paths=[[\"--clipanion=definitions\"]]});var JB,dre=Ze(()=>{s0();JB=class extends at{async execute(){this.context.stdout.write(this.cli.usage())}};JB.paths=[[\"-h\"],[\"--help\"]]});function Hx(e={}){return wa({definition(t,r){var s;t.addProxy({name:(s=e.name)!==null&&s!==void 0?s:r,required:e.required})},transformer(t,r,s){return s.positionals.map(({value:a})=>a)}})}var o_=Ze(()=>{wp()});var zB,mre=Ze(()=>{s0();o_();zB=class extends at{constructor(){super(...arguments),this.args=Hx()}async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.process(this.args).tokens,null,2)}\n`)}};zB.paths=[[\"--clipanion=tokens\"]]});var ZB,yre=Ze(()=>{s0();ZB=class extends at{async execute(){var t;this.context.stdout.write(`${(t=this.cli.binaryVersion)!==null&&t!==void 0?t:\"<unknown>\"}\n`)}};ZB.paths=[[\"-v\"],[\"--version\"]]});var a_={};Yt(a_,{DefinitionsCommand:()=>KB,HelpCommand:()=>JB,TokensCommand:()=>zB,VersionCommand:()=>ZB});var Ere=Ze(()=>{gre();dre();mre();yre()});function Ire(e,t,r){let[s,a]=Wf(t,r??{}),{arity:n=1}=a,c=e.split(\",\"),f=new Set(c);return wa({definition(p){p.addOption({names:c,arity:n,hidden:a?.hidden,description:a?.description,required:a.required})},transformer(p,h,E){let C,S=typeof s<\"u\"?[...s]:void 0;for(let{name:x,value:I}of E.options)f.has(x)&&(C=x,S=S??[],S.push(I));return typeof S<\"u\"?Fd(C??h,S,a.validator):S}})}var Cre=Ze(()=>{wp()});function wre(e,t,r){let[s,a]=Wf(t,r??{}),n=e.split(\",\"),c=new Set(n);return wa({definition(f){f.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(f,p,h){let E=s;for(let{name:C,value:S}of h.options)c.has(C)&&(E=S);return E}})}var Bre=Ze(()=>{wp()});function vre(e,t,r){let[s,a]=Wf(t,r??{}),n=e.split(\",\"),c=new Set(n);return wa({definition(f){f.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(f,p,h){let E=s;for(let{name:C,value:S}of h.options)c.has(C)&&(E??(E=0),S?E+=1:E=0);return E}})}var Sre=Ze(()=>{wp()});function Dre(e={}){return wa({definition(t,r){var s;t.addRest({name:(s=e.name)!==null&&s!==void 0?s:r,required:e.required})},transformer(t,r,s){let a=c=>{let f=s.positionals[c];return f.extra===Vl||f.extra===!1&&c<t.arity.leading.length},n=0;for(;n<s.positionals.length&&a(n);)n+=1;return s.positionals.splice(0,n).map(({value:c})=>c)}})}var bre=Ze(()=>{Mx();wp()});function u9e(e,t,r){let[s,a]=Wf(t,r??{}),{arity:n=1}=a,c=e.split(\",\"),f=new Set(c);return wa({definition(p){p.addOption({names:c,arity:a.tolerateBoolean?0:n,hidden:a.hidden,description:a.description,required:a.required})},transformer(p,h,E,C){let S,x=s;typeof a.env<\"u\"&&C.env[a.env]&&(S=a.env,x=C.env[a.env]);for(let{name:I,value:T}of E.options)f.has(I)&&(S=I,x=T);return typeof x==\"string\"?Fd(S??h,x,a.validator):x}})}function f9e(e={}){let{required:t=!0}=e;return wa({definition(r,s){var a;r.addPositional({name:(a=e.name)!==null&&a!==void 0?a:s,required:e.required})},transformer(r,s,a){var n;for(let c=0;c<a.positionals.length;++c){if(a.positionals[c].extra===Vl||t&&a.positionals[c].extra===!0||!t&&a.positionals[c].extra===!1)continue;let[f]=a.positionals.splice(c,1);return Fd((n=e.name)!==null&&n!==void 0?n:s,f.value,e.validator)}}})}function Pre(e,...t){return typeof e==\"string\"?u9e(e,...t):f9e(e)}var xre=Ze(()=>{Mx();wp()});var he={};Yt(he,{Array:()=>Ire,Boolean:()=>wre,Counter:()=>vre,Proxy:()=>Hx,Rest:()=>Dre,String:()=>Pre,applyValidator:()=>Fd,cleanValidationError:()=>Qx,formatError:()=>jB,isOptionSymbol:()=>HB,makeCommandOption:()=>wa,rerouteArguments:()=>Wf});var kre=Ze(()=>{wp();o_();Cre();Bre();Sre();bre();xre()});var XB={};Yt(XB,{Builtins:()=>a_,Cli:()=>va,Command:()=>at,Option:()=>he,UsageError:()=>st,formatMarkdownish:()=>Vo,run:()=>Are,runExit:()=>fre});var Vt=Ze(()=>{kx();JU();s0();hre();Ere();kre()});var Qre=G((akt,A9e)=>{A9e.exports={name:\"dotenv\",version:\"16.3.1\",description:\"Loads environment variables from .env file\",main:\"lib/main.js\",types:\"lib/main.d.ts\",exports:{\".\":{types:\"./lib/main.d.ts\",require:\"./lib/main.js\",default:\"./lib/main.js\"},\"./config\":\"./config.js\",\"./config.js\":\"./config.js\",\"./lib/env-options\":\"./lib/env-options.js\",\"./lib/env-options.js\":\"./lib/env-options.js\",\"./lib/cli-options\":\"./lib/cli-options.js\",\"./lib/cli-options.js\":\"./lib/cli-options.js\",\"./package.json\":\"./package.json\"},scripts:{\"dts-check\":\"tsc --project tests/types/tsconfig.json\",lint:\"standard\",\"lint-readme\":\"standard-markdown\",pretest:\"npm run lint && npm run dts-check\",test:\"tap tests/*.js --100 -Rspec\",prerelease:\"npm test\",release:\"standard-version\"},repository:{type:\"git\",url:\"git://github.com/motdotla/dotenv.git\"},funding:\"https://github.com/motdotla/dotenv?sponsor=1\",keywords:[\"dotenv\",\"env\",\".env\",\"environment\",\"variables\",\"config\",\"settings\"],readmeFilename:\"README.md\",license:\"BSD-2-Clause\",devDependencies:{\"@definitelytyped/dtslint\":\"^0.0.133\",\"@types/node\":\"^18.11.3\",decache:\"^4.6.1\",sinon:\"^14.0.1\",standard:\"^17.0.0\",\"standard-markdown\":\"^7.1.0\",\"standard-version\":\"^9.5.0\",tap:\"^16.3.0\",tar:\"^6.1.11\",typescript:\"^4.8.4\"},engines:{node:\">=12\"},browser:{fs:!1}}});var Nre=G((lkt,Bp)=>{var Rre=Ie(\"fs\"),c_=Ie(\"path\"),p9e=Ie(\"os\"),h9e=Ie(\"crypto\"),g9e=Qre(),u_=g9e.version,d9e=/(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg;function m9e(e){let t={},r=e.toString();r=r.replace(/\\r\\n?/mg,`\n`);let s;for(;(s=d9e.exec(r))!=null;){let a=s[1],n=s[2]||\"\";n=n.trim();let c=n[0];n=n.replace(/^(['\"`])([\\s\\S]*)\\1$/mg,\"$2\"),c==='\"'&&(n=n.replace(/\\\\n/g,`\n`),n=n.replace(/\\\\r/g,\"\\r\")),t[a]=n}return t}function y9e(e){let t=Fre(e),r=Ws.configDotenv({path:t});if(!r.parsed)throw new Error(`MISSING_DATA: Cannot parse ${t} for an unknown reason`);let s=Tre(e).split(\",\"),a=s.length,n;for(let c=0;c<a;c++)try{let f=s[c].trim(),p=C9e(r,f);n=Ws.decrypt(p.ciphertext,p.key);break}catch(f){if(c+1>=a)throw f}return Ws.parse(n)}function E9e(e){console.log(`[dotenv@${u_}][INFO] ${e}`)}function I9e(e){console.log(`[dotenv@${u_}][WARN] ${e}`)}function l_(e){console.log(`[dotenv@${u_}][DEBUG] ${e}`)}function Tre(e){return e&&e.DOTENV_KEY&&e.DOTENV_KEY.length>0?e.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:\"\"}function C9e(e,t){let r;try{r=new URL(t)}catch(f){throw f.code===\"ERR_INVALID_URL\"?new Error(\"INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development\"):f}let s=r.password;if(!s)throw new Error(\"INVALID_DOTENV_KEY: Missing key part\");let a=r.searchParams.get(\"environment\");if(!a)throw new Error(\"INVALID_DOTENV_KEY: Missing environment part\");let n=`DOTENV_VAULT_${a.toUpperCase()}`,c=e.parsed[n];if(!c)throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);return{ciphertext:c,key:s}}function Fre(e){let t=c_.resolve(process.cwd(),\".env\");return e&&e.path&&e.path.length>0&&(t=e.path),t.endsWith(\".vault\")?t:`${t}.vault`}function w9e(e){return e[0]===\"~\"?c_.join(p9e.homedir(),e.slice(1)):e}function B9e(e){E9e(\"Loading env from encrypted .env.vault\");let t=Ws._parseVault(e),r=process.env;return e&&e.processEnv!=null&&(r=e.processEnv),Ws.populate(r,t,e),{parsed:t}}function v9e(e){let t=c_.resolve(process.cwd(),\".env\"),r=\"utf8\",s=!!(e&&e.debug);e&&(e.path!=null&&(t=w9e(e.path)),e.encoding!=null&&(r=e.encoding));try{let a=Ws.parse(Rre.readFileSync(t,{encoding:r})),n=process.env;return e&&e.processEnv!=null&&(n=e.processEnv),Ws.populate(n,a,e),{parsed:a}}catch(a){return s&&l_(`Failed to load ${t} ${a.message}`),{error:a}}}function S9e(e){let t=Fre(e);return Tre(e).length===0?Ws.configDotenv(e):Rre.existsSync(t)?Ws._configVault(e):(I9e(`You set DOTENV_KEY but you are missing a .env.vault file at ${t}. Did you forget to build it?`),Ws.configDotenv(e))}function D9e(e,t){let r=Buffer.from(t.slice(-64),\"hex\"),s=Buffer.from(e,\"base64\"),a=s.slice(0,12),n=s.slice(-16);s=s.slice(12,-16);try{let c=h9e.createDecipheriv(\"aes-256-gcm\",r,a);return c.setAuthTag(n),`${c.update(s)}${c.final()}`}catch(c){let f=c instanceof RangeError,p=c.message===\"Invalid key length\",h=c.message===\"Unsupported state or unable to authenticate data\";if(f||p){let E=\"INVALID_DOTENV_KEY: It must be 64 characters long (or more)\";throw new Error(E)}else if(h){let E=\"DECRYPTION_FAILED: Please check your DOTENV_KEY\";throw new Error(E)}else throw console.error(\"Error: \",c.code),console.error(\"Error: \",c.message),c}}function b9e(e,t,r={}){let s=!!(r&&r.debug),a=!!(r&&r.override);if(typeof t!=\"object\")throw new Error(\"OBJECT_REQUIRED: Please check the processEnv argument being passed to populate\");for(let n of Object.keys(t))Object.prototype.hasOwnProperty.call(e,n)?(a===!0&&(e[n]=t[n]),s&&l_(a===!0?`\"${n}\" is already defined and WAS overwritten`:`\"${n}\" is already defined and was NOT overwritten`)):e[n]=t[n]}var Ws={configDotenv:v9e,_configVault:B9e,_parseVault:y9e,config:S9e,decrypt:D9e,parse:m9e,populate:b9e};Bp.exports.configDotenv=Ws.configDotenv;Bp.exports._configVault=Ws._configVault;Bp.exports._parseVault=Ws._parseVault;Bp.exports.config=Ws.config;Bp.exports.decrypt=Ws.decrypt;Bp.exports.parse=Ws.parse;Bp.exports.populate=Ws.populate;Bp.exports=Ws});var Lre=G((ckt,Ore)=>{\"use strict\";Ore.exports=(e,...t)=>new Promise(r=>{r(e(...t))})});var Nd=G((ukt,f_)=>{\"use strict\";var P9e=Lre(),Mre=e=>{if(e<1)throw new TypeError(\"Expected `concurrency` to be a number from 1 and up\");let t=[],r=0,s=()=>{r--,t.length>0&&t.shift()()},a=(f,p,...h)=>{r++;let E=P9e(f,...h);p(E),E.then(s,s)},n=(f,p,...h)=>{r<e?a(f,p,...h):t.push(a.bind(null,f,p,...h))},c=(f,...p)=>new Promise(h=>n(f,h,...p));return Object.defineProperties(c,{activeCount:{get:()=>r},pendingCount:{get:()=>t.length}}),c};f_.exports=Mre;f_.exports.default=Mre});function Kf(e){return`YN${e.toString(10).padStart(4,\"0\")}`}function jx(e){let t=Number(e.slice(2));if(typeof Br[t]>\"u\")throw new Error(`Unknown message name: \"${e}\"`);return t}var Br,Gx=Ze(()=>{Br=(Ue=>(Ue[Ue.UNNAMED=0]=\"UNNAMED\",Ue[Ue.EXCEPTION=1]=\"EXCEPTION\",Ue[Ue.MISSING_PEER_DEPENDENCY=2]=\"MISSING_PEER_DEPENDENCY\",Ue[Ue.CYCLIC_DEPENDENCIES=3]=\"CYCLIC_DEPENDENCIES\",Ue[Ue.DISABLED_BUILD_SCRIPTS=4]=\"DISABLED_BUILD_SCRIPTS\",Ue[Ue.BUILD_DISABLED=5]=\"BUILD_DISABLED\",Ue[Ue.SOFT_LINK_BUILD=6]=\"SOFT_LINK_BUILD\",Ue[Ue.MUST_BUILD=7]=\"MUST_BUILD\",Ue[Ue.MUST_REBUILD=8]=\"MUST_REBUILD\",Ue[Ue.BUILD_FAILED=9]=\"BUILD_FAILED\",Ue[Ue.RESOLVER_NOT_FOUND=10]=\"RESOLVER_NOT_FOUND\",Ue[Ue.FETCHER_NOT_FOUND=11]=\"FETCHER_NOT_FOUND\",Ue[Ue.LINKER_NOT_FOUND=12]=\"LINKER_NOT_FOUND\",Ue[Ue.FETCH_NOT_CACHED=13]=\"FETCH_NOT_CACHED\",Ue[Ue.YARN_IMPORT_FAILED=14]=\"YARN_IMPORT_FAILED\",Ue[Ue.REMOTE_INVALID=15]=\"REMOTE_INVALID\",Ue[Ue.REMOTE_NOT_FOUND=16]=\"REMOTE_NOT_FOUND\",Ue[Ue.RESOLUTION_PACK=17]=\"RESOLUTION_PACK\",Ue[Ue.CACHE_CHECKSUM_MISMATCH=18]=\"CACHE_CHECKSUM_MISMATCH\",Ue[Ue.UNUSED_CACHE_ENTRY=19]=\"UNUSED_CACHE_ENTRY\",Ue[Ue.MISSING_LOCKFILE_ENTRY=20]=\"MISSING_LOCKFILE_ENTRY\",Ue[Ue.WORKSPACE_NOT_FOUND=21]=\"WORKSPACE_NOT_FOUND\",Ue[Ue.TOO_MANY_MATCHING_WORKSPACES=22]=\"TOO_MANY_MATCHING_WORKSPACES\",Ue[Ue.CONSTRAINTS_MISSING_DEPENDENCY=23]=\"CONSTRAINTS_MISSING_DEPENDENCY\",Ue[Ue.CONSTRAINTS_INCOMPATIBLE_DEPENDENCY=24]=\"CONSTRAINTS_INCOMPATIBLE_DEPENDENCY\",Ue[Ue.CONSTRAINTS_EXTRANEOUS_DEPENDENCY=25]=\"CONSTRAINTS_EXTRANEOUS_DEPENDENCY\",Ue[Ue.CONSTRAINTS_INVALID_DEPENDENCY=26]=\"CONSTRAINTS_INVALID_DEPENDENCY\",Ue[Ue.CANT_SUGGEST_RESOLUTIONS=27]=\"CANT_SUGGEST_RESOLUTIONS\",Ue[Ue.FROZEN_LOCKFILE_EXCEPTION=28]=\"FROZEN_LOCKFILE_EXCEPTION\",Ue[Ue.CROSS_DRIVE_VIRTUAL_LOCAL=29]=\"CROSS_DRIVE_VIRTUAL_LOCAL\",Ue[Ue.FETCH_FAILED=30]=\"FETCH_FAILED\",Ue[Ue.DANGEROUS_NODE_MODULES=31]=\"DANGEROUS_NODE_MODULES\",Ue[Ue.NODE_GYP_INJECTED=32]=\"NODE_GYP_INJECTED\",Ue[Ue.AUTHENTICATION_NOT_FOUND=33]=\"AUTHENTICATION_NOT_FOUND\",Ue[Ue.INVALID_CONFIGURATION_KEY=34]=\"INVALID_CONFIGURATION_KEY\",Ue[Ue.NETWORK_ERROR=35]=\"NETWORK_ERROR\",Ue[Ue.LIFECYCLE_SCRIPT=36]=\"LIFECYCLE_SCRIPT\",Ue[Ue.CONSTRAINTS_MISSING_FIELD=37]=\"CONSTRAINTS_MISSING_FIELD\",Ue[Ue.CONSTRAINTS_INCOMPATIBLE_FIELD=38]=\"CONSTRAINTS_INCOMPATIBLE_FIELD\",Ue[Ue.CONSTRAINTS_EXTRANEOUS_FIELD=39]=\"CONSTRAINTS_EXTRANEOUS_FIELD\",Ue[Ue.CONSTRAINTS_INVALID_FIELD=40]=\"CONSTRAINTS_INVALID_FIELD\",Ue[Ue.AUTHENTICATION_INVALID=41]=\"AUTHENTICATION_INVALID\",Ue[Ue.PROLOG_UNKNOWN_ERROR=42]=\"PROLOG_UNKNOWN_ERROR\",Ue[Ue.PROLOG_SYNTAX_ERROR=43]=\"PROLOG_SYNTAX_ERROR\",Ue[Ue.PROLOG_EXISTENCE_ERROR=44]=\"PROLOG_EXISTENCE_ERROR\",Ue[Ue.STACK_OVERFLOW_RESOLUTION=45]=\"STACK_OVERFLOW_RESOLUTION\",Ue[Ue.AUTOMERGE_FAILED_TO_PARSE=46]=\"AUTOMERGE_FAILED_TO_PARSE\",Ue[Ue.AUTOMERGE_IMMUTABLE=47]=\"AUTOMERGE_IMMUTABLE\",Ue[Ue.AUTOMERGE_SUCCESS=48]=\"AUTOMERGE_SUCCESS\",Ue[Ue.AUTOMERGE_REQUIRED=49]=\"AUTOMERGE_REQUIRED\",Ue[Ue.DEPRECATED_CLI_SETTINGS=50]=\"DEPRECATED_CLI_SETTINGS\",Ue[Ue.PLUGIN_NAME_NOT_FOUND=51]=\"PLUGIN_NAME_NOT_FOUND\",Ue[Ue.INVALID_PLUGIN_REFERENCE=52]=\"INVALID_PLUGIN_REFERENCE\",Ue[Ue.CONSTRAINTS_AMBIGUITY=53]=\"CONSTRAINTS_AMBIGUITY\",Ue[Ue.CACHE_OUTSIDE_PROJECT=54]=\"CACHE_OUTSIDE_PROJECT\",Ue[Ue.IMMUTABLE_INSTALL=55]=\"IMMUTABLE_INSTALL\",Ue[Ue.IMMUTABLE_CACHE=56]=\"IMMUTABLE_CACHE\",Ue[Ue.INVALID_MANIFEST=57]=\"INVALID_MANIFEST\",Ue[Ue.PACKAGE_PREPARATION_FAILED=58]=\"PACKAGE_PREPARATION_FAILED\",Ue[Ue.INVALID_RANGE_PEER_DEPENDENCY=59]=\"INVALID_RANGE_PEER_DEPENDENCY\",Ue[Ue.INCOMPATIBLE_PEER_DEPENDENCY=60]=\"INCOMPATIBLE_PEER_DEPENDENCY\",Ue[Ue.DEPRECATED_PACKAGE=61]=\"DEPRECATED_PACKAGE\",Ue[Ue.INCOMPATIBLE_OS=62]=\"INCOMPATIBLE_OS\",Ue[Ue.INCOMPATIBLE_CPU=63]=\"INCOMPATIBLE_CPU\",Ue[Ue.FROZEN_ARTIFACT_EXCEPTION=64]=\"FROZEN_ARTIFACT_EXCEPTION\",Ue[Ue.TELEMETRY_NOTICE=65]=\"TELEMETRY_NOTICE\",Ue[Ue.PATCH_HUNK_FAILED=66]=\"PATCH_HUNK_FAILED\",Ue[Ue.INVALID_CONFIGURATION_VALUE=67]=\"INVALID_CONFIGURATION_VALUE\",Ue[Ue.UNUSED_PACKAGE_EXTENSION=68]=\"UNUSED_PACKAGE_EXTENSION\",Ue[Ue.REDUNDANT_PACKAGE_EXTENSION=69]=\"REDUNDANT_PACKAGE_EXTENSION\",Ue[Ue.AUTO_NM_SUCCESS=70]=\"AUTO_NM_SUCCESS\",Ue[Ue.NM_CANT_INSTALL_EXTERNAL_SOFT_LINK=71]=\"NM_CANT_INSTALL_EXTERNAL_SOFT_LINK\",Ue[Ue.NM_PRESERVE_SYMLINKS_REQUIRED=72]=\"NM_PRESERVE_SYMLINKS_REQUIRED\",Ue[Ue.UPDATE_LOCKFILE_ONLY_SKIP_LINK=73]=\"UPDATE_LOCKFILE_ONLY_SKIP_LINK\",Ue[Ue.NM_HARDLINKS_MODE_DOWNGRADED=74]=\"NM_HARDLINKS_MODE_DOWNGRADED\",Ue[Ue.PROLOG_INSTANTIATION_ERROR=75]=\"PROLOG_INSTANTIATION_ERROR\",Ue[Ue.INCOMPATIBLE_ARCHITECTURE=76]=\"INCOMPATIBLE_ARCHITECTURE\",Ue[Ue.GHOST_ARCHITECTURE=77]=\"GHOST_ARCHITECTURE\",Ue[Ue.RESOLUTION_MISMATCH=78]=\"RESOLUTION_MISMATCH\",Ue[Ue.PROLOG_LIMIT_EXCEEDED=79]=\"PROLOG_LIMIT_EXCEEDED\",Ue[Ue.NETWORK_DISABLED=80]=\"NETWORK_DISABLED\",Ue[Ue.NETWORK_UNSAFE_HTTP=81]=\"NETWORK_UNSAFE_HTTP\",Ue[Ue.RESOLUTION_FAILED=82]=\"RESOLUTION_FAILED\",Ue[Ue.AUTOMERGE_GIT_ERROR=83]=\"AUTOMERGE_GIT_ERROR\",Ue[Ue.CONSTRAINTS_CHECK_FAILED=84]=\"CONSTRAINTS_CHECK_FAILED\",Ue[Ue.UPDATED_RESOLUTION_RECORD=85]=\"UPDATED_RESOLUTION_RECORD\",Ue[Ue.EXPLAIN_PEER_DEPENDENCIES_CTA=86]=\"EXPLAIN_PEER_DEPENDENCIES_CTA\",Ue[Ue.MIGRATION_SUCCESS=87]=\"MIGRATION_SUCCESS\",Ue[Ue.VERSION_NOTICE=88]=\"VERSION_NOTICE\",Ue[Ue.TIPS_NOTICE=89]=\"TIPS_NOTICE\",Ue[Ue.OFFLINE_MODE_ENABLED=90]=\"OFFLINE_MODE_ENABLED\",Ue[Ue.INVALID_PROVENANCE_ENVIRONMENT=91]=\"INVALID_PROVENANCE_ENVIRONMENT\",Ue))(Br||{})});var $B=G((Akt,Ure)=>{var x9e=\"2.0.0\",k9e=Number.MAX_SAFE_INTEGER||9007199254740991,Q9e=16,R9e=250,T9e=[\"major\",\"premajor\",\"minor\",\"preminor\",\"patch\",\"prepatch\",\"prerelease\"];Ure.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:Q9e,MAX_SAFE_BUILD_LENGTH:R9e,MAX_SAFE_INTEGER:k9e,RELEASE_TYPES:T9e,SEMVER_SPEC_VERSION:x9e,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}});var e2=G((pkt,_re)=>{var F9e=typeof process==\"object\"&&process.env&&process.env.NODE_DEBUG&&/\\bsemver\\b/i.test(process.env.NODE_DEBUG)?(...e)=>console.error(\"SEMVER\",...e):()=>{};_re.exports=F9e});var bE=G((vp,Hre)=>{var{MAX_SAFE_COMPONENT_LENGTH:A_,MAX_SAFE_BUILD_LENGTH:N9e,MAX_LENGTH:O9e}=$B(),L9e=e2();vp=Hre.exports={};var M9e=vp.re=[],U9e=vp.safeRe=[],rr=vp.src=[],nr=vp.t={},_9e=0,p_=\"[a-zA-Z0-9-]\",H9e=[[\"\\\\s\",1],[\"\\\\d\",O9e],[p_,N9e]],j9e=e=>{for(let[t,r]of H9e)e=e.split(`${t}*`).join(`${t}{0,${r}}`).split(`${t}+`).join(`${t}{1,${r}}`);return e},Kr=(e,t,r)=>{let s=j9e(t),a=_9e++;L9e(e,a,t),nr[e]=a,rr[a]=t,M9e[a]=new RegExp(t,r?\"g\":void 0),U9e[a]=new RegExp(s,r?\"g\":void 0)};Kr(\"NUMERICIDENTIFIER\",\"0|[1-9]\\\\d*\");Kr(\"NUMERICIDENTIFIERLOOSE\",\"\\\\d+\");Kr(\"NONNUMERICIDENTIFIER\",`\\\\d*[a-zA-Z-]${p_}*`);Kr(\"MAINVERSION\",`(${rr[nr.NUMERICIDENTIFIER]})\\\\.(${rr[nr.NUMERICIDENTIFIER]})\\\\.(${rr[nr.NUMERICIDENTIFIER]})`);Kr(\"MAINVERSIONLOOSE\",`(${rr[nr.NUMERICIDENTIFIERLOOSE]})\\\\.(${rr[nr.NUMERICIDENTIFIERLOOSE]})\\\\.(${rr[nr.NUMERICIDENTIFIERLOOSE]})`);Kr(\"PRERELEASEIDENTIFIER\",`(?:${rr[nr.NUMERICIDENTIFIER]}|${rr[nr.NONNUMERICIDENTIFIER]})`);Kr(\"PRERELEASEIDENTIFIERLOOSE\",`(?:${rr[nr.NUMERICIDENTIFIERLOOSE]}|${rr[nr.NONNUMERICIDENTIFIER]})`);Kr(\"PRERELEASE\",`(?:-(${rr[nr.PRERELEASEIDENTIFIER]}(?:\\\\.${rr[nr.PRERELEASEIDENTIFIER]})*))`);Kr(\"PRERELEASELOOSE\",`(?:-?(${rr[nr.PRERELEASEIDENTIFIERLOOSE]}(?:\\\\.${rr[nr.PRERELEASEIDENTIFIERLOOSE]})*))`);Kr(\"BUILDIDENTIFIER\",`${p_}+`);Kr(\"BUILD\",`(?:\\\\+(${rr[nr.BUILDIDENTIFIER]}(?:\\\\.${rr[nr.BUILDIDENTIFIER]})*))`);Kr(\"FULLPLAIN\",`v?${rr[nr.MAINVERSION]}${rr[nr.PRERELEASE]}?${rr[nr.BUILD]}?`);Kr(\"FULL\",`^${rr[nr.FULLPLAIN]}$`);Kr(\"LOOSEPLAIN\",`[v=\\\\s]*${rr[nr.MAINVERSIONLOOSE]}${rr[nr.PRERELEASELOOSE]}?${rr[nr.BUILD]}?`);Kr(\"LOOSE\",`^${rr[nr.LOOSEPLAIN]}$`);Kr(\"GTLT\",\"((?:<|>)?=?)\");Kr(\"XRANGEIDENTIFIERLOOSE\",`${rr[nr.NUMERICIDENTIFIERLOOSE]}|x|X|\\\\*`);Kr(\"XRANGEIDENTIFIER\",`${rr[nr.NUMERICIDENTIFIER]}|x|X|\\\\*`);Kr(\"XRANGEPLAIN\",`[v=\\\\s]*(${rr[nr.XRANGEIDENTIFIER]})(?:\\\\.(${rr[nr.XRANGEIDENTIFIER]})(?:\\\\.(${rr[nr.XRANGEIDENTIFIER]})(?:${rr[nr.PRERELEASE]})?${rr[nr.BUILD]}?)?)?`);Kr(\"XRANGEPLAINLOOSE\",`[v=\\\\s]*(${rr[nr.XRANGEIDENTIFIERLOOSE]})(?:\\\\.(${rr[nr.XRANGEIDENTIFIERLOOSE]})(?:\\\\.(${rr[nr.XRANGEIDENTIFIERLOOSE]})(?:${rr[nr.PRERELEASELOOSE]})?${rr[nr.BUILD]}?)?)?`);Kr(\"XRANGE\",`^${rr[nr.GTLT]}\\\\s*${rr[nr.XRANGEPLAIN]}$`);Kr(\"XRANGELOOSE\",`^${rr[nr.GTLT]}\\\\s*${rr[nr.XRANGEPLAINLOOSE]}$`);Kr(\"COERCEPLAIN\",`(^|[^\\\\d])(\\\\d{1,${A_}})(?:\\\\.(\\\\d{1,${A_}}))?(?:\\\\.(\\\\d{1,${A_}}))?`);Kr(\"COERCE\",`${rr[nr.COERCEPLAIN]}(?:$|[^\\\\d])`);Kr(\"COERCEFULL\",rr[nr.COERCEPLAIN]+`(?:${rr[nr.PRERELEASE]})?(?:${rr[nr.BUILD]})?(?:$|[^\\\\d])`);Kr(\"COERCERTL\",rr[nr.COERCE],!0);Kr(\"COERCERTLFULL\",rr[nr.COERCEFULL],!0);Kr(\"LONETILDE\",\"(?:~>?)\");Kr(\"TILDETRIM\",`(\\\\s*)${rr[nr.LONETILDE]}\\\\s+`,!0);vp.tildeTrimReplace=\"$1~\";Kr(\"TILDE\",`^${rr[nr.LONETILDE]}${rr[nr.XRANGEPLAIN]}$`);Kr(\"TILDELOOSE\",`^${rr[nr.LONETILDE]}${rr[nr.XRANGEPLAINLOOSE]}$`);Kr(\"LONECARET\",\"(?:\\\\^)\");Kr(\"CARETTRIM\",`(\\\\s*)${rr[nr.LONECARET]}\\\\s+`,!0);vp.caretTrimReplace=\"$1^\";Kr(\"CARET\",`^${rr[nr.LONECARET]}${rr[nr.XRANGEPLAIN]}$`);Kr(\"CARETLOOSE\",`^${rr[nr.LONECARET]}${rr[nr.XRANGEPLAINLOOSE]}$`);Kr(\"COMPARATORLOOSE\",`^${rr[nr.GTLT]}\\\\s*(${rr[nr.LOOSEPLAIN]})$|^$`);Kr(\"COMPARATOR\",`^${rr[nr.GTLT]}\\\\s*(${rr[nr.FULLPLAIN]})$|^$`);Kr(\"COMPARATORTRIM\",`(\\\\s*)${rr[nr.GTLT]}\\\\s*(${rr[nr.LOOSEPLAIN]}|${rr[nr.XRANGEPLAIN]})`,!0);vp.comparatorTrimReplace=\"$1$2$3\";Kr(\"HYPHENRANGE\",`^\\\\s*(${rr[nr.XRANGEPLAIN]})\\\\s+-\\\\s+(${rr[nr.XRANGEPLAIN]})\\\\s*$`);Kr(\"HYPHENRANGELOOSE\",`^\\\\s*(${rr[nr.XRANGEPLAINLOOSE]})\\\\s+-\\\\s+(${rr[nr.XRANGEPLAINLOOSE]})\\\\s*$`);Kr(\"STAR\",\"(<|>)?=?\\\\s*\\\\*\");Kr(\"GTE0\",\"^\\\\s*>=\\\\s*0\\\\.0\\\\.0\\\\s*$\");Kr(\"GTE0PRE\",\"^\\\\s*>=\\\\s*0\\\\.0\\\\.0-0\\\\s*$\")});var qx=G((hkt,jre)=>{var G9e=Object.freeze({loose:!0}),q9e=Object.freeze({}),W9e=e=>e?typeof e!=\"object\"?G9e:e:q9e;jre.exports=W9e});var h_=G((gkt,Wre)=>{var Gre=/^[0-9]+$/,qre=(e,t)=>{let r=Gre.test(e),s=Gre.test(t);return r&&s&&(e=+e,t=+t),e===t?0:r&&!s?-1:s&&!r?1:e<t?-1:1},V9e=(e,t)=>qre(t,e);Wre.exports={compareIdentifiers:qre,rcompareIdentifiers:V9e}});var Ko=G((dkt,Jre)=>{var Wx=e2(),{MAX_LENGTH:Vre,MAX_SAFE_INTEGER:Vx}=$B(),{safeRe:Yre,t:Kre}=bE(),Y9e=qx(),{compareIdentifiers:PE}=h_(),g_=class e{constructor(t,r){if(r=Y9e(r),t instanceof e){if(t.loose===!!r.loose&&t.includePrerelease===!!r.includePrerelease)return t;t=t.version}else if(typeof t!=\"string\")throw new TypeError(`Invalid version. Must be a string. Got type \"${typeof t}\".`);if(t.length>Vre)throw new TypeError(`version is longer than ${Vre} characters`);Wx(\"SemVer\",t,r),this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease;let s=t.trim().match(r.loose?Yre[Kre.LOOSE]:Yre[Kre.FULL]);if(!s)throw new TypeError(`Invalid Version: ${t}`);if(this.raw=t,this.major=+s[1],this.minor=+s[2],this.patch=+s[3],this.major>Vx||this.major<0)throw new TypeError(\"Invalid major version\");if(this.minor>Vx||this.minor<0)throw new TypeError(\"Invalid minor version\");if(this.patch>Vx||this.patch<0)throw new TypeError(\"Invalid patch version\");s[4]?this.prerelease=s[4].split(\".\").map(a=>{if(/^[0-9]+$/.test(a)){let n=+a;if(n>=0&&n<Vx)return n}return a}):this.prerelease=[],this.build=s[5]?s[5].split(\".\"):[],this.format()}format(){return this.version=`${this.major}.${this.minor}.${this.patch}`,this.prerelease.length&&(this.version+=`-${this.prerelease.join(\".\")}`),this.version}toString(){return this.version}compare(t){if(Wx(\"SemVer.compare\",this.version,this.options,t),!(t instanceof e)){if(typeof t==\"string\"&&t===this.version)return 0;t=new e(t,this.options)}return t.version===this.version?0:this.compareMain(t)||this.comparePre(t)}compareMain(t){return t instanceof e||(t=new e(t,this.options)),PE(this.major,t.major)||PE(this.minor,t.minor)||PE(this.patch,t.patch)}comparePre(t){if(t instanceof e||(t=new e(t,this.options)),this.prerelease.length&&!t.prerelease.length)return-1;if(!this.prerelease.length&&t.prerelease.length)return 1;if(!this.prerelease.length&&!t.prerelease.length)return 0;let r=0;do{let s=this.prerelease[r],a=t.prerelease[r];if(Wx(\"prerelease compare\",r,s,a),s===void 0&&a===void 0)return 0;if(a===void 0)return 1;if(s===void 0)return-1;if(s===a)continue;return PE(s,a)}while(++r)}compareBuild(t){t instanceof e||(t=new e(t,this.options));let r=0;do{let s=this.build[r],a=t.build[r];if(Wx(\"prerelease compare\",r,s,a),s===void 0&&a===void 0)return 0;if(a===void 0)return 1;if(s===void 0)return-1;if(s===a)continue;return PE(s,a)}while(++r)}inc(t,r,s){switch(t){case\"premajor\":this.prerelease.length=0,this.patch=0,this.minor=0,this.major++,this.inc(\"pre\",r,s);break;case\"preminor\":this.prerelease.length=0,this.patch=0,this.minor++,this.inc(\"pre\",r,s);break;case\"prepatch\":this.prerelease.length=0,this.inc(\"patch\",r,s),this.inc(\"pre\",r,s);break;case\"prerelease\":this.prerelease.length===0&&this.inc(\"patch\",r,s),this.inc(\"pre\",r,s);break;case\"major\":(this.minor!==0||this.patch!==0||this.prerelease.length===0)&&this.major++,this.minor=0,this.patch=0,this.prerelease=[];break;case\"minor\":(this.patch!==0||this.prerelease.length===0)&&this.minor++,this.patch=0,this.prerelease=[];break;case\"patch\":this.prerelease.length===0&&this.patch++,this.prerelease=[];break;case\"pre\":{let a=Number(s)?1:0;if(!r&&s===!1)throw new Error(\"invalid increment argument: identifier is empty\");if(this.prerelease.length===0)this.prerelease=[a];else{let n=this.prerelease.length;for(;--n>=0;)typeof this.prerelease[n]==\"number\"&&(this.prerelease[n]++,n=-2);if(n===-1){if(r===this.prerelease.join(\".\")&&s===!1)throw new Error(\"invalid increment argument: identifier already exists\");this.prerelease.push(a)}}if(r){let n=[r,a];s===!1&&(n=[r]),PE(this.prerelease[0],r)===0?isNaN(this.prerelease[1])&&(this.prerelease=n):this.prerelease=n}break}default:throw new Error(`invalid increment argument: ${t}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(\".\")}`),this}};Jre.exports=g_});var Od=G((mkt,Zre)=>{var zre=Ko(),K9e=(e,t,r=!1)=>{if(e instanceof zre)return e;try{return new zre(e,t)}catch(s){if(!r)return null;throw s}};Zre.exports=K9e});var $re=G((ykt,Xre)=>{var J9e=Od(),z9e=(e,t)=>{let r=J9e(e,t);return r?r.version:null};Xre.exports=z9e});var tne=G((Ekt,ene)=>{var Z9e=Od(),X9e=(e,t)=>{let r=Z9e(e.trim().replace(/^[=v]+/,\"\"),t);return r?r.version:null};ene.exports=X9e});var ine=G((Ikt,nne)=>{var rne=Ko(),$9e=(e,t,r,s,a)=>{typeof r==\"string\"&&(a=s,s=r,r=void 0);try{return new rne(e instanceof rne?e.version:e,r).inc(t,s,a).version}catch{return null}};nne.exports=$9e});var ane=G((Ckt,one)=>{var sne=Od(),eWe=(e,t)=>{let r=sne(e,null,!0),s=sne(t,null,!0),a=r.compare(s);if(a===0)return null;let n=a>0,c=n?r:s,f=n?s:r,p=!!c.prerelease.length;if(!!f.prerelease.length&&!p)return!f.patch&&!f.minor?\"major\":c.patch?\"patch\":c.minor?\"minor\":\"major\";let E=p?\"pre\":\"\";return r.major!==s.major?E+\"major\":r.minor!==s.minor?E+\"minor\":r.patch!==s.patch?E+\"patch\":\"prerelease\"};one.exports=eWe});var cne=G((wkt,lne)=>{var tWe=Ko(),rWe=(e,t)=>new tWe(e,t).major;lne.exports=rWe});var fne=G((Bkt,une)=>{var nWe=Ko(),iWe=(e,t)=>new nWe(e,t).minor;une.exports=iWe});var pne=G((vkt,Ane)=>{var sWe=Ko(),oWe=(e,t)=>new sWe(e,t).patch;Ane.exports=oWe});var gne=G((Skt,hne)=>{var aWe=Od(),lWe=(e,t)=>{let r=aWe(e,t);return r&&r.prerelease.length?r.prerelease:null};hne.exports=lWe});var vc=G((Dkt,mne)=>{var dne=Ko(),cWe=(e,t,r)=>new dne(e,r).compare(new dne(t,r));mne.exports=cWe});var Ene=G((bkt,yne)=>{var uWe=vc(),fWe=(e,t,r)=>uWe(t,e,r);yne.exports=fWe});var Cne=G((Pkt,Ine)=>{var AWe=vc(),pWe=(e,t)=>AWe(e,t,!0);Ine.exports=pWe});var Yx=G((xkt,Bne)=>{var wne=Ko(),hWe=(e,t,r)=>{let s=new wne(e,r),a=new wne(t,r);return s.compare(a)||s.compareBuild(a)};Bne.exports=hWe});var Sne=G((kkt,vne)=>{var gWe=Yx(),dWe=(e,t)=>e.sort((r,s)=>gWe(r,s,t));vne.exports=dWe});var bne=G((Qkt,Dne)=>{var mWe=Yx(),yWe=(e,t)=>e.sort((r,s)=>mWe(s,r,t));Dne.exports=yWe});var t2=G((Rkt,Pne)=>{var EWe=vc(),IWe=(e,t,r)=>EWe(e,t,r)>0;Pne.exports=IWe});var Kx=G((Tkt,xne)=>{var CWe=vc(),wWe=(e,t,r)=>CWe(e,t,r)<0;xne.exports=wWe});var d_=G((Fkt,kne)=>{var BWe=vc(),vWe=(e,t,r)=>BWe(e,t,r)===0;kne.exports=vWe});var m_=G((Nkt,Qne)=>{var SWe=vc(),DWe=(e,t,r)=>SWe(e,t,r)!==0;Qne.exports=DWe});var Jx=G((Okt,Rne)=>{var bWe=vc(),PWe=(e,t,r)=>bWe(e,t,r)>=0;Rne.exports=PWe});var zx=G((Lkt,Tne)=>{var xWe=vc(),kWe=(e,t,r)=>xWe(e,t,r)<=0;Tne.exports=kWe});var y_=G((Mkt,Fne)=>{var QWe=d_(),RWe=m_(),TWe=t2(),FWe=Jx(),NWe=Kx(),OWe=zx(),LWe=(e,t,r,s)=>{switch(t){case\"===\":return typeof e==\"object\"&&(e=e.version),typeof r==\"object\"&&(r=r.version),e===r;case\"!==\":return typeof e==\"object\"&&(e=e.version),typeof r==\"object\"&&(r=r.version),e!==r;case\"\":case\"=\":case\"==\":return QWe(e,r,s);case\"!=\":return RWe(e,r,s);case\">\":return TWe(e,r,s);case\">=\":return FWe(e,r,s);case\"<\":return NWe(e,r,s);case\"<=\":return OWe(e,r,s);default:throw new TypeError(`Invalid operator: ${t}`)}};Fne.exports=LWe});var One=G((Ukt,Nne)=>{var MWe=Ko(),UWe=Od(),{safeRe:Zx,t:Xx}=bE(),_We=(e,t)=>{if(e instanceof MWe)return e;if(typeof e==\"number\"&&(e=String(e)),typeof e!=\"string\")return null;t=t||{};let r=null;if(!t.rtl)r=e.match(t.includePrerelease?Zx[Xx.COERCEFULL]:Zx[Xx.COERCE]);else{let p=t.includePrerelease?Zx[Xx.COERCERTLFULL]:Zx[Xx.COERCERTL],h;for(;(h=p.exec(e))&&(!r||r.index+r[0].length!==e.length);)(!r||h.index+h[0].length!==r.index+r[0].length)&&(r=h),p.lastIndex=h.index+h[1].length+h[2].length;p.lastIndex=-1}if(r===null)return null;let s=r[2],a=r[3]||\"0\",n=r[4]||\"0\",c=t.includePrerelease&&r[5]?`-${r[5]}`:\"\",f=t.includePrerelease&&r[6]?`+${r[6]}`:\"\";return UWe(`${s}.${a}.${n}${c}${f}`,t)};Nne.exports=_We});var Mne=G((_kt,Lne)=>{\"use strict\";Lne.exports=function(e){e.prototype[Symbol.iterator]=function*(){for(let t=this.head;t;t=t.next)yield t.value}}});var _ne=G((Hkt,Une)=>{\"use strict\";Une.exports=On;On.Node=Ld;On.create=On;function On(e){var t=this;if(t instanceof On||(t=new On),t.tail=null,t.head=null,t.length=0,e&&typeof e.forEach==\"function\")e.forEach(function(a){t.push(a)});else if(arguments.length>0)for(var r=0,s=arguments.length;r<s;r++)t.push(arguments[r]);return t}On.prototype.removeNode=function(e){if(e.list!==this)throw new Error(\"removing node which does not belong to this list\");var t=e.next,r=e.prev;return t&&(t.prev=r),r&&(r.next=t),e===this.head&&(this.head=t),e===this.tail&&(this.tail=r),e.list.length--,e.next=null,e.prev=null,e.list=null,t};On.prototype.unshiftNode=function(e){if(e!==this.head){e.list&&e.list.removeNode(e);var t=this.head;e.list=this,e.next=t,t&&(t.prev=e),this.head=e,this.tail||(this.tail=e),this.length++}};On.prototype.pushNode=function(e){if(e!==this.tail){e.list&&e.list.removeNode(e);var t=this.tail;e.list=this,e.prev=t,t&&(t.next=e),this.tail=e,this.head||(this.head=e),this.length++}};On.prototype.push=function(){for(var e=0,t=arguments.length;e<t;e++)jWe(this,arguments[e]);return this.length};On.prototype.unshift=function(){for(var e=0,t=arguments.length;e<t;e++)GWe(this,arguments[e]);return this.length};On.prototype.pop=function(){if(this.tail){var e=this.tail.value;return this.tail=this.tail.prev,this.tail?this.tail.next=null:this.head=null,this.length--,e}};On.prototype.shift=function(){if(this.head){var e=this.head.value;return this.head=this.head.next,this.head?this.head.prev=null:this.tail=null,this.length--,e}};On.prototype.forEach=function(e,t){t=t||this;for(var r=this.head,s=0;r!==null;s++)e.call(t,r.value,s,this),r=r.next};On.prototype.forEachReverse=function(e,t){t=t||this;for(var r=this.tail,s=this.length-1;r!==null;s--)e.call(t,r.value,s,this),r=r.prev};On.prototype.get=function(e){for(var t=0,r=this.head;r!==null&&t<e;t++)r=r.next;if(t===e&&r!==null)return r.value};On.prototype.getReverse=function(e){for(var t=0,r=this.tail;r!==null&&t<e;t++)r=r.prev;if(t===e&&r!==null)return r.value};On.prototype.map=function(e,t){t=t||this;for(var r=new On,s=this.head;s!==null;)r.push(e.call(t,s.value,this)),s=s.next;return r};On.prototype.mapReverse=function(e,t){t=t||this;for(var r=new On,s=this.tail;s!==null;)r.push(e.call(t,s.value,this)),s=s.prev;return r};On.prototype.reduce=function(e,t){var r,s=this.head;if(arguments.length>1)r=t;else if(this.head)s=this.head.next,r=this.head.value;else throw new TypeError(\"Reduce of empty list with no initial value\");for(var a=0;s!==null;a++)r=e(r,s.value,a),s=s.next;return r};On.prototype.reduceReverse=function(e,t){var r,s=this.tail;if(arguments.length>1)r=t;else if(this.tail)s=this.tail.prev,r=this.tail.value;else throw new TypeError(\"Reduce of empty list with no initial value\");for(var a=this.length-1;s!==null;a--)r=e(r,s.value,a),s=s.prev;return r};On.prototype.toArray=function(){for(var e=new Array(this.length),t=0,r=this.head;r!==null;t++)e[t]=r.value,r=r.next;return e};On.prototype.toArrayReverse=function(){for(var e=new Array(this.length),t=0,r=this.tail;r!==null;t++)e[t]=r.value,r=r.prev;return e};On.prototype.slice=function(e,t){t=t||this.length,t<0&&(t+=this.length),e=e||0,e<0&&(e+=this.length);var r=new On;if(t<e||t<0)return r;e<0&&(e=0),t>this.length&&(t=this.length);for(var s=0,a=this.head;a!==null&&s<e;s++)a=a.next;for(;a!==null&&s<t;s++,a=a.next)r.push(a.value);return r};On.prototype.sliceReverse=function(e,t){t=t||this.length,t<0&&(t+=this.length),e=e||0,e<0&&(e+=this.length);var r=new On;if(t<e||t<0)return r;e<0&&(e=0),t>this.length&&(t=this.length);for(var s=this.length,a=this.tail;a!==null&&s>t;s--)a=a.prev;for(;a!==null&&s>e;s--,a=a.prev)r.push(a.value);return r};On.prototype.splice=function(e,t,...r){e>this.length&&(e=this.length-1),e<0&&(e=this.length+e);for(var s=0,a=this.head;a!==null&&s<e;s++)a=a.next;for(var n=[],s=0;a&&s<t;s++)n.push(a.value),a=this.removeNode(a);a===null&&(a=this.tail),a!==this.head&&a!==this.tail&&(a=a.prev);for(var s=0;s<r.length;s++)a=HWe(this,a,r[s]);return n};On.prototype.reverse=function(){for(var e=this.head,t=this.tail,r=e;r!==null;r=r.prev){var s=r.prev;r.prev=r.next,r.next=s}return this.head=t,this.tail=e,this};function HWe(e,t,r){var s=t===e.head?new Ld(r,null,t,e):new Ld(r,t,t.next,e);return s.next===null&&(e.tail=s),s.prev===null&&(e.head=s),e.length++,s}function jWe(e,t){e.tail=new Ld(t,e.tail,null,e),e.head||(e.head=e.tail),e.length++}function GWe(e,t){e.head=new Ld(t,null,e.head,e),e.tail||(e.tail=e.head),e.length++}function Ld(e,t,r,s){if(!(this instanceof Ld))return new Ld(e,t,r,s);this.list=s,this.value=e,t?(t.next=this,this.prev=t):this.prev=null,r?(r.prev=this,this.next=r):this.next=null}try{Mne()(On)}catch{}});var Wne=G((jkt,qne)=>{\"use strict\";var qWe=_ne(),Md=Symbol(\"max\"),Dp=Symbol(\"length\"),xE=Symbol(\"lengthCalculator\"),n2=Symbol(\"allowStale\"),Ud=Symbol(\"maxAge\"),Sp=Symbol(\"dispose\"),Hne=Symbol(\"noDisposeOnSet\"),Vs=Symbol(\"lruList\"),Nu=Symbol(\"cache\"),Gne=Symbol(\"updateAgeOnGet\"),E_=()=>1,C_=class{constructor(t){if(typeof t==\"number\"&&(t={max:t}),t||(t={}),t.max&&(typeof t.max!=\"number\"||t.max<0))throw new TypeError(\"max must be a non-negative number\");let r=this[Md]=t.max||1/0,s=t.length||E_;if(this[xE]=typeof s!=\"function\"?E_:s,this[n2]=t.stale||!1,t.maxAge&&typeof t.maxAge!=\"number\")throw new TypeError(\"maxAge must be a number\");this[Ud]=t.maxAge||0,this[Sp]=t.dispose,this[Hne]=t.noDisposeOnSet||!1,this[Gne]=t.updateAgeOnGet||!1,this.reset()}set max(t){if(typeof t!=\"number\"||t<0)throw new TypeError(\"max must be a non-negative number\");this[Md]=t||1/0,r2(this)}get max(){return this[Md]}set allowStale(t){this[n2]=!!t}get allowStale(){return this[n2]}set maxAge(t){if(typeof t!=\"number\")throw new TypeError(\"maxAge must be a non-negative number\");this[Ud]=t,r2(this)}get maxAge(){return this[Ud]}set lengthCalculator(t){typeof t!=\"function\"&&(t=E_),t!==this[xE]&&(this[xE]=t,this[Dp]=0,this[Vs].forEach(r=>{r.length=this[xE](r.value,r.key),this[Dp]+=r.length})),r2(this)}get lengthCalculator(){return this[xE]}get length(){return this[Dp]}get itemCount(){return this[Vs].length}rforEach(t,r){r=r||this;for(let s=this[Vs].tail;s!==null;){let a=s.prev;jne(this,t,s,r),s=a}}forEach(t,r){r=r||this;for(let s=this[Vs].head;s!==null;){let a=s.next;jne(this,t,s,r),s=a}}keys(){return this[Vs].toArray().map(t=>t.key)}values(){return this[Vs].toArray().map(t=>t.value)}reset(){this[Sp]&&this[Vs]&&this[Vs].length&&this[Vs].forEach(t=>this[Sp](t.key,t.value)),this[Nu]=new Map,this[Vs]=new qWe,this[Dp]=0}dump(){return this[Vs].map(t=>$x(this,t)?!1:{k:t.key,v:t.value,e:t.now+(t.maxAge||0)}).toArray().filter(t=>t)}dumpLru(){return this[Vs]}set(t,r,s){if(s=s||this[Ud],s&&typeof s!=\"number\")throw new TypeError(\"maxAge must be a number\");let a=s?Date.now():0,n=this[xE](r,t);if(this[Nu].has(t)){if(n>this[Md])return kE(this,this[Nu].get(t)),!1;let p=this[Nu].get(t).value;return this[Sp]&&(this[Hne]||this[Sp](t,p.value)),p.now=a,p.maxAge=s,p.value=r,this[Dp]+=n-p.length,p.length=n,this.get(t),r2(this),!0}let c=new w_(t,r,n,a,s);return c.length>this[Md]?(this[Sp]&&this[Sp](t,r),!1):(this[Dp]+=c.length,this[Vs].unshift(c),this[Nu].set(t,this[Vs].head),r2(this),!0)}has(t){if(!this[Nu].has(t))return!1;let r=this[Nu].get(t).value;return!$x(this,r)}get(t){return I_(this,t,!0)}peek(t){return I_(this,t,!1)}pop(){let t=this[Vs].tail;return t?(kE(this,t),t.value):null}del(t){kE(this,this[Nu].get(t))}load(t){this.reset();let r=Date.now();for(let s=t.length-1;s>=0;s--){let a=t[s],n=a.e||0;if(n===0)this.set(a.k,a.v);else{let c=n-r;c>0&&this.set(a.k,a.v,c)}}}prune(){this[Nu].forEach((t,r)=>I_(this,r,!1))}},I_=(e,t,r)=>{let s=e[Nu].get(t);if(s){let a=s.value;if($x(e,a)){if(kE(e,s),!e[n2])return}else r&&(e[Gne]&&(s.value.now=Date.now()),e[Vs].unshiftNode(s));return a.value}},$x=(e,t)=>{if(!t||!t.maxAge&&!e[Ud])return!1;let r=Date.now()-t.now;return t.maxAge?r>t.maxAge:e[Ud]&&r>e[Ud]},r2=e=>{if(e[Dp]>e[Md])for(let t=e[Vs].tail;e[Dp]>e[Md]&&t!==null;){let r=t.prev;kE(e,t),t=r}},kE=(e,t)=>{if(t){let r=t.value;e[Sp]&&e[Sp](r.key,r.value),e[Dp]-=r.length,e[Nu].delete(r.key),e[Vs].removeNode(t)}},w_=class{constructor(t,r,s,a,n){this.key=t,this.value=r,this.length=s,this.now=a,this.maxAge=n||0}},jne=(e,t,r,s)=>{let a=r.value;$x(e,a)&&(kE(e,r),e[n2]||(a=void 0)),a&&t.call(s,a.value,a.key,e)};qne.exports=C_});var Sc=G((Gkt,Jne)=>{var B_=class e{constructor(t,r){if(r=VWe(r),t instanceof e)return t.loose===!!r.loose&&t.includePrerelease===!!r.includePrerelease?t:new e(t.raw,r);if(t instanceof v_)return this.raw=t.value,this.set=[[t]],this.format(),this;if(this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease,this.raw=t.trim().split(/\\s+/).join(\" \"),this.set=this.raw.split(\"||\").map(s=>this.parseRange(s.trim())).filter(s=>s.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){let s=this.set[0];if(this.set=this.set.filter(a=>!Yne(a[0])),this.set.length===0)this.set=[s];else if(this.set.length>1){for(let a of this.set)if(a.length===1&&$We(a[0])){this.set=[a];break}}}this.format()}format(){return this.range=this.set.map(t=>t.join(\" \").trim()).join(\"||\").trim(),this.range}toString(){return this.range}parseRange(t){let s=((this.options.includePrerelease&&ZWe)|(this.options.loose&&XWe))+\":\"+t,a=Vne.get(s);if(a)return a;let n=this.options.loose,c=n?Al[Sa.HYPHENRANGELOOSE]:Al[Sa.HYPHENRANGE];t=t.replace(c,cVe(this.options.includePrerelease)),Si(\"hyphen replace\",t),t=t.replace(Al[Sa.COMPARATORTRIM],KWe),Si(\"comparator trim\",t),t=t.replace(Al[Sa.TILDETRIM],JWe),Si(\"tilde trim\",t),t=t.replace(Al[Sa.CARETTRIM],zWe),Si(\"caret trim\",t);let f=t.split(\" \").map(C=>eVe(C,this.options)).join(\" \").split(/\\s+/).map(C=>lVe(C,this.options));n&&(f=f.filter(C=>(Si(\"loose invalid filter\",C,this.options),!!C.match(Al[Sa.COMPARATORLOOSE])))),Si(\"range list\",f);let p=new Map,h=f.map(C=>new v_(C,this.options));for(let C of h){if(Yne(C))return[C];p.set(C.value,C)}p.size>1&&p.has(\"\")&&p.delete(\"\");let E=[...p.values()];return Vne.set(s,E),E}intersects(t,r){if(!(t instanceof e))throw new TypeError(\"a Range is required\");return this.set.some(s=>Kne(s,r)&&t.set.some(a=>Kne(a,r)&&s.every(n=>a.every(c=>n.intersects(c,r)))))}test(t){if(!t)return!1;if(typeof t==\"string\")try{t=new YWe(t,this.options)}catch{return!1}for(let r=0;r<this.set.length;r++)if(uVe(this.set[r],t,this.options))return!0;return!1}};Jne.exports=B_;var WWe=Wne(),Vne=new WWe({max:1e3}),VWe=qx(),v_=i2(),Si=e2(),YWe=Ko(),{safeRe:Al,t:Sa,comparatorTrimReplace:KWe,tildeTrimReplace:JWe,caretTrimReplace:zWe}=bE(),{FLAG_INCLUDE_PRERELEASE:ZWe,FLAG_LOOSE:XWe}=$B(),Yne=e=>e.value===\"<0.0.0-0\",$We=e=>e.value===\"\",Kne=(e,t)=>{let r=!0,s=e.slice(),a=s.pop();for(;r&&s.length;)r=s.every(n=>a.intersects(n,t)),a=s.pop();return r},eVe=(e,t)=>(Si(\"comp\",e,t),e=nVe(e,t),Si(\"caret\",e),e=tVe(e,t),Si(\"tildes\",e),e=sVe(e,t),Si(\"xrange\",e),e=aVe(e,t),Si(\"stars\",e),e),Da=e=>!e||e.toLowerCase()===\"x\"||e===\"*\",tVe=(e,t)=>e.trim().split(/\\s+/).map(r=>rVe(r,t)).join(\" \"),rVe=(e,t)=>{let r=t.loose?Al[Sa.TILDELOOSE]:Al[Sa.TILDE];return e.replace(r,(s,a,n,c,f)=>{Si(\"tilde\",e,s,a,n,c,f);let p;return Da(a)?p=\"\":Da(n)?p=`>=${a}.0.0 <${+a+1}.0.0-0`:Da(c)?p=`>=${a}.${n}.0 <${a}.${+n+1}.0-0`:f?(Si(\"replaceTilde pr\",f),p=`>=${a}.${n}.${c}-${f} <${a}.${+n+1}.0-0`):p=`>=${a}.${n}.${c} <${a}.${+n+1}.0-0`,Si(\"tilde return\",p),p})},nVe=(e,t)=>e.trim().split(/\\s+/).map(r=>iVe(r,t)).join(\" \"),iVe=(e,t)=>{Si(\"caret\",e,t);let r=t.loose?Al[Sa.CARETLOOSE]:Al[Sa.CARET],s=t.includePrerelease?\"-0\":\"\";return e.replace(r,(a,n,c,f,p)=>{Si(\"caret\",e,a,n,c,f,p);let h;return Da(n)?h=\"\":Da(c)?h=`>=${n}.0.0${s} <${+n+1}.0.0-0`:Da(f)?n===\"0\"?h=`>=${n}.${c}.0${s} <${n}.${+c+1}.0-0`:h=`>=${n}.${c}.0${s} <${+n+1}.0.0-0`:p?(Si(\"replaceCaret pr\",p),n===\"0\"?c===\"0\"?h=`>=${n}.${c}.${f}-${p} <${n}.${c}.${+f+1}-0`:h=`>=${n}.${c}.${f}-${p} <${n}.${+c+1}.0-0`:h=`>=${n}.${c}.${f}-${p} <${+n+1}.0.0-0`):(Si(\"no pr\"),n===\"0\"?c===\"0\"?h=`>=${n}.${c}.${f}${s} <${n}.${c}.${+f+1}-0`:h=`>=${n}.${c}.${f}${s} <${n}.${+c+1}.0-0`:h=`>=${n}.${c}.${f} <${+n+1}.0.0-0`),Si(\"caret return\",h),h})},sVe=(e,t)=>(Si(\"replaceXRanges\",e,t),e.split(/\\s+/).map(r=>oVe(r,t)).join(\" \")),oVe=(e,t)=>{e=e.trim();let r=t.loose?Al[Sa.XRANGELOOSE]:Al[Sa.XRANGE];return e.replace(r,(s,a,n,c,f,p)=>{Si(\"xRange\",e,s,a,n,c,f,p);let h=Da(n),E=h||Da(c),C=E||Da(f),S=C;return a===\"=\"&&S&&(a=\"\"),p=t.includePrerelease?\"-0\":\"\",h?a===\">\"||a===\"<\"?s=\"<0.0.0-0\":s=\"*\":a&&S?(E&&(c=0),f=0,a===\">\"?(a=\">=\",E?(n=+n+1,c=0,f=0):(c=+c+1,f=0)):a===\"<=\"&&(a=\"<\",E?n=+n+1:c=+c+1),a===\"<\"&&(p=\"-0\"),s=`${a+n}.${c}.${f}${p}`):E?s=`>=${n}.0.0${p} <${+n+1}.0.0-0`:C&&(s=`>=${n}.${c}.0${p} <${n}.${+c+1}.0-0`),Si(\"xRange return\",s),s})},aVe=(e,t)=>(Si(\"replaceStars\",e,t),e.trim().replace(Al[Sa.STAR],\"\")),lVe=(e,t)=>(Si(\"replaceGTE0\",e,t),e.trim().replace(Al[t.includePrerelease?Sa.GTE0PRE:Sa.GTE0],\"\")),cVe=e=>(t,r,s,a,n,c,f,p,h,E,C,S,x)=>(Da(s)?r=\"\":Da(a)?r=`>=${s}.0.0${e?\"-0\":\"\"}`:Da(n)?r=`>=${s}.${a}.0${e?\"-0\":\"\"}`:c?r=`>=${r}`:r=`>=${r}${e?\"-0\":\"\"}`,Da(h)?p=\"\":Da(E)?p=`<${+h+1}.0.0-0`:Da(C)?p=`<${h}.${+E+1}.0-0`:S?p=`<=${h}.${E}.${C}-${S}`:e?p=`<${h}.${E}.${+C+1}-0`:p=`<=${p}`,`${r} ${p}`.trim()),uVe=(e,t,r)=>{for(let s=0;s<e.length;s++)if(!e[s].test(t))return!1;if(t.prerelease.length&&!r.includePrerelease){for(let s=0;s<e.length;s++)if(Si(e[s].semver),e[s].semver!==v_.ANY&&e[s].semver.prerelease.length>0){let a=e[s].semver;if(a.major===t.major&&a.minor===t.minor&&a.patch===t.patch)return!0}return!1}return!0}});var i2=G((qkt,tie)=>{var s2=Symbol(\"SemVer ANY\"),b_=class e{static get ANY(){return s2}constructor(t,r){if(r=zne(r),t instanceof e){if(t.loose===!!r.loose)return t;t=t.value}t=t.trim().split(/\\s+/).join(\" \"),D_(\"comparator\",t,r),this.options=r,this.loose=!!r.loose,this.parse(t),this.semver===s2?this.value=\"\":this.value=this.operator+this.semver.version,D_(\"comp\",this)}parse(t){let r=this.options.loose?Zne[Xne.COMPARATORLOOSE]:Zne[Xne.COMPARATOR],s=t.match(r);if(!s)throw new TypeError(`Invalid comparator: ${t}`);this.operator=s[1]!==void 0?s[1]:\"\",this.operator===\"=\"&&(this.operator=\"\"),s[2]?this.semver=new $ne(s[2],this.options.loose):this.semver=s2}toString(){return this.value}test(t){if(D_(\"Comparator.test\",t,this.options.loose),this.semver===s2||t===s2)return!0;if(typeof t==\"string\")try{t=new $ne(t,this.options)}catch{return!1}return S_(t,this.operator,this.semver,this.options)}intersects(t,r){if(!(t instanceof e))throw new TypeError(\"a Comparator is required\");return this.operator===\"\"?this.value===\"\"?!0:new eie(t.value,r).test(this.value):t.operator===\"\"?t.value===\"\"?!0:new eie(this.value,r).test(t.semver):(r=zne(r),r.includePrerelease&&(this.value===\"<0.0.0-0\"||t.value===\"<0.0.0-0\")||!r.includePrerelease&&(this.value.startsWith(\"<0.0.0\")||t.value.startsWith(\"<0.0.0\"))?!1:!!(this.operator.startsWith(\">\")&&t.operator.startsWith(\">\")||this.operator.startsWith(\"<\")&&t.operator.startsWith(\"<\")||this.semver.version===t.semver.version&&this.operator.includes(\"=\")&&t.operator.includes(\"=\")||S_(this.semver,\"<\",t.semver,r)&&this.operator.startsWith(\">\")&&t.operator.startsWith(\"<\")||S_(this.semver,\">\",t.semver,r)&&this.operator.startsWith(\"<\")&&t.operator.startsWith(\">\")))}};tie.exports=b_;var zne=qx(),{safeRe:Zne,t:Xne}=bE(),S_=y_(),D_=e2(),$ne=Ko(),eie=Sc()});var o2=G((Wkt,rie)=>{var fVe=Sc(),AVe=(e,t,r)=>{try{t=new fVe(t,r)}catch{return!1}return t.test(e)};rie.exports=AVe});var iie=G((Vkt,nie)=>{var pVe=Sc(),hVe=(e,t)=>new pVe(e,t).set.map(r=>r.map(s=>s.value).join(\" \").trim().split(\" \"));nie.exports=hVe});var oie=G((Ykt,sie)=>{var gVe=Ko(),dVe=Sc(),mVe=(e,t,r)=>{let s=null,a=null,n=null;try{n=new dVe(t,r)}catch{return null}return e.forEach(c=>{n.test(c)&&(!s||a.compare(c)===-1)&&(s=c,a=new gVe(s,r))}),s};sie.exports=mVe});var lie=G((Kkt,aie)=>{var yVe=Ko(),EVe=Sc(),IVe=(e,t,r)=>{let s=null,a=null,n=null;try{n=new EVe(t,r)}catch{return null}return e.forEach(c=>{n.test(c)&&(!s||a.compare(c)===1)&&(s=c,a=new yVe(s,r))}),s};aie.exports=IVe});var fie=G((Jkt,uie)=>{var P_=Ko(),CVe=Sc(),cie=t2(),wVe=(e,t)=>{e=new CVe(e,t);let r=new P_(\"0.0.0\");if(e.test(r)||(r=new P_(\"0.0.0-0\"),e.test(r)))return r;r=null;for(let s=0;s<e.set.length;++s){let a=e.set[s],n=null;a.forEach(c=>{let f=new P_(c.semver.version);switch(c.operator){case\">\":f.prerelease.length===0?f.patch++:f.prerelease.push(0),f.raw=f.format();case\"\":case\">=\":(!n||cie(f,n))&&(n=f);break;case\"<\":case\"<=\":break;default:throw new Error(`Unexpected operation: ${c.operator}`)}}),n&&(!r||cie(r,n))&&(r=n)}return r&&e.test(r)?r:null};uie.exports=wVe});var pie=G((zkt,Aie)=>{var BVe=Sc(),vVe=(e,t)=>{try{return new BVe(e,t).range||\"*\"}catch{return null}};Aie.exports=vVe});var ek=G((Zkt,mie)=>{var SVe=Ko(),die=i2(),{ANY:DVe}=die,bVe=Sc(),PVe=o2(),hie=t2(),gie=Kx(),xVe=zx(),kVe=Jx(),QVe=(e,t,r,s)=>{e=new SVe(e,s),t=new bVe(t,s);let a,n,c,f,p;switch(r){case\">\":a=hie,n=xVe,c=gie,f=\">\",p=\">=\";break;case\"<\":a=gie,n=kVe,c=hie,f=\"<\",p=\"<=\";break;default:throw new TypeError('Must provide a hilo val of \"<\" or \">\"')}if(PVe(e,t,s))return!1;for(let h=0;h<t.set.length;++h){let E=t.set[h],C=null,S=null;if(E.forEach(x=>{x.semver===DVe&&(x=new die(\">=0.0.0\")),C=C||x,S=S||x,a(x.semver,C.semver,s)?C=x:c(x.semver,S.semver,s)&&(S=x)}),C.operator===f||C.operator===p||(!S.operator||S.operator===f)&&n(e,S.semver))return!1;if(S.operator===p&&c(e,S.semver))return!1}return!0};mie.exports=QVe});var Eie=G((Xkt,yie)=>{var RVe=ek(),TVe=(e,t,r)=>RVe(e,t,\">\",r);yie.exports=TVe});var Cie=G(($kt,Iie)=>{var FVe=ek(),NVe=(e,t,r)=>FVe(e,t,\"<\",r);Iie.exports=NVe});var vie=G((eQt,Bie)=>{var wie=Sc(),OVe=(e,t,r)=>(e=new wie(e,r),t=new wie(t,r),e.intersects(t,r));Bie.exports=OVe});var Die=G((tQt,Sie)=>{var LVe=o2(),MVe=vc();Sie.exports=(e,t,r)=>{let s=[],a=null,n=null,c=e.sort((E,C)=>MVe(E,C,r));for(let E of c)LVe(E,t,r)?(n=E,a||(a=E)):(n&&s.push([a,n]),n=null,a=null);a&&s.push([a,null]);let f=[];for(let[E,C]of s)E===C?f.push(E):!C&&E===c[0]?f.push(\"*\"):C?E===c[0]?f.push(`<=${C}`):f.push(`${E} - ${C}`):f.push(`>=${E}`);let p=f.join(\" || \"),h=typeof t.raw==\"string\"?t.raw:String(t);return p.length<h.length?p:t}});var Rie=G((rQt,Qie)=>{var bie=Sc(),k_=i2(),{ANY:x_}=k_,a2=o2(),Q_=vc(),UVe=(e,t,r={})=>{if(e===t)return!0;e=new bie(e,r),t=new bie(t,r);let s=!1;e:for(let a of e.set){for(let n of t.set){let c=HVe(a,n,r);if(s=s||c!==null,c)continue e}if(s)return!1}return!0},_Ve=[new k_(\">=0.0.0-0\")],Pie=[new k_(\">=0.0.0\")],HVe=(e,t,r)=>{if(e===t)return!0;if(e.length===1&&e[0].semver===x_){if(t.length===1&&t[0].semver===x_)return!0;r.includePrerelease?e=_Ve:e=Pie}if(t.length===1&&t[0].semver===x_){if(r.includePrerelease)return!0;t=Pie}let s=new Set,a,n;for(let x of e)x.operator===\">\"||x.operator===\">=\"?a=xie(a,x,r):x.operator===\"<\"||x.operator===\"<=\"?n=kie(n,x,r):s.add(x.semver);if(s.size>1)return null;let c;if(a&&n){if(c=Q_(a.semver,n.semver,r),c>0)return null;if(c===0&&(a.operator!==\">=\"||n.operator!==\"<=\"))return null}for(let x of s){if(a&&!a2(x,String(a),r)||n&&!a2(x,String(n),r))return null;for(let I of t)if(!a2(x,String(I),r))return!1;return!0}let f,p,h,E,C=n&&!r.includePrerelease&&n.semver.prerelease.length?n.semver:!1,S=a&&!r.includePrerelease&&a.semver.prerelease.length?a.semver:!1;C&&C.prerelease.length===1&&n.operator===\"<\"&&C.prerelease[0]===0&&(C=!1);for(let x of t){if(E=E||x.operator===\">\"||x.operator===\">=\",h=h||x.operator===\"<\"||x.operator===\"<=\",a){if(S&&x.semver.prerelease&&x.semver.prerelease.length&&x.semver.major===S.major&&x.semver.minor===S.minor&&x.semver.patch===S.patch&&(S=!1),x.operator===\">\"||x.operator===\">=\"){if(f=xie(a,x,r),f===x&&f!==a)return!1}else if(a.operator===\">=\"&&!a2(a.semver,String(x),r))return!1}if(n){if(C&&x.semver.prerelease&&x.semver.prerelease.length&&x.semver.major===C.major&&x.semver.minor===C.minor&&x.semver.patch===C.patch&&(C=!1),x.operator===\"<\"||x.operator===\"<=\"){if(p=kie(n,x,r),p===x&&p!==n)return!1}else if(n.operator===\"<=\"&&!a2(n.semver,String(x),r))return!1}if(!x.operator&&(n||a)&&c!==0)return!1}return!(a&&h&&!n&&c!==0||n&&E&&!a&&c!==0||S||C)},xie=(e,t,r)=>{if(!e)return t;let s=Q_(e.semver,t.semver,r);return s>0?e:s<0||t.operator===\">\"&&e.operator===\">=\"?t:e},kie=(e,t,r)=>{if(!e)return t;let s=Q_(e.semver,t.semver,r);return s<0?e:s>0||t.operator===\"<\"&&e.operator===\"<=\"?t:e};Qie.exports=UVe});var pi=G((nQt,Nie)=>{var R_=bE(),Tie=$B(),jVe=Ko(),Fie=h_(),GVe=Od(),qVe=$re(),WVe=tne(),VVe=ine(),YVe=ane(),KVe=cne(),JVe=fne(),zVe=pne(),ZVe=gne(),XVe=vc(),$Ve=Ene(),eYe=Cne(),tYe=Yx(),rYe=Sne(),nYe=bne(),iYe=t2(),sYe=Kx(),oYe=d_(),aYe=m_(),lYe=Jx(),cYe=zx(),uYe=y_(),fYe=One(),AYe=i2(),pYe=Sc(),hYe=o2(),gYe=iie(),dYe=oie(),mYe=lie(),yYe=fie(),EYe=pie(),IYe=ek(),CYe=Eie(),wYe=Cie(),BYe=vie(),vYe=Die(),SYe=Rie();Nie.exports={parse:GVe,valid:qVe,clean:WVe,inc:VVe,diff:YVe,major:KVe,minor:JVe,patch:zVe,prerelease:ZVe,compare:XVe,rcompare:$Ve,compareLoose:eYe,compareBuild:tYe,sort:rYe,rsort:nYe,gt:iYe,lt:sYe,eq:oYe,neq:aYe,gte:lYe,lte:cYe,cmp:uYe,coerce:fYe,Comparator:AYe,Range:pYe,satisfies:hYe,toComparators:gYe,maxSatisfying:dYe,minSatisfying:mYe,minVersion:yYe,validRange:EYe,outside:IYe,gtr:CYe,ltr:wYe,intersects:BYe,simplifyRange:vYe,subset:SYe,SemVer:jVe,re:R_.re,src:R_.src,tokens:R_.t,SEMVER_SPEC_VERSION:Tie.SEMVER_SPEC_VERSION,RELEASE_TYPES:Tie.RELEASE_TYPES,compareIdentifiers:Fie.compareIdentifiers,rcompareIdentifiers:Fie.rcompareIdentifiers}});var Lie=G((iQt,Oie)=>{\"use strict\";function DYe(e,t){function r(){this.constructor=e}r.prototype=t.prototype,e.prototype=new r}function _d(e,t,r,s){this.message=e,this.expected=t,this.found=r,this.location=s,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,_d)}DYe(_d,Error);_d.buildMessage=function(e,t){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",C;for(C=0;C<h.parts.length;C++)E+=h.parts[C]instanceof Array?n(h.parts[C][0])+\"-\"+n(h.parts[C][1]):n(h.parts[C]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function s(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+s(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+s(E)})}function c(h){return r[h.type](h)}function f(h){var E=new Array(h.length),C,S;for(C=0;C<h.length;C++)E[C]=c(h[C]);if(E.sort(),E.length>0){for(C=1,S=1;C<E.length;C++)E[C-1]!==E[C]&&(E[S]=E[C],S++);E.length=S}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+f(e)+\" but \"+p(t)+\" found.\"};function bYe(e,t){t=t!==void 0?t:{};var r={},s={Expression:y},a=y,n=\"|\",c=Ne(\"|\",!1),f=\"&\",p=Ne(\"&\",!1),h=\"^\",E=Ne(\"^\",!1),C=function($,se){return!!se.reduce((xe,Fe)=>{switch(Fe[1]){case\"|\":return xe|Fe[3];case\"&\":return xe&Fe[3];case\"^\":return xe^Fe[3]}},$)},S=\"!\",x=Ne(\"!\",!1),I=function($){return!$},T=\"(\",O=Ne(\"(\",!1),U=\")\",Y=Ne(\")\",!1),te=function($){return $},ie=/^[^ \\t\\n\\r()!|&\\^]/,ue=ke([\" \",\"\t\",`\n`,\"\\r\",\"(\",\")\",\"!\",\"|\",\"&\",\"^\"],!0,!1),ae=function($){return t.queryPattern.test($)},de=function($){return t.checkFn($)},Ae=Re(\"whitespace\"),Ce=/^[ \\t\\n\\r]/,Ee=ke([\" \",\"\t\",`\n`,\"\\r\"],!1,!1),g=0,Se=0,Be=[{line:1,column:1}],me=0,ce=[],X=0,De;if(\"startRule\"in t){if(!(t.startRule in s))throw new Error(`Can't start parsing from rule \"`+t.startRule+'\".');a=s[t.startRule]}function Qe(){return e.substring(Se,g)}function it(){return Me(Se,g)}function _($,se){throw se=se!==void 0?se:Me(Se,g),b([Re($)],e.substring(Se,g),se)}function tt($,se){throw se=se!==void 0?se:Me(Se,g),w($,se)}function Ne($,se){return{type:\"literal\",text:$,ignoreCase:se}}function ke($,se,xe){return{type:\"class\",parts:$,inverted:se,ignoreCase:xe}}function be(){return{type:\"any\"}}function je(){return{type:\"end\"}}function Re($){return{type:\"other\",description:$}}function ct($){var se=Be[$],xe;if(se)return se;for(xe=$-1;!Be[xe];)xe--;for(se=Be[xe],se={line:se.line,column:se.column};xe<$;)e.charCodeAt(xe)===10?(se.line++,se.column=1):se.column++,xe++;return Be[$]=se,se}function Me($,se){var xe=ct($),Fe=ct(se);return{start:{offset:$,line:xe.line,column:xe.column},end:{offset:se,line:Fe.line,column:Fe.column}}}function P($){g<me||(g>me&&(me=g,ce=[]),ce.push($))}function w($,se){return new _d($,null,null,se)}function b($,se,xe){return new _d(_d.buildMessage($,se),$,se,xe)}function y(){var $,se,xe,Fe,ut,Ct,qt,ir;if($=g,se=F(),se!==r){for(xe=[],Fe=g,ut=Z(),ut!==r?(e.charCodeAt(g)===124?(Ct=n,g++):(Ct=r,X===0&&P(c)),Ct===r&&(e.charCodeAt(g)===38?(Ct=f,g++):(Ct=r,X===0&&P(p)),Ct===r&&(e.charCodeAt(g)===94?(Ct=h,g++):(Ct=r,X===0&&P(E)))),Ct!==r?(qt=Z(),qt!==r?(ir=F(),ir!==r?(ut=[ut,Ct,qt,ir],Fe=ut):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r);Fe!==r;)xe.push(Fe),Fe=g,ut=Z(),ut!==r?(e.charCodeAt(g)===124?(Ct=n,g++):(Ct=r,X===0&&P(c)),Ct===r&&(e.charCodeAt(g)===38?(Ct=f,g++):(Ct=r,X===0&&P(p)),Ct===r&&(e.charCodeAt(g)===94?(Ct=h,g++):(Ct=r,X===0&&P(E)))),Ct!==r?(qt=Z(),qt!==r?(ir=F(),ir!==r?(ut=[ut,Ct,qt,ir],Fe=ut):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r);xe!==r?(Se=$,se=C(se,xe),$=se):(g=$,$=r)}else g=$,$=r;return $}function F(){var $,se,xe,Fe,ut,Ct;return $=g,e.charCodeAt(g)===33?(se=S,g++):(se=r,X===0&&P(x)),se!==r?(xe=F(),xe!==r?(Se=$,se=I(xe),$=se):(g=$,$=r)):(g=$,$=r),$===r&&($=g,e.charCodeAt(g)===40?(se=T,g++):(se=r,X===0&&P(O)),se!==r?(xe=Z(),xe!==r?(Fe=y(),Fe!==r?(ut=Z(),ut!==r?(e.charCodeAt(g)===41?(Ct=U,g++):(Ct=r,X===0&&P(Y)),Ct!==r?(Se=$,se=te(Fe),$=se):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r),$===r&&($=z())),$}function z(){var $,se,xe,Fe,ut;if($=g,se=Z(),se!==r){if(xe=g,Fe=[],ie.test(e.charAt(g))?(ut=e.charAt(g),g++):(ut=r,X===0&&P(ue)),ut!==r)for(;ut!==r;)Fe.push(ut),ie.test(e.charAt(g))?(ut=e.charAt(g),g++):(ut=r,X===0&&P(ue));else Fe=r;Fe!==r?xe=e.substring(xe,g):xe=Fe,xe!==r?(Se=g,Fe=ae(xe),Fe?Fe=void 0:Fe=r,Fe!==r?(Se=$,se=de(xe),$=se):(g=$,$=r)):(g=$,$=r)}else g=$,$=r;return $}function Z(){var $,se;for(X++,$=[],Ce.test(e.charAt(g))?(se=e.charAt(g),g++):(se=r,X===0&&P(Ee));se!==r;)$.push(se),Ce.test(e.charAt(g))?(se=e.charAt(g),g++):(se=r,X===0&&P(Ee));return X--,$===r&&(se=r,X===0&&P(Ae)),$}if(De=a(),De!==r&&g===e.length)return De;throw De!==r&&g<e.length&&P(je()),b(ce,me<e.length?e.charAt(me):null,me<e.length?Me(me,me+1):Me(me,me))}Oie.exports={SyntaxError:_d,parse:bYe}});var Mie=G(tk=>{var{parse:PYe}=Lie();tk.makeParser=(e=/[a-z]+/)=>(t,r)=>PYe(t,{queryPattern:e,checkFn:r});tk.parse=tk.makeParser()});var _ie=G((oQt,Uie)=>{\"use strict\";Uie.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var T_=G((aQt,jie)=>{var l2=_ie(),Hie={};for(let e of Object.keys(l2))Hie[l2[e]]=e;var hr={rgb:{channels:3,labels:\"rgb\"},hsl:{channels:3,labels:\"hsl\"},hsv:{channels:3,labels:\"hsv\"},hwb:{channels:3,labels:\"hwb\"},cmyk:{channels:4,labels:\"cmyk\"},xyz:{channels:3,labels:\"xyz\"},lab:{channels:3,labels:\"lab\"},lch:{channels:3,labels:\"lch\"},hex:{channels:1,labels:[\"hex\"]},keyword:{channels:1,labels:[\"keyword\"]},ansi16:{channels:1,labels:[\"ansi16\"]},ansi256:{channels:1,labels:[\"ansi256\"]},hcg:{channels:3,labels:[\"h\",\"c\",\"g\"]},apple:{channels:3,labels:[\"r16\",\"g16\",\"b16\"]},gray:{channels:1,labels:[\"gray\"]}};jie.exports=hr;for(let e of Object.keys(hr)){if(!(\"channels\"in hr[e]))throw new Error(\"missing channels property: \"+e);if(!(\"labels\"in hr[e]))throw new Error(\"missing channel labels property: \"+e);if(hr[e].labels.length!==hr[e].channels)throw new Error(\"channel and label counts mismatch: \"+e);let{channels:t,labels:r}=hr[e];delete hr[e].channels,delete hr[e].labels,Object.defineProperty(hr[e],\"channels\",{value:t}),Object.defineProperty(hr[e],\"labels\",{value:r})}hr.rgb.hsl=function(e){let t=e[0]/255,r=e[1]/255,s=e[2]/255,a=Math.min(t,r,s),n=Math.max(t,r,s),c=n-a,f,p;n===a?f=0:t===n?f=(r-s)/c:r===n?f=2+(s-t)/c:s===n&&(f=4+(t-r)/c),f=Math.min(f*60,360),f<0&&(f+=360);let h=(a+n)/2;return n===a?p=0:h<=.5?p=c/(n+a):p=c/(2-n-a),[f,p*100,h*100]};hr.rgb.hsv=function(e){let t,r,s,a,n,c=e[0]/255,f=e[1]/255,p=e[2]/255,h=Math.max(c,f,p),E=h-Math.min(c,f,p),C=function(S){return(h-S)/6/E+1/2};return E===0?(a=0,n=0):(n=E/h,t=C(c),r=C(f),s=C(p),c===h?a=s-r:f===h?a=1/3+t-s:p===h&&(a=2/3+r-t),a<0?a+=1:a>1&&(a-=1)),[a*360,n*100,h*100]};hr.rgb.hwb=function(e){let t=e[0],r=e[1],s=e[2],a=hr.rgb.hsl(e)[0],n=1/255*Math.min(t,Math.min(r,s));return s=1-1/255*Math.max(t,Math.max(r,s)),[a,n*100,s*100]};hr.rgb.cmyk=function(e){let t=e[0]/255,r=e[1]/255,s=e[2]/255,a=Math.min(1-t,1-r,1-s),n=(1-t-a)/(1-a)||0,c=(1-r-a)/(1-a)||0,f=(1-s-a)/(1-a)||0;return[n*100,c*100,f*100,a*100]};function xYe(e,t){return(e[0]-t[0])**2+(e[1]-t[1])**2+(e[2]-t[2])**2}hr.rgb.keyword=function(e){let t=Hie[e];if(t)return t;let r=1/0,s;for(let a of Object.keys(l2)){let n=l2[a],c=xYe(e,n);c<r&&(r=c,s=a)}return s};hr.keyword.rgb=function(e){return l2[e]};hr.rgb.xyz=function(e){let t=e[0]/255,r=e[1]/255,s=e[2]/255;t=t>.04045?((t+.055)/1.055)**2.4:t/12.92,r=r>.04045?((r+.055)/1.055)**2.4:r/12.92,s=s>.04045?((s+.055)/1.055)**2.4:s/12.92;let a=t*.4124+r*.3576+s*.1805,n=t*.2126+r*.7152+s*.0722,c=t*.0193+r*.1192+s*.9505;return[a*100,n*100,c*100]};hr.rgb.lab=function(e){let t=hr.rgb.xyz(e),r=t[0],s=t[1],a=t[2];r/=95.047,s/=100,a/=108.883,r=r>.008856?r**(1/3):7.787*r+16/116,s=s>.008856?s**(1/3):7.787*s+16/116,a=a>.008856?a**(1/3):7.787*a+16/116;let n=116*s-16,c=500*(r-s),f=200*(s-a);return[n,c,f]};hr.hsl.rgb=function(e){let t=e[0]/360,r=e[1]/100,s=e[2]/100,a,n,c;if(r===0)return c=s*255,[c,c,c];s<.5?a=s*(1+r):a=s+r-s*r;let f=2*s-a,p=[0,0,0];for(let h=0;h<3;h++)n=t+1/3*-(h-1),n<0&&n++,n>1&&n--,6*n<1?c=f+(a-f)*6*n:2*n<1?c=a:3*n<2?c=f+(a-f)*(2/3-n)*6:c=f,p[h]=c*255;return p};hr.hsl.hsv=function(e){let t=e[0],r=e[1]/100,s=e[2]/100,a=r,n=Math.max(s,.01);s*=2,r*=s<=1?s:2-s,a*=n<=1?n:2-n;let c=(s+r)/2,f=s===0?2*a/(n+a):2*r/(s+r);return[t,f*100,c*100]};hr.hsv.rgb=function(e){let t=e[0]/60,r=e[1]/100,s=e[2]/100,a=Math.floor(t)%6,n=t-Math.floor(t),c=255*s*(1-r),f=255*s*(1-r*n),p=255*s*(1-r*(1-n));switch(s*=255,a){case 0:return[s,p,c];case 1:return[f,s,c];case 2:return[c,s,p];case 3:return[c,f,s];case 4:return[p,c,s];case 5:return[s,c,f]}};hr.hsv.hsl=function(e){let t=e[0],r=e[1]/100,s=e[2]/100,a=Math.max(s,.01),n,c;c=(2-r)*s;let f=(2-r)*a;return n=r*a,n/=f<=1?f:2-f,n=n||0,c/=2,[t,n*100,c*100]};hr.hwb.rgb=function(e){let t=e[0]/360,r=e[1]/100,s=e[2]/100,a=r+s,n;a>1&&(r/=a,s/=a);let c=Math.floor(6*t),f=1-s;n=6*t-c,c&1&&(n=1-n);let p=r+n*(f-r),h,E,C;switch(c){default:case 6:case 0:h=f,E=p,C=r;break;case 1:h=p,E=f,C=r;break;case 2:h=r,E=f,C=p;break;case 3:h=r,E=p,C=f;break;case 4:h=p,E=r,C=f;break;case 5:h=f,E=r,C=p;break}return[h*255,E*255,C*255]};hr.cmyk.rgb=function(e){let t=e[0]/100,r=e[1]/100,s=e[2]/100,a=e[3]/100,n=1-Math.min(1,t*(1-a)+a),c=1-Math.min(1,r*(1-a)+a),f=1-Math.min(1,s*(1-a)+a);return[n*255,c*255,f*255]};hr.xyz.rgb=function(e){let t=e[0]/100,r=e[1]/100,s=e[2]/100,a,n,c;return a=t*3.2406+r*-1.5372+s*-.4986,n=t*-.9689+r*1.8758+s*.0415,c=t*.0557+r*-.204+s*1.057,a=a>.0031308?1.055*a**(1/2.4)-.055:a*12.92,n=n>.0031308?1.055*n**(1/2.4)-.055:n*12.92,c=c>.0031308?1.055*c**(1/2.4)-.055:c*12.92,a=Math.min(Math.max(0,a),1),n=Math.min(Math.max(0,n),1),c=Math.min(Math.max(0,c),1),[a*255,n*255,c*255]};hr.xyz.lab=function(e){let t=e[0],r=e[1],s=e[2];t/=95.047,r/=100,s/=108.883,t=t>.008856?t**(1/3):7.787*t+16/116,r=r>.008856?r**(1/3):7.787*r+16/116,s=s>.008856?s**(1/3):7.787*s+16/116;let a=116*r-16,n=500*(t-r),c=200*(r-s);return[a,n,c]};hr.lab.xyz=function(e){let t=e[0],r=e[1],s=e[2],a,n,c;n=(t+16)/116,a=r/500+n,c=n-s/200;let f=n**3,p=a**3,h=c**3;return n=f>.008856?f:(n-16/116)/7.787,a=p>.008856?p:(a-16/116)/7.787,c=h>.008856?h:(c-16/116)/7.787,a*=95.047,n*=100,c*=108.883,[a,n,c]};hr.lab.lch=function(e){let t=e[0],r=e[1],s=e[2],a;a=Math.atan2(s,r)*360/2/Math.PI,a<0&&(a+=360);let c=Math.sqrt(r*r+s*s);return[t,c,a]};hr.lch.lab=function(e){let t=e[0],r=e[1],a=e[2]/360*2*Math.PI,n=r*Math.cos(a),c=r*Math.sin(a);return[t,n,c]};hr.rgb.ansi16=function(e,t=null){let[r,s,a]=e,n=t===null?hr.rgb.hsv(e)[2]:t;if(n=Math.round(n/50),n===0)return 30;let c=30+(Math.round(a/255)<<2|Math.round(s/255)<<1|Math.round(r/255));return n===2&&(c+=60),c};hr.hsv.ansi16=function(e){return hr.rgb.ansi16(hr.hsv.rgb(e),e[2])};hr.rgb.ansi256=function(e){let t=e[0],r=e[1],s=e[2];return t===r&&r===s?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(r/255*5)+Math.round(s/255*5)};hr.ansi16.rgb=function(e){let t=e%10;if(t===0||t===7)return e>50&&(t+=3.5),t=t/10.5*255,[t,t,t];let r=(~~(e>50)+1)*.5,s=(t&1)*r*255,a=(t>>1&1)*r*255,n=(t>>2&1)*r*255;return[s,a,n]};hr.ansi256.rgb=function(e){if(e>=232){let n=(e-232)*10+8;return[n,n,n]}e-=16;let t,r=Math.floor(e/36)/5*255,s=Math.floor((t=e%36)/6)/5*255,a=t%6/5*255;return[r,s,a]};hr.rgb.hex=function(e){let r=(((Math.round(e[0])&255)<<16)+((Math.round(e[1])&255)<<8)+(Math.round(e[2])&255)).toString(16).toUpperCase();return\"000000\".substring(r.length)+r};hr.hex.rgb=function(e){let t=e.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!t)return[0,0,0];let r=t[0];t[0].length===3&&(r=r.split(\"\").map(f=>f+f).join(\"\"));let s=parseInt(r,16),a=s>>16&255,n=s>>8&255,c=s&255;return[a,n,c]};hr.rgb.hcg=function(e){let t=e[0]/255,r=e[1]/255,s=e[2]/255,a=Math.max(Math.max(t,r),s),n=Math.min(Math.min(t,r),s),c=a-n,f,p;return c<1?f=n/(1-c):f=0,c<=0?p=0:a===t?p=(r-s)/c%6:a===r?p=2+(s-t)/c:p=4+(t-r)/c,p/=6,p%=1,[p*360,c*100,f*100]};hr.hsl.hcg=function(e){let t=e[1]/100,r=e[2]/100,s=r<.5?2*t*r:2*t*(1-r),a=0;return s<1&&(a=(r-.5*s)/(1-s)),[e[0],s*100,a*100]};hr.hsv.hcg=function(e){let t=e[1]/100,r=e[2]/100,s=t*r,a=0;return s<1&&(a=(r-s)/(1-s)),[e[0],s*100,a*100]};hr.hcg.rgb=function(e){let t=e[0]/360,r=e[1]/100,s=e[2]/100;if(r===0)return[s*255,s*255,s*255];let a=[0,0,0],n=t%1*6,c=n%1,f=1-c,p=0;switch(Math.floor(n)){case 0:a[0]=1,a[1]=c,a[2]=0;break;case 1:a[0]=f,a[1]=1,a[2]=0;break;case 2:a[0]=0,a[1]=1,a[2]=c;break;case 3:a[0]=0,a[1]=f,a[2]=1;break;case 4:a[0]=c,a[1]=0,a[2]=1;break;default:a[0]=1,a[1]=0,a[2]=f}return p=(1-r)*s,[(r*a[0]+p)*255,(r*a[1]+p)*255,(r*a[2]+p)*255]};hr.hcg.hsv=function(e){let t=e[1]/100,r=e[2]/100,s=t+r*(1-t),a=0;return s>0&&(a=t/s),[e[0],a*100,s*100]};hr.hcg.hsl=function(e){let t=e[1]/100,s=e[2]/100*(1-t)+.5*t,a=0;return s>0&&s<.5?a=t/(2*s):s>=.5&&s<1&&(a=t/(2*(1-s))),[e[0],a*100,s*100]};hr.hcg.hwb=function(e){let t=e[1]/100,r=e[2]/100,s=t+r*(1-t);return[e[0],(s-t)*100,(1-s)*100]};hr.hwb.hcg=function(e){let t=e[1]/100,s=1-e[2]/100,a=s-t,n=0;return a<1&&(n=(s-a)/(1-a)),[e[0],a*100,n*100]};hr.apple.rgb=function(e){return[e[0]/65535*255,e[1]/65535*255,e[2]/65535*255]};hr.rgb.apple=function(e){return[e[0]/255*65535,e[1]/255*65535,e[2]/255*65535]};hr.gray.rgb=function(e){return[e[0]/100*255,e[0]/100*255,e[0]/100*255]};hr.gray.hsl=function(e){return[0,0,e[0]]};hr.gray.hsv=hr.gray.hsl;hr.gray.hwb=function(e){return[0,100,e[0]]};hr.gray.cmyk=function(e){return[0,0,0,e[0]]};hr.gray.lab=function(e){return[e[0],0,0]};hr.gray.hex=function(e){let t=Math.round(e[0]/100*255)&255,s=((t<<16)+(t<<8)+t).toString(16).toUpperCase();return\"000000\".substring(s.length)+s};hr.rgb.gray=function(e){return[(e[0]+e[1]+e[2])/3/255*100]}});var qie=G((lQt,Gie)=>{var rk=T_();function kYe(){let e={},t=Object.keys(rk);for(let r=t.length,s=0;s<r;s++)e[t[s]]={distance:-1,parent:null};return e}function QYe(e){let t=kYe(),r=[e];for(t[e].distance=0;r.length;){let s=r.pop(),a=Object.keys(rk[s]);for(let n=a.length,c=0;c<n;c++){let f=a[c],p=t[f];p.distance===-1&&(p.distance=t[s].distance+1,p.parent=s,r.unshift(f))}}return t}function RYe(e,t){return function(r){return t(e(r))}}function TYe(e,t){let r=[t[e].parent,e],s=rk[t[e].parent][e],a=t[e].parent;for(;t[a].parent;)r.unshift(t[a].parent),s=RYe(rk[t[a].parent][a],s),a=t[a].parent;return s.conversion=r,s}Gie.exports=function(e){let t=QYe(e),r={},s=Object.keys(t);for(let a=s.length,n=0;n<a;n++){let c=s[n];t[c].parent!==null&&(r[c]=TYe(c,t))}return r}});var Vie=G((cQt,Wie)=>{var F_=T_(),FYe=qie(),QE={},NYe=Object.keys(F_);function OYe(e){let t=function(...r){let s=r[0];return s==null?s:(s.length>1&&(r=s),e(r))};return\"conversion\"in e&&(t.conversion=e.conversion),t}function LYe(e){let t=function(...r){let s=r[0];if(s==null)return s;s.length>1&&(r=s);let a=e(r);if(typeof a==\"object\")for(let n=a.length,c=0;c<n;c++)a[c]=Math.round(a[c]);return a};return\"conversion\"in e&&(t.conversion=e.conversion),t}NYe.forEach(e=>{QE[e]={},Object.defineProperty(QE[e],\"channels\",{value:F_[e].channels}),Object.defineProperty(QE[e],\"labels\",{value:F_[e].labels});let t=FYe(e);Object.keys(t).forEach(s=>{let a=t[s];QE[e][s]=LYe(a),QE[e][s].raw=OYe(a)})});Wie.exports=QE});var ik=G((uQt,Zie)=>{\"use strict\";var Yie=(e,t)=>(...r)=>`\\x1B[${e(...r)+t}m`,Kie=(e,t)=>(...r)=>{let s=e(...r);return`\\x1B[${38+t};5;${s}m`},Jie=(e,t)=>(...r)=>{let s=e(...r);return`\\x1B[${38+t};2;${s[0]};${s[1]};${s[2]}m`},nk=e=>e,zie=(e,t,r)=>[e,t,r],RE=(e,t,r)=>{Object.defineProperty(e,t,{get:()=>{let s=r();return Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0}),s},enumerable:!0,configurable:!0})},N_,TE=(e,t,r,s)=>{N_===void 0&&(N_=Vie());let a=s?10:0,n={};for(let[c,f]of Object.entries(N_)){let p=c===\"ansi16\"?\"ansi\":c;c===t?n[p]=e(r,a):typeof f==\"object\"&&(n[p]=e(f[t],a))}return n};function MYe(){let e=new Map,t={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};t.color.gray=t.color.blackBright,t.bgColor.bgGray=t.bgColor.bgBlackBright,t.color.grey=t.color.blackBright,t.bgColor.bgGrey=t.bgColor.bgBlackBright;for(let[r,s]of Object.entries(t)){for(let[a,n]of Object.entries(s))t[a]={open:`\\x1B[${n[0]}m`,close:`\\x1B[${n[1]}m`},s[a]=t[a],e.set(n[0],n[1]);Object.defineProperty(t,r,{value:s,enumerable:!1})}return Object.defineProperty(t,\"codes\",{value:e,enumerable:!1}),t.color.close=\"\\x1B[39m\",t.bgColor.close=\"\\x1B[49m\",RE(t.color,\"ansi\",()=>TE(Yie,\"ansi16\",nk,!1)),RE(t.color,\"ansi256\",()=>TE(Kie,\"ansi256\",nk,!1)),RE(t.color,\"ansi16m\",()=>TE(Jie,\"rgb\",zie,!1)),RE(t.bgColor,\"ansi\",()=>TE(Yie,\"ansi16\",nk,!0)),RE(t.bgColor,\"ansi256\",()=>TE(Kie,\"ansi256\",nk,!0)),RE(t.bgColor,\"ansi16m\",()=>TE(Jie,\"rgb\",zie,!0)),t}Object.defineProperty(Zie,\"exports\",{enumerable:!0,get:MYe})});var $ie=G((fQt,Xie)=>{\"use strict\";Xie.exports=(e,t=process.argv)=>{let r=e.startsWith(\"-\")?\"\":e.length===1?\"-\":\"--\",s=t.indexOf(r+e),a=t.indexOf(\"--\");return s!==-1&&(a===-1||s<a)}});var rse=G((AQt,tse)=>{\"use strict\";var UYe=Ie(\"os\"),ese=Ie(\"tty\"),Dc=$ie(),{env:Qs}=process,o0;Dc(\"no-color\")||Dc(\"no-colors\")||Dc(\"color=false\")||Dc(\"color=never\")?o0=0:(Dc(\"color\")||Dc(\"colors\")||Dc(\"color=true\")||Dc(\"color=always\"))&&(o0=1);\"FORCE_COLOR\"in Qs&&(Qs.FORCE_COLOR===\"true\"?o0=1:Qs.FORCE_COLOR===\"false\"?o0=0:o0=Qs.FORCE_COLOR.length===0?1:Math.min(parseInt(Qs.FORCE_COLOR,10),3));function O_(e){return e===0?!1:{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function L_(e,t){if(o0===0)return 0;if(Dc(\"color=16m\")||Dc(\"color=full\")||Dc(\"color=truecolor\"))return 3;if(Dc(\"color=256\"))return 2;if(e&&!t&&o0===void 0)return 0;let r=o0||0;if(Qs.TERM===\"dumb\")return r;if(process.platform===\"win32\"){let s=UYe.release().split(\".\");return Number(s[0])>=10&&Number(s[2])>=10586?Number(s[2])>=14931?3:2:1}if(\"CI\"in Qs)return[\"TRAVIS\",\"CIRCLECI\",\"APPVEYOR\",\"GITLAB_CI\"].some(s=>s in Qs)||Qs.CI_NAME===\"codeship\"?1:r;if(\"TEAMCITY_VERSION\"in Qs)return/^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(Qs.TEAMCITY_VERSION)?1:0;if(\"GITHUB_ACTIONS\"in Qs)return 1;if(Qs.COLORTERM===\"truecolor\")return 3;if(\"TERM_PROGRAM\"in Qs){let s=parseInt((Qs.TERM_PROGRAM_VERSION||\"\").split(\".\")[0],10);switch(Qs.TERM_PROGRAM){case\"iTerm.app\":return s>=3?3:2;case\"Apple_Terminal\":return 2}}return/-256(color)?$/i.test(Qs.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(Qs.TERM)||\"COLORTERM\"in Qs?1:r}function _Ye(e){let t=L_(e,e&&e.isTTY);return O_(t)}tse.exports={supportsColor:_Ye,stdout:O_(L_(!0,ese.isatty(1))),stderr:O_(L_(!0,ese.isatty(2)))}});var ise=G((pQt,nse)=>{\"use strict\";var HYe=(e,t,r)=>{let s=e.indexOf(t);if(s===-1)return e;let a=t.length,n=0,c=\"\";do c+=e.substr(n,s-n)+t+r,n=s+a,s=e.indexOf(t,n);while(s!==-1);return c+=e.substr(n),c},jYe=(e,t,r,s)=>{let a=0,n=\"\";do{let c=e[s-1]===\"\\r\";n+=e.substr(a,(c?s-1:s)-a)+t+(c?`\\r\n`:`\n`)+r,a=s+1,s=e.indexOf(`\n`,a)}while(s!==-1);return n+=e.substr(a),n};nse.exports={stringReplaceAll:HYe,stringEncaseCRLFWithFirstIndex:jYe}});var cse=G((hQt,lse)=>{\"use strict\";var GYe=/(?:\\\\(u(?:[a-f\\d]{4}|\\{[a-f\\d]{1,6}\\})|x[a-f\\d]{2}|.))|(?:\\{(~)?(\\w+(?:\\([^)]*\\))?(?:\\.\\w+(?:\\([^)]*\\))?)*)(?:[ \\t]|(?=\\r?\\n)))|(\\})|((?:.|[\\r\\n\\f])+?)/gi,sse=/(?:^|\\.)(\\w+)(?:\\(([^)]*)\\))?/g,qYe=/^(['\"])((?:\\\\.|(?!\\1)[^\\\\])*)\\1$/,WYe=/\\\\(u(?:[a-f\\d]{4}|{[a-f\\d]{1,6}})|x[a-f\\d]{2}|.)|([^\\\\])/gi,VYe=new Map([[\"n\",`\n`],[\"r\",\"\\r\"],[\"t\",\"\t\"],[\"b\",\"\\b\"],[\"f\",\"\\f\"],[\"v\",\"\\v\"],[\"0\",\"\\0\"],[\"\\\\\",\"\\\\\"],[\"e\",\"\\x1B\"],[\"a\",\"\\x07\"]]);function ase(e){let t=e[0]===\"u\",r=e[1]===\"{\";return t&&!r&&e.length===5||e[0]===\"x\"&&e.length===3?String.fromCharCode(parseInt(e.slice(1),16)):t&&r?String.fromCodePoint(parseInt(e.slice(2,-1),16)):VYe.get(e)||e}function YYe(e,t){let r=[],s=t.trim().split(/\\s*,\\s*/g),a;for(let n of s){let c=Number(n);if(!Number.isNaN(c))r.push(c);else if(a=n.match(qYe))r.push(a[2].replace(WYe,(f,p,h)=>p?ase(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${e}')`)}return r}function KYe(e){sse.lastIndex=0;let t=[],r;for(;(r=sse.exec(e))!==null;){let s=r[1];if(r[2]){let a=YYe(s,r[2]);t.push([s].concat(a))}else t.push([s])}return t}function ose(e,t){let r={};for(let a of t)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let s=e;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in s))throw new Error(`Unknown Chalk style: ${a}`);s=n.length>0?s[a](...n):s[a]}return s}lse.exports=(e,t)=>{let r=[],s=[],a=[];if(t.replace(GYe,(n,c,f,p,h,E)=>{if(c)a.push(ase(c));else if(p){let C=a.join(\"\");a=[],s.push(r.length===0?C:ose(e,r)(C)),r.push({inverse:f,styles:KYe(p)})}else if(h){if(r.length===0)throw new Error(\"Found extraneous } in Chalk template literal\");s.push(ose(e,r)(a.join(\"\"))),a=[],r.pop()}else a.push(E)}),s.push(a.join(\"\")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?\"\":\"s\"} (\\`}\\`)`;throw new Error(n)}return s.join(\"\")}});var NE=G((gQt,gse)=>{\"use strict\";var c2=ik(),{stdout:U_,stderr:__}=rse(),{stringReplaceAll:JYe,stringEncaseCRLFWithFirstIndex:zYe}=ise(),{isArray:sk}=Array,fse=[\"ansi\",\"ansi\",\"ansi256\",\"ansi16m\"],FE=Object.create(null),ZYe=(e,t={})=>{if(t.level&&!(Number.isInteger(t.level)&&t.level>=0&&t.level<=3))throw new Error(\"The `level` option should be an integer from 0 to 3\");let r=U_?U_.level:0;e.level=t.level===void 0?r:t.level},H_=class{constructor(t){return Ase(t)}},Ase=e=>{let t={};return ZYe(t,e),t.template=(...r)=>hse(t.template,...r),Object.setPrototypeOf(t,ok.prototype),Object.setPrototypeOf(t.template,t),t.template.constructor=()=>{throw new Error(\"`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.\")},t.template.Instance=H_,t.template};function ok(e){return Ase(e)}for(let[e,t]of Object.entries(c2))FE[e]={get(){let r=ak(this,j_(t.open,t.close,this._styler),this._isEmpty);return Object.defineProperty(this,e,{value:r}),r}};FE.visible={get(){let e=ak(this,this._styler,!0);return Object.defineProperty(this,\"visible\",{value:e}),e}};var pse=[\"rgb\",\"hex\",\"keyword\",\"hsl\",\"hsv\",\"hwb\",\"ansi\",\"ansi256\"];for(let e of pse)FE[e]={get(){let{level:t}=this;return function(...r){let s=j_(c2.color[fse[t]][e](...r),c2.color.close,this._styler);return ak(this,s,this._isEmpty)}}};for(let e of pse){let t=\"bg\"+e[0].toUpperCase()+e.slice(1);FE[t]={get(){let{level:r}=this;return function(...s){let a=j_(c2.bgColor[fse[r]][e](...s),c2.bgColor.close,this._styler);return ak(this,a,this._isEmpty)}}}}var XYe=Object.defineProperties(()=>{},{...FE,level:{enumerable:!0,get(){return this._generator.level},set(e){this._generator.level=e}}}),j_=(e,t,r)=>{let s,a;return r===void 0?(s=e,a=t):(s=r.openAll+e,a=t+r.closeAll),{open:e,close:t,openAll:s,closeAll:a,parent:r}},ak=(e,t,r)=>{let s=(...a)=>sk(a[0])&&sk(a[0].raw)?use(s,hse(s,...a)):use(s,a.length===1?\"\"+a[0]:a.join(\" \"));return Object.setPrototypeOf(s,XYe),s._generator=e,s._styler=t,s._isEmpty=r,s},use=(e,t)=>{if(e.level<=0||!t)return e._isEmpty?\"\":t;let r=e._styler;if(r===void 0)return t;let{openAll:s,closeAll:a}=r;if(t.indexOf(\"\\x1B\")!==-1)for(;r!==void 0;)t=JYe(t,r.close,r.open),r=r.parent;let n=t.indexOf(`\n`);return n!==-1&&(t=zYe(t,a,s,n)),s+t+a},M_,hse=(e,...t)=>{let[r]=t;if(!sk(r)||!sk(r.raw))return t.join(\" \");let s=t.slice(1),a=[r.raw[0]];for(let n=1;n<r.length;n++)a.push(String(s[n-1]).replace(/[{}\\\\]/g,\"\\\\$&\"),String(r.raw[n]));return M_===void 0&&(M_=cse()),M_(e,a.join(\"\"))};Object.defineProperties(ok.prototype,FE);var lk=ok();lk.supportsColor=U_;lk.stderr=ok({level:__?__.level:0});lk.stderr.supportsColor=__;gse.exports=lk});var ck=G(bc=>{\"use strict\";bc.isInteger=e=>typeof e==\"number\"?Number.isInteger(e):typeof e==\"string\"&&e.trim()!==\"\"?Number.isInteger(Number(e)):!1;bc.find=(e,t)=>e.nodes.find(r=>r.type===t);bc.exceedsLimit=(e,t,r=1,s)=>s===!1||!bc.isInteger(e)||!bc.isInteger(t)?!1:(Number(t)-Number(e))/Number(r)>=s;bc.escapeNode=(e,t=0,r)=>{let s=e.nodes[t];s&&(r&&s.type===r||s.type===\"open\"||s.type===\"close\")&&s.escaped!==!0&&(s.value=\"\\\\\"+s.value,s.escaped=!0)};bc.encloseBrace=e=>e.type!==\"brace\"||e.commas>>0+e.ranges>>0?!1:(e.invalid=!0,!0);bc.isInvalidBrace=e=>e.type!==\"brace\"?!1:e.invalid===!0||e.dollar?!0:!(e.commas>>0+e.ranges>>0)||e.open!==!0||e.close!==!0?(e.invalid=!0,!0):!1;bc.isOpenOrClose=e=>e.type===\"open\"||e.type===\"close\"?!0:e.open===!0||e.close===!0;bc.reduce=e=>e.reduce((t,r)=>(r.type===\"text\"&&t.push(r.value),r.type===\"range\"&&(r.type=\"text\"),t),[]);bc.flatten=(...e)=>{let t=[],r=s=>{for(let a=0;a<s.length;a++){let n=s[a];Array.isArray(n)?r(n,t):n!==void 0&&t.push(n)}return t};return r(e),t}});var uk=G((mQt,mse)=>{\"use strict\";var dse=ck();mse.exports=(e,t={})=>{let r=(s,a={})=>{let n=t.escapeInvalid&&dse.isInvalidBrace(a),c=s.invalid===!0&&t.escapeInvalid===!0,f=\"\";if(s.value)return(n||c)&&dse.isOpenOrClose(s)?\"\\\\\"+s.value:s.value;if(s.value)return s.value;if(s.nodes)for(let p of s.nodes)f+=r(p);return f};return r(e)}});var Ese=G((yQt,yse)=>{\"use strict\";yse.exports=function(e){return typeof e==\"number\"?e-e===0:typeof e==\"string\"&&e.trim()!==\"\"?Number.isFinite?Number.isFinite(+e):isFinite(+e):!1}});var Pse=G((EQt,bse)=>{\"use strict\";var Ise=Ese(),Hd=(e,t,r)=>{if(Ise(e)===!1)throw new TypeError(\"toRegexRange: expected the first argument to be a number\");if(t===void 0||e===t)return String(e);if(Ise(t)===!1)throw new TypeError(\"toRegexRange: expected the second argument to be a number.\");let s={relaxZeros:!0,...r};typeof s.strictZeros==\"boolean\"&&(s.relaxZeros=s.strictZeros===!1);let a=String(s.relaxZeros),n=String(s.shorthand),c=String(s.capture),f=String(s.wrap),p=e+\":\"+t+\"=\"+a+n+c+f;if(Hd.cache.hasOwnProperty(p))return Hd.cache[p].result;let h=Math.min(e,t),E=Math.max(e,t);if(Math.abs(h-E)===1){let T=e+\"|\"+t;return s.capture?`(${T})`:s.wrap===!1?T:`(?:${T})`}let C=Dse(e)||Dse(t),S={min:e,max:t,a:h,b:E},x=[],I=[];if(C&&(S.isPadded=C,S.maxLen=String(S.max).length),h<0){let T=E<0?Math.abs(E):1;I=Cse(T,Math.abs(h),S,s),h=S.a=0}return E>=0&&(x=Cse(h,E,S,s)),S.negatives=I,S.positives=x,S.result=$Ye(I,x,s),s.capture===!0?S.result=`(${S.result})`:s.wrap!==!1&&x.length+I.length>1&&(S.result=`(?:${S.result})`),Hd.cache[p]=S,S.result};function $Ye(e,t,r){let s=G_(e,t,\"-\",!1,r)||[],a=G_(t,e,\"\",!1,r)||[],n=G_(e,t,\"-?\",!0,r)||[];return s.concat(n).concat(a).join(\"|\")}function e7e(e,t){let r=1,s=1,a=Bse(e,r),n=new Set([t]);for(;e<=a&&a<=t;)n.add(a),r+=1,a=Bse(e,r);for(a=vse(t+1,s)-1;e<a&&a<=t;)n.add(a),s+=1,a=vse(t+1,s)-1;return n=[...n],n.sort(n7e),n}function t7e(e,t,r){if(e===t)return{pattern:e,count:[],digits:0};let s=r7e(e,t),a=s.length,n=\"\",c=0;for(let f=0;f<a;f++){let[p,h]=s[f];p===h?n+=p:p!==\"0\"||h!==\"9\"?n+=i7e(p,h,r):c++}return c&&(n+=r.shorthand===!0?\"\\\\d\":\"[0-9]\"),{pattern:n,count:[c],digits:a}}function Cse(e,t,r,s){let a=e7e(e,t),n=[],c=e,f;for(let p=0;p<a.length;p++){let h=a[p],E=t7e(String(c),String(h),s),C=\"\";if(!r.isPadded&&f&&f.pattern===E.pattern){f.count.length>1&&f.count.pop(),f.count.push(E.count[0]),f.string=f.pattern+Sse(f.count),c=h+1;continue}r.isPadded&&(C=s7e(h,r,s)),E.string=C+E.pattern+Sse(E.count),n.push(E),c=h+1,f=E}return n}function G_(e,t,r,s,a){let n=[];for(let c of e){let{string:f}=c;!s&&!wse(t,\"string\",f)&&n.push(r+f),s&&wse(t,\"string\",f)&&n.push(r+f)}return n}function r7e(e,t){let r=[];for(let s=0;s<e.length;s++)r.push([e[s],t[s]]);return r}function n7e(e,t){return e>t?1:t>e?-1:0}function wse(e,t,r){return e.some(s=>s[t]===r)}function Bse(e,t){return Number(String(e).slice(0,-t)+\"9\".repeat(t))}function vse(e,t){return e-e%Math.pow(10,t)}function Sse(e){let[t=0,r=\"\"]=e;return r||t>1?`{${t+(r?\",\"+r:\"\")}}`:\"\"}function i7e(e,t,r){return`[${e}${t-e===1?\"\":\"-\"}${t}]`}function Dse(e){return/^-?(0+)\\d/.test(e)}function s7e(e,t,r){if(!t.isPadded)return e;let s=Math.abs(t.maxLen-String(e).length),a=r.relaxZeros!==!1;switch(s){case 0:return\"\";case 1:return a?\"0?\":\"0\";case 2:return a?\"0{0,2}\":\"00\";default:return a?`0{0,${s}}`:`0{${s}}`}}Hd.cache={};Hd.clearCache=()=>Hd.cache={};bse.exports=Hd});var V_=G((IQt,Ose)=>{\"use strict\";var o7e=Ie(\"util\"),Qse=Pse(),xse=e=>e!==null&&typeof e==\"object\"&&!Array.isArray(e),a7e=e=>t=>e===!0?Number(t):String(t),q_=e=>typeof e==\"number\"||typeof e==\"string\"&&e!==\"\",u2=e=>Number.isInteger(+e),W_=e=>{let t=`${e}`,r=-1;if(t[0]===\"-\"&&(t=t.slice(1)),t===\"0\")return!1;for(;t[++r]===\"0\";);return r>0},l7e=(e,t,r)=>typeof e==\"string\"||typeof t==\"string\"?!0:r.stringify===!0,c7e=(e,t,r)=>{if(t>0){let s=e[0]===\"-\"?\"-\":\"\";s&&(e=e.slice(1)),e=s+e.padStart(s?t-1:t,\"0\")}return r===!1?String(e):e},kse=(e,t)=>{let r=e[0]===\"-\"?\"-\":\"\";for(r&&(e=e.slice(1),t--);e.length<t;)e=\"0\"+e;return r?\"-\"+e:e},u7e=(e,t)=>{e.negatives.sort((c,f)=>c<f?-1:c>f?1:0),e.positives.sort((c,f)=>c<f?-1:c>f?1:0);let r=t.capture?\"\":\"?:\",s=\"\",a=\"\",n;return e.positives.length&&(s=e.positives.join(\"|\")),e.negatives.length&&(a=`-(${r}${e.negatives.join(\"|\")})`),s&&a?n=`${s}|${a}`:n=s||a,t.wrap?`(${r}${n})`:n},Rse=(e,t,r,s)=>{if(r)return Qse(e,t,{wrap:!1,...s});let a=String.fromCharCode(e);if(e===t)return a;let n=String.fromCharCode(t);return`[${a}-${n}]`},Tse=(e,t,r)=>{if(Array.isArray(e)){let s=r.wrap===!0,a=r.capture?\"\":\"?:\";return s?`(${a}${e.join(\"|\")})`:e.join(\"|\")}return Qse(e,t,r)},Fse=(...e)=>new RangeError(\"Invalid range arguments: \"+o7e.inspect(...e)),Nse=(e,t,r)=>{if(r.strictRanges===!0)throw Fse([e,t]);return[]},f7e=(e,t)=>{if(t.strictRanges===!0)throw new TypeError(`Expected step \"${e}\" to be a number`);return[]},A7e=(e,t,r=1,s={})=>{let a=Number(e),n=Number(t);if(!Number.isInteger(a)||!Number.isInteger(n)){if(s.strictRanges===!0)throw Fse([e,t]);return[]}a===0&&(a=0),n===0&&(n=0);let c=a>n,f=String(e),p=String(t),h=String(r);r=Math.max(Math.abs(r),1);let E=W_(f)||W_(p)||W_(h),C=E?Math.max(f.length,p.length,h.length):0,S=E===!1&&l7e(e,t,s)===!1,x=s.transform||a7e(S);if(s.toRegex&&r===1)return Rse(kse(e,C),kse(t,C),!0,s);let I={negatives:[],positives:[]},T=Y=>I[Y<0?\"negatives\":\"positives\"].push(Math.abs(Y)),O=[],U=0;for(;c?a>=n:a<=n;)s.toRegex===!0&&r>1?T(a):O.push(c7e(x(a,U),C,S)),a=c?a-r:a+r,U++;return s.toRegex===!0?r>1?u7e(I,s):Tse(O,null,{wrap:!1,...s}):O},p7e=(e,t,r=1,s={})=>{if(!u2(e)&&e.length>1||!u2(t)&&t.length>1)return Nse(e,t,s);let a=s.transform||(S=>String.fromCharCode(S)),n=`${e}`.charCodeAt(0),c=`${t}`.charCodeAt(0),f=n>c,p=Math.min(n,c),h=Math.max(n,c);if(s.toRegex&&r===1)return Rse(p,h,!1,s);let E=[],C=0;for(;f?n>=c:n<=c;)E.push(a(n,C)),n=f?n-r:n+r,C++;return s.toRegex===!0?Tse(E,null,{wrap:!1,options:s}):E},fk=(e,t,r,s={})=>{if(t==null&&q_(e))return[e];if(!q_(e)||!q_(t))return Nse(e,t,s);if(typeof r==\"function\")return fk(e,t,1,{transform:r});if(xse(r))return fk(e,t,0,r);let a={...s};return a.capture===!0&&(a.wrap=!0),r=r||a.step||1,u2(r)?u2(e)&&u2(t)?A7e(e,t,r,a):p7e(e,t,Math.max(Math.abs(r),1),a):r!=null&&!xse(r)?f7e(r,a):fk(e,t,1,r)};Ose.exports=fk});var Use=G((CQt,Mse)=>{\"use strict\";var h7e=V_(),Lse=ck(),g7e=(e,t={})=>{let r=(s,a={})=>{let n=Lse.isInvalidBrace(a),c=s.invalid===!0&&t.escapeInvalid===!0,f=n===!0||c===!0,p=t.escapeInvalid===!0?\"\\\\\":\"\",h=\"\";if(s.isOpen===!0||s.isClose===!0)return p+s.value;if(s.type===\"open\")return f?p+s.value:\"(\";if(s.type===\"close\")return f?p+s.value:\")\";if(s.type===\"comma\")return s.prev.type===\"comma\"?\"\":f?s.value:\"|\";if(s.value)return s.value;if(s.nodes&&s.ranges>0){let E=Lse.reduce(s.nodes),C=h7e(...E,{...t,wrap:!1,toRegex:!0});if(C.length!==0)return E.length>1&&C.length>1?`(${C})`:C}if(s.nodes)for(let E of s.nodes)h+=r(E,s);return h};return r(e)};Mse.exports=g7e});var jse=G((wQt,Hse)=>{\"use strict\";var d7e=V_(),_se=uk(),OE=ck(),jd=(e=\"\",t=\"\",r=!1)=>{let s=[];if(e=[].concat(e),t=[].concat(t),!t.length)return e;if(!e.length)return r?OE.flatten(t).map(a=>`{${a}}`):t;for(let a of e)if(Array.isArray(a))for(let n of a)s.push(jd(n,t,r));else for(let n of t)r===!0&&typeof n==\"string\"&&(n=`{${n}}`),s.push(Array.isArray(n)?jd(a,n,r):a+n);return OE.flatten(s)},m7e=(e,t={})=>{let r=t.rangeLimit===void 0?1e3:t.rangeLimit,s=(a,n={})=>{a.queue=[];let c=n,f=n.queue;for(;c.type!==\"brace\"&&c.type!==\"root\"&&c.parent;)c=c.parent,f=c.queue;if(a.invalid||a.dollar){f.push(jd(f.pop(),_se(a,t)));return}if(a.type===\"brace\"&&a.invalid!==!0&&a.nodes.length===2){f.push(jd(f.pop(),[\"{}\"]));return}if(a.nodes&&a.ranges>0){let C=OE.reduce(a.nodes);if(OE.exceedsLimit(...C,t.step,r))throw new RangeError(\"expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.\");let S=d7e(...C,t);S.length===0&&(S=_se(a,t)),f.push(jd(f.pop(),S)),a.nodes=[];return}let p=OE.encloseBrace(a),h=a.queue,E=a;for(;E.type!==\"brace\"&&E.type!==\"root\"&&E.parent;)E=E.parent,h=E.queue;for(let C=0;C<a.nodes.length;C++){let S=a.nodes[C];if(S.type===\"comma\"&&a.type===\"brace\"){C===1&&h.push(\"\"),h.push(\"\");continue}if(S.type===\"close\"){f.push(jd(f.pop(),h,p));continue}if(S.value&&S.type!==\"open\"){h.push(jd(h.pop(),S.value));continue}S.nodes&&s(S,a)}return h};return OE.flatten(s(e))};Hse.exports=m7e});var qse=G((BQt,Gse)=>{\"use strict\";Gse.exports={MAX_LENGTH:1024*64,CHAR_0:\"0\",CHAR_9:\"9\",CHAR_UPPERCASE_A:\"A\",CHAR_LOWERCASE_A:\"a\",CHAR_UPPERCASE_Z:\"Z\",CHAR_LOWERCASE_Z:\"z\",CHAR_LEFT_PARENTHESES:\"(\",CHAR_RIGHT_PARENTHESES:\")\",CHAR_ASTERISK:\"*\",CHAR_AMPERSAND:\"&\",CHAR_AT:\"@\",CHAR_BACKSLASH:\"\\\\\",CHAR_BACKTICK:\"`\",CHAR_CARRIAGE_RETURN:\"\\r\",CHAR_CIRCUMFLEX_ACCENT:\"^\",CHAR_COLON:\":\",CHAR_COMMA:\",\",CHAR_DOLLAR:\"$\",CHAR_DOT:\".\",CHAR_DOUBLE_QUOTE:'\"',CHAR_EQUAL:\"=\",CHAR_EXCLAMATION_MARK:\"!\",CHAR_FORM_FEED:\"\\f\",CHAR_FORWARD_SLASH:\"/\",CHAR_HASH:\"#\",CHAR_HYPHEN_MINUS:\"-\",CHAR_LEFT_ANGLE_BRACKET:\"<\",CHAR_LEFT_CURLY_BRACE:\"{\",CHAR_LEFT_SQUARE_BRACKET:\"[\",CHAR_LINE_FEED:`\n`,CHAR_NO_BREAK_SPACE:\"\\xA0\",CHAR_PERCENT:\"%\",CHAR_PLUS:\"+\",CHAR_QUESTION_MARK:\"?\",CHAR_RIGHT_ANGLE_BRACKET:\">\",CHAR_RIGHT_CURLY_BRACE:\"}\",CHAR_RIGHT_SQUARE_BRACKET:\"]\",CHAR_SEMICOLON:\";\",CHAR_SINGLE_QUOTE:\"'\",CHAR_SPACE:\" \",CHAR_TAB:\"\t\",CHAR_UNDERSCORE:\"_\",CHAR_VERTICAL_LINE:\"|\",CHAR_ZERO_WIDTH_NOBREAK_SPACE:\"\\uFEFF\"}});var Jse=G((vQt,Kse)=>{\"use strict\";var y7e=uk(),{MAX_LENGTH:Wse,CHAR_BACKSLASH:Y_,CHAR_BACKTICK:E7e,CHAR_COMMA:I7e,CHAR_DOT:C7e,CHAR_LEFT_PARENTHESES:w7e,CHAR_RIGHT_PARENTHESES:B7e,CHAR_LEFT_CURLY_BRACE:v7e,CHAR_RIGHT_CURLY_BRACE:S7e,CHAR_LEFT_SQUARE_BRACKET:Vse,CHAR_RIGHT_SQUARE_BRACKET:Yse,CHAR_DOUBLE_QUOTE:D7e,CHAR_SINGLE_QUOTE:b7e,CHAR_NO_BREAK_SPACE:P7e,CHAR_ZERO_WIDTH_NOBREAK_SPACE:x7e}=qse(),k7e=(e,t={})=>{if(typeof e!=\"string\")throw new TypeError(\"Expected a string\");let r=t||{},s=typeof r.maxLength==\"number\"?Math.min(Wse,r.maxLength):Wse;if(e.length>s)throw new SyntaxError(`Input length (${e.length}), exceeds max characters (${s})`);let a={type:\"root\",input:e,nodes:[]},n=[a],c=a,f=a,p=0,h=e.length,E=0,C=0,S,x={},I=()=>e[E++],T=O=>{if(O.type===\"text\"&&f.type===\"dot\"&&(f.type=\"text\"),f&&f.type===\"text\"&&O.type===\"text\"){f.value+=O.value;return}return c.nodes.push(O),O.parent=c,O.prev=f,f=O,O};for(T({type:\"bos\"});E<h;)if(c=n[n.length-1],S=I(),!(S===x7e||S===P7e)){if(S===Y_){T({type:\"text\",value:(t.keepEscaping?S:\"\")+I()});continue}if(S===Yse){T({type:\"text\",value:\"\\\\\"+S});continue}if(S===Vse){p++;let O=!0,U;for(;E<h&&(U=I());){if(S+=U,U===Vse){p++;continue}if(U===Y_){S+=I();continue}if(U===Yse&&(p--,p===0))break}T({type:\"text\",value:S});continue}if(S===w7e){c=T({type:\"paren\",nodes:[]}),n.push(c),T({type:\"text\",value:S});continue}if(S===B7e){if(c.type!==\"paren\"){T({type:\"text\",value:S});continue}c=n.pop(),T({type:\"text\",value:S}),c=n[n.length-1];continue}if(S===D7e||S===b7e||S===E7e){let O=S,U;for(t.keepQuotes!==!0&&(S=\"\");E<h&&(U=I());){if(U===Y_){S+=U+I();continue}if(U===O){t.keepQuotes===!0&&(S+=U);break}S+=U}T({type:\"text\",value:S});continue}if(S===v7e){C++;let U={type:\"brace\",open:!0,close:!1,dollar:f.value&&f.value.slice(-1)===\"$\"||c.dollar===!0,depth:C,commas:0,ranges:0,nodes:[]};c=T(U),n.push(c),T({type:\"open\",value:S});continue}if(S===S7e){if(c.type!==\"brace\"){T({type:\"text\",value:S});continue}let O=\"close\";c=n.pop(),c.close=!0,T({type:O,value:S}),C--,c=n[n.length-1];continue}if(S===I7e&&C>0){if(c.ranges>0){c.ranges=0;let O=c.nodes.shift();c.nodes=[O,{type:\"text\",value:y7e(c)}]}T({type:\"comma\",value:S}),c.commas++;continue}if(S===C7e&&C>0&&c.commas===0){let O=c.nodes;if(C===0||O.length===0){T({type:\"text\",value:S});continue}if(f.type===\"dot\"){if(c.range=[],f.value+=S,f.type=\"range\",c.nodes.length!==3&&c.nodes.length!==5){c.invalid=!0,c.ranges=0,f.type=\"text\";continue}c.ranges++,c.args=[];continue}if(f.type===\"range\"){O.pop();let U=O[O.length-1];U.value+=f.value+S,f=U,c.ranges--;continue}T({type:\"dot\",value:S});continue}T({type:\"text\",value:S})}do if(c=n.pop(),c.type!==\"root\"){c.nodes.forEach(Y=>{Y.nodes||(Y.type===\"open\"&&(Y.isOpen=!0),Y.type===\"close\"&&(Y.isClose=!0),Y.nodes||(Y.type=\"text\"),Y.invalid=!0)});let O=n[n.length-1],U=O.nodes.indexOf(c);O.nodes.splice(U,1,...c.nodes)}while(n.length>0);return T({type:\"eos\"}),a};Kse.exports=k7e});var Xse=G((SQt,Zse)=>{\"use strict\";var zse=uk(),Q7e=Use(),R7e=jse(),T7e=Jse(),Yl=(e,t={})=>{let r=[];if(Array.isArray(e))for(let s of e){let a=Yl.create(s,t);Array.isArray(a)?r.push(...a):r.push(a)}else r=[].concat(Yl.create(e,t));return t&&t.expand===!0&&t.nodupes===!0&&(r=[...new Set(r)]),r};Yl.parse=(e,t={})=>T7e(e,t);Yl.stringify=(e,t={})=>zse(typeof e==\"string\"?Yl.parse(e,t):e,t);Yl.compile=(e,t={})=>(typeof e==\"string\"&&(e=Yl.parse(e,t)),Q7e(e,t));Yl.expand=(e,t={})=>{typeof e==\"string\"&&(e=Yl.parse(e,t));let r=R7e(e,t);return t.noempty===!0&&(r=r.filter(Boolean)),t.nodupes===!0&&(r=[...new Set(r)]),r};Yl.create=(e,t={})=>e===\"\"||e.length<3?[e]:t.expand!==!0?Yl.compile(e,t):Yl.expand(e,t);Zse.exports=Yl});var f2=G((DQt,noe)=>{\"use strict\";var F7e=Ie(\"path\"),Jf=\"\\\\\\\\/\",$se=`[^${Jf}]`,bp=\"\\\\.\",N7e=\"\\\\+\",O7e=\"\\\\?\",Ak=\"\\\\/\",L7e=\"(?=.)\",eoe=\"[^/]\",K_=`(?:${Ak}|$)`,toe=`(?:^|${Ak})`,J_=`${bp}{1,2}${K_}`,M7e=`(?!${bp})`,U7e=`(?!${toe}${J_})`,_7e=`(?!${bp}{0,1}${K_})`,H7e=`(?!${J_})`,j7e=`[^.${Ak}]`,G7e=`${eoe}*?`,roe={DOT_LITERAL:bp,PLUS_LITERAL:N7e,QMARK_LITERAL:O7e,SLASH_LITERAL:Ak,ONE_CHAR:L7e,QMARK:eoe,END_ANCHOR:K_,DOTS_SLASH:J_,NO_DOT:M7e,NO_DOTS:U7e,NO_DOT_SLASH:_7e,NO_DOTS_SLASH:H7e,QMARK_NO_DOT:j7e,STAR:G7e,START_ANCHOR:toe},q7e={...roe,SLASH_LITERAL:`[${Jf}]`,QMARK:$se,STAR:`${$se}*?`,DOTS_SLASH:`${bp}{1,2}(?:[${Jf}]|$)`,NO_DOT:`(?!${bp})`,NO_DOTS:`(?!(?:^|[${Jf}])${bp}{1,2}(?:[${Jf}]|$))`,NO_DOT_SLASH:`(?!${bp}{0,1}(?:[${Jf}]|$))`,NO_DOTS_SLASH:`(?!${bp}{1,2}(?:[${Jf}]|$))`,QMARK_NO_DOT:`[^.${Jf}]`,START_ANCHOR:`(?:^|[${Jf}])`,END_ANCHOR:`(?:[${Jf}]|$)`},W7e={alnum:\"a-zA-Z0-9\",alpha:\"a-zA-Z\",ascii:\"\\\\x00-\\\\x7F\",blank:\" \\\\t\",cntrl:\"\\\\x00-\\\\x1F\\\\x7F\",digit:\"0-9\",graph:\"\\\\x21-\\\\x7E\",lower:\"a-z\",print:\"\\\\x20-\\\\x7E \",punct:\"\\\\-!\\\"#$%&'()\\\\*+,./:;<=>?@[\\\\]^_`{|}~\",space:\" \\\\t\\\\r\\\\n\\\\v\\\\f\",upper:\"A-Z\",word:\"A-Za-z0-9_\",xdigit:\"A-Fa-f0-9\"};noe.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:W7e,REGEX_BACKSLASH:/\\\\(?![*+?^${}(|)[\\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\\].,$*+?^{}()|\\\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\\\?)((\\W)(\\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\\[.*?[^\\\\]\\]|\\\\(?=.))/g,REPLACEMENTS:{\"***\":\"*\",\"**/**\":\"**\",\"**/**/**\":\"**\"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:F7e.sep,extglobChars(e){return{\"!\":{type:\"negate\",open:\"(?:(?!(?:\",close:`))${e.STAR})`},\"?\":{type:\"qmark\",open:\"(?:\",close:\")?\"},\"+\":{type:\"plus\",open:\"(?:\",close:\")+\"},\"*\":{type:\"star\",open:\"(?:\",close:\")*\"},\"@\":{type:\"at\",open:\"(?:\",close:\")\"}}},globChars(e){return e===!0?q7e:roe}}});var A2=G(pl=>{\"use strict\";var V7e=Ie(\"path\"),Y7e=process.platform===\"win32\",{REGEX_BACKSLASH:K7e,REGEX_REMOVE_BACKSLASH:J7e,REGEX_SPECIAL_CHARS:z7e,REGEX_SPECIAL_CHARS_GLOBAL:Z7e}=f2();pl.isObject=e=>e!==null&&typeof e==\"object\"&&!Array.isArray(e);pl.hasRegexChars=e=>z7e.test(e);pl.isRegexChar=e=>e.length===1&&pl.hasRegexChars(e);pl.escapeRegex=e=>e.replace(Z7e,\"\\\\$1\");pl.toPosixSlashes=e=>e.replace(K7e,\"/\");pl.removeBackslashes=e=>e.replace(J7e,t=>t===\"\\\\\"?\"\":t);pl.supportsLookbehinds=()=>{let e=process.version.slice(1).split(\".\").map(Number);return e.length===3&&e[0]>=9||e[0]===8&&e[1]>=10};pl.isWindows=e=>e&&typeof e.windows==\"boolean\"?e.windows:Y7e===!0||V7e.sep===\"\\\\\";pl.escapeLast=(e,t,r)=>{let s=e.lastIndexOf(t,r);return s===-1?e:e[s-1]===\"\\\\\"?pl.escapeLast(e,t,s-1):`${e.slice(0,s)}\\\\${e.slice(s)}`};pl.removePrefix=(e,t={})=>{let r=e;return r.startsWith(\"./\")&&(r=r.slice(2),t.prefix=\"./\"),r};pl.wrapOutput=(e,t={},r={})=>{let s=r.contains?\"\":\"^\",a=r.contains?\"\":\"$\",n=`${s}(?:${e})${a}`;return t.negated===!0&&(n=`(?:^(?!${n}).*$)`),n}});var foe=G((PQt,uoe)=>{\"use strict\";var ioe=A2(),{CHAR_ASTERISK:z_,CHAR_AT:X7e,CHAR_BACKWARD_SLASH:p2,CHAR_COMMA:$7e,CHAR_DOT:Z_,CHAR_EXCLAMATION_MARK:X_,CHAR_FORWARD_SLASH:coe,CHAR_LEFT_CURLY_BRACE:$_,CHAR_LEFT_PARENTHESES:e4,CHAR_LEFT_SQUARE_BRACKET:eKe,CHAR_PLUS:tKe,CHAR_QUESTION_MARK:soe,CHAR_RIGHT_CURLY_BRACE:rKe,CHAR_RIGHT_PARENTHESES:ooe,CHAR_RIGHT_SQUARE_BRACKET:nKe}=f2(),aoe=e=>e===coe||e===p2,loe=e=>{e.isPrefix!==!0&&(e.depth=e.isGlobstar?1/0:1)},iKe=(e,t)=>{let r=t||{},s=e.length-1,a=r.parts===!0||r.scanToEnd===!0,n=[],c=[],f=[],p=e,h=-1,E=0,C=0,S=!1,x=!1,I=!1,T=!1,O=!1,U=!1,Y=!1,te=!1,ie=!1,ue=!1,ae=0,de,Ae,Ce={value:\"\",depth:0,isGlob:!1},Ee=()=>h>=s,g=()=>p.charCodeAt(h+1),Se=()=>(de=Ae,p.charCodeAt(++h));for(;h<s;){Ae=Se();let De;if(Ae===p2){Y=Ce.backslashes=!0,Ae=Se(),Ae===$_&&(U=!0);continue}if(U===!0||Ae===$_){for(ae++;Ee()!==!0&&(Ae=Se());){if(Ae===p2){Y=Ce.backslashes=!0,Se();continue}if(Ae===$_){ae++;continue}if(U!==!0&&Ae===Z_&&(Ae=Se())===Z_){if(S=Ce.isBrace=!0,I=Ce.isGlob=!0,ue=!0,a===!0)continue;break}if(U!==!0&&Ae===$7e){if(S=Ce.isBrace=!0,I=Ce.isGlob=!0,ue=!0,a===!0)continue;break}if(Ae===rKe&&(ae--,ae===0)){U=!1,S=Ce.isBrace=!0,ue=!0;break}}if(a===!0)continue;break}if(Ae===coe){if(n.push(h),c.push(Ce),Ce={value:\"\",depth:0,isGlob:!1},ue===!0)continue;if(de===Z_&&h===E+1){E+=2;continue}C=h+1;continue}if(r.noext!==!0&&(Ae===tKe||Ae===X7e||Ae===z_||Ae===soe||Ae===X_)===!0&&g()===e4){if(I=Ce.isGlob=!0,T=Ce.isExtglob=!0,ue=!0,Ae===X_&&h===E&&(ie=!0),a===!0){for(;Ee()!==!0&&(Ae=Se());){if(Ae===p2){Y=Ce.backslashes=!0,Ae=Se();continue}if(Ae===ooe){I=Ce.isGlob=!0,ue=!0;break}}continue}break}if(Ae===z_){if(de===z_&&(O=Ce.isGlobstar=!0),I=Ce.isGlob=!0,ue=!0,a===!0)continue;break}if(Ae===soe){if(I=Ce.isGlob=!0,ue=!0,a===!0)continue;break}if(Ae===eKe){for(;Ee()!==!0&&(De=Se());){if(De===p2){Y=Ce.backslashes=!0,Se();continue}if(De===nKe){x=Ce.isBracket=!0,I=Ce.isGlob=!0,ue=!0;break}}if(a===!0)continue;break}if(r.nonegate!==!0&&Ae===X_&&h===E){te=Ce.negated=!0,E++;continue}if(r.noparen!==!0&&Ae===e4){if(I=Ce.isGlob=!0,a===!0){for(;Ee()!==!0&&(Ae=Se());){if(Ae===e4){Y=Ce.backslashes=!0,Ae=Se();continue}if(Ae===ooe){ue=!0;break}}continue}break}if(I===!0){if(ue=!0,a===!0)continue;break}}r.noext===!0&&(T=!1,I=!1);let Be=p,me=\"\",ce=\"\";E>0&&(me=p.slice(0,E),p=p.slice(E),C-=E),Be&&I===!0&&C>0?(Be=p.slice(0,C),ce=p.slice(C)):I===!0?(Be=\"\",ce=p):Be=p,Be&&Be!==\"\"&&Be!==\"/\"&&Be!==p&&aoe(Be.charCodeAt(Be.length-1))&&(Be=Be.slice(0,-1)),r.unescape===!0&&(ce&&(ce=ioe.removeBackslashes(ce)),Be&&Y===!0&&(Be=ioe.removeBackslashes(Be)));let X={prefix:me,input:e,start:E,base:Be,glob:ce,isBrace:S,isBracket:x,isGlob:I,isExtglob:T,isGlobstar:O,negated:te,negatedExtglob:ie};if(r.tokens===!0&&(X.maxDepth=0,aoe(Ae)||c.push(Ce),X.tokens=c),r.parts===!0||r.tokens===!0){let De;for(let Qe=0;Qe<n.length;Qe++){let it=De?De+1:E,_=n[Qe],tt=e.slice(it,_);r.tokens&&(Qe===0&&E!==0?(c[Qe].isPrefix=!0,c[Qe].value=me):c[Qe].value=tt,loe(c[Qe]),X.maxDepth+=c[Qe].depth),(Qe!==0||tt!==\"\")&&f.push(tt),De=_}if(De&&De+1<e.length){let Qe=e.slice(De+1);f.push(Qe),r.tokens&&(c[c.length-1].value=Qe,loe(c[c.length-1]),X.maxDepth+=c[c.length-1].depth)}X.slashes=n,X.parts=f}return X};uoe.exports=iKe});var hoe=G((xQt,poe)=>{\"use strict\";var pk=f2(),Kl=A2(),{MAX_LENGTH:hk,POSIX_REGEX_SOURCE:sKe,REGEX_NON_SPECIAL_CHARS:oKe,REGEX_SPECIAL_CHARS_BACKREF:aKe,REPLACEMENTS:Aoe}=pk,lKe=(e,t)=>{if(typeof t.expandRange==\"function\")return t.expandRange(...e,t);e.sort();let r=`[${e.join(\"-\")}]`;try{new RegExp(r)}catch{return e.map(a=>Kl.escapeRegex(a)).join(\"..\")}return r},LE=(e,t)=>`Missing ${e}: \"${t}\" - use \"\\\\\\\\${t}\" to match literal characters`,t4=(e,t)=>{if(typeof e!=\"string\")throw new TypeError(\"Expected a string\");e=Aoe[e]||e;let r={...t},s=typeof r.maxLength==\"number\"?Math.min(hk,r.maxLength):hk,a=e.length;if(a>s)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${s}`);let n={type:\"bos\",value:\"\",output:r.prepend||\"\"},c=[n],f=r.capture?\"\":\"?:\",p=Kl.isWindows(t),h=pk.globChars(p),E=pk.extglobChars(h),{DOT_LITERAL:C,PLUS_LITERAL:S,SLASH_LITERAL:x,ONE_CHAR:I,DOTS_SLASH:T,NO_DOT:O,NO_DOT_SLASH:U,NO_DOTS_SLASH:Y,QMARK:te,QMARK_NO_DOT:ie,STAR:ue,START_ANCHOR:ae}=h,de=P=>`(${f}(?:(?!${ae}${P.dot?T:C}).)*?)`,Ae=r.dot?\"\":O,Ce=r.dot?te:ie,Ee=r.bash===!0?de(r):ue;r.capture&&(Ee=`(${Ee})`),typeof r.noext==\"boolean\"&&(r.noextglob=r.noext);let g={input:e,index:-1,start:0,dot:r.dot===!0,consumed:\"\",output:\"\",prefix:\"\",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:c};e=Kl.removePrefix(e,g),a=e.length;let Se=[],Be=[],me=[],ce=n,X,De=()=>g.index===a-1,Qe=g.peek=(P=1)=>e[g.index+P],it=g.advance=()=>e[++g.index]||\"\",_=()=>e.slice(g.index+1),tt=(P=\"\",w=0)=>{g.consumed+=P,g.index+=w},Ne=P=>{g.output+=P.output!=null?P.output:P.value,tt(P.value)},ke=()=>{let P=1;for(;Qe()===\"!\"&&(Qe(2)!==\"(\"||Qe(3)===\"?\");)it(),g.start++,P++;return P%2===0?!1:(g.negated=!0,g.start++,!0)},be=P=>{g[P]++,me.push(P)},je=P=>{g[P]--,me.pop()},Re=P=>{if(ce.type===\"globstar\"){let w=g.braces>0&&(P.type===\"comma\"||P.type===\"brace\"),b=P.extglob===!0||Se.length&&(P.type===\"pipe\"||P.type===\"paren\");P.type!==\"slash\"&&P.type!==\"paren\"&&!w&&!b&&(g.output=g.output.slice(0,-ce.output.length),ce.type=\"star\",ce.value=\"*\",ce.output=Ee,g.output+=ce.output)}if(Se.length&&P.type!==\"paren\"&&(Se[Se.length-1].inner+=P.value),(P.value||P.output)&&Ne(P),ce&&ce.type===\"text\"&&P.type===\"text\"){ce.value+=P.value,ce.output=(ce.output||\"\")+P.value;return}P.prev=ce,c.push(P),ce=P},ct=(P,w)=>{let b={...E[w],conditions:1,inner:\"\"};b.prev=ce,b.parens=g.parens,b.output=g.output;let y=(r.capture?\"(\":\"\")+b.open;be(\"parens\"),Re({type:P,value:w,output:g.output?\"\":I}),Re({type:\"paren\",extglob:!0,value:it(),output:y}),Se.push(b)},Me=P=>{let w=P.close+(r.capture?\")\":\"\"),b;if(P.type===\"negate\"){let y=Ee;if(P.inner&&P.inner.length>1&&P.inner.includes(\"/\")&&(y=de(r)),(y!==Ee||De()||/^\\)+$/.test(_()))&&(w=P.close=`)$))${y}`),P.inner.includes(\"*\")&&(b=_())&&/^\\.[^\\\\/.]+$/.test(b)){let F=t4(b,{...t,fastpaths:!1}).output;w=P.close=`)${F})${y})`}P.prev.type===\"bos\"&&(g.negatedExtglob=!0)}Re({type:\"paren\",extglob:!0,value:X,output:w}),je(\"parens\")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\\]{}\"])/.test(e)){let P=!1,w=e.replace(aKe,(b,y,F,z,Z,$)=>z===\"\\\\\"?(P=!0,b):z===\"?\"?y?y+z+(Z?te.repeat(Z.length):\"\"):$===0?Ce+(Z?te.repeat(Z.length):\"\"):te.repeat(F.length):z===\".\"?C.repeat(F.length):z===\"*\"?y?y+z+(Z?Ee:\"\"):Ee:y?b:`\\\\${b}`);return P===!0&&(r.unescape===!0?w=w.replace(/\\\\/g,\"\"):w=w.replace(/\\\\+/g,b=>b.length%2===0?\"\\\\\\\\\":b?\"\\\\\":\"\")),w===e&&r.contains===!0?(g.output=e,g):(g.output=Kl.wrapOutput(w,g,t),g)}for(;!De();){if(X=it(),X===\"\\0\")continue;if(X===\"\\\\\"){let b=Qe();if(b===\"/\"&&r.bash!==!0||b===\".\"||b===\";\")continue;if(!b){X+=\"\\\\\",Re({type:\"text\",value:X});continue}let y=/^\\\\+/.exec(_()),F=0;if(y&&y[0].length>2&&(F=y[0].length,g.index+=F,F%2!==0&&(X+=\"\\\\\")),r.unescape===!0?X=it():X+=it(),g.brackets===0){Re({type:\"text\",value:X});continue}}if(g.brackets>0&&(X!==\"]\"||ce.value===\"[\"||ce.value===\"[^\")){if(r.posix!==!1&&X===\":\"){let b=ce.value.slice(1);if(b.includes(\"[\")&&(ce.posix=!0,b.includes(\":\"))){let y=ce.value.lastIndexOf(\"[\"),F=ce.value.slice(0,y),z=ce.value.slice(y+2),Z=sKe[z];if(Z){ce.value=F+Z,g.backtrack=!0,it(),!n.output&&c.indexOf(ce)===1&&(n.output=I);continue}}}(X===\"[\"&&Qe()!==\":\"||X===\"-\"&&Qe()===\"]\")&&(X=`\\\\${X}`),X===\"]\"&&(ce.value===\"[\"||ce.value===\"[^\")&&(X=`\\\\${X}`),r.posix===!0&&X===\"!\"&&ce.value===\"[\"&&(X=\"^\"),ce.value+=X,Ne({value:X});continue}if(g.quotes===1&&X!=='\"'){X=Kl.escapeRegex(X),ce.value+=X,Ne({value:X});continue}if(X==='\"'){g.quotes=g.quotes===1?0:1,r.keepQuotes===!0&&Re({type:\"text\",value:X});continue}if(X===\"(\"){be(\"parens\"),Re({type:\"paren\",value:X});continue}if(X===\")\"){if(g.parens===0&&r.strictBrackets===!0)throw new SyntaxError(LE(\"opening\",\"(\"));let b=Se[Se.length-1];if(b&&g.parens===b.parens+1){Me(Se.pop());continue}Re({type:\"paren\",value:X,output:g.parens?\")\":\"\\\\)\"}),je(\"parens\");continue}if(X===\"[\"){if(r.nobracket===!0||!_().includes(\"]\")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(LE(\"closing\",\"]\"));X=`\\\\${X}`}else be(\"brackets\");Re({type:\"bracket\",value:X});continue}if(X===\"]\"){if(r.nobracket===!0||ce&&ce.type===\"bracket\"&&ce.value.length===1){Re({type:\"text\",value:X,output:`\\\\${X}`});continue}if(g.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(LE(\"opening\",\"[\"));Re({type:\"text\",value:X,output:`\\\\${X}`});continue}je(\"brackets\");let b=ce.value.slice(1);if(ce.posix!==!0&&b[0]===\"^\"&&!b.includes(\"/\")&&(X=`/${X}`),ce.value+=X,Ne({value:X}),r.literalBrackets===!1||Kl.hasRegexChars(b))continue;let y=Kl.escapeRegex(ce.value);if(g.output=g.output.slice(0,-ce.value.length),r.literalBrackets===!0){g.output+=y,ce.value=y;continue}ce.value=`(${f}${y}|${ce.value})`,g.output+=ce.value;continue}if(X===\"{\"&&r.nobrace!==!0){be(\"braces\");let b={type:\"brace\",value:X,output:\"(\",outputIndex:g.output.length,tokensIndex:g.tokens.length};Be.push(b),Re(b);continue}if(X===\"}\"){let b=Be[Be.length-1];if(r.nobrace===!0||!b){Re({type:\"text\",value:X,output:X});continue}let y=\")\";if(b.dots===!0){let F=c.slice(),z=[];for(let Z=F.length-1;Z>=0&&(c.pop(),F[Z].type!==\"brace\");Z--)F[Z].type!==\"dots\"&&z.unshift(F[Z].value);y=lKe(z,r),g.backtrack=!0}if(b.comma!==!0&&b.dots!==!0){let F=g.output.slice(0,b.outputIndex),z=g.tokens.slice(b.tokensIndex);b.value=b.output=\"\\\\{\",X=y=\"\\\\}\",g.output=F;for(let Z of z)g.output+=Z.output||Z.value}Re({type:\"brace\",value:X,output:y}),je(\"braces\"),Be.pop();continue}if(X===\"|\"){Se.length>0&&Se[Se.length-1].conditions++,Re({type:\"text\",value:X});continue}if(X===\",\"){let b=X,y=Be[Be.length-1];y&&me[me.length-1]===\"braces\"&&(y.comma=!0,b=\"|\"),Re({type:\"comma\",value:X,output:b});continue}if(X===\"/\"){if(ce.type===\"dot\"&&g.index===g.start+1){g.start=g.index+1,g.consumed=\"\",g.output=\"\",c.pop(),ce=n;continue}Re({type:\"slash\",value:X,output:x});continue}if(X===\".\"){if(g.braces>0&&ce.type===\"dot\"){ce.value===\".\"&&(ce.output=C);let b=Be[Be.length-1];ce.type=\"dots\",ce.output+=X,ce.value+=X,b.dots=!0;continue}if(g.braces+g.parens===0&&ce.type!==\"bos\"&&ce.type!==\"slash\"){Re({type:\"text\",value:X,output:C});continue}Re({type:\"dot\",value:X,output:C});continue}if(X===\"?\"){if(!(ce&&ce.value===\"(\")&&r.noextglob!==!0&&Qe()===\"(\"&&Qe(2)!==\"?\"){ct(\"qmark\",X);continue}if(ce&&ce.type===\"paren\"){let y=Qe(),F=X;if(y===\"<\"&&!Kl.supportsLookbehinds())throw new Error(\"Node.js v10 or higher is required for regex lookbehinds\");(ce.value===\"(\"&&!/[!=<:]/.test(y)||y===\"<\"&&!/<([!=]|\\w+>)/.test(_()))&&(F=`\\\\${X}`),Re({type:\"text\",value:X,output:F});continue}if(r.dot!==!0&&(ce.type===\"slash\"||ce.type===\"bos\")){Re({type:\"qmark\",value:X,output:ie});continue}Re({type:\"qmark\",value:X,output:te});continue}if(X===\"!\"){if(r.noextglob!==!0&&Qe()===\"(\"&&(Qe(2)!==\"?\"||!/[!=<:]/.test(Qe(3)))){ct(\"negate\",X);continue}if(r.nonegate!==!0&&g.index===0){ke();continue}}if(X===\"+\"){if(r.noextglob!==!0&&Qe()===\"(\"&&Qe(2)!==\"?\"){ct(\"plus\",X);continue}if(ce&&ce.value===\"(\"||r.regex===!1){Re({type:\"plus\",value:X,output:S});continue}if(ce&&(ce.type===\"bracket\"||ce.type===\"paren\"||ce.type===\"brace\")||g.parens>0){Re({type:\"plus\",value:X});continue}Re({type:\"plus\",value:S});continue}if(X===\"@\"){if(r.noextglob!==!0&&Qe()===\"(\"&&Qe(2)!==\"?\"){Re({type:\"at\",extglob:!0,value:X,output:\"\"});continue}Re({type:\"text\",value:X});continue}if(X!==\"*\"){(X===\"$\"||X===\"^\")&&(X=`\\\\${X}`);let b=oKe.exec(_());b&&(X+=b[0],g.index+=b[0].length),Re({type:\"text\",value:X});continue}if(ce&&(ce.type===\"globstar\"||ce.star===!0)){ce.type=\"star\",ce.star=!0,ce.value+=X,ce.output=Ee,g.backtrack=!0,g.globstar=!0,tt(X);continue}let P=_();if(r.noextglob!==!0&&/^\\([^?]/.test(P)){ct(\"star\",X);continue}if(ce.type===\"star\"){if(r.noglobstar===!0){tt(X);continue}let b=ce.prev,y=b.prev,F=b.type===\"slash\"||b.type===\"bos\",z=y&&(y.type===\"star\"||y.type===\"globstar\");if(r.bash===!0&&(!F||P[0]&&P[0]!==\"/\")){Re({type:\"star\",value:X,output:\"\"});continue}let Z=g.braces>0&&(b.type===\"comma\"||b.type===\"brace\"),$=Se.length&&(b.type===\"pipe\"||b.type===\"paren\");if(!F&&b.type!==\"paren\"&&!Z&&!$){Re({type:\"star\",value:X,output:\"\"});continue}for(;P.slice(0,3)===\"/**\";){let se=e[g.index+4];if(se&&se!==\"/\")break;P=P.slice(3),tt(\"/**\",3)}if(b.type===\"bos\"&&De()){ce.type=\"globstar\",ce.value+=X,ce.output=de(r),g.output=ce.output,g.globstar=!0,tt(X);continue}if(b.type===\"slash\"&&b.prev.type!==\"bos\"&&!z&&De()){g.output=g.output.slice(0,-(b.output+ce.output).length),b.output=`(?:${b.output}`,ce.type=\"globstar\",ce.output=de(r)+(r.strictSlashes?\")\":\"|$)\"),ce.value+=X,g.globstar=!0,g.output+=b.output+ce.output,tt(X);continue}if(b.type===\"slash\"&&b.prev.type!==\"bos\"&&P[0]===\"/\"){let se=P[1]!==void 0?\"|$\":\"\";g.output=g.output.slice(0,-(b.output+ce.output).length),b.output=`(?:${b.output}`,ce.type=\"globstar\",ce.output=`${de(r)}${x}|${x}${se})`,ce.value+=X,g.output+=b.output+ce.output,g.globstar=!0,tt(X+it()),Re({type:\"slash\",value:\"/\",output:\"\"});continue}if(b.type===\"bos\"&&P[0]===\"/\"){ce.type=\"globstar\",ce.value+=X,ce.output=`(?:^|${x}|${de(r)}${x})`,g.output=ce.output,g.globstar=!0,tt(X+it()),Re({type:\"slash\",value:\"/\",output:\"\"});continue}g.output=g.output.slice(0,-ce.output.length),ce.type=\"globstar\",ce.output=de(r),ce.value+=X,g.output+=ce.output,g.globstar=!0,tt(X);continue}let w={type:\"star\",value:X,output:Ee};if(r.bash===!0){w.output=\".*?\",(ce.type===\"bos\"||ce.type===\"slash\")&&(w.output=Ae+w.output),Re(w);continue}if(ce&&(ce.type===\"bracket\"||ce.type===\"paren\")&&r.regex===!0){w.output=X,Re(w);continue}(g.index===g.start||ce.type===\"slash\"||ce.type===\"dot\")&&(ce.type===\"dot\"?(g.output+=U,ce.output+=U):r.dot===!0?(g.output+=Y,ce.output+=Y):(g.output+=Ae,ce.output+=Ae),Qe()!==\"*\"&&(g.output+=I,ce.output+=I)),Re(w)}for(;g.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(LE(\"closing\",\"]\"));g.output=Kl.escapeLast(g.output,\"[\"),je(\"brackets\")}for(;g.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(LE(\"closing\",\")\"));g.output=Kl.escapeLast(g.output,\"(\"),je(\"parens\")}for(;g.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(LE(\"closing\",\"}\"));g.output=Kl.escapeLast(g.output,\"{\"),je(\"braces\")}if(r.strictSlashes!==!0&&(ce.type===\"star\"||ce.type===\"bracket\")&&Re({type:\"maybe_slash\",value:\"\",output:`${x}?`}),g.backtrack===!0){g.output=\"\";for(let P of g.tokens)g.output+=P.output!=null?P.output:P.value,P.suffix&&(g.output+=P.suffix)}return g};t4.fastpaths=(e,t)=>{let r={...t},s=typeof r.maxLength==\"number\"?Math.min(hk,r.maxLength):hk,a=e.length;if(a>s)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${s}`);e=Aoe[e]||e;let n=Kl.isWindows(t),{DOT_LITERAL:c,SLASH_LITERAL:f,ONE_CHAR:p,DOTS_SLASH:h,NO_DOT:E,NO_DOTS:C,NO_DOTS_SLASH:S,STAR:x,START_ANCHOR:I}=pk.globChars(n),T=r.dot?C:E,O=r.dot?S:E,U=r.capture?\"\":\"?:\",Y={negated:!1,prefix:\"\"},te=r.bash===!0?\".*?\":x;r.capture&&(te=`(${te})`);let ie=Ae=>Ae.noglobstar===!0?te:`(${U}(?:(?!${I}${Ae.dot?h:c}).)*?)`,ue=Ae=>{switch(Ae){case\"*\":return`${T}${p}${te}`;case\".*\":return`${c}${p}${te}`;case\"*.*\":return`${T}${te}${c}${p}${te}`;case\"*/*\":return`${T}${te}${f}${p}${O}${te}`;case\"**\":return T+ie(r);case\"**/*\":return`(?:${T}${ie(r)}${f})?${O}${p}${te}`;case\"**/*.*\":return`(?:${T}${ie(r)}${f})?${O}${te}${c}${p}${te}`;case\"**/.*\":return`(?:${T}${ie(r)}${f})?${c}${p}${te}`;default:{let Ce=/^(.*?)\\.(\\w+)$/.exec(Ae);if(!Ce)return;let Ee=ue(Ce[1]);return Ee?Ee+c+Ce[2]:void 0}}},ae=Kl.removePrefix(e,Y),de=ue(ae);return de&&r.strictSlashes!==!0&&(de+=`${f}?`),de};poe.exports=t4});var doe=G((kQt,goe)=>{\"use strict\";var cKe=Ie(\"path\"),uKe=foe(),r4=hoe(),n4=A2(),fKe=f2(),AKe=e=>e&&typeof e==\"object\"&&!Array.isArray(e),Xi=(e,t,r=!1)=>{if(Array.isArray(e)){let E=e.map(S=>Xi(S,t,r));return S=>{for(let x of E){let I=x(S);if(I)return I}return!1}}let s=AKe(e)&&e.tokens&&e.input;if(e===\"\"||typeof e!=\"string\"&&!s)throw new TypeError(\"Expected pattern to be a non-empty string\");let a=t||{},n=n4.isWindows(t),c=s?Xi.compileRe(e,t):Xi.makeRe(e,t,!1,!0),f=c.state;delete c.state;let p=()=>!1;if(a.ignore){let E={...t,ignore:null,onMatch:null,onResult:null};p=Xi(a.ignore,E,r)}let h=(E,C=!1)=>{let{isMatch:S,match:x,output:I}=Xi.test(E,c,t,{glob:e,posix:n}),T={glob:e,state:f,regex:c,posix:n,input:E,output:I,match:x,isMatch:S};return typeof a.onResult==\"function\"&&a.onResult(T),S===!1?(T.isMatch=!1,C?T:!1):p(E)?(typeof a.onIgnore==\"function\"&&a.onIgnore(T),T.isMatch=!1,C?T:!1):(typeof a.onMatch==\"function\"&&a.onMatch(T),C?T:!0)};return r&&(h.state=f),h};Xi.test=(e,t,r,{glob:s,posix:a}={})=>{if(typeof e!=\"string\")throw new TypeError(\"Expected input to be a string\");if(e===\"\")return{isMatch:!1,output:\"\"};let n=r||{},c=n.format||(a?n4.toPosixSlashes:null),f=e===s,p=f&&c?c(e):e;return f===!1&&(p=c?c(e):e,f=p===s),(f===!1||n.capture===!0)&&(n.matchBase===!0||n.basename===!0?f=Xi.matchBase(e,t,r,a):f=t.exec(p)),{isMatch:!!f,match:f,output:p}};Xi.matchBase=(e,t,r,s=n4.isWindows(r))=>(t instanceof RegExp?t:Xi.makeRe(t,r)).test(cKe.basename(e));Xi.isMatch=(e,t,r)=>Xi(t,r)(e);Xi.parse=(e,t)=>Array.isArray(e)?e.map(r=>Xi.parse(r,t)):r4(e,{...t,fastpaths:!1});Xi.scan=(e,t)=>uKe(e,t);Xi.compileRe=(e,t,r=!1,s=!1)=>{if(r===!0)return e.output;let a=t||{},n=a.contains?\"\":\"^\",c=a.contains?\"\":\"$\",f=`${n}(?:${e.output})${c}`;e&&e.negated===!0&&(f=`^(?!${f}).*$`);let p=Xi.toRegex(f,t);return s===!0&&(p.state=e),p};Xi.makeRe=(e,t={},r=!1,s=!1)=>{if(!e||typeof e!=\"string\")throw new TypeError(\"Expected a non-empty string\");let a={negated:!1,fastpaths:!0};return t.fastpaths!==!1&&(e[0]===\".\"||e[0]===\"*\")&&(a.output=r4.fastpaths(e,t)),a.output||(a=r4(e,t)),Xi.compileRe(a,t,r,s)};Xi.toRegex=(e,t)=>{try{let r=t||{};return new RegExp(e,r.flags||(r.nocase?\"i\":\"\"))}catch(r){if(t&&t.debug===!0)throw r;return/$^/}};Xi.constants=fKe;goe.exports=Xi});var yoe=G((QQt,moe)=>{\"use strict\";moe.exports=doe()});var Jo=G((RQt,woe)=>{\"use strict\";var Ioe=Ie(\"util\"),Coe=Xse(),zf=yoe(),i4=A2(),Eoe=e=>e===\"\"||e===\"./\",xi=(e,t,r)=>{t=[].concat(t),e=[].concat(e);let s=new Set,a=new Set,n=new Set,c=0,f=E=>{n.add(E.output),r&&r.onResult&&r.onResult(E)};for(let E=0;E<t.length;E++){let C=zf(String(t[E]),{...r,onResult:f},!0),S=C.state.negated||C.state.negatedExtglob;S&&c++;for(let x of e){let I=C(x,!0);(S?!I.isMatch:I.isMatch)&&(S?s.add(I.output):(s.delete(I.output),a.add(I.output)))}}let h=(c===t.length?[...n]:[...a]).filter(E=>!s.has(E));if(r&&h.length===0){if(r.failglob===!0)throw new Error(`No matches found for \"${t.join(\", \")}\"`);if(r.nonull===!0||r.nullglob===!0)return r.unescape?t.map(E=>E.replace(/\\\\/g,\"\")):t}return h};xi.match=xi;xi.matcher=(e,t)=>zf(e,t);xi.isMatch=(e,t,r)=>zf(t,r)(e);xi.any=xi.isMatch;xi.not=(e,t,r={})=>{t=[].concat(t).map(String);let s=new Set,a=[],n=f=>{r.onResult&&r.onResult(f),a.push(f.output)},c=new Set(xi(e,t,{...r,onResult:n}));for(let f of a)c.has(f)||s.add(f);return[...s]};xi.contains=(e,t,r)=>{if(typeof e!=\"string\")throw new TypeError(`Expected a string: \"${Ioe.inspect(e)}\"`);if(Array.isArray(t))return t.some(s=>xi.contains(e,s,r));if(typeof t==\"string\"){if(Eoe(e)||Eoe(t))return!1;if(e.includes(t)||e.startsWith(\"./\")&&e.slice(2).includes(t))return!0}return xi.isMatch(e,t,{...r,contains:!0})};xi.matchKeys=(e,t,r)=>{if(!i4.isObject(e))throw new TypeError(\"Expected the first argument to be an object\");let s=xi(Object.keys(e),t,r),a={};for(let n of s)a[n]=e[n];return a};xi.some=(e,t,r)=>{let s=[].concat(e);for(let a of[].concat(t)){let n=zf(String(a),r);if(s.some(c=>n(c)))return!0}return!1};xi.every=(e,t,r)=>{let s=[].concat(e);for(let a of[].concat(t)){let n=zf(String(a),r);if(!s.every(c=>n(c)))return!1}return!0};xi.all=(e,t,r)=>{if(typeof e!=\"string\")throw new TypeError(`Expected a string: \"${Ioe.inspect(e)}\"`);return[].concat(t).every(s=>zf(s,r)(e))};xi.capture=(e,t,r)=>{let s=i4.isWindows(r),n=zf.makeRe(String(e),{...r,capture:!0}).exec(s?i4.toPosixSlashes(t):t);if(n)return n.slice(1).map(c=>c===void 0?\"\":c)};xi.makeRe=(...e)=>zf.makeRe(...e);xi.scan=(...e)=>zf.scan(...e);xi.parse=(e,t)=>{let r=[];for(let s of[].concat(e||[]))for(let a of Coe(String(s),t))r.push(zf.parse(a,t));return r};xi.braces=(e,t)=>{if(typeof e!=\"string\")throw new TypeError(\"Expected a string\");return t&&t.nobrace===!0||!/\\{.*\\}/.test(e)?[e]:Coe(e,t)};xi.braceExpand=(e,t)=>{if(typeof e!=\"string\")throw new TypeError(\"Expected a string\");return xi.braces(e,{...t,expand:!0})};woe.exports=xi});var voe=G((TQt,Boe)=>{\"use strict\";Boe.exports=({onlyFirst:e=!1}={})=>{let t=[\"[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]+)*|[a-zA-Z\\\\d]+(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)\",\"(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))\"].join(\"|\");return new RegExp(t,e?void 0:\"g\")}});var gk=G((FQt,Soe)=>{\"use strict\";var pKe=voe();Soe.exports=e=>typeof e==\"string\"?e.replace(pKe(),\"\"):e});function Doe(e){return Number.isSafeInteger(e)&&e>=0}var boe=Ze(()=>{});function Poe(e){return e!=null&&typeof e!=\"function\"&&Doe(e.length)}var xoe=Ze(()=>{boe()});function Pc(e){return e===\"__proto__\"}var h2=Ze(()=>{});function ME(e){switch(typeof e){case\"number\":case\"symbol\":return!1;case\"string\":return e.includes(\".\")||e.includes(\"[\")||e.includes(\"]\")}}var dk=Ze(()=>{});function UE(e){return typeof e==\"string\"||typeof e==\"symbol\"?e:Object.is(e?.valueOf?.(),-0)?\"-0\":String(e)}var mk=Ze(()=>{});function Ou(e){let t=[],r=e.length;if(r===0)return t;let s=0,a=\"\",n=\"\",c=!1;for(e.charCodeAt(0)===46&&(t.push(\"\"),s++);s<r;){let f=e[s];n?f===\"\\\\\"&&s+1<r?(s++,a+=e[s]):f===n?n=\"\":a+=f:c?f==='\"'||f===\"'\"?n=f:f===\"]\"?(c=!1,t.push(a),a=\"\"):a+=f:f===\"[\"?(c=!0,a&&(t.push(a),a=\"\")):f===\".\"?a&&(t.push(a),a=\"\"):a+=f,s++}return a&&t.push(a),t}var _E=Ze(()=>{});function ba(e,t,r){if(e==null)return r;switch(typeof t){case\"string\":{if(Pc(t))return r;let s=e[t];return s===void 0?ME(t)?ba(e,Ou(t),r):r:s}case\"number\":case\"symbol\":{typeof t==\"number\"&&(t=UE(t));let s=e[t];return s===void 0?r:s}default:{if(Array.isArray(t))return hKe(e,t,r);if(Object.is(t?.valueOf(),-0)?t=\"-0\":t=String(t),Pc(t))return r;let s=e[t];return s===void 0?r:s}}}function hKe(e,t,r){if(t.length===0)return r;let s=e;for(let a=0;a<t.length;a++){if(s==null||Pc(t[a]))return r;s=s[t[a]]}return s===void 0?r:s}var yk=Ze(()=>{h2();dk();mk();_E()});function s4(e){return e!==null&&(typeof e==\"object\"||typeof e==\"function\")}var koe=Ze(()=>{});function HE(e){return e==null||typeof e!=\"object\"&&typeof e!=\"function\"}var Ek=Ze(()=>{});function Ik(e,t){return e===t||Number.isNaN(e)&&Number.isNaN(t)}var o4=Ze(()=>{});function Gd(e){return Object.getOwnPropertySymbols(e).filter(t=>Object.prototype.propertyIsEnumerable.call(e,t))}var Ck=Ze(()=>{});function qd(e){return e==null?e===void 0?\"[object Undefined]\":\"[object Null]\":Object.prototype.toString.call(e)}var wk=Ze(()=>{});var Bk,jE,GE,qE,Wd,vk,Sk,Dk,bk,Pk,Qoe,xk,WE,Roe,kk,Qk,Rk,Tk,Fk,Toe,Nk,Ok,Lk,Foe,Mk,Uk,_k=Ze(()=>{Bk=\"[object RegExp]\",jE=\"[object String]\",GE=\"[object Number]\",qE=\"[object Boolean]\",Wd=\"[object Arguments]\",vk=\"[object Symbol]\",Sk=\"[object Date]\",Dk=\"[object Map]\",bk=\"[object Set]\",Pk=\"[object Array]\",Qoe=\"[object Function]\",xk=\"[object ArrayBuffer]\",WE=\"[object Object]\",Roe=\"[object Error]\",kk=\"[object DataView]\",Qk=\"[object Uint8Array]\",Rk=\"[object Uint8ClampedArray]\",Tk=\"[object Uint16Array]\",Fk=\"[object Uint32Array]\",Toe=\"[object BigUint64Array]\",Nk=\"[object Int8Array]\",Ok=\"[object Int16Array]\",Lk=\"[object Int32Array]\",Foe=\"[object BigInt64Array]\",Mk=\"[object Float32Array]\",Uk=\"[object Float64Array]\"});function VE(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}var Hk=Ze(()=>{});function Noe(e,t){return l0(e,void 0,e,new Map,t)}function l0(e,t,r,s=new Map,a=void 0){let n=a?.(e,t,r,s);if(n!=null)return n;if(HE(e))return e;if(s.has(e))return s.get(e);if(Array.isArray(e)){let c=new Array(e.length);s.set(e,c);for(let f=0;f<e.length;f++)c[f]=l0(e[f],f,r,s,a);return Object.hasOwn(e,\"index\")&&(c.index=e.index),Object.hasOwn(e,\"input\")&&(c.input=e.input),c}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp){let c=new RegExp(e.source,e.flags);return c.lastIndex=e.lastIndex,c}if(e instanceof Map){let c=new Map;s.set(e,c);for(let[f,p]of e)c.set(f,l0(p,f,r,s,a));return c}if(e instanceof Set){let c=new Set;s.set(e,c);for(let f of e)c.add(l0(f,void 0,r,s,a));return c}if(typeof Buffer<\"u\"&&Buffer.isBuffer(e))return e.subarray();if(VE(e)){let c=new(Object.getPrototypeOf(e)).constructor(e.length);s.set(e,c);for(let f=0;f<e.length;f++)c[f]=l0(e[f],f,r,s,a);return c}if(e instanceof ArrayBuffer||typeof SharedArrayBuffer<\"u\"&&e instanceof SharedArrayBuffer)return e.slice(0);if(e instanceof DataView){let c=new DataView(e.buffer.slice(0),e.byteOffset,e.byteLength);return s.set(e,c),a0(c,e,r,s,a),c}if(typeof File<\"u\"&&e instanceof File){let c=new File([e],e.name,{type:e.type});return s.set(e,c),a0(c,e,r,s,a),c}if(e instanceof Blob){let c=new Blob([e],{type:e.type});return s.set(e,c),a0(c,e,r,s,a),c}if(e instanceof Error){let c=new e.constructor;return s.set(e,c),c.message=e.message,c.name=e.name,c.stack=e.stack,c.cause=e.cause,a0(c,e,r,s,a),c}if(typeof e==\"object\"&&gKe(e)){let c=Object.create(Object.getPrototypeOf(e));return s.set(e,c),a0(c,e,r,s,a),c}return e}function a0(e,t,r=e,s,a){let n=[...Object.keys(t),...Gd(t)];for(let c=0;c<n.length;c++){let f=n[c],p=Object.getOwnPropertyDescriptor(e,f);(p==null||p.writable)&&(e[f]=l0(t[f],f,r,s,a))}}function gKe(e){switch(qd(e)){case Wd:case Pk:case xk:case kk:case qE:case Sk:case Mk:case Uk:case Nk:case Ok:case Lk:case Dk:case GE:case WE:case Bk:case bk:case jE:case vk:case Qk:case Rk:case Tk:case Fk:return!0;default:return!1}}var a4=Ze(()=>{Ck();wk();_k();Ek();Hk()});function Ooe(e){return l0(e,void 0,e,new Map,void 0)}var Loe=Ze(()=>{a4()});function Moe(e,t){return Noe(e,(r,s,a,n)=>{let c=t?.(r,s,a,n);if(c!=null)return c;if(typeof e==\"object\")switch(Object.prototype.toString.call(e)){case GE:case jE:case qE:{let f=new e.constructor(e?.valueOf());return a0(f,e),f}case Wd:{let f={};return a0(f,e),f.length=e.length,f[Symbol.iterator]=e[Symbol.iterator],f}default:return}})}var Uoe=Ze(()=>{a4();_k()});function c0(e){return Moe(e)}var l4=Ze(()=>{Uoe()});function jk(e,t=Number.MAX_SAFE_INTEGER){switch(typeof e){case\"number\":return Number.isInteger(e)&&e>=0&&e<t;case\"symbol\":return!1;case\"string\":return dKe.test(e)}}var dKe,c4=Ze(()=>{dKe=/^(?:0|[1-9]\\d*)$/});function g2(e){return e!==null&&typeof e==\"object\"&&qd(e)===\"[object Arguments]\"}var u4=Ze(()=>{wk()});function d2(e,t){let r;if(Array.isArray(t)?r=t:typeof t==\"string\"&&ME(t)&&e?.[t]==null?r=Ou(t):r=[t],r.length===0)return!1;let s=e;for(let a=0;a<r.length;a++){let n=r[a];if((s==null||!Object.hasOwn(s,n))&&!((Array.isArray(s)||g2(s))&&jk(n)&&n<s.length))return!1;s=s[n]}return!0}var f4=Ze(()=>{dk();c4();u4();_E()});function A4(e){return typeof e==\"object\"&&e!==null}var _oe=Ze(()=>{});function Hoe(e){return typeof e==\"symbol\"||e instanceof Symbol}var joe=Ze(()=>{});function Goe(e,t){return Array.isArray(e)?!1:typeof e==\"number\"||typeof e==\"boolean\"||e==null||Hoe(e)?!0:typeof e==\"string\"&&(yKe.test(e)||!mKe.test(e))||t!=null&&Object.hasOwn(t,e)}var mKe,yKe,qoe=Ze(()=>{joe();mKe=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,yKe=/^\\w*$/});function u0(e,t){if(e==null)return!0;switch(typeof t){case\"symbol\":case\"number\":case\"object\":{if(Array.isArray(t))return Woe(e,t);if(typeof t==\"number\"?t=UE(t):typeof t==\"object\"&&(Object.is(t?.valueOf(),-0)?t=\"-0\":t=String(t)),Pc(t))return!1;if(e?.[t]===void 0)return!0;try{return delete e[t],!0}catch{return!1}}case\"string\":{if(e?.[t]===void 0&&ME(t))return Woe(e,Ou(t));if(Pc(t))return!1;try{return delete e[t],!0}catch{return!1}}}}function Woe(e,t){let r=ba(e,t.slice(0,-1),e),s=t[t.length-1];if(r?.[s]===void 0)return!0;if(Pc(s))return!1;try{return delete r[s],!0}catch{return!1}}var p4=Ze(()=>{yk();h2();dk();mk();_E()});function Voe(e){return e==null}var Yoe=Ze(()=>{});var Koe,Joe=Ze(()=>{o4();Koe=(e,t,r)=>{let s=e[t];(!(Object.hasOwn(e,t)&&Ik(s,r))||r===void 0&&!(t in e))&&(e[t]=r)}});function zoe(e,t,r,s){if(e==null&&!s4(e))return e;let a=Goe(t,e)?[t]:Array.isArray(t)?t:typeof t==\"string\"?Ou(t):[t],n=e;for(let c=0;c<a.length&&n!=null;c++){let f=UE(a[c]);if(Pc(f))continue;let p;if(c===a.length-1)p=r(n[f]);else{let h=n[f],E=s?.(h,f,e);p=E!==void 0?E:s4(h)?h:jk(a[c+1])?[]:{}}Koe(n,f,p),n=n[f]}return e}var Zoe=Ze(()=>{h2();Joe();c4();qoe();mk();koe();_E()});function Vd(e,t,r){return zoe(e,t,()=>r,()=>{})}var h4=Ze(()=>{Zoe()});function Xoe(e,t=0,r={}){typeof r!=\"object\"&&(r={});let s=null,a=null,n=null,c=0,f=null,p,{leading:h=!1,trailing:E=!0,maxWait:C}=r,S=\"maxWait\"in r,x=S?Math.max(Number(C)||0,t):0,I=ue=>(s!==null&&(p=e.apply(a,s)),s=a=null,c=ue,p),T=ue=>(c=ue,f=setTimeout(te,t),h&&s!==null?I(ue):p),O=ue=>(f=null,E&&s!==null?I(ue):p),U=ue=>{if(n===null)return!0;let ae=ue-n,de=ae>=t||ae<0,Ae=S&&ue-c>=x;return de||Ae},Y=ue=>{let ae=n===null?0:ue-n,de=t-ae,Ae=x-(ue-c);return S?Math.min(de,Ae):de},te=()=>{let ue=Date.now();if(U(ue))return O(ue);f=setTimeout(te,Y(ue))},ie=function(...ue){let ae=Date.now(),de=U(ae);if(s=ue,a=this,n=ae,de){if(f===null)return T(ae);if(S)return clearTimeout(f),f=setTimeout(te,t),I(ae)}return f===null&&(f=setTimeout(te,t)),p};return ie.cancel=()=>{f!==null&&clearTimeout(f),c=0,n=s=a=f=null},ie.flush=()=>f===null?p:O(Date.now()),ie}var $oe=Ze(()=>{});function g4(e,t=0,r={}){let{leading:s=!0,trailing:a=!0}=r;return Xoe(e,t,{leading:s,maxWait:t,trailing:a})}var eae=Ze(()=>{$oe()});function d4(e){if(e==null)return\"\";if(typeof e==\"string\")return e;if(Array.isArray(e))return e.map(d4).join(\",\");let t=String(e);return t===\"0\"&&Object.is(Number(e),-0)?\"-0\":t}var tae=Ze(()=>{});function m4(e){if(!e||typeof e!=\"object\")return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype||Object.getPrototypeOf(t)===null?Object.prototype.toString.call(e)===\"[object Object]\":!1}var rae=Ze(()=>{});function nae(e,t,r){return m2(e,t,void 0,void 0,void 0,void 0,r)}function m2(e,t,r,s,a,n,c){let f=c(e,t,r,s,a,n);if(f!==void 0)return f;if(typeof e==typeof t)switch(typeof e){case\"bigint\":case\"string\":case\"boolean\":case\"symbol\":case\"undefined\":return e===t;case\"number\":return e===t||Object.is(e,t);case\"function\":return e===t;case\"object\":return y2(e,t,n,c)}return y2(e,t,n,c)}function y2(e,t,r,s){if(Object.is(e,t))return!0;let a=qd(e),n=qd(t);if(a===Wd&&(a=WE),n===Wd&&(n=WE),a!==n)return!1;switch(a){case jE:return e.toString()===t.toString();case GE:{let p=e.valueOf(),h=t.valueOf();return Ik(p,h)}case qE:case Sk:case vk:return Object.is(e.valueOf(),t.valueOf());case Bk:return e.source===t.source&&e.flags===t.flags;case Qoe:return e===t}r=r??new Map;let c=r.get(e),f=r.get(t);if(c!=null&&f!=null)return c===t;r.set(e,t),r.set(t,e);try{switch(a){case Dk:{if(e.size!==t.size)return!1;for(let[p,h]of e.entries())if(!t.has(p)||!m2(h,t.get(p),p,e,t,r,s))return!1;return!0}case bk:{if(e.size!==t.size)return!1;let p=Array.from(e.values()),h=Array.from(t.values());for(let E=0;E<p.length;E++){let C=p[E],S=h.findIndex(x=>m2(C,x,void 0,e,t,r,s));if(S===-1)return!1;h.splice(S,1)}return!0}case Pk:case Qk:case Rk:case Tk:case Fk:case Toe:case Nk:case Ok:case Lk:case Foe:case Mk:case Uk:{if(typeof Buffer<\"u\"&&Buffer.isBuffer(e)!==Buffer.isBuffer(t)||e.length!==t.length)return!1;for(let p=0;p<e.length;p++)if(!m2(e[p],t[p],p,e,t,r,s))return!1;return!0}case xk:return e.byteLength!==t.byteLength?!1:y2(new Uint8Array(e),new Uint8Array(t),r,s);case kk:return e.byteLength!==t.byteLength||e.byteOffset!==t.byteOffset?!1:y2(new Uint8Array(e),new Uint8Array(t),r,s);case Roe:return e.name===t.name&&e.message===t.message;case WE:{if(!(y2(e.constructor,t.constructor,r,s)||m4(e)&&m4(t)))return!1;let h=[...Object.keys(e),...Gd(e)],E=[...Object.keys(t),...Gd(t)];if(h.length!==E.length)return!1;for(let C=0;C<h.length;C++){let S=h[C],x=e[S];if(!Object.hasOwn(t,S))return!1;let I=t[S];if(!m2(x,I,S,e,t,r,s))return!1}return!0}default:return!1}}finally{r.delete(e),r.delete(t)}}var iae=Ze(()=>{rae();Ck();wk();_k();o4()});function sae(){}var oae=Ze(()=>{});function y4(e,t){return nae(e,t,sae)}var aae=Ze(()=>{iae();oae()});function lae(e){return VE(e)}var cae=Ze(()=>{Hk()});function uae(e){if(typeof e!=\"object\"||e==null)return!1;if(Object.getPrototypeOf(e)===null)return!0;if(Object.prototype.toString.call(e)!==\"[object Object]\"){let r=e[Symbol.toStringTag];return r==null||!Object.getOwnPropertyDescriptor(e,Symbol.toStringTag)?.writable?!1:e.toString()===`[object ${r}]`}let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}var fae=Ze(()=>{});function Aae(e){if(HE(e))return e;if(Array.isArray(e)||VE(e)||e instanceof ArrayBuffer||typeof SharedArrayBuffer<\"u\"&&e instanceof SharedArrayBuffer)return e.slice(0);let t=Object.getPrototypeOf(e),r=t.constructor;if(e instanceof Date||e instanceof Map||e instanceof Set)return new r(e);if(e instanceof RegExp){let s=new r(e);return s.lastIndex=e.lastIndex,s}if(e instanceof DataView)return new r(e.buffer.slice(0));if(e instanceof Error){let s=new r(e.message);return s.stack=e.stack,s.name=e.name,s.cause=e.cause,s}if(typeof File<\"u\"&&e instanceof File)return new r([e],e.name,{type:e.type,lastModified:e.lastModified});if(typeof e==\"object\"){let s=Object.create(t);return Object.assign(s,e)}return e}var pae=Ze(()=>{Ek();Hk()});function E4(e,...t){let r=t.slice(0,-1),s=t[t.length-1],a=e;for(let n=0;n<r.length;n++){let c=r[n];a=Gk(a,c,s,new Map)}return a}function Gk(e,t,r,s){if(HE(e)&&(e=Object(e)),t==null||typeof t!=\"object\")return e;if(s.has(t))return Aae(s.get(t));if(s.set(t,e),Array.isArray(t)){t=t.slice();for(let n=0;n<t.length;n++)t[n]=t[n]??void 0}let a=[...Object.keys(t),...Gd(t)];for(let n=0;n<a.length;n++){let c=a[n];if(Pc(c))continue;let f=t[c],p=e[c];if(g2(f)&&(f={...f}),g2(p)&&(p={...p}),typeof Buffer<\"u\"&&Buffer.isBuffer(f)&&(f=c0(f)),Array.isArray(f))if(typeof p==\"object\"&&p!=null){let E=[],C=Reflect.ownKeys(p);for(let S=0;S<C.length;S++){let x=C[S];E[x]=p[x]}p=E}else p=[];let h=r(p,f,c,e,t,s);h!=null?e[c]=h:Array.isArray(f)||A4(p)&&A4(f)?e[c]=Gk(p,f,r,s):p==null&&uae(f)?e[c]=Gk({},f,r,s):p==null&&lae(f)?e[c]=c0(f):(p===void 0||f!==void 0)&&(e[c]=f)}return e}var hae=Ze(()=>{l4();h2();pae();Ek();Ck();u4();_oe();fae();cae()});function I4(e,...t){if(e==null)return{};let r=Ooe(e);for(let s=0;s<t.length;s++){let a=t[s];switch(typeof a){case\"object\":{Array.isArray(a)||(a=Array.from(a));for(let n=0;n<a.length;n++){let c=a[n];u0(r,c)}break}case\"string\":case\"symbol\":case\"number\":{u0(r,a);break}}}return r}var gae=Ze(()=>{p4();Loe()});function Yd(e,...t){if(Voe(e))return{};let r={};for(let s=0;s<t.length;s++){let a=t[s];switch(typeof a){case\"object\":{Array.isArray(a)||(Poe(a)?a=Array.from(a):a=[a]);break}case\"string\":case\"symbol\":case\"number\":{a=[a];break}}for(let n of a){let c=ba(e,n);c===void 0&&!d2(e,n)||(typeof n==\"string\"&&Object.hasOwn(e,n)?r[n]=c:Vd(r,n,c))}}return r}var dae=Ze(()=>{yk();f4();h4();xoe();Yoe()});function mae(e){return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()}var yae=Ze(()=>{});function E2(e){return mae(d4(e))}var Eae=Ze(()=>{yae();tae()});var Jl=Ze(()=>{eae();aae();l4();yk();f4();hae();gae();dae();h4();p4();Eae();_E()});var Ge={};Yt(Ge,{AsyncActions:()=>B4,BufferStream:()=>w4,CachingStrategy:()=>xae,DefaultStream:()=>v4,allSettledSafe:()=>Lu,assertNever:()=>b4,bufferStream:()=>KE,buildIgnorePattern:()=>SKe,convertMapsToIndexableObjects:()=>Wk,dynamicRequire:()=>xp,escapeRegExp:()=>IKe,getArrayWithDefault:()=>C2,getFactoryWithDefault:()=>Zl,getMapWithDefault:()=>P4,getSetWithDefault:()=>Pp,groupBy:()=>PKe,isIndexableObject:()=>C4,isPathLike:()=>DKe,isTaggedYarnVersion:()=>EKe,makeDeferred:()=>Dae,mapAndFilter:()=>zl,mapAndFind:()=>f0,mergeIntoTarget:()=>Qae,overrideType:()=>CKe,parseBoolean:()=>w2,parseDuration:()=>Yk,parseInt:()=>JE,parseOptionalBoolean:()=>kae,plural:()=>qk,prettifyAsyncErrors:()=>YE,prettifySyncErrors:()=>x4,releaseAfterUseAsync:()=>BKe,replaceEnvVariables:()=>Vk,sortMap:()=>Ys,toMerged:()=>bKe,tryParseOptionalBoolean:()=>k4,validateEnum:()=>wKe});function EKe(e){return!!(Bae.default.valid(e)&&e.match(/^[^-]+(-rc\\.[0-9]+)?$/))}function qk(e,{one:t,more:r,zero:s=r}){return e===0?s:e===1?t:r}function IKe(e){return e.replace(/[.*+?^${}()|[\\]\\\\]/g,\"\\\\$&\")}function CKe(e){}function b4(e){throw new Error(`Assertion failed: Unexpected object '${e}'`)}function wKe(e,t){let r=Object.values(e);if(!r.includes(t))throw new st(`Invalid value for enumeration: ${JSON.stringify(t)} (expected one of ${r.map(s=>JSON.stringify(s)).join(\", \")})`);return t}function zl(e,t){let r=[];for(let s of e){let a=t(s);a!==vae&&r.push(a)}return r}function f0(e,t){for(let r of e){let s=t(r);if(s!==Sae)return s}}function C4(e){return typeof e==\"object\"&&e!==null}async function Lu(e){let t=await Promise.allSettled(e),r=[];for(let s of t){if(s.status===\"rejected\")throw s.reason;r.push(s.value)}return r}function Wk(e){if(e instanceof Map&&(e=Object.fromEntries(e)),C4(e))for(let t of Object.keys(e)){let r=e[t];C4(r)&&(e[t]=Wk(r))}return e}function Zl(e,t,r){let s=e.get(t);return typeof s>\"u\"&&e.set(t,s=r()),s}function C2(e,t){let r=e.get(t);return typeof r>\"u\"&&e.set(t,r=[]),r}function Pp(e,t){let r=e.get(t);return typeof r>\"u\"&&e.set(t,r=new Set),r}function P4(e,t){let r=e.get(t);return typeof r>\"u\"&&e.set(t,r=new Map),r}async function BKe(e,t){if(t==null)return await e();try{return await e()}finally{await t()}}async function YE(e,t){try{return await e()}catch(r){throw r.message=t(r.message),r}}function x4(e,t){try{return e()}catch(r){throw r.message=t(r.message),r}}async function KE(e){return await new Promise((t,r)=>{let s=[];e.on(\"error\",a=>{r(a)}),e.on(\"data\",a=>{s.push(a)}),e.on(\"end\",()=>{t(Buffer.concat(s))})})}function Dae(){let e,t;return{promise:new Promise((s,a)=>{e=s,t=a}),resolve:e,reject:t}}function bae(e){return I2(fe.fromPortablePath(e))}function Pae(path){let physicalPath=fe.fromPortablePath(path),currentCacheEntry=I2.cache[physicalPath];delete I2.cache[physicalPath];let result;try{result=bae(physicalPath);let freshCacheEntry=I2.cache[physicalPath],dynamicModule=eval(\"module\"),freshCacheIndex=dynamicModule.children.indexOf(freshCacheEntry);freshCacheIndex!==-1&&dynamicModule.children.splice(freshCacheIndex,1)}finally{I2.cache[physicalPath]=currentCacheEntry}return result}function vKe(e){let t=Iae.get(e),r=le.statSync(e);if(t?.mtime===r.mtimeMs)return t.instance;let s=Pae(e);return Iae.set(e,{mtime:r.mtimeMs,instance:s}),s}function xp(e,{cachingStrategy:t=2}={}){switch(t){case 0:return Pae(e);case 1:return vKe(e);case 2:return bae(e);default:throw new Error(\"Unsupported caching strategy\")}}function Ys(e,t){let r=Array.from(e);Array.isArray(t)||(t=[t]);let s=[];for(let n of t)s.push(r.map(c=>n(c)));let a=r.map((n,c)=>c);return a.sort((n,c)=>{for(let f of s){let p=f[n]<f[c]?-1:f[n]>f[c]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function SKe(e){return e.length===0?null:e.map(t=>`(${Cae.default.makeRe(t,{windows:!1,dot:!0}).source})`).join(\"|\")}function Vk(e,{env:t}){let r=\"\",s=0,a=0,n=e.matchAll(/\\\\(?<escaped>[\\\\$}])|\\$\\{(?<variable>[a-zA-Z]\\w*)(?<operator>:-|-|(?=\\}))|(?<unknown>\\$\\{)|\\}/g),c=()=>{let f=a;for(let{0:p,index:h,groups:{variable:E}={}}of n)if(E)a++;else if(p===\"}\"&&--a<f)return h+p.length;return e.length};for(let{0:f,index:p,groups:{escaped:h,variable:E,operator:C,unknown:S}={}}of n)if(r+=e.slice(s,p),s=p+f.length,h)r+=h;else if(E){let x=t[E];if(a++,C===\"\"&&x!==void 0||C===\":-\"&&x!==void 0&&x!==\"\"||C===\"-\"&&x!==void 0)r+=x,s=c();else if(C===\"\")throw new st(`Environment variable not found (${E})`)}else if(f===\"}\")a===0?r+=f:a--;else if(S)throw new st(`Invalid environment variable substitution syntax: ${e}`);if(a>0)throw new st(`Incomplete variable substitution in input: ${e}`);return r+e.slice(s)}function w2(e){switch(e){case\"true\":case\"1\":case 1:case!0:return!0;case\"false\":case\"0\":case 0:case!1:return!1;default:throw new Error(`Couldn't parse \"${e}\" as a boolean`)}}function kae(e){return typeof e>\"u\"?e:w2(e)}function k4(e){try{return kae(e)}catch{return null}}function DKe(e){return!!(fe.isAbsolute(e)||e.match(/^(\\.{1,2}|~)\\//))}function Qae(e,...t){let r=c=>({value:c}),s=r(e),a=t.map(c=>r(c)),{value:n}=E4(s,...a,(c,f)=>{if(Array.isArray(c)&&Array.isArray(f)){for(let p of f)c.find(h=>y4(h,p))||c.push(p);return c}});return n}function bKe(...e){return Qae({},...e)}function PKe(e,t){let r=Object.create(null);for(let s of e){let a=s[t];r[a]??=[],r[a].push(s)}return r}function JE(e){return typeof e==\"string\"?Number.parseInt(e,10):e}function Yk(e,t){let r=xKe.exec(e)?.groups;if(!r)throw new Error(`Couldn't parse \"${e}\" as a duration`);if(r.unit===void 0)return parseFloat(r.num);let s=S4[r.unit];if(!s)throw new Error(`Invalid duration unit \"${r.unit}\"`);return parseFloat(r.num)*s/S4[t]}var Cae,wae,Bae,D4,vae,Sae,w4,B4,v4,I2,Iae,xae,S4,xKe,xc=Ze(()=>{Dt();Vt();Jl();Cae=et(Jo()),wae=et(Nd()),Bae=et(pi()),D4=Ie(\"stream\");vae=Symbol();zl.skip=vae;Sae=Symbol();f0.skip=Sae;w4=class extends D4.Transform{constructor(){super(...arguments);this.chunks=[]}_transform(r,s,a){if(s!==\"buffer\"||!Buffer.isBuffer(r))throw new Error(\"Assertion failed: BufferStream only accept buffers\");this.chunks.push(r),a(null,null)}_flush(r){r(null,Buffer.concat(this.chunks))}};B4=class{constructor(t){this.deferred=new Map;this.promises=new Map;this.limit=(0,wae.default)(t)}set(t,r){let s=this.deferred.get(t);typeof s>\"u\"&&this.deferred.set(t,s=Dae());let a=this.limit(()=>r());return this.promises.set(t,a),a.then(()=>{this.promises.get(t)===a&&s.resolve()},n=>{this.promises.get(t)===a&&s.reject(n)}),s.promise}reduce(t,r){let s=this.promises.get(t)??Promise.resolve();this.set(t,()=>r(s))}async wait(){await Promise.all(this.promises.values())}},v4=class extends D4.Transform{constructor(r=Buffer.alloc(0)){super();this.active=!0;this.ifEmpty=r}_transform(r,s,a){if(s!==\"buffer\"||!Buffer.isBuffer(r))throw new Error(\"Assertion failed: DefaultStream only accept buffers\");this.active=!1,a(null,r)}_flush(r){this.active&&this.ifEmpty.length>0?r(null,this.ifEmpty):r(null)}},I2=eval(\"require\");Iae=new Map;xae=(s=>(s[s.NoCache=0]=\"NoCache\",s[s.FsTime=1]=\"FsTime\",s[s.Node=2]=\"Node\",s))(xae||{});S4={ms:1,s:1e3,m:60*1e3,h:60*60*1e3,d:24*60*60*1e3,w:7*24*60*60*1e3},xKe=new RegExp(`^(?<num>\\\\d*\\\\.?\\\\d+)(?<unit>${Object.keys(S4).join(\"|\")})?$`)});var zE,Q4,R4,Rae=Ze(()=>{zE=(r=>(r.HARD=\"HARD\",r.SOFT=\"SOFT\",r))(zE||{}),Q4=(s=>(s.Dependency=\"Dependency\",s.PeerDependency=\"PeerDependency\",s.PeerDependencyMeta=\"PeerDependencyMeta\",s))(Q4||{}),R4=(s=>(s.Inactive=\"inactive\",s.Redundant=\"redundant\",s.Active=\"active\",s))(R4||{})});var pe={};Yt(pe,{LogLevel:()=>$k,Style:()=>zk,Type:()=>gt,addLogFilterSupport:()=>S2,applyColor:()=>si,applyHyperlink:()=>XE,applyStyle:()=>Kd,json:()=>Jd,jsonOrPretty:()=>RKe,mark:()=>L4,pretty:()=>jt,prettyField:()=>Zf,prettyList:()=>O4,prettyTruncatedLocatorList:()=>Xk,stripAnsi:()=>ZE.default,supportsColor:()=>Zk,supportsHyperlinks:()=>N4,tuple:()=>Mu});function Tae(e){let t=[\"KiB\",\"MiB\",\"GiB\",\"TiB\"],r=t.length;for(;r>1&&e<1024**r;)r-=1;let s=1024**r;return`${Math.floor(e*100/s)/100} ${t[r-1]}`}function Kk(e,t){if(Array.isArray(t))return t.length===0?si(e,\"[]\",gt.CODE):si(e,\"[ \",gt.CODE)+t.map(r=>Kk(e,r)).join(\", \")+si(e,\" ]\",gt.CODE);if(typeof t==\"string\")return si(e,JSON.stringify(t),gt.STRING);if(typeof t==\"number\")return si(e,JSON.stringify(t),gt.NUMBER);if(typeof t==\"boolean\")return si(e,JSON.stringify(t),gt.BOOLEAN);if(t===null)return si(e,\"null\",gt.NULL);if(typeof t==\"object\"&&Object.getPrototypeOf(t)===Object.prototype){let r=Object.entries(t);return r.length===0?si(e,\"{}\",gt.CODE):si(e,\"{ \",gt.CODE)+r.map(([s,a])=>`${Kk(e,s)}: ${Kk(e,a)}`).join(\", \")+si(e,\" }\",gt.CODE)}if(typeof t>\"u\")return si(e,\"undefined\",gt.NULL);throw new Error(\"Assertion failed: The value doesn't seem to be a valid JSON object\")}function Mu(e,t){return[t,e]}function Kd(e,t,r){return e.get(\"enableColors\")&&r&2&&(t=v2.default.bold(t)),t}function si(e,t,r){if(!e.get(\"enableColors\"))return t;let s=kKe.get(r);if(s===null)return t;let a=typeof s>\"u\"?r:F4.level>=3?s[0]:s[1],n=typeof a==\"number\"?T4.ansi256(a):a.startsWith(\"#\")?T4.hex(a):T4[a];if(typeof n!=\"function\")throw new Error(`Invalid format type ${a}`);return n(t)}function XE(e,t,r){return e.get(\"enableHyperlinks\")?QKe?`\\x1B]8;;${r}\\x1B\\\\${t}\\x1B]8;;\\x1B\\\\`:`\\x1B]8;;${r}\\x07${t}\\x1B]8;;\\x07`:t}function jt(e,t,r){if(t===null)return si(e,\"null\",gt.NULL);if(Object.hasOwn(Jk,r))return Jk[r].pretty(e,t);if(typeof t!=\"string\")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof t}`);return si(e,t,r)}function O4(e,t,r,{separator:s=\", \"}={}){return[...t].map(a=>jt(e,a,r)).join(s)}function Jd(e,t){if(e===null)return null;if(Object.hasOwn(Jk,t))return Jk[t].json(e);if(typeof e!=\"string\")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof e}`);return e}function RKe(e,t,[r,s]){return e?Jd(r,s):jt(t,r,s)}function L4(e){return{Check:si(e,\"\\u2713\",\"green\"),Cross:si(e,\"\\u2718\",\"red\"),Question:si(e,\"?\",\"cyan\")}}function Zf(e,{label:t,value:[r,s]}){return`${jt(e,t,gt.CODE)}: ${jt(e,r,s)}`}function Xk(e,t,r){let s=[],a=[...t],n=r;for(;a.length>0;){let h=a[0],E=`${Vr(e,h)}, `,C=M4(h).length+2;if(s.length>0&&n<C)break;s.push([E,C]),n-=C,a.shift()}if(a.length===0)return s.map(([h])=>h).join(\"\").slice(0,-2);let c=\"X\".repeat(a.length.toString().length),f=`and ${c} more.`,p=a.length;for(;s.length>1&&n<f.length;)n+=s[s.length-1][1],p+=1,s.pop();return[s.map(([h])=>h).join(\"\"),f.replace(c,jt(e,p,gt.NUMBER))].join(\"\")}function S2(e,{configuration:t}){let r=t.get(\"logFilters\"),s=new Map,a=new Map,n=[];for(let C of r){let S=C.get(\"level\");if(typeof S>\"u\")continue;let x=C.get(\"code\");typeof x<\"u\"&&s.set(x,S);let I=C.get(\"text\");typeof I<\"u\"&&a.set(I,S);let T=C.get(\"pattern\");typeof T<\"u\"&&n.push([Fae.default.matcher(T,{contains:!0}),S])}n.reverse();let c=(C,S,x)=>{if(C===null||C===0)return x;let I=a.size>0||n.length>0?(0,ZE.default)(S):S;if(a.size>0){let T=a.get(I);if(typeof T<\"u\")return T??x}if(n.length>0){for(let[T,O]of n)if(T(I))return O??x}if(s.size>0){let T=s.get(Kf(C));if(typeof T<\"u\")return T??x}return x},f=e.reportInfo,p=e.reportWarning,h=e.reportError,E=function(C,S,x,I){switch(c(S,x,I)){case\"info\":f.call(C,S,x);break;case\"warning\":p.call(C,S??0,x);break;case\"error\":h.call(C,S??0,x);break}};e.reportInfo=function(...C){return E(this,...C,\"info\")},e.reportWarning=function(...C){return E(this,...C,\"warning\")},e.reportError=function(...C){return E(this,...C,\"error\")}}var v2,B2,Fae,ZE,gt,zk,F4,Zk,N4,T4,kKe,zo,Jk,QKe,$k,kc=Ze(()=>{Dt();v2=et(NE()),B2=et(Rd());Vt();Fae=et(Jo()),ZE=et(gk());Gx();Zo();gt={NO_HINT:\"NO_HINT\",ID:\"ID\",NULL:\"NULL\",SCOPE:\"SCOPE\",NAME:\"NAME\",RANGE:\"RANGE\",REFERENCE:\"REFERENCE\",NUMBER:\"NUMBER\",STRING:\"STRING\",BOOLEAN:\"BOOLEAN\",PATH:\"PATH\",URL:\"URL\",ADDED:\"ADDED\",REMOVED:\"REMOVED\",CODE:\"CODE\",INSPECT:\"INSPECT\",DURATION:\"DURATION\",SIZE:\"SIZE\",SIZE_DIFF:\"SIZE_DIFF\",IDENT:\"IDENT\",DESCRIPTOR:\"DESCRIPTOR\",LOCATOR:\"LOCATOR\",RESOLUTION:\"RESOLUTION\",DEPENDENT:\"DEPENDENT\",PACKAGE_EXTENSION:\"PACKAGE_EXTENSION\",SETTING:\"SETTING\",MARKDOWN:\"MARKDOWN\",MARKDOWN_INLINE:\"MARKDOWN_INLINE\"},zk=(t=>(t[t.BOLD=2]=\"BOLD\",t))(zk||{}),F4=B2.default.GITHUB_ACTIONS?{level:2}:v2.default.supportsColor?{level:v2.default.supportsColor.level}:{level:0},Zk=F4.level!==0,N4=Zk&&!B2.default.GITHUB_ACTIONS&&!B2.default.CIRCLE&&!B2.default.GITLAB,T4=new v2.default.Instance(F4),kKe=new Map([[gt.NO_HINT,null],[gt.NULL,[\"#a853b5\",129]],[gt.SCOPE,[\"#d75f00\",166]],[gt.NAME,[\"#d7875f\",173]],[gt.RANGE,[\"#00afaf\",37]],[gt.REFERENCE,[\"#87afff\",111]],[gt.NUMBER,[\"#ffd700\",220]],[gt.STRING,[\"#b4bd68\",32]],[gt.BOOLEAN,[\"#faa023\",209]],[gt.PATH,[\"#d75fd7\",170]],[gt.URL,[\"#d75fd7\",170]],[gt.ADDED,[\"#5faf00\",70]],[gt.REMOVED,[\"#ff3131\",160]],[gt.CODE,[\"#87afff\",111]],[gt.SIZE,[\"#ffd700\",220]]]),zo=e=>e;Jk={[gt.ID]:zo({pretty:(e,t)=>typeof t==\"number\"?si(e,`${t}`,gt.NUMBER):si(e,t,gt.CODE),json:e=>e}),[gt.INSPECT]:zo({pretty:(e,t)=>Kk(e,t),json:e=>e}),[gt.NUMBER]:zo({pretty:(e,t)=>si(e,`${t}`,gt.NUMBER),json:e=>e}),[gt.IDENT]:zo({pretty:(e,t)=>$i(e,t),json:e=>fn(e)}),[gt.LOCATOR]:zo({pretty:(e,t)=>Vr(e,t),json:e=>gl(e)}),[gt.DESCRIPTOR]:zo({pretty:(e,t)=>oi(e,t),json:e=>hl(e)}),[gt.RESOLUTION]:zo({pretty:(e,{descriptor:t,locator:r})=>D2(e,t,r),json:({descriptor:e,locator:t})=>({descriptor:hl(e),locator:t!==null?gl(t):null})}),[gt.DEPENDENT]:zo({pretty:(e,{locator:t,descriptor:r})=>U4(e,t,r),json:({locator:e,descriptor:t})=>({locator:gl(e),descriptor:hl(t)})}),[gt.PACKAGE_EXTENSION]:zo({pretty:(e,t)=>{switch(t.type){case\"Dependency\":return`${$i(e,t.parentDescriptor)} \\u27A4 ${si(e,\"dependencies\",gt.CODE)} \\u27A4 ${$i(e,t.descriptor)}`;case\"PeerDependency\":return`${$i(e,t.parentDescriptor)} \\u27A4 ${si(e,\"peerDependencies\",gt.CODE)} \\u27A4 ${$i(e,t.descriptor)}`;case\"PeerDependencyMeta\":return`${$i(e,t.parentDescriptor)} \\u27A4 ${si(e,\"peerDependenciesMeta\",gt.CODE)} \\u27A4 ${$i(e,Pa(t.selector))} \\u27A4 ${si(e,t.key,gt.CODE)}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${t.type}`)}},json:e=>{switch(e.type){case\"Dependency\":return`${fn(e.parentDescriptor)} > ${fn(e.descriptor)}`;case\"PeerDependency\":return`${fn(e.parentDescriptor)} >> ${fn(e.descriptor)}`;case\"PeerDependencyMeta\":return`${fn(e.parentDescriptor)} >> ${e.selector} / ${e.key}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${e.type}`)}}}),[gt.SETTING]:zo({pretty:(e,t)=>(e.get(t),XE(e,si(e,t,gt.CODE),`https://yarnpkg.com/configuration/yarnrc#${t}`)),json:e=>e}),[gt.DURATION]:zo({pretty:(e,t)=>{if(t>1e3*60){let r=Math.floor(t/1e3/60),s=Math.ceil((t-r*60*1e3)/1e3);return s===0?`${r}m`:`${r}m ${s}s`}else{let r=Math.floor(t/1e3),s=t-r*1e3;return s===0?`${r}s`:`${r}s ${s}ms`}},json:e=>e}),[gt.SIZE]:zo({pretty:(e,t)=>si(e,Tae(t),gt.NUMBER),json:e=>e}),[gt.SIZE_DIFF]:zo({pretty:(e,t)=>{let r=t>=0?\"+\":\"-\",s=r===\"+\"?gt.REMOVED:gt.ADDED;return si(e,`${r} ${Tae(Math.max(Math.abs(t),1))}`,s)},json:e=>e}),[gt.PATH]:zo({pretty:(e,t)=>si(e,fe.fromPortablePath(t),gt.PATH),json:e=>fe.fromPortablePath(e)}),[gt.MARKDOWN]:zo({pretty:(e,{text:t,format:r,paragraphs:s})=>Vo(t,{format:r,paragraphs:s}),json:({text:e})=>e}),[gt.MARKDOWN_INLINE]:zo({pretty:(e,t)=>(t=t.replace(/(`+)((?:.|[\\n])*?)\\1/g,(r,s,a)=>jt(e,s+a+s,gt.CODE)),t=t.replace(/(\\*\\*)((?:.|[\\n])*?)\\1/g,(r,s,a)=>Kd(e,a,2)),t),json:e=>e})};QKe=!!process.env.KONSOLE_VERSION;$k=(a=>(a.Error=\"error\",a.Warning=\"warning\",a.Info=\"info\",a.Discard=\"discard\",a))($k||{})});var Nae=G($E=>{\"use strict\";Object.defineProperty($E,\"__esModule\",{value:!0});$E.splitWhen=$E.flatten=void 0;function TKe(e){return e.reduce((t,r)=>[].concat(t,r),[])}$E.flatten=TKe;function FKe(e,t){let r=[[]],s=0;for(let a of e)t(a)?(s++,r[s]=[]):r[s].push(a);return r}$E.splitWhen=FKe});var Oae=G(eQ=>{\"use strict\";Object.defineProperty(eQ,\"__esModule\",{value:!0});eQ.isEnoentCodeError=void 0;function NKe(e){return e.code===\"ENOENT\"}eQ.isEnoentCodeError=NKe});var Lae=G(tQ=>{\"use strict\";Object.defineProperty(tQ,\"__esModule\",{value:!0});tQ.createDirentFromStats=void 0;var _4=class{constructor(t,r){this.name=t,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function OKe(e,t){return new _4(e,t)}tQ.createDirentFromStats=OKe});var Hae=G(us=>{\"use strict\";Object.defineProperty(us,\"__esModule\",{value:!0});us.convertPosixPathToPattern=us.convertWindowsPathToPattern=us.convertPathToPattern=us.escapePosixPath=us.escapeWindowsPath=us.escape=us.removeLeadingDotSegment=us.makeAbsolute=us.unixify=void 0;var LKe=Ie(\"os\"),MKe=Ie(\"path\"),Mae=LKe.platform()===\"win32\",UKe=2,_Ke=/(\\\\?)([()*?[\\]{|}]|^!|[!+@](?=\\()|\\\\(?![!()*+?@[\\]{|}]))/g,HKe=/(\\\\?)([()[\\]{}]|^!|[!+@](?=\\())/g,jKe=/^\\\\\\\\([.?])/,GKe=/\\\\(?![!()+@[\\]{}])/g;function qKe(e){return e.replace(/\\\\/g,\"/\")}us.unixify=qKe;function WKe(e,t){return MKe.resolve(e,t)}us.makeAbsolute=WKe;function VKe(e){if(e.charAt(0)===\".\"){let t=e.charAt(1);if(t===\"/\"||t===\"\\\\\")return e.slice(UKe)}return e}us.removeLeadingDotSegment=VKe;us.escape=Mae?H4:j4;function H4(e){return e.replace(HKe,\"\\\\$2\")}us.escapeWindowsPath=H4;function j4(e){return e.replace(_Ke,\"\\\\$2\")}us.escapePosixPath=j4;us.convertPathToPattern=Mae?Uae:_ae;function Uae(e){return H4(e).replace(jKe,\"//$1\").replace(GKe,\"/\")}us.convertWindowsPathToPattern=Uae;function _ae(e){return j4(e)}us.convertPosixPathToPattern=_ae});var Gae=G((lFt,jae)=>{jae.exports=function(t){if(typeof t!=\"string\"||t===\"\")return!1;for(var r;r=/(\\\\).|([@?!+*]\\(.*\\))/g.exec(t);){if(r[2])return!0;t=t.slice(r.index+r[0].length)}return!1}});var Vae=G((cFt,Wae)=>{var YKe=Gae(),qae={\"{\":\"}\",\"(\":\")\",\"[\":\"]\"},KKe=function(e){if(e[0]===\"!\")return!0;for(var t=0,r=-2,s=-2,a=-2,n=-2,c=-2;t<e.length;){if(e[t]===\"*\"||e[t+1]===\"?\"&&/[\\].+)]/.test(e[t])||s!==-1&&e[t]===\"[\"&&e[t+1]!==\"]\"&&(s<t&&(s=e.indexOf(\"]\",t)),s>t&&(c===-1||c>s||(c=e.indexOf(\"\\\\\",t),c===-1||c>s)))||a!==-1&&e[t]===\"{\"&&e[t+1]!==\"}\"&&(a=e.indexOf(\"}\",t),a>t&&(c=e.indexOf(\"\\\\\",t),c===-1||c>a))||n!==-1&&e[t]===\"(\"&&e[t+1]===\"?\"&&/[:!=]/.test(e[t+2])&&e[t+3]!==\")\"&&(n=e.indexOf(\")\",t),n>t&&(c=e.indexOf(\"\\\\\",t),c===-1||c>n))||r!==-1&&e[t]===\"(\"&&e[t+1]!==\"|\"&&(r<t&&(r=e.indexOf(\"|\",t)),r!==-1&&e[r+1]!==\")\"&&(n=e.indexOf(\")\",r),n>r&&(c=e.indexOf(\"\\\\\",r),c===-1||c>n))))return!0;if(e[t]===\"\\\\\"){var f=e[t+1];t+=2;var p=qae[f];if(p){var h=e.indexOf(p,t);h!==-1&&(t=h+1)}if(e[t]===\"!\")return!0}else t++}return!1},JKe=function(e){if(e[0]===\"!\")return!0;for(var t=0;t<e.length;){if(/[*?{}()[\\]]/.test(e[t]))return!0;if(e[t]===\"\\\\\"){var r=e[t+1];t+=2;var s=qae[r];if(s){var a=e.indexOf(s,t);a!==-1&&(t=a+1)}if(e[t]===\"!\")return!0}else t++}return!1};Wae.exports=function(t,r){if(typeof t!=\"string\"||t===\"\")return!1;if(YKe(t))return!0;var s=KKe;return r&&r.strict===!1&&(s=JKe),s(t)}});var Kae=G((uFt,Yae)=>{\"use strict\";var zKe=Vae(),ZKe=Ie(\"path\").posix.dirname,XKe=Ie(\"os\").platform()===\"win32\",G4=\"/\",$Ke=/\\\\/g,eJe=/[\\{\\[].*[\\}\\]]$/,tJe=/(^|[^\\\\])([\\{\\[]|\\([^\\)]+$)/,rJe=/\\\\([\\!\\*\\?\\|\\[\\]\\(\\)\\{\\}])/g;Yae.exports=function(t,r){var s=Object.assign({flipBackslashes:!0},r);s.flipBackslashes&&XKe&&t.indexOf(G4)<0&&(t=t.replace($Ke,G4)),eJe.test(t)&&(t+=G4),t+=\"a\";do t=ZKe(t);while(zKe(t)||tJe.test(t));return t.replace(rJe,\"$1\")}});var rle=G(jr=>{\"use strict\";Object.defineProperty(jr,\"__esModule\",{value:!0});jr.removeDuplicateSlashes=jr.matchAny=jr.convertPatternsToRe=jr.makeRe=jr.getPatternParts=jr.expandBraceExpansion=jr.expandPatternsWithBraceExpansion=jr.isAffectDepthOfReadingPattern=jr.endsWithSlashGlobStar=jr.hasGlobStar=jr.getBaseDirectory=jr.isPatternRelatedToParentDirectory=jr.getPatternsOutsideCurrentDirectory=jr.getPatternsInsideCurrentDirectory=jr.getPositivePatterns=jr.getNegativePatterns=jr.isPositivePattern=jr.isNegativePattern=jr.convertToNegativePattern=jr.convertToPositivePattern=jr.isDynamicPattern=jr.isStaticPattern=void 0;var nJe=Ie(\"path\"),iJe=Kae(),q4=Jo(),Jae=\"**\",sJe=\"\\\\\",oJe=/[*?]|^!/,aJe=/\\[[^[]*]/,lJe=/(?:^|[^!*+?@])\\([^(]*\\|[^|]*\\)/,cJe=/[!*+?@]\\([^(]*\\)/,uJe=/,|\\.\\./,fJe=/(?!^)\\/{2,}/g;function zae(e,t={}){return!Zae(e,t)}jr.isStaticPattern=zae;function Zae(e,t={}){return e===\"\"?!1:!!(t.caseSensitiveMatch===!1||e.includes(sJe)||oJe.test(e)||aJe.test(e)||lJe.test(e)||t.extglob!==!1&&cJe.test(e)||t.braceExpansion!==!1&&AJe(e))}jr.isDynamicPattern=Zae;function AJe(e){let t=e.indexOf(\"{\");if(t===-1)return!1;let r=e.indexOf(\"}\",t+1);if(r===-1)return!1;let s=e.slice(t,r);return uJe.test(s)}function pJe(e){return rQ(e)?e.slice(1):e}jr.convertToPositivePattern=pJe;function hJe(e){return\"!\"+e}jr.convertToNegativePattern=hJe;function rQ(e){return e.startsWith(\"!\")&&e[1]!==\"(\"}jr.isNegativePattern=rQ;function Xae(e){return!rQ(e)}jr.isPositivePattern=Xae;function gJe(e){return e.filter(rQ)}jr.getNegativePatterns=gJe;function dJe(e){return e.filter(Xae)}jr.getPositivePatterns=dJe;function mJe(e){return e.filter(t=>!W4(t))}jr.getPatternsInsideCurrentDirectory=mJe;function yJe(e){return e.filter(W4)}jr.getPatternsOutsideCurrentDirectory=yJe;function W4(e){return e.startsWith(\"..\")||e.startsWith(\"./..\")}jr.isPatternRelatedToParentDirectory=W4;function EJe(e){return iJe(e,{flipBackslashes:!1})}jr.getBaseDirectory=EJe;function IJe(e){return e.includes(Jae)}jr.hasGlobStar=IJe;function $ae(e){return e.endsWith(\"/\"+Jae)}jr.endsWithSlashGlobStar=$ae;function CJe(e){let t=nJe.basename(e);return $ae(e)||zae(t)}jr.isAffectDepthOfReadingPattern=CJe;function wJe(e){return e.reduce((t,r)=>t.concat(ele(r)),[])}jr.expandPatternsWithBraceExpansion=wJe;function ele(e){let t=q4.braces(e,{expand:!0,nodupes:!0,keepEscaping:!0});return t.sort((r,s)=>r.length-s.length),t.filter(r=>r!==\"\")}jr.expandBraceExpansion=ele;function BJe(e,t){let{parts:r}=q4.scan(e,Object.assign(Object.assign({},t),{parts:!0}));return r.length===0&&(r=[e]),r[0].startsWith(\"/\")&&(r[0]=r[0].slice(1),r.unshift(\"\")),r}jr.getPatternParts=BJe;function tle(e,t){return q4.makeRe(e,t)}jr.makeRe=tle;function vJe(e,t){return e.map(r=>tle(r,t))}jr.convertPatternsToRe=vJe;function SJe(e,t){return t.some(r=>r.test(e))}jr.matchAny=SJe;function DJe(e){return e.replace(fJe,\"/\")}jr.removeDuplicateSlashes=DJe});var ole=G((AFt,sle)=>{\"use strict\";var bJe=Ie(\"stream\"),nle=bJe.PassThrough,PJe=Array.prototype.slice;sle.exports=xJe;function xJe(){let e=[],t=PJe.call(arguments),r=!1,s=t[t.length-1];s&&!Array.isArray(s)&&s.pipe==null?t.pop():s={};let a=s.end!==!1,n=s.pipeError===!0;s.objectMode==null&&(s.objectMode=!0),s.highWaterMark==null&&(s.highWaterMark=64*1024);let c=nle(s);function f(){for(let E=0,C=arguments.length;E<C;E++)e.push(ile(arguments[E],s));return p(),this}function p(){if(r)return;r=!0;let E=e.shift();if(!E){process.nextTick(h);return}Array.isArray(E)||(E=[E]);let C=E.length+1;function S(){--C>0||(r=!1,p())}function x(I){function T(){I.removeListener(\"merge2UnpipeEnd\",T),I.removeListener(\"end\",T),n&&I.removeListener(\"error\",O),S()}function O(U){c.emit(\"error\",U)}if(I._readableState.endEmitted)return S();I.on(\"merge2UnpipeEnd\",T),I.on(\"end\",T),n&&I.on(\"error\",O),I.pipe(c,{end:!1}),I.resume()}for(let I=0;I<E.length;I++)x(E[I]);S()}function h(){r=!1,c.emit(\"queueDrain\"),a&&c.end()}return c.setMaxListeners(0),c.add=f,c.on(\"unpipe\",function(E){E.emit(\"merge2UnpipeEnd\")}),t.length&&f.apply(null,t),c}function ile(e,t){if(Array.isArray(e))for(let r=0,s=e.length;r<s;r++)e[r]=ile(e[r],t);else{if(!e._readableState&&e.pipe&&(e=e.pipe(nle(t))),!e._readableState||!e.pause||!e.pipe)throw new Error(\"Only readable stream can be merged.\");e.pause()}return e}});var lle=G(nQ=>{\"use strict\";Object.defineProperty(nQ,\"__esModule\",{value:!0});nQ.merge=void 0;var kJe=ole();function QJe(e){let t=kJe(e);return e.forEach(r=>{r.once(\"error\",s=>t.emit(\"error\",s))}),t.once(\"close\",()=>ale(e)),t.once(\"end\",()=>ale(e)),t}nQ.merge=QJe;function ale(e){e.forEach(t=>t.emit(\"close\"))}});var cle=G(eI=>{\"use strict\";Object.defineProperty(eI,\"__esModule\",{value:!0});eI.isEmpty=eI.isString=void 0;function RJe(e){return typeof e==\"string\"}eI.isString=RJe;function TJe(e){return e===\"\"}eI.isEmpty=TJe});var kp=G(Xo=>{\"use strict\";Object.defineProperty(Xo,\"__esModule\",{value:!0});Xo.string=Xo.stream=Xo.pattern=Xo.path=Xo.fs=Xo.errno=Xo.array=void 0;var FJe=Nae();Xo.array=FJe;var NJe=Oae();Xo.errno=NJe;var OJe=Lae();Xo.fs=OJe;var LJe=Hae();Xo.path=LJe;var MJe=rle();Xo.pattern=MJe;var UJe=lle();Xo.stream=UJe;var _Je=cle();Xo.string=_Je});var ple=G($o=>{\"use strict\";Object.defineProperty($o,\"__esModule\",{value:!0});$o.convertPatternGroupToTask=$o.convertPatternGroupsToTasks=$o.groupPatternsByBaseDirectory=$o.getNegativePatternsAsPositive=$o.getPositivePatterns=$o.convertPatternsToTasks=$o.generate=void 0;var Uu=kp();function HJe(e,t){let r=ule(e,t),s=ule(t.ignore,t),a=fle(r),n=Ale(r,s),c=a.filter(E=>Uu.pattern.isStaticPattern(E,t)),f=a.filter(E=>Uu.pattern.isDynamicPattern(E,t)),p=V4(c,n,!1),h=V4(f,n,!0);return p.concat(h)}$o.generate=HJe;function ule(e,t){let r=e;return t.braceExpansion&&(r=Uu.pattern.expandPatternsWithBraceExpansion(r)),t.baseNameMatch&&(r=r.map(s=>s.includes(\"/\")?s:`**/${s}`)),r.map(s=>Uu.pattern.removeDuplicateSlashes(s))}function V4(e,t,r){let s=[],a=Uu.pattern.getPatternsOutsideCurrentDirectory(e),n=Uu.pattern.getPatternsInsideCurrentDirectory(e),c=Y4(a),f=Y4(n);return s.push(...K4(c,t,r)),\".\"in f?s.push(J4(\".\",n,t,r)):s.push(...K4(f,t,r)),s}$o.convertPatternsToTasks=V4;function fle(e){return Uu.pattern.getPositivePatterns(e)}$o.getPositivePatterns=fle;function Ale(e,t){return Uu.pattern.getNegativePatterns(e).concat(t).map(Uu.pattern.convertToPositivePattern)}$o.getNegativePatternsAsPositive=Ale;function Y4(e){let t={};return e.reduce((r,s)=>{let a=Uu.pattern.getBaseDirectory(s);return a in r?r[a].push(s):r[a]=[s],r},t)}$o.groupPatternsByBaseDirectory=Y4;function K4(e,t,r){return Object.keys(e).map(s=>J4(s,e[s],t,r))}$o.convertPatternGroupsToTasks=K4;function J4(e,t,r,s){return{dynamic:s,positive:t,negative:r,base:e,patterns:[].concat(t,r.map(Uu.pattern.convertToNegativePattern))}}$o.convertPatternGroupToTask=J4});var gle=G(iQ=>{\"use strict\";Object.defineProperty(iQ,\"__esModule\",{value:!0});iQ.read=void 0;function jJe(e,t,r){t.fs.lstat(e,(s,a)=>{if(s!==null){hle(r,s);return}if(!a.isSymbolicLink()||!t.followSymbolicLink){z4(r,a);return}t.fs.stat(e,(n,c)=>{if(n!==null){if(t.throwErrorOnBrokenSymbolicLink){hle(r,n);return}z4(r,a);return}t.markSymbolicLink&&(c.isSymbolicLink=()=>!0),z4(r,c)})})}iQ.read=jJe;function hle(e,t){e(t)}function z4(e,t){e(null,t)}});var dle=G(sQ=>{\"use strict\";Object.defineProperty(sQ,\"__esModule\",{value:!0});sQ.read=void 0;function GJe(e,t){let r=t.fs.lstatSync(e);if(!r.isSymbolicLink()||!t.followSymbolicLink)return r;try{let s=t.fs.statSync(e);return t.markSymbolicLink&&(s.isSymbolicLink=()=>!0),s}catch(s){if(!t.throwErrorOnBrokenSymbolicLink)return r;throw s}}sQ.read=GJe});var mle=G(A0=>{\"use strict\";Object.defineProperty(A0,\"__esModule\",{value:!0});A0.createFileSystemAdapter=A0.FILE_SYSTEM_ADAPTER=void 0;var oQ=Ie(\"fs\");A0.FILE_SYSTEM_ADAPTER={lstat:oQ.lstat,stat:oQ.stat,lstatSync:oQ.lstatSync,statSync:oQ.statSync};function qJe(e){return e===void 0?A0.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},A0.FILE_SYSTEM_ADAPTER),e)}A0.createFileSystemAdapter=qJe});var yle=G(X4=>{\"use strict\";Object.defineProperty(X4,\"__esModule\",{value:!0});var WJe=mle(),Z4=class{constructor(t={}){this._options=t,this.followSymbolicLink=this._getValue(this._options.followSymbolicLink,!0),this.fs=WJe.createFileSystemAdapter(this._options.fs),this.markSymbolicLink=this._getValue(this._options.markSymbolicLink,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0)}_getValue(t,r){return t??r}};X4.default=Z4});var zd=G(p0=>{\"use strict\";Object.defineProperty(p0,\"__esModule\",{value:!0});p0.statSync=p0.stat=p0.Settings=void 0;var Ele=gle(),VJe=dle(),$4=yle();p0.Settings=$4.default;function YJe(e,t,r){if(typeof t==\"function\"){Ele.read(e,e3(),t);return}Ele.read(e,e3(t),r)}p0.stat=YJe;function KJe(e,t){let r=e3(t);return VJe.read(e,r)}p0.statSync=KJe;function e3(e={}){return e instanceof $4.default?e:new $4.default(e)}});var wle=G((wFt,Cle)=>{var Ile;Cle.exports=typeof queueMicrotask==\"function\"?queueMicrotask.bind(typeof window<\"u\"?window:global):e=>(Ile||(Ile=Promise.resolve())).then(e).catch(t=>setTimeout(()=>{throw t},0))});var vle=G((BFt,Ble)=>{Ble.exports=zJe;var JJe=wle();function zJe(e,t){let r,s,a,n=!0;Array.isArray(e)?(r=[],s=e.length):(a=Object.keys(e),r={},s=a.length);function c(p){function h(){t&&t(p,r),t=null}n?JJe(h):h()}function f(p,h,E){r[p]=E,(--s===0||h)&&c(h)}s?a?a.forEach(function(p){e[p](function(h,E){f(p,h,E)})}):e.forEach(function(p,h){p(function(E,C){f(h,E,C)})}):c(null),n=!1}});var t3=G(lQ=>{\"use strict\";Object.defineProperty(lQ,\"__esModule\",{value:!0});lQ.IS_SUPPORT_READDIR_WITH_FILE_TYPES=void 0;var aQ=process.versions.node.split(\".\");if(aQ[0]===void 0||aQ[1]===void 0)throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);var Sle=Number.parseInt(aQ[0],10),ZJe=Number.parseInt(aQ[1],10),Dle=10,XJe=10,$Je=Sle>Dle,eze=Sle===Dle&&ZJe>=XJe;lQ.IS_SUPPORT_READDIR_WITH_FILE_TYPES=$Je||eze});var ble=G(cQ=>{\"use strict\";Object.defineProperty(cQ,\"__esModule\",{value:!0});cQ.createDirentFromStats=void 0;var r3=class{constructor(t,r){this.name=t,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function tze(e,t){return new r3(e,t)}cQ.createDirentFromStats=tze});var n3=G(uQ=>{\"use strict\";Object.defineProperty(uQ,\"__esModule\",{value:!0});uQ.fs=void 0;var rze=ble();uQ.fs=rze});var i3=G(fQ=>{\"use strict\";Object.defineProperty(fQ,\"__esModule\",{value:!0});fQ.joinPathSegments=void 0;function nze(e,t,r){return e.endsWith(r)?e+t:e+r+t}fQ.joinPathSegments=nze});var Tle=G(h0=>{\"use strict\";Object.defineProperty(h0,\"__esModule\",{value:!0});h0.readdir=h0.readdirWithFileTypes=h0.read=void 0;var ize=zd(),Ple=vle(),sze=t3(),xle=n3(),kle=i3();function oze(e,t,r){if(!t.stats&&sze.IS_SUPPORT_READDIR_WITH_FILE_TYPES){Qle(e,t,r);return}Rle(e,t,r)}h0.read=oze;function Qle(e,t,r){t.fs.readdir(e,{withFileTypes:!0},(s,a)=>{if(s!==null){AQ(r,s);return}let n=a.map(f=>({dirent:f,name:f.name,path:kle.joinPathSegments(e,f.name,t.pathSegmentSeparator)}));if(!t.followSymbolicLinks){s3(r,n);return}let c=n.map(f=>aze(f,t));Ple(c,(f,p)=>{if(f!==null){AQ(r,f);return}s3(r,p)})})}h0.readdirWithFileTypes=Qle;function aze(e,t){return r=>{if(!e.dirent.isSymbolicLink()){r(null,e);return}t.fs.stat(e.path,(s,a)=>{if(s!==null){if(t.throwErrorOnBrokenSymbolicLink){r(s);return}r(null,e);return}e.dirent=xle.fs.createDirentFromStats(e.name,a),r(null,e)})}}function Rle(e,t,r){t.fs.readdir(e,(s,a)=>{if(s!==null){AQ(r,s);return}let n=a.map(c=>{let f=kle.joinPathSegments(e,c,t.pathSegmentSeparator);return p=>{ize.stat(f,t.fsStatSettings,(h,E)=>{if(h!==null){p(h);return}let C={name:c,path:f,dirent:xle.fs.createDirentFromStats(c,E)};t.stats&&(C.stats=E),p(null,C)})}});Ple(n,(c,f)=>{if(c!==null){AQ(r,c);return}s3(r,f)})})}h0.readdir=Rle;function AQ(e,t){e(t)}function s3(e,t){e(null,t)}});var Mle=G(g0=>{\"use strict\";Object.defineProperty(g0,\"__esModule\",{value:!0});g0.readdir=g0.readdirWithFileTypes=g0.read=void 0;var lze=zd(),cze=t3(),Fle=n3(),Nle=i3();function uze(e,t){return!t.stats&&cze.IS_SUPPORT_READDIR_WITH_FILE_TYPES?Ole(e,t):Lle(e,t)}g0.read=uze;function Ole(e,t){return t.fs.readdirSync(e,{withFileTypes:!0}).map(s=>{let a={dirent:s,name:s.name,path:Nle.joinPathSegments(e,s.name,t.pathSegmentSeparator)};if(a.dirent.isSymbolicLink()&&t.followSymbolicLinks)try{let n=t.fs.statSync(a.path);a.dirent=Fle.fs.createDirentFromStats(a.name,n)}catch(n){if(t.throwErrorOnBrokenSymbolicLink)throw n}return a})}g0.readdirWithFileTypes=Ole;function Lle(e,t){return t.fs.readdirSync(e).map(s=>{let a=Nle.joinPathSegments(e,s,t.pathSegmentSeparator),n=lze.statSync(a,t.fsStatSettings),c={name:s,path:a,dirent:Fle.fs.createDirentFromStats(s,n)};return t.stats&&(c.stats=n),c})}g0.readdir=Lle});var Ule=G(d0=>{\"use strict\";Object.defineProperty(d0,\"__esModule\",{value:!0});d0.createFileSystemAdapter=d0.FILE_SYSTEM_ADAPTER=void 0;var tI=Ie(\"fs\");d0.FILE_SYSTEM_ADAPTER={lstat:tI.lstat,stat:tI.stat,lstatSync:tI.lstatSync,statSync:tI.statSync,readdir:tI.readdir,readdirSync:tI.readdirSync};function fze(e){return e===void 0?d0.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},d0.FILE_SYSTEM_ADAPTER),e)}d0.createFileSystemAdapter=fze});var _le=G(a3=>{\"use strict\";Object.defineProperty(a3,\"__esModule\",{value:!0});var Aze=Ie(\"path\"),pze=zd(),hze=Ule(),o3=class{constructor(t={}){this._options=t,this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!1),this.fs=hze.createFileSystemAdapter(this._options.fs),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,Aze.sep),this.stats=this._getValue(this._options.stats,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0),this.fsStatSettings=new pze.Settings({followSymbolicLink:this.followSymbolicLinks,fs:this.fs,throwErrorOnBrokenSymbolicLink:this.throwErrorOnBrokenSymbolicLink})}_getValue(t,r){return t??r}};a3.default=o3});var pQ=G(m0=>{\"use strict\";Object.defineProperty(m0,\"__esModule\",{value:!0});m0.Settings=m0.scandirSync=m0.scandir=void 0;var Hle=Tle(),gze=Mle(),l3=_le();m0.Settings=l3.default;function dze(e,t,r){if(typeof t==\"function\"){Hle.read(e,c3(),t);return}Hle.read(e,c3(t),r)}m0.scandir=dze;function mze(e,t){let r=c3(t);return gze.read(e,r)}m0.scandirSync=mze;function c3(e={}){return e instanceof l3.default?e:new l3.default(e)}});var Gle=G((TFt,jle)=>{\"use strict\";function yze(e){var t=new e,r=t;function s(){var n=t;return n.next?t=n.next:(t=new e,r=t),n.next=null,n}function a(n){r.next=n,r=n}return{get:s,release:a}}jle.exports=yze});var Wle=G((FFt,u3)=>{\"use strict\";var Eze=Gle();function qle(e,t,r){if(typeof e==\"function\"&&(r=t,t=e,e=null),!(r>=1))throw new Error(\"fastqueue concurrency must be equal to or greater than 1\");var s=Eze(Ize),a=null,n=null,c=0,f=null,p={push:T,drain:Qc,saturated:Qc,pause:E,paused:!1,get concurrency(){return r},set concurrency(ue){if(!(ue>=1))throw new Error(\"fastqueue concurrency must be equal to or greater than 1\");if(r=ue,!p.paused)for(;a&&c<r;)c++,U()},running:h,resume:x,idle:I,length:C,getQueue:S,unshift:O,empty:Qc,kill:Y,killAndDrain:te,error:ie};return p;function h(){return c}function E(){p.paused=!0}function C(){for(var ue=a,ae=0;ue;)ue=ue.next,ae++;return ae}function S(){for(var ue=a,ae=[];ue;)ae.push(ue.value),ue=ue.next;return ae}function x(){if(p.paused){if(p.paused=!1,a===null){c++,U();return}for(;a&&c<r;)c++,U()}}function I(){return c===0&&p.length()===0}function T(ue,ae){var de=s.get();de.context=e,de.release=U,de.value=ue,de.callback=ae||Qc,de.errorHandler=f,c>=r||p.paused?n?(n.next=de,n=de):(a=de,n=de,p.saturated()):(c++,t.call(e,de.value,de.worked))}function O(ue,ae){var de=s.get();de.context=e,de.release=U,de.value=ue,de.callback=ae||Qc,de.errorHandler=f,c>=r||p.paused?a?(de.next=a,a=de):(a=de,n=de,p.saturated()):(c++,t.call(e,de.value,de.worked))}function U(ue){ue&&s.release(ue);var ae=a;ae&&c<=r?p.paused?c--:(n===a&&(n=null),a=ae.next,ae.next=null,t.call(e,ae.value,ae.worked),n===null&&p.empty()):--c===0&&p.drain()}function Y(){a=null,n=null,p.drain=Qc}function te(){a=null,n=null,p.drain(),p.drain=Qc}function ie(ue){f=ue}}function Qc(){}function Ize(){this.value=null,this.callback=Qc,this.next=null,this.release=Qc,this.context=null,this.errorHandler=null;var e=this;this.worked=function(r,s){var a=e.callback,n=e.errorHandler,c=e.value;e.value=null,e.callback=Qc,e.errorHandler&&n(r,c),a.call(e.context,r,s),e.release(e)}}function Cze(e,t,r){typeof e==\"function\"&&(r=t,t=e,e=null);function s(E,C){t.call(this,E).then(function(S){C(null,S)},C)}var a=qle(e,s,r),n=a.push,c=a.unshift;return a.push=f,a.unshift=p,a.drained=h,a;function f(E){var C=new Promise(function(S,x){n(E,function(I,T){if(I){x(I);return}S(T)})});return C.catch(Qc),C}function p(E){var C=new Promise(function(S,x){c(E,function(I,T){if(I){x(I);return}S(T)})});return C.catch(Qc),C}function h(){if(a.idle())return new Promise(function(S){S()});var E=a.drain,C=new Promise(function(S){a.drain=function(){E(),S()}});return C}}u3.exports=qle;u3.exports.promise=Cze});var hQ=G(Xf=>{\"use strict\";Object.defineProperty(Xf,\"__esModule\",{value:!0});Xf.joinPathSegments=Xf.replacePathSegmentSeparator=Xf.isAppliedFilter=Xf.isFatalError=void 0;function wze(e,t){return e.errorFilter===null?!0:!e.errorFilter(t)}Xf.isFatalError=wze;function Bze(e,t){return e===null||e(t)}Xf.isAppliedFilter=Bze;function vze(e,t){return e.split(/[/\\\\]/).join(t)}Xf.replacePathSegmentSeparator=vze;function Sze(e,t,r){return e===\"\"?t:e.endsWith(r)?e+t:e+r+t}Xf.joinPathSegments=Sze});var p3=G(A3=>{\"use strict\";Object.defineProperty(A3,\"__esModule\",{value:!0});var Dze=hQ(),f3=class{constructor(t,r){this._root=t,this._settings=r,this._root=Dze.replacePathSegmentSeparator(t,r.pathSegmentSeparator)}};A3.default=f3});var d3=G(g3=>{\"use strict\";Object.defineProperty(g3,\"__esModule\",{value:!0});var bze=Ie(\"events\"),Pze=pQ(),xze=Wle(),gQ=hQ(),kze=p3(),h3=class extends kze.default{constructor(t,r){super(t,r),this._settings=r,this._scandir=Pze.scandir,this._emitter=new bze.EventEmitter,this._queue=xze(this._worker.bind(this),this._settings.concurrency),this._isFatalError=!1,this._isDestroyed=!1,this._queue.drain=()=>{this._isFatalError||this._emitter.emit(\"end\")}}read(){return this._isFatalError=!1,this._isDestroyed=!1,setImmediate(()=>{this._pushToQueue(this._root,this._settings.basePath)}),this._emitter}get isDestroyed(){return this._isDestroyed}destroy(){if(this._isDestroyed)throw new Error(\"The reader is already destroyed\");this._isDestroyed=!0,this._queue.killAndDrain()}onEntry(t){this._emitter.on(\"entry\",t)}onError(t){this._emitter.once(\"error\",t)}onEnd(t){this._emitter.once(\"end\",t)}_pushToQueue(t,r){let s={directory:t,base:r};this._queue.push(s,a=>{a!==null&&this._handleError(a)})}_worker(t,r){this._scandir(t.directory,this._settings.fsScandirSettings,(s,a)=>{if(s!==null){r(s,void 0);return}for(let n of a)this._handleEntry(n,t.base);r(null,void 0)})}_handleError(t){this._isDestroyed||!gQ.isFatalError(this._settings,t)||(this._isFatalError=!0,this._isDestroyed=!0,this._emitter.emit(\"error\",t))}_handleEntry(t,r){if(this._isDestroyed||this._isFatalError)return;let s=t.path;r!==void 0&&(t.path=gQ.joinPathSegments(r,t.name,this._settings.pathSegmentSeparator)),gQ.isAppliedFilter(this._settings.entryFilter,t)&&this._emitEntry(t),t.dirent.isDirectory()&&gQ.isAppliedFilter(this._settings.deepFilter,t)&&this._pushToQueue(s,r===void 0?void 0:t.path)}_emitEntry(t){this._emitter.emit(\"entry\",t)}};g3.default=h3});var Vle=G(y3=>{\"use strict\";Object.defineProperty(y3,\"__esModule\",{value:!0});var Qze=d3(),m3=class{constructor(t,r){this._root=t,this._settings=r,this._reader=new Qze.default(this._root,this._settings),this._storage=[]}read(t){this._reader.onError(r=>{Rze(t,r)}),this._reader.onEntry(r=>{this._storage.push(r)}),this._reader.onEnd(()=>{Tze(t,this._storage)}),this._reader.read()}};y3.default=m3;function Rze(e,t){e(t)}function Tze(e,t){e(null,t)}});var Yle=G(I3=>{\"use strict\";Object.defineProperty(I3,\"__esModule\",{value:!0});var Fze=Ie(\"stream\"),Nze=d3(),E3=class{constructor(t,r){this._root=t,this._settings=r,this._reader=new Nze.default(this._root,this._settings),this._stream=new Fze.Readable({objectMode:!0,read:()=>{},destroy:()=>{this._reader.isDestroyed||this._reader.destroy()}})}read(){return this._reader.onError(t=>{this._stream.emit(\"error\",t)}),this._reader.onEntry(t=>{this._stream.push(t)}),this._reader.onEnd(()=>{this._stream.push(null)}),this._reader.read(),this._stream}};I3.default=E3});var Kle=G(w3=>{\"use strict\";Object.defineProperty(w3,\"__esModule\",{value:!0});var Oze=pQ(),dQ=hQ(),Lze=p3(),C3=class extends Lze.default{constructor(){super(...arguments),this._scandir=Oze.scandirSync,this._storage=[],this._queue=new Set}read(){return this._pushToQueue(this._root,this._settings.basePath),this._handleQueue(),this._storage}_pushToQueue(t,r){this._queue.add({directory:t,base:r})}_handleQueue(){for(let t of this._queue.values())this._handleDirectory(t.directory,t.base)}_handleDirectory(t,r){try{let s=this._scandir(t,this._settings.fsScandirSettings);for(let a of s)this._handleEntry(a,r)}catch(s){this._handleError(s)}}_handleError(t){if(dQ.isFatalError(this._settings,t))throw t}_handleEntry(t,r){let s=t.path;r!==void 0&&(t.path=dQ.joinPathSegments(r,t.name,this._settings.pathSegmentSeparator)),dQ.isAppliedFilter(this._settings.entryFilter,t)&&this._pushToStorage(t),t.dirent.isDirectory()&&dQ.isAppliedFilter(this._settings.deepFilter,t)&&this._pushToQueue(s,r===void 0?void 0:t.path)}_pushToStorage(t){this._storage.push(t)}};w3.default=C3});var Jle=G(v3=>{\"use strict\";Object.defineProperty(v3,\"__esModule\",{value:!0});var Mze=Kle(),B3=class{constructor(t,r){this._root=t,this._settings=r,this._reader=new Mze.default(this._root,this._settings)}read(){return this._reader.read()}};v3.default=B3});var zle=G(D3=>{\"use strict\";Object.defineProperty(D3,\"__esModule\",{value:!0});var Uze=Ie(\"path\"),_ze=pQ(),S3=class{constructor(t={}){this._options=t,this.basePath=this._getValue(this._options.basePath,void 0),this.concurrency=this._getValue(this._options.concurrency,Number.POSITIVE_INFINITY),this.deepFilter=this._getValue(this._options.deepFilter,null),this.entryFilter=this._getValue(this._options.entryFilter,null),this.errorFilter=this._getValue(this._options.errorFilter,null),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,Uze.sep),this.fsScandirSettings=new _ze.Settings({followSymbolicLinks:this._options.followSymbolicLinks,fs:this._options.fs,pathSegmentSeparator:this._options.pathSegmentSeparator,stats:this._options.stats,throwErrorOnBrokenSymbolicLink:this._options.throwErrorOnBrokenSymbolicLink})}_getValue(t,r){return t??r}};D3.default=S3});var yQ=G($f=>{\"use strict\";Object.defineProperty($f,\"__esModule\",{value:!0});$f.Settings=$f.walkStream=$f.walkSync=$f.walk=void 0;var Zle=Vle(),Hze=Yle(),jze=Jle(),b3=zle();$f.Settings=b3.default;function Gze(e,t,r){if(typeof t==\"function\"){new Zle.default(e,mQ()).read(t);return}new Zle.default(e,mQ(t)).read(r)}$f.walk=Gze;function qze(e,t){let r=mQ(t);return new jze.default(e,r).read()}$f.walkSync=qze;function Wze(e,t){let r=mQ(t);return new Hze.default(e,r).read()}$f.walkStream=Wze;function mQ(e={}){return e instanceof b3.default?e:new b3.default(e)}});var EQ=G(x3=>{\"use strict\";Object.defineProperty(x3,\"__esModule\",{value:!0});var Vze=Ie(\"path\"),Yze=zd(),Xle=kp(),P3=class{constructor(t){this._settings=t,this._fsStatSettings=new Yze.Settings({followSymbolicLink:this._settings.followSymbolicLinks,fs:this._settings.fs,throwErrorOnBrokenSymbolicLink:this._settings.followSymbolicLinks})}_getFullEntryPath(t){return Vze.resolve(this._settings.cwd,t)}_makeEntry(t,r){let s={name:r,path:r,dirent:Xle.fs.createDirentFromStats(r,t)};return this._settings.stats&&(s.stats=t),s}_isFatalError(t){return!Xle.errno.isEnoentCodeError(t)&&!this._settings.suppressErrors}};x3.default=P3});var R3=G(Q3=>{\"use strict\";Object.defineProperty(Q3,\"__esModule\",{value:!0});var Kze=Ie(\"stream\"),Jze=zd(),zze=yQ(),Zze=EQ(),k3=class extends Zze.default{constructor(){super(...arguments),this._walkStream=zze.walkStream,this._stat=Jze.stat}dynamic(t,r){return this._walkStream(t,r)}static(t,r){let s=t.map(this._getFullEntryPath,this),a=new Kze.PassThrough({objectMode:!0});a._write=(n,c,f)=>this._getEntry(s[n],t[n],r).then(p=>{p!==null&&r.entryFilter(p)&&a.push(p),n===s.length-1&&a.end(),f()}).catch(f);for(let n=0;n<s.length;n++)a.write(n);return a}_getEntry(t,r,s){return this._getStat(t).then(a=>this._makeEntry(a,r)).catch(a=>{if(s.errorFilter(a))return null;throw a})}_getStat(t){return new Promise((r,s)=>{this._stat(t,this._fsStatSettings,(a,n)=>a===null?r(n):s(a))})}};Q3.default=k3});var $le=G(F3=>{\"use strict\";Object.defineProperty(F3,\"__esModule\",{value:!0});var Xze=yQ(),$ze=EQ(),eZe=R3(),T3=class extends $ze.default{constructor(){super(...arguments),this._walkAsync=Xze.walk,this._readerStream=new eZe.default(this._settings)}dynamic(t,r){return new Promise((s,a)=>{this._walkAsync(t,r,(n,c)=>{n===null?s(c):a(n)})})}async static(t,r){let s=[],a=this._readerStream.static(t,r);return new Promise((n,c)=>{a.once(\"error\",c),a.on(\"data\",f=>s.push(f)),a.once(\"end\",()=>n(s))})}};F3.default=T3});var ece=G(O3=>{\"use strict\";Object.defineProperty(O3,\"__esModule\",{value:!0});var b2=kp(),N3=class{constructor(t,r,s){this._patterns=t,this._settings=r,this._micromatchOptions=s,this._storage=[],this._fillStorage()}_fillStorage(){for(let t of this._patterns){let r=this._getPatternSegments(t),s=this._splitSegmentsIntoSections(r);this._storage.push({complete:s.length<=1,pattern:t,segments:r,sections:s})}}_getPatternSegments(t){return b2.pattern.getPatternParts(t,this._micromatchOptions).map(s=>b2.pattern.isDynamicPattern(s,this._settings)?{dynamic:!0,pattern:s,patternRe:b2.pattern.makeRe(s,this._micromatchOptions)}:{dynamic:!1,pattern:s})}_splitSegmentsIntoSections(t){return b2.array.splitWhen(t,r=>r.dynamic&&b2.pattern.hasGlobStar(r.pattern))}};O3.default=N3});var tce=G(M3=>{\"use strict\";Object.defineProperty(M3,\"__esModule\",{value:!0});var tZe=ece(),L3=class extends tZe.default{match(t){let r=t.split(\"/\"),s=r.length,a=this._storage.filter(n=>!n.complete||n.segments.length>s);for(let n of a){let c=n.sections[0];if(!n.complete&&s>c.length||r.every((p,h)=>{let E=n.segments[h];return!!(E.dynamic&&E.patternRe.test(p)||!E.dynamic&&E.pattern===p)}))return!0}return!1}};M3.default=L3});var rce=G(_3=>{\"use strict\";Object.defineProperty(_3,\"__esModule\",{value:!0});var IQ=kp(),rZe=tce(),U3=class{constructor(t,r){this._settings=t,this._micromatchOptions=r}getFilter(t,r,s){let a=this._getMatcher(r),n=this._getNegativePatternsRe(s);return c=>this._filter(t,c,a,n)}_getMatcher(t){return new rZe.default(t,this._settings,this._micromatchOptions)}_getNegativePatternsRe(t){let r=t.filter(IQ.pattern.isAffectDepthOfReadingPattern);return IQ.pattern.convertPatternsToRe(r,this._micromatchOptions)}_filter(t,r,s,a){if(this._isSkippedByDeep(t,r.path)||this._isSkippedSymbolicLink(r))return!1;let n=IQ.path.removeLeadingDotSegment(r.path);return this._isSkippedByPositivePatterns(n,s)?!1:this._isSkippedByNegativePatterns(n,a)}_isSkippedByDeep(t,r){return this._settings.deep===1/0?!1:this._getEntryLevel(t,r)>=this._settings.deep}_getEntryLevel(t,r){let s=r.split(\"/\").length;if(t===\"\")return s;let a=t.split(\"/\").length;return s-a}_isSkippedSymbolicLink(t){return!this._settings.followSymbolicLinks&&t.dirent.isSymbolicLink()}_isSkippedByPositivePatterns(t,r){return!this._settings.baseNameMatch&&!r.match(t)}_isSkippedByNegativePatterns(t,r){return!IQ.pattern.matchAny(t,r)}};_3.default=U3});var nce=G(j3=>{\"use strict\";Object.defineProperty(j3,\"__esModule\",{value:!0});var Zd=kp(),H3=class{constructor(t,r){this._settings=t,this._micromatchOptions=r,this.index=new Map}getFilter(t,r){let s=Zd.pattern.convertPatternsToRe(t,this._micromatchOptions),a=Zd.pattern.convertPatternsToRe(r,Object.assign(Object.assign({},this._micromatchOptions),{dot:!0}));return n=>this._filter(n,s,a)}_filter(t,r,s){let a=Zd.path.removeLeadingDotSegment(t.path);if(this._settings.unique&&this._isDuplicateEntry(a)||this._onlyFileFilter(t)||this._onlyDirectoryFilter(t)||this._isSkippedByAbsoluteNegativePatterns(a,s))return!1;let n=t.dirent.isDirectory(),c=this._isMatchToPatterns(a,r,n)&&!this._isMatchToPatterns(a,s,n);return this._settings.unique&&c&&this._createIndexRecord(a),c}_isDuplicateEntry(t){return this.index.has(t)}_createIndexRecord(t){this.index.set(t,void 0)}_onlyFileFilter(t){return this._settings.onlyFiles&&!t.dirent.isFile()}_onlyDirectoryFilter(t){return this._settings.onlyDirectories&&!t.dirent.isDirectory()}_isSkippedByAbsoluteNegativePatterns(t,r){if(!this._settings.absolute)return!1;let s=Zd.path.makeAbsolute(this._settings.cwd,t);return Zd.pattern.matchAny(s,r)}_isMatchToPatterns(t,r,s){let a=Zd.pattern.matchAny(t,r);return!a&&s?Zd.pattern.matchAny(t+\"/\",r):a}};j3.default=H3});var ice=G(q3=>{\"use strict\";Object.defineProperty(q3,\"__esModule\",{value:!0});var nZe=kp(),G3=class{constructor(t){this._settings=t}getFilter(){return t=>this._isNonFatalError(t)}_isNonFatalError(t){return nZe.errno.isEnoentCodeError(t)||this._settings.suppressErrors}};q3.default=G3});var oce=G(V3=>{\"use strict\";Object.defineProperty(V3,\"__esModule\",{value:!0});var sce=kp(),W3=class{constructor(t){this._settings=t}getTransformer(){return t=>this._transform(t)}_transform(t){let r=t.path;return this._settings.absolute&&(r=sce.path.makeAbsolute(this._settings.cwd,r),r=sce.path.unixify(r)),this._settings.markDirectories&&t.dirent.isDirectory()&&(r+=\"/\"),this._settings.objectMode?Object.assign(Object.assign({},t),{path:r}):r}};V3.default=W3});var CQ=G(K3=>{\"use strict\";Object.defineProperty(K3,\"__esModule\",{value:!0});var iZe=Ie(\"path\"),sZe=rce(),oZe=nce(),aZe=ice(),lZe=oce(),Y3=class{constructor(t){this._settings=t,this.errorFilter=new aZe.default(this._settings),this.entryFilter=new oZe.default(this._settings,this._getMicromatchOptions()),this.deepFilter=new sZe.default(this._settings,this._getMicromatchOptions()),this.entryTransformer=new lZe.default(this._settings)}_getRootDirectory(t){return iZe.resolve(this._settings.cwd,t.base)}_getReaderOptions(t){let r=t.base===\".\"?\"\":t.base;return{basePath:r,pathSegmentSeparator:\"/\",concurrency:this._settings.concurrency,deepFilter:this.deepFilter.getFilter(r,t.positive,t.negative),entryFilter:this.entryFilter.getFilter(t.positive,t.negative),errorFilter:this.errorFilter.getFilter(),followSymbolicLinks:this._settings.followSymbolicLinks,fs:this._settings.fs,stats:this._settings.stats,throwErrorOnBrokenSymbolicLink:this._settings.throwErrorOnBrokenSymbolicLink,transform:this.entryTransformer.getTransformer()}}_getMicromatchOptions(){return{dot:this._settings.dot,matchBase:this._settings.baseNameMatch,nobrace:!this._settings.braceExpansion,nocase:!this._settings.caseSensitiveMatch,noext:!this._settings.extglob,noglobstar:!this._settings.globstar,posix:!0,strictSlashes:!1}}};K3.default=Y3});var ace=G(z3=>{\"use strict\";Object.defineProperty(z3,\"__esModule\",{value:!0});var cZe=$le(),uZe=CQ(),J3=class extends uZe.default{constructor(){super(...arguments),this._reader=new cZe.default(this._settings)}async read(t){let r=this._getRootDirectory(t),s=this._getReaderOptions(t);return(await this.api(r,t,s)).map(n=>s.transform(n))}api(t,r,s){return r.dynamic?this._reader.dynamic(t,s):this._reader.static(r.patterns,s)}};z3.default=J3});var lce=G(X3=>{\"use strict\";Object.defineProperty(X3,\"__esModule\",{value:!0});var fZe=Ie(\"stream\"),AZe=R3(),pZe=CQ(),Z3=class extends pZe.default{constructor(){super(...arguments),this._reader=new AZe.default(this._settings)}read(t){let r=this._getRootDirectory(t),s=this._getReaderOptions(t),a=this.api(r,t,s),n=new fZe.Readable({objectMode:!0,read:()=>{}});return a.once(\"error\",c=>n.emit(\"error\",c)).on(\"data\",c=>n.emit(\"data\",s.transform(c))).once(\"end\",()=>n.emit(\"end\")),n.once(\"close\",()=>a.destroy()),n}api(t,r,s){return r.dynamic?this._reader.dynamic(t,s):this._reader.static(r.patterns,s)}};X3.default=Z3});var cce=G(e8=>{\"use strict\";Object.defineProperty(e8,\"__esModule\",{value:!0});var hZe=zd(),gZe=yQ(),dZe=EQ(),$3=class extends dZe.default{constructor(){super(...arguments),this._walkSync=gZe.walkSync,this._statSync=hZe.statSync}dynamic(t,r){return this._walkSync(t,r)}static(t,r){let s=[];for(let a of t){let n=this._getFullEntryPath(a),c=this._getEntry(n,a,r);c===null||!r.entryFilter(c)||s.push(c)}return s}_getEntry(t,r,s){try{let a=this._getStat(t);return this._makeEntry(a,r)}catch(a){if(s.errorFilter(a))return null;throw a}}_getStat(t){return this._statSync(t,this._fsStatSettings)}};e8.default=$3});var uce=G(r8=>{\"use strict\";Object.defineProperty(r8,\"__esModule\",{value:!0});var mZe=cce(),yZe=CQ(),t8=class extends yZe.default{constructor(){super(...arguments),this._reader=new mZe.default(this._settings)}read(t){let r=this._getRootDirectory(t),s=this._getReaderOptions(t);return this.api(r,t,s).map(s.transform)}api(t,r,s){return r.dynamic?this._reader.dynamic(t,s):this._reader.static(r.patterns,s)}};r8.default=t8});var fce=G(nI=>{\"use strict\";Object.defineProperty(nI,\"__esModule\",{value:!0});nI.DEFAULT_FILE_SYSTEM_ADAPTER=void 0;var rI=Ie(\"fs\"),EZe=Ie(\"os\"),IZe=Math.max(EZe.cpus().length,1);nI.DEFAULT_FILE_SYSTEM_ADAPTER={lstat:rI.lstat,lstatSync:rI.lstatSync,stat:rI.stat,statSync:rI.statSync,readdir:rI.readdir,readdirSync:rI.readdirSync};var n8=class{constructor(t={}){this._options=t,this.absolute=this._getValue(this._options.absolute,!1),this.baseNameMatch=this._getValue(this._options.baseNameMatch,!1),this.braceExpansion=this._getValue(this._options.braceExpansion,!0),this.caseSensitiveMatch=this._getValue(this._options.caseSensitiveMatch,!0),this.concurrency=this._getValue(this._options.concurrency,IZe),this.cwd=this._getValue(this._options.cwd,process.cwd()),this.deep=this._getValue(this._options.deep,1/0),this.dot=this._getValue(this._options.dot,!1),this.extglob=this._getValue(this._options.extglob,!0),this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!0),this.fs=this._getFileSystemMethods(this._options.fs),this.globstar=this._getValue(this._options.globstar,!0),this.ignore=this._getValue(this._options.ignore,[]),this.markDirectories=this._getValue(this._options.markDirectories,!1),this.objectMode=this._getValue(this._options.objectMode,!1),this.onlyDirectories=this._getValue(this._options.onlyDirectories,!1),this.onlyFiles=this._getValue(this._options.onlyFiles,!0),this.stats=this._getValue(this._options.stats,!1),this.suppressErrors=this._getValue(this._options.suppressErrors,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!1),this.unique=this._getValue(this._options.unique,!0),this.onlyDirectories&&(this.onlyFiles=!1),this.stats&&(this.objectMode=!0),this.ignore=[].concat(this.ignore)}_getValue(t,r){return t===void 0?r:t}_getFileSystemMethods(t={}){return Object.assign(Object.assign({},nI.DEFAULT_FILE_SYSTEM_ADAPTER),t)}};nI.default=n8});var wQ=G((sNt,pce)=>{\"use strict\";var Ace=ple(),CZe=ace(),wZe=lce(),BZe=uce(),i8=fce(),Rc=kp();async function s8(e,t){_u(e);let r=o8(e,CZe.default,t),s=await Promise.all(r);return Rc.array.flatten(s)}(function(e){e.glob=e,e.globSync=t,e.globStream=r,e.async=e;function t(h,E){_u(h);let C=o8(h,BZe.default,E);return Rc.array.flatten(C)}e.sync=t;function r(h,E){_u(h);let C=o8(h,wZe.default,E);return Rc.stream.merge(C)}e.stream=r;function s(h,E){_u(h);let C=[].concat(h),S=new i8.default(E);return Ace.generate(C,S)}e.generateTasks=s;function a(h,E){_u(h);let C=new i8.default(E);return Rc.pattern.isDynamicPattern(h,C)}e.isDynamicPattern=a;function n(h){return _u(h),Rc.path.escape(h)}e.escapePath=n;function c(h){return _u(h),Rc.path.convertPathToPattern(h)}e.convertPathToPattern=c;let f;(function(h){function E(S){return _u(S),Rc.path.escapePosixPath(S)}h.escapePath=E;function C(S){return _u(S),Rc.path.convertPosixPathToPattern(S)}h.convertPathToPattern=C})(f=e.posix||(e.posix={}));let p;(function(h){function E(S){return _u(S),Rc.path.escapeWindowsPath(S)}h.escapePath=E;function C(S){return _u(S),Rc.path.convertWindowsPathToPattern(S)}h.convertPathToPattern=C})(p=e.win32||(e.win32={}))})(s8||(s8={}));function o8(e,t,r){let s=[].concat(e),a=new i8.default(r),n=Ace.generate(s,a),c=new t(a);return n.map(c.read,c)}function _u(e){if(![].concat(e).every(s=>Rc.string.isString(s)&&!Rc.string.isEmpty(s)))throw new TypeError(\"Patterns must be a string (non empty) or an array of strings\")}pce.exports=s8});var Ln={};Yt(Ln,{checksumFile:()=>vQ,checksumPattern:()=>SQ,makeHash:()=>fs});function fs(...e){let t=(0,BQ.createHash)(\"sha512\"),r=\"\";for(let s of e)typeof s==\"string\"?r+=s:s&&(r&&(t.update(r),r=\"\"),t.update(s));return r&&t.update(r),t.digest(\"hex\")}async function vQ(e,{baseFs:t,algorithm:r}={baseFs:le,algorithm:\"sha512\"}){let s=await t.openPromise(e,\"r\");try{let n=Buffer.allocUnsafeSlow(65536),c=(0,BQ.createHash)(r),f=0;for(;(f=await t.readPromise(s,n,0,65536))!==0;)c.update(f===65536?n:n.slice(0,f));return c.digest(\"hex\")}finally{await t.closePromise(s)}}async function SQ(e,{cwd:t}){let s=(await(0,a8.default)(e,{cwd:fe.fromPortablePath(t),onlyDirectories:!0})).map(f=>`${f}/**/*`),a=await(0,a8.default)([e,...s],{cwd:fe.fromPortablePath(t),onlyFiles:!1});a.sort();let n=await Promise.all(a.map(async f=>{let p=[Buffer.from(f)],h=K.join(t,fe.toPortablePath(f)),E=await le.lstatPromise(h);return E.isSymbolicLink()?p.push(Buffer.from(await le.readlinkPromise(h))):E.isFile()&&p.push(await le.readFilePromise(h)),p.join(\"\\0\")})),c=(0,BQ.createHash)(\"sha512\");for(let f of n)c.update(f);return c.digest(\"hex\")}var BQ,a8,y0=Ze(()=>{Dt();BQ=Ie(\"crypto\"),a8=et(wQ())});var j={};Yt(j,{allPeerRequests:()=>O2,areDescriptorsEqual:()=>yce,areIdentsEqual:()=>Q2,areLocatorsEqual:()=>R2,areVirtualPackagesEquivalent:()=>RZe,bindDescriptor:()=>kZe,bindLocator:()=>QZe,convertDescriptorToLocator:()=>DQ,convertLocatorToDescriptor:()=>c8,convertPackageToLocator:()=>bZe,convertToIdent:()=>DZe,convertToManifestRange:()=>jZe,copyPackage:()=>x2,devirtualizeDescriptor:()=>k2,devirtualizeLocator:()=>sI,ensureDevirtualizedDescriptor:()=>PZe,ensureDevirtualizedLocator:()=>xZe,getIdentVendorPath:()=>p8,isPackageCompatible:()=>QQ,isVirtualDescriptor:()=>Qp,isVirtualLocator:()=>Hu,makeDescriptor:()=>Mn,makeIdent:()=>xa,makeLocator:()=>Ks,makeRange:()=>xQ,parseDescriptor:()=>E0,parseFileStyleRange:()=>_Ze,parseIdent:()=>Pa,parseLocator:()=>Rp,parseRange:()=>Xd,prettyDependent:()=>U4,prettyDescriptor:()=>oi,prettyIdent:()=>$i,prettyLocator:()=>Vr,prettyLocatorNoColors:()=>M4,prettyRange:()=>aI,prettyReference:()=>F2,prettyResolution:()=>D2,prettyWorkspace:()=>N2,renamePackage:()=>u8,slugifyIdent:()=>l8,slugifyLocator:()=>oI,sortDescriptors:()=>lI,stringifyDescriptor:()=>hl,stringifyIdent:()=>fn,stringifyLocator:()=>gl,tryParseDescriptor:()=>T2,tryParseIdent:()=>Ece,tryParseLocator:()=>PQ,tryParseRange:()=>UZe,unwrapIdentFromScope:()=>qZe,virtualizeDescriptor:()=>f8,virtualizePackage:()=>A8,wrapIdentIntoScope:()=>GZe});function xa(e,t){if(e?.startsWith(\"@\"))throw new Error(\"Invalid scope: don't prefix it with '@'\");return{identHash:fs(e,t),scope:e,name:t}}function Mn(e,t){return{identHash:e.identHash,scope:e.scope,name:e.name,descriptorHash:fs(e.identHash,t),range:t}}function Ks(e,t){return{identHash:e.identHash,scope:e.scope,name:e.name,locatorHash:fs(e.identHash,t),reference:t}}function DZe(e){return{identHash:e.identHash,scope:e.scope,name:e.name}}function DQ(e){return{identHash:e.identHash,scope:e.scope,name:e.name,locatorHash:e.descriptorHash,reference:e.range}}function c8(e){return{identHash:e.identHash,scope:e.scope,name:e.name,descriptorHash:e.locatorHash,range:e.reference}}function bZe(e){return{identHash:e.identHash,scope:e.scope,name:e.name,locatorHash:e.locatorHash,reference:e.reference}}function u8(e,t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.locatorHash,reference:t.reference,version:e.version,languageName:e.languageName,linkType:e.linkType,conditions:e.conditions,dependencies:new Map(e.dependencies),peerDependencies:new Map(e.peerDependencies),dependenciesMeta:new Map(e.dependenciesMeta),peerDependenciesMeta:new Map(e.peerDependenciesMeta),bin:new Map(e.bin)}}function x2(e){return u8(e,e)}function f8(e,t){if(t.includes(\"#\"))throw new Error(\"Invalid entropy\");return Mn(e,`virtual:${t}#${e.range}`)}function A8(e,t){if(t.includes(\"#\"))throw new Error(\"Invalid entropy\");return u8(e,Ks(e,`virtual:${t}#${e.reference}`))}function Qp(e){return e.range.startsWith(P2)}function Hu(e){return e.reference.startsWith(P2)}function k2(e){if(!Qp(e))throw new Error(\"Not a virtual descriptor\");return Mn(e,e.range.replace(bQ,\"\"))}function sI(e){if(!Hu(e))throw new Error(\"Not a virtual descriptor\");return Ks(e,e.reference.replace(bQ,\"\"))}function PZe(e){return Qp(e)?Mn(e,e.range.replace(bQ,\"\")):e}function xZe(e){return Hu(e)?Ks(e,e.reference.replace(bQ,\"\")):e}function kZe(e,t){return e.range.includes(\"::\")?e:Mn(e,`${e.range}::${iI.default.stringify(t)}`)}function QZe(e,t){return e.reference.includes(\"::\")?e:Ks(e,`${e.reference}::${iI.default.stringify(t)}`)}function Q2(e,t){return e.identHash===t.identHash}function yce(e,t){return e.descriptorHash===t.descriptorHash}function R2(e,t){return e.locatorHash===t.locatorHash}function RZe(e,t){if(!Hu(e))throw new Error(\"Invalid package type\");if(!Hu(t))throw new Error(\"Invalid package type\");if(!Q2(e,t)||e.dependencies.size!==t.dependencies.size)return!1;for(let r of e.dependencies.values()){let s=t.dependencies.get(r.identHash);if(!s||!yce(r,s))return!1}return!0}function Pa(e){let t=Ece(e);if(!t)throw new Error(`Invalid ident (${e})`);return t}function Ece(e){let t=e.match(TZe);if(!t)return null;let[,r,s]=t;return xa(typeof r<\"u\"?r:null,s)}function E0(e,t=!1){let r=T2(e,t);if(!r)throw new Error(`Invalid descriptor (${e})`);return r}function T2(e,t=!1){let r=t?e.match(FZe):e.match(NZe);if(!r)return null;let[,s,a,n]=r;if(n===\"unknown\")throw new Error(`Invalid range (${e})`);let c=typeof s<\"u\"?s:null,f=typeof n<\"u\"?n:\"unknown\";return Mn(xa(c,a),f)}function Rp(e,t=!1){let r=PQ(e,t);if(!r)throw new Error(`Invalid locator (${e})`);return r}function PQ(e,t=!1){let r=t?e.match(OZe):e.match(LZe);if(!r)return null;let[,s,a,n]=r;if(n===\"unknown\")throw new Error(`Invalid reference (${e})`);let c=typeof s<\"u\"?s:null,f=typeof n<\"u\"?n:\"unknown\";return Ks(xa(c,a),f)}function Xd(e,t){let r=e.match(MZe);if(r===null)throw new Error(`Invalid range (${e})`);let s=typeof r[1]<\"u\"?r[1]:null;if(typeof t?.requireProtocol==\"string\"&&s!==t.requireProtocol)throw new Error(`Invalid protocol (${s})`);if(t?.requireProtocol&&s===null)throw new Error(`Missing protocol (${s})`);let a=typeof r[3]<\"u\"?decodeURIComponent(r[2]):null;if(t?.requireSource&&a===null)throw new Error(`Missing source (${e})`);let n=typeof r[3]<\"u\"?decodeURIComponent(r[3]):decodeURIComponent(r[2]),c=t?.parseSelector?iI.default.parse(n):n,f=typeof r[4]<\"u\"?iI.default.parse(r[4]):null;return{protocol:s,source:a,selector:c,params:f}}function UZe(e,t){try{return Xd(e,t)}catch{return null}}function _Ze(e,{protocol:t}){let{selector:r,params:s}=Xd(e,{requireProtocol:t,requireBindings:!0});if(typeof s.locator!=\"string\")throw new Error(`Assertion failed: Invalid bindings for ${e}`);return{parentLocator:Rp(s.locator,!0),path:r}}function hce(e){return e=e.replaceAll(\"%\",\"%25\"),e=e.replaceAll(\":\",\"%3A\"),e=e.replaceAll(\"#\",\"%23\"),e}function HZe(e){return e===null?!1:Object.entries(e).length>0}function xQ({protocol:e,source:t,selector:r,params:s}){let a=\"\";return e!==null&&(a+=`${e}`),t!==null&&(a+=`${hce(t)}#`),a+=hce(r),HZe(s)&&(a+=`::${iI.default.stringify(s)}`),a}function jZe(e){let{params:t,protocol:r,source:s,selector:a}=Xd(e);for(let n in t)n.startsWith(\"__\")&&delete t[n];return xQ({protocol:r,source:s,params:t,selector:a})}function fn(e){return e.scope?`@${e.scope}/${e.name}`:`${e.name}`}function GZe(e,t){return e.scope?xa(t,`${e.scope}__${e.name}`):xa(t,e.name)}function qZe(e,t){if(e.scope!==t)return e;let r=e.name.indexOf(\"__\");if(r===-1)return xa(null,e.name);let s=e.name.slice(0,r),a=e.name.slice(r+2);return xa(s,a)}function hl(e){return e.scope?`@${e.scope}/${e.name}@${e.range}`:`${e.name}@${e.range}`}function gl(e){return e.scope?`@${e.scope}/${e.name}@${e.reference}`:`${e.name}@${e.reference}`}function l8(e){return e.scope!==null?`@${e.scope}-${e.name}`:e.name}function oI(e){let{protocol:t,selector:r}=Xd(e.reference),s=t!==null?t.replace(WZe,\"\"):\"exotic\",a=gce.default.valid(r),n=a!==null?`${s}-${a}`:`${s}`,c=10;return e.scope?`${l8(e)}-${n}-${e.locatorHash.slice(0,c)}`:`${l8(e)}-${n}-${e.locatorHash.slice(0,c)}`}function $i(e,t){return t.scope?`${jt(e,`@${t.scope}/`,gt.SCOPE)}${jt(e,t.name,gt.NAME)}`:`${jt(e,t.name,gt.NAME)}`}function kQ(e){if(e.startsWith(P2)){let t=kQ(e.substring(e.indexOf(\"#\")+1)),r=e.substring(P2.length,P2.length+vZe);return`${t} [${r}]`}else return e.replace(VZe,\"?[...]\")}function aI(e,t){return`${jt(e,kQ(t),gt.RANGE)}`}function oi(e,t){return`${$i(e,t)}${jt(e,\"@\",gt.RANGE)}${aI(e,t.range)}`}function F2(e,t){return`${jt(e,kQ(t),gt.REFERENCE)}`}function Vr(e,t){return`${$i(e,t)}${jt(e,\"@\",gt.REFERENCE)}${F2(e,t.reference)}`}function M4(e){return`${fn(e)}@${kQ(e.reference)}`}function lI(e){return Ys(e,[t=>fn(t),t=>t.range])}function N2(e,t){return $i(e,t.anchoredLocator)}function D2(e,t,r){let s=Qp(t)?k2(t):t;return r===null?`${oi(e,s)} \\u2192 ${L4(e).Cross}`:s.identHash===r.identHash?`${oi(e,s)} \\u2192 ${F2(e,r.reference)}`:`${oi(e,s)} \\u2192 ${Vr(e,r)}`}function U4(e,t,r){return r===null?`${Vr(e,t)}`:`${Vr(e,t)} (via ${aI(e,r.range)})`}function p8(e){return`node_modules/${fn(e)}`}function QQ(e,t){return e.conditions?SZe(e.conditions,r=>{let[,s,a]=r.match(mce),n=t[s];return n?n.includes(a):!0}):!0}function O2(e){let t=new Set;if(\"children\"in e)t.add(e);else for(let r of e.requests.values())t.add(r);for(let r of t)for(let s of r.children.values())t.add(s);return t}var iI,gce,dce,P2,vZe,mce,SZe,bQ,TZe,FZe,NZe,OZe,LZe,MZe,WZe,VZe,Zo=Ze(()=>{iI=et(Ie(\"querystring\")),gce=et(pi()),dce=et(Mie());kc();y0();xc();Zo();P2=\"virtual:\",vZe=5,mce=/(os|cpu|libc)=([a-z0-9_-]+)/,SZe=(0,dce.makeParser)(mce);bQ=/^[^#]*#/;TZe=/^(?:@([^/]+?)\\/)?([^@/]+)$/;FZe=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))$/,NZe=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))?$/;OZe=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))$/,LZe=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))?$/;MZe=/^([^#:]*:)?((?:(?!::)[^#])*)(?:#((?:(?!::).)*))?(?:::(.*))?$/;WZe=/:$/;VZe=/\\?.*/});var Ice,Cce=Ze(()=>{Zo();Ice={hooks:{reduceDependency:(e,t,r,s,{resolver:a,resolveOptions:n})=>{for(let{pattern:c,reference:f}of t.topLevelWorkspace.manifest.resolutions){if(c.from&&(c.from.fullName!==fn(r)||t.configuration.normalizeLocator(Ks(Pa(c.from.fullName),c.from.description??r.reference)).locatorHash!==r.locatorHash)||c.descriptor.fullName!==fn(e)||t.configuration.normalizeDependency(Mn(Rp(c.descriptor.fullName),c.descriptor.description??e.range)).descriptorHash!==e.descriptorHash)continue;return a.bindDescriptor(t.configuration.normalizeDependency(Mn(e,f)),t.topLevelWorkspace.anchoredLocator,n)}return e},validateProject:async(e,t)=>{for(let r of e.workspaces){let s=N2(e.configuration,r);await e.configuration.triggerHook(a=>a.validateWorkspace,r,{reportWarning:(a,n)=>t.reportWarning(a,`${s}: ${n}`),reportError:(a,n)=>t.reportError(a,`${s}: ${n}`)})}},validateWorkspace:async(e,t)=>{let{manifest:r}=e;r.resolutions.length&&e.cwd!==e.project.cwd&&r.errors.push(new Error(\"Resolutions field will be ignored\"));for(let s of r.errors)t.reportWarning(57,s.message)}}}});var Ii,$d=Ze(()=>{Ii=class e{static{this.protocol=\"workspace:\"}supportsDescriptor(t,r){return!!(t.range.startsWith(e.protocol)||r.project.tryWorkspaceByDescriptor(t)!==null)}supportsLocator(t,r){return!!t.reference.startsWith(e.protocol)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){return[s.project.getWorkspaceByDescriptor(t).anchoredLocator]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){let s=r.project.getWorkspaceByCwd(t.reference.slice(e.protocol.length));return{...t,version:s.manifest.version||\"0.0.0\",languageName:\"unknown\",linkType:\"SOFT\",conditions:null,dependencies:r.project.configuration.normalizeDependencyMap(new Map([...s.manifest.dependencies,...s.manifest.devDependencies])),peerDependencies:new Map([...s.manifest.peerDependencies]),dependenciesMeta:s.manifest.dependenciesMeta,peerDependenciesMeta:s.manifest.peerDependenciesMeta,bin:s.manifest.bin}}}});var Fr={};Yt(Fr,{SemVer:()=>Dce.SemVer,clean:()=>KZe,getComparator:()=>vce,mergeComparators:()=>h8,satisfiesWithPrereleases:()=>eA,simplifyRanges:()=>g8,stringifyComparator:()=>Sce,validRange:()=>dl});function eA(e,t,r=!1){if(!e)return!1;let s=`${t}${r}`,a=wce.get(s);if(typeof a>\"u\")try{a=new Tp.default.Range(t,{includePrerelease:!0,loose:r})}catch{return!1}finally{wce.set(s,a||null)}else if(a===null)return!1;let n;try{n=new Tp.default.SemVer(e,a)}catch{return!1}return a.test(n)?!0:(n.prerelease&&(n.prerelease=[]),a.set.some(c=>{for(let f of c)f.semver.prerelease&&(f.semver.prerelease=[]);return c.every(f=>f.test(n))}))}function dl(e){if(e.indexOf(\":\")!==-1)return null;let t=Bce.get(e);if(typeof t<\"u\")return t;try{t=new Tp.default.Range(e)}catch{t=null}return Bce.set(e,t),t}function KZe(e){let t=YZe.exec(e);return t?t[1]:null}function vce(e){if(e.semver===Tp.default.Comparator.ANY)return{gt:null,lt:null};switch(e.operator){case\"\":return{gt:[\">=\",e.semver],lt:[\"<=\",e.semver]};case\">\":case\">=\":return{gt:[e.operator,e.semver],lt:null};case\"<\":case\"<=\":return{gt:null,lt:[e.operator,e.semver]};default:throw new Error(`Assertion failed: Unexpected comparator operator (${e.operator})`)}}function h8(e){if(e.length===0)return null;let t=null,r=null;for(let s of e){if(s.gt){let a=t!==null?Tp.default.compare(s.gt[1],t[1]):null;(a===null||a>0||a===0&&s.gt[0]===\">\")&&(t=s.gt)}if(s.lt){let a=r!==null?Tp.default.compare(s.lt[1],r[1]):null;(a===null||a<0||a===0&&s.lt[0]===\"<\")&&(r=s.lt)}}if(t&&r){let s=Tp.default.compare(t[1],r[1]);if(s===0&&(t[0]===\">\"||r[0]===\"<\")||s>0)return null}return{gt:t,lt:r}}function Sce(e){if(e.gt&&e.lt){if(e.gt[0]===\">=\"&&e.lt[0]===\"<=\"&&e.gt[1].version===e.lt[1].version)return e.gt[1].version;if(e.gt[0]===\">=\"&&e.lt[0]===\"<\"){if(e.lt[1].version===`${e.gt[1].major+1}.0.0-0`)return`^${e.gt[1].version}`;if(e.lt[1].version===`${e.gt[1].major}.${e.gt[1].minor+1}.0-0`)return`~${e.gt[1].version}`}}let t=[];return e.gt&&t.push(e.gt[0]+e.gt[1].version),e.lt&&t.push(e.lt[0]+e.lt[1].version),t.length?t.join(\" \"):\"*\"}function g8(e){let t=e.map(JZe).map(s=>dl(s).set.map(a=>a.map(n=>vce(n)))),r=t.shift().map(s=>h8(s)).filter(s=>s!==null);for(let s of t){let a=[];for(let n of r)for(let c of s){let f=h8([n,...c]);f!==null&&a.push(f)}r=a}return r.length===0?null:r.map(s=>Sce(s)).join(\" || \")}function JZe(e){let t=e.split(\"||\");if(t.length>1){let r=new Set;for(let s of t)t.some(a=>a!==s&&Tp.default.subset(s,a))||r.add(s);if(r.size<t.length)return[...r].join(\" || \")}return e}var Tp,Dce,wce,Bce,YZe,Fp=Ze(()=>{Tp=et(pi()),Dce=et(pi()),wce=new Map;Bce=new Map;YZe=/^(?:[\\sv=]*?)((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)(?:\\s*)$/});function bce(e){let t=e.match(/^[ \\t]+/m);return t?t[0]:\"  \"}function Pce(e){return e.charCodeAt(0)===65279?e.slice(1):e}function ka(e){return e.replace(/\\\\/g,\"/\")}function RQ(e,{yamlCompatibilityMode:t}){return t?k4(e):typeof e>\"u\"||typeof e==\"boolean\"?e:null}function xce(e,t){let r=t.search(/[^!]/);if(r===-1)return\"invalid\";let s=r%2===0?\"\":\"!\",a=t.slice(r);return`${s}${e}=${a}`}function d8(e,t){return t.length===1?xce(e,t[0]):`(${t.map(r=>xce(e,r)).join(\" | \")})`}var kce,Ut,cI=Ze(()=>{Dt();Bc();kce=et(pi());$d();xc();Fp();Zo();Ut=class e{constructor(){this.indent=\"  \";this.name=null;this.version=null;this.os=null;this.cpu=null;this.libc=null;this.type=null;this.packageManager=null;this.private=!1;this.license=null;this.main=null;this.module=null;this.browser=null;this.languageName=null;this.bin=new Map;this.scripts=new Map;this.dependencies=new Map;this.devDependencies=new Map;this.peerDependencies=new Map;this.workspaceDefinitions=[];this.dependenciesMeta=new Map;this.peerDependenciesMeta=new Map;this.resolutions=[];this.files=null;this.publishConfig=null;this.installConfig=null;this.preferUnplugged=null;this.raw={};this.errors=[]}static{this.fileName=\"package.json\"}static{this.allDependencies=[\"dependencies\",\"devDependencies\",\"peerDependencies\"]}static{this.hardDependencies=[\"dependencies\",\"devDependencies\"]}static async tryFind(t,{baseFs:r=new Yn}={}){let s=K.join(t,\"package.json\");try{return await e.fromFile(s,{baseFs:r})}catch(a){if(a.code===\"ENOENT\")return null;throw a}}static async find(t,{baseFs:r}={}){let s=await e.tryFind(t,{baseFs:r});if(s===null)throw new Error(\"Manifest not found\");return s}static async fromFile(t,{baseFs:r=new Yn}={}){let s=new e;return await s.loadFile(t,{baseFs:r}),s}static fromText(t){let r=new e;return r.loadFromText(t),r}loadFromText(t){let r;try{r=JSON.parse(Pce(t)||\"{}\")}catch(s){throw s.message+=` (when parsing ${t})`,s}this.load(r),this.indent=bce(t)}async loadFile(t,{baseFs:r=new Yn}){let s=await r.readFilePromise(t,\"utf8\"),a;try{a=JSON.parse(Pce(s)||\"{}\")}catch(n){throw n.message+=` (when parsing ${t})`,n}this.load(a),this.indent=bce(s)}load(t,{yamlCompatibilityMode:r=!1}={}){if(typeof t!=\"object\"||t===null)throw new Error(`Utterly invalid manifest data (${t})`);this.raw=t;let s=[];if(this.name=null,typeof t.name==\"string\")try{this.name=Pa(t.name)}catch{s.push(new Error(\"Parsing failed for the 'name' field\"))}if(typeof t.version==\"string\"?this.version=t.version:this.version=null,Array.isArray(t.os)){let n=[];this.os=n;for(let c of t.os)typeof c!=\"string\"?s.push(new Error(\"Parsing failed for the 'os' field\")):n.push(c)}else this.os=null;if(Array.isArray(t.cpu)){let n=[];this.cpu=n;for(let c of t.cpu)typeof c!=\"string\"?s.push(new Error(\"Parsing failed for the 'cpu' field\")):n.push(c)}else this.cpu=null;if(Array.isArray(t.libc)){let n=[];this.libc=n;for(let c of t.libc)typeof c!=\"string\"?s.push(new Error(\"Parsing failed for the 'libc' field\")):n.push(c)}else this.libc=null;if(typeof t.type==\"string\"?this.type=t.type:this.type=null,typeof t.packageManager==\"string\"?this.packageManager=t.packageManager:this.packageManager=null,typeof t.private==\"boolean\"?this.private=t.private:this.private=!1,typeof t.license==\"string\"?this.license=t.license:this.license=null,typeof t.languageName==\"string\"?this.languageName=t.languageName:this.languageName=null,typeof t.main==\"string\"?this.main=ka(t.main):this.main=null,typeof t.module==\"string\"?this.module=ka(t.module):this.module=null,t.browser!=null)if(typeof t.browser==\"string\")this.browser=ka(t.browser);else{this.browser=new Map;for(let[n,c]of Object.entries(t.browser))this.browser.set(ka(n),typeof c==\"string\"?ka(c):c)}else this.browser=null;if(this.bin=new Map,typeof t.bin==\"string\")t.bin.trim()===\"\"?s.push(new Error(\"Invalid bin field\")):this.name!==null?this.bin.set(this.name.name,ka(t.bin)):s.push(new Error(\"String bin field, but no attached package name\"));else if(typeof t.bin==\"object\"&&t.bin!==null)for(let[n,c]of Object.entries(t.bin)){if(typeof c!=\"string\"||c.trim()===\"\"){s.push(new Error(`Invalid bin definition for '${n}'`));continue}let f=Pa(n);this.bin.set(f.name,ka(c))}if(this.scripts=new Map,typeof t.scripts==\"object\"&&t.scripts!==null)for(let[n,c]of Object.entries(t.scripts)){if(typeof c!=\"string\"){s.push(new Error(`Invalid script definition for '${n}'`));continue}this.scripts.set(n,c)}if(this.dependencies=new Map,typeof t.dependencies==\"object\"&&t.dependencies!==null)for(let[n,c]of Object.entries(t.dependencies)){if(typeof c!=\"string\"){s.push(new Error(`Invalid dependency range for '${n}'`));continue}let f;try{f=Pa(n)}catch{s.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=Mn(f,c);this.dependencies.set(p.identHash,p)}if(this.devDependencies=new Map,typeof t.devDependencies==\"object\"&&t.devDependencies!==null)for(let[n,c]of Object.entries(t.devDependencies)){if(typeof c!=\"string\"){s.push(new Error(`Invalid dependency range for '${n}'`));continue}let f;try{f=Pa(n)}catch{s.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=Mn(f,c);this.devDependencies.set(p.identHash,p)}if(this.peerDependencies=new Map,typeof t.peerDependencies==\"object\"&&t.peerDependencies!==null)for(let[n,c]of Object.entries(t.peerDependencies)){let f;try{f=Pa(n)}catch{s.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}(typeof c!=\"string\"||!c.startsWith(Ii.protocol)&&!dl(c))&&(s.push(new Error(`Invalid dependency range for '${n}'`)),c=\"*\");let p=Mn(f,c);this.peerDependencies.set(p.identHash,p)}typeof t.workspaces==\"object\"&&t.workspaces!==null&&t.workspaces.nohoist&&s.push(new Error(\"'nohoist' is deprecated, please use 'installConfig.hoistingLimits' instead\"));let a=Array.isArray(t.workspaces)?t.workspaces:typeof t.workspaces==\"object\"&&t.workspaces!==null&&Array.isArray(t.workspaces.packages)?t.workspaces.packages:[];this.workspaceDefinitions=[];for(let n of a){if(typeof n!=\"string\"){s.push(new Error(`Invalid workspace definition for '${n}'`));continue}this.workspaceDefinitions.push({pattern:n})}if(this.dependenciesMeta=new Map,typeof t.dependenciesMeta==\"object\"&&t.dependenciesMeta!==null)for(let[n,c]of Object.entries(t.dependenciesMeta)){if(typeof c!=\"object\"||c===null){s.push(new Error(`Invalid meta field for '${n}`));continue}let f=E0(n),p=this.ensureDependencyMeta(f),h=RQ(c.built,{yamlCompatibilityMode:r});if(h===null){s.push(new Error(`Invalid built meta field for '${n}'`));continue}let E=RQ(c.optional,{yamlCompatibilityMode:r});if(E===null){s.push(new Error(`Invalid optional meta field for '${n}'`));continue}let C=RQ(c.unplugged,{yamlCompatibilityMode:r});if(C===null){s.push(new Error(`Invalid unplugged meta field for '${n}'`));continue}Object.assign(p,{built:h,optional:E,unplugged:C})}if(this.peerDependenciesMeta=new Map,typeof t.peerDependenciesMeta==\"object\"&&t.peerDependenciesMeta!==null)for(let[n,c]of Object.entries(t.peerDependenciesMeta)){if(typeof c!=\"object\"||c===null){s.push(new Error(`Invalid meta field for '${n}'`));continue}let f=E0(n),p=this.ensurePeerDependencyMeta(f),h=RQ(c.optional,{yamlCompatibilityMode:r});if(h===null){s.push(new Error(`Invalid optional meta field for '${n}'`));continue}Object.assign(p,{optional:h})}if(this.resolutions=[],typeof t.resolutions==\"object\"&&t.resolutions!==null)for(let[n,c]of Object.entries(t.resolutions)){if(typeof c!=\"string\"){s.push(new Error(`Invalid resolution entry for '${n}'`));continue}try{this.resolutions.push({pattern:px(n),reference:c})}catch(f){s.push(f);continue}}if(Array.isArray(t.files)){this.files=new Set;for(let n of t.files){if(typeof n!=\"string\"){s.push(new Error(`Invalid files entry for '${n}'`));continue}this.files.add(n)}}else this.files=null;if(typeof t.publishConfig==\"object\"&&t.publishConfig!==null){if(this.publishConfig={},typeof t.publishConfig.access==\"string\"&&(this.publishConfig.access=t.publishConfig.access),typeof t.publishConfig.main==\"string\"&&(this.publishConfig.main=ka(t.publishConfig.main)),typeof t.publishConfig.module==\"string\"&&(this.publishConfig.module=ka(t.publishConfig.module)),t.publishConfig.browser!=null)if(typeof t.publishConfig.browser==\"string\")this.publishConfig.browser=ka(t.publishConfig.browser);else{this.publishConfig.browser=new Map;for(let[n,c]of Object.entries(t.publishConfig.browser))this.publishConfig.browser.set(ka(n),typeof c==\"string\"?ka(c):c)}if(typeof t.publishConfig.registry==\"string\"&&(this.publishConfig.registry=t.publishConfig.registry),typeof t.publishConfig.provenance==\"boolean\"&&(this.publishConfig.provenance=t.publishConfig.provenance),typeof t.publishConfig.bin==\"string\")this.name!==null?this.publishConfig.bin=new Map([[this.name.name,ka(t.publishConfig.bin)]]):s.push(new Error(\"String bin field, but no attached package name\"));else if(typeof t.publishConfig.bin==\"object\"&&t.publishConfig.bin!==null){this.publishConfig.bin=new Map;for(let[n,c]of Object.entries(t.publishConfig.bin)){if(typeof c!=\"string\"){s.push(new Error(`Invalid bin definition for '${n}'`));continue}this.publishConfig.bin.set(n,ka(c))}}if(Array.isArray(t.publishConfig.executableFiles)){this.publishConfig.executableFiles=new Set;for(let n of t.publishConfig.executableFiles){if(typeof n!=\"string\"){s.push(new Error(\"Invalid executable file definition\"));continue}this.publishConfig.executableFiles.add(ka(n))}}}else this.publishConfig=null;if(typeof t.installConfig==\"object\"&&t.installConfig!==null){this.installConfig={};for(let n of Object.keys(t.installConfig))n===\"hoistingLimits\"?typeof t.installConfig.hoistingLimits==\"string\"?this.installConfig.hoistingLimits=t.installConfig.hoistingLimits:s.push(new Error(\"Invalid hoisting limits definition\")):n==\"selfReferences\"?typeof t.installConfig.selfReferences==\"boolean\"?this.installConfig.selfReferences=t.installConfig.selfReferences:s.push(new Error(\"Invalid selfReferences definition, must be a boolean value\")):s.push(new Error(`Unrecognized installConfig key: ${n}`))}else this.installConfig=null;if(typeof t.optionalDependencies==\"object\"&&t.optionalDependencies!==null)for(let[n,c]of Object.entries(t.optionalDependencies)){if(typeof c!=\"string\"){s.push(new Error(`Invalid dependency range for '${n}'`));continue}let f;try{f=Pa(n)}catch{s.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=Mn(f,c);this.dependencies.set(p.identHash,p);let h=Mn(f,\"unknown\"),E=this.ensureDependencyMeta(h);Object.assign(E,{optional:!0})}typeof t.preferUnplugged==\"boolean\"?this.preferUnplugged=t.preferUnplugged:this.preferUnplugged=null,this.errors=s}getForScope(t){switch(t){case\"dependencies\":return this.dependencies;case\"devDependencies\":return this.devDependencies;case\"peerDependencies\":return this.peerDependencies;default:throw new Error(`Unsupported value (\"${t}\")`)}}hasConsumerDependency(t){return!!(this.dependencies.has(t.identHash)||this.peerDependencies.has(t.identHash))}hasHardDependency(t){return!!(this.dependencies.has(t.identHash)||this.devDependencies.has(t.identHash))}hasSoftDependency(t){return!!this.peerDependencies.has(t.identHash)}hasDependency(t){return!!(this.hasHardDependency(t)||this.hasSoftDependency(t))}getConditions(){let t=[];return this.os&&this.os.length>0&&t.push(d8(\"os\",this.os)),this.cpu&&this.cpu.length>0&&t.push(d8(\"cpu\",this.cpu)),this.libc&&this.libc.length>0&&t.push(d8(\"libc\",this.libc)),t.length>0?t.join(\" & \"):null}ensureDependencyMeta(t){if(t.range!==\"unknown\"&&!kce.default.valid(t.range))throw new Error(`Invalid meta field range for '${hl(t)}'`);let r=fn(t),s=t.range!==\"unknown\"?t.range:null,a=this.dependenciesMeta.get(r);a||this.dependenciesMeta.set(r,a=new Map);let n=a.get(s);return n||a.set(s,n={}),n}ensurePeerDependencyMeta(t){if(t.range!==\"unknown\")throw new Error(`Invalid meta field range for '${hl(t)}'`);let r=fn(t),s=this.peerDependenciesMeta.get(r);return s||this.peerDependenciesMeta.set(r,s={}),s}setRawField(t,r,{after:s=[]}={}){let a=new Set(s.filter(n=>Object.hasOwn(this.raw,n)));if(a.size===0||Object.hasOwn(this.raw,t))this.raw[t]=r;else{let n=this.raw,c=this.raw={},f=!1;for(let p of Object.keys(n))c[p]=n[p],f||(a.delete(p),a.size===0&&(c[t]=r,f=!0))}}exportTo(t,{compatibilityMode:r=!0}={}){if(Object.assign(t,this.raw),this.name!==null?t.name=fn(this.name):delete t.name,this.version!==null?t.version=this.version:delete t.version,this.os!==null?t.os=this.os:delete t.os,this.cpu!==null?t.cpu=this.cpu:delete t.cpu,this.type!==null?t.type=this.type:delete t.type,this.packageManager!==null?t.packageManager=this.packageManager:delete t.packageManager,this.private?t.private=!0:delete t.private,this.license!==null?t.license=this.license:delete t.license,this.languageName!==null?t.languageName=this.languageName:delete t.languageName,this.main!==null?t.main=this.main:delete t.main,this.module!==null?t.module=this.module:delete t.module,this.browser!==null){let n=this.browser;typeof n==\"string\"?t.browser=n:n instanceof Map&&(t.browser=Object.assign({},...Array.from(n.keys()).sort().map(c=>({[c]:n.get(c)}))))}else delete t.browser;this.bin.size===1&&this.name!==null&&this.bin.has(this.name.name)?t.bin=this.bin.get(this.name.name):this.bin.size>0?t.bin=Object.assign({},...Array.from(this.bin.keys()).sort().map(n=>({[n]:this.bin.get(n)}))):delete t.bin,this.workspaceDefinitions.length>0?this.raw.workspaces&&!Array.isArray(this.raw.workspaces)?t.workspaces={...this.raw.workspaces,packages:this.workspaceDefinitions.map(({pattern:n})=>n)}:t.workspaces=this.workspaceDefinitions.map(({pattern:n})=>n):this.raw.workspaces&&!Array.isArray(this.raw.workspaces)&&Object.keys(this.raw.workspaces).length>0?t.workspaces=this.raw.workspaces:delete t.workspaces;let s=[],a=[];for(let n of this.dependencies.values()){let c=this.dependenciesMeta.get(fn(n)),f=!1;if(r&&c){let p=c.get(null);p&&p.optional&&(f=!0)}f?a.push(n):s.push(n)}s.length>0?t.dependencies=Object.assign({},...lI(s).map(n=>({[fn(n)]:n.range}))):delete t.dependencies,a.length>0?t.optionalDependencies=Object.assign({},...lI(a).map(n=>({[fn(n)]:n.range}))):delete t.optionalDependencies,this.devDependencies.size>0?t.devDependencies=Object.assign({},...lI(this.devDependencies.values()).map(n=>({[fn(n)]:n.range}))):delete t.devDependencies,this.peerDependencies.size>0?t.peerDependencies=Object.assign({},...lI(this.peerDependencies.values()).map(n=>({[fn(n)]:n.range}))):delete t.peerDependencies,t.dependenciesMeta={};for(let[n,c]of Ys(this.dependenciesMeta.entries(),([f,p])=>f))for(let[f,p]of Ys(c.entries(),([h,E])=>h!==null?`0${h}`:\"1\")){let h=f!==null?hl(Mn(Pa(n),f)):n,E={...p};r&&f===null&&delete E.optional,Object.keys(E).length!==0&&(t.dependenciesMeta[h]=E)}if(Object.keys(t.dependenciesMeta).length===0&&delete t.dependenciesMeta,this.peerDependenciesMeta.size>0?t.peerDependenciesMeta=Object.assign({},...Ys(this.peerDependenciesMeta.entries(),([n,c])=>n).map(([n,c])=>({[n]:c}))):delete t.peerDependenciesMeta,this.resolutions.length>0?t.resolutions=Object.assign({},...this.resolutions.map(({pattern:n,reference:c})=>({[hx(n)]:c}))):delete t.resolutions,this.files!==null?t.files=Array.from(this.files):delete t.files,this.preferUnplugged!==null?t.preferUnplugged=this.preferUnplugged:delete t.preferUnplugged,this.scripts!==null&&this.scripts.size>0){t.scripts??={};for(let n of Object.keys(t.scripts))this.scripts.has(n)||delete t.scripts[n];for(let[n,c]of this.scripts.entries())t.scripts[n]=c}else delete t.scripts;return t}}});function ZZe(e){return typeof e.reportCode<\"u\"}var Qce,Rce,zZe,_t,yo,Tc=Ze(()=>{Jl();Qce=Ie(\"stream\"),Rce=Ie(\"string_decoder\"),zZe=15,_t=class extends Error{constructor(r,s,a){super(s);this.reportExtra=a;this.reportCode=r}};yo=class{constructor(){this.cacheHits=new Set;this.cacheMisses=new Set;this.reportedInfos=new Set;this.reportedWarnings=new Set;this.reportedErrors=new Set}getRecommendedLength(){return 180}reportCacheHit(t){this.cacheHits.add(t.locatorHash)}reportCacheMiss(t,r){this.cacheMisses.add(t.locatorHash)}static progressViaCounter(t){let r=0,s,a=new Promise(p=>{s=p}),n=p=>{let h=s;a=new Promise(E=>{s=E}),r=p,h()},c=(p=0)=>{n(r+1)},f=async function*(){for(;r<t;)await a,yield{progress:r/t}}();return{[Symbol.asyncIterator](){return f},hasProgress:!0,hasTitle:!1,set:n,tick:c}}static progressViaTitle(){let t,r,s=new Promise(c=>{r=c}),a=g4(c=>{let f=r;s=new Promise(p=>{r=p}),t=c,f()},1e3/zZe),n=async function*(){for(;;)await s,yield{title:t}}();return{[Symbol.asyncIterator](){return n},hasProgress:!1,hasTitle:!0,setTitle:a}}async startProgressPromise(t,r){let s=this.reportProgress(t);try{return await r(t)}finally{s.stop()}}startProgressSync(t,r){let s=this.reportProgress(t);try{return r(t)}finally{s.stop()}}reportInfoOnce(t,r,s){let a=s&&s.key?s.key:r;this.reportedInfos.has(a)||(this.reportedInfos.add(a),this.reportInfo(t,r),s?.reportExtra?.(this))}reportWarningOnce(t,r,s){let a=s&&s.key?s.key:r;this.reportedWarnings.has(a)||(this.reportedWarnings.add(a),this.reportWarning(t,r),s?.reportExtra?.(this))}reportErrorOnce(t,r,s){let a=s&&s.key?s.key:r;this.reportedErrors.has(a)||(this.reportedErrors.add(a),this.reportError(t,r),s?.reportExtra?.(this))}reportExceptionOnce(t){ZZe(t)?this.reportErrorOnce(t.reportCode,t.message,{key:t,reportExtra:t.reportExtra}):this.reportErrorOnce(1,t.stack||t.message,{key:t})}createStreamReporter(t=null){let r=new Qce.PassThrough,s=new Rce.StringDecoder,a=\"\";return r.on(\"data\",n=>{let c=s.write(n),f;do if(f=c.indexOf(`\n`),f!==-1){let p=a+c.substring(0,f);c=c.substring(f+1),a=\"\",t!==null?this.reportInfo(null,`${t} ${p}`):this.reportInfo(null,p)}while(f!==-1);a+=c}),r.on(\"end\",()=>{let n=s.end();n!==\"\"&&(t!==null?this.reportInfo(null,`${t} ${n}`):this.reportInfo(null,n))}),r}}});var uI,m8=Ze(()=>{Tc();Zo();uI=class{constructor(t){this.fetchers=t}supports(t,r){return!!this.tryFetcher(t,r)}getLocalPath(t,r){return this.getFetcher(t,r).getLocalPath(t,r)}async fetch(t,r){return await this.getFetcher(t,r).fetch(t,r)}tryFetcher(t,r){let s=this.fetchers.find(a=>a.supports(t,r));return s||null}getFetcher(t,r){let s=this.fetchers.find(a=>a.supports(t,r));if(!s)throw new _t(11,`${Vr(r.project.configuration,t)} isn't supported by any available fetcher`);return s}}});var em,y8=Ze(()=>{Zo();em=class{constructor(t){this.resolvers=t.filter(r=>r)}supportsDescriptor(t,r){return!!this.tryResolverByDescriptor(t,r)}supportsLocator(t,r){return!!this.tryResolverByLocator(t,r)}shouldPersistResolution(t,r){return this.getResolverByLocator(t,r).shouldPersistResolution(t,r)}bindDescriptor(t,r,s){return this.getResolverByDescriptor(t,s).bindDescriptor(t,r,s)}getResolutionDependencies(t,r){return this.getResolverByDescriptor(t,r).getResolutionDependencies(t,r)}async getCandidates(t,r,s){return await this.getResolverByDescriptor(t,s).getCandidates(t,r,s)}async getSatisfying(t,r,s,a){return this.getResolverByDescriptor(t,a).getSatisfying(t,r,s,a)}async resolve(t,r){return await this.getResolverByLocator(t,r).resolve(t,r)}tryResolverByDescriptor(t,r){let s=this.resolvers.find(a=>a.supportsDescriptor(t,r));return s||null}getResolverByDescriptor(t,r){let s=this.resolvers.find(a=>a.supportsDescriptor(t,r));if(!s)throw new Error(`${oi(r.project.configuration,t)} isn't supported by any available resolver`);return s}tryResolverByLocator(t,r){let s=this.resolvers.find(a=>a.supportsLocator(t,r));return s||null}getResolverByLocator(t,r){let s=this.resolvers.find(a=>a.supportsLocator(t,r));if(!s)throw new Error(`${Vr(r.project.configuration,t)} isn't supported by any available resolver`);return s}}});var fI,E8=Ze(()=>{Dt();Zo();fI=class{supports(t){return!!t.reference.startsWith(\"virtual:\")}getLocalPath(t,r){let s=t.reference.indexOf(\"#\");if(s===-1)throw new Error(\"Invalid virtual package reference\");let a=t.reference.slice(s+1),n=Ks(t,a);return r.fetcher.getLocalPath(n,r)}async fetch(t,r){let s=t.reference.indexOf(\"#\");if(s===-1)throw new Error(\"Invalid virtual package reference\");let a=t.reference.slice(s+1),n=Ks(t,a),c=await r.fetcher.fetch(n,r);return await this.ensureVirtualLink(t,c,r)}getLocatorFilename(t){return oI(t)}async ensureVirtualLink(t,r,s){let a=r.packageFs.getRealPath(),n=s.project.configuration.get(\"virtualFolder\"),c=this.getLocatorFilename(t),f=mo.makeVirtualPath(n,c,a),p=new jf(f,{baseFs:r.packageFs,pathUtils:K});return{...r,packageFs:p}}}});var TQ,Tce=Ze(()=>{TQ=class e{static{this.protocol=\"virtual:\"}static isVirtualDescriptor(t){return!!t.range.startsWith(e.protocol)}static isVirtualLocator(t){return!!t.reference.startsWith(e.protocol)}supportsDescriptor(t,r){return e.isVirtualDescriptor(t)}supportsLocator(t,r){return e.isVirtualLocator(t)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){throw new Error('Assertion failed: calling \"bindDescriptor\" on a virtual descriptor is unsupported')}getResolutionDependencies(t,r){throw new Error('Assertion failed: calling \"getResolutionDependencies\" on a virtual descriptor is unsupported')}async getCandidates(t,r,s){throw new Error('Assertion failed: calling \"getCandidates\" on a virtual descriptor is unsupported')}async getSatisfying(t,r,s,a){throw new Error('Assertion failed: calling \"getSatisfying\" on a virtual descriptor is unsupported')}async resolve(t,r){throw new Error('Assertion failed: calling \"resolve\" on a virtual locator is unsupported')}}});var AI,I8=Ze(()=>{Dt();$d();AI=class{supports(t){return!!t.reference.startsWith(Ii.protocol)}getLocalPath(t,r){return this.getWorkspace(t,r).cwd}async fetch(t,r){let s=this.getWorkspace(t,r).cwd;return{packageFs:new bn(s),prefixPath:vt.dot,localPath:s}}getWorkspace(t,r){return r.project.getWorkspaceByCwd(t.reference.slice(Ii.protocol.length))}}});function L2(e){return typeof e==\"object\"&&e!==null&&!Array.isArray(e)}function Fce(e){return typeof e>\"u\"?3:L2(e)?0:Array.isArray(e)?1:2}function B8(e,t){return Object.hasOwn(e,t)}function $Ze(e){return L2(e)&&B8(e,\"onConflict\")&&typeof e.onConflict==\"string\"}function eXe(e){if(typeof e>\"u\")return{onConflict:\"default\",value:e};if(!$Ze(e))return{onConflict:\"default\",value:e};if(B8(e,\"value\"))return e;let{onConflict:t,...r}=e;return{onConflict:t,value:r}}function Nce(e,t){let r=L2(e)&&B8(e,t)?e[t]:void 0;return eXe(r)}function pI(e,t){return[e,t,Oce]}function v8(e){return Array.isArray(e)?e[2]===Oce:!1}function C8(e,t){if(L2(e)){let r={};for(let s of Object.keys(e))r[s]=C8(e[s],t);return pI(t,r)}return Array.isArray(e)?pI(t,e.map(r=>C8(r,t))):pI(t,e)}function w8(e,t,r,s,a){let n,c=[],f=a,p=0;for(let E=a-1;E>=s;--E){let[C,S]=e[E],{onConflict:x,value:I}=Nce(S,r),T=Fce(I);if(T!==3){if(n??=T,T!==n||x===\"hardReset\"){p=f;break}if(T===2)return pI(C,I);if(c.unshift([C,I]),x===\"reset\"){p=E;break}x===\"extend\"&&E===s&&(s=0),f=E}}if(typeof n>\"u\")return null;let h=c.map(([E])=>E).join(\", \");switch(n){case 1:return pI(h,new Array().concat(...c.map(([E,C])=>C.map(S=>C8(S,E)))));case 0:{let E=Object.assign({},...c.map(([,T])=>T)),C=Object.keys(E),S={},x=e.map(([T,O])=>[T,Nce(O,r).value]),I=XZe(x,([T,O])=>{let U=Fce(O);return U!==0&&U!==3});if(I!==-1){let T=x.slice(I+1);for(let O of C)S[O]=w8(T,t,O,0,T.length)}else for(let T of C)S[T]=w8(x,t,T,p,x.length);return pI(h,S)}default:throw new Error(\"Assertion failed: Non-extendable value type\")}}function Lce(e){return w8(e.map(([t,r])=>[t,{\".\":r}]),[],\".\",0,e.length)}function M2(e){return v8(e)?e[1]:e}function FQ(e){let t=v8(e)?e[1]:e;if(Array.isArray(t))return t.map(r=>FQ(r));if(L2(t)){let r={};for(let[s,a]of Object.entries(t))r[s]=FQ(a);return r}return t}function S8(e){return v8(e)?e[0]:null}var XZe,Oce,Mce=Ze(()=>{XZe=(e,t,r)=>{let s=[...e];return s.reverse(),s.findIndex(t,r)};Oce=Symbol()});var NQ={};Yt(NQ,{getDefaultGlobalFolder:()=>b8,getHomeFolder:()=>hI,isFolderInside:()=>P8});function b8(){if(process.platform===\"win32\"){let e=fe.toPortablePath(process.env.LOCALAPPDATA||fe.join((0,D8.homedir)(),\"AppData\",\"Local\"));return K.resolve(e,\"Yarn/Berry\")}if(process.env.XDG_DATA_HOME){let e=fe.toPortablePath(process.env.XDG_DATA_HOME);return K.resolve(e,\"yarn/berry\")}return K.resolve(hI(),\".yarn/berry\")}function hI(){return fe.toPortablePath((0,D8.homedir)()||\"/usr/local/share\")}function P8(e,t){let r=K.relative(t,e);return r&&!r.startsWith(\"..\")&&!K.isAbsolute(r)}var D8,OQ=Ze(()=>{Dt();D8=Ie(\"os\")});var Hce=G((TNt,_ce)=>{\"use strict\";var x8=Ie(\"https\"),k8=Ie(\"http\"),{URL:Uce}=Ie(\"url\"),Q8=class extends k8.Agent{constructor(t){let{proxy:r,proxyRequestOptions:s,...a}=t;super(a),this.proxy=typeof r==\"string\"?new Uce(r):r,this.proxyRequestOptions=s||{}}createConnection(t,r){let s={...this.proxyRequestOptions,method:\"CONNECT\",host:this.proxy.hostname,port:this.proxy.port,path:`${t.host}:${t.port}`,setHost:!1,headers:{...this.proxyRequestOptions.headers,connection:this.keepAlive?\"keep-alive\":\"close\",host:`${t.host}:${t.port}`},agent:!1,timeout:t.timeout||0};if(this.proxy.username||this.proxy.password){let n=Buffer.from(`${decodeURIComponent(this.proxy.username||\"\")}:${decodeURIComponent(this.proxy.password||\"\")}`).toString(\"base64\");s.headers[\"proxy-authorization\"]=`Basic ${n}`}this.proxy.protocol===\"https:\"&&(s.servername=this.proxy.hostname);let a=(this.proxy.protocol===\"http:\"?k8:x8).request(s);a.once(\"connect\",(n,c,f)=>{a.removeAllListeners(),c.removeAllListeners(),n.statusCode===200?r(null,c):(c.destroy(),r(new Error(`Bad response: ${n.statusCode}`),null))}),a.once(\"timeout\",()=>{a.destroy(new Error(\"Proxy timeout\"))}),a.once(\"error\",n=>{a.removeAllListeners(),r(n,null)}),a.end()}},R8=class extends x8.Agent{constructor(t){let{proxy:r,proxyRequestOptions:s,...a}=t;super(a),this.proxy=typeof r==\"string\"?new Uce(r):r,this.proxyRequestOptions=s||{}}createConnection(t,r){let s={...this.proxyRequestOptions,method:\"CONNECT\",host:this.proxy.hostname,port:this.proxy.port,path:`${t.host}:${t.port}`,setHost:!1,headers:{...this.proxyRequestOptions.headers,connection:this.keepAlive?\"keep-alive\":\"close\",host:`${t.host}:${t.port}`},agent:!1,timeout:t.timeout||0};if(this.proxy.username||this.proxy.password){let n=Buffer.from(`${decodeURIComponent(this.proxy.username||\"\")}:${decodeURIComponent(this.proxy.password||\"\")}`).toString(\"base64\");s.headers[\"proxy-authorization\"]=`Basic ${n}`}this.proxy.protocol===\"https:\"&&(s.servername=this.proxy.hostname);let a=(this.proxy.protocol===\"http:\"?k8:x8).request(s);a.once(\"connect\",(n,c,f)=>{if(a.removeAllListeners(),c.removeAllListeners(),n.statusCode===200){let p=super.createConnection({...t,socket:c});r(null,p)}else c.destroy(),r(new Error(`Bad response: ${n.statusCode}`),null)}),a.once(\"timeout\",()=>{a.destroy(new Error(\"Proxy timeout\"))}),a.once(\"error\",n=>{a.removeAllListeners(),r(n,null)}),a.end()}};_ce.exports={HttpProxyAgent:Q8,HttpsProxyAgent:R8}});var T8,jce,Gce,qce=Ze(()=>{T8=et(Hce(),1),jce=T8.default.HttpProxyAgent,Gce=T8.default.HttpsProxyAgent});var Op=G((Np,LQ)=>{\"use strict\";Object.defineProperty(Np,\"__esModule\",{value:!0});var Wce=[\"Int8Array\",\"Uint8Array\",\"Uint8ClampedArray\",\"Int16Array\",\"Uint16Array\",\"Int32Array\",\"Uint32Array\",\"Float32Array\",\"Float64Array\",\"BigInt64Array\",\"BigUint64Array\"];function rXe(e){return Wce.includes(e)}var nXe=[\"Function\",\"Generator\",\"AsyncGenerator\",\"GeneratorFunction\",\"AsyncGeneratorFunction\",\"AsyncFunction\",\"Observable\",\"Array\",\"Buffer\",\"Blob\",\"Object\",\"RegExp\",\"Date\",\"Error\",\"Map\",\"Set\",\"WeakMap\",\"WeakSet\",\"ArrayBuffer\",\"SharedArrayBuffer\",\"DataView\",\"Promise\",\"URL\",\"FormData\",\"URLSearchParams\",\"HTMLElement\",...Wce];function iXe(e){return nXe.includes(e)}var sXe=[\"null\",\"undefined\",\"string\",\"number\",\"bigint\",\"boolean\",\"symbol\"];function oXe(e){return sXe.includes(e)}function gI(e){return t=>typeof t===e}var{toString:Vce}=Object.prototype,U2=e=>{let t=Vce.call(e).slice(8,-1);if(/HTML\\w+Element/.test(t)&&Pe.domElement(e))return\"HTMLElement\";if(iXe(t))return t},hi=e=>t=>U2(t)===e;function Pe(e){if(e===null)return\"null\";switch(typeof e){case\"undefined\":return\"undefined\";case\"string\":return\"string\";case\"number\":return\"number\";case\"boolean\":return\"boolean\";case\"function\":return\"Function\";case\"bigint\":return\"bigint\";case\"symbol\":return\"symbol\";default:}if(Pe.observable(e))return\"Observable\";if(Pe.array(e))return\"Array\";if(Pe.buffer(e))return\"Buffer\";let t=U2(e);if(t)return t;if(e instanceof String||e instanceof Boolean||e instanceof Number)throw new TypeError(\"Please don't use object wrappers for primitive types\");return\"Object\"}Pe.undefined=gI(\"undefined\");Pe.string=gI(\"string\");var aXe=gI(\"number\");Pe.number=e=>aXe(e)&&!Pe.nan(e);Pe.bigint=gI(\"bigint\");Pe.function_=gI(\"function\");Pe.null_=e=>e===null;Pe.class_=e=>Pe.function_(e)&&e.toString().startsWith(\"class \");Pe.boolean=e=>e===!0||e===!1;Pe.symbol=gI(\"symbol\");Pe.numericString=e=>Pe.string(e)&&!Pe.emptyStringOrWhitespace(e)&&!Number.isNaN(Number(e));Pe.array=(e,t)=>Array.isArray(e)?Pe.function_(t)?e.every(t):!0:!1;Pe.buffer=e=>{var t,r,s,a;return(a=(s=(r=(t=e)===null||t===void 0?void 0:t.constructor)===null||r===void 0?void 0:r.isBuffer)===null||s===void 0?void 0:s.call(r,e))!==null&&a!==void 0?a:!1};Pe.blob=e=>hi(\"Blob\")(e);Pe.nullOrUndefined=e=>Pe.null_(e)||Pe.undefined(e);Pe.object=e=>!Pe.null_(e)&&(typeof e==\"object\"||Pe.function_(e));Pe.iterable=e=>{var t;return Pe.function_((t=e)===null||t===void 0?void 0:t[Symbol.iterator])};Pe.asyncIterable=e=>{var t;return Pe.function_((t=e)===null||t===void 0?void 0:t[Symbol.asyncIterator])};Pe.generator=e=>{var t,r;return Pe.iterable(e)&&Pe.function_((t=e)===null||t===void 0?void 0:t.next)&&Pe.function_((r=e)===null||r===void 0?void 0:r.throw)};Pe.asyncGenerator=e=>Pe.asyncIterable(e)&&Pe.function_(e.next)&&Pe.function_(e.throw);Pe.nativePromise=e=>hi(\"Promise\")(e);var lXe=e=>{var t,r;return Pe.function_((t=e)===null||t===void 0?void 0:t.then)&&Pe.function_((r=e)===null||r===void 0?void 0:r.catch)};Pe.promise=e=>Pe.nativePromise(e)||lXe(e);Pe.generatorFunction=hi(\"GeneratorFunction\");Pe.asyncGeneratorFunction=e=>U2(e)===\"AsyncGeneratorFunction\";Pe.asyncFunction=e=>U2(e)===\"AsyncFunction\";Pe.boundFunction=e=>Pe.function_(e)&&!e.hasOwnProperty(\"prototype\");Pe.regExp=hi(\"RegExp\");Pe.date=hi(\"Date\");Pe.error=hi(\"Error\");Pe.map=e=>hi(\"Map\")(e);Pe.set=e=>hi(\"Set\")(e);Pe.weakMap=e=>hi(\"WeakMap\")(e);Pe.weakSet=e=>hi(\"WeakSet\")(e);Pe.int8Array=hi(\"Int8Array\");Pe.uint8Array=hi(\"Uint8Array\");Pe.uint8ClampedArray=hi(\"Uint8ClampedArray\");Pe.int16Array=hi(\"Int16Array\");Pe.uint16Array=hi(\"Uint16Array\");Pe.int32Array=hi(\"Int32Array\");Pe.uint32Array=hi(\"Uint32Array\");Pe.float32Array=hi(\"Float32Array\");Pe.float64Array=hi(\"Float64Array\");Pe.bigInt64Array=hi(\"BigInt64Array\");Pe.bigUint64Array=hi(\"BigUint64Array\");Pe.arrayBuffer=hi(\"ArrayBuffer\");Pe.sharedArrayBuffer=hi(\"SharedArrayBuffer\");Pe.dataView=hi(\"DataView\");Pe.enumCase=(e,t)=>Object.values(t).includes(e);Pe.directInstanceOf=(e,t)=>Object.getPrototypeOf(e)===t.prototype;Pe.urlInstance=e=>hi(\"URL\")(e);Pe.urlString=e=>{if(!Pe.string(e))return!1;try{return new URL(e),!0}catch{return!1}};Pe.truthy=e=>!!e;Pe.falsy=e=>!e;Pe.nan=e=>Number.isNaN(e);Pe.primitive=e=>Pe.null_(e)||oXe(typeof e);Pe.integer=e=>Number.isInteger(e);Pe.safeInteger=e=>Number.isSafeInteger(e);Pe.plainObject=e=>{if(Vce.call(e)!==\"[object Object]\")return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.getPrototypeOf({})};Pe.typedArray=e=>rXe(U2(e));var cXe=e=>Pe.safeInteger(e)&&e>=0;Pe.arrayLike=e=>!Pe.nullOrUndefined(e)&&!Pe.function_(e)&&cXe(e.length);Pe.inRange=(e,t)=>{if(Pe.number(t))return e>=Math.min(0,t)&&e<=Math.max(t,0);if(Pe.array(t)&&t.length===2)return e>=Math.min(...t)&&e<=Math.max(...t);throw new TypeError(`Invalid range: ${JSON.stringify(t)}`)};var uXe=1,fXe=[\"innerHTML\",\"ownerDocument\",\"style\",\"attributes\",\"nodeValue\"];Pe.domElement=e=>Pe.object(e)&&e.nodeType===uXe&&Pe.string(e.nodeName)&&!Pe.plainObject(e)&&fXe.every(t=>t in e);Pe.observable=e=>{var t,r,s,a;return e?e===((r=(t=e)[Symbol.observable])===null||r===void 0?void 0:r.call(t))||e===((a=(s=e)[\"@@observable\"])===null||a===void 0?void 0:a.call(s)):!1};Pe.nodeStream=e=>Pe.object(e)&&Pe.function_(e.pipe)&&!Pe.observable(e);Pe.infinite=e=>e===1/0||e===-1/0;var Yce=e=>t=>Pe.integer(t)&&Math.abs(t%2)===e;Pe.evenInteger=Yce(0);Pe.oddInteger=Yce(1);Pe.emptyArray=e=>Pe.array(e)&&e.length===0;Pe.nonEmptyArray=e=>Pe.array(e)&&e.length>0;Pe.emptyString=e=>Pe.string(e)&&e.length===0;var AXe=e=>Pe.string(e)&&!/\\S/.test(e);Pe.emptyStringOrWhitespace=e=>Pe.emptyString(e)||AXe(e);Pe.nonEmptyString=e=>Pe.string(e)&&e.length>0;Pe.nonEmptyStringAndNotWhitespace=e=>Pe.string(e)&&!Pe.emptyStringOrWhitespace(e);Pe.emptyObject=e=>Pe.object(e)&&!Pe.map(e)&&!Pe.set(e)&&Object.keys(e).length===0;Pe.nonEmptyObject=e=>Pe.object(e)&&!Pe.map(e)&&!Pe.set(e)&&Object.keys(e).length>0;Pe.emptySet=e=>Pe.set(e)&&e.size===0;Pe.nonEmptySet=e=>Pe.set(e)&&e.size>0;Pe.emptyMap=e=>Pe.map(e)&&e.size===0;Pe.nonEmptyMap=e=>Pe.map(e)&&e.size>0;Pe.propertyKey=e=>Pe.any([Pe.string,Pe.number,Pe.symbol],e);Pe.formData=e=>hi(\"FormData\")(e);Pe.urlSearchParams=e=>hi(\"URLSearchParams\")(e);var Kce=(e,t,r)=>{if(!Pe.function_(t))throw new TypeError(`Invalid predicate: ${JSON.stringify(t)}`);if(r.length===0)throw new TypeError(\"Invalid number of values\");return e.call(r,t)};Pe.any=(e,...t)=>(Pe.array(e)?e:[e]).some(s=>Kce(Array.prototype.some,s,t));Pe.all=(e,...t)=>Kce(Array.prototype.every,e,t);var Ht=(e,t,r,s={})=>{if(!e){let{multipleValues:a}=s,n=a?`received values of types ${[...new Set(r.map(c=>`\\`${Pe(c)}\\``))].join(\", \")}`:`received value of type \\`${Pe(r)}\\``;throw new TypeError(`Expected value which is \\`${t}\\`, ${n}.`)}};Np.assert={undefined:e=>Ht(Pe.undefined(e),\"undefined\",e),string:e=>Ht(Pe.string(e),\"string\",e),number:e=>Ht(Pe.number(e),\"number\",e),bigint:e=>Ht(Pe.bigint(e),\"bigint\",e),function_:e=>Ht(Pe.function_(e),\"Function\",e),null_:e=>Ht(Pe.null_(e),\"null\",e),class_:e=>Ht(Pe.class_(e),\"Class\",e),boolean:e=>Ht(Pe.boolean(e),\"boolean\",e),symbol:e=>Ht(Pe.symbol(e),\"symbol\",e),numericString:e=>Ht(Pe.numericString(e),\"string with a number\",e),array:(e,t)=>{Ht(Pe.array(e),\"Array\",e),t&&e.forEach(t)},buffer:e=>Ht(Pe.buffer(e),\"Buffer\",e),blob:e=>Ht(Pe.blob(e),\"Blob\",e),nullOrUndefined:e=>Ht(Pe.nullOrUndefined(e),\"null or undefined\",e),object:e=>Ht(Pe.object(e),\"Object\",e),iterable:e=>Ht(Pe.iterable(e),\"Iterable\",e),asyncIterable:e=>Ht(Pe.asyncIterable(e),\"AsyncIterable\",e),generator:e=>Ht(Pe.generator(e),\"Generator\",e),asyncGenerator:e=>Ht(Pe.asyncGenerator(e),\"AsyncGenerator\",e),nativePromise:e=>Ht(Pe.nativePromise(e),\"native Promise\",e),promise:e=>Ht(Pe.promise(e),\"Promise\",e),generatorFunction:e=>Ht(Pe.generatorFunction(e),\"GeneratorFunction\",e),asyncGeneratorFunction:e=>Ht(Pe.asyncGeneratorFunction(e),\"AsyncGeneratorFunction\",e),asyncFunction:e=>Ht(Pe.asyncFunction(e),\"AsyncFunction\",e),boundFunction:e=>Ht(Pe.boundFunction(e),\"Function\",e),regExp:e=>Ht(Pe.regExp(e),\"RegExp\",e),date:e=>Ht(Pe.date(e),\"Date\",e),error:e=>Ht(Pe.error(e),\"Error\",e),map:e=>Ht(Pe.map(e),\"Map\",e),set:e=>Ht(Pe.set(e),\"Set\",e),weakMap:e=>Ht(Pe.weakMap(e),\"WeakMap\",e),weakSet:e=>Ht(Pe.weakSet(e),\"WeakSet\",e),int8Array:e=>Ht(Pe.int8Array(e),\"Int8Array\",e),uint8Array:e=>Ht(Pe.uint8Array(e),\"Uint8Array\",e),uint8ClampedArray:e=>Ht(Pe.uint8ClampedArray(e),\"Uint8ClampedArray\",e),int16Array:e=>Ht(Pe.int16Array(e),\"Int16Array\",e),uint16Array:e=>Ht(Pe.uint16Array(e),\"Uint16Array\",e),int32Array:e=>Ht(Pe.int32Array(e),\"Int32Array\",e),uint32Array:e=>Ht(Pe.uint32Array(e),\"Uint32Array\",e),float32Array:e=>Ht(Pe.float32Array(e),\"Float32Array\",e),float64Array:e=>Ht(Pe.float64Array(e),\"Float64Array\",e),bigInt64Array:e=>Ht(Pe.bigInt64Array(e),\"BigInt64Array\",e),bigUint64Array:e=>Ht(Pe.bigUint64Array(e),\"BigUint64Array\",e),arrayBuffer:e=>Ht(Pe.arrayBuffer(e),\"ArrayBuffer\",e),sharedArrayBuffer:e=>Ht(Pe.sharedArrayBuffer(e),\"SharedArrayBuffer\",e),dataView:e=>Ht(Pe.dataView(e),\"DataView\",e),enumCase:(e,t)=>Ht(Pe.enumCase(e,t),\"EnumCase\",e),urlInstance:e=>Ht(Pe.urlInstance(e),\"URL\",e),urlString:e=>Ht(Pe.urlString(e),\"string with a URL\",e),truthy:e=>Ht(Pe.truthy(e),\"truthy\",e),falsy:e=>Ht(Pe.falsy(e),\"falsy\",e),nan:e=>Ht(Pe.nan(e),\"NaN\",e),primitive:e=>Ht(Pe.primitive(e),\"primitive\",e),integer:e=>Ht(Pe.integer(e),\"integer\",e),safeInteger:e=>Ht(Pe.safeInteger(e),\"integer\",e),plainObject:e=>Ht(Pe.plainObject(e),\"plain object\",e),typedArray:e=>Ht(Pe.typedArray(e),\"TypedArray\",e),arrayLike:e=>Ht(Pe.arrayLike(e),\"array-like\",e),domElement:e=>Ht(Pe.domElement(e),\"HTMLElement\",e),observable:e=>Ht(Pe.observable(e),\"Observable\",e),nodeStream:e=>Ht(Pe.nodeStream(e),\"Node.js Stream\",e),infinite:e=>Ht(Pe.infinite(e),\"infinite number\",e),emptyArray:e=>Ht(Pe.emptyArray(e),\"empty array\",e),nonEmptyArray:e=>Ht(Pe.nonEmptyArray(e),\"non-empty array\",e),emptyString:e=>Ht(Pe.emptyString(e),\"empty string\",e),emptyStringOrWhitespace:e=>Ht(Pe.emptyStringOrWhitespace(e),\"empty string or whitespace\",e),nonEmptyString:e=>Ht(Pe.nonEmptyString(e),\"non-empty string\",e),nonEmptyStringAndNotWhitespace:e=>Ht(Pe.nonEmptyStringAndNotWhitespace(e),\"non-empty string and not whitespace\",e),emptyObject:e=>Ht(Pe.emptyObject(e),\"empty object\",e),nonEmptyObject:e=>Ht(Pe.nonEmptyObject(e),\"non-empty object\",e),emptySet:e=>Ht(Pe.emptySet(e),\"empty set\",e),nonEmptySet:e=>Ht(Pe.nonEmptySet(e),\"non-empty set\",e),emptyMap:e=>Ht(Pe.emptyMap(e),\"empty map\",e),nonEmptyMap:e=>Ht(Pe.nonEmptyMap(e),\"non-empty map\",e),propertyKey:e=>Ht(Pe.propertyKey(e),\"PropertyKey\",e),formData:e=>Ht(Pe.formData(e),\"FormData\",e),urlSearchParams:e=>Ht(Pe.urlSearchParams(e),\"URLSearchParams\",e),evenInteger:e=>Ht(Pe.evenInteger(e),\"even integer\",e),oddInteger:e=>Ht(Pe.oddInteger(e),\"odd integer\",e),directInstanceOf:(e,t)=>Ht(Pe.directInstanceOf(e,t),\"T\",e),inRange:(e,t)=>Ht(Pe.inRange(e,t),\"in range\",e),any:(e,...t)=>Ht(Pe.any(e,...t),\"predicate returns truthy for any value\",t,{multipleValues:!0}),all:(e,...t)=>Ht(Pe.all(e,...t),\"predicate returns truthy for all values\",t,{multipleValues:!0})};Object.defineProperties(Pe,{class:{value:Pe.class_},function:{value:Pe.function_},null:{value:Pe.null_}});Object.defineProperties(Np.assert,{class:{value:Np.assert.class_},function:{value:Np.assert.function_},null:{value:Np.assert.null_}});Np.default=Pe;LQ.exports=Pe;LQ.exports.default=Pe;LQ.exports.assert=Np.assert});var Jce=G((NNt,F8)=>{\"use strict\";var MQ=class extends Error{constructor(t){super(t||\"Promise was canceled\"),this.name=\"CancelError\"}get isCanceled(){return!0}},UQ=class e{static fn(t){return(...r)=>new e((s,a,n)=>{r.push(n),t(...r).then(s,a)})}constructor(t){this._cancelHandlers=[],this._isPending=!0,this._isCanceled=!1,this._rejectOnCancel=!0,this._promise=new Promise((r,s)=>{this._reject=s;let a=f=>{this._isPending=!1,r(f)},n=f=>{this._isPending=!1,s(f)},c=f=>{if(!this._isPending)throw new Error(\"The `onCancel` handler was attached after the promise settled.\");this._cancelHandlers.push(f)};return Object.defineProperties(c,{shouldReject:{get:()=>this._rejectOnCancel,set:f=>{this._rejectOnCancel=f}}}),t(a,n,c)})}then(t,r){return this._promise.then(t,r)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}cancel(t){if(!(!this._isPending||this._isCanceled)){if(this._cancelHandlers.length>0)try{for(let r of this._cancelHandlers)r()}catch(r){this._reject(r)}this._isCanceled=!0,this._rejectOnCancel&&this._reject(new MQ(t))}}get isCanceled(){return this._isCanceled}};Object.setPrototypeOf(UQ.prototype,Promise.prototype);F8.exports=UQ;F8.exports.CancelError=MQ});var zce=G((O8,L8)=>{\"use strict\";Object.defineProperty(O8,\"__esModule\",{value:!0});function pXe(e){return e.encrypted}var N8=(e,t)=>{let r;typeof t==\"function\"?r={connect:t}:r=t;let s=typeof r.connect==\"function\",a=typeof r.secureConnect==\"function\",n=typeof r.close==\"function\",c=()=>{s&&r.connect(),pXe(e)&&a&&(e.authorized?r.secureConnect():e.authorizationError||e.once(\"secureConnect\",r.secureConnect)),n&&e.once(\"close\",r.close)};e.writable&&!e.connecting?c():e.connecting?e.once(\"connect\",c):e.destroyed&&n&&r.close(e._hadError)};O8.default=N8;L8.exports=N8;L8.exports.default=N8});var Zce=G((U8,_8)=>{\"use strict\";Object.defineProperty(U8,\"__esModule\",{value:!0});var hXe=zce(),gXe=Number(process.versions.node.split(\".\")[0]),M8=e=>{let t={start:Date.now(),socket:void 0,lookup:void 0,connect:void 0,secureConnect:void 0,upload:void 0,response:void 0,end:void 0,error:void 0,abort:void 0,phases:{wait:void 0,dns:void 0,tcp:void 0,tls:void 0,request:void 0,firstByte:void 0,download:void 0,total:void 0}};e.timings=t;let r=c=>{let f=c.emit.bind(c);c.emit=(p,...h)=>(p===\"error\"&&(t.error=Date.now(),t.phases.total=t.error-t.start,c.emit=f),f(p,...h))};r(e),e.prependOnceListener(\"abort\",()=>{t.abort=Date.now(),(!t.response||gXe>=13)&&(t.phases.total=Date.now()-t.start)});let s=c=>{t.socket=Date.now(),t.phases.wait=t.socket-t.start;let f=()=>{t.lookup=Date.now(),t.phases.dns=t.lookup-t.socket};c.prependOnceListener(\"lookup\",f),hXe.default(c,{connect:()=>{t.connect=Date.now(),t.lookup===void 0&&(c.removeListener(\"lookup\",f),t.lookup=t.connect,t.phases.dns=t.lookup-t.socket),t.phases.tcp=t.connect-t.lookup},secureConnect:()=>{t.secureConnect=Date.now(),t.phases.tls=t.secureConnect-t.connect}})};e.socket?s(e.socket):e.prependOnceListener(\"socket\",s);let a=()=>{var c;t.upload=Date.now(),t.phases.request=t.upload-(c=t.secureConnect,c??t.connect)};return(typeof e.writableFinished==\"boolean\"?e.writableFinished:e.finished&&e.outputSize===0&&(!e.socket||e.socket.writableLength===0))?a():e.prependOnceListener(\"finish\",a),e.prependOnceListener(\"response\",c=>{t.response=Date.now(),t.phases.firstByte=t.response-t.upload,c.timings=t,r(c),c.prependOnceListener(\"end\",()=>{t.end=Date.now(),t.phases.download=t.end-t.response,t.phases.total=t.end-t.start})}),t};U8.default=M8;_8.exports=M8;_8.exports.default=M8});var iue=G((ONt,G8)=>{\"use strict\";var{V4MAPPED:dXe,ADDRCONFIG:mXe,ALL:nue,promises:{Resolver:Xce},lookup:yXe}=Ie(\"dns\"),{promisify:H8}=Ie(\"util\"),EXe=Ie(\"os\"),dI=Symbol(\"cacheableLookupCreateConnection\"),j8=Symbol(\"cacheableLookupInstance\"),$ce=Symbol(\"expires\"),IXe=typeof nue==\"number\",eue=e=>{if(!(e&&typeof e.createConnection==\"function\"))throw new Error(\"Expected an Agent instance as the first argument\")},CXe=e=>{for(let t of e)t.family!==6&&(t.address=`::ffff:${t.address}`,t.family=6)},tue=()=>{let e=!1,t=!1;for(let r of Object.values(EXe.networkInterfaces()))for(let s of r)if(!s.internal&&(s.family===\"IPv6\"?t=!0:e=!0,e&&t))return{has4:e,has6:t};return{has4:e,has6:t}},wXe=e=>Symbol.iterator in e,rue={ttl:!0},BXe={all:!0},_Q=class{constructor({cache:t=new Map,maxTtl:r=1/0,fallbackDuration:s=3600,errorTtl:a=.15,resolver:n=new Xce,lookup:c=yXe}={}){if(this.maxTtl=r,this.errorTtl=a,this._cache=t,this._resolver=n,this._dnsLookup=H8(c),this._resolver instanceof Xce?(this._resolve4=this._resolver.resolve4.bind(this._resolver),this._resolve6=this._resolver.resolve6.bind(this._resolver)):(this._resolve4=H8(this._resolver.resolve4.bind(this._resolver)),this._resolve6=H8(this._resolver.resolve6.bind(this._resolver))),this._iface=tue(),this._pending={},this._nextRemovalTime=!1,this._hostnamesToFallback=new Set,s<1)this._fallback=!1;else{this._fallback=!0;let f=setInterval(()=>{this._hostnamesToFallback.clear()},s*1e3);f.unref&&f.unref()}this.lookup=this.lookup.bind(this),this.lookupAsync=this.lookupAsync.bind(this)}set servers(t){this.clear(),this._resolver.setServers(t)}get servers(){return this._resolver.getServers()}lookup(t,r,s){if(typeof r==\"function\"?(s=r,r={}):typeof r==\"number\"&&(r={family:r}),!s)throw new Error(\"Callback must be a function.\");this.lookupAsync(t,r).then(a=>{r.all?s(null,a):s(null,a.address,a.family,a.expires,a.ttl)},s)}async lookupAsync(t,r={}){typeof r==\"number\"&&(r={family:r});let s=await this.query(t);if(r.family===6){let a=s.filter(n=>n.family===6);r.hints&dXe&&(IXe&&r.hints&nue||a.length===0)?CXe(s):s=a}else r.family===4&&(s=s.filter(a=>a.family===4));if(r.hints&mXe){let{_iface:a}=this;s=s.filter(n=>n.family===6?a.has6:a.has4)}if(s.length===0){let a=new Error(`cacheableLookup ENOTFOUND ${t}`);throw a.code=\"ENOTFOUND\",a.hostname=t,a}return r.all?s:s[0]}async query(t){let r=await this._cache.get(t);if(!r){let s=this._pending[t];if(s)r=await s;else{let a=this.queryAndCache(t);this._pending[t]=a,r=await a}}return r=r.map(s=>({...s})),r}async _resolve(t){let r=async h=>{try{return await h}catch(E){if(E.code===\"ENODATA\"||E.code===\"ENOTFOUND\")return[];throw E}},[s,a]=await Promise.all([this._resolve4(t,rue),this._resolve6(t,rue)].map(h=>r(h))),n=0,c=0,f=0,p=Date.now();for(let h of s)h.family=4,h.expires=p+h.ttl*1e3,n=Math.max(n,h.ttl);for(let h of a)h.family=6,h.expires=p+h.ttl*1e3,c=Math.max(c,h.ttl);return s.length>0?a.length>0?f=Math.min(n,c):f=n:f=c,{entries:[...s,...a],cacheTtl:f}}async _lookup(t){try{return{entries:await this._dnsLookup(t,{all:!0}),cacheTtl:0}}catch{return{entries:[],cacheTtl:0}}}async _set(t,r,s){if(this.maxTtl>0&&s>0){s=Math.min(s,this.maxTtl)*1e3,r[$ce]=Date.now()+s;try{await this._cache.set(t,r,s)}catch(a){this.lookupAsync=async()=>{let n=new Error(\"Cache Error. Please recreate the CacheableLookup instance.\");throw n.cause=a,n}}wXe(this._cache)&&this._tick(s)}}async queryAndCache(t){if(this._hostnamesToFallback.has(t))return this._dnsLookup(t,BXe);try{let r=await this._resolve(t);r.entries.length===0&&this._fallback&&(r=await this._lookup(t),r.entries.length!==0&&this._hostnamesToFallback.add(t));let s=r.entries.length===0?this.errorTtl:r.cacheTtl;return await this._set(t,r.entries,s),delete this._pending[t],r.entries}catch(r){throw delete this._pending[t],r}}_tick(t){let r=this._nextRemovalTime;(!r||t<r)&&(clearTimeout(this._removalTimeout),this._nextRemovalTime=t,this._removalTimeout=setTimeout(()=>{this._nextRemovalTime=!1;let s=1/0,a=Date.now();for(let[n,c]of this._cache){let f=c[$ce];a>=f?this._cache.delete(n):f<s&&(s=f)}s!==1/0&&this._tick(s-a)},t),this._removalTimeout.unref&&this._removalTimeout.unref())}install(t){if(eue(t),dI in t)throw new Error(\"CacheableLookup has been already installed\");t[dI]=t.createConnection,t[j8]=this,t.createConnection=(r,s)=>(\"lookup\"in r||(r.lookup=this.lookup),t[dI](r,s))}uninstall(t){if(eue(t),t[dI]){if(t[j8]!==this)throw new Error(\"The agent is not owned by this CacheableLookup instance\");t.createConnection=t[dI],delete t[dI],delete t[j8]}}updateInterfaceInfo(){let{_iface:t}=this;this._iface=tue(),(t.has4&&!this._iface.has4||t.has6&&!this._iface.has6)&&this._cache.clear()}clear(t){if(t){this._cache.delete(t);return}this._cache.clear()}};G8.exports=_Q;G8.exports.default=_Q});var aue=G((LNt,q8)=>{\"use strict\";var vXe=typeof URL>\"u\"?Ie(\"url\").URL:URL,SXe=\"text/plain\",DXe=\"us-ascii\",sue=(e,t)=>t.some(r=>r instanceof RegExp?r.test(e):r===e),bXe=(e,{stripHash:t})=>{let r=e.match(/^data:([^,]*?),([^#]*?)(?:#(.*))?$/);if(!r)throw new Error(`Invalid URL: ${e}`);let s=r[1].split(\";\"),a=r[2],n=t?\"\":r[3],c=!1;s[s.length-1]===\"base64\"&&(s.pop(),c=!0);let f=(s.shift()||\"\").toLowerCase(),h=[...s.map(E=>{let[C,S=\"\"]=E.split(\"=\").map(x=>x.trim());return C===\"charset\"&&(S=S.toLowerCase(),S===DXe)?\"\":`${C}${S?`=${S}`:\"\"}`}).filter(Boolean)];return c&&h.push(\"base64\"),(h.length!==0||f&&f!==SXe)&&h.unshift(f),`data:${h.join(\";\")},${c?a.trim():a}${n?`#${n}`:\"\"}`},oue=(e,t)=>{if(t={defaultProtocol:\"http:\",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripWWW:!0,removeQueryParameters:[/^utm_\\w+/i],removeTrailingSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...t},Reflect.has(t,\"normalizeHttps\"))throw new Error(\"options.normalizeHttps is renamed to options.forceHttp\");if(Reflect.has(t,\"normalizeHttp\"))throw new Error(\"options.normalizeHttp is renamed to options.forceHttps\");if(Reflect.has(t,\"stripFragment\"))throw new Error(\"options.stripFragment is renamed to options.stripHash\");if(e=e.trim(),/^data:/i.test(e))return bXe(e,t);let r=e.startsWith(\"//\");!r&&/^\\.*\\//.test(e)||(e=e.replace(/^(?!(?:\\w+:)?\\/\\/)|^\\/\\//,t.defaultProtocol));let a=new vXe(e);if(t.forceHttp&&t.forceHttps)throw new Error(\"The `forceHttp` and `forceHttps` options cannot be used together\");if(t.forceHttp&&a.protocol===\"https:\"&&(a.protocol=\"http:\"),t.forceHttps&&a.protocol===\"http:\"&&(a.protocol=\"https:\"),t.stripAuthentication&&(a.username=\"\",a.password=\"\"),t.stripHash&&(a.hash=\"\"),a.pathname&&(a.pathname=a.pathname.replace(/((?!:).|^)\\/{2,}/g,(n,c)=>/^(?!\\/)/g.test(c)?`${c}/`:\"/\")),a.pathname&&(a.pathname=decodeURI(a.pathname)),t.removeDirectoryIndex===!0&&(t.removeDirectoryIndex=[/^index\\.[a-z]+$/]),Array.isArray(t.removeDirectoryIndex)&&t.removeDirectoryIndex.length>0){let n=a.pathname.split(\"/\"),c=n[n.length-1];sue(c,t.removeDirectoryIndex)&&(n=n.slice(0,n.length-1),a.pathname=n.slice(1).join(\"/\")+\"/\")}if(a.hostname&&(a.hostname=a.hostname.replace(/\\.$/,\"\"),t.stripWWW&&/^www\\.([a-z\\-\\d]{2,63})\\.([a-z.]{2,5})$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\\./,\"\"))),Array.isArray(t.removeQueryParameters))for(let n of[...a.searchParams.keys()])sue(n,t.removeQueryParameters)&&a.searchParams.delete(n);return t.sortQueryParameters&&a.searchParams.sort(),t.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\\/$/,\"\")),e=a.toString(),(t.removeTrailingSlash||a.pathname===\"/\")&&a.hash===\"\"&&(e=e.replace(/\\/$/,\"\")),r&&!t.normalizeProtocol&&(e=e.replace(/^http:\\/\\//,\"//\")),t.stripProtocol&&(e=e.replace(/^(?:https?:)?\\/\\//,\"\")),e};q8.exports=oue;q8.exports.default=oue});var uue=G((MNt,cue)=>{cue.exports=lue;function lue(e,t){if(e&&t)return lue(e)(t);if(typeof e!=\"function\")throw new TypeError(\"need wrapper function\");return Object.keys(e).forEach(function(s){r[s]=e[s]}),r;function r(){for(var s=new Array(arguments.length),a=0;a<s.length;a++)s[a]=arguments[a];var n=e.apply(this,s),c=s[s.length-1];return typeof n==\"function\"&&n!==c&&Object.keys(c).forEach(function(f){n[f]=c[f]}),n}}});var V8=G((UNt,W8)=>{var fue=uue();W8.exports=fue(HQ);W8.exports.strict=fue(Aue);HQ.proto=HQ(function(){Object.defineProperty(Function.prototype,\"once\",{value:function(){return HQ(this)},configurable:!0}),Object.defineProperty(Function.prototype,\"onceStrict\",{value:function(){return Aue(this)},configurable:!0})});function HQ(e){var t=function(){return t.called?t.value:(t.called=!0,t.value=e.apply(this,arguments))};return t.called=!1,t}function Aue(e){var t=function(){if(t.called)throw new Error(t.onceError);return t.called=!0,t.value=e.apply(this,arguments)},r=e.name||\"Function wrapped with `once`\";return t.onceError=r+\" shouldn't be called more than once\",t.called=!1,t}});var Y8=G((_Nt,hue)=>{var PXe=V8(),xXe=function(){},kXe=function(e){return e.setHeader&&typeof e.abort==\"function\"},QXe=function(e){return e.stdio&&Array.isArray(e.stdio)&&e.stdio.length===3},pue=function(e,t,r){if(typeof t==\"function\")return pue(e,null,t);t||(t={}),r=PXe(r||xXe);var s=e._writableState,a=e._readableState,n=t.readable||t.readable!==!1&&e.readable,c=t.writable||t.writable!==!1&&e.writable,f=function(){e.writable||p()},p=function(){c=!1,n||r.call(e)},h=function(){n=!1,c||r.call(e)},E=function(I){r.call(e,I?new Error(\"exited with error code: \"+I):null)},C=function(I){r.call(e,I)},S=function(){if(n&&!(a&&a.ended))return r.call(e,new Error(\"premature close\"));if(c&&!(s&&s.ended))return r.call(e,new Error(\"premature close\"))},x=function(){e.req.on(\"finish\",p)};return kXe(e)?(e.on(\"complete\",p),e.on(\"abort\",S),e.req?x():e.on(\"request\",x)):c&&!s&&(e.on(\"end\",f),e.on(\"close\",f)),QXe(e)&&e.on(\"exit\",E),e.on(\"end\",h),e.on(\"finish\",p),t.error!==!1&&e.on(\"error\",C),e.on(\"close\",S),function(){e.removeListener(\"complete\",p),e.removeListener(\"abort\",S),e.removeListener(\"request\",x),e.req&&e.req.removeListener(\"finish\",p),e.removeListener(\"end\",f),e.removeListener(\"close\",f),e.removeListener(\"finish\",p),e.removeListener(\"exit\",E),e.removeListener(\"end\",h),e.removeListener(\"error\",C),e.removeListener(\"close\",S)}};hue.exports=pue});var mue=G((HNt,due)=>{var RXe=V8(),TXe=Y8(),K8=Ie(\"fs\"),_2=function(){},FXe=/^v?\\.0/.test(process.version),jQ=function(e){return typeof e==\"function\"},NXe=function(e){return!FXe||!K8?!1:(e instanceof(K8.ReadStream||_2)||e instanceof(K8.WriteStream||_2))&&jQ(e.close)},OXe=function(e){return e.setHeader&&jQ(e.abort)},LXe=function(e,t,r,s){s=RXe(s);var a=!1;e.on(\"close\",function(){a=!0}),TXe(e,{readable:t,writable:r},function(c){if(c)return s(c);a=!0,s()});var n=!1;return function(c){if(!a&&!n){if(n=!0,NXe(e))return e.close(_2);if(OXe(e))return e.abort();if(jQ(e.destroy))return e.destroy();s(c||new Error(\"stream was destroyed\"))}}},gue=function(e){e()},MXe=function(e,t){return e.pipe(t)},UXe=function(){var e=Array.prototype.slice.call(arguments),t=jQ(e[e.length-1]||_2)&&e.pop()||_2;if(Array.isArray(e[0])&&(e=e[0]),e.length<2)throw new Error(\"pump requires two streams per minimum\");var r,s=e.map(function(a,n){var c=n<e.length-1,f=n>0;return LXe(a,c,f,function(p){r||(r=p),p&&s.forEach(gue),!c&&(s.forEach(gue),t(r))})});return e.reduce(MXe)};due.exports=UXe});var Eue=G((jNt,yue)=>{\"use strict\";var{PassThrough:_Xe}=Ie(\"stream\");yue.exports=e=>{e={...e};let{array:t}=e,{encoding:r}=e,s=r===\"buffer\",a=!1;t?a=!(r||s):r=r||\"utf8\",s&&(r=null);let n=new _Xe({objectMode:a});r&&n.setEncoding(r);let c=0,f=[];return n.on(\"data\",p=>{f.push(p),a?c=f.length:c+=p.length}),n.getBufferedValue=()=>t?f:s?Buffer.concat(f,c):f.join(\"\"),n.getBufferedLength=()=>c,n}});var Iue=G((GNt,mI)=>{\"use strict\";var HXe=mue(),jXe=Eue(),GQ=class extends Error{constructor(){super(\"maxBuffer exceeded\"),this.name=\"MaxBufferError\"}};async function qQ(e,t){if(!e)return Promise.reject(new Error(\"Expected a stream\"));t={maxBuffer:1/0,...t};let{maxBuffer:r}=t,s;return await new Promise((a,n)=>{let c=f=>{f&&(f.bufferedData=s.getBufferedValue()),n(f)};s=HXe(e,jXe(t),f=>{if(f){c(f);return}a()}),s.on(\"data\",()=>{s.getBufferedLength()>r&&c(new GQ)})}),s.getBufferedValue()}mI.exports=qQ;mI.exports.default=qQ;mI.exports.buffer=(e,t)=>qQ(e,{...t,encoding:\"buffer\"});mI.exports.array=(e,t)=>qQ(e,{...t,array:!0});mI.exports.MaxBufferError=GQ});var wue=G((WNt,Cue)=>{\"use strict\";var GXe=new Set([200,203,204,206,300,301,308,404,405,410,414,501]),qXe=new Set([200,203,204,300,301,302,303,307,308,404,405,410,414,501]),WXe=new Set([500,502,503,504]),VXe={date:!0,connection:!0,\"keep-alive\":!0,\"proxy-authenticate\":!0,\"proxy-authorization\":!0,te:!0,trailer:!0,\"transfer-encoding\":!0,upgrade:!0},YXe={\"content-length\":!0,\"content-encoding\":!0,\"transfer-encoding\":!0,\"content-range\":!0};function tm(e){let t=parseInt(e,10);return isFinite(t)?t:0}function KXe(e){return e?WXe.has(e.status):!0}function J8(e){let t={};if(!e)return t;let r=e.trim().split(/,/);for(let s of r){let[a,n]=s.split(/=/,2);t[a.trim()]=n===void 0?!0:n.trim().replace(/^\"|\"$/g,\"\")}return t}function JXe(e){let t=[];for(let r in e){let s=e[r];t.push(s===!0?r:r+\"=\"+s)}if(t.length)return t.join(\", \")}Cue.exports=class{constructor(t,r,{shared:s,cacheHeuristic:a,immutableMinTimeToLive:n,ignoreCargoCult:c,_fromObject:f}={}){if(f){this._fromObject(f);return}if(!r||!r.headers)throw Error(\"Response headers missing\");this._assertRequestHasHeaders(t),this._responseTime=this.now(),this._isShared=s!==!1,this._cacheHeuristic=a!==void 0?a:.1,this._immutableMinTtl=n!==void 0?n:24*3600*1e3,this._status=\"status\"in r?r.status:200,this._resHeaders=r.headers,this._rescc=J8(r.headers[\"cache-control\"]),this._method=\"method\"in t?t.method:\"GET\",this._url=t.url,this._host=t.headers.host,this._noAuthorization=!t.headers.authorization,this._reqHeaders=r.headers.vary?t.headers:null,this._reqcc=J8(t.headers[\"cache-control\"]),c&&\"pre-check\"in this._rescc&&\"post-check\"in this._rescc&&(delete this._rescc[\"pre-check\"],delete this._rescc[\"post-check\"],delete this._rescc[\"no-cache\"],delete this._rescc[\"no-store\"],delete this._rescc[\"must-revalidate\"],this._resHeaders=Object.assign({},this._resHeaders,{\"cache-control\":JXe(this._rescc)}),delete this._resHeaders.expires,delete this._resHeaders.pragma),r.headers[\"cache-control\"]==null&&/no-cache/.test(r.headers.pragma)&&(this._rescc[\"no-cache\"]=!0)}now(){return Date.now()}storable(){return!!(!this._reqcc[\"no-store\"]&&(this._method===\"GET\"||this._method===\"HEAD\"||this._method===\"POST\"&&this._hasExplicitExpiration())&&qXe.has(this._status)&&!this._rescc[\"no-store\"]&&(!this._isShared||!this._rescc.private)&&(!this._isShared||this._noAuthorization||this._allowsStoringAuthenticated())&&(this._resHeaders.expires||this._rescc[\"max-age\"]||this._isShared&&this._rescc[\"s-maxage\"]||this._rescc.public||GXe.has(this._status)))}_hasExplicitExpiration(){return this._isShared&&this._rescc[\"s-maxage\"]||this._rescc[\"max-age\"]||this._resHeaders.expires}_assertRequestHasHeaders(t){if(!t||!t.headers)throw Error(\"Request headers missing\")}satisfiesWithoutRevalidation(t){this._assertRequestHasHeaders(t);let r=J8(t.headers[\"cache-control\"]);return r[\"no-cache\"]||/no-cache/.test(t.headers.pragma)||r[\"max-age\"]&&this.age()>r[\"max-age\"]||r[\"min-fresh\"]&&this.timeToLive()<1e3*r[\"min-fresh\"]||this.stale()&&!(r[\"max-stale\"]&&!this._rescc[\"must-revalidate\"]&&(r[\"max-stale\"]===!0||r[\"max-stale\"]>this.age()-this.maxAge()))?!1:this._requestMatches(t,!1)}_requestMatches(t,r){return(!this._url||this._url===t.url)&&this._host===t.headers.host&&(!t.method||this._method===t.method||r&&t.method===\"HEAD\")&&this._varyMatches(t)}_allowsStoringAuthenticated(){return this._rescc[\"must-revalidate\"]||this._rescc.public||this._rescc[\"s-maxage\"]}_varyMatches(t){if(!this._resHeaders.vary)return!0;if(this._resHeaders.vary===\"*\")return!1;let r=this._resHeaders.vary.trim().toLowerCase().split(/\\s*,\\s*/);for(let s of r)if(t.headers[s]!==this._reqHeaders[s])return!1;return!0}_copyWithoutHopByHopHeaders(t){let r={};for(let s in t)VXe[s]||(r[s]=t[s]);if(t.connection){let s=t.connection.trim().split(/\\s*,\\s*/);for(let a of s)delete r[a]}if(r.warning){let s=r.warning.split(/,/).filter(a=>!/^\\s*1[0-9][0-9]/.test(a));s.length?r.warning=s.join(\",\").trim():delete r.warning}return r}responseHeaders(){let t=this._copyWithoutHopByHopHeaders(this._resHeaders),r=this.age();return r>3600*24&&!this._hasExplicitExpiration()&&this.maxAge()>3600*24&&(t.warning=(t.warning?`${t.warning}, `:\"\")+'113 - \"rfc7234 5.5.4\"'),t.age=`${Math.round(r)}`,t.date=new Date(this.now()).toUTCString(),t}date(){let t=Date.parse(this._resHeaders.date);return isFinite(t)?t:this._responseTime}age(){let t=this._ageValue(),r=(this.now()-this._responseTime)/1e3;return t+r}_ageValue(){return tm(this._resHeaders.age)}maxAge(){if(!this.storable()||this._rescc[\"no-cache\"]||this._isShared&&this._resHeaders[\"set-cookie\"]&&!this._rescc.public&&!this._rescc.immutable||this._resHeaders.vary===\"*\")return 0;if(this._isShared){if(this._rescc[\"proxy-revalidate\"])return 0;if(this._rescc[\"s-maxage\"])return tm(this._rescc[\"s-maxage\"])}if(this._rescc[\"max-age\"])return tm(this._rescc[\"max-age\"]);let t=this._rescc.immutable?this._immutableMinTtl:0,r=this.date();if(this._resHeaders.expires){let s=Date.parse(this._resHeaders.expires);return Number.isNaN(s)||s<r?0:Math.max(t,(s-r)/1e3)}if(this._resHeaders[\"last-modified\"]){let s=Date.parse(this._resHeaders[\"last-modified\"]);if(isFinite(s)&&r>s)return Math.max(t,(r-s)/1e3*this._cacheHeuristic)}return t}timeToLive(){let t=this.maxAge()-this.age(),r=t+tm(this._rescc[\"stale-if-error\"]),s=t+tm(this._rescc[\"stale-while-revalidate\"]);return Math.max(0,t,r,s)*1e3}stale(){return this.maxAge()<=this.age()}_useStaleIfError(){return this.maxAge()+tm(this._rescc[\"stale-if-error\"])>this.age()}useStaleWhileRevalidate(){return this.maxAge()+tm(this._rescc[\"stale-while-revalidate\"])>this.age()}static fromObject(t){return new this(void 0,void 0,{_fromObject:t})}_fromObject(t){if(this._responseTime)throw Error(\"Reinitialized\");if(!t||t.v!==1)throw Error(\"Invalid serialization\");this._responseTime=t.t,this._isShared=t.sh,this._cacheHeuristic=t.ch,this._immutableMinTtl=t.imm!==void 0?t.imm:24*3600*1e3,this._status=t.st,this._resHeaders=t.resh,this._rescc=t.rescc,this._method=t.m,this._url=t.u,this._host=t.h,this._noAuthorization=t.a,this._reqHeaders=t.reqh,this._reqcc=t.reqcc}toObject(){return{v:1,t:this._responseTime,sh:this._isShared,ch:this._cacheHeuristic,imm:this._immutableMinTtl,st:this._status,resh:this._resHeaders,rescc:this._rescc,m:this._method,u:this._url,h:this._host,a:this._noAuthorization,reqh:this._reqHeaders,reqcc:this._reqcc}}revalidationHeaders(t){this._assertRequestHasHeaders(t);let r=this._copyWithoutHopByHopHeaders(t.headers);if(delete r[\"if-range\"],!this._requestMatches(t,!0)||!this.storable())return delete r[\"if-none-match\"],delete r[\"if-modified-since\"],r;if(this._resHeaders.etag&&(r[\"if-none-match\"]=r[\"if-none-match\"]?`${r[\"if-none-match\"]}, ${this._resHeaders.etag}`:this._resHeaders.etag),r[\"accept-ranges\"]||r[\"if-match\"]||r[\"if-unmodified-since\"]||this._method&&this._method!=\"GET\"){if(delete r[\"if-modified-since\"],r[\"if-none-match\"]){let a=r[\"if-none-match\"].split(/,/).filter(n=>!/^\\s*W\\//.test(n));a.length?r[\"if-none-match\"]=a.join(\",\").trim():delete r[\"if-none-match\"]}}else this._resHeaders[\"last-modified\"]&&!r[\"if-modified-since\"]&&(r[\"if-modified-since\"]=this._resHeaders[\"last-modified\"]);return r}revalidatedPolicy(t,r){if(this._assertRequestHasHeaders(t),this._useStaleIfError()&&KXe(r))return{modified:!1,matches:!1,policy:this};if(!r||!r.headers)throw Error(\"Response headers missing\");let s=!1;if(r.status!==void 0&&r.status!=304?s=!1:r.headers.etag&&!/^\\s*W\\//.test(r.headers.etag)?s=this._resHeaders.etag&&this._resHeaders.etag.replace(/^\\s*W\\//,\"\")===r.headers.etag:this._resHeaders.etag&&r.headers.etag?s=this._resHeaders.etag.replace(/^\\s*W\\//,\"\")===r.headers.etag.replace(/^\\s*W\\//,\"\"):this._resHeaders[\"last-modified\"]?s=this._resHeaders[\"last-modified\"]===r.headers[\"last-modified\"]:!this._resHeaders.etag&&!this._resHeaders[\"last-modified\"]&&!r.headers.etag&&!r.headers[\"last-modified\"]&&(s=!0),!s)return{policy:new this.constructor(t,r),modified:r.status!=304,matches:!1};let a={};for(let c in this._resHeaders)a[c]=c in r.headers&&!YXe[c]?r.headers[c]:this._resHeaders[c];let n=Object.assign({},r,{status:this._status,method:this._method,headers:a});return{policy:new this.constructor(t,n,{shared:this._isShared,cacheHeuristic:this._cacheHeuristic,immutableMinTimeToLive:this._immutableMinTtl}),modified:!1,matches:!0}}}});var WQ=G((VNt,Bue)=>{\"use strict\";Bue.exports=e=>{let t={};for(let[r,s]of Object.entries(e))t[r.toLowerCase()]=s;return t}});var Sue=G((YNt,vue)=>{\"use strict\";var zXe=Ie(\"stream\").Readable,ZXe=WQ(),z8=class extends zXe{constructor(t,r,s,a){if(typeof t!=\"number\")throw new TypeError(\"Argument `statusCode` should be a number\");if(typeof r!=\"object\")throw new TypeError(\"Argument `headers` should be an object\");if(!(s instanceof Buffer))throw new TypeError(\"Argument `body` should be a buffer\");if(typeof a!=\"string\")throw new TypeError(\"Argument `url` should be a string\");super(),this.statusCode=t,this.headers=ZXe(r),this.body=s,this.url=a}_read(){this.push(this.body),this.push(null)}};vue.exports=z8});var bue=G((KNt,Due)=>{\"use strict\";var XXe=[\"destroy\",\"setTimeout\",\"socket\",\"headers\",\"trailers\",\"rawHeaders\",\"statusCode\",\"httpVersion\",\"httpVersionMinor\",\"httpVersionMajor\",\"rawTrailers\",\"statusMessage\"];Due.exports=(e,t)=>{let r=new Set(Object.keys(e).concat(XXe));for(let s of r)s in t||(t[s]=typeof e[s]==\"function\"?e[s].bind(e):e[s])}});var xue=G((JNt,Pue)=>{\"use strict\";var $Xe=Ie(\"stream\").PassThrough,e$e=bue(),t$e=e=>{if(!(e&&e.pipe))throw new TypeError(\"Parameter `response` must be a response stream.\");let t=new $Xe;return e$e(e,t),e.pipe(t)};Pue.exports=t$e});var kue=G(Z8=>{Z8.stringify=function e(t){if(typeof t>\"u\")return t;if(t&&Buffer.isBuffer(t))return JSON.stringify(\":base64:\"+t.toString(\"base64\"));if(t&&t.toJSON&&(t=t.toJSON()),t&&typeof t==\"object\"){var r=\"\",s=Array.isArray(t);r=s?\"[\":\"{\";var a=!0;for(var n in t){var c=typeof t[n]==\"function\"||!s&&typeof t[n]>\"u\";Object.hasOwnProperty.call(t,n)&&!c&&(a||(r+=\",\"),a=!1,s?t[n]==null?r+=\"null\":r+=e(t[n]):t[n]!==void 0&&(r+=e(n)+\":\"+e(t[n])))}return r+=s?\"]\":\"}\",r}else return typeof t==\"string\"?JSON.stringify(/^:/.test(t)?\":\"+t:t):typeof t>\"u\"?\"null\":JSON.stringify(t)};Z8.parse=function(e){return JSON.parse(e,function(t,r){return typeof r==\"string\"?/^:base64:/.test(r)?Buffer.from(r.substring(8),\"base64\"):/^:/.test(r)?r.substring(1):r:r})}});var Fue=G((ZNt,Tue)=>{\"use strict\";var r$e=Ie(\"events\"),Que=kue(),n$e=e=>{let t={redis:\"@keyv/redis\",rediss:\"@keyv/redis\",mongodb:\"@keyv/mongo\",mongo:\"@keyv/mongo\",sqlite:\"@keyv/sqlite\",postgresql:\"@keyv/postgres\",postgres:\"@keyv/postgres\",mysql:\"@keyv/mysql\",etcd:\"@keyv/etcd\",offline:\"@keyv/offline\",tiered:\"@keyv/tiered\"};if(e.adapter||e.uri){let r=e.adapter||/^[^:+]*/.exec(e.uri)[0];return new(Ie(t[r]))(e)}return new Map},Rue=[\"sqlite\",\"postgres\",\"mysql\",\"mongo\",\"redis\",\"tiered\"],X8=class extends r$e{constructor(t,{emitErrors:r=!0,...s}={}){if(super(),this.opts={namespace:\"keyv\",serialize:Que.stringify,deserialize:Que.parse,...typeof t==\"string\"?{uri:t}:t,...s},!this.opts.store){let n={...this.opts};this.opts.store=n$e(n)}if(this.opts.compression){let n=this.opts.compression;this.opts.serialize=n.serialize.bind(n),this.opts.deserialize=n.deserialize.bind(n)}typeof this.opts.store.on==\"function\"&&r&&this.opts.store.on(\"error\",n=>this.emit(\"error\",n)),this.opts.store.namespace=this.opts.namespace;let a=n=>async function*(){for await(let[c,f]of typeof n==\"function\"?n(this.opts.store.namespace):n){let p=await this.opts.deserialize(f);if(!(this.opts.store.namespace&&!c.includes(this.opts.store.namespace))){if(typeof p.expires==\"number\"&&Date.now()>p.expires){this.delete(c);continue}yield[this._getKeyUnprefix(c),p.value]}}};typeof this.opts.store[Symbol.iterator]==\"function\"&&this.opts.store instanceof Map?this.iterator=a(this.opts.store):typeof this.opts.store.iterator==\"function\"&&this.opts.store.opts&&this._checkIterableAdaptar()&&(this.iterator=a(this.opts.store.iterator.bind(this.opts.store)))}_checkIterableAdaptar(){return Rue.includes(this.opts.store.opts.dialect)||Rue.findIndex(t=>this.opts.store.opts.url.includes(t))>=0}_getKeyPrefix(t){return`${this.opts.namespace}:${t}`}_getKeyPrefixArray(t){return t.map(r=>`${this.opts.namespace}:${r}`)}_getKeyUnprefix(t){return t.split(\":\").splice(1).join(\":\")}get(t,r){let{store:s}=this.opts,a=Array.isArray(t),n=a?this._getKeyPrefixArray(t):this._getKeyPrefix(t);if(a&&s.getMany===void 0){let c=[];for(let f of n)c.push(Promise.resolve().then(()=>s.get(f)).then(p=>typeof p==\"string\"?this.opts.deserialize(p):this.opts.compression?this.opts.deserialize(p):p).then(p=>{if(p!=null)return typeof p.expires==\"number\"&&Date.now()>p.expires?this.delete(f).then(()=>{}):r&&r.raw?p:p.value}));return Promise.allSettled(c).then(f=>{let p=[];for(let h of f)p.push(h.value);return p})}return Promise.resolve().then(()=>a?s.getMany(n):s.get(n)).then(c=>typeof c==\"string\"?this.opts.deserialize(c):this.opts.compression?this.opts.deserialize(c):c).then(c=>{if(c!=null)return a?c.map((f,p)=>{if(typeof f==\"string\"&&(f=this.opts.deserialize(f)),f!=null){if(typeof f.expires==\"number\"&&Date.now()>f.expires){this.delete(t[p]).then(()=>{});return}return r&&r.raw?f:f.value}}):typeof c.expires==\"number\"&&Date.now()>c.expires?this.delete(t).then(()=>{}):r&&r.raw?c:c.value})}set(t,r,s){let a=this._getKeyPrefix(t);typeof s>\"u\"&&(s=this.opts.ttl),s===0&&(s=void 0);let{store:n}=this.opts;return Promise.resolve().then(()=>{let c=typeof s==\"number\"?Date.now()+s:null;return typeof r==\"symbol\"&&this.emit(\"error\",\"symbol cannot be serialized\"),r={value:r,expires:c},this.opts.serialize(r)}).then(c=>n.set(a,c,s)).then(()=>!0)}delete(t){let{store:r}=this.opts;if(Array.isArray(t)){let a=this._getKeyPrefixArray(t);if(r.deleteMany===void 0){let n=[];for(let c of a)n.push(r.delete(c));return Promise.allSettled(n).then(c=>c.every(f=>f.value===!0))}return Promise.resolve().then(()=>r.deleteMany(a))}let s=this._getKeyPrefix(t);return Promise.resolve().then(()=>r.delete(s))}clear(){let{store:t}=this.opts;return Promise.resolve().then(()=>t.clear())}has(t){let r=this._getKeyPrefix(t),{store:s}=this.opts;return Promise.resolve().then(async()=>typeof s.has==\"function\"?s.has(r):await s.get(r)!==void 0)}disconnect(){let{store:t}=this.opts;if(typeof t.disconnect==\"function\")return t.disconnect()}};Tue.exports=X8});var Lue=G(($Nt,Oue)=>{\"use strict\";var i$e=Ie(\"events\"),VQ=Ie(\"url\"),s$e=aue(),o$e=Iue(),$8=wue(),Nue=Sue(),a$e=WQ(),l$e=xue(),c$e=Fue(),H2=class e{constructor(t,r){if(typeof t!=\"function\")throw new TypeError(\"Parameter `request` must be a function\");return this.cache=new c$e({uri:typeof r==\"string\"&&r,store:typeof r!=\"string\"&&r,namespace:\"cacheable-request\"}),this.createCacheableRequest(t)}createCacheableRequest(t){return(r,s)=>{let a;if(typeof r==\"string\")a=eH(VQ.parse(r)),r={};else if(r instanceof VQ.URL)a=eH(VQ.parse(r.toString())),r={};else{let[C,...S]=(r.path||\"\").split(\"?\"),x=S.length>0?`?${S.join(\"?\")}`:\"\";a=eH({...r,pathname:C,search:x})}r={headers:{},method:\"GET\",cache:!0,strictTtl:!1,automaticFailover:!1,...r,...u$e(a)},r.headers=a$e(r.headers);let n=new i$e,c=s$e(VQ.format(a),{stripWWW:!1,removeTrailingSlash:!1,stripAuthentication:!1}),f=`${r.method}:${c}`,p=!1,h=!1,E=C=>{h=!0;let S=!1,x,I=new Promise(O=>{x=()=>{S||(S=!0,O())}}),T=O=>{if(p&&!C.forceRefresh){O.status=O.statusCode;let Y=$8.fromObject(p.cachePolicy).revalidatedPolicy(C,O);if(!Y.modified){let te=Y.policy.responseHeaders();O=new Nue(p.statusCode,te,p.body,p.url),O.cachePolicy=Y.policy,O.fromCache=!0}}O.fromCache||(O.cachePolicy=new $8(C,O,C),O.fromCache=!1);let U;C.cache&&O.cachePolicy.storable()?(U=l$e(O),(async()=>{try{let Y=o$e.buffer(O);if(await Promise.race([I,new Promise(ae=>O.once(\"end\",ae))]),S)return;let te=await Y,ie={cachePolicy:O.cachePolicy.toObject(),url:O.url,statusCode:O.fromCache?p.statusCode:O.statusCode,body:te},ue=C.strictTtl?O.cachePolicy.timeToLive():void 0;C.maxTtl&&(ue=ue?Math.min(ue,C.maxTtl):C.maxTtl),await this.cache.set(f,ie,ue)}catch(Y){n.emit(\"error\",new e.CacheError(Y))}})()):C.cache&&p&&(async()=>{try{await this.cache.delete(f)}catch(Y){n.emit(\"error\",new e.CacheError(Y))}})(),n.emit(\"response\",U||O),typeof s==\"function\"&&s(U||O)};try{let O=t(C,T);O.once(\"error\",x),O.once(\"abort\",x),n.emit(\"request\",O)}catch(O){n.emit(\"error\",new e.RequestError(O))}};return(async()=>{let C=async x=>{await Promise.resolve();let I=x.cache?await this.cache.get(f):void 0;if(typeof I>\"u\")return E(x);let T=$8.fromObject(I.cachePolicy);if(T.satisfiesWithoutRevalidation(x)&&!x.forceRefresh){let O=T.responseHeaders(),U=new Nue(I.statusCode,O,I.body,I.url);U.cachePolicy=T,U.fromCache=!0,n.emit(\"response\",U),typeof s==\"function\"&&s(U)}else p=I,x.headers=T.revalidationHeaders(x),E(x)},S=x=>n.emit(\"error\",new e.CacheError(x));this.cache.once(\"error\",S),n.on(\"response\",()=>this.cache.removeListener(\"error\",S));try{await C(r)}catch(x){r.automaticFailover&&!h&&E(r),n.emit(\"error\",new e.CacheError(x))}})(),n}}};function u$e(e){let t={...e};return t.path=`${e.pathname||\"/\"}${e.search||\"\"}`,delete t.pathname,delete t.search,t}function eH(e){return{protocol:e.protocol,auth:e.auth,hostname:e.hostname||e.host||\"localhost\",port:e.port,pathname:e.pathname,search:e.search}}H2.RequestError=class extends Error{constructor(e){super(e.message),this.name=\"RequestError\",Object.assign(this,e)}};H2.CacheError=class extends Error{constructor(e){super(e.message),this.name=\"CacheError\",Object.assign(this,e)}};Oue.exports=H2});var Uue=G((rOt,Mue)=>{\"use strict\";var f$e=[\"aborted\",\"complete\",\"headers\",\"httpVersion\",\"httpVersionMinor\",\"httpVersionMajor\",\"method\",\"rawHeaders\",\"rawTrailers\",\"setTimeout\",\"socket\",\"statusCode\",\"statusMessage\",\"trailers\",\"url\"];Mue.exports=(e,t)=>{if(t._readableState.autoDestroy)throw new Error(\"The second stream must have the `autoDestroy` option set to `false`\");let r=new Set(Object.keys(e).concat(f$e)),s={};for(let a of r)a in t||(s[a]={get(){let n=e[a];return typeof n==\"function\"?n.bind(e):n},set(n){e[a]=n},enumerable:!0,configurable:!1});return Object.defineProperties(t,s),e.once(\"aborted\",()=>{t.destroy(),t.emit(\"aborted\")}),e.once(\"close\",()=>{e.complete&&t.readable?t.once(\"end\",()=>{t.emit(\"close\")}):t.emit(\"close\")}),t}});var Hue=G((nOt,_ue)=>{\"use strict\";var{Transform:A$e,PassThrough:p$e}=Ie(\"stream\"),tH=Ie(\"zlib\"),h$e=Uue();_ue.exports=e=>{let t=(e.headers[\"content-encoding\"]||\"\").toLowerCase();if(![\"gzip\",\"deflate\",\"br\"].includes(t))return e;let r=t===\"br\";if(r&&typeof tH.createBrotliDecompress!=\"function\")return e.destroy(new Error(\"Brotli is not supported on Node.js < 12\")),e;let s=!0,a=new A$e({transform(f,p,h){s=!1,h(null,f)},flush(f){f()}}),n=new p$e({autoDestroy:!1,destroy(f,p){e.destroy(),p(f)}}),c=r?tH.createBrotliDecompress():tH.createUnzip();return c.once(\"error\",f=>{if(s&&!e.readable){n.end();return}n.destroy(f)}),h$e(e,n),e.pipe(a).pipe(c).pipe(n),n}});var nH=G((iOt,jue)=>{\"use strict\";var rH=class{constructor(t={}){if(!(t.maxSize&&t.maxSize>0))throw new TypeError(\"`maxSize` must be a number greater than 0\");this.maxSize=t.maxSize,this.onEviction=t.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_set(t,r){if(this.cache.set(t,r),this._size++,this._size>=this.maxSize){if(this._size=0,typeof this.onEviction==\"function\")for(let[s,a]of this.oldCache.entries())this.onEviction(s,a);this.oldCache=this.cache,this.cache=new Map}}get(t){if(this.cache.has(t))return this.cache.get(t);if(this.oldCache.has(t)){let r=this.oldCache.get(t);return this.oldCache.delete(t),this._set(t,r),r}}set(t,r){return this.cache.has(t)?this.cache.set(t,r):this._set(t,r),this}has(t){return this.cache.has(t)||this.oldCache.has(t)}peek(t){if(this.cache.has(t))return this.cache.get(t);if(this.oldCache.has(t))return this.oldCache.get(t)}delete(t){let r=this.cache.delete(t);return r&&this._size--,this.oldCache.delete(t)||r}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}*keys(){for(let[t]of this)yield t}*values(){for(let[,t]of this)yield t}*[Symbol.iterator](){for(let t of this.cache)yield t;for(let t of this.oldCache){let[r]=t;this.cache.has(r)||(yield t)}}get size(){let t=0;for(let r of this.oldCache.keys())this.cache.has(r)||t++;return Math.min(this._size+t,this.maxSize)}};jue.exports=rH});var sH=G((sOt,Vue)=>{\"use strict\";var g$e=Ie(\"events\"),d$e=Ie(\"tls\"),m$e=Ie(\"http2\"),y$e=nH(),Qa=Symbol(\"currentStreamsCount\"),Gue=Symbol(\"request\"),Fc=Symbol(\"cachedOriginSet\"),yI=Symbol(\"gracefullyClosing\"),E$e=[\"maxDeflateDynamicTableSize\",\"maxSessionMemory\",\"maxHeaderListPairs\",\"maxOutstandingPings\",\"maxReservedRemoteStreams\",\"maxSendHeaderBlockLength\",\"paddingStrategy\",\"localAddress\",\"path\",\"rejectUnauthorized\",\"minDHSize\",\"ca\",\"cert\",\"clientCertEngine\",\"ciphers\",\"key\",\"pfx\",\"servername\",\"minVersion\",\"maxVersion\",\"secureProtocol\",\"crl\",\"honorCipherOrder\",\"ecdhCurve\",\"dhparam\",\"secureOptions\",\"sessionIdContext\"],I$e=(e,t,r)=>{let s=0,a=e.length;for(;s<a;){let n=s+a>>>1;r(e[n],t)?s=n+1:a=n}return s},C$e=(e,t)=>e.remoteSettings.maxConcurrentStreams>t.remoteSettings.maxConcurrentStreams,iH=(e,t)=>{for(let r of e)r[Fc].length<t[Fc].length&&r[Fc].every(s=>t[Fc].includes(s))&&r[Qa]+t[Qa]<=t.remoteSettings.maxConcurrentStreams&&Wue(r)},w$e=(e,t)=>{for(let r of e)t[Fc].length<r[Fc].length&&t[Fc].every(s=>r[Fc].includes(s))&&t[Qa]+r[Qa]<=r.remoteSettings.maxConcurrentStreams&&Wue(t)},que=({agent:e,isFree:t})=>{let r={};for(let s in e.sessions){let n=e.sessions[s].filter(c=>{let f=c[rm.kCurrentStreamsCount]<c.remoteSettings.maxConcurrentStreams;return t?f:!f});n.length!==0&&(r[s]=n)}return r},Wue=e=>{e[yI]=!0,e[Qa]===0&&e.close()},rm=class e extends g$e{constructor({timeout:t=6e4,maxSessions:r=1/0,maxFreeSessions:s=10,maxCachedTlsSessions:a=100}={}){super(),this.sessions={},this.queue={},this.timeout=t,this.maxSessions=r,this.maxFreeSessions=s,this._freeSessionsCount=0,this._sessionsCount=0,this.settings={enablePush:!1},this.tlsSessionCache=new y$e({maxSize:a})}static normalizeOrigin(t,r){return typeof t==\"string\"&&(t=new URL(t)),r&&t.hostname!==r&&(t.hostname=r),t.origin}normalizeOptions(t){let r=\"\";if(t)for(let s of E$e)t[s]&&(r+=`:${t[s]}`);return r}_tryToCreateNewSession(t,r){if(!(t in this.queue)||!(r in this.queue[t]))return;let s=this.queue[t][r];this._sessionsCount<this.maxSessions&&!s.completed&&(s.completed=!0,s())}getSession(t,r,s){return new Promise((a,n)=>{Array.isArray(s)?(s=[...s],a()):s=[{resolve:a,reject:n}];let c=this.normalizeOptions(r),f=e.normalizeOrigin(t,r&&r.servername);if(f===void 0){for(let{reject:E}of s)E(new TypeError(\"The `origin` argument needs to be a string or an URL object\"));return}if(c in this.sessions){let E=this.sessions[c],C=-1,S=-1,x;for(let I of E){let T=I.remoteSettings.maxConcurrentStreams;if(T<C)break;if(I[Fc].includes(f)){let O=I[Qa];if(O>=T||I[yI]||I.destroyed)continue;x||(C=T),O>S&&(x=I,S=O)}}if(x){if(s.length!==1){for(let{reject:I}of s){let T=new Error(`Expected the length of listeners to be 1, got ${s.length}.\nPlease report this to https://github.com/szmarczak/http2-wrapper/`);I(T)}return}s[0].resolve(x);return}}if(c in this.queue){if(f in this.queue[c]){this.queue[c][f].listeners.push(...s),this._tryToCreateNewSession(c,f);return}}else this.queue[c]={};let p=()=>{c in this.queue&&this.queue[c][f]===h&&(delete this.queue[c][f],Object.keys(this.queue[c]).length===0&&delete this.queue[c])},h=()=>{let E=`${f}:${c}`,C=!1;try{let S=m$e.connect(t,{createConnection:this.createConnection,settings:this.settings,session:this.tlsSessionCache.get(E),...r});S[Qa]=0,S[yI]=!1;let x=()=>S[Qa]<S.remoteSettings.maxConcurrentStreams,I=!0;S.socket.once(\"session\",O=>{this.tlsSessionCache.set(E,O)}),S.once(\"error\",O=>{for(let{reject:U}of s)U(O);this.tlsSessionCache.delete(E)}),S.setTimeout(this.timeout,()=>{S.destroy()}),S.once(\"close\",()=>{if(C){I&&this._freeSessionsCount--,this._sessionsCount--;let O=this.sessions[c];O.splice(O.indexOf(S),1),O.length===0&&delete this.sessions[c]}else{let O=new Error(\"Session closed without receiving a SETTINGS frame\");O.code=\"HTTP2WRAPPER_NOSETTINGS\";for(let{reject:U}of s)U(O);p()}this._tryToCreateNewSession(c,f)});let T=()=>{if(!(!(c in this.queue)||!x())){for(let O of S[Fc])if(O in this.queue[c]){let{listeners:U}=this.queue[c][O];for(;U.length!==0&&x();)U.shift().resolve(S);let Y=this.queue[c];if(Y[O].listeners.length===0&&(delete Y[O],Object.keys(Y).length===0)){delete this.queue[c];break}if(!x())break}}};S.on(\"origin\",()=>{S[Fc]=S.originSet,x()&&(T(),iH(this.sessions[c],S))}),S.once(\"remoteSettings\",()=>{if(S.ref(),S.unref(),this._sessionsCount++,h.destroyed){let O=new Error(\"Agent has been destroyed\");for(let U of s)U.reject(O);S.destroy();return}S[Fc]=S.originSet;{let O=this.sessions;if(c in O){let U=O[c];U.splice(I$e(U,S,C$e),0,S)}else O[c]=[S]}this._freeSessionsCount+=1,C=!0,this.emit(\"session\",S),T(),p(),S[Qa]===0&&this._freeSessionsCount>this.maxFreeSessions&&S.close(),s.length!==0&&(this.getSession(f,r,s),s.length=0),S.on(\"remoteSettings\",()=>{T(),iH(this.sessions[c],S)})}),S[Gue]=S.request,S.request=(O,U)=>{if(S[yI])throw new Error(\"The session is gracefully closing. No new streams are allowed.\");let Y=S[Gue](O,U);return S.ref(),++S[Qa],S[Qa]===S.remoteSettings.maxConcurrentStreams&&this._freeSessionsCount--,Y.once(\"close\",()=>{if(I=x(),--S[Qa],!S.destroyed&&!S.closed&&(w$e(this.sessions[c],S),x()&&!S.closed)){I||(this._freeSessionsCount++,I=!0);let te=S[Qa]===0;te&&S.unref(),te&&(this._freeSessionsCount>this.maxFreeSessions||S[yI])?S.close():(iH(this.sessions[c],S),T())}}),Y}}catch(S){for(let x of s)x.reject(S);p()}};h.listeners=s,h.completed=!1,h.destroyed=!1,this.queue[c][f]=h,this._tryToCreateNewSession(c,f)})}request(t,r,s,a){return new Promise((n,c)=>{this.getSession(t,r,[{reject:c,resolve:f=>{try{n(f.request(s,a))}catch(p){c(p)}}}])})}createConnection(t,r){return e.connect(t,r)}static connect(t,r){r.ALPNProtocols=[\"h2\"];let s=t.port||443,a=t.hostname||t.host;return typeof r.servername>\"u\"&&(r.servername=a),d$e.connect(s,a,r)}closeFreeSessions(){for(let t of Object.values(this.sessions))for(let r of t)r[Qa]===0&&r.close()}destroy(t){for(let r of Object.values(this.sessions))for(let s of r)s.destroy(t);for(let r of Object.values(this.queue))for(let s of Object.values(r))s.destroyed=!0;this.queue={}}get freeSessions(){return que({agent:this,isFree:!0})}get busySessions(){return que({agent:this,isFree:!1})}};rm.kCurrentStreamsCount=Qa;rm.kGracefullyClosing=yI;Vue.exports={Agent:rm,globalAgent:new rm}});var aH=G((oOt,Yue)=>{\"use strict\";var{Readable:B$e}=Ie(\"stream\"),oH=class extends B$e{constructor(t,r){super({highWaterMark:r,autoDestroy:!1}),this.statusCode=null,this.statusMessage=\"\",this.httpVersion=\"2.0\",this.httpVersionMajor=2,this.httpVersionMinor=0,this.headers={},this.trailers={},this.req=null,this.aborted=!1,this.complete=!1,this.upgrade=null,this.rawHeaders=[],this.rawTrailers=[],this.socket=t,this.connection=t,this._dumped=!1}_destroy(t){this.req._request.destroy(t)}setTimeout(t,r){return this.req.setTimeout(t,r),this}_dump(){this._dumped||(this._dumped=!0,this.removeAllListeners(\"data\"),this.resume())}_read(){this.req&&this.req._request.resume()}};Yue.exports=oH});var lH=G((aOt,Kue)=>{\"use strict\";Kue.exports=e=>{let t={protocol:e.protocol,hostname:typeof e.hostname==\"string\"&&e.hostname.startsWith(\"[\")?e.hostname.slice(1,-1):e.hostname,host:e.host,hash:e.hash,search:e.search,pathname:e.pathname,href:e.href,path:`${e.pathname||\"\"}${e.search||\"\"}`};return typeof e.port==\"string\"&&e.port.length!==0&&(t.port=Number(e.port)),(e.username||e.password)&&(t.auth=`${e.username||\"\"}:${e.password||\"\"}`),t}});var zue=G((lOt,Jue)=>{\"use strict\";Jue.exports=(e,t,r)=>{for(let s of r)e.on(s,(...a)=>t.emit(s,...a))}});var Xue=G((cOt,Zue)=>{\"use strict\";Zue.exports=e=>{switch(e){case\":method\":case\":scheme\":case\":authority\":case\":path\":return!0;default:return!1}}});var efe=G((fOt,$ue)=>{\"use strict\";var EI=(e,t,r)=>{$ue.exports[t]=class extends e{constructor(...a){super(typeof r==\"string\"?r:r(a)),this.name=`${super.name} [${t}]`,this.code=t}}};EI(TypeError,\"ERR_INVALID_ARG_TYPE\",e=>{let t=e[0].includes(\".\")?\"property\":\"argument\",r=e[1],s=Array.isArray(r);return s&&(r=`${r.slice(0,-1).join(\", \")} or ${r.slice(-1)}`),`The \"${e[0]}\" ${t} must be ${s?\"one of\":\"of\"} type ${r}. Received ${typeof e[2]}`});EI(TypeError,\"ERR_INVALID_PROTOCOL\",e=>`Protocol \"${e[0]}\" not supported. Expected \"${e[1]}\"`);EI(Error,\"ERR_HTTP_HEADERS_SENT\",e=>`Cannot ${e[0]} headers after they are sent to the client`);EI(TypeError,\"ERR_INVALID_HTTP_TOKEN\",e=>`${e[0]} must be a valid HTTP token [${e[1]}]`);EI(TypeError,\"ERR_HTTP_INVALID_HEADER_VALUE\",e=>`Invalid value \"${e[0]} for header \"${e[1]}\"`);EI(TypeError,\"ERR_INVALID_CHAR\",e=>`Invalid character in ${e[0]} [${e[1]}]`)});var pH=G((AOt,afe)=>{\"use strict\";var v$e=Ie(\"http2\"),{Writable:S$e}=Ie(\"stream\"),{Agent:tfe,globalAgent:D$e}=sH(),b$e=aH(),P$e=lH(),x$e=zue(),k$e=Xue(),{ERR_INVALID_ARG_TYPE:cH,ERR_INVALID_PROTOCOL:Q$e,ERR_HTTP_HEADERS_SENT:rfe,ERR_INVALID_HTTP_TOKEN:R$e,ERR_HTTP_INVALID_HEADER_VALUE:T$e,ERR_INVALID_CHAR:F$e}=efe(),{HTTP2_HEADER_STATUS:nfe,HTTP2_HEADER_METHOD:ife,HTTP2_HEADER_PATH:sfe,HTTP2_METHOD_CONNECT:N$e}=v$e.constants,ea=Symbol(\"headers\"),uH=Symbol(\"origin\"),fH=Symbol(\"session\"),ofe=Symbol(\"options\"),YQ=Symbol(\"flushedHeaders\"),j2=Symbol(\"jobs\"),O$e=/^[\\^`\\-\\w!#$%&*+.|~]+$/,L$e=/[^\\t\\u0020-\\u007E\\u0080-\\u00FF]/,AH=class extends S$e{constructor(t,r,s){super({autoDestroy:!1});let a=typeof t==\"string\"||t instanceof URL;if(a&&(t=P$e(t instanceof URL?t:new URL(t))),typeof r==\"function\"||r===void 0?(s=r,r=a?t:{...t}):r={...t,...r},r.h2session)this[fH]=r.h2session;else if(r.agent===!1)this.agent=new tfe({maxFreeSessions:0});else if(typeof r.agent>\"u\"||r.agent===null)typeof r.createConnection==\"function\"?(this.agent=new tfe({maxFreeSessions:0}),this.agent.createConnection=r.createConnection):this.agent=D$e;else if(typeof r.agent.request==\"function\")this.agent=r.agent;else throw new cH(\"options.agent\",[\"Agent-like Object\",\"undefined\",\"false\"],r.agent);if(r.protocol&&r.protocol!==\"https:\")throw new Q$e(r.protocol,\"https:\");let n=r.port||r.defaultPort||this.agent&&this.agent.defaultPort||443,c=r.hostname||r.host||\"localhost\";delete r.hostname,delete r.host,delete r.port;let{timeout:f}=r;if(r.timeout=void 0,this[ea]=Object.create(null),this[j2]=[],this.socket=null,this.connection=null,this.method=r.method||\"GET\",this.path=r.path,this.res=null,this.aborted=!1,this.reusedSocket=!1,r.headers)for(let[p,h]of Object.entries(r.headers))this.setHeader(p,h);r.auth&&!(\"authorization\"in this[ea])&&(this[ea].authorization=\"Basic \"+Buffer.from(r.auth).toString(\"base64\")),r.session=r.tlsSession,r.path=r.socketPath,this[ofe]=r,n===443?(this[uH]=`https://${c}`,\":authority\"in this[ea]||(this[ea][\":authority\"]=c)):(this[uH]=`https://${c}:${n}`,\":authority\"in this[ea]||(this[ea][\":authority\"]=`${c}:${n}`)),f&&this.setTimeout(f),s&&this.once(\"response\",s),this[YQ]=!1}get method(){return this[ea][ife]}set method(t){t&&(this[ea][ife]=t.toUpperCase())}get path(){return this[ea][sfe]}set path(t){t&&(this[ea][sfe]=t)}get _mustNotHaveABody(){return this.method===\"GET\"||this.method===\"HEAD\"||this.method===\"DELETE\"}_write(t,r,s){if(this._mustNotHaveABody){s(new Error(\"The GET, HEAD and DELETE methods must NOT have a body\"));return}this.flushHeaders();let a=()=>this._request.write(t,r,s);this._request?a():this[j2].push(a)}_final(t){if(this.destroyed)return;this.flushHeaders();let r=()=>{if(this._mustNotHaveABody){t();return}this._request.end(t)};this._request?r():this[j2].push(r)}abort(){this.res&&this.res.complete||(this.aborted||process.nextTick(()=>this.emit(\"abort\")),this.aborted=!0,this.destroy())}_destroy(t,r){this.res&&this.res._dump(),this._request&&this._request.destroy(),r(t)}async flushHeaders(){if(this[YQ]||this.destroyed)return;this[YQ]=!0;let t=this.method===N$e,r=s=>{if(this._request=s,this.destroyed){s.destroy();return}t||x$e(s,this,[\"timeout\",\"continue\",\"close\",\"error\"]);let a=c=>(...f)=>{!this.writable&&!this.destroyed?c(...f):this.once(\"finish\",()=>{c(...f)})};s.once(\"response\",a((c,f,p)=>{let h=new b$e(this.socket,s.readableHighWaterMark);this.res=h,h.req=this,h.statusCode=c[nfe],h.headers=c,h.rawHeaders=p,h.once(\"end\",()=>{this.aborted?(h.aborted=!0,h.emit(\"aborted\")):(h.complete=!0,h.socket=null,h.connection=null)}),t?(h.upgrade=!0,this.emit(\"connect\",h,s,Buffer.alloc(0))?this.emit(\"close\"):s.destroy()):(s.on(\"data\",E=>{!h._dumped&&!h.push(E)&&s.pause()}),s.once(\"end\",()=>{h.push(null)}),this.emit(\"response\",h)||h._dump())})),s.once(\"headers\",a(c=>this.emit(\"information\",{statusCode:c[nfe]}))),s.once(\"trailers\",a((c,f,p)=>{let{res:h}=this;h.trailers=c,h.rawTrailers=p}));let{socket:n}=s.session;this.socket=n,this.connection=n;for(let c of this[j2])c();this.emit(\"socket\",this.socket)};if(this[fH])try{r(this[fH].request(this[ea]))}catch(s){this.emit(\"error\",s)}else{this.reusedSocket=!0;try{r(await this.agent.request(this[uH],this[ofe],this[ea]))}catch(s){this.emit(\"error\",s)}}}getHeader(t){if(typeof t!=\"string\")throw new cH(\"name\",\"string\",t);return this[ea][t.toLowerCase()]}get headersSent(){return this[YQ]}removeHeader(t){if(typeof t!=\"string\")throw new cH(\"name\",\"string\",t);if(this.headersSent)throw new rfe(\"remove\");delete this[ea][t.toLowerCase()]}setHeader(t,r){if(this.headersSent)throw new rfe(\"set\");if(typeof t!=\"string\"||!O$e.test(t)&&!k$e(t))throw new R$e(\"Header name\",t);if(typeof r>\"u\")throw new T$e(r,t);if(L$e.test(r))throw new F$e(\"header content\",t);this[ea][t.toLowerCase()]=r}setNoDelay(){}setSocketKeepAlive(){}setTimeout(t,r){let s=()=>this._request.setTimeout(t,r);return this._request?s():this[j2].push(s),this}get maxHeadersCount(){if(!this.destroyed&&this._request)return this._request.session.localSettings.maxHeaderListSize}set maxHeadersCount(t){}};afe.exports=AH});var cfe=G((pOt,lfe)=>{\"use strict\";var M$e=Ie(\"tls\");lfe.exports=(e={},t=M$e.connect)=>new Promise((r,s)=>{let a=!1,n,c=async()=>{await p,n.off(\"timeout\",f),n.off(\"error\",s),e.resolveSocket?(r({alpnProtocol:n.alpnProtocol,socket:n,timeout:a}),a&&(await Promise.resolve(),n.emit(\"timeout\"))):(n.destroy(),r({alpnProtocol:n.alpnProtocol,timeout:a}))},f=async()=>{a=!0,c()},p=(async()=>{try{n=await t(e,c),n.on(\"error\",s),n.once(\"timeout\",f)}catch(h){s(h)}})()})});var ffe=G((hOt,ufe)=>{\"use strict\";var U$e=Ie(\"net\");ufe.exports=e=>{let t=e.host,r=e.headers&&e.headers.host;return r&&(r.startsWith(\"[\")?r.indexOf(\"]\")===-1?t=r:t=r.slice(1,-1):t=r.split(\":\",1)[0]),U$e.isIP(t)?\"\":t}});var hfe=G((gOt,gH)=>{\"use strict\";var Afe=Ie(\"http\"),hH=Ie(\"https\"),_$e=cfe(),H$e=nH(),j$e=pH(),G$e=ffe(),q$e=lH(),KQ=new H$e({maxSize:100}),G2=new Map,pfe=(e,t,r)=>{t._httpMessage={shouldKeepAlive:!0};let s=()=>{e.emit(\"free\",t,r)};t.on(\"free\",s);let a=()=>{e.removeSocket(t,r)};t.on(\"close\",a);let n=()=>{e.removeSocket(t,r),t.off(\"close\",a),t.off(\"free\",s),t.off(\"agentRemove\",n)};t.on(\"agentRemove\",n),e.emit(\"free\",t,r)},W$e=async e=>{let t=`${e.host}:${e.port}:${e.ALPNProtocols.sort()}`;if(!KQ.has(t)){if(G2.has(t))return(await G2.get(t)).alpnProtocol;let{path:r,agent:s}=e;e.path=e.socketPath;let a=_$e(e);G2.set(t,a);try{let{socket:n,alpnProtocol:c}=await a;if(KQ.set(t,c),e.path=r,c===\"h2\")n.destroy();else{let{globalAgent:f}=hH,p=hH.Agent.prototype.createConnection;s?s.createConnection===p?pfe(s,n,e):n.destroy():f.createConnection===p?pfe(f,n,e):n.destroy()}return G2.delete(t),c}catch(n){throw G2.delete(t),n}}return KQ.get(t)};gH.exports=async(e,t,r)=>{if((typeof e==\"string\"||e instanceof URL)&&(e=q$e(new URL(e))),typeof t==\"function\"&&(r=t,t=void 0),t={ALPNProtocols:[\"h2\",\"http/1.1\"],...e,...t,resolveSocket:!0},!Array.isArray(t.ALPNProtocols)||t.ALPNProtocols.length===0)throw new Error(\"The `ALPNProtocols` option must be an Array with at least one entry\");t.protocol=t.protocol||\"https:\";let s=t.protocol===\"https:\";t.host=t.hostname||t.host||\"localhost\",t.session=t.tlsSession,t.servername=t.servername||G$e(t),t.port=t.port||(s?443:80),t._defaultAgent=s?hH.globalAgent:Afe.globalAgent;let a=t.agent;if(a){if(a.addRequest)throw new Error(\"The `options.agent` object can contain only `http`, `https` or `http2` properties\");t.agent=a[s?\"https\":\"http\"]}return s&&await W$e(t)===\"h2\"?(a&&(t.agent=a.http2),new j$e(t,r)):Afe.request(t,r)};gH.exports.protocolCache=KQ});var dfe=G((dOt,gfe)=>{\"use strict\";var V$e=Ie(\"http2\"),Y$e=sH(),dH=pH(),K$e=aH(),J$e=hfe(),z$e=(e,t,r)=>new dH(e,t,r),Z$e=(e,t,r)=>{let s=new dH(e,t,r);return s.end(),s};gfe.exports={...V$e,ClientRequest:dH,IncomingMessage:K$e,...Y$e,request:z$e,get:Z$e,auto:J$e}});var yH=G(mH=>{\"use strict\";Object.defineProperty(mH,\"__esModule\",{value:!0});var mfe=Op();mH.default=e=>mfe.default.nodeStream(e)&&mfe.default.function_(e.getBoundary)});var Cfe=G(EH=>{\"use strict\";Object.defineProperty(EH,\"__esModule\",{value:!0});var Efe=Ie(\"fs\"),Ife=Ie(\"util\"),yfe=Op(),X$e=yH(),$$e=Ife.promisify(Efe.stat);EH.default=async(e,t)=>{if(t&&\"content-length\"in t)return Number(t[\"content-length\"]);if(!e)return 0;if(yfe.default.string(e))return Buffer.byteLength(e);if(yfe.default.buffer(e))return e.length;if(X$e.default(e))return Ife.promisify(e.getLength.bind(e))();if(e instanceof Efe.ReadStream){let{size:r}=await $$e(e.path);return r===0?void 0:r}}});var CH=G(IH=>{\"use strict\";Object.defineProperty(IH,\"__esModule\",{value:!0});function eet(e,t,r){let s={};for(let a of r)s[a]=(...n)=>{t.emit(a,...n)},e.on(a,s[a]);return()=>{for(let a of r)e.off(a,s[a])}}IH.default=eet});var wfe=G(wH=>{\"use strict\";Object.defineProperty(wH,\"__esModule\",{value:!0});wH.default=()=>{let e=[];return{once(t,r,s){t.once(r,s),e.push({origin:t,event:r,fn:s})},unhandleAll(){for(let t of e){let{origin:r,event:s,fn:a}=t;r.removeListener(s,a)}e.length=0}}}});var vfe=G(q2=>{\"use strict\";Object.defineProperty(q2,\"__esModule\",{value:!0});q2.TimeoutError=void 0;var tet=Ie(\"net\"),ret=wfe(),Bfe=Symbol(\"reentry\"),net=()=>{},JQ=class extends Error{constructor(t,r){super(`Timeout awaiting '${r}' for ${t}ms`),this.event=r,this.name=\"TimeoutError\",this.code=\"ETIMEDOUT\"}};q2.TimeoutError=JQ;q2.default=(e,t,r)=>{if(Bfe in e)return net;e[Bfe]=!0;let s=[],{once:a,unhandleAll:n}=ret.default(),c=(C,S,x)=>{var I;let T=setTimeout(S,C,C,x);(I=T.unref)===null||I===void 0||I.call(T);let O=()=>{clearTimeout(T)};return s.push(O),O},{host:f,hostname:p}=r,h=(C,S)=>{e.destroy(new JQ(C,S))},E=()=>{for(let C of s)C();n()};if(e.once(\"error\",C=>{if(E(),e.listenerCount(\"error\")===0)throw C}),e.once(\"close\",E),a(e,\"response\",C=>{a(C,\"end\",E)}),typeof t.request<\"u\"&&c(t.request,h,\"request\"),typeof t.socket<\"u\"){let C=()=>{h(t.socket,\"socket\")};e.setTimeout(t.socket,C),s.push(()=>{e.removeListener(\"timeout\",C)})}return a(e,\"socket\",C=>{var S;let{socketPath:x}=e;if(C.connecting){let I=!!(x??tet.isIP((S=p??f)!==null&&S!==void 0?S:\"\")!==0);if(typeof t.lookup<\"u\"&&!I&&typeof C.address().address>\"u\"){let T=c(t.lookup,h,\"lookup\");a(C,\"lookup\",T)}if(typeof t.connect<\"u\"){let T=()=>c(t.connect,h,\"connect\");I?a(C,\"connect\",T()):a(C,\"lookup\",O=>{O===null&&a(C,\"connect\",T())})}typeof t.secureConnect<\"u\"&&r.protocol===\"https:\"&&a(C,\"connect\",()=>{let T=c(t.secureConnect,h,\"secureConnect\");a(C,\"secureConnect\",T)})}if(typeof t.send<\"u\"){let I=()=>c(t.send,h,\"send\");C.connecting?a(C,\"connect\",()=>{a(e,\"upload-complete\",I())}):a(e,\"upload-complete\",I())}}),typeof t.response<\"u\"&&a(e,\"upload-complete\",()=>{let C=c(t.response,h,\"response\");a(e,\"response\",C)}),E}});var Dfe=G(BH=>{\"use strict\";Object.defineProperty(BH,\"__esModule\",{value:!0});var Sfe=Op();BH.default=e=>{e=e;let t={protocol:e.protocol,hostname:Sfe.default.string(e.hostname)&&e.hostname.startsWith(\"[\")?e.hostname.slice(1,-1):e.hostname,host:e.host,hash:e.hash,search:e.search,pathname:e.pathname,href:e.href,path:`${e.pathname||\"\"}${e.search||\"\"}`};return Sfe.default.string(e.port)&&e.port.length>0&&(t.port=Number(e.port)),(e.username||e.password)&&(t.auth=`${e.username||\"\"}:${e.password||\"\"}`),t}});var bfe=G(vH=>{\"use strict\";Object.defineProperty(vH,\"__esModule\",{value:!0});var iet=Ie(\"url\"),set=[\"protocol\",\"host\",\"hostname\",\"port\",\"pathname\",\"search\"];vH.default=(e,t)=>{var r,s;if(t.path){if(t.pathname)throw new TypeError(\"Parameters `path` and `pathname` are mutually exclusive.\");if(t.search)throw new TypeError(\"Parameters `path` and `search` are mutually exclusive.\");if(t.searchParams)throw new TypeError(\"Parameters `path` and `searchParams` are mutually exclusive.\")}if(t.search&&t.searchParams)throw new TypeError(\"Parameters `search` and `searchParams` are mutually exclusive.\");if(!e){if(!t.protocol)throw new TypeError(\"No URL protocol specified\");e=`${t.protocol}//${(s=(r=t.hostname)!==null&&r!==void 0?r:t.host)!==null&&s!==void 0?s:\"\"}`}let a=new iet.URL(e);if(t.path){let n=t.path.indexOf(\"?\");n===-1?t.pathname=t.path:(t.pathname=t.path.slice(0,n),t.search=t.path.slice(n+1)),delete t.path}for(let n of set)t[n]&&(a[n]=t[n].toString());return a}});var Pfe=G(DH=>{\"use strict\";Object.defineProperty(DH,\"__esModule\",{value:!0});var SH=class{constructor(){this.weakMap=new WeakMap,this.map=new Map}set(t,r){typeof t==\"object\"?this.weakMap.set(t,r):this.map.set(t,r)}get(t){return typeof t==\"object\"?this.weakMap.get(t):this.map.get(t)}has(t){return typeof t==\"object\"?this.weakMap.has(t):this.map.has(t)}};DH.default=SH});var PH=G(bH=>{\"use strict\";Object.defineProperty(bH,\"__esModule\",{value:!0});var oet=async e=>{let t=[],r=0;for await(let s of e)t.push(s),r+=Buffer.byteLength(s);return Buffer.isBuffer(t[0])?Buffer.concat(t,r):Buffer.from(t.join(\"\"))};bH.default=oet});var kfe=G(nm=>{\"use strict\";Object.defineProperty(nm,\"__esModule\",{value:!0});nm.dnsLookupIpVersionToFamily=nm.isDnsLookupIpVersion=void 0;var xfe={auto:0,ipv4:4,ipv6:6};nm.isDnsLookupIpVersion=e=>e in xfe;nm.dnsLookupIpVersionToFamily=e=>{if(nm.isDnsLookupIpVersion(e))return xfe[e];throw new Error(\"Invalid DNS lookup IP version\")}});var xH=G(zQ=>{\"use strict\";Object.defineProperty(zQ,\"__esModule\",{value:!0});zQ.isResponseOk=void 0;zQ.isResponseOk=e=>{let{statusCode:t}=e,r=e.request.options.followRedirect?299:399;return t>=200&&t<=r||t===304}});var Rfe=G(kH=>{\"use strict\";Object.defineProperty(kH,\"__esModule\",{value:!0});var Qfe=new Set;kH.default=e=>{Qfe.has(e)||(Qfe.add(e),process.emitWarning(`Got: ${e}`,{type:\"DeprecationWarning\"}))}});var Tfe=G(QH=>{\"use strict\";Object.defineProperty(QH,\"__esModule\",{value:!0});var Di=Op(),aet=(e,t)=>{if(Di.default.null_(e.encoding))throw new TypeError(\"To get a Buffer, set `options.responseType` to `buffer` instead\");Di.assert.any([Di.default.string,Di.default.undefined],e.encoding),Di.assert.any([Di.default.boolean,Di.default.undefined],e.resolveBodyOnly),Di.assert.any([Di.default.boolean,Di.default.undefined],e.methodRewriting),Di.assert.any([Di.default.boolean,Di.default.undefined],e.isStream),Di.assert.any([Di.default.string,Di.default.undefined],e.responseType),e.responseType===void 0&&(e.responseType=\"text\");let{retry:r}=e;if(t?e.retry={...t.retry}:e.retry={calculateDelay:s=>s.computedValue,limit:0,methods:[],statusCodes:[],errorCodes:[],maxRetryAfter:void 0},Di.default.object(r)?(e.retry={...e.retry,...r},e.retry.methods=[...new Set(e.retry.methods.map(s=>s.toUpperCase()))],e.retry.statusCodes=[...new Set(e.retry.statusCodes)],e.retry.errorCodes=[...new Set(e.retry.errorCodes)]):Di.default.number(r)&&(e.retry.limit=r),Di.default.undefined(e.retry.maxRetryAfter)&&(e.retry.maxRetryAfter=Math.min(...[e.timeout.request,e.timeout.connect].filter(Di.default.number))),Di.default.object(e.pagination)){t&&(e.pagination={...t.pagination,...e.pagination});let{pagination:s}=e;if(!Di.default.function_(s.transform))throw new Error(\"`options.pagination.transform` must be implemented\");if(!Di.default.function_(s.shouldContinue))throw new Error(\"`options.pagination.shouldContinue` must be implemented\");if(!Di.default.function_(s.filter))throw new TypeError(\"`options.pagination.filter` must be implemented\");if(!Di.default.function_(s.paginate))throw new Error(\"`options.pagination.paginate` must be implemented\")}return e.responseType===\"json\"&&e.headers.accept===void 0&&(e.headers.accept=\"application/json\"),e};QH.default=aet});var Ffe=G(W2=>{\"use strict\";Object.defineProperty(W2,\"__esModule\",{value:!0});W2.retryAfterStatusCodes=void 0;W2.retryAfterStatusCodes=new Set([413,429,503]);var cet=({attemptCount:e,retryOptions:t,error:r,retryAfter:s})=>{if(e>t.limit)return 0;let a=t.methods.includes(r.options.method),n=t.errorCodes.includes(r.code),c=r.response&&t.statusCodes.includes(r.response.statusCode);if(!a||!n&&!c)return 0;if(r.response){if(s)return t.maxRetryAfter===void 0||s>t.maxRetryAfter?0:s;if(r.response.statusCode===413)return 0}let f=Math.random()*100;return 2**(e-1)*1e3+f};W2.default=cet});var K2=G(Un=>{\"use strict\";Object.defineProperty(Un,\"__esModule\",{value:!0});Un.UnsupportedProtocolError=Un.ReadError=Un.TimeoutError=Un.UploadError=Un.CacheError=Un.HTTPError=Un.MaxRedirectsError=Un.RequestError=Un.setNonEnumerableProperties=Un.knownHookEvents=Un.withoutBody=Un.kIsNormalizedAlready=void 0;var Nfe=Ie(\"util\"),Ofe=Ie(\"stream\"),uet=Ie(\"fs\"),I0=Ie(\"url\"),Lfe=Ie(\"http\"),RH=Ie(\"http\"),fet=Ie(\"https\"),Aet=Zce(),pet=iue(),Mfe=Lue(),het=Hue(),get=dfe(),det=WQ(),lt=Op(),met=Cfe(),Ufe=yH(),yet=CH(),_fe=vfe(),Eet=Dfe(),Hfe=bfe(),Iet=Pfe(),Cet=PH(),jfe=kfe(),wet=xH(),C0=Rfe(),Bet=Tfe(),vet=Ffe(),TH,Eo=Symbol(\"request\"),$Q=Symbol(\"response\"),II=Symbol(\"responseSize\"),CI=Symbol(\"downloadedSize\"),wI=Symbol(\"bodySize\"),BI=Symbol(\"uploadedSize\"),ZQ=Symbol(\"serverResponsesPiped\"),Gfe=Symbol(\"unproxyEvents\"),qfe=Symbol(\"isFromCache\"),FH=Symbol(\"cancelTimeouts\"),Wfe=Symbol(\"startedReading\"),vI=Symbol(\"stopReading\"),XQ=Symbol(\"triggerRead\"),w0=Symbol(\"body\"),V2=Symbol(\"jobs\"),Vfe=Symbol(\"originalResponse\"),Yfe=Symbol(\"retryTimeout\");Un.kIsNormalizedAlready=Symbol(\"isNormalizedAlready\");var Det=lt.default.string(process.versions.brotli);Un.withoutBody=new Set([\"GET\",\"HEAD\"]);Un.knownHookEvents=[\"init\",\"beforeRequest\",\"beforeRedirect\",\"beforeError\",\"beforeRetry\",\"afterResponse\"];function bet(e){for(let t in e){let r=e[t];if(!lt.default.string(r)&&!lt.default.number(r)&&!lt.default.boolean(r)&&!lt.default.null_(r)&&!lt.default.undefined(r))throw new TypeError(`The \\`searchParams\\` value '${String(r)}' must be a string, number, boolean or null`)}}function Pet(e){return lt.default.object(e)&&!(\"statusCode\"in e)}var NH=new Iet.default,xet=async e=>new Promise((t,r)=>{let s=a=>{r(a)};e.pending||t(),e.once(\"error\",s),e.once(\"ready\",()=>{e.off(\"error\",s),t()})}),ket=new Set([300,301,302,303,304,307,308]),Qet=[\"context\",\"body\",\"json\",\"form\"];Un.setNonEnumerableProperties=(e,t)=>{let r={};for(let s of e)if(s)for(let a of Qet)a in s&&(r[a]={writable:!0,configurable:!0,enumerable:!1,value:s[a]});Object.defineProperties(t,r)};var As=class extends Error{constructor(t,r,s){var a;if(super(t),Error.captureStackTrace(this,this.constructor),this.name=\"RequestError\",this.code=r.code,s instanceof oR?(Object.defineProperty(this,\"request\",{enumerable:!1,value:s}),Object.defineProperty(this,\"response\",{enumerable:!1,value:s[$Q]}),Object.defineProperty(this,\"options\",{enumerable:!1,value:s.options})):Object.defineProperty(this,\"options\",{enumerable:!1,value:s}),this.timings=(a=this.request)===null||a===void 0?void 0:a.timings,lt.default.string(r.stack)&&lt.default.string(this.stack)){let n=this.stack.indexOf(this.message)+this.message.length,c=this.stack.slice(n).split(`\n`).reverse(),f=r.stack.slice(r.stack.indexOf(r.message)+r.message.length).split(`\n`).reverse();for(;f.length!==0&&f[0]===c[0];)c.shift();this.stack=`${this.stack.slice(0,n)}${c.reverse().join(`\n`)}${f.reverse().join(`\n`)}`}}};Un.RequestError=As;var eR=class extends As{constructor(t){super(`Redirected ${t.options.maxRedirects} times. Aborting.`,{},t),this.name=\"MaxRedirectsError\"}};Un.MaxRedirectsError=eR;var tR=class extends As{constructor(t){super(`Response code ${t.statusCode} (${t.statusMessage})`,{},t.request),this.name=\"HTTPError\"}};Un.HTTPError=tR;var rR=class extends As{constructor(t,r){super(t.message,t,r),this.name=\"CacheError\"}};Un.CacheError=rR;var nR=class extends As{constructor(t,r){super(t.message,t,r),this.name=\"UploadError\"}};Un.UploadError=nR;var iR=class extends As{constructor(t,r,s){super(t.message,t,s),this.name=\"TimeoutError\",this.event=t.event,this.timings=r}};Un.TimeoutError=iR;var Y2=class extends As{constructor(t,r){super(t.message,t,r),this.name=\"ReadError\"}};Un.ReadError=Y2;var sR=class extends As{constructor(t){super(`Unsupported protocol \"${t.url.protocol}\"`,{},t),this.name=\"UnsupportedProtocolError\"}};Un.UnsupportedProtocolError=sR;var Ret=[\"socket\",\"connect\",\"continue\",\"information\",\"upgrade\",\"timeout\"],oR=class extends Ofe.Duplex{constructor(t,r={},s){super({autoDestroy:!1,highWaterMark:0}),this[CI]=0,this[BI]=0,this.requestInitialized=!1,this[ZQ]=new Set,this.redirects=[],this[vI]=!1,this[XQ]=!1,this[V2]=[],this.retryCount=0,this._progressCallbacks=[];let a=()=>this._unlockWrite(),n=()=>this._lockWrite();this.on(\"pipe\",h=>{h.prependListener(\"data\",a),h.on(\"data\",n),h.prependListener(\"end\",a),h.on(\"end\",n)}),this.on(\"unpipe\",h=>{h.off(\"data\",a),h.off(\"data\",n),h.off(\"end\",a),h.off(\"end\",n)}),this.on(\"pipe\",h=>{h instanceof RH.IncomingMessage&&(this.options.headers={...h.headers,...this.options.headers})});let{json:c,body:f,form:p}=r;if((c||f||p)&&this._lockWrite(),Un.kIsNormalizedAlready in r)this.options=r;else try{this.options=this.constructor.normalizeArguments(t,r,s)}catch(h){lt.default.nodeStream(r.body)&&r.body.destroy(),this.destroy(h);return}(async()=>{var h;try{this.options.body instanceof uet.ReadStream&&await xet(this.options.body);let{url:E}=this.options;if(!E)throw new TypeError(\"Missing `url` property\");if(this.requestUrl=E.toString(),decodeURI(this.requestUrl),await this._finalizeBody(),await this._makeRequest(),this.destroyed){(h=this[Eo])===null||h===void 0||h.destroy();return}for(let C of this[V2])C();this[V2].length=0,this.requestInitialized=!0}catch(E){if(E instanceof As){this._beforeError(E);return}this.destroyed||this.destroy(E)}})()}static normalizeArguments(t,r,s){var a,n,c,f,p;let h=r;if(lt.default.object(t)&&!lt.default.urlInstance(t))r={...s,...t,...r};else{if(t&&r&&r.url!==void 0)throw new TypeError(\"The `url` option is mutually exclusive with the `input` argument\");r={...s,...r},t!==void 0&&(r.url=t),lt.default.urlInstance(r.url)&&(r.url=new I0.URL(r.url.toString()))}if(r.cache===!1&&(r.cache=void 0),r.dnsCache===!1&&(r.dnsCache=void 0),lt.assert.any([lt.default.string,lt.default.undefined],r.method),lt.assert.any([lt.default.object,lt.default.undefined],r.headers),lt.assert.any([lt.default.string,lt.default.urlInstance,lt.default.undefined],r.prefixUrl),lt.assert.any([lt.default.object,lt.default.undefined],r.cookieJar),lt.assert.any([lt.default.object,lt.default.string,lt.default.undefined],r.searchParams),lt.assert.any([lt.default.object,lt.default.string,lt.default.undefined],r.cache),lt.assert.any([lt.default.object,lt.default.number,lt.default.undefined],r.timeout),lt.assert.any([lt.default.object,lt.default.undefined],r.context),lt.assert.any([lt.default.object,lt.default.undefined],r.hooks),lt.assert.any([lt.default.boolean,lt.default.undefined],r.decompress),lt.assert.any([lt.default.boolean,lt.default.undefined],r.ignoreInvalidCookies),lt.assert.any([lt.default.boolean,lt.default.undefined],r.followRedirect),lt.assert.any([lt.default.number,lt.default.undefined],r.maxRedirects),lt.assert.any([lt.default.boolean,lt.default.undefined],r.throwHttpErrors),lt.assert.any([lt.default.boolean,lt.default.undefined],r.http2),lt.assert.any([lt.default.boolean,lt.default.undefined],r.allowGetBody),lt.assert.any([lt.default.string,lt.default.undefined],r.localAddress),lt.assert.any([jfe.isDnsLookupIpVersion,lt.default.undefined],r.dnsLookupIpVersion),lt.assert.any([lt.default.object,lt.default.undefined],r.https),lt.assert.any([lt.default.boolean,lt.default.undefined],r.rejectUnauthorized),r.https&&(lt.assert.any([lt.default.boolean,lt.default.undefined],r.https.rejectUnauthorized),lt.assert.any([lt.default.function_,lt.default.undefined],r.https.checkServerIdentity),lt.assert.any([lt.default.string,lt.default.object,lt.default.array,lt.default.undefined],r.https.certificateAuthority),lt.assert.any([lt.default.string,lt.default.object,lt.default.array,lt.default.undefined],r.https.key),lt.assert.any([lt.default.string,lt.default.object,lt.default.array,lt.default.undefined],r.https.certificate),lt.assert.any([lt.default.string,lt.default.undefined],r.https.passphrase),lt.assert.any([lt.default.string,lt.default.buffer,lt.default.array,lt.default.undefined],r.https.pfx)),lt.assert.any([lt.default.object,lt.default.undefined],r.cacheOptions),lt.default.string(r.method)?r.method=r.method.toUpperCase():r.method=\"GET\",r.headers===s?.headers?r.headers={...r.headers}:r.headers=det({...s?.headers,...r.headers}),\"slashes\"in r)throw new TypeError(\"The legacy `url.Url` has been deprecated. Use `URL` instead.\");if(\"auth\"in r)throw new TypeError(\"Parameter `auth` is deprecated. Use `username` / `password` instead.\");if(\"searchParams\"in r&&r.searchParams&&r.searchParams!==s?.searchParams){let x;if(lt.default.string(r.searchParams)||r.searchParams instanceof I0.URLSearchParams)x=new I0.URLSearchParams(r.searchParams);else{bet(r.searchParams),x=new I0.URLSearchParams;for(let I in r.searchParams){let T=r.searchParams[I];T===null?x.append(I,\"\"):T!==void 0&&x.append(I,T)}}(a=s?.searchParams)===null||a===void 0||a.forEach((I,T)=>{x.has(T)||x.append(T,I)}),r.searchParams=x}if(r.username=(n=r.username)!==null&&n!==void 0?n:\"\",r.password=(c=r.password)!==null&&c!==void 0?c:\"\",lt.default.undefined(r.prefixUrl)?r.prefixUrl=(f=s?.prefixUrl)!==null&&f!==void 0?f:\"\":(r.prefixUrl=r.prefixUrl.toString(),r.prefixUrl!==\"\"&&!r.prefixUrl.endsWith(\"/\")&&(r.prefixUrl+=\"/\")),lt.default.string(r.url)){if(r.url.startsWith(\"/\"))throw new Error(\"`input` must not start with a slash when using `prefixUrl`\");r.url=Hfe.default(r.prefixUrl+r.url,r)}else(lt.default.undefined(r.url)&&r.prefixUrl!==\"\"||r.protocol)&&(r.url=Hfe.default(r.prefixUrl,r));if(r.url){\"port\"in r&&delete r.port;let{prefixUrl:x}=r;Object.defineProperty(r,\"prefixUrl\",{set:T=>{let O=r.url;if(!O.href.startsWith(T))throw new Error(`Cannot change \\`prefixUrl\\` from ${x} to ${T}: ${O.href}`);r.url=new I0.URL(T+O.href.slice(x.length)),x=T},get:()=>x});let{protocol:I}=r.url;if(I===\"unix:\"&&(I=\"http:\",r.url=new I0.URL(`http://unix${r.url.pathname}${r.url.search}`)),r.searchParams&&(r.url.search=r.searchParams.toString()),I!==\"http:\"&&I!==\"https:\")throw new sR(r);r.username===\"\"?r.username=r.url.username:r.url.username=r.username,r.password===\"\"?r.password=r.url.password:r.url.password=r.password}let{cookieJar:E}=r;if(E){let{setCookie:x,getCookieString:I}=E;lt.assert.function_(x),lt.assert.function_(I),x.length===4&&I.length===0&&(x=Nfe.promisify(x.bind(r.cookieJar)),I=Nfe.promisify(I.bind(r.cookieJar)),r.cookieJar={setCookie:x,getCookieString:I})}let{cache:C}=r;if(C&&(NH.has(C)||NH.set(C,new Mfe((x,I)=>{let T=x[Eo](x,I);return lt.default.promise(T)&&(T.once=(O,U)=>{if(O===\"error\")T.catch(U);else if(O===\"abort\")(async()=>{try{(await T).once(\"abort\",U)}catch{}})();else throw new Error(`Unknown HTTP2 promise event: ${O}`);return T}),T},C))),r.cacheOptions={...r.cacheOptions},r.dnsCache===!0)TH||(TH=new pet.default),r.dnsCache=TH;else if(!lt.default.undefined(r.dnsCache)&&!r.dnsCache.lookup)throw new TypeError(`Parameter \\`dnsCache\\` must be a CacheableLookup instance or a boolean, got ${lt.default(r.dnsCache)}`);lt.default.number(r.timeout)?r.timeout={request:r.timeout}:s&&r.timeout!==s.timeout?r.timeout={...s.timeout,...r.timeout}:r.timeout={...r.timeout},r.context||(r.context={});let S=r.hooks===s?.hooks;r.hooks={...r.hooks};for(let x of Un.knownHookEvents)if(x in r.hooks)if(lt.default.array(r.hooks[x]))r.hooks[x]=[...r.hooks[x]];else throw new TypeError(`Parameter \\`${x}\\` must be an Array, got ${lt.default(r.hooks[x])}`);else r.hooks[x]=[];if(s&&!S)for(let x of Un.knownHookEvents)s.hooks[x].length>0&&(r.hooks[x]=[...s.hooks[x],...r.hooks[x]]);if(\"family\"in r&&C0.default('\"options.family\" was never documented, please use \"options.dnsLookupIpVersion\"'),s?.https&&(r.https={...s.https,...r.https}),\"rejectUnauthorized\"in r&&C0.default('\"options.rejectUnauthorized\" is now deprecated, please use \"options.https.rejectUnauthorized\"'),\"checkServerIdentity\"in r&&C0.default('\"options.checkServerIdentity\" was never documented, please use \"options.https.checkServerIdentity\"'),\"ca\"in r&&C0.default('\"options.ca\" was never documented, please use \"options.https.certificateAuthority\"'),\"key\"in r&&C0.default('\"options.key\" was never documented, please use \"options.https.key\"'),\"cert\"in r&&C0.default('\"options.cert\" was never documented, please use \"options.https.certificate\"'),\"passphrase\"in r&&C0.default('\"options.passphrase\" was never documented, please use \"options.https.passphrase\"'),\"pfx\"in r&&C0.default('\"options.pfx\" was never documented, please use \"options.https.pfx\"'),\"followRedirects\"in r)throw new TypeError(\"The `followRedirects` option does not exist. Use `followRedirect` instead.\");if(r.agent){for(let x in r.agent)if(x!==\"http\"&&x!==\"https\"&&x!==\"http2\")throw new TypeError(`Expected the \\`options.agent\\` properties to be \\`http\\`, \\`https\\` or \\`http2\\`, got \\`${x}\\``)}return r.maxRedirects=(p=r.maxRedirects)!==null&&p!==void 0?p:0,Un.setNonEnumerableProperties([s,h],r),Bet.default(r,s)}_lockWrite(){let t=()=>{throw new TypeError(\"The payload has been already provided\")};this.write=t,this.end=t}_unlockWrite(){this.write=super.write,this.end=super.end}async _finalizeBody(){let{options:t}=this,{headers:r}=t,s=!lt.default.undefined(t.form),a=!lt.default.undefined(t.json),n=!lt.default.undefined(t.body),c=s||a||n,f=Un.withoutBody.has(t.method)&&!(t.method===\"GET\"&&t.allowGetBody);if(this._cannotHaveBody=f,c){if(f)throw new TypeError(`The \\`${t.method}\\` method cannot be used with a body`);if([n,s,a].filter(p=>p).length>1)throw new TypeError(\"The `body`, `json` and `form` options are mutually exclusive\");if(n&&!(t.body instanceof Ofe.Readable)&&!lt.default.string(t.body)&&!lt.default.buffer(t.body)&&!Ufe.default(t.body))throw new TypeError(\"The `body` option must be a stream.Readable, string or Buffer\");if(s&&!lt.default.object(t.form))throw new TypeError(\"The `form` option must be an Object\");{let p=!lt.default.string(r[\"content-type\"]);n?(Ufe.default(t.body)&&p&&(r[\"content-type\"]=`multipart/form-data; boundary=${t.body.getBoundary()}`),this[w0]=t.body):s?(p&&(r[\"content-type\"]=\"application/x-www-form-urlencoded\"),this[w0]=new I0.URLSearchParams(t.form).toString()):(p&&(r[\"content-type\"]=\"application/json\"),this[w0]=t.stringifyJson(t.json));let h=await met.default(this[w0],t.headers);lt.default.undefined(r[\"content-length\"])&&lt.default.undefined(r[\"transfer-encoding\"])&&!f&&!lt.default.undefined(h)&&(r[\"content-length\"]=String(h))}}else f?this._lockWrite():this._unlockWrite();this[wI]=Number(r[\"content-length\"])||void 0}async _onResponseBase(t){let{options:r}=this,{url:s}=r;this[Vfe]=t,r.decompress&&(t=het(t));let a=t.statusCode,n=t;n.statusMessage=n.statusMessage?n.statusMessage:Lfe.STATUS_CODES[a],n.url=r.url.toString(),n.requestUrl=this.requestUrl,n.redirectUrls=this.redirects,n.request=this,n.isFromCache=t.fromCache||!1,n.ip=this.ip,n.retryCount=this.retryCount,this[qfe]=n.isFromCache,this[II]=Number(t.headers[\"content-length\"])||void 0,this[$Q]=t,t.once(\"end\",()=>{this[II]=this[CI],this.emit(\"downloadProgress\",this.downloadProgress)}),t.once(\"error\",f=>{t.destroy(),this._beforeError(new Y2(f,this))}),t.once(\"aborted\",()=>{this._beforeError(new Y2({name:\"Error\",message:\"The server aborted pending request\",code:\"ECONNRESET\"},this))}),this.emit(\"downloadProgress\",this.downloadProgress);let c=t.headers[\"set-cookie\"];if(lt.default.object(r.cookieJar)&&c){let f=c.map(async p=>r.cookieJar.setCookie(p,s.toString()));r.ignoreInvalidCookies&&(f=f.map(async p=>p.catch(()=>{})));try{await Promise.all(f)}catch(p){this._beforeError(p);return}}if(r.followRedirect&&t.headers.location&&ket.has(a)){if(t.resume(),this[Eo]&&(this[FH](),delete this[Eo],this[Gfe]()),(a===303&&r.method!==\"GET\"&&r.method!==\"HEAD\"||!r.methodRewriting)&&(r.method=\"GET\",\"body\"in r&&delete r.body,\"json\"in r&&delete r.json,\"form\"in r&&delete r.form,this[w0]=void 0,delete r.headers[\"content-length\"]),this.redirects.length>=r.maxRedirects){this._beforeError(new eR(this));return}try{let p=Buffer.from(t.headers.location,\"binary\").toString(),h=new I0.URL(p,s),E=h.toString();decodeURI(E),h.hostname!==s.hostname||h.port!==s.port?(\"host\"in r.headers&&delete r.headers.host,\"cookie\"in r.headers&&delete r.headers.cookie,\"authorization\"in r.headers&&delete r.headers.authorization,(r.username||r.password)&&(r.username=\"\",r.password=\"\")):(h.username=r.username,h.password=r.password),this.redirects.push(E),r.url=h;for(let C of r.hooks.beforeRedirect)await C(r,n);this.emit(\"redirect\",n,r),await this._makeRequest()}catch(p){this._beforeError(p);return}return}if(r.isStream&&r.throwHttpErrors&&!wet.isResponseOk(n)){this._beforeError(new tR(n));return}t.on(\"readable\",()=>{this[XQ]&&this._read()}),this.on(\"resume\",()=>{t.resume()}),this.on(\"pause\",()=>{t.pause()}),t.once(\"end\",()=>{this.push(null)}),this.emit(\"response\",t);for(let f of this[ZQ])if(!f.headersSent){for(let p in t.headers){let h=r.decompress?p!==\"content-encoding\":!0,E=t.headers[p];h&&f.setHeader(p,E)}f.statusCode=a}}async _onResponse(t){try{await this._onResponseBase(t)}catch(r){this._beforeError(r)}}_onRequest(t){let{options:r}=this,{timeout:s,url:a}=r;Aet.default(t),this[FH]=_fe.default(t,s,a);let n=r.cache?\"cacheableResponse\":\"response\";t.once(n,p=>{this._onResponse(p)}),t.once(\"error\",p=>{var h;t.destroy(),(h=t.res)===null||h===void 0||h.removeAllListeners(\"end\"),p=p instanceof _fe.TimeoutError?new iR(p,this.timings,this):new As(p.message,p,this),this._beforeError(p)}),this[Gfe]=yet.default(t,this,Ret),this[Eo]=t,this.emit(\"uploadProgress\",this.uploadProgress);let c=this[w0],f=this.redirects.length===0?this:t;lt.default.nodeStream(c)?(c.pipe(f),c.once(\"error\",p=>{this._beforeError(new nR(p,this))})):(this._unlockWrite(),lt.default.undefined(c)?(this._cannotHaveBody||this._noPipe)&&(f.end(),this._lockWrite()):(this._writeRequest(c,void 0,()=>{}),f.end(),this._lockWrite())),this.emit(\"request\",t)}async _createCacheableRequest(t,r){return new Promise((s,a)=>{Object.assign(r,Eet.default(t)),delete r.url;let n,c=NH.get(r.cache)(r,async f=>{f._readableState.autoDestroy=!1,n&&(await n).emit(\"cacheableResponse\",f),s(f)});r.url=t,c.once(\"error\",a),c.once(\"request\",async f=>{n=f,s(n)})})}async _makeRequest(){var t,r,s,a,n;let{options:c}=this,{headers:f}=c;for(let U in f)if(lt.default.undefined(f[U]))delete f[U];else if(lt.default.null_(f[U]))throw new TypeError(`Use \\`undefined\\` instead of \\`null\\` to delete the \\`${U}\\` header`);if(c.decompress&&lt.default.undefined(f[\"accept-encoding\"])&&(f[\"accept-encoding\"]=Det?\"gzip, deflate, br\":\"gzip, deflate\"),c.cookieJar){let U=await c.cookieJar.getCookieString(c.url.toString());lt.default.nonEmptyString(U)&&(c.headers.cookie=U)}for(let U of c.hooks.beforeRequest){let Y=await U(c);if(!lt.default.undefined(Y)){c.request=()=>Y;break}}c.body&&this[w0]!==c.body&&(this[w0]=c.body);let{agent:p,request:h,timeout:E,url:C}=c;if(c.dnsCache&&!(\"lookup\"in c)&&(c.lookup=c.dnsCache.lookup),C.hostname===\"unix\"){let U=/(?<socketPath>.+?):(?<path>.+)/.exec(`${C.pathname}${C.search}`);if(U?.groups){let{socketPath:Y,path:te}=U.groups;Object.assign(c,{socketPath:Y,path:te,host:\"\"})}}let S=C.protocol===\"https:\",x;c.http2?x=get.auto:x=S?fet.request:Lfe.request;let I=(t=c.request)!==null&&t!==void 0?t:x,T=c.cache?this._createCacheableRequest:I;p&&!c.http2&&(c.agent=p[S?\"https\":\"http\"]),c[Eo]=I,delete c.request,delete c.timeout;let O=c;if(O.shared=(r=c.cacheOptions)===null||r===void 0?void 0:r.shared,O.cacheHeuristic=(s=c.cacheOptions)===null||s===void 0?void 0:s.cacheHeuristic,O.immutableMinTimeToLive=(a=c.cacheOptions)===null||a===void 0?void 0:a.immutableMinTimeToLive,O.ignoreCargoCult=(n=c.cacheOptions)===null||n===void 0?void 0:n.ignoreCargoCult,c.dnsLookupIpVersion!==void 0)try{O.family=jfe.dnsLookupIpVersionToFamily(c.dnsLookupIpVersion)}catch{throw new Error(\"Invalid `dnsLookupIpVersion` option value\")}c.https&&(\"rejectUnauthorized\"in c.https&&(O.rejectUnauthorized=c.https.rejectUnauthorized),c.https.checkServerIdentity&&(O.checkServerIdentity=c.https.checkServerIdentity),c.https.certificateAuthority&&(O.ca=c.https.certificateAuthority),c.https.certificate&&(O.cert=c.https.certificate),c.https.key&&(O.key=c.https.key),c.https.passphrase&&(O.passphrase=c.https.passphrase),c.https.pfx&&(O.pfx=c.https.pfx));try{let U=await T(C,O);lt.default.undefined(U)&&(U=x(C,O)),c.request=h,c.timeout=E,c.agent=p,c.https&&(\"rejectUnauthorized\"in c.https&&delete O.rejectUnauthorized,c.https.checkServerIdentity&&delete O.checkServerIdentity,c.https.certificateAuthority&&delete O.ca,c.https.certificate&&delete O.cert,c.https.key&&delete O.key,c.https.passphrase&&delete O.passphrase,c.https.pfx&&delete O.pfx),Pet(U)?this._onRequest(U):this.writable?(this.once(\"finish\",()=>{this._onResponse(U)}),this._unlockWrite(),this.end(),this._lockWrite()):this._onResponse(U)}catch(U){throw U instanceof Mfe.CacheError?new rR(U,this):new As(U.message,U,this)}}async _error(t){try{for(let r of this.options.hooks.beforeError)t=await r(t)}catch(r){t=new As(r.message,r,this)}this.destroy(t)}_beforeError(t){if(this[vI])return;let{options:r}=this,s=this.retryCount+1;this[vI]=!0,t instanceof As||(t=new As(t.message,t,this));let a=t,{response:n}=a;(async()=>{if(n&&!n.body){n.setEncoding(this._readableState.encoding);try{n.rawBody=await Cet.default(n),n.body=n.rawBody.toString()}catch{}}if(this.listenerCount(\"retry\")!==0){let c;try{let f;n&&\"retry-after\"in n.headers&&(f=Number(n.headers[\"retry-after\"]),Number.isNaN(f)?(f=Date.parse(n.headers[\"retry-after\"])-Date.now(),f<=0&&(f=1)):f*=1e3),c=await r.retry.calculateDelay({attemptCount:s,retryOptions:r.retry,error:a,retryAfter:f,computedValue:vet.default({attemptCount:s,retryOptions:r.retry,error:a,retryAfter:f,computedValue:0})})}catch(f){this._error(new As(f.message,f,this));return}if(c){let f=async()=>{try{for(let p of this.options.hooks.beforeRetry)await p(this.options,a,s)}catch(p){this._error(new As(p.message,t,this));return}this.destroyed||(this.destroy(),this.emit(\"retry\",s,t))};this[Yfe]=setTimeout(f,c);return}}this._error(a)})()}_read(){this[XQ]=!0;let t=this[$Q];if(t&&!this[vI]){t.readableLength&&(this[XQ]=!1);let r;for(;(r=t.read())!==null;){this[CI]+=r.length,this[Wfe]=!0;let s=this.downloadProgress;s.percent<1&&this.emit(\"downloadProgress\",s),this.push(r)}}}_write(t,r,s){let a=()=>{this._writeRequest(t,r,s)};this.requestInitialized?a():this[V2].push(a)}_writeRequest(t,r,s){this[Eo].destroyed||(this._progressCallbacks.push(()=>{this[BI]+=Buffer.byteLength(t,r);let a=this.uploadProgress;a.percent<1&&this.emit(\"uploadProgress\",a)}),this[Eo].write(t,r,a=>{!a&&this._progressCallbacks.length>0&&this._progressCallbacks.shift()(),s(a)}))}_final(t){let r=()=>{for(;this._progressCallbacks.length!==0;)this._progressCallbacks.shift()();if(!(Eo in this)){t();return}if(this[Eo].destroyed){t();return}this[Eo].end(s=>{s||(this[wI]=this[BI],this.emit(\"uploadProgress\",this.uploadProgress),this[Eo].emit(\"upload-complete\")),t(s)})};this.requestInitialized?r():this[V2].push(r)}_destroy(t,r){var s;this[vI]=!0,clearTimeout(this[Yfe]),Eo in this&&(this[FH](),!((s=this[$Q])===null||s===void 0)&&s.complete||this[Eo].destroy()),t!==null&&!lt.default.undefined(t)&&!(t instanceof As)&&(t=new As(t.message,t,this)),r(t)}get _isAboutToError(){return this[vI]}get ip(){var t;return(t=this.socket)===null||t===void 0?void 0:t.remoteAddress}get aborted(){var t,r,s;return((r=(t=this[Eo])===null||t===void 0?void 0:t.destroyed)!==null&&r!==void 0?r:this.destroyed)&&!(!((s=this[Vfe])===null||s===void 0)&&s.complete)}get socket(){var t,r;return(r=(t=this[Eo])===null||t===void 0?void 0:t.socket)!==null&&r!==void 0?r:void 0}get downloadProgress(){let t;return this[II]?t=this[CI]/this[II]:this[II]===this[CI]?t=1:t=0,{percent:t,transferred:this[CI],total:this[II]}}get uploadProgress(){let t;return this[wI]?t=this[BI]/this[wI]:this[wI]===this[BI]?t=1:t=0,{percent:t,transferred:this[BI],total:this[wI]}}get timings(){var t;return(t=this[Eo])===null||t===void 0?void 0:t.timings}get isFromCache(){return this[qfe]}pipe(t,r){if(this[Wfe])throw new Error(\"Failed to pipe. The response has been emitted already.\");return t instanceof RH.ServerResponse&&this[ZQ].add(t),super.pipe(t,r)}unpipe(t){return t instanceof RH.ServerResponse&&this[ZQ].delete(t),super.unpipe(t),this}};Un.default=oR});var J2=G(ju=>{\"use strict\";var Tet=ju&&ju.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Fet=ju&&ju.__exportStar||function(e,t){for(var r in e)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(t,r)&&Tet(t,e,r)};Object.defineProperty(ju,\"__esModule\",{value:!0});ju.CancelError=ju.ParseError=void 0;var Kfe=K2(),OH=class extends Kfe.RequestError{constructor(t,r){let{options:s}=r.request;super(`${t.message} in \"${s.url.toString()}\"`,t,r.request),this.name=\"ParseError\"}};ju.ParseError=OH;var LH=class extends Kfe.RequestError{constructor(t){super(\"Promise was canceled\",{},t),this.name=\"CancelError\"}get isCanceled(){return!0}};ju.CancelError=LH;Fet(K2(),ju)});var zfe=G(MH=>{\"use strict\";Object.defineProperty(MH,\"__esModule\",{value:!0});var Jfe=J2(),Net=(e,t,r,s)=>{let{rawBody:a}=e;try{if(t===\"text\")return a.toString(s);if(t===\"json\")return a.length===0?\"\":r(a.toString());if(t===\"buffer\")return a;throw new Jfe.ParseError({message:`Unknown body type '${t}'`,name:\"Error\"},e)}catch(n){throw new Jfe.ParseError(n,e)}};MH.default=Net});var UH=G(B0=>{\"use strict\";var Oet=B0&&B0.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Let=B0&&B0.__exportStar||function(e,t){for(var r in e)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(t,r)&&Oet(t,e,r)};Object.defineProperty(B0,\"__esModule\",{value:!0});var Met=Ie(\"events\"),Uet=Op(),_et=Jce(),aR=J2(),Zfe=zfe(),Xfe=K2(),Het=CH(),jet=PH(),$fe=xH(),Get=[\"request\",\"response\",\"redirect\",\"uploadProgress\",\"downloadProgress\"];function eAe(e){let t,r,s=new Met.EventEmitter,a=new _et((c,f,p)=>{let h=E=>{let C=new Xfe.default(void 0,e);C.retryCount=E,C._noPipe=!0,p(()=>C.destroy()),p.shouldReject=!1,p(()=>f(new aR.CancelError(C))),t=C,C.once(\"response\",async I=>{var T;if(I.retryCount=E,I.request.aborted)return;let O;try{O=await jet.default(C),I.rawBody=O}catch{return}if(C._isAboutToError)return;let U=((T=I.headers[\"content-encoding\"])!==null&&T!==void 0?T:\"\").toLowerCase(),Y=[\"gzip\",\"deflate\",\"br\"].includes(U),{options:te}=C;if(Y&&!te.decompress)I.body=O;else try{I.body=Zfe.default(I,te.responseType,te.parseJson,te.encoding)}catch(ie){if(I.body=O.toString(),$fe.isResponseOk(I)){C._beforeError(ie);return}}try{for(let[ie,ue]of te.hooks.afterResponse.entries())I=await ue(I,async ae=>{let de=Xfe.default.normalizeArguments(void 0,{...ae,retry:{calculateDelay:()=>0},throwHttpErrors:!1,resolveBodyOnly:!1},te);de.hooks.afterResponse=de.hooks.afterResponse.slice(0,ie);for(let Ce of de.hooks.beforeRetry)await Ce(de);let Ae=eAe(de);return p(()=>{Ae.catch(()=>{}),Ae.cancel()}),Ae})}catch(ie){C._beforeError(new aR.RequestError(ie.message,ie,C));return}if(!$fe.isResponseOk(I)){C._beforeError(new aR.HTTPError(I));return}r=I,c(C.options.resolveBodyOnly?I.body:I)});let S=I=>{if(a.isCanceled)return;let{options:T}=C;if(I instanceof aR.HTTPError&&!T.throwHttpErrors){let{response:O}=I;c(C.options.resolveBodyOnly?O.body:O);return}f(I)};C.once(\"error\",S);let x=C.options.body;C.once(\"retry\",(I,T)=>{var O,U;if(x===((O=T.request)===null||O===void 0?void 0:O.options.body)&&Uet.default.nodeStream((U=T.request)===null||U===void 0?void 0:U.options.body)){S(T);return}h(I)}),Het.default(C,s,Get)};h(0)});a.on=(c,f)=>(s.on(c,f),a);let n=c=>{let f=(async()=>{await a;let{options:p}=r.request;return Zfe.default(r,c,p.parseJson,p.encoding)})();return Object.defineProperties(f,Object.getOwnPropertyDescriptors(a)),f};return a.json=()=>{let{headers:c}=t.options;return!t.writableFinished&&c.accept===void 0&&(c.accept=\"application/json\"),n(\"json\")},a.buffer=()=>n(\"buffer\"),a.text=()=>n(\"text\"),a}B0.default=eAe;Let(J2(),B0)});var tAe=G(_H=>{\"use strict\";Object.defineProperty(_H,\"__esModule\",{value:!0});var qet=J2();function Wet(e,...t){let r=(async()=>{if(e instanceof qet.RequestError)try{for(let a of t)if(a)for(let n of a)e=await n(e)}catch(a){e=a}throw e})(),s=()=>r;return r.json=s,r.text=s,r.buffer=s,r.on=s,r}_H.default=Wet});var iAe=G(HH=>{\"use strict\";Object.defineProperty(HH,\"__esModule\",{value:!0});var rAe=Op();function nAe(e){for(let t of Object.values(e))(rAe.default.plainObject(t)||rAe.default.array(t))&&nAe(t);return Object.freeze(e)}HH.default=nAe});var oAe=G(sAe=>{\"use strict\";Object.defineProperty(sAe,\"__esModule\",{value:!0})});var jH=G(Oc=>{\"use strict\";var Vet=Oc&&Oc.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Yet=Oc&&Oc.__exportStar||function(e,t){for(var r in e)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(t,r)&&Vet(t,e,r)};Object.defineProperty(Oc,\"__esModule\",{value:!0});Oc.defaultHandler=void 0;var aAe=Op(),Nc=UH(),Ket=tAe(),cR=K2(),Jet=iAe(),zet={RequestError:Nc.RequestError,CacheError:Nc.CacheError,ReadError:Nc.ReadError,HTTPError:Nc.HTTPError,MaxRedirectsError:Nc.MaxRedirectsError,TimeoutError:Nc.TimeoutError,ParseError:Nc.ParseError,CancelError:Nc.CancelError,UnsupportedProtocolError:Nc.UnsupportedProtocolError,UploadError:Nc.UploadError},Zet=async e=>new Promise(t=>{setTimeout(t,e)}),{normalizeArguments:lR}=cR.default,lAe=(...e)=>{let t;for(let r of e)t=lR(void 0,r,t);return t},Xet=e=>e.isStream?new cR.default(void 0,e):Nc.default(e),$et=e=>\"defaults\"in e&&\"options\"in e.defaults,ett=[\"get\",\"post\",\"put\",\"patch\",\"head\",\"delete\"];Oc.defaultHandler=(e,t)=>t(e);var cAe=(e,t)=>{if(e)for(let r of e)r(t)},uAe=e=>{e._rawHandlers=e.handlers,e.handlers=e.handlers.map(s=>(a,n)=>{let c,f=s(a,p=>(c=n(p),c));if(f!==c&&!a.isStream&&c){let p=f,{then:h,catch:E,finally:C}=p;Object.setPrototypeOf(p,Object.getPrototypeOf(c)),Object.defineProperties(p,Object.getOwnPropertyDescriptors(c)),p.then=h,p.catch=E,p.finally=C}return f});let t=(s,a={},n)=>{var c,f;let p=0,h=E=>e.handlers[p++](E,p===e.handlers.length?Xet:h);if(aAe.default.plainObject(s)){let E={...s,...a};cR.setNonEnumerableProperties([s,a],E),a=E,s=void 0}try{let E;try{cAe(e.options.hooks.init,a),cAe((c=a.hooks)===null||c===void 0?void 0:c.init,a)}catch(S){E=S}let C=lR(s,a,n??e.options);if(C[cR.kIsNormalizedAlready]=!0,E)throw new Nc.RequestError(E.message,E,C);return h(C)}catch(E){if(a.isStream)throw E;return Ket.default(E,e.options.hooks.beforeError,(f=a.hooks)===null||f===void 0?void 0:f.beforeError)}};t.extend=(...s)=>{let a=[e.options],n=[...e._rawHandlers],c;for(let f of s)$et(f)?(a.push(f.defaults.options),n.push(...f.defaults._rawHandlers),c=f.defaults.mutableDefaults):(a.push(f),\"handlers\"in f&&n.push(...f.handlers),c=f.mutableDefaults);return n=n.filter(f=>f!==Oc.defaultHandler),n.length===0&&n.push(Oc.defaultHandler),uAe({options:lAe(...a),handlers:n,mutableDefaults:!!c})};let r=async function*(s,a){let n=lR(s,a,e.options);n.resolveBodyOnly=!1;let c=n.pagination;if(!aAe.default.object(c))throw new TypeError(\"`options.pagination` must be implemented\");let f=[],{countLimit:p}=c,h=0;for(;h<c.requestLimit;){h!==0&&await Zet(c.backoff);let E=await t(void 0,void 0,n),C=await c.transform(E),S=[];for(let I of C)if(c.filter(I,f,S)&&(!c.shouldContinue(I,f,S)||(yield I,c.stackAllItems&&f.push(I),S.push(I),--p<=0)))return;let x=c.paginate(E,f,S);if(x===!1)return;x===E.request.options?n=E.request.options:x!==void 0&&(n=lR(void 0,x,n)),h++}};t.paginate=r,t.paginate.all=async(s,a)=>{let n=[];for await(let c of r(s,a))n.push(c);return n},t.paginate.each=r,t.stream=(s,a)=>t(s,{...a,isStream:!0});for(let s of ett)t[s]=(a,n)=>t(a,{...n,method:s}),t.stream[s]=(a,n)=>t(a,{...n,method:s,isStream:!0});return Object.assign(t,zet),Object.defineProperty(t,\"defaults\",{value:e.mutableDefaults?e:Jet.default(e),writable:e.mutableDefaults,configurable:e.mutableDefaults,enumerable:!0}),t.mergeOptions=lAe,t};Oc.default=uAe;Yet(oAe(),Oc)});var pAe=G((Lp,uR)=>{\"use strict\";var ttt=Lp&&Lp.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),fAe=Lp&&Lp.__exportStar||function(e,t){for(var r in e)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(t,r)&&ttt(t,e,r)};Object.defineProperty(Lp,\"__esModule\",{value:!0});var rtt=Ie(\"url\"),AAe=jH(),ntt={options:{method:\"GET\",retry:{limit:2,methods:[\"GET\",\"PUT\",\"HEAD\",\"DELETE\",\"OPTIONS\",\"TRACE\"],statusCodes:[408,413,429,500,502,503,504,521,522,524],errorCodes:[\"ETIMEDOUT\",\"ECONNRESET\",\"EADDRINUSE\",\"ECONNREFUSED\",\"EPIPE\",\"ENOTFOUND\",\"ENETUNREACH\",\"EAI_AGAIN\"],maxRetryAfter:void 0,calculateDelay:({computedValue:e})=>e},timeout:{},headers:{\"user-agent\":\"got (https://github.com/sindresorhus/got)\"},hooks:{init:[],beforeRequest:[],beforeRedirect:[],beforeRetry:[],beforeError:[],afterResponse:[]},cache:void 0,dnsCache:void 0,decompress:!0,throwHttpErrors:!0,followRedirect:!0,isStream:!1,responseType:\"text\",resolveBodyOnly:!1,maxRedirects:10,prefixUrl:\"\",methodRewriting:!0,ignoreInvalidCookies:!1,context:{},http2:!1,allowGetBody:!1,https:void 0,pagination:{transform:e=>e.request.options.responseType===\"json\"?e.body:JSON.parse(e.body),paginate:e=>{if(!Reflect.has(e.headers,\"link\"))return!1;let t=e.headers.link.split(\",\"),r;for(let s of t){let a=s.split(\";\");if(a[1].includes(\"next\")){r=a[0].trimStart().trim(),r=r.slice(1,-1);break}}return r?{url:new rtt.URL(r)}:!1},filter:()=>!0,shouldContinue:()=>!0,countLimit:1/0,backoff:0,requestLimit:1e4,stackAllItems:!0},parseJson:e=>JSON.parse(e),stringifyJson:e=>JSON.stringify(e),cacheOptions:{}},handlers:[AAe.defaultHandler],mutableDefaults:!1},GH=AAe.default(ntt);Lp.default=GH;uR.exports=GH;uR.exports.default=GH;uR.exports.__esModule=!0;fAe(jH(),Lp);fAe(UH(),Lp)});var nn={};Yt(nn,{Method:()=>EAe,del:()=>ltt,get:()=>VH,getNetworkSettings:()=>yAe,post:()=>YH,put:()=>att,request:()=>z2});async function qH(e){return Zl(gAe,e,()=>le.readFilePromise(e).then(t=>(gAe.set(e,t),t)))}function ott({statusCode:e,statusMessage:t},r){let s=jt(r,e,gt.NUMBER),a=`https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/${e}`;return XE(r,`${s}${t?` (${t})`:\"\"}`,a)}async function fR(e,{configuration:t,customErrorMessage:r}){try{return await e}catch(s){if(s.name!==\"HTTPError\")throw s;let a=r?.(s,t)??s.response.body?.error;a==null&&(s.message.startsWith(\"Response code\")?a=\"The remote server failed to provide the requested resource\":a=s.message),s.code===\"ETIMEDOUT\"&&s.event===\"socket\"&&(a+=`(can be increased via ${jt(t,\"httpTimeout\",gt.SETTING)})`);let n=new _t(35,a,c=>{s.response&&c.reportError(35,`  ${Zf(t,{label:\"Response Code\",value:Mu(gt.NO_HINT,ott(s.response,t))})}`),s.request&&(c.reportError(35,`  ${Zf(t,{label:\"Request Method\",value:Mu(gt.NO_HINT,s.request.options.method)})}`),c.reportError(35,`  ${Zf(t,{label:\"Request URL\",value:Mu(gt.URL,s.request.requestUrl)})}`)),s.request.redirects.length>0&&c.reportError(35,`  ${Zf(t,{label:\"Request Redirects\",value:Mu(gt.NO_HINT,O4(t,s.request.redirects,gt.URL))})}`),s.request.retryCount===s.request.options.retry.limit&&c.reportError(35,`  ${Zf(t,{label:\"Request Retry Count\",value:Mu(gt.NO_HINT,`${jt(t,s.request.retryCount,gt.NUMBER)} (can be increased via ${jt(t,\"httpRetry\",gt.SETTING)})`)})}`)});throw n.originalError=s,n}}function yAe(e,t){let r=[...t.configuration.get(\"networkSettings\")].sort(([c],[f])=>f.length-c.length),s={enableNetwork:void 0,httpsCaFilePath:void 0,httpProxy:void 0,httpsProxy:void 0,httpsKeyFilePath:void 0,httpsCertFilePath:void 0},a=Object.keys(s),n=typeof e==\"string\"?new URL(e):e;for(let[c,f]of r)if(WH.default.isMatch(n.hostname,c))for(let p of a){let h=f.get(p);h!==null&&typeof s[p]>\"u\"&&(s[p]=h)}for(let c of a)typeof s[c]>\"u\"&&(s[c]=t.configuration.get(c));return s}async function z2(e,t,{configuration:r,headers:s,jsonRequest:a,jsonResponse:n,method:c=\"GET\",wrapNetworkRequest:f}){let p={target:e,body:t,configuration:r,headers:s,jsonRequest:a,jsonResponse:n,method:c},h=async()=>await ctt(e,t,p),E=typeof f<\"u\"?await f(h,p):h;return await(await r.reduceHook(S=>S.wrapNetworkRequest,E,p))()}async function VH(e,{configuration:t,jsonResponse:r,customErrorMessage:s,wrapNetworkRequest:a,...n}){let c=()=>fR(z2(e,null,{configuration:t,wrapNetworkRequest:a,...n}),{configuration:t,customErrorMessage:s}).then(p=>p.body),f=await(typeof a<\"u\"?c():Zl(hAe,e,()=>c().then(p=>(hAe.set(e,p),p))));return r?JSON.parse(f.toString()):f}async function att(e,t,{customErrorMessage:r,...s}){return(await fR(z2(e,t,{...s,method:\"PUT\"}),{customErrorMessage:r,configuration:s.configuration})).body}async function YH(e,t,{customErrorMessage:r,...s}){return(await fR(z2(e,t,{...s,method:\"POST\"}),{customErrorMessage:r,configuration:s.configuration})).body}async function ltt(e,{customErrorMessage:t,...r}){return(await fR(z2(e,null,{...r,method:\"DELETE\"}),{customErrorMessage:t,configuration:r.configuration})).body}async function ctt(e,t,{configuration:r,headers:s,jsonRequest:a,jsonResponse:n,method:c=\"GET\"}){let f=typeof e==\"string\"?new URL(e):e,p=yAe(f,{configuration:r});if(p.enableNetwork===!1)throw new _t(80,`Request to '${f.href}' has been blocked because of your configuration settings`);if(f.protocol===\"http:\"&&!WH.default.isMatch(f.hostname,r.get(\"unsafeHttpWhitelist\")))throw new _t(81,`Unsafe http requests must be explicitly whitelisted in your configuration (${f.hostname})`);let h={headers:s,method:c};h.responseType=n?\"json\":\"buffer\",t!==null&&(Buffer.isBuffer(t)||!a&&typeof t==\"string\"?h.body=t:h.json=t);let E=r.get(\"httpTimeout\"),C=r.get(\"httpRetry\"),S=r.get(\"enableStrictSsl\"),x=p.httpsCaFilePath,I=p.httpsCertFilePath,T=p.httpsKeyFilePath,{default:O}=await Promise.resolve().then(()=>et(pAe())),U=x?await qH(x):void 0,Y=I?await qH(I):void 0,te=T?await qH(T):void 0,ie={rejectUnauthorized:S,ca:U,cert:Y,key:te},ue={http:p.httpProxy?new jce({proxy:p.httpProxy,proxyRequestOptions:ie}):itt,https:p.httpsProxy?new Gce({proxy:p.httpsProxy,proxyRequestOptions:ie}):stt},ae=O.extend({timeout:{socket:E},retry:C,agent:ue,https:{rejectUnauthorized:S,certificateAuthority:U,certificate:Y,key:te},...h});return r.getLimit(\"networkConcurrency\")(()=>ae(f))}var dAe,mAe,WH,hAe,gAe,itt,stt,EAe,AR=Ze(()=>{Dt();qce();dAe=Ie(\"https\"),mAe=Ie(\"http\"),WH=et(Jo());Tc();kc();xc();hAe=new Map,gAe=new Map,itt=new mAe.Agent({keepAlive:!0}),stt=new dAe.Agent({keepAlive:!0});EAe=(a=>(a.GET=\"GET\",a.PUT=\"PUT\",a.POST=\"POST\",a.DELETE=\"DELETE\",a))(EAe||{})});var Ui={};Yt(Ui,{availableParallelism:()=>JH,getArchitecture:()=>Z2,getArchitectureName:()=>htt,getArchitectureSet:()=>KH,getCaller:()=>ytt,major:()=>utt,openUrl:()=>ftt});function ptt(){if(process.platform!==\"linux\")return null;let e;try{e=le.readFileSync(Att)}catch{}if(typeof e<\"u\"){if(e&&(e.includes(\"GLIBC\")||e.includes(\"GNU libc\")||e.includes(\"GNU C Library\")))return\"glibc\";if(e&&e.includes(\"musl\"))return\"musl\"}let r=(process.report?.getReport()??{}).sharedObjects??[],s=/\\/(?:(ld-linux-|[^/]+-linux-gnu\\/)|(libc.musl-|ld-musl-))/;return f0(r,a=>{let n=a.match(s);if(!n)return f0.skip;if(n[1])return\"glibc\";if(n[2])return\"musl\";throw new Error(\"Assertion failed: Expected the libc variant to have been detected\")})??null}function Z2(){return CAe=CAe??{os:(process.env.YARN_IS_TEST_ENV?process.env.YARN_OS_OVERRIDE:void 0)??process.platform,cpu:(process.env.YARN_IS_TEST_ENV?process.env.YARN_CPU_OVERRIDE:void 0)??process.arch,libc:(process.env.YARN_IS_TEST_ENV?process.env.YARN_LIBC_OVERRIDE:void 0)??ptt()}}function htt(e=Z2()){return e.libc?`${e.os}-${e.cpu}-${e.libc}`:`${e.os}-${e.cpu}`}function KH(){let e=Z2();return wAe=wAe??{os:[e.os],cpu:[e.cpu],libc:e.libc?[e.libc]:[]}}function mtt(e){let t=gtt.exec(e);if(!t)return null;let r=t[2]&&t[2].indexOf(\"native\")===0,s=t[2]&&t[2].indexOf(\"eval\")===0,a=dtt.exec(t[2]);return s&&a!=null&&(t[2]=a[1],t[3]=a[2],t[4]=a[3]),{file:r?null:t[2],methodName:t[1]||\"<unknown>\",arguments:r?[t[2]]:[],line:t[3]?+t[3]:null,column:t[4]?+t[4]:null}}function ytt(){let t=new Error().stack.split(`\n`)[3];return mtt(t)}function JH(){return typeof pR.default.availableParallelism<\"u\"?pR.default.availableParallelism():Math.max(1,pR.default.cpus().length)}var pR,utt,IAe,ftt,Att,CAe,wAe,gtt,dtt,hR=Ze(()=>{Dt();pR=et(Ie(\"os\"));gR();xc();utt=Number(process.versions.node.split(\".\")[0]),IAe=new Map([[\"darwin\",\"open\"],[\"linux\",\"xdg-open\"],[\"win32\",\"explorer.exe\"]]).get(process.platform),ftt=typeof IAe<\"u\"?async e=>{try{return await zH(IAe,[e],{cwd:K.cwd()}),!0}catch{return!1}}:void 0,Att=\"/usr/bin/ldd\";gtt=/^\\s*at (.*?) ?\\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|\\/|[a-z]:\\\\|\\\\\\\\).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i,dtt=/\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/});function rj(e,t,r,s,a){let n=M2(r);if(s.isArray||s.type===\"ANY\"&&Array.isArray(n))return Array.isArray(n)?n.map((c,f)=>ZH(e,`${t}[${f}]`,c,s,a)):String(n).split(/,/).map(c=>ZH(e,t,c,s,a));if(Array.isArray(n))throw new Error(`Non-array configuration settings \"${t}\" cannot be an array`);return ZH(e,t,r,s,a)}function ZH(e,t,r,s,a){let n=M2(r);switch(s.type){case\"ANY\":return FQ(n);case\"SHAPE\":return wtt(e,t,r,s,a);case\"MAP\":return Btt(e,t,r,s,a)}if(n===null&&!s.isNullable&&s.default!==null)throw new Error(`Non-nullable configuration settings \"${t}\" cannot be set to null`);if(\"values\"in s&&s.values?.includes(n))return n;let f=(()=>{if(s.type===\"BOOLEAN\"&&typeof n!=\"string\")return w2(n);if(typeof n!=\"string\")throw new Error(`Expected configuration setting \"${t}\" to be a string, got ${typeof n}`);let p=Vk(n,{env:e.env});switch(s.type){case\"ABSOLUTE_PATH\":{let h=a,E=S8(r);return E&&E[0]!==\"<\"&&(h=K.dirname(E)),K.resolve(h,fe.toPortablePath(p))}case\"LOCATOR_LOOSE\":return Rp(p,!1);case\"NUMBER\":return parseInt(p);case\"LOCATOR\":return Rp(p);case\"BOOLEAN\":return w2(p);case\"DURATION\":return Yk(p,s.unit);default:return p}})();if(\"values\"in s&&s.values&&!s.values.includes(f))throw new Error(`Invalid value, expected one of ${s.values.join(\", \")}`);return f}function wtt(e,t,r,s,a){let n=M2(r);if(typeof n!=\"object\"||Array.isArray(n))throw new st(`Object configuration settings \"${t}\" must be an object`);let c=nj(e,s,{ignoreArrays:!0});if(n===null)return c;for(let[f,p]of Object.entries(n)){let h=`${t}.${f}`;if(!s.properties[f])throw new st(`Unrecognized configuration settings found: ${t}.${f} - run \"yarn config\" to see the list of settings supported in Yarn`);c.set(f,rj(e,h,p,s.properties[f],a))}return c}function Btt(e,t,r,s,a){let n=M2(r),c=new Map;if(typeof n!=\"object\"||Array.isArray(n))throw new st(`Map configuration settings \"${t}\" must be an object`);if(n===null)return c;for(let[f,p]of Object.entries(n)){let h=s.normalizeKeys?s.normalizeKeys(f):f,E=`${t}['${h}']`,C=s.valueDefinition;c.set(h,rj(e,E,p,C,a))}return c}function nj(e,t,{ignoreArrays:r=!1}={}){switch(t.type){case\"SHAPE\":{if(t.isArray&&!r)return[];let s=new Map;for(let[a,n]of Object.entries(t.properties))s.set(a,nj(e,n));return s}case\"MAP\":return t.isArray&&!r?[]:new Map;case\"ABSOLUTE_PATH\":return t.default===null?null:e.projectCwd===null?Array.isArray(t.default)?t.default.map(s=>K.normalize(s)):K.isAbsolute(t.default)?K.normalize(t.default):t.isNullable?null:void 0:Array.isArray(t.default)?t.default.map(s=>K.resolve(e.projectCwd,s)):K.resolve(e.projectCwd,t.default);case\"DURATION\":return Yk(t.default,t.unit);default:return t.default}}function mR(e,t,r){if(t.type===\"SECRET\"&&typeof e==\"string\"&&r.hideSecrets)return Ctt;if(t.type===\"ABSOLUTE_PATH\"&&typeof e==\"string\"&&r.getNativePaths)return fe.fromPortablePath(e);if(t.isArray&&Array.isArray(e)){let s=[];for(let a of e)s.push(mR(a,t,r));return s}if(t.type===\"MAP\"&&e instanceof Map){if(e.size===0)return;let s=new Map;for(let[a,n]of e.entries()){let c=mR(n,t.valueDefinition,r);typeof c<\"u\"&&s.set(a,c)}return s}if(t.type===\"SHAPE\"&&e instanceof Map){if(e.size===0)return;let s=new Map;for(let[a,n]of e.entries()){let c=t.properties[a],f=mR(n,c,r);typeof f<\"u\"&&s.set(a,f)}return s}return e}function vtt(){let e={};for(let[t,r]of Object.entries(process.env))t=t.toLowerCase(),t.startsWith(yR)&&(t=(0,vAe.default)(t.slice(yR.length)),e[t]=r);return e}function $H(){let e=`${yR}rc_filename`;for(let[t,r]of Object.entries(process.env))if(t.toLowerCase()===e&&typeof r==\"string\")return r;return ej}async function BAe(e){try{return await le.readFilePromise(e)}catch{return Buffer.of()}}async function Stt(e,t){return Buffer.compare(...await Promise.all([BAe(e),BAe(t)]))===0}async function Dtt(e,t){let[r,s]=await Promise.all([le.statPromise(e),le.statPromise(t)]);return r.dev===s.dev&&r.ino===s.ino}async function Ptt({configuration:e,selfPath:t}){let r=e.get(\"yarnPath\");return e.get(\"ignorePath\")||r===null||r===t||await btt(r,t)?null:r}var vAe,Mp,SAe,DAe,bAe,XH,Ett,X2,Itt,Up,yR,ej,Ctt,SI,PAe,tj,ER,dR,btt,ze,$2=Ze(()=>{Dt();Bc();vAe=et(jte()),Mp=et(Rd());Vt();SAe=et(Nre()),DAe=Ie(\"module\"),bAe=et(Nd()),XH=Ie(\"stream\");Cce();cI();m8();y8();E8();Tce();I8();$d();Mce();OQ();kc();y0();AR();xc();hR();Fp();Zo();Ett=function(){if(!Mp.GITHUB_ACTIONS||!process.env.GITHUB_EVENT_PATH)return!1;let e=fe.toPortablePath(process.env.GITHUB_EVENT_PATH),t;try{t=le.readJsonSync(e)}catch{return!1}return!(!(\"repository\"in t)||!t.repository||(t.repository.private??!0))}(),X2=new Set([\"@yarnpkg/plugin-constraints\",\"@yarnpkg/plugin-exec\",\"@yarnpkg/plugin-interactive-tools\",\"@yarnpkg/plugin-stage\",\"@yarnpkg/plugin-typescript\",\"@yarnpkg/plugin-version\",\"@yarnpkg/plugin-workspace-tools\"]),Itt=new Set([\"isTestEnv\",\"injectNpmUser\",\"injectNpmPassword\",\"injectNpm2FaToken\",\"zipDataEpilogue\",\"cacheCheckpointOverride\",\"cacheVersionOverride\",\"lockfileVersionOverride\",\"osOverride\",\"cpuOverride\",\"libcOverride\",\"binFolder\",\"version\",\"flags\",\"profile\",\"gpg\",\"ignoreNode\",\"wrapOutput\",\"home\",\"confDir\",\"registry\",\"ignoreCwd\"]),Up=/^(?!v)[a-z0-9._-]+$/i,yR=\"yarn_\",ej=\".yarnrc.yml\",Ctt=\"********\",SI=(C=>(C.ANY=\"ANY\",C.BOOLEAN=\"BOOLEAN\",C.ABSOLUTE_PATH=\"ABSOLUTE_PATH\",C.LOCATOR=\"LOCATOR\",C.LOCATOR_LOOSE=\"LOCATOR_LOOSE\",C.NUMBER=\"NUMBER\",C.STRING=\"STRING\",C.DURATION=\"DURATION\",C.SECRET=\"SECRET\",C.SHAPE=\"SHAPE\",C.MAP=\"MAP\",C))(SI||{}),PAe=gt,tj=(c=>(c.MILLISECONDS=\"ms\",c.SECONDS=\"s\",c.MINUTES=\"m\",c.HOURS=\"h\",c.DAYS=\"d\",c.WEEKS=\"w\",c))(tj||{}),ER=(r=>(r.JUNCTIONS=\"junctions\",r.SYMLINKS=\"symlinks\",r))(ER||{}),dR={lastUpdateCheck:{description:\"Last timestamp we checked whether new Yarn versions were available\",type:\"STRING\",default:null},yarnPath:{description:\"Path to the local executable that must be used over the global one\",type:\"ABSOLUTE_PATH\",default:null},ignorePath:{description:\"If true, the local executable will be ignored when using the global one\",type:\"BOOLEAN\",default:!1},globalFolder:{description:\"Folder where all system-global files are stored\",type:\"ABSOLUTE_PATH\",default:b8()},cacheFolder:{description:\"Folder where the cache files must be written\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/cache\"},compressionLevel:{description:\"Zip files compression level, from 0 to 9 or mixed (a variant of 9, which stores some files uncompressed, when compression doesn't yield good results)\",type:\"NUMBER\",values:[\"mixed\",0,1,2,3,4,5,6,7,8,9],default:0},virtualFolder:{description:\"Folder where the virtual packages (cf doc) will be mapped on the disk (must be named __virtual__)\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/__virtual__\"},installStatePath:{description:\"Path of the file where the install state will be persisted\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/install-state.gz\"},immutablePatterns:{description:\"Array of glob patterns; files matching them won't be allowed to change during immutable installs\",type:\"STRING\",default:[],isArray:!0},rcFilename:{description:\"Name of the files where the configuration can be found\",type:\"STRING\",default:$H()},enableGlobalCache:{description:\"If true, the system-wide cache folder will be used regardless of `cache-folder`\",type:\"BOOLEAN\",default:!0},cacheMigrationMode:{description:\"Defines the conditions under which Yarn upgrades should cause the cache archives to be regenerated.\",type:\"STRING\",values:[\"always\",\"match-spec\",\"required-only\"],default:\"always\"},enableColors:{description:\"If true, the CLI is allowed to use colors in its output\",type:\"BOOLEAN\",default:Zk,defaultText:\"<dynamic>\"},enableHyperlinks:{description:\"If true, the CLI is allowed to use hyperlinks in its output\",type:\"BOOLEAN\",default:N4,defaultText:\"<dynamic>\"},enableInlineBuilds:{description:\"If true, the CLI will print the build output on the command line\",type:\"BOOLEAN\",default:Mp.isCI,defaultText:\"<dynamic>\"},enableMessageNames:{description:\"If true, the CLI will prefix most messages with codes suitable for search engines\",type:\"BOOLEAN\",default:!0},enableProgressBars:{description:\"If true, the CLI is allowed to show a progress bar for long-running events\",type:\"BOOLEAN\",default:!Mp.isCI,defaultText:\"<dynamic>\"},enableTimers:{description:\"If true, the CLI is allowed to print the time spent executing commands\",type:\"BOOLEAN\",default:!0},enableTips:{description:\"If true, installs will print a helpful message every day of the week\",type:\"BOOLEAN\",default:!Mp.isCI,defaultText:\"<dynamic>\"},preferInteractive:{description:\"If true, the CLI will automatically use the interactive mode when called from a TTY\",type:\"BOOLEAN\",default:!1},preferTruncatedLines:{description:\"If true, the CLI will truncate lines that would go beyond the size of the terminal\",type:\"BOOLEAN\",default:!1},progressBarStyle:{description:\"Which style of progress bar should be used (only when progress bars are enabled)\",type:\"STRING\",default:void 0,defaultText:\"<dynamic>\"},defaultLanguageName:{description:\"Default language mode that should be used when a package doesn't offer any insight\",type:\"STRING\",default:\"node\"},defaultProtocol:{description:\"Default resolution protocol used when resolving pure semver and tag ranges\",type:\"STRING\",default:\"npm:\"},enableTransparentWorkspaces:{description:\"If false, Yarn won't automatically resolve workspace dependencies unless they use the `workspace:` protocol\",type:\"BOOLEAN\",default:!0},supportedArchitectures:{description:\"Architectures that Yarn will fetch and inject into the resolver\",type:\"SHAPE\",properties:{os:{description:\"Array of supported process.platform strings, or null to target them all\",type:\"STRING\",isArray:!0,isNullable:!0,default:[\"current\"]},cpu:{description:\"Array of supported process.arch strings, or null to target them all\",type:\"STRING\",isArray:!0,isNullable:!0,default:[\"current\"]},libc:{description:\"Array of supported libc libraries, or null to target them all\",type:\"STRING\",isArray:!0,isNullable:!0,default:[\"current\"]}}},enableMirror:{description:\"If true, the downloaded packages will be retrieved and stored in both the local and global folders\",type:\"BOOLEAN\",default:!0},enableNetwork:{description:\"If false, Yarn will refuse to use the network if required to\",type:\"BOOLEAN\",default:!0},enableOfflineMode:{description:\"If true, Yarn will attempt to retrieve files and metadata from the global cache rather than the network\",type:\"BOOLEAN\",default:!1},httpProxy:{description:\"URL of the http proxy that must be used for outgoing http requests\",type:\"STRING\",default:null},httpsProxy:{description:\"URL of the http proxy that must be used for outgoing https requests\",type:\"STRING\",default:null},unsafeHttpWhitelist:{description:\"List of the hostnames for which http queries are allowed (glob patterns are supported)\",type:\"STRING\",default:[],isArray:!0},httpTimeout:{description:\"Timeout of each http request\",type:\"DURATION\",unit:\"ms\",default:\"1m\"},httpRetry:{description:\"Retry times on http failure\",type:\"NUMBER\",default:3},networkConcurrency:{description:\"Maximal number of concurrent requests\",type:\"NUMBER\",default:50},taskPoolConcurrency:{description:\"Maximal amount of concurrent heavy task processing\",type:\"NUMBER\",default:JH()},taskPoolMode:{description:\"Execution strategy for heavy tasks\",type:\"STRING\",values:[\"async\",\"workers\"],default:\"workers\"},networkSettings:{description:\"Network settings per hostname (glob patterns are supported)\",type:\"MAP\",valueDefinition:{description:\"\",type:\"SHAPE\",properties:{httpsCaFilePath:{description:\"Path to file containing one or multiple Certificate Authority signing certificates\",type:\"ABSOLUTE_PATH\",default:null},enableNetwork:{description:\"If false, the package manager will refuse to use the network if required to\",type:\"BOOLEAN\",default:null},httpProxy:{description:\"URL of the http proxy that must be used for outgoing http requests\",type:\"STRING\",default:null},httpsProxy:{description:\"URL of the http proxy that must be used for outgoing https requests\",type:\"STRING\",default:null},httpsKeyFilePath:{description:\"Path to file containing private key in PEM format\",type:\"ABSOLUTE_PATH\",default:null},httpsCertFilePath:{description:\"Path to file containing certificate chain in PEM format\",type:\"ABSOLUTE_PATH\",default:null}}}},httpsCaFilePath:{description:\"A path to a file containing one or multiple Certificate Authority signing certificates\",type:\"ABSOLUTE_PATH\",default:null},httpsKeyFilePath:{description:\"Path to file containing private key in PEM format\",type:\"ABSOLUTE_PATH\",default:null},httpsCertFilePath:{description:\"Path to file containing certificate chain in PEM format\",type:\"ABSOLUTE_PATH\",default:null},enableStrictSsl:{description:\"If false, SSL certificate errors will be ignored\",type:\"BOOLEAN\",default:!0},logFilters:{description:\"Overrides for log levels\",type:\"SHAPE\",isArray:!0,concatenateValues:!0,properties:{code:{description:\"Code of the messages covered by this override\",type:\"STRING\",default:void 0},text:{description:\"Code of the texts covered by this override\",type:\"STRING\",default:void 0},pattern:{description:\"Code of the patterns covered by this override\",type:\"STRING\",default:void 0},level:{description:\"Log level override, set to null to remove override\",type:\"STRING\",values:Object.values($k),isNullable:!0,default:void 0}}},enableTelemetry:{description:\"If true, telemetry will be periodically sent, following the rules in https://yarnpkg.com/advanced/telemetry\",type:\"BOOLEAN\",default:!0},telemetryInterval:{description:\"Minimal amount of time between two telemetry uploads\",type:\"DURATION\",unit:\"d\",default:\"7d\"},telemetryUserId:{description:\"If you desire to tell us which project you are, you can set this field. Completely optional and opt-in.\",type:\"STRING\",default:null},enableHardenedMode:{description:\"If true, automatically enable --check-resolutions --refresh-lockfile on installs\",type:\"BOOLEAN\",default:Mp.isPR&&Ett,defaultText:\"<true on public PRs>\"},enableScripts:{description:\"If true, packages are allowed to have install scripts by default\",type:\"BOOLEAN\",default:!0},enableStrictSettings:{description:\"If true, unknown settings will cause Yarn to abort\",type:\"BOOLEAN\",default:!0},enableImmutableCache:{description:\"If true, the cache is reputed immutable and actions that would modify it will throw\",type:\"BOOLEAN\",default:!1},enableCacheClean:{description:\"If false, disallows the `cache clean` command\",type:\"BOOLEAN\",default:!0},checksumBehavior:{description:\"Enumeration defining what to do when a checksum doesn't match expectations\",type:\"STRING\",default:\"throw\"},injectEnvironmentFiles:{description:\"List of all the environment files that Yarn should inject inside the process when it starts\",type:\"ABSOLUTE_PATH\",default:[\".env.yarn?\"],isArray:!0},packageExtensions:{description:\"Map of package corrections to apply on the dependency tree\",type:\"MAP\",valueDefinition:{description:\"The extension that will be applied to any package whose version matches the specified range\",type:\"SHAPE\",properties:{dependencies:{description:\"The set of dependencies that must be made available to the current package in order for it to work properly\",type:\"MAP\",valueDefinition:{description:\"A range\",type:\"STRING\"}},peerDependencies:{description:\"Inherited dependencies - the consumer of the package will be tasked to provide them\",type:\"MAP\",valueDefinition:{description:\"A semver range\",type:\"STRING\"}},peerDependenciesMeta:{description:\"Extra information related to the dependencies listed in the peerDependencies field\",type:\"MAP\",valueDefinition:{description:\"The peerDependency meta\",type:\"SHAPE\",properties:{optional:{description:\"If true, the selected peer dependency will be marked as optional by the package manager and the consumer omitting it won't be reported as an error\",type:\"BOOLEAN\",default:!1}}}}}}}};btt=process.platform===\"win32\"?Stt:Dtt;ze=class e{constructor(t){this.isCI=Mp.isCI;this.projectCwd=null;this.plugins=new Map;this.settings=new Map;this.values=new Map;this.sources=new Map;this.invalid=new Map;this.env={};this.limits=new Map;this.packageExtensions=null;this.startingCwd=t}static{this.deleteProperty=Symbol()}static{this.telemetry=null}static create(t,r,s){let a=new e(t);typeof r<\"u\"&&!(r instanceof Map)&&(a.projectCwd=r),a.importSettings(dR);let n=typeof s<\"u\"?s:r instanceof Map?r:new Map;for(let[c,f]of n)a.activatePlugin(c,f);return a}static async find(t,r,{strict:s=!0,usePathCheck:a=null,useRc:n=!0}={}){let c=vtt();delete c.rcFilename;let f=new e(t),p=await e.findRcFiles(t),h=await e.findFolderRcFile(hI());h&&(p.find(de=>de.path===h.path)||p.unshift(h));let E=Lce(p.map(ae=>[ae.path,ae.data])),C=vt.dot,S=new Set(Object.keys(dR)),x=({yarnPath:ae,ignorePath:de,injectEnvironmentFiles:Ae})=>({yarnPath:ae,ignorePath:de,injectEnvironmentFiles:Ae}),I=({yarnPath:ae,ignorePath:de,injectEnvironmentFiles:Ae,...Ce})=>{let Ee={};for(let[g,Se]of Object.entries(Ce))S.has(g)&&(Ee[g]=Se);return Ee},T=({yarnPath:ae,ignorePath:de,...Ae})=>{let Ce={};for(let[Ee,g]of Object.entries(Ae))S.has(Ee)||(Ce[Ee]=g);return Ce};if(f.importSettings(x(dR)),f.useWithSource(\"<environment>\",x(c),t,{strict:!1}),E){let[ae,de]=E;f.useWithSource(ae,x(de),C,{strict:!1})}if(a){if(await Ptt({configuration:f,selfPath:a})!==null)return f;f.useWithSource(\"<override>\",{ignorePath:!0},t,{strict:!1,overwrite:!0})}let O=await e.findProjectCwd(t);f.startingCwd=t,f.projectCwd=O;let U=Object.assign(Object.create(null),process.env);f.env=U;let Y=await Promise.all(f.get(\"injectEnvironmentFiles\").map(async ae=>{let de=ae.endsWith(\"?\")?await le.readFilePromise(ae.slice(0,-1),\"utf8\").catch(()=>\"\"):await le.readFilePromise(ae,\"utf8\");return(0,SAe.parse)(de)}));for(let ae of Y)for(let[de,Ae]of Object.entries(ae))f.env[de]=Vk(Ae,{env:U});if(f.importSettings(I(dR)),f.useWithSource(\"<environment>\",I(c),t,{strict:s}),E){let[ae,de]=E;f.useWithSource(ae,I(de),C,{strict:s})}let te=ae=>\"default\"in ae?ae.default:ae,ie=new Map([[\"@@core\",Ice]]);if(r!==null)for(let ae of r.plugins.keys())ie.set(ae,te(r.modules.get(ae)));for(let[ae,de]of ie)f.activatePlugin(ae,de);let ue=new Map([]);if(r!==null){let ae=new Map;for(let[Ce,Ee]of r.modules)ae.set(Ce,()=>Ee);let de=new Set,Ae=async(Ce,Ee)=>{let{factory:g,name:Se}=xp(Ce);if(!g||de.has(Se))return;let Be=new Map(ae),me=X=>{if((0,DAe.isBuiltin)(X))return xp(X);if(Be.has(X))return Be.get(X)();throw new st(`This plugin cannot access the package referenced via ${X} which is neither a builtin, nor an exposed entry`)},ce=await YE(async()=>te(await g(me)),X=>`${X} (when initializing ${Se}, defined in ${Ee})`);ae.set(Se,()=>ce),de.add(Se),ue.set(Se,ce)};if(c.plugins)for(let Ce of c.plugins.split(\";\")){let Ee=K.resolve(t,fe.toPortablePath(Ce));await Ae(Ee,\"<environment>\")}for(let{path:Ce,cwd:Ee,data:g}of p)if(n&&Array.isArray(g.plugins))for(let Se of g.plugins){let Be=typeof Se!=\"string\"?Se.path:Se,me=Se?.spec??\"\",ce=Se?.checksum??\"\";if(X2.has(me))continue;let X=K.resolve(Ee,fe.toPortablePath(Be));if(!await le.existsPromise(X)){if(!me){let it=jt(f,K.basename(X,\".cjs\"),gt.NAME),_=jt(f,\".gitignore\",gt.NAME),tt=jt(f,f.values.get(\"rcFilename\"),gt.NAME),Ne=jt(f,\"https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored\",gt.URL);throw new st(`Missing source for the ${it} plugin - please try to remove the plugin from ${tt} then reinstall it manually. This error usually occurs because ${_} is incorrect, check ${Ne} to make sure your plugin folder isn't gitignored.`)}if(!me.match(/^https?:/)){let it=jt(f,K.basename(X,\".cjs\"),gt.NAME),_=jt(f,f.values.get(\"rcFilename\"),gt.NAME);throw new st(`Failed to recognize the source for the ${it} plugin - please try to delete the plugin from ${_} then reinstall it manually.`)}let De=await VH(me,{configuration:f}),Qe=fs(De);if(ce&&ce!==Qe){let it=jt(f,K.basename(X,\".cjs\"),gt.NAME),_=jt(f,f.values.get(\"rcFilename\"),gt.NAME),tt=jt(f,`yarn plugin import ${me}`,gt.CODE);throw new st(`Failed to fetch the ${it} plugin from its remote location: its checksum seems to have changed. If this is expected, please remove the plugin from ${_} then run ${tt} to reimport it.`)}await le.mkdirPromise(K.dirname(X),{recursive:!0}),await le.writeFilePromise(X,De)}await Ae(X,Ce)}}for(let[ae,de]of ue)f.activatePlugin(ae,de);if(f.useWithSource(\"<environment>\",T(c),t,{strict:s}),E){let[ae,de]=E;f.useWithSource(ae,T(de),C,{strict:s})}return f.get(\"enableGlobalCache\")&&(f.values.set(\"cacheFolder\",`${f.get(\"globalFolder\")}/cache`),f.sources.set(\"cacheFolder\",\"<internal>\")),f}static async findRcFiles(t){let r=$H(),s=[],a=t,n=null;for(;a!==n;){n=a;let c=K.join(n,r);if(le.existsSync(c)){let f,p;try{p=await le.readFilePromise(c,\"utf8\"),f=cs(p)}catch{let h=\"\";throw p?.match(/^\\s+(?!-)[^:]+\\s+\\S+/m)&&(h=\" (in particular, make sure you list the colons after each key name)\"),new st(`Parse error when loading ${c}; please check it's proper Yaml${h}`)}s.unshift({path:c,cwd:n,data:f})}a=K.dirname(n)}return s}static async findFolderRcFile(t){let r=K.join(t,Er.rc),s;try{s=await le.readFilePromise(r,\"utf8\")}catch(n){if(n.code===\"ENOENT\")return null;throw n}let a=cs(s);return{path:r,cwd:t,data:a}}static async findProjectCwd(t){let r=null,s=t,a=null;for(;s!==a;){if(a=s,le.existsSync(K.join(a,Er.lockfile)))return a;le.existsSync(K.join(a,Er.manifest))&&(r=a),s=K.dirname(a)}return r}static async updateConfiguration(t,r,s={}){let a=$H(),n=K.join(t,a),c=le.existsSync(n)?cs(await le.readFilePromise(n,\"utf8\")):{},f=!1,p;if(typeof r==\"function\"){try{p=r(c)}catch{p=r({})}if(p===c)return!1}else{p=c;for(let h of Object.keys(r)){let E=c[h],C=r[h],S;if(typeof C==\"function\")try{S=C(E)}catch{S=C(void 0)}else S=C;E!==S&&(S===e.deleteProperty?delete p[h]:p[h]=S,f=!0)}if(!f)return!1}return await le.changeFilePromise(n,cl(p),{automaticNewlines:!0}),!0}static async addPlugin(t,r){r.length!==0&&await e.updateConfiguration(t,s=>{let a=s.plugins??[];if(a.length===0)return{...s,plugins:r};let n=[],c=[...r];for(let f of a){let p=typeof f!=\"string\"?f.path:f,h=c.find(E=>E.path===p);h?(n.push(h),c=c.filter(E=>E!==h)):n.push(f)}return n.push(...c),{...s,plugins:n}})}static async updateHomeConfiguration(t){let r=hI();return await e.updateConfiguration(r,t)}activatePlugin(t,r){this.plugins.set(t,r),typeof r.configuration<\"u\"&&this.importSettings(r.configuration)}importSettings(t){for(let[r,s]of Object.entries(t))if(s!=null){if(this.settings.has(r))throw new Error(`Cannot redefine settings \"${r}\"`);this.settings.set(r,s),this.values.set(r,nj(this,s))}}useWithSource(t,r,s,a){try{this.use(t,r,s,a)}catch(n){throw n.message+=` (in ${jt(this,t,gt.PATH)})`,n}}use(t,r,s,{strict:a=!0,overwrite:n=!1}={}){a=a&&this.get(\"enableStrictSettings\");for(let c of[\"enableStrictSettings\",...Object.keys(r)]){let f=r[c],p=S8(f);if(p&&(t=p),typeof f>\"u\"||c===\"plugins\"||t===\"<environment>\"&&Itt.has(c))continue;if(c===\"rcFilename\")throw new st(`The rcFilename settings can only be set via ${`${yR}RC_FILENAME`.toUpperCase()}, not via a rc file`);let h=this.settings.get(c);if(!h){let C=hI(),S=t[0]!==\"<\"?K.dirname(t):null;if(a&&!(S!==null?C===S:!1))throw new st(`Unrecognized or legacy configuration settings found: ${c} - run \"yarn config\" to see the list of settings supported in Yarn`);this.invalid.set(c,t);continue}if(this.sources.has(c)&&!(n||h.type===\"MAP\"||h.isArray&&h.concatenateValues))continue;let E;try{E=rj(this,c,f,h,s)}catch(C){throw C.message+=` in ${jt(this,t,gt.PATH)}`,C}if(c===\"enableStrictSettings\"&&t!==\"<environment>\"){a=E;continue}if(h.type===\"MAP\"){let C=this.values.get(c);this.values.set(c,new Map(n?[...C,...E]:[...E,...C])),this.sources.set(c,`${this.sources.get(c)}, ${t}`)}else if(h.isArray&&h.concatenateValues){let C=this.values.get(c);this.values.set(c,n?[...C,...E]:[...E,...C]),this.sources.set(c,`${this.sources.get(c)}, ${t}`)}else this.values.set(c,E),this.sources.set(c,t)}}get(t){if(!this.values.has(t))throw new Error(`Invalid configuration key \"${t}\"`);return this.values.get(t)}getSpecial(t,{hideSecrets:r=!1,getNativePaths:s=!1}){let a=this.get(t),n=this.settings.get(t);if(typeof n>\"u\")throw new st(`Couldn't find a configuration settings named \"${t}\"`);return mR(a,n,{hideSecrets:r,getNativePaths:s})}getSubprocessStreams(t,{header:r,prefix:s,report:a}){let n,c,f=le.createWriteStream(t);if(this.get(\"enableInlineBuilds\")){let p=a.createStreamReporter(`${s} ${jt(this,\"STDOUT\",\"green\")}`),h=a.createStreamReporter(`${s} ${jt(this,\"STDERR\",\"red\")}`);n=new XH.PassThrough,n.pipe(p),n.pipe(f),c=new XH.PassThrough,c.pipe(h),c.pipe(f)}else n=f,c=f,typeof r<\"u\"&&n.write(`${r}\n`);return{stdout:n,stderr:c}}makeResolver(){let t=[];for(let r of this.plugins.values())for(let s of r.resolvers||[])t.push(new s);return new em([new TQ,new Ii,...t])}makeFetcher(){let t=[];for(let r of this.plugins.values())for(let s of r.fetchers||[])t.push(new s);return new uI([new fI,new AI,...t])}getLinkers(){let t=[];for(let r of this.plugins.values())for(let s of r.linkers||[])t.push(new s);return t}getSupportedArchitectures(){let t=Z2(),r=this.get(\"supportedArchitectures\"),s=r.get(\"os\");s!==null&&(s=s.map(c=>c===\"current\"?t.os:c));let a=r.get(\"cpu\");a!==null&&(a=a.map(c=>c===\"current\"?t.cpu:c));let n=r.get(\"libc\");return n!==null&&(n=zl(n,c=>c===\"current\"?t.libc??zl.skip:c)),{os:s,cpu:a,libc:n}}isInteractive({interactive:t,stdout:r}){return r.isTTY?t??this.get(\"preferInteractive\"):!1}async getPackageExtensions(){if(this.packageExtensions!==null)return this.packageExtensions;this.packageExtensions=new Map;let t=this.packageExtensions,r=(s,a,{userProvided:n=!1}={})=>{if(!dl(s.range))throw new Error(\"Only semver ranges are allowed as keys for the packageExtensions setting\");let c=new Ut;c.load(a,{yamlCompatibilityMode:!0});let f=C2(t,s.identHash),p=[];f.push([s.range,p]);let h={status:\"inactive\",userProvided:n,parentDescriptor:s};for(let E of c.dependencies.values())p.push({...h,type:\"Dependency\",descriptor:E});for(let E of c.peerDependencies.values())p.push({...h,type:\"PeerDependency\",descriptor:E});for(let[E,C]of c.peerDependenciesMeta)for(let[S,x]of Object.entries(C))p.push({...h,type:\"PeerDependencyMeta\",selector:E,key:S,value:x})};await this.triggerHook(s=>s.registerPackageExtensions,this,r);for(let[s,a]of this.get(\"packageExtensions\"))r(E0(s,!0),Wk(a),{userProvided:!0});return t}normalizeLocator(t){return dl(t.reference)?Ks(t,`${this.get(\"defaultProtocol\")}${t.reference}`):Up.test(t.reference)?Ks(t,`${this.get(\"defaultProtocol\")}${t.reference}`):t}normalizeDependency(t){return dl(t.range)?Mn(t,`${this.get(\"defaultProtocol\")}${t.range}`):Up.test(t.range)?Mn(t,`${this.get(\"defaultProtocol\")}${t.range}`):t}normalizeDependencyMap(t){return new Map([...t].map(([r,s])=>[r,this.normalizeDependency(s)]))}normalizePackage(t,{packageExtensions:r}){let s=x2(t),a=r.get(t.identHash);if(typeof a<\"u\"){let c=t.version;if(c!==null){for(let[f,p]of a)if(eA(c,f))for(let h of p)switch(h.status===\"inactive\"&&(h.status=\"redundant\"),h.type){case\"Dependency\":typeof s.dependencies.get(h.descriptor.identHash)>\"u\"&&(h.status=\"active\",s.dependencies.set(h.descriptor.identHash,this.normalizeDependency(h.descriptor)));break;case\"PeerDependency\":typeof s.peerDependencies.get(h.descriptor.identHash)>\"u\"&&(h.status=\"active\",s.peerDependencies.set(h.descriptor.identHash,h.descriptor));break;case\"PeerDependencyMeta\":{let E=s.peerDependenciesMeta.get(h.selector);(typeof E>\"u\"||!Object.hasOwn(E,h.key)||E[h.key]!==h.value)&&(h.status=\"active\",Zl(s.peerDependenciesMeta,h.selector,()=>({}))[h.key]=h.value)}break;default:b4(h)}}}let n=c=>c.scope?`${c.scope}__${c.name}`:`${c.name}`;for(let c of s.peerDependenciesMeta.keys()){let f=Pa(c);s.peerDependencies.has(f.identHash)||s.peerDependencies.set(f.identHash,Mn(f,\"*\"))}for(let c of s.peerDependencies.values()){if(c.scope===\"types\")continue;let f=n(c),p=xa(\"types\",f),h=fn(p);s.peerDependencies.has(p.identHash)||s.peerDependenciesMeta.has(h)||s.dependencies.has(p.identHash)||(s.peerDependencies.set(p.identHash,Mn(p,\"*\")),s.peerDependenciesMeta.set(h,{optional:!0}))}return s.dependencies=new Map(Ys(s.dependencies,([,c])=>hl(c))),s.peerDependencies=new Map(Ys(s.peerDependencies,([,c])=>hl(c))),s}getLimit(t){return Zl(this.limits,t,()=>(0,bAe.default)(this.get(t)))}async triggerHook(t,...r){for(let s of this.plugins.values()){let a=s.hooks;if(!a)continue;let n=t(a);n&&await n(...r)}}async triggerMultipleHooks(t,r){for(let s of r)await this.triggerHook(t,...s)}async reduceHook(t,r,...s){let a=r;for(let n of this.plugins.values()){let c=n.hooks;if(!c)continue;let f=t(c);f&&(a=await f(a,...s))}return a}async firstHook(t,...r){for(let s of this.plugins.values()){let a=s.hooks;if(!a)continue;let n=t(a);if(!n)continue;let c=await n(...r);if(typeof c<\"u\")return c}return null}}});var qr={};Yt(qr,{EndStrategy:()=>aj,ExecError:()=>IR,PipeError:()=>ev,execvp:()=>zH,pipevp:()=>Gu});function im(e){return e!==null&&typeof e.fd==\"number\"}function ij(){}function sj(){for(let e of sm)e.kill()}async function Gu(e,t,{cwd:r,env:s=process.env,strict:a=!1,stdin:n=null,stdout:c,stderr:f,end:p=2}){let h=[\"pipe\",\"pipe\",\"pipe\"];n===null?h[0]=\"ignore\":im(n)&&(h[0]=n),im(c)&&(h[1]=c),im(f)&&(h[2]=f);let E=(0,oj.default)(e,t,{cwd:fe.fromPortablePath(r),env:{...s,PWD:fe.fromPortablePath(r)},stdio:h});sm.add(E),sm.size===1&&(process.on(\"SIGINT\",ij),process.on(\"SIGTERM\",sj)),!im(n)&&n!==null&&n.pipe(E.stdin),im(c)||E.stdout.pipe(c,{end:!1}),im(f)||E.stderr.pipe(f,{end:!1});let C=()=>{for(let S of new Set([c,f]))im(S)||S.end()};return new Promise((S,x)=>{E.on(\"error\",I=>{sm.delete(E),sm.size===0&&(process.off(\"SIGINT\",ij),process.off(\"SIGTERM\",sj)),(p===2||p===1)&&C(),x(I)}),E.on(\"close\",(I,T)=>{sm.delete(E),sm.size===0&&(process.off(\"SIGINT\",ij),process.off(\"SIGTERM\",sj)),(p===2||p===1&&I!==0)&&C(),I===0||!a?S({code:lj(I,T)}):x(new ev({fileName:e,code:I,signal:T}))})})}async function zH(e,t,{cwd:r,env:s=process.env,encoding:a=\"utf8\",strict:n=!1}){let c=[\"ignore\",\"pipe\",\"pipe\"],f=[],p=[],h=fe.fromPortablePath(r);typeof s.PWD<\"u\"&&(s={...s,PWD:h});let E=(0,oj.default)(e,t,{cwd:h,env:s,stdio:c});return E.stdout.on(\"data\",C=>{f.push(C)}),E.stderr.on(\"data\",C=>{p.push(C)}),await new Promise((C,S)=>{E.on(\"error\",x=>{let I=ze.create(r),T=jt(I,e,gt.PATH);S(new _t(1,`Process ${T} failed to spawn`,O=>{O.reportError(1,`  ${Zf(I,{label:\"Thrown Error\",value:Mu(gt.NO_HINT,x.message)})}`)}))}),E.on(\"close\",(x,I)=>{let T=a===\"buffer\"?Buffer.concat(f):Buffer.concat(f).toString(a),O=a===\"buffer\"?Buffer.concat(p):Buffer.concat(p).toString(a);x===0||!n?C({code:lj(x,I),stdout:T,stderr:O}):S(new IR({fileName:e,code:x,signal:I,stdout:T,stderr:O}))})})}function lj(e,t){let r=xtt.get(t);return typeof r<\"u\"?128+r:e??1}function ktt(e,t,{configuration:r,report:s}){s.reportError(1,`  ${Zf(r,e!==null?{label:\"Exit Code\",value:Mu(gt.NUMBER,e)}:{label:\"Exit Signal\",value:Mu(gt.CODE,t)})}`)}var oj,aj,ev,IR,sm,xtt,gR=Ze(()=>{Dt();oj=et(vU());$2();Tc();kc();aj=(s=>(s[s.Never=0]=\"Never\",s[s.ErrorCode=1]=\"ErrorCode\",s[s.Always=2]=\"Always\",s))(aj||{}),ev=class extends _t{constructor({fileName:t,code:r,signal:s}){let a=ze.create(K.cwd()),n=jt(a,t,gt.PATH);super(1,`Child ${n} reported an error`,c=>{ktt(r,s,{configuration:a,report:c})}),this.code=lj(r,s)}},IR=class extends ev{constructor({fileName:t,code:r,signal:s,stdout:a,stderr:n}){super({fileName:t,code:r,signal:s}),this.stdout=a,this.stderr=n}};sm=new Set;xtt=new Map([[\"SIGINT\",2],[\"SIGQUIT\",3],[\"SIGKILL\",9],[\"SIGTERM\",15]])});function kAe(e){xAe=e}function tv(){return typeof cj>\"u\"&&(cj=xAe()),cj}var cj,xAe,uj=Ze(()=>{xAe=()=>{throw new Error(\"Assertion failed: No libzip instance is available, and no factory was configured\")}});var QAe=G((CR,Aj)=>{var Qtt=Object.assign({},Ie(\"fs\")),fj=function(){var e=typeof document<\"u\"&&document.currentScript?document.currentScript.src:void 0;return typeof __filename<\"u\"&&(e=e||__filename),function(t){t=t||{};var r=typeof t<\"u\"?t:{},s,a;r.ready=new Promise(function(Je,ot){s=Je,a=ot});var n={},c;for(c in r)r.hasOwnProperty(c)&&(n[c]=r[c]);var f=[],p=\"./this.program\",h=function(Je,ot){throw ot},E=!1,C=!0,S=\"\";function x(Je){return r.locateFile?r.locateFile(Je,S):S+Je}var I,T,O,U;C&&(E?S=Ie(\"path\").dirname(S)+\"/\":S=__dirname+\"/\",I=function(ot,St){var lr=Ue(ot);return lr?St?lr:lr.toString():(O||(O=Qtt),U||(U=Ie(\"path\")),ot=U.normalize(ot),O.readFileSync(ot,St?null:\"utf8\"))},T=function(ot){var St=I(ot,!0);return St.buffer||(St=new Uint8Array(St)),Se(St.buffer),St},process.argv.length>1&&(p=process.argv[1].replace(/\\\\/g,\"/\")),f=process.argv.slice(2),h=function(Je){process.exit(Je)},r.inspect=function(){return\"[Emscripten Module object]\"});var Y=r.print||console.log.bind(console),te=r.printErr||console.warn.bind(console);for(c in n)n.hasOwnProperty(c)&&(r[c]=n[c]);n=null,r.arguments&&(f=r.arguments),r.thisProgram&&(p=r.thisProgram),r.quit&&(h=r.quit);var ie=0,ue=function(Je){ie=Je},ae;r.wasmBinary&&(ae=r.wasmBinary);var de=r.noExitRuntime||!0;typeof WebAssembly!=\"object\"&&ns(\"no native wasm support detected\");function Ae(Je,ot,St){switch(ot=ot||\"i8\",ot.charAt(ot.length-1)===\"*\"&&(ot=\"i32\"),ot){case\"i1\":return je[Je>>0];case\"i8\":return je[Je>>0];case\"i16\":return gh((Je>>1)*2);case\"i32\":return ao((Je>>2)*4);case\"i64\":return ao((Je>>2)*4);case\"float\":return hf((Je>>2)*4);case\"double\":return hh((Je>>3)*8);default:ns(\"invalid type for getValue: \"+ot)}return null}var Ce,Ee=!1,g;function Se(Je,ot){Je||ns(\"Assertion failed: \"+ot)}function Be(Je){var ot=r[\"_\"+Je];return Se(ot,\"Cannot call unknown function \"+Je+\", make sure it is exported\"),ot}function me(Je,ot,St,lr,ee){var ye={string:function(qi){var Fn=0;if(qi!=null&&qi!==0){var Ja=(qi.length<<2)+1;Fn=Bi(Ja),it(qi,Fn,Ja)}return Fn},array:function(qi){var Fn=Bi(qi.length);return Ne(qi,Fn),Fn}};function Oe(qi){return ot===\"string\"?De(qi):ot===\"boolean\"?!!qi:qi}var mt=Be(Je),Et=[],bt=0;if(lr)for(var tr=0;tr<lr.length;tr++){var pn=ye[St[tr]];pn?(bt===0&&(bt=mf()),Et[tr]=pn(lr[tr])):Et[tr]=lr[tr]}var ci=mt.apply(null,Et);return ci=Oe(ci),bt!==0&&Ac(bt),ci}function ce(Je,ot,St,lr){St=St||[];var ee=St.every(function(Oe){return Oe===\"number\"}),ye=ot!==\"string\";return ye&&ee&&!lr?Be(Je):function(){return me(Je,ot,St,arguments,lr)}}var X=new TextDecoder(\"utf8\");function De(Je,ot){if(!Je)return\"\";for(var St=Je+ot,lr=Je;!(lr>=St)&&Re[lr];)++lr;return X.decode(Re.subarray(Je,lr))}function Qe(Je,ot,St,lr){if(!(lr>0))return 0;for(var ee=St,ye=St+lr-1,Oe=0;Oe<Je.length;++Oe){var mt=Je.charCodeAt(Oe);if(mt>=55296&&mt<=57343){var Et=Je.charCodeAt(++Oe);mt=65536+((mt&1023)<<10)|Et&1023}if(mt<=127){if(St>=ye)break;ot[St++]=mt}else if(mt<=2047){if(St+1>=ye)break;ot[St++]=192|mt>>6,ot[St++]=128|mt&63}else if(mt<=65535){if(St+2>=ye)break;ot[St++]=224|mt>>12,ot[St++]=128|mt>>6&63,ot[St++]=128|mt&63}else{if(St+3>=ye)break;ot[St++]=240|mt>>18,ot[St++]=128|mt>>12&63,ot[St++]=128|mt>>6&63,ot[St++]=128|mt&63}}return ot[St]=0,St-ee}function it(Je,ot,St){return Qe(Je,Re,ot,St)}function _(Je){for(var ot=0,St=0;St<Je.length;++St){var lr=Je.charCodeAt(St);lr>=55296&&lr<=57343&&(lr=65536+((lr&1023)<<10)|Je.charCodeAt(++St)&1023),lr<=127?++ot:lr<=2047?ot+=2:lr<=65535?ot+=3:ot+=4}return ot}function tt(Je){var ot=_(Je)+1,St=qa(ot);return St&&Qe(Je,je,St,ot),St}function Ne(Je,ot){je.set(Je,ot)}function ke(Je,ot){return Je%ot>0&&(Je+=ot-Je%ot),Je}var be,je,Re,ct,Me,P,w,b,y,F;function z(Je){be=Je,r.HEAP_DATA_VIEW=F=new DataView(Je),r.HEAP8=je=new Int8Array(Je),r.HEAP16=ct=new Int16Array(Je),r.HEAP32=P=new Int32Array(Je),r.HEAPU8=Re=new Uint8Array(Je),r.HEAPU16=Me=new Uint16Array(Je),r.HEAPU32=w=new Uint32Array(Je),r.HEAPF32=b=new Float32Array(Je),r.HEAPF64=y=new Float64Array(Je)}var Z=r.INITIAL_MEMORY||16777216,$,se=[],xe=[],Fe=[],ut=!1;function Ct(){if(r.preRun)for(typeof r.preRun==\"function\"&&(r.preRun=[r.preRun]);r.preRun.length;)Pt(r.preRun.shift());Ns(se)}function qt(){ut=!0,Ns(xe)}function ir(){if(r.postRun)for(typeof r.postRun==\"function\"&&(r.postRun=[r.postRun]);r.postRun.length;)Pr(r.postRun.shift());Ns(Fe)}function Pt(Je){se.unshift(Je)}function dn(Je){xe.unshift(Je)}function Pr(Je){Fe.unshift(Je)}var Ir=0,Or=null,on=null;function li(Je){Ir++,r.monitorRunDependencies&&r.monitorRunDependencies(Ir)}function So(Je){if(Ir--,r.monitorRunDependencies&&r.monitorRunDependencies(Ir),Ir==0&&(Or!==null&&(clearInterval(Or),Or=null),on)){var ot=on;on=null,ot()}}r.preloadedImages={},r.preloadedAudios={};function ns(Je){r.onAbort&&r.onAbort(Je),Je+=\"\",te(Je),Ee=!0,g=1,Je=\"abort(\"+Je+\"). Build with -s ASSERTIONS=1 for more info.\";var ot=new WebAssembly.RuntimeError(Je);throw a(ot),ot}var so=\"data:application/octet-stream;base64,\";function Do(Je){return Je.startsWith(so)}var ji=\"data:application/octet-stream;base64,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QCAAKAJIIgEgASADaiADEAcaAkAgAyAAKAJsIgFNBEAgACABIANrNgJsDAELIABCADcCbAsgACAAKAJoIANrIgE2AmggACAAKAJYIANrNgJYIAEgACgChC5JBEAgACABNgKELgsgAEH8gAEoAgARAwAgAiADaiECCwJAIAAoAgAiASgCBCIERQ0AIAAoAjwhBSAAIAIgBCACIARJGyICBH8gACgCSCAAKAJoaiAFaiEFIAEgBCACazYCBAJAAkACQAJAIAEoAhwiBCgCFEEBaw4CAQACCyAEQaABaiAFIAEoAgAgAkHcgAEoAgARCAAMAgsgASABKAIwIAUgASgCACACQcSAASgCABEEADYCMAwBCyAFIAEoAgAgAhAHGgsgASABKAIAIAJqNgIAIAEgASgCCCACajYCCCAAKAI8BSAFCyACaiICNgI8AkAgACgChC4iASACakEDSQ0AIAAoAmggAWshAQJAIAAoAnRBgQhPBEAgACAAIAAoAkggAWoiAi0AACACLQABIAAoAnwRAAA2AlQMAQsgAUUNACAAIAFBAWsgACgChAERAgAaCyAAKAKELiAAKAI8IgJBAUZrIgRFDQAgACABIAQgACgCgAERBQAgACAAKAKELiAEazYChC4gACgCPCECCyACQYUCSw0AIAAoAgAoAgRFDQAgACgCMCEBDAELCwJAIAAoAkQiAiAAKAJAIgNNDQAgAAJ/IAAoAjwgACgCaGoiASADSwRAIAAoAkggAWpBACACIAFrIgNBggIgA0GCAkkbIgMQGSABIANqDAELIAFBggJqIgEgA00NASAAKAJIIANqQQAgAiADayICIAEgA2siAyACIANJGyIDEBkgACgCQCADags2AkALC50CAQF/AkAgAAJ/IAAoAqAuIgFBwABGBEAgACgCBCAAKAIQaiAAKQOYLjcAACAAQgA3A5guIAAgACgCEEEIajYCEEEADAELIAFBIE4EQCAAKAIEIAAoAhBqIAApA5guPgAAIAAgAEGcLmo1AgA3A5guIAAgACgCEEEEajYCECAAIAAoAqAuQSBrIgE2AqAuCyABQRBOBEAgACgCBCAAKAIQaiAAKQOYLj0AACAAIAAoAhBBAmo2AhAgACAAKQOYLkIQiDcDmC4gACAAKAKgLkEQayIBNgKgLgsgAUEISA0BIAAgACgCECIBQQFqNgIQ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KAJUIgEEfyABQQAgARAiEBkgACgCVAVBAAsQBiAAQQA2AlQLC9wMAgl/AX4jAEFAaiIGJAACQAJAAkACQAJAIAEoAjBBABAjIgVBAkZBACABKAI4QQAQIyIEQQFGGw0AIAVBAUZBACAEQQJGGw0AIAVBAkciAw0BIARBAkcNAQsgASABLwEMQYAQcjsBDEEAIQMMAQsgASABLwEMQf/vA3E7AQxBACEFIANFBEBB9eABIAEoAjAgAEEIahBpIgVFDQILIAJBgAJxBEAgBSEDDAELIARBAkcEQCAFIQMMAQtB9cYBIAEoAjggAEEIahBpIgNFBEAgBRAcDAILIAMgBTYCAAsgASABLwEMQf7/A3EgAS8BUiIFQQBHcjsBDAJAAkACQAJAAn8CQAJAIAEpAyhC/v///w9WDQAgASkDIEL+////D1YNACACQYAEcUUNASABKQNIQv////8PVA0BCyAFQYECa0H//wNxQQNJIQdBAQwBCyAFQYECa0H//wNxIQQgAkGACnFBgApHDQEgBEEDSSEHQQALIQkgBkIcEBciBEUEQCAAQQhqIgAEQCAAQQA2AgQgAEEONgIACyADEBwMBQsgAkGACHEhBQJAAkAgAkGAAnEEQAJAIAUNACABKQMgQv////8PVg0AIAEpAyhCgICAgBBUDQMLIAQgASkDKBAYIAEpAyAhDAwBCwJAAkACQCAFDQAgASkDIEL/////D1YNACABKQMoIgxC/////w9WDQEgASkDSEKAgICAEFQNBAsgASkDKCIMQv////8PVA0BCyAEIAwQGAsgASkDICIMQv////8PWgRAIAQgDBAYCyABKQNIIgxC/////w9UDQELIAQgDBAYCyAELQAARQRAIABBCGoiAARAIABBADYCBCAAQRQ2AgALIAQQCCADEBwMBQtBASEKQQEgBC0AAAR+IAQpAxAFQgALp0H//wNxIAYQRyEFIAQQCCAFIAM2AgAgBw0BDAILIAMhBSAEQQJLDQELIAZCBxAXIgRFBEAgAEEIaiIABEAgAEEANgIEIABBDjYCAAsgBRAcDAMLIARBAhANIARBhxJBAhAsIAQgAS0AUhBwIAQgAS8BEBANIAQtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAsgBBAIDAILQYGyAkEHIAYQRyEDIAQQCCADIAU2AgBBASEL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NgIEIABB7A42AhggGiEdDAMLIARB/wFxIgJBwABxRQRAIAggDSADLwECQQJ0aiAdp0F/IAJ0QX9zcUECdGoiAy0AASICayEIIB0gAq2IIR0gAy0AACIERQ0HDAELCyAEQSBxBEAgB0G//gA2AgQgASECDAgLIAdB0f4ANgIEIABB0A42AhggASECDAcLIB1BfyAGdEF/c62DIBt8IhunIQUgCCAEQQ9xIgNrIQggGiAErUIPg4ghHSABIBdrIgYgAjMBAiAaQX8gA3RBf3Otg3ynIgRPDQIgBCAGayIGIBlNDQEgBygCjEdFDQEgB0HR/gA2AgQgAEG5DDYCGAsgASECIAshBQwFCwJAIA5FBEAgDCARIAZraiEDDAELIAYgDk0EQCAMIA4gBmtqIQMMAQsgDCARIAYgDmsiBmtqIQMgBSAGTQ0AIAUgBmshBQJAAkAgASADTSABIA8gAWusIhogBq0iGyAaIBtUGyIapyIGaiICIANLcQ0AIAMgBmogAUsgASADT3ENACABIAMgBhAHGiACIQEMAQsgASADIAMgAWsiASABQR91IgFqIAFzIgIQByACaiEBIBogAq0iHn0iHFANACACIANqIQIDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgASACKQAANwAAIAEgAikAGDcAGCABIAIpABA3ABAgASACKQAINwAIIBpCIH0hGiACQSBqIQIgAUEgaiEBIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAEgAikAADcAACABIAIpABg3ABggASACKQAQNwAQIAEgAikACDcACCABIAIpADg3ADggASACKQAwNwAwIAEgAikAKDcAKCABIAIpACA3ACAgASACKQBYNwBYIAEgAikAUDcAUCABIAIpAEg3AEggASACKQBANwBAIAEgAikAYDcAYCABIAIpAGg3AGggASACKQBwNwBwIAEgAikAeDcAeCACQYABaiECIAFBgAFqIQEgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAEgAikAADcAACABIAIpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCABIAIpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCABIAIoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCABIAIvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCABIAItAAA6AAAgAkEBaiECIAFBAWohAQsgHEIAUg0ACwsgDiEGIAwhAwsgBSAGSwRAAkACQCABIANNIAEgDyABa6wiGiAGrSIbIBogG1QbIhqnIglqIgIgA0txDQAgAyAJaiABSyABIANPcQ0AIAEgAyAJEAcaDAELIAEgAyADIAFrIgEgAUEfdSIBaiABcyIBEAcgAWohAiAaIAGtIh59IhxQDQAgASADaiEBA0ACQCAcIB4gHCAeVBsiG0IgVARAIBshGgwBCyAbIhpCIH0iIEIFiEIBfEIDgyIfUEUEQANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCAaQiB9IRogAUEgaiEBIAJBIGohAiAfQgF9Ih9CAFINAAsLICBC4ABUDQADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggAiABKQA4NwA4IAIgASkAMDcAMCACIAEpACg3ACggAiABKQAgNwAgIAIgASkAWDcAWCACIAEpAFA3AFAgAiABKQBINwBIIAIgASkAQDcAQCACIAEpAGA3AGAgAiABKQBoNwBoIAIgASkAcDcAcCACIAEpAHg3AHggAUGAAWohASACQYABaiECIBpCgAF9IhpCH1YNAAsLIBpCEFoEQCACIAEpAAA3AAAgAiABKQAINwAIIBpCEH0hGiACQRBqIQIgAUEQaiEBCyAaQghaBEAgAiABKQAANwAAIBpCCH0hGiACQQhqIQIgAUEIaiEBCyAaQgRaBEAgAiABKAAANgAAIBpCBH0hGiACQQRqIQIgAUEEaiEBCyAaQgJaBEAgAiABLwAAOwAAIBpCAn0hGiACQQJqIQIgAUECaiEBCyAcIBt9IRwgGlBFBEAgAiABLQAAOgAAIAJBAWohAiABQQFqIQELIBxCAFINAAsLIAUgBmshAUEAIARrIQUCQCAEQQdLBEAgBCEDDAELIAEgBE0EQCAEIQMMAQsgAiAEayEFA0ACQCACIAUpAAA3AAAgBEEBdCEDIAEgBGshASACIARqIQIgBEEDSw0AIAMhBCABIANLDQELC0EAIANrIQULIAIgBWohBAJAIAUgDyACa6wiGiABrSIbIBogG1QbIhqnIgFIIAVBf0pxDQAgBUEBSCABIARqIAJLcQ0AIAIgBCABEAcgAWohAgwDCyACIAQgAyADQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANAiABIARqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAILAkAgASADTSABIA8gAWusIhogBa0iGyAaIBtUGyIapyIEaiICIANLcQ0AIAMgBGogAUsgASADT3ENACABIAMgBBAHGgwCCyABIAMgAyABayIBIAFBH3UiAWogAXMiARAHIAFqIQIgGiABrSIefSIcUA0BIAEgA2ohAQNAAkAgHCAeIBwgHlQbIhtCIFQEQCAbIRoMAQsgGyIaQiB9IiBCBYhCAXxCA4MiH1BFBEADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggGkIgfSEaIAFBIGohASACQSBqIQIgH0IBfSIfQgBSDQALCyAgQuAAVA0AA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIAIgASkAODcAOCACIAEpADA3ADAgAiABKQAoNwAoIAIgASkAIDcAICACIAEpAFg3AFggAiABKQBQNwBQIAIgASkASDcASCACIAEpAEA3AEAgAiABKQBgNwBgIAIgASkAaDcAaCACIAEpAHA3AHAgAiABKQB4NwB4IAFBgAFqIQEgAkGAAWohAiAaQoABfSIaQh9WDQALCyAaQhBaBEAgAiABKQAANwAAIAIgASkACDcACCAaQhB9IRogAkEQaiECIAFBEGohAQsgGkIIWgRAIAIgASkAADcAACAaQgh9IRogAkEIaiECIAFBCGohAQsgGkIEWgRAIAIgASgAADYAACAaQgR9IRogAkEEaiECIAFBBGohAQsgGkICWgRAIAIgAS8AADsAACAaQgJ9IRogAkECaiECIAFBAmohAQsgHCAbfSEcIBpQRQRAIAIgAS0AADoAACACQQFqIQIgAUEBaiEBCyAcUEUNAAsMAQsCQAJAIBYEQAJAIAQgBUkEQCAHKAKYRyAESw0BCyABIARrIQMCQEEAIARrIgVBf0ogDyABa6wiGiAbIBogG1QbIhqnIgIgBUpxDQAgBUEBSCACIANqIAFLcQ0AIAEgAyACEAcgAmohAgwFCyABIAMgBCAEQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANBCABIANqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAQLIBAgAWsiCUEBaiIGIAUgBSAGSxshAyABIARrIQIgAUEHcUUNAiADRQ0CIAEgAi0AADoAACACQQFqIQIgAUEBaiIGQQdxQQAgA0EBayIFGw0BIAYhASAFIQMgCSEGDAILAkAgBCAFSQRAIAcoAphHIARLDQELIAEgASAEayIGKQAANwAAIAEgBUEBa0EHcUEBaiIDaiECIAUgA2siBEUNAyADIAZqIQEDQCACIAEpAAA3AAAgAUEIaiEBIAJBCGohAiAEQQhrIgQNAAsMAwsgASAEIAUQPyECDAILIAEgAi0AADoAASAJQQFrIQYgA0ECayEFIAJBAWohAgJAIAFBAmoiCkEHcUUNACAFRQ0AIAEgAi0AADoAAiAJQQJrIQYgA0EDayEFIAJBAWohAgJAIAFBA2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAAyAJQQNrIQYgA0EEayEFIAJBAWohAgJAIAFBBGoiCkEHcUUNACAFRQ0AIAEgAi0AADoABCAJQQRrIQYgA0EFayEFIAJBAWohAgJAIAFBBWoiCkEHcUUNACAFRQ0AIAEgAi0AADoABSAJQQVrIQYgA0EGayEFIAJBAWohAgJAIAFBBmoiCkEHcUUNACAFRQ0AIAEgAi0AADoABiAJQQZrIQYgA0EHayEFIAJBAWohAgJAIAFBB2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAByAJQQdrIQYgA0EIayEDIAFBCGohASACQQFqIQIMBgsgCiEBIAUhAwwFCyAKIQEgBSEDDAQLIAohASAFIQMMAwsgCiEBIAUhAwwCCyAKIQEgBSEDDAELIAohASAFIQMLAkACQCAGQRdNBEAgA0UNASADQQFrIQUgA0EHcSIEBEADQCABIAItAAA6AAAgA0EBayEDIAFBAWohASACQQFqIQIgBEEBayIEDQALCyAFQQdJDQEDQCABIAItAAA6AAAgASACLQABOgABIAEgAi0AAjoAAiABIAItAAM6AAMgASACLQAEOgAEIAEgAi0ABToABSABIAItAAY6AAYgASACLQAHOgAHIAFBCGohASACQQhqIQIgA0EIayIDDQALDAELIAMNAQsgASECDAELIAEgBCADED8hAgsgCyEFDAELIAEgAy0AAjoAACABQQFqIQILIAUgFE8NACACIBNJDQELCyAAIAI2AgwgACAFIAhBA3ZrIgE2AgAgACATIAJrQYMCajYCECAAIBQgAWtBDmo2AgQgByAIQQdxIgA2AogBIAcgHUJ/IACthkJ/hYM+AoQBC+cFAQR/IAMgAiACIANLGyEEIAAgAWshAgJAIABBB3FFDQAgBEUNACAAIAItAAA6AAAgA0EBayEGIAJBAWohAiAAQQFqIgdBB3FBACAEQQFrIgUbRQRAIAchACAFIQQgBiEDDAELIAAgAi0AADoAASADQQJrIQYgBEECayEFIAJBAWohAgJAIABBAmoiB0EHcUUNACAFRQ0AIAAgAi0AADoAAiADQQNrIQYgBEEDayEFIAJBAWohAgJAIABBA2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAAyADQQRrIQYgBEEEayEFIAJBAWohAgJAIABBBGoiB0EHcUUNACAFRQ0AIAAgAi0AADoABCADQQVrIQYgBEEFayEFIAJBAWohAgJAIABBBWoiB0EHcUUNACAFRQ0AIAAgAi0AADoABSADQQZrIQYgBEEGayEFIAJBAWohAgJAIABBBmoiB0EHcUUNACAFRQ0AIAAgAi0AADoABiADQQdrIQYgBEEHayEFIAJBAWohAgJAIABBB2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAByADQQhrIQMgBEEIayEEIABBCGohACACQQFqIQIMBgsgByEAIAUhBCAGIQMMBQsgByEAIAUhBCAGIQMMBAsgByEAIAUhBCAGIQMMAwsgByEAIAUhBCAGIQMMAgsgByEAIAUhBCAGIQMMAQsgByEAIAUhBCAGIQMLAkAgA0EXTQRAIARFDQEgBEEBayEBIARBB3EiAwRAA0AgACACLQAAOgAAIARBAWshBCAAQQFqIQAgAkEBaiECIANBAWsi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CyAAIAMtAAAEfiADKQMQBUIAC6dB//8DcSADKAIEEEcLIQUgAxAICyAEQRBqJAAgBQvgAQICfwF+QTAQCSICRQRAIAEEQCABQQA2AgQgAUEONgIAC0EADwsgAkIANwMIIAJBADYCACACQgA3AxAgAkIANwMYIAJCADcDICACQgA3ACUgAFAEQCACDwsCQCAAQv////8AVg0AIACnQQR0EAkiA0UNACACIAM2AgBBACEBQgEhBANAIAMgAUEEdGoiAUIANwIAIAFCADcABSAAIARSBEAgBKchASAEQgF8IQQMAQsLIAIgADcDCCACIAA3AxAgAg8LIAEEQCABQQA2AgQgAUEONgIAC0EAEBAgAhAGQQAL7gECA38BfiMAQRBrIgQkAAJAIARBDGpCBBAXIgNFBEBBfyECDAELAkAgAQRAIAJBgAZxIQUDQAJAIAUgASgCBHFFDQACQCADKQMIQgBUBEAgA0EAOgAADAELIANCADcDECADQQE6AAALIAMgAS8BCBANIAMgAS8BChANIAMtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAtBfyECDAQLQX8hAiAAIARBDGpCBBAbQQBIDQMgATMBCiIGUA0AIAAgASgCDCAGEBtBAEgNAwsgASgCACIBDQALC0EAIQILIAMQCAsgBEEQaiQAIAILPAEBfyAABEAgAUGABnEhAQNAIAEgACgCBHEEQCACIAAvAQpqQQRqIQILIAAoAgAiAA0ACwsgAkH//wNxC5wBAQN/IABFBEBBAA8LIAAhAwNAAn8CQAJAIAAvAQgiAUH04AFNBEAgAUEBRg0BIAFB9cYBRg0BDAILIAFBgbICRg0AIAFB9eABRw0BCyAAKAIAIQEgAEEANgIAIAAoAgwQBiAAEAYgASADIAAgA0YbIQMCQCACRQRAQQAhAgwBCyACIAE2AgALIAEMAQsgACICKAIACyIADQALIAMLsgQCBX8BfgJAAkACQCAAIAGtEBciAQRAIAEtAAANAUEAIQAMAgsgBARAIARBADYCBCAEQQ42AgALQQAPC0EAIQADQCABLQAABH4gASkDCCABKQMQfQVCAAtCBFQNASABEAwhByABIAEQDCIGrRATIghFBEBBACECIAQEQCAEQQA2AgQgBEEVNgIACyABEAggAEUNAwNAIAAoAgAhASAAKAIMEAYg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DCAAQRg2AggLDAMLIAAgBiAFLwFqQQAgBCABEQYAIQEgBhALIAFFDQILAkAgDUUEQCABIQMMAQsgACABIAUvAWgQgQEhAyABEAsgA0UNAQsCQCAJRSAMckUEQCADIQEMAQsgACADQQEQgAEhASADEAsgAUUNAQsgASEDDAELQQAhAwsgBUHwAGokACADC4UBAQF/IAFFBEAgAEEIaiIABEAgAEEANgIEIABBEjYCAAtBAA8LQTgQCSIDRQRAIABBCGoiAARAIABBADYCBCAAQQ42AgALQQAPCyADQQA2AhAgA0IANwIIIANCADcDKCADQQA2AgQgAyACNgIAIANCADcDGCADQQA2AjAgACABQTsgAxBCCw8AIAAgASACQQBBABCCAQusAgECfyABRQRAIABBCGoiAARAIABBADYCBCAAQRI2AgALQQAPCwJAIAJBfUsNACACQf//A3FBCEYNACAAQQhqIgAEQCAAQQA2AgQgAEEQNgIAC0EADwsCQEGwwAAQCSIFBEAgBUEANgIIIAVCADcCACAFQYiBAUGogQEgAxs2AqhAIAUgAjYCFCAFIAM6ABAgBUEAOgAPIAVBADsBDCAFIAMgAkF9SyIGcToADiAFQQggAiAGG0H//wNxIAQgBUGIgQFBqIEBIAMbKAIAEQAAIgI2AqxAIAINASAFEDEgBRAGCyAAQQhqIgAEQCAAQQA2AgQgAEEONgIAC0EADwsgACABQTogBRBCIgAEfyAABSAFKAKsQCAFKAKoQCgCBBEDACAFEDEgBRAGQQALC6ABAQF/IAIgACgCBCIDIAIgA0kbIgIEQCAAIAMgAms2AgQCQAJAAkACQCAAKAIcIgMoAhRBAWsOAgEAAgsgA0GgAWogASAAKAIAIAJB3IABKAIAEQgADAILIAAgACgCMCABIAAoAgAgAkHEgAEoAgARBAA2AjAMAQsgASAAKAIAIAIQBxoLIAAgACgCACACajYCACAAIAAoAgggAmo2AggLC7cCAQR/QX4hAgJAIABFDQAgACgCIEUNACAAKAIkIgRFDQAgACgCHCIBRQ0AIAEoAgAgAEcNAAJAAkAgASgCICIDQTlrDjkBAgICAgICAgICAgIBAgICAQICAgICAgICAgICAgICAgICAQICAgICAgICAgICAQICAgICAgICAgEACyADQZoFRg0AIANBKkcN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DCABajYCDCAGIAYoAgggAWo2AgggBSAFKAIUIAFqNgIUIAUgBSgCECABazYCECAGIAYoAhAgAWsiATYCECABDQAgBiAGKAIENgIIC0EAIQRBACEJIAMoAhBFDQAMCgsgAygCHCgCJCEGIAMgAygCGCIBQQFqNgIYIAEgBmotAAAhASADIARBAWo2AhAgAygCBCAEaiABOgAAIAEEQCADKAIQIQQMAQsLIAMoAhwoAixFDQAgAygCECIGIAlNDQAgBQJ/IAUoAjAhBEEAIAMoAgQgCWoiAUUNABogBCABIAYgCWtB1IABKAIAEQAACzYCMAsgA0HnADYCIAsCQCADKAIcKAIsBEAgAygCDCADKAIQIgFBAmpJBH8gBRAKIAMoAhANAkEABSABCyADKAIEaiAFKAIwOwAAIAMgAygCEEECajYCECADQaABakHkgAEoAgARAQAaCyADQfEANgIgIAUQCiADKAIQRQ0BDAcLDAYLIAUoAgQNAQsgAygCPA0AIApFDQEgAygCIEGaBUYNAQsCfyADKAKIASIBRQRAIAMgChCFAQwBCwJAAkACQCADKAKMAUECaw4CAAECCwJ/AkADQAJAAkAgAygCPA0AIAMQLyADKAI8DQAgCg0BQQAMBAsgAygCSCADKAJoai0AACEEIAMgAygC8C0iAUEBajYC8C0gASADKALsLWpBADoAACADIAMoAvAtIgFBAWo2AvAtIAEgAygC7C1qQQA6AAAgAyADKALwLSIBQQFqNgLwLSABIAMoAuwtaiAEOgAAIAMgBEECdGoiASABLwHkAUEBajsB5AEgAyADKAI8QQFrNgI8IAMgAygCaEEBaiIBNgJoIAMoAvAtIAMoAvQtRw0BQQAhBCADIAMoAlgiBkEATgR/IAMoAkggBmoFQQALIAEgBmtBABAPIAMgAygCaDYCWCADKAIAEAogAygCACgCEA0BDAILCyADQQA2AoQuIApBBEYEQCADIAMoAlgiAUEATgR/IAMoAkggAWoFQQALIAMoAmggAWtBARAPIAMgAygCaDYCWCADKAIAEApBA0ECIAMoAgAoAhAbDAILIAMoAvAtBEBBACEEIAMgAygCWCIBQQBOBH8gAygCSCABagVBAAsgAygCaCABa0EAEA8gAyADKAJoNgJYIAMoAgAQCiADKAIAKAIQRQ0BC0EBIQQLIAQL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bGl0ZXJhbC9sZW5ndGhzIHNldABpbnZhbGlkIGNvZGUgbGVuZ3RocyBzZXQAdW5rbm93biBoZWFkZXIgZmxhZ3Mgc2V0AGludmFsaWQgZGlzdGFuY2VzIHNldABpbnZhbGlkIGJpdCBsZW5ndGggcmVwZWF0AEZpbGUgYWxyZWFkeSBleGlzdHMAdG9vIG1hbnkgbGVuZ3RoIG9yIGRpc3RhbmNlIHN5bWJvbHMAaW52YWxpZCBzdG9yZWQgYmxvY2sgbGVuZ3RocwAlcyVzJXMAYnVmZmVyIGVycm9yAE5vIGVycm9yAHN0cmVhbSBlcnJvcgBUZWxsIGVycm9yAEludGVybmFsIGVycm9yAFNlZWsgZXJyb3IAV3JpdGUgZXJyb3IAZmlsZSBlcnJvcgBSZWFkIGVycm9yAFpsaWIgZXJyb3IAZGF0YSBlcnJvcgBDUkMgZXJyb3IAaW5jb21wYXRpYmxlIHZlcnNpb24AaW52YWxpZCBjb2RlIC0tIG1pc3NpbmcgZW5kLW9mLWJsb2NrAGluY29ycmVjdCBoZWFkZXIgY2hlY2sAaW5jb3JyZWN0IGxlbmd0aCBjaGVjawBpbmNvcnJlY3QgZGF0YSBjaGVjawBpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjawBoZWFkZXIgY3JjIG1pc21hdGNoADEuMi4xMy56bGliLW5nAGludmFsaWQgd2luZG93IHNpemUAUmVhZC1vbmx5IGFyY2hpdmUATm90IGEgemlwIGFyY2hpdmUAUmVzb3VyY2Ugc3RpbGwgaW4gdXNlAE1hbGxvYyBmYWlsdXJlAGludmFsaWQgYmxvY2sgdHlwZQBGYWlsdXJlIHRvIGNyZWF0ZSB0ZW1wb3JhcnkgZmlsZQBDYW4ndCBvcGVuIGZpbGUATm8gc3VjaCBmaWxlAFByZW1hdHVyZSBlbmQgb2YgZmlsZQBDYW4ndCByZW1vdmUgZmlsZQBpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUAaW52YWxpZCBkaXN0YW5jZSBjb2RlAHVua25vd24gY29tcHJlc3Npb24gbWV0aG9kAHN0cmVhbSBlbmQAQ29tcHJlc3NlZCBkYXRhIGludmFsaWQATXVsdGktZGlzayB6aXAgYXJjaGl2ZXMgbm90IHN1cHBvcnRl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UgAIANIACAAyAAgAsgAIAHIACADyAAgACgAIAIoACABKAAgAygAIACoACACqAAgAagAIAOoACAAaAAgAmgAIAFoACADaAAgAOgAIALoACAB6AAgA+gAIAAYACACGAAgARgAIAMYACAAmAAgApgAIAGYACADmAAgAFgAIAJYACABWAAgA1gAIADYACAC2AAgAdgAIAPYACAAOAAgAjgAIAE4ACADOAAgALgAIAK4ACABuAAgA7gAIAB4ACACeAAgAXgAIAN4ACAA+AAgAvgAIAH4ACAD+AAgAAQAIAIEACABBAAgAwQAIACEACAChAAgAYQAIAOEACAARAAgAkQAIAFEACADRAAgAMQAIALEACABxAAgA8QAIAAkACACJAAgASQAIAMkACAApAAgAqQAIAGkACADpAAgAGQAIAJkACABZAAgA2QAIADkACAC5AAgAeQAIAPkACAAFAAgAhQAIAEUACADFAAgAJQAIAKUACABlAAgA5QAIABUACACVAAgAVQAIANUACAA1AAgAtQAIAHUACAD1AAgADQAIAI0ACABNAAgAzQAIAC0ACACtAAgAbQAIAO0ACAAdAAgAnQAIAF0ACADdAAgAPQAIAL0ACAB9AAgA/QAIABMACQATAQkAkwAJAJMBCQBTAAkAUwEJANMACQDTAQkAMwAJADMBCQCzAAkAswEJAHMACQBzAQkA8wAJAPMBCQALAAkACwEJAIsACQCLAQkASwAJAEsBCQDLAAkAywEJACsACQArAQkAqwAJAKsBCQBrAAkAawEJAOsACQDrAQkAGwAJABsBCQCbAAkAmwEJAFsACQBbAQkA2wAJANsBCQA7AAkAOwEJALsACQC7AQkAewAJAHsBCQD7AAkA+wEJAAcACQAHAQkAhwAJAIcBCQBHAAkARwEJAMcACQDHAQkAJwAJACcBCQCnAAkApwEJAGcACQBnAQkA5wAJAOcBCQAXAAkAFwEJAJcACQCXAQkAVwAJAFcBCQDXAAkA1wEJADcACQA3AQkAtwAJALcBCQB3AAkAdwEJAPcACQD3AQkADwAJAA8BCQCPAAkAjwEJAE8ACQBPAQkAzwAJAM8BCQAvAAkALwEJAK8ACQCvAQkAbwAJAG8BCQDvAAkA7wEJAB8ACQAfAQkAnwAJAJ8BCQBfAAkAXwEJAN8ACQDfAQkAPwAJAD8BCQC/AAkA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SXMgYSBkaXJlY3RvcnkAVGV4dCBmaWxlIGJ1c3kARXhlYyBmb3JtYXQgZXJyb3IASW52YWxpZCBhcmd1bWVudABBcmd1bWVudCBsaXN0IHRvbyBsb25nAFN5bWJvbGljIGxpbmsgbG9vcABGaWxlbmFtZSB0b28gbG9uZwBUb28gbWFueSBvcGVuIGZpbGVzIGluIHN5c3RlbQBObyBmaWxlIGRlc2NyaXB0b3JzIGF2YWlsYWJsZQBCYWQgZmlsZSBkZXNjcmlwdG9yAE5vIGNoaWxkIHByb2Nlc3MAQmFkIGFkZHJlc3MARmlsZSB0b28gbGFyZ2UAVG9vIG1hbnkgbGlua3MATm8gbG9ja3MgYXZhaWxhYmxlAFJlc291cmNlIGRlYWRsb2NrIHdvdWxkIG9jY3VyAFN0YXRlIG5vdCByZWNvdmVyYWJsZQBQcmV2aW91cyBvd25lciBkaWVkAE9wZXJhdGlvbiBjYW5jZWxlZABGdW5jdGlvbiBub3QgaW1wbGVtZW50ZWQATm8gbWVzc2FnZSBvZiBkZXNpcmVkIHR5cGUASWRlbnRpZmllciByZW1vdmVkAERldmljZSBub3QgYSBzdHJlYW0ATm8gZGF0YSBhdmFpbGFibGUARGV2aWNlIHRpbWVvdXQAT3V0IG9mIHN0cmVhbXMgcmVzb3VyY2VzAExpbmsgaGFzIGJlZW4gc2V2ZXJlZABQcm90b2NvbCBlcnJvcgBCYWQgbWVzc2FnZQBGaWxlIGRlc2NyaXB0b3IgaW4gYmFkIHN0YXRlAE5vdCBhIHNvY2tldABEZXN0aW5hdGlvbiBhZGRyZXNzIHJlcXVpcmVkAE1lc3NhZ2UgdG9vIGxhcmdlAFByb3RvY29sIHdyb25nIHR5cGUgZm9yIHNvY2tldABQcm90b2NvbCBub3QgYXZhaWxhYmxlAFByb3RvY29sIG5vdCBzdXBwb3J0ZWQAU29ja2V0IHR5cGUgbm90IHN1cHBvcnRlZABOb3Qgc3VwcG9ydGVkAFByb3RvY29sIGZhbWlseSBub3Qgc3VwcG9ydGVkAEFkZHJlc3MgZmFtaWx5IG5vdCBzdXBwb3J0ZWQgYnkgcHJvdG9jb2wAQWRkcmVzcyBub3QgYXZhaWxhYmxlAE5ldHdvcmsgaXMgZG93bgBOZXR3b3JrIHVucmVhY2hhYmxlAENvbm5lY3Rpb24gcmVzZXQgYnkgbmV0d29yawBDb25uZWN0aW9uIGFib3J0ZWQATm8gYnVmZmVyIHNwYWNlIGF2YWlsYWJsZQBTb2NrZXQgaXMgY29ubmVjdGVkAFNvY2tldCBub3QgY29ubmVjdGVkAENhbm5vdCBzZW5kIGFmdGVyIHNvY2tldCBzaHV0ZG93bgBPcGVyYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcwBPcGVyYXRpb24gaW4gcHJvZ3Jlc3MAU3RhbGUgZmlsZSBoYW5kbGUAUmVtb3RlIEkvTyBlcnJvcgBRdW90YSBleGNlZWRlZABObyBtZWRpdW0gZm91bmQAV3JvbmcgbWVkaXVtIHR5cGUATm8gZXJyb3IgaW5mb3JtYXRpb24AQcCAAQuFARMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAGwAAABwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAACIAAAAjAAAAgERQADEAAAAyAAAAMwAAADQAAAA1AAAANgAAADcAAAA4AAAAOQAAADIAAAAzAAAANAAAADUAAAA2AAAANwAAADgAQfSCAQsCXEQAQbCDAQsQ/////////////////////w==\";Do(ji)||(ji=x(ji));function oo(Je){try{if(Je==ji&&ae)return new Uint8Array(ae);var ot=Ue(Je);if(ot)return ot;if(T)return T(Je);throw\"sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)\"}catch(St){ns(St)}}function bo(Je,ot){var St,lr,ee;try{ee=oo(Je),lr=new WebAssembly.Module(ee),St=new WebAssembly.Instance(lr,ot)}catch(Oe){var ye=Oe.toString();throw te(\"failed to compile wasm module: \"+ye),(ye.includes(\"imported Memory\")||ye.includes(\"memory import\"))&&te(\"Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time).\"),Oe}return[St,lr]}function RA(){var Je={a:au};function ot(ee,ye){var Oe=ee.exports;r.asm=Oe,Ce=r.asm.g,z(Ce.buffer),$=r.asm.W,dn(r.asm.h),So(\"wasm-instantiate\")}if(li(\"wasm-instantiate\"),r.instantiateWasm)try{var St=r.instantiateWasm(Je,ot);return St}catch(ee){return te(\"Module.instantiateWasm callback failed with error: \"+ee),!1}var lr=bo(ji,Je);return ot(lr[0]),r.asm}function hf(Je){return F.getFloat32(Je,!0)}function hh(Je){return F.getFloat64(Je,!0)}function gh(Je){return F.getInt16(Je,!0)}function ao(Je){return F.getInt32(Je,!0)}function Gn(Je,ot){F.setInt32(Je,ot,!0)}function Ns(Je){for(;Je.length>0;){var ot=Je.shift();if(typeof ot==\"function\"){ot(r);continue}var St=ot.func;typeof St==\"number\"?ot.arg===void 0?$.get(St)():$.get(St)(ot.arg):St(ot.arg===void 0?null:ot.arg)}}function lo(Je,ot){var St=new Date(ao((Je>>2)*4)*1e3);Gn((ot>>2)*4,St.getUTCSeconds()),Gn((ot+4>>2)*4,St.getUTCMinutes()),Gn((ot+8>>2)*4,St.getUTCHours()),Gn((ot+12>>2)*4,St.getUTCDate()),Gn((ot+16>>2)*4,St.getUTCMonth()),Gn((ot+20>>2)*4,St.getUTCFullYear()-1900),Gn((ot+24>>2)*4,St.getUTCDay()),Gn((ot+36>>2)*4,0),Gn((ot+32>>2)*4,0);var lr=Date.UTC(St.getUTCFullYear(),0,1,0,0,0,0),ee=(St.getTime()-lr)/(1e3*60*60*24)|0;return Gn((ot+28>>2)*4,ee),lo.GMTString||(lo.GMTString=tt(\"GMT\")),Gn((ot+40>>2)*4,lo.GMTString),ot}function iu(Je,ot){return lo(Je,ot)}function su(Je,ot,St){Re.copyWithin(Je,ot,ot+St)}function ou(Je){try{return Ce.grow(Je-be.byteLength+65535>>>16),z(Ce.buffer),1}catch{}}function TA(Je){var ot=Re.length;Je=Je>>>0;var St=2147483648;if(Je>St)return!1;for(var lr=1;lr<=4;lr*=2){var ee=ot*(1+.2/lr);ee=Math.min(ee,Je+100663296);var ye=Math.min(St,ke(Math.max(Je,ee),65536)),Oe=ou(ye);if(Oe)return!0}return!1}function FA(Je){ue(Je)}function ua(Je){var ot=Date.now()/1e3|0;return Je&&Gn((Je>>2)*4,ot),ot}function fa(){if(fa.called)return;fa.called=!0;var Je=new Date().getFullYear(),ot=new Date(Je,0,1),St=new Date(Je,6,1),lr=ot.getTimezoneOffset(),ee=St.getTimezoneOffset(),ye=Math.max(lr,ee);Gn((kl()>>2)*4,ye*60),Gn((Bs()>>2)*4,+(lr!=ee));function Oe(pn){var ci=pn.toTimeString().match(/\\(([A-Za-z ]+)\\)$/);return ci?ci[1]:\"GMT\"}var mt=Oe(ot),Et=Oe(St),bt=tt(mt),tr=tt(Et);ee<lr?(Gn((Mi()>>2)*4,bt),Gn((Mi()+4>>2)*4,tr)):(Gn((Mi()>>2)*4,tr),Gn((Mi()+4>>2)*4,bt))}function NA(Je){fa();var ot=Date.UTC(ao((Je+20>>2)*4)+1900,ao((Je+16>>2)*4),ao((Je+12>>2)*4),ao((Je+8>>2)*4),ao((Je+4>>2)*4),ao((Je>>2)*4),0),St=new Date(ot);Gn((Je+24>>2)*4,St.getUTCDay());var lr=Date.UTC(St.getUTCFullYear(),0,1,0,0,0,0),ee=(St.getTime()-lr)/(1e3*60*60*24)|0;return Gn((Je+28>>2)*4,ee),St.getTime()/1e3|0}var gr=typeof atob==\"function\"?atob:function(Je){var ot=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",St=\"\",lr,ee,ye,Oe,mt,Et,bt,tr=0;Je=Je.replace(/[^A-Za-z0-9\\+\\/\\=]/g,\"\");do Oe=ot.indexOf(Je.charAt(tr++)),mt=ot.indexOf(Je.charAt(tr++)),Et=ot.indexOf(Je.charAt(tr++)),bt=ot.indexOf(Je.charAt(tr++)),lr=Oe<<2|mt>>4,ee=(mt&15)<<4|Et>>2,ye=(Et&3)<<6|bt,St=St+String.fromCharCode(lr),Et!==64&&(St=St+String.fromCharCode(ee)),bt!==64&&(St=St+String.fromCharCode(ye));while(tr<Je.length);return St};function Po(Je){if(typeof C==\"boolean\"&&C){var ot;try{ot=Buffer.from(Je,\"base64\")}catch{ot=new Buffer(Je,\"base64\")}return new Uint8Array(ot.buffer,ot.byteOffset,ot.byteLength)}try{for(var St=gr(Je),lr=new Uint8Array(St.length),ee=0;ee<St.length;++ee)lr[ee]=St.charCodeAt(ee);return lr}catch{throw new Error(\"Converting base64 string to bytes failed.\")}}function Ue(Je){if(Do(Je))return Po(Je.slice(so.length))}var au={e:iu,c:su,d:TA,a:FA,b:ua,f:NA},Cr=RA(),gf=r.___wasm_call_ctors=Cr.h,OA=r._zip_ext_count_symlinks=Cr.i,LA=r._zip_file_get_external_attributes=Cr.j,lu=r._zipstruct_statS=Cr.k,cu=r._zipstruct_stat_size=Cr.l,ac=r._zipstruct_stat_mtime=Cr.m,we=r._zipstruct_stat_crc=Cr.n,Nt=r._zipstruct_errorS=Cr.o,lc=r._zipstruct_error_code_zip=Cr.p,Oi=r._zipstruct_stat_comp_size=Cr.q,co=r._zipstruct_stat_comp_method=Cr.r,Tt=r._zip_close=Cr.s,Qn=r._zip_delete=Cr.t,Aa=r._zip_dir_add=Cr.u,Gi=r._zip_discard=Cr.v,Li=r._zip_error_init_with_code=Cr.w,ja=r._zip_get_error=Cr.x,mn=r._zip_file_get_error=Cr.y,Zn=r._zip_error_strerror=Cr.z,uu=r._zip_fclose=Cr.A,dh=r._zip_file_add=Cr.B,Ga=r._free=Cr.C,qa=r._malloc=Cr.D,Wa=r._zip_source_error=Cr.E,$e=r._zip_source_seek=Cr.F,Va=r._zip_file_set_external_attributes=Cr.G,df=r._zip_file_set_mtime=Cr.H,cc=r._zip_fopen_index=Cr.I,vn=r._zip_fread=Cr.J,pa=r._zip_get_name=Cr.K,MA=r._zip_get_num_entries=Cr.L,UA=r._zip_source_read=Cr.M,ha=r._zip_name_locate=Cr.N,xl=r._zip_open_from_source=Cr.O,Mt=r._zip_set_file_compression=Cr.P,Rn=r._zip_source_buffer=Cr.Q,ga=r._zip_source_buffer_create=Cr.R,Ya=r._zip_source_close=Cr.S,is=r._zip_source_free=Cr.T,uc=r._zip_source_keep=Cr.U,fu=r._zip_source_open=Cr.V,fc=r._zip_source_tell=Cr.X,Ka=r._zip_stat_index=Cr.Y,Mi=r.__get_tzname=Cr.Z,Bs=r.__get_daylight=Cr._,kl=r.__get_timezone=Cr.$,mf=r.stackSave=Cr.aa,Ac=r.stackRestore=Cr.ba,Bi=r.stackAlloc=Cr.ca;r.cwrap=ce,r.getValue=Ae;var Tn;on=function Je(){Tn||pc(),Tn||(on=Je)};function pc(Je){if(Je=Je||f,Ir>0||(Ct(),Ir>0))return;function ot(){Tn||(Tn=!0,r.calledRun=!0,!Ee&&(qt(),s(r),r.onRuntimeInitialized&&r.onRuntimeInitialized(),ir()))}r.setStatus?(r.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){r.setStatus(\"\")},1),ot()},1)):ot()}if(r.run=pc,r.preInit)for(typeof r.preInit==\"function\"&&(r.preInit=[r.preInit]);r.preInit.length>0;)r.preInit.pop()();return pc(),t}}();typeof CR==\"object\"&&typeof Aj==\"object\"?Aj.exports=fj:typeof define==\"function\"&&define.amd?define([],function(){return fj}):typeof CR==\"object\"&&(CR.createModule=fj)});var _p,RAe,TAe,FAe=Ze(()=>{_p=[\"number\",\"number\"],RAe=(X=>(X[X.ZIP_ER_OK=0]=\"ZIP_ER_OK\",X[X.ZIP_ER_MULTIDISK=1]=\"ZIP_ER_MULTIDISK\",X[X.ZIP_ER_RENAME=2]=\"ZIP_ER_RENAME\",X[X.ZIP_ER_CLOSE=3]=\"ZIP_ER_CLOSE\",X[X.ZIP_ER_SEEK=4]=\"ZIP_ER_SEEK\",X[X.ZIP_ER_READ=5]=\"ZIP_ER_READ\",X[X.ZIP_ER_WRITE=6]=\"ZIP_ER_WRITE\",X[X.ZIP_ER_CRC=7]=\"ZIP_ER_CRC\",X[X.ZIP_ER_ZIPCLOSED=8]=\"ZIP_ER_ZIPCLOSED\",X[X.ZIP_ER_NOENT=9]=\"ZIP_ER_NOENT\",X[X.ZIP_ER_EXISTS=10]=\"ZIP_ER_EXISTS\",X[X.ZIP_ER_OPEN=11]=\"ZIP_ER_OPEN\",X[X.ZIP_ER_TMPOPEN=12]=\"ZIP_ER_TMPOPEN\",X[X.ZIP_ER_ZLIB=13]=\"ZIP_ER_ZLIB\",X[X.ZIP_ER_MEMORY=14]=\"ZIP_ER_MEMORY\",X[X.ZIP_ER_CHANGED=15]=\"ZIP_ER_CHANGED\",X[X.ZIP_ER_COMPNOTSUPP=16]=\"ZIP_ER_COMPNOTSUPP\",X[X.ZIP_ER_EOF=17]=\"ZIP_ER_EOF\",X[X.ZIP_ER_INVAL=18]=\"ZIP_ER_INVAL\",X[X.ZIP_ER_NOZIP=19]=\"ZIP_ER_NOZIP\",X[X.ZIP_ER_INTERNAL=20]=\"ZIP_ER_INTERNAL\",X[X.ZIP_ER_INCONS=21]=\"ZIP_ER_INCONS\",X[X.ZIP_ER_REMOVE=22]=\"ZIP_ER_REMOVE\",X[X.ZIP_ER_DELETED=23]=\"ZIP_ER_DELETED\",X[X.ZIP_ER_ENCRNOTSUPP=24]=\"ZIP_ER_ENCRNOTSUPP\",X[X.ZIP_ER_RDONLY=25]=\"ZIP_ER_RDONLY\",X[X.ZIP_ER_NOPASSWD=26]=\"ZIP_ER_NOPASSWD\",X[X.ZIP_ER_WRONGPASSWD=27]=\"ZIP_ER_WRONGPASSWD\",X[X.ZIP_ER_OPNOTSUPP=28]=\"ZIP_ER_OPNOTSUPP\",X[X.ZIP_ER_INUSE=29]=\"ZIP_ER_INUSE\",X[X.ZIP_ER_TELL=30]=\"ZIP_ER_TELL\",X[X.ZIP_ER_COMPRESSED_DATA=31]=\"ZIP_ER_COMPRESSED_DATA\",X))(RAe||{}),TAe=e=>({get HEAPU8(){return e.HEAPU8},errors:RAe,SEEK_SET:0,SEEK_CUR:1,SEEK_END:2,ZIP_CHECKCONS:4,ZIP_EXCL:2,ZIP_RDONLY:16,ZIP_FL_OVERWRITE:8192,ZIP_FL_COMPRESSED:4,ZIP_OPSYS_DOS:0,ZIP_OPSYS_AMIGA:1,ZIP_OPSYS_OPENVMS:2,ZIP_OPSYS_UNIX:3,ZIP_OPSYS_VM_CMS:4,ZIP_OPSYS_ATARI_ST:5,ZIP_OPSYS_OS_2:6,ZIP_OPSYS_MACINTOSH:7,ZIP_OPSYS_Z_SYSTEM:8,ZIP_OPSYS_CPM:9,ZIP_OPSYS_WINDOWS_NTFS:10,ZIP_OPSYS_MVS:11,ZIP_OPSYS_VSE:12,ZIP_OPSYS_ACORN_RISC:13,ZIP_OPSYS_VFAT:14,ZIP_OPSYS_ALTERNATE_MVS:15,ZIP_OPSYS_BEOS:16,ZIP_OPSYS_TANDEM:17,ZIP_OPSYS_OS_400:18,ZIP_OPSYS_OS_X:19,ZIP_CM_DEFAULT:-1,ZIP_CM_STORE:0,ZIP_CM_DEFLATE:8,uint08S:e._malloc(1),uint32S:e._malloc(4),malloc:e._malloc,free:e._free,getValue:e.getValue,openFromSource:e.cwrap(\"zip_open_from_source\",\"number\",[\"number\",\"number\",\"number\"]),close:e.cwrap(\"zip_close\",\"number\",[\"number\"]),discard:e.cwrap(\"zip_discard\",null,[\"number\"]),getError:e.cwrap(\"zip_get_error\",\"number\",[\"number\"]),getName:e.cwrap(\"zip_get_name\",\"string\",[\"number\",\"number\",\"number\"]),getNumEntries:e.cwrap(\"zip_get_num_entries\",\"number\",[\"number\",\"number\"]),delete:e.cwrap(\"zip_delete\",\"number\",[\"number\",\"number\"]),statIndex:e.cwrap(\"zip_stat_index\",\"number\",[\"number\",..._p,\"number\",\"number\"]),fopenIndex:e.cwrap(\"zip_fopen_index\",\"number\",[\"number\",..._p,\"number\"]),fread:e.cwrap(\"zip_fread\",\"number\",[\"number\",\"number\",\"number\",\"number\"]),fclose:e.cwrap(\"zip_fclose\",\"number\",[\"number\"]),dir:{add:e.cwrap(\"zip_dir_add\",\"number\",[\"number\",\"string\"])},file:{add:e.cwrap(\"zip_file_add\",\"number\",[\"number\",\"string\",\"number\",\"number\"]),getError:e.cwrap(\"zip_file_get_error\",\"number\",[\"number\"]),getExternalAttributes:e.cwrap(\"zip_file_get_external_attributes\",\"number\",[\"number\",..._p,\"number\",\"number\",\"number\"]),setExternalAttributes:e.cwrap(\"zip_file_set_external_attributes\",\"number\",[\"number\",..._p,\"number\",\"number\",\"number\"]),setMtime:e.cwrap(\"zip_file_set_mtime\",\"number\",[\"number\",..._p,\"number\",\"number\"]),setCompression:e.cwrap(\"zip_set_file_compression\",\"number\",[\"number\",..._p,\"number\",\"number\"])},ext:{countSymlinks:e.cwrap(\"zip_ext_count_symlinks\",\"number\",[\"number\"])},error:{initWithCode:e.cwrap(\"zip_error_init_with_code\",null,[\"number\",\"number\"]),strerror:e.cwrap(\"zip_error_strerror\",\"string\",[\"number\"])},name:{locate:e.cwrap(\"zip_name_locate\",\"number\",[\"number\",\"string\",\"number\"])},source:{fromUnattachedBuffer:e.cwrap(\"zip_source_buffer_create\",\"number\",[\"number\",..._p,\"number\",\"number\"]),fromBuffer:e.cwrap(\"zip_source_buffer\",\"number\",[\"number\",\"number\",..._p,\"number\"]),free:e.cwrap(\"zip_source_free\",null,[\"number\"]),keep:e.cwrap(\"zip_source_keep\",null,[\"number\"]),open:e.cwrap(\"zip_source_open\",\"number\",[\"number\"]),close:e.cwrap(\"zip_source_close\",\"number\",[\"number\"]),seek:e.cwrap(\"zip_source_seek\",\"number\",[\"number\",..._p,\"number\"]),tell:e.cwrap(\"zip_source_tell\",\"number\",[\"number\"]),read:e.cwrap(\"zip_source_read\",\"number\",[\"number\",\"number\",\"number\"]),error:e.cwrap(\"zip_source_error\",\"number\",[\"number\"])},struct:{statS:e.cwrap(\"zipstruct_statS\",\"number\",[]),statSize:e.cwrap(\"zipstruct_stat_size\",\"number\",[\"number\"]),statCompSize:e.cwrap(\"zipstruct_stat_comp_size\",\"number\",[\"number\"]),statCompMethod:e.cwrap(\"zipstruct_stat_comp_method\",\"number\",[\"number\"]),statMtime:e.cwrap(\"zipstruct_stat_mtime\",\"number\",[\"number\"]),statCrc:e.cwrap(\"zipstruct_stat_crc\",\"number\",[\"number\"]),errorS:e.cwrap(\"zipstruct_errorS\",\"number\",[]),errorCodeZip:e.cwrap(\"zipstruct_error_code_zip\",\"number\",[\"number\"])}})});function pj(e,t){let r=e.indexOf(t);if(r<=0)return null;let s=r;for(;r>=0&&(s=r+t.length,e[s]!==K.sep);){if(e[r-1]===K.sep)return null;r=e.indexOf(t,s)}return e.length>s&&e[s]!==K.sep?null:e.slice(0,s)}var tA,NAe=Ze(()=>{Dt();Dt();rA();tA=class e extends Xh{static async openPromise(t,r){let s=new e(r);try{return await t(s)}finally{s.saveAndClose()}}constructor(t={}){let r=t.fileExtensions,s=t.readOnlyArchives,a=typeof r>\"u\"?f=>pj(f,\".zip\"):f=>{for(let p of r){let h=pj(f,p);if(h)return h}return null},n=(f,p)=>new ps(p,{baseFs:f,readOnly:s,stats:f.statSync(p),customZipImplementation:t.customZipImplementation}),c=async(f,p)=>{let h={baseFs:f,readOnly:s,stats:await f.statPromise(p),customZipImplementation:t.customZipImplementation};return()=>new ps(p,h)};super({...t,factorySync:n,factoryPromise:c,getMountPoint:a})}}});var hj,DI,gj=Ze(()=>{uj();hj=class extends Error{constructor(t,r){super(t),this.name=\"Libzip Error\",this.code=r}},DI=class{constructor(t){this.filesShouldBeCached=!0;let r=\"buffer\"in t?t.buffer:t.baseFs.readFileSync(t.path);this.libzip=tv();let s=this.libzip.malloc(4);try{let c=0;t.readOnly&&(c|=this.libzip.ZIP_RDONLY);let f=this.allocateUnattachedSource(r);try{this.zip=this.libzip.openFromSource(f,c,s),this.lzSource=f}catch(p){throw this.libzip.source.free(f),p}if(this.zip===0){let p=this.libzip.struct.errorS();throw this.libzip.error.initWithCode(p,this.libzip.getValue(s,\"i32\")),this.makeLibzipError(p)}}finally{this.libzip.free(s)}let a=this.libzip.getNumEntries(this.zip,0),n=new Array(a);for(let c=0;c<a;++c)n[c]=this.libzip.getName(this.zip,c,0);if(this.listings=n,this.symlinkCount=this.libzip.ext.countSymlinks(this.zip),this.symlinkCount===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}getSymlinkCount(){return this.symlinkCount}getListings(){return this.listings}stat(t){let r=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,t,0,0,r)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let a=this.libzip.struct.statSize(r)>>>0,n=this.libzip.struct.statMtime(r)>>>0,c=this.libzip.struct.statCrc(r)>>>0;return{size:a,mtime:n,crc:c}}makeLibzipError(t){let r=this.libzip.struct.errorCodeZip(t),s=this.libzip.error.strerror(t),a=new hj(s,this.libzip.errors[r]);if(r===this.libzip.errors.ZIP_ER_CHANGED)throw new Error(`Assertion failed: Unexpected libzip error: ${a.message}`);return a}setFileSource(t,r,s){let a=this.allocateSource(s);try{let n=this.libzip.file.add(this.zip,t,a,this.libzip.ZIP_FL_OVERWRITE);if(n===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(r!==null&&this.libzip.file.setCompression(this.zip,n,0,r[0],r[1])===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return n}catch(n){throw this.libzip.source.free(a),n}}setMtime(t,r){if(this.libzip.file.setMtime(this.zip,t,0,r,0)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}getExternalAttributes(t){if(this.libzip.file.getExternalAttributes(this.zip,t,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let s=this.libzip.getValue(this.libzip.uint08S,\"i8\")>>>0,a=this.libzip.getValue(this.libzip.uint32S,\"i32\")>>>0;return[s,a]}setExternalAttributes(t,r,s){if(this.libzip.file.setExternalAttributes(this.zip,t,0,0,r,s)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}locate(t){return this.libzip.name.locate(this.zip,t,0)}getFileSource(t){let r=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,t,0,0,r)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let a=this.libzip.struct.statCompSize(r),n=this.libzip.struct.statCompMethod(r),c=this.libzip.malloc(a);try{let f=this.libzip.fopenIndex(this.zip,t,0,this.libzip.ZIP_FL_COMPRESSED);if(f===0)throw this.makeLibzipError(this.libzip.getError(this.zip));try{let p=this.libzip.fread(f,c,a,0);if(p===-1)throw this.makeLibzipError(this.libzip.file.getError(f));if(p<a)throw new Error(\"Incomplete read\");if(p>a)throw new Error(\"Overread\");let h=this.libzip.HEAPU8.subarray(c,c+a);return{data:Buffer.from(h),compressionMethod:n}}finally{this.libzip.fclose(f)}}finally{this.libzip.free(c)}}deleteEntry(t){if(this.libzip.delete(this.zip,t)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}addDirectory(t){let r=this.libzip.dir.add(this.zip,t);if(r===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return r}getBufferAndClose(){try{if(this.libzip.source.keep(this.lzSource),this.libzip.close(this.zip)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(this.libzip.source.open(this.lzSource)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(this.libzip.source.seek(this.lzSource,0,0,this.libzip.SEEK_END)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));let t=this.libzip.source.tell(this.lzSource);if(t===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(this.libzip.source.seek(this.lzSource,0,0,this.libzip.SEEK_SET)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));let r=this.libzip.malloc(t);if(!r)throw new Error(\"Couldn't allocate enough memory\");try{let s=this.libzip.source.read(this.lzSource,r,t);if(s===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(s<t)throw new Error(\"Incomplete read\");if(s>t)throw new Error(\"Overread\");let a=Buffer.from(this.libzip.HEAPU8.subarray(r,r+t));return process.env.YARN_IS_TEST_ENV&&process.env.YARN_ZIP_DATA_EPILOGUE&&(a=Buffer.concat([a,Buffer.from(process.env.YARN_ZIP_DATA_EPILOGUE)])),a}finally{this.libzip.free(r)}}finally{this.libzip.source.close(this.lzSource),this.libzip.source.free(this.lzSource)}}allocateBuffer(t){Buffer.isBuffer(t)||(t=Buffer.from(t));let r=this.libzip.malloc(t.byteLength);if(!r)throw new Error(\"Couldn't allocate enough memory\");return new Uint8Array(this.libzip.HEAPU8.buffer,r,t.byteLength).set(t),{buffer:r,byteLength:t.byteLength}}allocateUnattachedSource(t){let r=this.libzip.struct.errorS(),{buffer:s,byteLength:a}=this.allocateBuffer(t),n=this.libzip.source.fromUnattachedBuffer(s,a,0,1,r);if(n===0)throw this.libzip.free(r),this.makeLibzipError(r);return n}allocateSource(t){let{buffer:r,byteLength:s}=this.allocateBuffer(t),a=this.libzip.source.fromBuffer(this.zip,r,s,0,1);if(a===0)throw this.libzip.free(r),this.makeLibzipError(this.libzip.getError(this.zip));return a}discard(){this.libzip.discard(this.zip)}}});function Rtt(e){if(typeof e==\"string\"&&String(+e)===e)return+e;if(typeof e==\"number\"&&Number.isFinite(e))return e<0?Date.now()/1e3:e;if(OAe.types.isDate(e))return e.getTime()/1e3;throw new Error(\"Invalid time\")}function wR(){return Buffer.from([80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])}var Ra,dj,OAe,mj,om,yj,Ej,LAe,ps,BR=Ze(()=>{Dt();Dt();Dt();Dt();Dt();Dt();Ra=Ie(\"fs\"),dj=Ie(\"stream\"),OAe=Ie(\"util\"),mj=et(Ie(\"zlib\"));gj();om=3,yj=0,Ej=8,LAe=\"mixed\";ps=class extends Hf{constructor(r,s={}){super();this.listings=new Map;this.entries=new Map;this.fileSources=new Map;this.fds=new Map;this.nextFd=0;this.ready=!1;this.readOnly=!1;s.readOnly&&(this.readOnly=!0);let a=s;this.level=typeof a.level<\"u\"?a.level:LAe;let n=s.customZipImplementation??DI;if(typeof r==\"string\"){let{baseFs:f=new Yn}=a;this.baseFs=f,this.path=r}else this.path=null,this.baseFs=null;if(s.stats)this.stats=s.stats;else if(typeof r==\"string\")try{this.stats=this.baseFs.statSync(r)}catch(f){if(f.code===\"ENOENT\"&&a.create)this.stats=sl.makeDefaultStats();else throw f}else this.stats=sl.makeDefaultStats();typeof r==\"string\"?s.create?this.zipImpl=new n({buffer:wR(),readOnly:this.readOnly}):this.zipImpl=new n({path:r,baseFs:this.baseFs,readOnly:this.readOnly,size:this.stats.size}):this.zipImpl=new n({buffer:r??wR(),readOnly:this.readOnly}),this.listings.set(vt.root,new Set);let c=this.zipImpl.getListings();for(let f=0;f<c.length;f++){let p=c[f];if(K.isAbsolute(p))continue;let h=K.resolve(vt.root,p);this.registerEntry(h,f),p.endsWith(\"/\")&&this.registerListing(h)}this.symlinkCount=this.zipImpl.getSymlinkCount(),this.ready=!0}getExtractHint(r){for(let s of this.entries.keys()){let a=this.pathUtils.extname(s);if(r.relevantExtensions.has(a))return!0}return!1}getAllFiles(){return Array.from(this.entries.keys())}getRealPath(){if(!this.path)throw new Error(\"ZipFS don't have real paths when loaded from a buffer\");return this.path}prepareClose(){if(!this.ready)throw or.EBUSY(\"archive closed, close\");dd(this)}getBufferAndClose(){if(this.prepareClose(),this.entries.size===0)return this.discardAndClose(),wR();try{return this.zipImpl.getBufferAndClose()}finally{this.ready=!1}}discardAndClose(){this.prepareClose(),this.zipImpl.discard(),this.ready=!1}saveAndClose(){if(!this.path||!this.baseFs)throw new Error(\"ZipFS cannot be saved and must be discarded when loaded from a buffer\");if(this.readOnly){this.discardAndClose();return}let r=this.baseFs.existsSync(this.path)||this.stats.mode===sl.DEFAULT_MODE?void 0:this.stats.mode;this.baseFs.writeFileSync(this.path,this.getBufferAndClose(),{mode:r}),this.ready=!1}resolve(r){return K.resolve(vt.root,r)}async openPromise(r,s,a){return this.openSync(r,s,a)}openSync(r,s,a){let n=this.nextFd++;return this.fds.set(n,{cursor:0,p:r}),n}hasOpenFileHandles(){return!!this.fds.size}async opendirPromise(r,s){return this.opendirSync(r,s)}opendirSync(r,s={}){let a=this.resolveFilename(`opendir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw or.ENOENT(`opendir '${r}'`);let n=this.listings.get(a);if(!n)throw or.ENOTDIR(`opendir '${r}'`);let c=[...n],f=this.openSync(a,\"r\");return ex(this,a,c,{onClose:()=>{this.closeSync(f)}})}async readPromise(r,s,a,n,c){return this.readSync(r,s,a,n,c)}readSync(r,s,a=0,n=s.byteLength,c=-1){let f=this.fds.get(r);if(typeof f>\"u\")throw or.EBADF(\"read\");let p=c===-1||c===null?f.cursor:c,h=this.readFileSync(f.p);h.copy(s,a,p,p+n);let E=Math.max(0,Math.min(h.length-p,n));return(c===-1||c===null)&&(f.cursor+=E),E}async writePromise(r,s,a,n,c){return typeof s==\"string\"?this.writeSync(r,s,c):this.writeSync(r,s,a,n,c)}writeSync(r,s,a,n,c){throw typeof this.fds.get(r)>\"u\"?or.EBADF(\"read\"):new Error(\"Unimplemented\")}async closePromise(r){return this.closeSync(r)}closeSync(r){if(typeof this.fds.get(r)>\"u\")throw or.EBADF(\"read\");this.fds.delete(r)}createReadStream(r,{encoding:s}={}){if(r===null)throw new Error(\"Unimplemented\");let a=this.openSync(r,\"r\"),n=Object.assign(new dj.PassThrough({emitClose:!0,autoDestroy:!0,destroy:(f,p)=>{clearImmediate(c),this.closeSync(a),p(f)}}),{close(){n.destroy()},bytesRead:0,path:r,pending:!1}),c=setImmediate(async()=>{try{let f=await this.readFilePromise(r,s);n.bytesRead=f.length,n.end(f)}catch(f){n.destroy(f)}});return n}createWriteStream(r,{encoding:s}={}){if(this.readOnly)throw or.EROFS(`open '${r}'`);if(r===null)throw new Error(\"Unimplemented\");let a=[],n=this.openSync(r,\"w\"),c=Object.assign(new dj.PassThrough({autoDestroy:!0,emitClose:!0,destroy:(f,p)=>{try{f?p(f):(this.writeFileSync(r,Buffer.concat(a),s),p(null))}catch(h){p(h)}finally{this.closeSync(n)}}}),{close(){c.destroy()},bytesWritten:0,path:r,pending:!1});return c.on(\"data\",f=>{let p=Buffer.from(f);c.bytesWritten+=p.length,a.push(p)}),c}async realpathPromise(r){return this.realpathSync(r)}realpathSync(r){let s=this.resolveFilename(`lstat '${r}'`,r);if(!this.entries.has(s)&&!this.listings.has(s))throw or.ENOENT(`lstat '${r}'`);return s}async existsPromise(r){return this.existsSync(r)}existsSync(r){if(!this.ready)throw or.EBUSY(`archive closed, existsSync '${r}'`);if(this.symlinkCount===0){let a=K.resolve(vt.root,r);return this.entries.has(a)||this.listings.has(a)}let s;try{s=this.resolveFilename(`stat '${r}'`,r,void 0,!1)}catch{return!1}return s===void 0?!1:this.entries.has(s)||this.listings.has(s)}async accessPromise(r,s){return this.accessSync(r,s)}accessSync(r,s=Ra.constants.F_OK){let a=this.resolveFilename(`access '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw or.ENOENT(`access '${r}'`);if(this.readOnly&&s&Ra.constants.W_OK)throw or.EROFS(`access '${r}'`)}async statPromise(r,s={bigint:!1}){return s.bigint?this.statSync(r,{bigint:!0}):this.statSync(r)}statSync(r,s={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`stat '${r}'`,r,void 0,s.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(s.throwIfNoEntry===!1)return;throw or.ENOENT(`stat '${r}'`)}if(r[r.length-1]===\"/\"&&!this.listings.has(a))throw or.ENOTDIR(`stat '${r}'`);return this.statImpl(`stat '${r}'`,a,s)}}async fstatPromise(r,s){return this.fstatSync(r,s)}fstatSync(r,s){let a=this.fds.get(r);if(typeof a>\"u\")throw or.EBADF(\"fstatSync\");let{p:n}=a,c=this.resolveFilename(`stat '${n}'`,n);if(!this.entries.has(c)&&!this.listings.has(c))throw or.ENOENT(`stat '${n}'`);if(n[n.length-1]===\"/\"&&!this.listings.has(c))throw or.ENOTDIR(`stat '${n}'`);return this.statImpl(`fstat '${n}'`,c,s)}async lstatPromise(r,s={bigint:!1}){return s.bigint?this.lstatSync(r,{bigint:!0}):this.lstatSync(r)}lstatSync(r,s={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`lstat '${r}'`,r,!1,s.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(s.throwIfNoEntry===!1)return;throw or.ENOENT(`lstat '${r}'`)}if(r[r.length-1]===\"/\"&&!this.listings.has(a))throw or.ENOTDIR(`lstat '${r}'`);return this.statImpl(`lstat '${r}'`,a,s)}}statImpl(r,s,a={}){let n=this.entries.get(s);if(typeof n<\"u\"){let c=this.zipImpl.stat(n),f=c.crc,p=c.size,h=c.mtime*1e3,E=this.stats.uid,C=this.stats.gid,S=512,x=Math.ceil(c.size/S),I=h,T=h,O=h,U=new Date(I),Y=new Date(T),te=new Date(O),ie=new Date(h),ue=this.listings.has(s)?Ra.constants.S_IFDIR:this.isSymbolicLink(n)?Ra.constants.S_IFLNK:Ra.constants.S_IFREG,ae=ue===Ra.constants.S_IFDIR?493:420,de=ue|this.getUnixMode(n,ae)&511,Ae=Object.assign(new sl.StatEntry,{uid:E,gid:C,size:p,blksize:S,blocks:x,atime:U,birthtime:Y,ctime:te,mtime:ie,atimeMs:I,birthtimeMs:T,ctimeMs:O,mtimeMs:h,mode:de,crc:f});return a.bigint===!0?sl.convertToBigIntStats(Ae):Ae}if(this.listings.has(s)){let c=this.stats.uid,f=this.stats.gid,p=0,h=512,E=0,C=this.stats.mtimeMs,S=this.stats.mtimeMs,x=this.stats.mtimeMs,I=this.stats.mtimeMs,T=new Date(C),O=new Date(S),U=new Date(x),Y=new Date(I),te=Ra.constants.S_IFDIR|493,ue=Object.assign(new sl.StatEntry,{uid:c,gid:f,size:p,blksize:h,blocks:E,atime:T,birthtime:O,ctime:U,mtime:Y,atimeMs:C,birthtimeMs:S,ctimeMs:x,mtimeMs:I,mode:te,crc:0});return a.bigint===!0?sl.convertToBigIntStats(ue):ue}throw new Error(\"Unreachable\")}getUnixMode(r,s){let[a,n]=this.zipImpl.getExternalAttributes(r);return a!==om?s:n>>>16}registerListing(r){let s=this.listings.get(r);if(s)return s;this.registerListing(K.dirname(r)).add(K.basename(r));let n=new Set;return this.listings.set(r,n),n}registerEntry(r,s){this.registerListing(K.dirname(r)).add(K.basename(r)),this.entries.set(r,s)}unregisterListing(r){this.listings.delete(r),this.listings.get(K.dirname(r))?.delete(K.basename(r))}unregisterEntry(r){this.unregisterListing(r);let s=this.entries.get(r);this.entries.delete(r),!(typeof s>\"u\")&&(this.fileSources.delete(s),this.isSymbolicLink(s)&&this.symlinkCount--)}deleteEntry(r,s){this.unregisterEntry(r),this.zipImpl.deleteEntry(s)}resolveFilename(r,s,a=!0,n=!0){if(!this.ready)throw or.EBUSY(`archive closed, ${r}`);let c=K.resolve(vt.root,s);if(c===\"/\")return vt.root;let f=this.entries.get(c);if(a&&f!==void 0)if(this.symlinkCount!==0&&this.isSymbolicLink(f)){let p=this.getFileSource(f).toString();return this.resolveFilename(r,K.resolve(K.dirname(c),p),!0,n)}else return c;for(;;){let p=this.resolveFilename(r,K.dirname(c),!0,n);if(p===void 0)return p;let h=this.listings.has(p),E=this.entries.has(p);if(!h&&!E){if(n===!1)return;throw or.ENOENT(r)}if(!h)throw or.ENOTDIR(r);if(c=K.resolve(p,K.basename(c)),!a||this.symlinkCount===0)break;let C=this.zipImpl.locate(c.slice(1));if(C===-1)break;if(this.isSymbolicLink(C)){let S=this.getFileSource(C).toString();c=K.resolve(K.dirname(c),S)}else break}return c}setFileSource(r,s){let a=Buffer.isBuffer(s)?s:Buffer.from(s),n=K.relative(vt.root,r),c=null;this.level!==\"mixed\"&&(c=[this.level===0?yj:Ej,this.level]);let f=this.zipImpl.setFileSource(n,c,a);return this.fileSources.set(f,a),f}isSymbolicLink(r){if(this.symlinkCount===0)return!1;let[s,a]=this.zipImpl.getExternalAttributes(r);return s!==om?!1:(a>>>16&Ra.constants.S_IFMT)===Ra.constants.S_IFLNK}getFileSource(r,s={asyncDecompress:!1}){let a=this.fileSources.get(r);if(typeof a<\"u\")return a;let{data:n,compressionMethod:c}=this.zipImpl.getFileSource(r);if(c===yj)return this.zipImpl.filesShouldBeCached&&this.fileSources.set(r,n),n;if(c===Ej){if(s.asyncDecompress)return new Promise((f,p)=>{mj.default.inflateRaw(n,(h,E)=>{h?p(h):(this.zipImpl.filesShouldBeCached&&this.fileSources.set(r,E),f(E))})});{let f=mj.default.inflateRawSync(n);return this.zipImpl.filesShouldBeCached&&this.fileSources.set(r,f),f}}else throw new Error(`Unsupported compression method: ${c}`)}async fchmodPromise(r,s){return this.chmodPromise(this.fdToPath(r,\"fchmod\"),s)}fchmodSync(r,s){return this.chmodSync(this.fdToPath(r,\"fchmodSync\"),s)}async chmodPromise(r,s){return this.chmodSync(r,s)}chmodSync(r,s){if(this.readOnly)throw or.EROFS(`chmod '${r}'`);s&=493;let a=this.resolveFilename(`chmod '${r}'`,r,!1),n=this.entries.get(a);if(typeof n>\"u\")throw new Error(`Assertion failed: The entry should have been registered (${a})`);let f=this.getUnixMode(n,Ra.constants.S_IFREG|0)&-512|s;this.zipImpl.setExternalAttributes(n,om,f<<16)}async fchownPromise(r,s,a){return this.chownPromise(this.fdToPath(r,\"fchown\"),s,a)}fchownSync(r,s,a){return this.chownSync(this.fdToPath(r,\"fchownSync\"),s,a)}async chownPromise(r,s,a){return this.chownSync(r,s,a)}chownSync(r,s,a){throw new Error(\"Unimplemented\")}async renamePromise(r,s){return this.renameSync(r,s)}renameSync(r,s){throw new Error(\"Unimplemented\")}async copyFilePromise(r,s,a){let{indexSource:n,indexDest:c,resolvedDestP:f}=this.prepareCopyFile(r,s,a),p=await this.getFileSource(n,{asyncDecompress:!0}),h=this.setFileSource(f,p);h!==c&&this.registerEntry(f,h)}copyFileSync(r,s,a=0){let{indexSource:n,indexDest:c,resolvedDestP:f}=this.prepareCopyFile(r,s,a),p=this.getFileSource(n),h=this.setFileSource(f,p);h!==c&&this.registerEntry(f,h)}prepareCopyFile(r,s,a=0){if(this.readOnly)throw or.EROFS(`copyfile '${r} -> '${s}'`);if(a&Ra.constants.COPYFILE_FICLONE_FORCE)throw or.ENOSYS(\"unsupported clone operation\",`copyfile '${r}' -> ${s}'`);let n=this.resolveFilename(`copyfile '${r} -> ${s}'`,r),c=this.entries.get(n);if(typeof c>\"u\")throw or.EINVAL(`copyfile '${r}' -> '${s}'`);let f=this.resolveFilename(`copyfile '${r}' -> ${s}'`,s),p=this.entries.get(f);if(a&(Ra.constants.COPYFILE_EXCL|Ra.constants.COPYFILE_FICLONE_FORCE)&&typeof p<\"u\")throw or.EEXIST(`copyfile '${r}' -> '${s}'`);return{indexSource:c,resolvedDestP:f,indexDest:p}}async appendFilePromise(r,s,a){if(this.readOnly)throw or.EROFS(`open '${r}'`);return typeof a>\"u\"?a={flag:\"a\"}:typeof a==\"string\"?a={flag:\"a\",encoding:a}:typeof a.flag>\"u\"&&(a={flag:\"a\",...a}),this.writeFilePromise(r,s,a)}appendFileSync(r,s,a={}){if(this.readOnly)throw or.EROFS(`open '${r}'`);return typeof a>\"u\"?a={flag:\"a\"}:typeof a==\"string\"?a={flag:\"a\",encoding:a}:typeof a.flag>\"u\"&&(a={flag:\"a\",...a}),this.writeFileSync(r,s,a)}fdToPath(r,s){let a=this.fds.get(r)?.p;if(typeof a>\"u\")throw or.EBADF(s);return a}async writeFilePromise(r,s,a){let{encoding:n,mode:c,index:f,resolvedP:p}=this.prepareWriteFile(r,a);f!==void 0&&typeof a==\"object\"&&a.flag&&a.flag.includes(\"a\")&&(s=Buffer.concat([await this.getFileSource(f,{asyncDecompress:!0}),Buffer.from(s)])),n!==null&&(s=s.toString(n));let h=this.setFileSource(p,s);h!==f&&this.registerEntry(p,h),c!==null&&await this.chmodPromise(p,c)}writeFileSync(r,s,a){let{encoding:n,mode:c,index:f,resolvedP:p}=this.prepareWriteFile(r,a);f!==void 0&&typeof a==\"object\"&&a.flag&&a.flag.includes(\"a\")&&(s=Buffer.concat([this.getFileSource(f),Buffer.from(s)])),n!==null&&(s=s.toString(n));let h=this.setFileSource(p,s);h!==f&&this.registerEntry(p,h),c!==null&&this.chmodSync(p,c)}prepareWriteFile(r,s){if(typeof r==\"number\"&&(r=this.fdToPath(r,\"read\")),this.readOnly)throw or.EROFS(`open '${r}'`);let a=this.resolveFilename(`open '${r}'`,r);if(this.listings.has(a))throw or.EISDIR(`open '${r}'`);let n=null,c=null;typeof s==\"string\"?n=s:typeof s==\"object\"&&({encoding:n=null,mode:c=null}=s);let f=this.entries.get(a);return{encoding:n,mode:c,resolvedP:a,index:f}}async unlinkPromise(r){return this.unlinkSync(r)}unlinkSync(r){if(this.readOnly)throw or.EROFS(`unlink '${r}'`);let s=this.resolveFilename(`unlink '${r}'`,r);if(this.listings.has(s))throw or.EISDIR(`unlink '${r}'`);let a=this.entries.get(s);if(typeof a>\"u\")throw or.EINVAL(`unlink '${r}'`);this.deleteEntry(s,a)}async utimesPromise(r,s,a){return this.utimesSync(r,s,a)}utimesSync(r,s,a){if(this.readOnly)throw or.EROFS(`utimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r);this.utimesImpl(n,a)}async lutimesPromise(r,s,a){return this.lutimesSync(r,s,a)}lutimesSync(r,s,a){if(this.readOnly)throw or.EROFS(`lutimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r,!1);this.utimesImpl(n,a)}utimesImpl(r,s){this.listings.has(r)&&(this.entries.has(r)||this.hydrateDirectory(r));let a=this.entries.get(r);if(a===void 0)throw new Error(\"Unreachable\");this.zipImpl.setMtime(a,Rtt(s))}async mkdirPromise(r,s){return this.mkdirSync(r,s)}mkdirSync(r,{mode:s=493,recursive:a=!1}={}){if(a)return this.mkdirpSync(r,{chmod:s});if(this.readOnly)throw or.EROFS(`mkdir '${r}'`);let n=this.resolveFilename(`mkdir '${r}'`,r);if(this.entries.has(n)||this.listings.has(n))throw or.EEXIST(`mkdir '${r}'`);this.hydrateDirectory(n),this.chmodSync(n,s)}async rmdirPromise(r,s){return this.rmdirSync(r,s)}rmdirSync(r,{recursive:s=!1}={}){if(this.readOnly)throw or.EROFS(`rmdir '${r}'`);if(s){this.removeSync(r);return}let a=this.resolveFilename(`rmdir '${r}'`,r),n=this.listings.get(a);if(!n)throw or.ENOTDIR(`rmdir '${r}'`);if(n.size>0)throw or.ENOTEMPTY(`rmdir '${r}'`);let c=this.entries.get(a);if(typeof c>\"u\")throw or.EINVAL(`rmdir '${r}'`);this.deleteEntry(r,c)}async rmPromise(r,s){return this.rmSync(r,s)}rmSync(r,{recursive:s=!1}={}){if(this.readOnly)throw or.EROFS(`rm '${r}'`);if(s){this.removeSync(r);return}let a=this.resolveFilename(`rm '${r}'`,r),n=this.listings.get(a);if(!n)throw or.ENOTDIR(`rm '${r}'`);if(n.size>0)throw or.ENOTEMPTY(`rm '${r}'`);let c=this.entries.get(a);if(typeof c>\"u\")throw or.EINVAL(`rm '${r}'`);this.deleteEntry(r,c)}hydrateDirectory(r){let s=this.zipImpl.addDirectory(K.relative(vt.root,r));return this.registerListing(r),this.registerEntry(r,s),s}async linkPromise(r,s){return this.linkSync(r,s)}linkSync(r,s){throw or.EOPNOTSUPP(`link '${r}' -> '${s}'`)}async symlinkPromise(r,s){return this.symlinkSync(r,s)}symlinkSync(r,s){if(this.readOnly)throw or.EROFS(`symlink '${r}' -> '${s}'`);let a=this.resolveFilename(`symlink '${r}' -> '${s}'`,s);if(this.listings.has(a))throw or.EISDIR(`symlink '${r}' -> '${s}'`);if(this.entries.has(a))throw or.EEXIST(`symlink '${r}' -> '${s}'`);let n=this.setFileSource(a,r);this.registerEntry(a,n),this.zipImpl.setExternalAttributes(n,om,(Ra.constants.S_IFLNK|511)<<16),this.symlinkCount+=1}async readFilePromise(r,s){typeof s==\"object\"&&(s=s?s.encoding:void 0);let a=await this.readFileBuffer(r,{asyncDecompress:!0});return s?a.toString(s):a}readFileSync(r,s){typeof s==\"object\"&&(s=s?s.encoding:void 0);let a=this.readFileBuffer(r);return s?a.toString(s):a}readFileBuffer(r,s={asyncDecompress:!1}){typeof r==\"number\"&&(r=this.fdToPath(r,\"read\"));let a=this.resolveFilename(`open '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw or.ENOENT(`open '${r}'`);if(r[r.length-1]===\"/\"&&!this.listings.has(a))throw or.ENOTDIR(`open '${r}'`);if(this.listings.has(a))throw or.EISDIR(\"read\");let n=this.entries.get(a);if(n===void 0)throw new Error(\"Unreachable\");return this.getFileSource(n,s)}async readdirPromise(r,s){return this.readdirSync(r,s)}readdirSync(r,s){let a=this.resolveFilename(`scandir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw or.ENOENT(`scandir '${r}'`);let n=this.listings.get(a);if(!n)throw or.ENOTDIR(`scandir '${r}'`);if(s?.recursive)if(s?.withFileTypes){let c=Array.from(n,f=>Object.assign(this.statImpl(\"lstat\",K.join(r,f)),{name:f,path:vt.dot,parentPath:vt.dot}));for(let f of c){if(!f.isDirectory())continue;let p=K.join(f.path,f.name),h=this.listings.get(K.join(a,p));for(let E of h)c.push(Object.assign(this.statImpl(\"lstat\",K.join(r,p,E)),{name:E,path:p,parentPath:p}))}return c}else{let c=[...n];for(let f of c){let p=this.listings.get(K.join(a,f));if(!(typeof p>\"u\"))for(let h of p)c.push(K.join(f,h))}return c}else return s?.withFileTypes?Array.from(n,c=>Object.assign(this.statImpl(\"lstat\",K.join(r,c)),{name:c,path:void 0,parentPath:void 0})):[...n]}async readlinkPromise(r){let s=this.prepareReadlink(r);return(await this.getFileSource(s,{asyncDecompress:!0})).toString()}readlinkSync(r){let s=this.prepareReadlink(r);return this.getFileSource(s).toString()}prepareReadlink(r){let s=this.resolveFilename(`readlink '${r}'`,r,!1);if(!this.entries.has(s)&&!this.listings.has(s))throw or.ENOENT(`readlink '${r}'`);if(r[r.length-1]===\"/\"&&!this.listings.has(s))throw or.ENOTDIR(`open '${r}'`);if(this.listings.has(s))throw or.EINVAL(`readlink '${r}'`);let a=this.entries.get(s);if(a===void 0)throw new Error(\"Unreachable\");if(!this.isSymbolicLink(a))throw or.EINVAL(`readlink '${r}'`);return a}async truncatePromise(r,s=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>\"u\")throw or.EINVAL(`open '${r}'`);let c=await this.getFileSource(n,{asyncDecompress:!0}),f=Buffer.alloc(s,0);return c.copy(f),await this.writeFilePromise(r,f)}truncateSync(r,s=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>\"u\")throw or.EINVAL(`open '${r}'`);let c=this.getFileSource(n),f=Buffer.alloc(s,0);return c.copy(f),this.writeFileSync(r,f)}async ftruncatePromise(r,s){return this.truncatePromise(this.fdToPath(r,\"ftruncate\"),s)}ftruncateSync(r,s){return this.truncateSync(this.fdToPath(r,\"ftruncateSync\"),s)}watch(r,s,a){let n;switch(typeof s){case\"function\":case\"string\":case\"undefined\":n=!0;break;default:({persistent:n=!0}=s);break}if(!n)return{on:()=>{},close:()=>{}};let c=setInterval(()=>{},24*60*60*1e3);return{on:()=>{},close:()=>{clearInterval(c)}}}watchFile(r,s,a){let n=K.resolve(vt.root,r);return lE(this,n,s,a)}unwatchFile(r,s){let a=K.resolve(vt.root,r);return gd(this,a,s)}}});function UAe(e,t,r=Buffer.alloc(0),s){let a=new ps(r),n=C=>C===t||C.startsWith(`${t}/`)?C.slice(0,t.length):null,c=async(C,S)=>()=>a,f=(C,S)=>a,p={...e},h=new Yn(p),E=new Xh({baseFs:h,getMountPoint:n,factoryPromise:c,factorySync:f,magicByte:21,maxAge:1/0,typeCheck:s?.typeCheck});return QB(MAe.default,new $h(E)),a}var MAe,_Ae=Ze(()=>{Dt();MAe=et(Ie(\"fs\"));BR()});var HAe=Ze(()=>{NAe();BR();_Ae()});var Ij,rv,vR,jAe=Ze(()=>{Dt();BR();Ij={CENTRAL_DIRECTORY:33639248,END_OF_CENTRAL_DIRECTORY:101010256},rv=22,vR=class e{constructor(t){this.filesShouldBeCached=!1;if(\"buffer\"in t)throw new Error(\"Buffer based zip archives are not supported\");if(!t.readOnly)throw new Error(\"Writable zip archives are not supported\");this.baseFs=t.baseFs,this.fd=this.baseFs.openSync(t.path,\"r\");try{this.entries=e.readZipSync(this.fd,this.baseFs,t.size)}catch(r){throw this.baseFs.closeSync(this.fd),this.fd=\"closed\",r}}static readZipSync(t,r,s){if(s<rv)throw new Error(\"Invalid ZIP file: EOCD not found\");let a=-1,n=Buffer.alloc(rv);if(r.readSync(t,n,0,rv,s-rv),n.readUInt32LE(0)===Ij.END_OF_CENTRAL_DIRECTORY)a=0;else{let T=Math.min(65557,s);n=Buffer.alloc(T),r.readSync(t,n,0,T,Math.max(0,s-T));for(let O=n.length-4;O>=0;O--)if(n.readUInt32LE(O)===Ij.END_OF_CENTRAL_DIRECTORY){a=O;break}if(a===-1)throw new Error(\"Not a zip archive\")}let c=n.readUInt16LE(a+10),f=n.readUInt32LE(a+12),p=n.readUInt32LE(a+16),h=n.readUInt16LE(a+20);if(a+h+rv>n.length)throw new Error(\"Zip archive inconsistent\");if(c==65535||f==4294967295||p==4294967295)throw new Error(\"Zip 64 is not supported\");if(f>s)throw new Error(\"Zip archive inconsistent\");if(c>f/46)throw new Error(\"Zip archive inconsistent\");let E=Buffer.alloc(f);if(r.readSync(t,E,0,E.length,p)!==E.length)throw new Error(\"Zip archive inconsistent\");let C=[],S=0,x=0,I=0;for(;x<c;){if(S+46>E.length)throw new Error(\"Zip archive inconsistent\");if(E.readUInt32LE(S)!==Ij.CENTRAL_DIRECTORY)throw new Error(\"Zip archive inconsistent\");let O=E.readUInt16LE(S+4)>>>8;if(E.readUInt16LE(S+8)&1)throw new Error(\"Encrypted zip files are not supported\");let Y=E.readUInt16LE(S+10),te=E.readUInt32LE(S+16),ie=E.readUInt16LE(S+28),ue=E.readUInt16LE(S+30),ae=E.readUInt16LE(S+32),de=E.readUInt32LE(S+42),Ae=E.toString(\"utf8\",S+46,S+46+ie).replaceAll(\"\\0\",\" \");if(Ae.includes(\"\\0\"))throw new Error(\"Invalid ZIP file\");let Ce=E.readUInt32LE(S+20),Ee=E.readUInt32LE(S+38);C.push({name:Ae,os:O,mtime:Ai.SAFE_TIME,crc:te,compressionMethod:Y,isSymbolicLink:O===om&&(Ee>>>16&Ai.S_IFMT)===Ai.S_IFLNK,size:E.readUInt32LE(S+24),compressedSize:Ce,externalAttributes:Ee,localHeaderOffset:de}),I+=Ce,x+=1,S+=46+ie+ue+ae}if(I>s)throw new Error(\"Zip archive inconsistent\");if(S!==E.length)throw new Error(\"Zip archive inconsistent\");return C}getExternalAttributes(t){let r=this.entries[t];return[r.os,r.externalAttributes]}getListings(){return this.entries.map(t=>t.name)}getSymlinkCount(){let t=0;for(let r of this.entries)r.isSymbolicLink&&(t+=1);return t}stat(t){let r=this.entries[t];return{crc:r.crc,mtime:r.mtime,size:r.size}}locate(t){for(let r=0;r<this.entries.length;r++)if(this.entries[r].name===t)return r;return-1}getFileSource(t){if(this.fd===\"closed\")throw new Error(\"ZIP file is closed\");let r=this.entries[t],s=Buffer.alloc(30);this.baseFs.readSync(this.fd,s,0,s.length,r.localHeaderOffset);let a=s.readUInt16LE(26),n=s.readUInt16LE(28),c=Buffer.alloc(r.compressedSize);if(this.baseFs.readSync(this.fd,c,0,r.compressedSize,r.localHeaderOffset+30+a+n)!==r.compressedSize)throw new Error(\"Invalid ZIP file\");return{data:c,compressionMethod:r.compressionMethod}}discard(){this.fd!==\"closed\"&&(this.baseFs.closeSync(this.fd),this.fd=\"closed\")}addDirectory(t){throw new Error(\"Not implemented\")}deleteEntry(t){throw new Error(\"Not implemented\")}setMtime(t,r){throw new Error(\"Not implemented\")}getBufferAndClose(){throw new Error(\"Not implemented\")}setFileSource(t,r,s){throw new Error(\"Not implemented\")}setExternalAttributes(t,r,s){throw new Error(\"Not implemented\")}}});var nv={};Yt(nv,{DEFAULT_COMPRESSION_LEVEL:()=>LAe,DEFLATE:()=>Ej,JsZipImpl:()=>vR,LibZipImpl:()=>DI,STORE:()=>yj,ZIP_UNIX:()=>om,ZipFS:()=>ps,ZipOpenFS:()=>tA,getArchivePart:()=>pj,getLibzipPromise:()=>Ftt,getLibzipSync:()=>Ttt,makeEmptyArchive:()=>wR,mountMemoryDrive:()=>UAe});function Ttt(){return tv()}async function Ftt(){return tv()}var GAe,rA=Ze(()=>{uj();GAe=et(QAe());FAe();HAe();jAe();gj();kAe(()=>{let e=(0,GAe.default)();return TAe(e)})});var iv,qAe=Ze(()=>{Dt();Vt();sv();iv=class extends at{constructor(){super(...arguments);this.cwd=he.String(\"--cwd\",process.cwd(),{description:\"The directory to run the command in\"});this.commandName=he.String();this.args=he.Proxy()}static{this.usage={description:\"run a command using yarn's portable shell\",details:`\n      This command will run a command using Yarn's portable shell.\n\n      Make sure to escape glob patterns, redirections, and other features that might be expanded by your own shell.\n\n      Note: To escape something from Yarn's shell, you might have to escape it twice, the first time from your own shell.\n\n      Note: Don't use this command in Yarn scripts, as Yarn's shell is automatically used.\n\n      For a list of features, visit: https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-shell/README.md.\n    `,examples:[[\"Run a simple command\",\"$0 echo Hello\"],[\"Run a command with a glob pattern\",\"$0 echo '*.js'\"],[\"Run a command with a redirection\",\"$0 echo Hello World '>' hello.txt\"],[\"Run a command with an escaped glob pattern (The double escape is needed in Unix shells)\",`$0 echo '\"*.js\"'`],[\"Run a command with a variable (Double quotes are needed in Unix shells, to prevent them from expanding the variable)\",'$0 \"GREETING=Hello echo $GREETING World\"']]}}async execute(){let r=this.args.length>0?`${this.commandName} ${this.args.join(\" \")}`:this.commandName;return await bI(r,[],{cwd:fe.toPortablePath(this.cwd),stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}}});var Xl,WAe=Ze(()=>{Xl=class extends Error{constructor(t){super(t),this.name=\"ShellError\"}}});var bR={};Yt(bR,{fastGlobOptions:()=>KAe,isBraceExpansion:()=>Cj,isGlobPattern:()=>Ntt,match:()=>Ott,micromatchOptions:()=>DR});function Ntt(e){if(!SR.default.scan(e,DR).isGlob)return!1;try{SR.default.parse(e,DR)}catch{return!1}return!0}function Ott(e,{cwd:t,baseFs:r}){return(0,VAe.default)(e,{...KAe,cwd:fe.fromPortablePath(t),fs:ax(YAe.default,new $h(r))})}function Cj(e){return SR.default.scan(e,DR).isBrace}var VAe,YAe,SR,DR,KAe,JAe=Ze(()=>{Dt();VAe=et(wQ()),YAe=et(Ie(\"fs\")),SR=et(Jo()),DR={strictBrackets:!0},KAe={onlyDirectories:!1,onlyFiles:!1}});function wj(){}function Bj(){for(let e of am)e.kill()}function $Ae(e,t,r,s){return a=>{let n=a[0]instanceof nA.Transform?\"pipe\":a[0],c=a[1]instanceof nA.Transform?\"pipe\":a[1],f=a[2]instanceof nA.Transform?\"pipe\":a[2],p=(0,ZAe.default)(e,t,{...s,stdio:[n,c,f]});return am.add(p),am.size===1&&(process.on(\"SIGINT\",wj),process.on(\"SIGTERM\",Bj)),a[0]instanceof nA.Transform&&a[0].pipe(p.stdin),a[1]instanceof nA.Transform&&p.stdout.pipe(a[1],{end:!1}),a[2]instanceof nA.Transform&&p.stderr.pipe(a[2],{end:!1}),{stdin:p.stdin,promise:new Promise(h=>{p.on(\"error\",E=>{switch(am.delete(p),am.size===0&&(process.off(\"SIGINT\",wj),process.off(\"SIGTERM\",Bj)),E.code){case\"ENOENT\":a[2].write(`command not found: ${e}\n`),h(127);break;case\"EACCES\":a[2].write(`permission denied: ${e}\n`),h(128);break;default:a[2].write(`uncaught error: ${E.message}\n`),h(1);break}}),p.on(\"close\",E=>{am.delete(p),am.size===0&&(process.off(\"SIGINT\",wj),process.off(\"SIGTERM\",Bj)),h(E!==null?E:129)})})}}}function epe(e){return t=>{let r=t[0]===\"pipe\"?new nA.PassThrough:t[0];return{stdin:r,promise:Promise.resolve().then(()=>e({stdin:r,stdout:t[1],stderr:t[2]}))}}}function PR(e,t){return Sj.start(e,t)}function zAe(e,t=null){let r=new nA.PassThrough,s=new XAe.StringDecoder,a=\"\";return r.on(\"data\",n=>{let c=s.write(n),f;do if(f=c.indexOf(`\n`),f!==-1){let p=a+c.substring(0,f);c=c.substring(f+1),a=\"\",e(t!==null?`${t} ${p}`:p)}while(f!==-1);a+=c}),r.on(\"end\",()=>{let n=s.end();n!==\"\"&&e(t!==null?`${t} ${n}`:n)}),r}function tpe(e,{prefix:t}){return{stdout:zAe(r=>e.stdout.write(`${r}\n`),e.stdout.isTTY?t:null),stderr:zAe(r=>e.stderr.write(`${r}\n`),e.stderr.isTTY?t:null)}}var ZAe,nA,XAe,am,Lc,vj,Sj,Dj=Ze(()=>{ZAe=et(vU()),nA=Ie(\"stream\"),XAe=Ie(\"string_decoder\"),am=new Set;Lc=class{constructor(t){this.stream=t}close(){}get(){return this.stream}},vj=class{constructor(){this.stream=null}close(){if(this.stream===null)throw new Error(\"Assertion failed: No stream attached\");this.stream.end()}attach(t){this.stream=t}get(){if(this.stream===null)throw new Error(\"Assertion failed: No stream attached\");return this.stream}},Sj=class e{constructor(t,r){this.stdin=null;this.stdout=null;this.stderr=null;this.pipe=null;this.ancestor=t,this.implementation=r}static start(t,{stdin:r,stdout:s,stderr:a}){let n=new e(null,t);return n.stdin=r,n.stdout=s,n.stderr=a,n}pipeTo(t,r=1){let s=new e(this,t),a=new vj;return s.pipe=a,s.stdout=this.stdout,s.stderr=this.stderr,(r&1)===1?this.stdout=a:this.ancestor!==null&&(this.stderr=this.ancestor.stdout),(r&2)===2?this.stderr=a:this.ancestor!==null&&(this.stderr=this.ancestor.stderr),s}async exec(){let t=[\"ignore\",\"ignore\",\"ignore\"];if(this.pipe)t[0]=\"pipe\";else{if(this.stdin===null)throw new Error(\"Assertion failed: No input stream registered\");t[0]=this.stdin.get()}let r;if(this.stdout===null)throw new Error(\"Assertion failed: No output stream registered\");r=this.stdout,t[1]=r.get();let s;if(this.stderr===null)throw new Error(\"Assertion failed: No error stream registered\");s=this.stderr,t[2]=s.get();let a=this.implementation(t);return this.pipe&&this.pipe.attach(a.stdin),await a.promise.then(n=>(r.close(),s.close(),n))}async run(){let t=[];for(let s=this;s;s=s.ancestor)t.push(s.exec());return(await Promise.all(t))[0]}}});var cv={};Yt(cv,{EntryCommand:()=>iv,ShellError:()=>Xl,execute:()=>bI,globUtils:()=>bR});function rpe(e,t,r){let s=new $l.PassThrough({autoDestroy:!0});switch(e){case 0:(t&1)===1&&r.stdin.pipe(s,{end:!1}),(t&2)===2&&r.stdin instanceof $l.Writable&&s.pipe(r.stdin,{end:!1});break;case 1:(t&1)===1&&r.stdout.pipe(s,{end:!1}),(t&2)===2&&s.pipe(r.stdout,{end:!1});break;case 2:(t&1)===1&&r.stderr.pipe(s,{end:!1}),(t&2)===2&&s.pipe(r.stderr,{end:!1});break;default:throw new Xl(`Bad file descriptor: \"${e}\"`)}return s}function kR(e,t={}){let r={...e,...t};return r.environment={...e.environment,...t.environment},r.variables={...e.variables,...t.variables},r}async function Mtt(e,t,r){let s=[],a=new $l.PassThrough;return a.on(\"data\",n=>s.push(n)),await QR(e,t,kR(r,{stdout:a})),Buffer.concat(s).toString().replace(/[\\r\\n]+$/,\"\")}async function npe(e,t,r){let s=e.map(async n=>{let c=await lm(n.args,t,r);return{name:n.name,value:c.join(\" \")}});return(await Promise.all(s)).reduce((n,c)=>(n[c.name]=c.value,n),{})}function xR(e){return e.match(/[^ \\r\\n\\t]+/g)||[]}async function cpe(e,t,r,s,a=s){switch(e.name){case\"$\":s(String(process.pid));break;case\"#\":s(String(t.args.length));break;case\"@\":if(e.quoted)for(let n of t.args)a(n);else for(let n of t.args){let c=xR(n);for(let f=0;f<c.length-1;++f)a(c[f]);s(c[c.length-1])}break;case\"*\":{let n=t.args.join(\" \");if(e.quoted)s(n);else for(let c of xR(n))a(c)}break;case\"PPID\":s(String(process.ppid));break;case\"RANDOM\":s(String(Math.floor(Math.random()*32768)));break;default:{let n=parseInt(e.name,10),c,f=Number.isFinite(n);if(f?n>=0&&n<t.args.length&&(c=t.args[n]):Object.hasOwn(r.variables,e.name)?c=r.variables[e.name]:Object.hasOwn(r.environment,e.name)&&(c=r.environment[e.name]),typeof c<\"u\"&&e.alternativeValue?c=(await lm(e.alternativeValue,t,r)).join(\" \"):typeof c>\"u\"&&(e.defaultValue?c=(await lm(e.defaultValue,t,r)).join(\" \"):e.alternativeValue&&(c=\"\")),typeof c>\"u\")throw f?new Xl(`Unbound argument #${n}`):new Xl(`Unbound variable \"${e.name}\"`);if(e.quoted)s(c);else{let p=xR(c);for(let E=0;E<p.length-1;++E)a(p[E]);let h=p[p.length-1];typeof h<\"u\"&&s(h)}}break}}async function ov(e,t,r){if(e.type===\"number\"){if(Number.isInteger(e.value))return e.value;throw new Error(`Invalid number: \"${e.value}\", only integers are allowed`)}else if(e.type===\"variable\"){let s=[];await cpe({...e,quoted:!0},t,r,n=>s.push(n));let a=Number(s.join(\" \"));return Number.isNaN(a)?ov({type:\"variable\",name:s.join(\" \")},t,r):ov({type:\"number\",value:a},t,r)}else return Utt[e.type](await ov(e.left,t,r),await ov(e.right,t,r))}async function lm(e,t,r){let s=new Map,a=[],n=[],c=E=>{n.push(E)},f=()=>{n.length>0&&a.push(n.join(\"\")),n=[]},p=E=>{c(E),f()},h=(E,C,S)=>{let x=JSON.stringify({type:E,fd:C}),I=s.get(x);typeof I>\"u\"&&s.set(x,I=[]),I.push(S)};for(let E of e){let C=!1;switch(E.type){case\"redirection\":{let S=await lm(E.args,t,r);for(let x of S)h(E.subtype,E.fd,x)}break;case\"argument\":for(let S of E.segments)switch(S.type){case\"text\":c(S.text);break;case\"glob\":c(S.pattern),C=!0;break;case\"shell\":{let x=await Mtt(S.shell,t,r);if(S.quoted)c(x);else{let I=xR(x);for(let T=0;T<I.length-1;++T)p(I[T]);c(I[I.length-1])}}break;case\"variable\":await cpe(S,t,r,c,p);break;case\"arithmetic\":c(String(await ov(S.arithmetic,t,r)));break}break}if(f(),C){let S=a.pop();if(typeof S>\"u\")throw new Error(\"Assertion failed: Expected a glob pattern to have been set\");let x=await t.glob.match(S,{cwd:r.cwd,baseFs:t.baseFs});if(x.length===0){let I=Cj(S)?\". Note: Brace expansion of arbitrary strings isn't currently supported. For more details, please read this issue: https://github.com/yarnpkg/berry/issues/22\":\"\";throw new Xl(`No matches found: \"${S}\"${I}`)}for(let I of x.sort())p(I)}}if(s.size>0){let E=[];for(let[C,S]of s.entries())E.splice(E.length,0,C,String(S.length),...S);a.splice(0,0,\"__ysh_set_redirects\",...E,\"--\")}return a}function av(e,t,r){t.builtins.has(e[0])||(e=[\"command\",...e]);let s=fe.fromPortablePath(r.cwd),a=r.environment;typeof a.PWD<\"u\"&&(a={...a,PWD:s});let[n,...c]=e;if(n===\"command\")return $Ae(c[0],c.slice(1),t,{cwd:s,env:a});let f=t.builtins.get(n);if(typeof f>\"u\")throw new Error(`Assertion failed: A builtin should exist for \"${n}\"`);return epe(async({stdin:p,stdout:h,stderr:E})=>{let{stdin:C,stdout:S,stderr:x}=r;r.stdin=p,r.stdout=h,r.stderr=E;try{return await f(c,t,r)}finally{r.stdin=C,r.stdout=S,r.stderr=x}})}function _tt(e,t,r){return s=>{let a=new $l.PassThrough,n=QR(e,t,kR(r,{stdin:a}));return{stdin:a,promise:n}}}function Htt(e,t,r){return s=>{let a=new $l.PassThrough,n=QR(e,t,r);return{stdin:a,promise:n}}}function ipe(e,t,r,s){if(t.length===0)return e;{let a;do a=String(Math.random());while(Object.hasOwn(s.procedures,a));return s.procedures={...s.procedures},s.procedures[a]=e,av([...t,\"__ysh_run_procedure\",a],r,s)}}async function spe(e,t,r){let s=e,a=null,n=null;for(;s;){let c=s.then?{...r}:r,f;switch(s.type){case\"command\":{let p=await lm(s.args,t,r),h=await npe(s.envs,t,r);f=s.envs.length?av(p,t,kR(c,{environment:h})):av(p,t,c)}break;case\"subshell\":{let p=await lm(s.args,t,r),h=_tt(s.subshell,t,c);f=ipe(h,p,t,c)}break;case\"group\":{let p=await lm(s.args,t,r),h=Htt(s.group,t,c);f=ipe(h,p,t,c)}break;case\"envs\":{let p=await npe(s.envs,t,r);c.environment={...c.environment,...p},f=av([\"true\"],t,c)}break}if(typeof f>\"u\")throw new Error(\"Assertion failed: An action should have been generated\");if(a===null)n=PR(f,{stdin:new Lc(c.stdin),stdout:new Lc(c.stdout),stderr:new Lc(c.stderr)});else{if(n===null)throw new Error(\"Assertion failed: The execution pipeline should have been setup\");switch(a){case\"|\":n=n.pipeTo(f,1);break;case\"|&\":n=n.pipeTo(f,3);break}}s.then?(a=s.then.type,s=s.then.chain):s=null}if(n===null)throw new Error(\"Assertion failed: The execution pipeline should have been setup\");return await n.run()}async function jtt(e,t,r,{background:s=!1}={}){function a(n){let c=[\"#2E86AB\",\"#A23B72\",\"#F18F01\",\"#C73E1D\",\"#CCE2A3\"],f=c[n%c.length];return ope.default.hex(f)}if(s){let n=r.nextBackgroundJobIndex++,c=a(n),f=`[${n}]`,p=c(f),{stdout:h,stderr:E}=tpe(r,{prefix:p});return r.backgroundJobs.push(spe(e,t,kR(r,{stdout:h,stderr:E})).catch(C=>E.write(`${C.message}\n`)).finally(()=>{r.stdout.isTTY&&r.stdout.write(`Job ${p}, '${c(gE(e))}' has ended\n`)})),0}return await spe(e,t,r)}async function Gtt(e,t,r,{background:s=!1}={}){let a,n=f=>{a=f,r.variables[\"?\"]=String(f)},c=async f=>{try{return await jtt(f.chain,t,r,{background:s&&typeof f.then>\"u\"})}catch(p){if(!(p instanceof Xl))throw p;return r.stderr.write(`${p.message}\n`),1}};for(n(await c(e));e.then;){if(r.exitCode!==null)return r.exitCode;switch(e.then.type){case\"&&\":a===0&&n(await c(e.then.line));break;case\"||\":a!==0&&n(await c(e.then.line));break;default:throw new Error(`Assertion failed: Unsupported command type: \"${e.then.type}\"`)}e=e.then.line}return a}async function QR(e,t,r){let s=r.backgroundJobs;r.backgroundJobs=[];let a=0;for(let{command:n,type:c}of e){if(a=await Gtt(n,t,r,{background:c===\"&\"}),r.exitCode!==null)return r.exitCode;r.variables[\"?\"]=String(a)}return await Promise.all(r.backgroundJobs),r.backgroundJobs=s,a}function upe(e){switch(e.type){case\"variable\":return e.name===\"@\"||e.name===\"#\"||e.name===\"*\"||Number.isFinite(parseInt(e.name,10))||\"defaultValue\"in e&&!!e.defaultValue&&e.defaultValue.some(t=>lv(t))||\"alternativeValue\"in e&&!!e.alternativeValue&&e.alternativeValue.some(t=>lv(t));case\"arithmetic\":return bj(e.arithmetic);case\"shell\":return Pj(e.shell);default:return!1}}function lv(e){switch(e.type){case\"redirection\":return e.args.some(t=>lv(t));case\"argument\":return e.segments.some(t=>upe(t));default:throw new Error(`Assertion failed: Unsupported argument type: \"${e.type}\"`)}}function bj(e){switch(e.type){case\"variable\":return upe(e);case\"number\":return!1;default:return bj(e.left)||bj(e.right)}}function Pj(e){return e.some(({command:t})=>{for(;t;){let r=t.chain;for(;r;){let s;switch(r.type){case\"subshell\":s=Pj(r.subshell);break;case\"command\":s=r.envs.some(a=>a.args.some(n=>lv(n)))||r.args.some(a=>lv(a));break}if(s)return!0;if(!r.then)break;r=r.then.chain}if(!t.then)break;t=t.then.line}return!1})}async function bI(e,t=[],{baseFs:r=new Yn,builtins:s={},cwd:a=fe.toPortablePath(process.cwd()),env:n=process.env,stdin:c=process.stdin,stdout:f=process.stdout,stderr:p=process.stderr,variables:h={},glob:E=bR}={}){let C={};for(let[I,T]of Object.entries(n))typeof T<\"u\"&&(C[I]=T);let S=new Map(Ltt);for(let[I,T]of Object.entries(s))S.set(I,T);c===null&&(c=new $l.PassThrough,c.end());let x=ux(e,E);if(!Pj(x)&&x.length>0&&t.length>0){let{command:I}=x[x.length-1];for(;I.then;)I=I.then.line;let T=I.chain;for(;T.then;)T=T.then.chain;T.type===\"command\"&&(T.args=T.args.concat(t.map(O=>({type:\"argument\",segments:[{type:\"text\",text:O}]}))))}return await QR(x,{args:t,baseFs:r,builtins:S,initialStdin:c,initialStdout:f,initialStderr:p,glob:E},{cwd:a,environment:C,exitCode:null,procedures:{},stdin:c,stdout:f,stderr:p,variables:Object.assign({},h,{\"?\":0}),nextBackgroundJobIndex:1,backgroundJobs:[]})}var ope,ape,$l,lpe,Ltt,Utt,sv=Ze(()=>{Dt();Bc();ope=et(NE()),ape=Ie(\"os\"),$l=Ie(\"stream\"),lpe=Ie(\"timers/promises\");qAe();WAe();JAe();Dj();Dj();Ltt=new Map([[\"cd\",async([e=(0,ape.homedir)(),...t],r,s)=>{let a=K.resolve(s.cwd,fe.toPortablePath(e));if(!(await r.baseFs.statPromise(a).catch(c=>{throw c.code===\"ENOENT\"?new Xl(`cd: no such file or directory: ${e}`):c})).isDirectory())throw new Xl(`cd: not a directory: ${e}`);return s.cwd=a,0}],[\"pwd\",async(e,t,r)=>(r.stdout.write(`${fe.fromPortablePath(r.cwd)}\n`),0)],[\":\",async(e,t,r)=>0],[\"true\",async(e,t,r)=>0],[\"false\",async(e,t,r)=>1],[\"exit\",async([e,...t],r,s)=>s.exitCode=parseInt(e??s.variables[\"?\"],10)],[\"echo\",async(e,t,r)=>(r.stdout.write(`${e.join(\" \")}\n`),0)],[\"sleep\",async([e],t,r)=>{if(typeof e>\"u\")throw new Xl(\"sleep: missing operand\");let s=Number(e);if(Number.isNaN(s))throw new Xl(`sleep: invalid time interval '${e}'`);return await(0,lpe.setTimeout)(1e3*s,0)}],[\"unset\",async(e,t,r)=>{for(let s of e)delete r.environment[s],delete r.variables[s];return 0}],[\"__ysh_run_procedure\",async(e,t,r)=>{let s=r.procedures[e[0]];return await PR(s,{stdin:new Lc(r.stdin),stdout:new Lc(r.stdout),stderr:new Lc(r.stderr)}).run()}],[\"__ysh_set_redirects\",async(e,t,r)=>{let s=r.stdin,a=r.stdout,n=r.stderr,c=[],f=[],p=[],h=0;for(;e[h]!==\"--\";){let C=e[h++],{type:S,fd:x}=JSON.parse(C),I=Y=>{switch(x){case null:case 0:c.push(Y);break;default:throw new Error(`Unsupported file descriptor: \"${x}\"`)}},T=Y=>{switch(x){case null:case 1:f.push(Y);break;case 2:p.push(Y);break;default:throw new Error(`Unsupported file descriptor: \"${x}\"`)}},O=Number(e[h++]),U=h+O;for(let Y=h;Y<U;++h,++Y)switch(S){case\"<\":I(()=>t.baseFs.createReadStream(K.resolve(r.cwd,fe.toPortablePath(e[Y]))));break;case\"<<<\":I(()=>{let te=new $l.PassThrough;return process.nextTick(()=>{te.write(`${e[Y]}\n`),te.end()}),te});break;case\"<&\":I(()=>rpe(Number(e[Y]),1,r));break;case\">\":case\">>\":{let te=K.resolve(r.cwd,fe.toPortablePath(e[Y]));T(te===\"/dev/null\"?new $l.Writable({autoDestroy:!0,emitClose:!0,write(ie,ue,ae){setImmediate(ae)}}):t.baseFs.createWriteStream(te,S===\">>\"?{flags:\"a\"}:void 0))}break;case\">&\":T(rpe(Number(e[Y]),2,r));break;default:throw new Error(`Assertion failed: Unsupported redirection type: \"${S}\"`)}}if(c.length>0){let C=new $l.PassThrough;s=C;let S=x=>{if(x===c.length)C.end();else{let I=c[x]();I.pipe(C,{end:!1}),I.on(\"end\",()=>{S(x+1)})}};S(0)}if(f.length>0){let C=new $l.PassThrough;a=C;for(let S of f)C.pipe(S)}if(p.length>0){let C=new $l.PassThrough;n=C;for(let S of p)C.pipe(S)}let E=await PR(av(e.slice(h+1),t,r),{stdin:new Lc(s),stdout:new Lc(a),stderr:new Lc(n)}).run();return await Promise.all(f.map(C=>new Promise((S,x)=>{C.on(\"error\",I=>{x(I)}),C.on(\"close\",()=>{S()}),C.end()}))),await Promise.all(p.map(C=>new Promise((S,x)=>{C.on(\"error\",I=>{x(I)}),C.on(\"close\",()=>{S()}),C.end()}))),E}]]);Utt={addition:(e,t)=>e+t,subtraction:(e,t)=>e-t,multiplication:(e,t)=>e*t,division:(e,t)=>Math.trunc(e/t)}});var fpe=G((UMt,RR)=>{function qtt(){var e=0,t=1,r=2,s=3,a=4,n=5,c=6,f=7,p=8,h=9,E=10,C=11,S=12,x=13,I=14,T=15,O=16,U=17,Y=0,te=1,ie=2,ue=3,ae=4;function de(g,Se){return 55296<=g.charCodeAt(Se)&&g.charCodeAt(Se)<=56319&&56320<=g.charCodeAt(Se+1)&&g.charCodeAt(Se+1)<=57343}function Ae(g,Se){Se===void 0&&(Se=0);var Be=g.charCodeAt(Se);if(55296<=Be&&Be<=56319&&Se<g.length-1){var me=Be,ce=g.charCodeAt(Se+1);return 56320<=ce&&ce<=57343?(me-55296)*1024+(ce-56320)+65536:me}if(56320<=Be&&Be<=57343&&Se>=1){var me=g.charCodeAt(Se-1),ce=Be;return 55296<=me&&me<=56319?(me-55296)*1024+(ce-56320)+65536:ce}return Be}function Ce(g,Se,Be){var me=[g].concat(Se).concat([Be]),ce=me[me.length-2],X=Be,De=me.lastIndexOf(I);if(De>1&&me.slice(1,De).every(function(_){return _==s})&&[s,x,U].indexOf(g)==-1)return ie;var Qe=me.lastIndexOf(a);if(Qe>0&&me.slice(1,Qe).every(function(_){return _==a})&&[S,a].indexOf(ce)==-1)return me.filter(function(_){return _==a}).length%2==1?ue:ae;if(ce==e&&X==t)return Y;if(ce==r||ce==e||ce==t)return X==I&&Se.every(function(_){return _==s})?ie:te;if(X==r||X==e||X==t)return te;if(ce==c&&(X==c||X==f||X==h||X==E))return Y;if((ce==h||ce==f)&&(X==f||X==p))return Y;if((ce==E||ce==p)&&X==p)return Y;if(X==s||X==T)return Y;if(X==n)return Y;if(ce==S)return Y;var it=me.indexOf(s)!=-1?me.lastIndexOf(s)-1:me.length-2;return[x,U].indexOf(me[it])!=-1&&me.slice(it+1,-1).every(function(_){return _==s})&&X==I||ce==T&&[O,U].indexOf(X)!=-1?Y:Se.indexOf(a)!=-1?ie:ce==a&&X==a?Y:te}this.nextBreak=function(g,Se){if(Se===void 0&&(Se=0),Se<0)return 0;if(Se>=g.length-1)return g.length;for(var Be=Ee(Ae(g,Se)),me=[],ce=Se+1;ce<g.length;ce++)if(!de(g,ce-1)){var X=Ee(Ae(g,ce));if(Ce(Be,me,X))return ce;me.push(X)}return g.length},this.splitGraphemes=function(g){for(var Se=[],Be=0,me;(me=this.nextBreak(g,Be))<g.length;)Se.push(g.slice(Be,me)),Be=me;return Be<g.length&&Se.push(g.slice(Be)),Se},this.iterateGraphemes=function(g){var Se=0,Be={next:function(){var me,ce;return(ce=this.nextBreak(g,Se))<g.length?(me=g.slice(Se,ce),Se=ce,{value:me,done:!1}):Se<g.length?(me=g.slice(Se),Se=g.length,{value:me,done:!1}):{value:void 0,done:!0}}.bind(this)};return typeof Symbol<\"u\"&&Symbol.iterator&&(Be[Symbol.iterator]=function(){return Be}),Be},this.countGraphemes=function(g){for(var Se=0,Be=0,me;(me=this.nextBreak(g,Be))<g.length;)Be=me,Se++;return Be<g.length&&Se++,Se};function Ee(g){return 1536<=g&&g<=1541||g==1757||g==1807||g==2274||g==3406||g==69821||70082<=g&&g<=70083||g==72250||72326<=g&&g<=72329||g==73030?S:g==13?e:g==10?t:0<=g&&g<=9||11<=g&&g<=12||14<=g&&g<=31||127<=g&&g<=159||g==173||g==1564||g==6158||g==8203||8206<=g&&g<=8207||g==8232||g==8233||8234<=g&&g<=8238||8288<=g&&g<=8292||g==8293||8294<=g&&g<=8303||55296<=g&&g<=57343||g==65279||65520<=g&&g<=65528||65529<=g&&g<=65531||113824<=g&&g<=113827||119155<=g&&g<=119162||g==917504||g==917505||917506<=g&&g<=917535||917632<=g&&g<=917759||918e3<=g&&g<=921599?r:768<=g&&g<=879||1155<=g&&g<=1159||1160<=g&&g<=1161||1425<=g&&g<=1469||g==1471||1473<=g&&g<=1474||1476<=g&&g<=1477||g==1479||1552<=g&&g<=1562||1611<=g&&g<=1631||g==1648||1750<=g&&g<=1756||1759<=g&&g<=1764||1767<=g&&g<=1768||1770<=g&&g<=1773||g==1809||1840<=g&&g<=1866||1958<=g&&g<=1968||2027<=g&&g<=2035||2070<=g&&g<=2073||2075<=g&&g<=2083||2085<=g&&g<=2087||2089<=g&&g<=2093||2137<=g&&g<=2139||2260<=g&&g<=2273||2275<=g&&g<=2306||g==2362||g==2364||2369<=g&&g<=2376||g==2381||2385<=g&&g<=2391||2402<=g&&g<=2403||g==2433||g==2492||g==2494||2497<=g&&g<=2500||g==2509||g==2519||2530<=g&&g<=2531||2561<=g&&g<=2562||g==2620||2625<=g&&g<=2626||2631<=g&&g<=2632||2635<=g&&g<=2637||g==2641||2672<=g&&g<=2673||g==2677||2689<=g&&g<=2690||g==2748||2753<=g&&g<=2757||2759<=g&&g<=2760||g==2765||2786<=g&&g<=2787||2810<=g&&g<=2815||g==2817||g==2876||g==2878||g==2879||2881<=g&&g<=2884||g==2893||g==2902||g==2903||2914<=g&&g<=2915||g==2946||g==3006||g==3008||g==3021||g==3031||g==3072||3134<=g&&g<=3136||3142<=g&&g<=3144||3146<=g&&g<=3149||3157<=g&&g<=3158||3170<=g&&g<=3171||g==3201||g==3260||g==3263||g==3266||g==3270||3276<=g&&g<=3277||3285<=g&&g<=3286||3298<=g&&g<=3299||3328<=g&&g<=3329||3387<=g&&g<=3388||g==3390||3393<=g&&g<=3396||g==3405||g==3415||3426<=g&&g<=3427||g==3530||g==3535||3538<=g&&g<=3540||g==3542||g==3551||g==3633||3636<=g&&g<=3642||3655<=g&&g<=3662||g==3761||3764<=g&&g<=3769||3771<=g&&g<=3772||3784<=g&&g<=3789||3864<=g&&g<=3865||g==3893||g==3895||g==3897||3953<=g&&g<=3966||3968<=g&&g<=3972||3974<=g&&g<=3975||3981<=g&&g<=3991||3993<=g&&g<=4028||g==4038||4141<=g&&g<=4144||4146<=g&&g<=4151||4153<=g&&g<=4154||4157<=g&&g<=4158||4184<=g&&g<=4185||4190<=g&&g<=4192||4209<=g&&g<=4212||g==4226||4229<=g&&g<=4230||g==4237||g==4253||4957<=g&&g<=4959||5906<=g&&g<=5908||5938<=g&&g<=5940||5970<=g&&g<=5971||6002<=g&&g<=6003||6068<=g&&g<=6069||6071<=g&&g<=6077||g==6086||6089<=g&&g<=6099||g==6109||6155<=g&&g<=6157||6277<=g&&g<=6278||g==6313||6432<=g&&g<=6434||6439<=g&&g<=6440||g==6450||6457<=g&&g<=6459||6679<=g&&g<=6680||g==6683||g==6742||6744<=g&&g<=6750||g==6752||g==6754||6757<=g&&g<=6764||6771<=g&&g<=6780||g==6783||6832<=g&&g<=6845||g==6846||6912<=g&&g<=6915||g==6964||6966<=g&&g<=6970||g==6972||g==6978||7019<=g&&g<=7027||7040<=g&&g<=7041||7074<=g&&g<=7077||7080<=g&&g<=7081||7083<=g&&g<=7085||g==7142||7144<=g&&g<=7145||g==7149||7151<=g&&g<=7153||7212<=g&&g<=7219||7222<=g&&g<=7223||7376<=g&&g<=7378||7380<=g&&g<=7392||7394<=g&&g<=7400||g==7405||g==7412||7416<=g&&g<=7417||7616<=g&&g<=7673||7675<=g&&g<=7679||g==8204||8400<=g&&g<=8412||8413<=g&&g<=8416||g==8417||8418<=g&&g<=8420||8421<=g&&g<=8432||11503<=g&&g<=11505||g==11647||11744<=g&&g<=11775||12330<=g&&g<=12333||12334<=g&&g<=12335||12441<=g&&g<=12442||g==42607||42608<=g&&g<=42610||42612<=g&&g<=42621||42654<=g&&g<=42655||42736<=g&&g<=42737||g==43010||g==43014||g==43019||43045<=g&&g<=43046||43204<=g&&g<=43205||43232<=g&&g<=43249||43302<=g&&g<=43309||43335<=g&&g<=43345||43392<=g&&g<=43394||g==43443||43446<=g&&g<=43449||g==43452||g==43493||43561<=g&&g<=43566||43569<=g&&g<=43570||43573<=g&&g<=43574||g==43587||g==43596||g==43644||g==43696||43698<=g&&g<=43700||43703<=g&&g<=43704||43710<=g&&g<=43711||g==43713||43756<=g&&g<=43757||g==43766||g==44005||g==44008||g==44013||g==64286||65024<=g&&g<=65039||65056<=g&&g<=65071||65438<=g&&g<=65439||g==66045||g==66272||66422<=g&&g<=66426||68097<=g&&g<=68099||68101<=g&&g<=68102||68108<=g&&g<=68111||68152<=g&&g<=68154||g==68159||68325<=g&&g<=68326||g==69633||69688<=g&&g<=69702||69759<=g&&g<=69761||69811<=g&&g<=69814||69817<=g&&g<=69818||69888<=g&&g<=69890||69927<=g&&g<=69931||69933<=g&&g<=69940||g==70003||70016<=g&&g<=70017||70070<=g&&g<=70078||70090<=g&&g<=70092||70191<=g&&g<=70193||g==70196||70198<=g&&g<=70199||g==70206||g==70367||70371<=g&&g<=70378||70400<=g&&g<=70401||g==70460||g==70462||g==70464||g==70487||70502<=g&&g<=70508||70512<=g&&g<=70516||70712<=g&&g<=70719||70722<=g&&g<=70724||g==70726||g==70832||70835<=g&&g<=70840||g==70842||g==70845||70847<=g&&g<=70848||70850<=g&&g<=70851||g==71087||71090<=g&&g<=71093||71100<=g&&g<=71101||71103<=g&&g<=71104||71132<=g&&g<=71133||71219<=g&&g<=71226||g==71229||71231<=g&&g<=71232||g==71339||g==71341||71344<=g&&g<=71349||g==71351||71453<=g&&g<=71455||71458<=g&&g<=71461||71463<=g&&g<=71467||72193<=g&&g<=72198||72201<=g&&g<=72202||72243<=g&&g<=72248||72251<=g&&g<=72254||g==72263||72273<=g&&g<=72278||72281<=g&&g<=72283||72330<=g&&g<=72342||72344<=g&&g<=72345||72752<=g&&g<=72758||72760<=g&&g<=72765||g==72767||72850<=g&&g<=72871||72874<=g&&g<=72880||72882<=g&&g<=72883||72885<=g&&g<=72886||73009<=g&&g<=73014||g==73018||73020<=g&&g<=73021||73023<=g&&g<=73029||g==73031||92912<=g&&g<=92916||92976<=g&&g<=92982||94095<=g&&g<=94098||113821<=g&&g<=113822||g==119141||119143<=g&&g<=119145||119150<=g&&g<=119154||119163<=g&&g<=119170||119173<=g&&g<=119179||119210<=g&&g<=119213||119362<=g&&g<=119364||121344<=g&&g<=121398||121403<=g&&g<=121452||g==121461||g==121476||121499<=g&&g<=121503||121505<=g&&g<=121519||122880<=g&&g<=122886||122888<=g&&g<=122904||122907<=g&&g<=122913||122915<=g&&g<=122916||122918<=g&&g<=122922||125136<=g&&g<=125142||125252<=g&&g<=125258||917536<=g&&g<=917631||917760<=g&&g<=917999?s:127462<=g&&g<=127487?a:g==2307||g==2363||2366<=g&&g<=2368||2377<=g&&g<=2380||2382<=g&&g<=2383||2434<=g&&g<=2435||2495<=g&&g<=2496||2503<=g&&g<=2504||2507<=g&&g<=2508||g==2563||2622<=g&&g<=2624||g==2691||2750<=g&&g<=2752||g==2761||2763<=g&&g<=2764||2818<=g&&g<=2819||g==2880||2887<=g&&g<=2888||2891<=g&&g<=2892||g==3007||3009<=g&&g<=3010||3014<=g&&g<=3016||3018<=g&&g<=3020||3073<=g&&g<=3075||3137<=g&&g<=3140||3202<=g&&g<=3203||g==3262||3264<=g&&g<=3265||3267<=g&&g<=3268||3271<=g&&g<=3272||3274<=g&&g<=3275||3330<=g&&g<=3331||3391<=g&&g<=3392||3398<=g&&g<=3400||3402<=g&&g<=3404||3458<=g&&g<=3459||3536<=g&&g<=3537||3544<=g&&g<=3550||3570<=g&&g<=3571||g==3635||g==3763||3902<=g&&g<=3903||g==3967||g==4145||4155<=g&&g<=4156||4182<=g&&g<=4183||g==4228||g==6070||6078<=g&&g<=6085||6087<=g&&g<=6088||6435<=g&&g<=6438||6441<=g&&g<=6443||6448<=g&&g<=6449||6451<=g&&g<=6456||6681<=g&&g<=6682||g==6741||g==6743||6765<=g&&g<=6770||g==6916||g==6965||g==6971||6973<=g&&g<=6977||6979<=g&&g<=6980||g==7042||g==7073||7078<=g&&g<=7079||g==7082||g==7143||7146<=g&&g<=7148||g==7150||7154<=g&&g<=7155||7204<=g&&g<=7211||7220<=g&&g<=7221||g==7393||7410<=g&&g<=7411||g==7415||43043<=g&&g<=43044||g==43047||43136<=g&&g<=43137||43188<=g&&g<=43203||43346<=g&&g<=43347||g==43395||43444<=g&&g<=43445||43450<=g&&g<=43451||43453<=g&&g<=43456||43567<=g&&g<=43568||43571<=g&&g<=43572||g==43597||g==43755||43758<=g&&g<=43759||g==43765||44003<=g&&g<=44004||44006<=g&&g<=44007||44009<=g&&g<=44010||g==44012||g==69632||g==69634||g==69762||69808<=g&&g<=69810||69815<=g&&g<=69816||g==69932||g==70018||70067<=g&&g<=70069||70079<=g&&g<=70080||70188<=g&&g<=70190||70194<=g&&g<=70195||g==70197||70368<=g&&g<=70370||70402<=g&&g<=70403||g==70463||70465<=g&&g<=70468||70471<=g&&g<=70472||70475<=g&&g<=70477||70498<=g&&g<=70499||70709<=g&&g<=70711||70720<=g&&g<=70721||g==70725||70833<=g&&g<=70834||g==70841||70843<=g&&g<=70844||g==70846||g==70849||71088<=g&&g<=71089||71096<=g&&g<=71099||g==71102||71216<=g&&g<=71218||71227<=g&&g<=71228||g==71230||g==71340||71342<=g&&g<=71343||g==71350||71456<=g&&g<=71457||g==71462||72199<=g&&g<=72200||g==72249||72279<=g&&g<=72280||g==72343||g==72751||g==72766||g==72873||g==72881||g==72884||94033<=g&&g<=94078||g==119142||g==119149?n:4352<=g&&g<=4447||43360<=g&&g<=43388?c:4448<=g&&g<=4519||55216<=g&&g<=55238?f:4520<=g&&g<=4607||55243<=g&&g<=55291?p:g==44032||g==44060||g==44088||g==44116||g==44144||g==44172||g==44200||g==44228||g==44256||g==44284||g==44312||g==44340||g==44368||g==44396||g==44424||g==44452||g==44480||g==44508||g==44536||g==44564||g==44592||g==44620||g==44648||g==44676||g==44704||g==44732||g==44760||g==44788||g==44816||g==44844||g==44872||g==44900||g==44928||g==44956||g==44984||g==45012||g==45040||g==45068||g==45096||g==45124||g==45152||g==45180||g==45208||g==45236||g==45264||g==45292||g==45320||g==45348||g==45376||g==45404||g==45432||g==45460||g==45488||g==45516||g==45544||g==45572||g==45600||g==45628||g==45656||g==45684||g==45712||g==45740||g==45768||g==45796||g==45824||g==45852||g==45880||g==45908||g==45936||g==45964||g==45992||g==46020||g==46048||g==46076||g==46104||g==46132||g==46160||g==46188||g==46216||g==46244||g==46272||g==46300||g==46328||g==46356||g==46384||g==46412||g==46440||g==46468||g==46496||g==46524||g==46552||g==46580||g==46608||g==46636||g==46664||g==46692||g==46720||g==46748||g==46776||g==46804||g==46832||g==46860||g==46888||g==46916||g==46944||g==46972||g==47e3||g==47028||g==47056||g==47084||g==47112||g==47140||g==47168||g==47196||g==47224||g==47252||g==47280||g==47308||g==47336||g==47364||g==47392||g==47420||g==47448||g==47476||g==47504||g==47532||g==47560||g==47588||g==47616||g==47644||g==47672||g==47700||g==47728||g==47756||g==47784||g==47812||g==47840||g==47868||g==47896||g==47924||g==47952||g==47980||g==48008||g==48036||g==48064||g==48092||g==48120||g==48148||g==48176||g==48204||g==48232||g==48260||g==48288||g==48316||g==48344||g==48372||g==48400||g==48428||g==48456||g==48484||g==48512||g==48540||g==48568||g==48596||g==48624||g==48652||g==48680||g==48708||g==48736||g==48764||g==48792||g==48820||g==48848||g==48876||g==48904||g==48932||g==48960||g==48988||g==49016||g==49044||g==49072||g==49100||g==49128||g==49156||g==49184||g==49212||g==49240||g==49268||g==49296||g==49324||g==49352||g==49380||g==49408||g==49436||g==49464||g==49492||g==49520||g==49548||g==49576||g==49604||g==49632||g==49660||g==49688||g==49716||g==49744||g==49772||g==49800||g==49828||g==49856||g==49884||g==49912||g==49940||g==49968||g==49996||g==50024||g==50052||g==50080||g==50108||g==50136||g==50164||g==50192||g==50220||g==50248||g==50276||g==50304||g==50332||g==50360||g==50388||g==50416||g==50444||g==50472||g==50500||g==50528||g==50556||g==50584||g==50612||g==50640||g==50668||g==50696||g==50724||g==50752||g==50780||g==50808||g==50836||g==50864||g==50892||g==50920||g==50948||g==50976||g==51004||g==51032||g==51060||g==51088||g==51116||g==51144||g==51172||g==51200||g==51228||g==51256||g==51284||g==51312||g==51340||g==51368||g==51396||g==51424||g==51452||g==51480||g==51508||g==51536||g==51564||g==51592||g==51620||g==51648||g==51676||g==51704||g==51732||g==51760||g==51788||g==51816||g==51844||g==51872||g==51900||g==51928||g==51956||g==51984||g==52012||g==52040||g==52068||g==52096||g==52124||g==52152||g==52180||g==52208||g==52236||g==52264||g==52292||g==52320||g==52348||g==52376||g==52404||g==52432||g==52460||g==52488||g==52516||g==52544||g==52572||g==52600||g==52628||g==52656||g==52684||g==52712||g==52740||g==52768||g==52796||g==52824||g==52852||g==52880||g==52908||g==52936||g==52964||g==52992||g==53020||g==53048||g==53076||g==53104||g==53132||g==53160||g==53188||g==53216||g==53244||g==53272||g==53300||g==53328||g==53356||g==53384||g==53412||g==53440||g==53468||g==53496||g==53524||g==53552||g==53580||g==53608||g==53636||g==53664||g==53692||g==53720||g==53748||g==53776||g==53804||g==53832||g==53860||g==53888||g==53916||g==53944||g==53972||g==54e3||g==54028||g==54056||g==54084||g==54112||g==54140||g==54168||g==54196||g==54224||g==54252||g==54280||g==54308||g==54336||g==54364||g==54392||g==54420||g==54448||g==54476||g==54504||g==54532||g==54560||g==54588||g==54616||g==54644||g==54672||g==54700||g==54728||g==54756||g==54784||g==54812||g==54840||g==54868||g==54896||g==54924||g==54952||g==54980||g==55008||g==55036||g==55064||g==55092||g==55120||g==55148||g==55176?h:44033<=g&&g<=44059||44061<=g&&g<=44087||44089<=g&&g<=44115||44117<=g&&g<=44143||44145<=g&&g<=44171||44173<=g&&g<=44199||44201<=g&&g<=44227||44229<=g&&g<=44255||44257<=g&&g<=44283||44285<=g&&g<=44311||44313<=g&&g<=44339||44341<=g&&g<=44367||44369<=g&&g<=44395||44397<=g&&g<=44423||44425<=g&&g<=44451||44453<=g&&g<=44479||44481<=g&&g<=44507||44509<=g&&g<=44535||44537<=g&&g<=44563||44565<=g&&g<=44591||44593<=g&&g<=44619||44621<=g&&g<=44647||44649<=g&&g<=44675||44677<=g&&g<=44703||44705<=g&&g<=44731||44733<=g&&g<=44759||44761<=g&&g<=44787||44789<=g&&g<=44815||44817<=g&&g<=44843||44845<=g&&g<=44871||44873<=g&&g<=44899||44901<=g&&g<=44927||44929<=g&&g<=44955||44957<=g&&g<=44983||44985<=g&&g<=45011||45013<=g&&g<=45039||45041<=g&&g<=45067||45069<=g&&g<=45095||45097<=g&&g<=45123||45125<=g&&g<=45151||45153<=g&&g<=45179||45181<=g&&g<=45207||45209<=g&&g<=45235||45237<=g&&g<=45263||45265<=g&&g<=45291||45293<=g&&g<=45319||45321<=g&&g<=45347||45349<=g&&g<=45375||45377<=g&&g<=45403||45405<=g&&g<=45431||45433<=g&&g<=45459||45461<=g&&g<=45487||45489<=g&&g<=45515||45517<=g&&g<=45543||45545<=g&&g<=45571||45573<=g&&g<=45599||45601<=g&&g<=45627||45629<=g&&g<=45655||45657<=g&&g<=45683||45685<=g&&g<=45711||45713<=g&&g<=45739||45741<=g&&g<=45767||45769<=g&&g<=45795||45797<=g&&g<=45823||45825<=g&&g<=45851||45853<=g&&g<=45879||45881<=g&&g<=45907||45909<=g&&g<=45935||45937<=g&&g<=45963||45965<=g&&g<=45991||45993<=g&&g<=46019||46021<=g&&g<=46047||46049<=g&&g<=46075||46077<=g&&g<=46103||46105<=g&&g<=46131||46133<=g&&g<=46159||46161<=g&&g<=46187||46189<=g&&g<=46215||46217<=g&&g<=46243||46245<=g&&g<=46271||46273<=g&&g<=46299||46301<=g&&g<=46327||46329<=g&&g<=46355||46357<=g&&g<=46383||46385<=g&&g<=46411||46413<=g&&g<=46439||46441<=g&&g<=46467||46469<=g&&g<=46495||46497<=g&&g<=46523||46525<=g&&g<=46551||46553<=g&&g<=46579||46581<=g&&g<=46607||46609<=g&&g<=46635||46637<=g&&g<=46663||46665<=g&&g<=46691||46693<=g&&g<=46719||46721<=g&&g<=46747||46749<=g&&g<=46775||46777<=g&&g<=46803||46805<=g&&g<=46831||46833<=g&&g<=46859||46861<=g&&g<=46887||46889<=g&&g<=46915||46917<=g&&g<=46943||46945<=g&&g<=46971||46973<=g&&g<=46999||47001<=g&&g<=47027||47029<=g&&g<=47055||47057<=g&&g<=47083||47085<=g&&g<=47111||47113<=g&&g<=47139||47141<=g&&g<=47167||47169<=g&&g<=47195||47197<=g&&g<=47223||47225<=g&&g<=47251||47253<=g&&g<=47279||47281<=g&&g<=47307||47309<=g&&g<=47335||47337<=g&&g<=47363||47365<=g&&g<=47391||47393<=g&&g<=47419||47421<=g&&g<=47447||47449<=g&&g<=47475||47477<=g&&g<=47503||47505<=g&&g<=47531||47533<=g&&g<=47559||47561<=g&&g<=47587||47589<=g&&g<=47615||47617<=g&&g<=47643||47645<=g&&g<=47671||47673<=g&&g<=47699||47701<=g&&g<=47727||47729<=g&&g<=47755||47757<=g&&g<=47783||47785<=g&&g<=47811||47813<=g&&g<=47839||47841<=g&&g<=47867||47869<=g&&g<=47895||47897<=g&&g<=47923||47925<=g&&g<=47951||47953<=g&&g<=47979||47981<=g&&g<=48007||48009<=g&&g<=48035||48037<=g&&g<=48063||48065<=g&&g<=48091||48093<=g&&g<=48119||48121<=g&&g<=48147||48149<=g&&g<=48175||48177<=g&&g<=48203||48205<=g&&g<=48231||48233<=g&&g<=48259||48261<=g&&g<=48287||48289<=g&&g<=48315||48317<=g&&g<=48343||48345<=g&&g<=48371||48373<=g&&g<=48399||48401<=g&&g<=48427||48429<=g&&g<=48455||48457<=g&&g<=48483||48485<=g&&g<=48511||48513<=g&&g<=48539||48541<=g&&g<=48567||48569<=g&&g<=48595||48597<=g&&g<=48623||48625<=g&&g<=48651||48653<=g&&g<=48679||48681<=g&&g<=48707||48709<=g&&g<=48735||48737<=g&&g<=48763||48765<=g&&g<=48791||48793<=g&&g<=48819||48821<=g&&g<=48847||48849<=g&&g<=48875||48877<=g&&g<=48903||48905<=g&&g<=48931||48933<=g&&g<=48959||48961<=g&&g<=48987||48989<=g&&g<=49015||49017<=g&&g<=49043||49045<=g&&g<=49071||49073<=g&&g<=49099||49101<=g&&g<=49127||49129<=g&&g<=49155||49157<=g&&g<=49183||49185<=g&&g<=49211||49213<=g&&g<=49239||49241<=g&&g<=49267||49269<=g&&g<=49295||49297<=g&&g<=49323||49325<=g&&g<=49351||49353<=g&&g<=49379||49381<=g&&g<=49407||49409<=g&&g<=49435||49437<=g&&g<=49463||49465<=g&&g<=49491||49493<=g&&g<=49519||49521<=g&&g<=49547||49549<=g&&g<=49575||49577<=g&&g<=49603||49605<=g&&g<=49631||49633<=g&&g<=49659||49661<=g&&g<=49687||49689<=g&&g<=49715||49717<=g&&g<=49743||49745<=g&&g<=49771||49773<=g&&g<=49799||49801<=g&&g<=49827||49829<=g&&g<=49855||49857<=g&&g<=49883||49885<=g&&g<=49911||49913<=g&&g<=49939||49941<=g&&g<=49967||49969<=g&&g<=49995||49997<=g&&g<=50023||50025<=g&&g<=50051||50053<=g&&g<=50079||50081<=g&&g<=50107||50109<=g&&g<=50135||50137<=g&&g<=50163||50165<=g&&g<=50191||50193<=g&&g<=50219||50221<=g&&g<=50247||50249<=g&&g<=50275||50277<=g&&g<=50303||50305<=g&&g<=50331||50333<=g&&g<=50359||50361<=g&&g<=50387||50389<=g&&g<=50415||50417<=g&&g<=50443||50445<=g&&g<=50471||50473<=g&&g<=50499||50501<=g&&g<=50527||50529<=g&&g<=50555||50557<=g&&g<=50583||50585<=g&&g<=50611||50613<=g&&g<=50639||50641<=g&&g<=50667||50669<=g&&g<=50695||50697<=g&&g<=50723||50725<=g&&g<=50751||50753<=g&&g<=50779||50781<=g&&g<=50807||50809<=g&&g<=50835||50837<=g&&g<=50863||50865<=g&&g<=50891||50893<=g&&g<=50919||50921<=g&&g<=50947||50949<=g&&g<=50975||50977<=g&&g<=51003||51005<=g&&g<=51031||51033<=g&&g<=51059||51061<=g&&g<=51087||51089<=g&&g<=51115||51117<=g&&g<=51143||51145<=g&&g<=51171||51173<=g&&g<=51199||51201<=g&&g<=51227||51229<=g&&g<=51255||51257<=g&&g<=51283||51285<=g&&g<=51311||51313<=g&&g<=51339||51341<=g&&g<=51367||51369<=g&&g<=51395||51397<=g&&g<=51423||51425<=g&&g<=51451||51453<=g&&g<=51479||51481<=g&&g<=51507||51509<=g&&g<=51535||51537<=g&&g<=51563||51565<=g&&g<=51591||51593<=g&&g<=51619||51621<=g&&g<=51647||51649<=g&&g<=51675||51677<=g&&g<=51703||51705<=g&&g<=51731||51733<=g&&g<=51759||51761<=g&&g<=51787||51789<=g&&g<=51815||51817<=g&&g<=51843||51845<=g&&g<=51871||51873<=g&&g<=51899||51901<=g&&g<=51927||51929<=g&&g<=51955||51957<=g&&g<=51983||51985<=g&&g<=52011||52013<=g&&g<=52039||52041<=g&&g<=52067||52069<=g&&g<=52095||52097<=g&&g<=52123||52125<=g&&g<=52151||52153<=g&&g<=52179||52181<=g&&g<=52207||52209<=g&&g<=52235||52237<=g&&g<=52263||52265<=g&&g<=52291||52293<=g&&g<=52319||52321<=g&&g<=52347||52349<=g&&g<=52375||52377<=g&&g<=52403||52405<=g&&g<=52431||52433<=g&&g<=52459||52461<=g&&g<=52487||52489<=g&&g<=52515||52517<=g&&g<=52543||52545<=g&&g<=52571||52573<=g&&g<=52599||52601<=g&&g<=52627||52629<=g&&g<=52655||52657<=g&&g<=52683||52685<=g&&g<=52711||52713<=g&&g<=52739||52741<=g&&g<=52767||52769<=g&&g<=52795||52797<=g&&g<=52823||52825<=g&&g<=52851||52853<=g&&g<=52879||52881<=g&&g<=52907||52909<=g&&g<=52935||52937<=g&&g<=52963||52965<=g&&g<=52991||52993<=g&&g<=53019||53021<=g&&g<=53047||53049<=g&&g<=53075||53077<=g&&g<=53103||53105<=g&&g<=53131||53133<=g&&g<=53159||53161<=g&&g<=53187||53189<=g&&g<=53215||53217<=g&&g<=53243||53245<=g&&g<=53271||53273<=g&&g<=53299||53301<=g&&g<=53327||53329<=g&&g<=53355||53357<=g&&g<=53383||53385<=g&&g<=53411||53413<=g&&g<=53439||53441<=g&&g<=53467||53469<=g&&g<=53495||53497<=g&&g<=53523||53525<=g&&g<=53551||53553<=g&&g<=53579||53581<=g&&g<=53607||53609<=g&&g<=53635||53637<=g&&g<=53663||53665<=g&&g<=53691||53693<=g&&g<=53719||53721<=g&&g<=53747||53749<=g&&g<=53775||53777<=g&&g<=53803||53805<=g&&g<=53831||53833<=g&&g<=53859||53861<=g&&g<=53887||53889<=g&&g<=53915||53917<=g&&g<=53943||53945<=g&&g<=53971||53973<=g&&g<=53999||54001<=g&&g<=54027||54029<=g&&g<=54055||54057<=g&&g<=54083||54085<=g&&g<=54111||54113<=g&&g<=54139||54141<=g&&g<=54167||54169<=g&&g<=54195||54197<=g&&g<=54223||54225<=g&&g<=54251||54253<=g&&g<=54279||54281<=g&&g<=54307||54309<=g&&g<=54335||54337<=g&&g<=54363||54365<=g&&g<=54391||54393<=g&&g<=54419||54421<=g&&g<=54447||54449<=g&&g<=54475||54477<=g&&g<=54503||54505<=g&&g<=54531||54533<=g&&g<=54559||54561<=g&&g<=54587||54589<=g&&g<=54615||54617<=g&&g<=54643||54645<=g&&g<=54671||54673<=g&&g<=54699||54701<=g&&g<=54727||54729<=g&&g<=54755||54757<=g&&g<=54783||54785<=g&&g<=54811||54813<=g&&g<=54839||54841<=g&&g<=54867||54869<=g&&g<=54895||54897<=g&&g<=54923||54925<=g&&g<=54951||54953<=g&&g<=54979||54981<=g&&g<=55007||55009<=g&&g<=55035||55037<=g&&g<=55063||55065<=g&&g<=55091||55093<=g&&g<=55119||55121<=g&&g<=55147||55149<=g&&g<=55175||55177<=g&&g<=55203?E:g==9757||g==9977||9994<=g&&g<=9997||g==127877||127938<=g&&g<=127940||g==127943||127946<=g&&g<=127948||128066<=g&&g<=128067||128070<=g&&g<=128080||g==128110||128112<=g&&g<=128120||g==128124||128129<=g&&g<=128131||128133<=g&&g<=128135||g==128170||128372<=g&&g<=128373||g==128378||g==128400||128405<=g&&g<=128406||128581<=g&&g<=128583||128587<=g&&g<=128591||g==128675||128692<=g&&g<=128694||g==128704||g==128716||129304<=g&&g<=129308||129310<=g&&g<=129311||g==129318||129328<=g&&g<=129337||129341<=g&&g<=129342||129489<=g&&g<=129501?x:127995<=g&&g<=127999?I:g==8205?T:g==9792||g==9794||9877<=g&&g<=9878||g==9992||g==10084||g==127752||g==127806||g==127859||g==127891||g==127908||g==127912||g==127979||g==127981||g==128139||128187<=g&&g<=128188||g==128295||g==128300||g==128488||g==128640||g==128658?O:128102<=g&&g<=128105?U:C}return this}typeof RR<\"u\"&&RR.exports&&(RR.exports=qtt)});var ppe=G((_Mt,Ape)=>{var Wtt=/^(.*?)(\\x1b\\[[^m]+m|\\x1b\\]8;;.*?(\\x1b\\\\|\\u0007))/,TR;function Vtt(){if(TR)return TR;if(typeof Intl.Segmenter<\"u\"){let e=new Intl.Segmenter(\"en\",{granularity:\"grapheme\"});return TR=t=>Array.from(e.segment(t),({segment:r})=>r)}else{let e=fpe(),t=new e;return TR=r=>t.splitGraphemes(r)}}Ape.exports=(e,t=0,r=e.length)=>{if(t<0||r<0)throw new RangeError(\"Negative indices aren't supported by this implementation\");let s=r-t,a=\"\",n=0,c=0;for(;e.length>0;){let f=e.match(Wtt)||[e,e,void 0],p=Vtt()(f[1]),h=Math.min(t-n,p.length);p=p.slice(h);let E=Math.min(s-c,p.length);a+=p.slice(0,E).join(\"\"),n+=h,c+=E,typeof f[2]<\"u\"&&(a+=f[2]),e=e.slice(f[0].length)}return a}});var An,uv=Ze(()=>{An=process.env.YARN_IS_TEST_ENV?\"0.0.0\":\"4.13.0\"});function Epe(e,{configuration:t,json:r}){if(!t.get(\"enableMessageNames\"))return\"\";let a=Kf(e===null?0:e);return!r&&e===null?jt(t,a,\"grey\"):a}function xj(e,{configuration:t,json:r}){let s=Epe(e,{configuration:t,json:r});if(!s||e===null||e===0)return s;let a=Br[e],n=`https://yarnpkg.com/advanced/error-codes#${s}---${a}`.toLowerCase();return XE(t,s,n)}async function PI({configuration:e,stdout:t,forceError:r},s){let a=await Ot.start({configuration:e,stdout:t,includeFooter:!1},async n=>{let c=!1,f=!1;for(let p of s)typeof p.option<\"u\"&&(p.error||r?(f=!0,n.reportError(50,p.message)):(c=!0,n.reportWarning(50,p.message)),p.callback?.());c&&!f&&n.reportSeparator()});return a.hasErrors()?a.exitCode():null}var mpe,FR,Ytt,hpe,gpe,v0,ype,dpe,Ktt,Jtt,NR,ztt,Ot,fv=Ze(()=>{mpe=et(ppe()),FR=et(Rd());Gx();Tc();uv();kc();Ytt=\"\\xB7\",hpe=[\"\\u280B\",\"\\u2819\",\"\\u2839\",\"\\u2838\",\"\\u283C\",\"\\u2834\",\"\\u2826\",\"\\u2827\",\"\\u2807\",\"\\u280F\"],gpe=80,v0=FR.default.GITHUB_ACTIONS?{start:e=>`::group::${e}\n`,end:e=>`::endgroup::\n`}:FR.default.TRAVIS?{start:e=>`travis_fold:start:${e}\n`,end:e=>`travis_fold:end:${e}\n`}:FR.default.GITLAB?{start:e=>`section_start:${Math.floor(Date.now()/1e3)}:${e.toLowerCase().replace(/\\W+/g,\"_\")}[collapsed=true]\\r\\x1B[0K${e}\n`,end:e=>`section_end:${Math.floor(Date.now()/1e3)}:${e.toLowerCase().replace(/\\W+/g,\"_\")}\\r\\x1B[0K`}:null,ype=v0!==null,dpe=new Date,Ktt=[\"iTerm.app\",\"Apple_Terminal\",\"WarpTerminal\",\"vscode\"].includes(process.env.TERM_PROGRAM)||!!process.env.WT_SESSION,Jtt=e=>e,NR=Jtt({patrick:{date:[17,3],chars:[\"\\u{1F340}\",\"\\u{1F331}\"],size:40},simba:{date:[19,7],chars:[\"\\u{1F981}\",\"\\u{1F334}\"],size:40},jack:{date:[31,10],chars:[\"\\u{1F383}\",\"\\u{1F987}\"],size:40},hogsfather:{date:[31,12],chars:[\"\\u{1F389}\",\"\\u{1F384}\"],size:40},default:{chars:[\"=\",\"-\"],size:80}}),ztt=Ktt&&Object.keys(NR).find(e=>{let t=NR[e];return!(t.date&&(t.date[0]!==dpe.getDate()||t.date[1]!==dpe.getMonth()+1))})||\"default\";Ot=class extends yo{constructor({configuration:r,stdout:s,json:a=!1,forceSectionAlignment:n=!1,includeNames:c=!0,includePrefix:f=!0,includeFooter:p=!0,includeLogs:h=!a,includeInfos:E=h,includeWarnings:C=h}){super();this.uncommitted=new Set;this.warningCount=0;this.errorCount=0;this.timerFooter=[];this.startTime=Date.now();this.indent=0;this.level=0;this.progress=new Map;this.progressTime=0;this.progressFrame=0;this.progressTimeout=null;this.progressStyle=null;this.progressMaxScaledSize=null;if(S2(this,{configuration:r}),this.configuration=r,this.forceSectionAlignment=n,this.includeNames=c,this.includePrefix=f,this.includeFooter=p,this.includeInfos=E,this.includeWarnings=C,this.json=a,this.stdout=s,r.get(\"enableProgressBars\")&&!a&&s.isTTY&&s.columns>22){let S=r.get(\"progressBarStyle\")||ztt;if(!Object.hasOwn(NR,S))throw new Error(\"Assertion failed: Invalid progress bar style\");this.progressStyle=NR[S];let x=Math.min(this.getRecommendedLength(),80);this.progressMaxScaledSize=Math.floor(this.progressStyle.size*x/80)}}static async start(r,s){let a=new this(r),n=process.emitWarning;process.emitWarning=(c,f)=>{if(typeof c!=\"string\"){let h=c;c=h.message,f=f??h.name}let p=typeof f<\"u\"?`${f}: ${c}`:c;a.reportWarning(0,p)},r.includeVersion&&a.reportInfo(0,Kd(r.configuration,`Yarn ${An}`,2));try{await s(a)}catch(c){a.reportExceptionOnce(c)}finally{await a.finalize(),process.emitWarning=n}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}getRecommendedLength(){let s=this.progressStyle!==null?this.stdout.columns-1:super.getRecommendedLength();return Math.max(40,s-12-this.indent*2)}startSectionSync({reportHeader:r,reportFooter:s,skipIfEmpty:a},n){let c={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(c):(c.action(),c.committed=!0);let f=Date.now();try{return n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(c),c.committed&&s?.(p-f)}}async startSectionPromise({reportHeader:r,reportFooter:s,skipIfEmpty:a},n){let c={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(c):(c.action(),c.committed=!0);let f=Date.now();try{return await n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(c),c.committed&&s?.(p-f)}}startTimerImpl(r,s,a){return{cb:typeof s==\"function\"?s:a,reportHeader:()=>{this.level+=1,this.reportInfo(null,`\\u250C ${r}`),this.indent+=1,v0!==null&&!this.json&&this.includeInfos&&this.stdout.write(v0.start(r))},reportFooter:f=>{if(this.indent-=1,v0!==null&&!this.json&&this.includeInfos){this.stdout.write(v0.end(r));for(let p of this.timerFooter)p()}this.configuration.get(\"enableTimers\")&&f>200?this.reportInfo(null,`\\u2514 Completed in ${jt(this.configuration,f,gt.DURATION)}`):this.reportInfo(null,\"\\u2514 Completed\"),this.level-=1},skipIfEmpty:(typeof s==\"function\"?{}:s).skipIfEmpty}}startTimerSync(r,s,a){let{cb:n,...c}=this.startTimerImpl(r,s,a);return this.startSectionSync(c,n)}async startTimerPromise(r,s,a){let{cb:n,...c}=this.startTimerImpl(r,s,a);return this.startSectionPromise(c,n)}reportSeparator(){this.indent===0?this.writeLine(\"\"):this.reportInfo(null,\"\")}reportInfo(r,s){if(!this.includeInfos)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:\"\",c=`${this.formatPrefix(n,\"blueBright\")}${s}`;this.json?this.reportJson({type:\"info\",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:s}):this.writeLine(c)}reportWarning(r,s){if(this.warningCount+=1,!this.includeWarnings)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:\"\";this.json?this.reportJson({type:\"warning\",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:s}):this.writeLine(`${this.formatPrefix(n,\"yellowBright\")}${s}`)}reportError(r,s){this.errorCount+=1,this.timerFooter.push(()=>this.reportErrorImpl(r,s)),this.reportErrorImpl(r,s)}reportErrorImpl(r,s){this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:\"\";this.json?this.reportJson({type:\"error\",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:s}):this.writeLine(`${this.formatPrefix(n,\"redBright\")}${s}`,{truncate:!1})}reportFold(r,s){if(!v0)return;let a=`${v0.start(r)}${s}${v0.end(r)}`;this.timerFooter.push(()=>this.stdout.write(a))}reportProgress(r){if(this.progressStyle===null)return{...Promise.resolve(),stop:()=>{}};if(r.hasProgress&&r.hasTitle)throw new Error(\"Unimplemented: Progress bars can't have both progress and titles.\");let s=!1,a=Promise.resolve().then(async()=>{let c={progress:r.hasProgress?0:void 0,title:r.hasTitle?\"\":void 0};this.progress.set(r,{definition:c,lastScaledSize:r.hasProgress?-1:void 0,lastTitle:void 0}),this.refreshProgress({delta:-1});for await(let{progress:f,title:p}of r)s||c.progress===f&&c.title===p||(c.progress=f,c.title=p,this.refreshProgress());n()}),n=()=>{s||(s=!0,this.progress.delete(r),this.refreshProgress({delta:1}))};return{...a,stop:n}}reportJson(r){this.json&&this.writeLine(`${JSON.stringify(r)}`)}async finalize(){if(!this.includeFooter)return;let r=\"\";this.errorCount>0?r=\"Failed with errors\":this.warningCount>0?r=\"Done with warnings\":r=\"Done\";let s=jt(this.configuration,Date.now()-this.startTime,gt.DURATION),a=this.configuration.get(\"enableTimers\")?`${r} in ${s}`:r;this.errorCount>0?this.reportError(0,a):this.warningCount>0?this.reportWarning(0,a):this.reportInfo(0,a)}writeLine(r,{truncate:s}={}){this.clearProgress({clear:!0}),this.stdout.write(`${this.truncate(r,{truncate:s})}\n`),this.writeProgress()}writeLines(r,{truncate:s}={}){this.clearProgress({delta:r.length});for(let a of r)this.stdout.write(`${this.truncate(a,{truncate:s})}\n`);this.writeProgress()}commit(){let r=this.uncommitted;this.uncommitted=new Set;for(let s of r)s.committed=!0,s.action()}clearProgress({delta:r=0,clear:s=!1}){this.progressStyle!==null&&this.progress.size+r>0&&(this.stdout.write(`\\x1B[${this.progress.size+r}A`),(r>0||s)&&this.stdout.write(\"\\x1B[0J\"))}writeProgress(){if(this.progressStyle===null||(this.progressTimeout!==null&&clearTimeout(this.progressTimeout),this.progressTimeout=null,this.progress.size===0))return;let r=Date.now();r-this.progressTime>gpe&&(this.progressFrame=(this.progressFrame+1)%hpe.length,this.progressTime=r);let s=hpe[this.progressFrame];for(let a of this.progress.values()){let n=\"\";if(typeof a.lastScaledSize<\"u\"){let h=this.progressStyle.chars[0].repeat(a.lastScaledSize),E=this.progressStyle.chars[1].repeat(this.progressMaxScaledSize-a.lastScaledSize);n=` ${h}${E}`}let c=this.formatName(null),f=c?`${c}: `:\"\",p=a.definition.title?` ${a.definition.title}`:\"\";this.stdout.write(`${jt(this.configuration,\"\\u27A4\",\"blueBright\")} ${f}${s}${n}${p}\n`)}this.progressTimeout=setTimeout(()=>{this.refreshProgress({force:!0})},gpe)}refreshProgress({delta:r=0,force:s=!1}={}){let a=!1,n=!1;if(s||this.progress.size===0)a=!0;else for(let c of this.progress.values()){let f=typeof c.definition.progress<\"u\"?Math.trunc(this.progressMaxScaledSize*c.definition.progress):void 0,p=c.lastScaledSize;c.lastScaledSize=f;let h=c.lastTitle;if(c.lastTitle=c.definition.title,f!==p||(n=h!==c.definition.title)){a=!0;break}}a&&(this.clearProgress({delta:r,clear:n}),this.writeProgress())}truncate(r,{truncate:s}={}){return this.progressStyle===null&&(s=!1),typeof s>\"u\"&&(s=this.configuration.get(\"preferTruncatedLines\")),s&&(r=(0,mpe.default)(r,0,this.stdout.columns-1)),r}formatName(r){return this.includeNames?Epe(r,{configuration:this.configuration,json:this.json}):\"\"}formatPrefix(r,s){return this.includePrefix?`${jt(this.configuration,\"\\u27A4\",s)} ${r}${this.formatIndent()}`:\"\"}formatNameWithHyperlink(r){return this.includeNames?xj(r,{configuration:this.configuration,json:this.json}):\"\"}formatIndent(){return this.level>0||!this.forceSectionAlignment?\"\\u2502 \".repeat(this.indent):`${Ytt} `}}});var Cn={};Yt(Cn,{PackageManager:()=>Cpe,detectPackageManager:()=>wpe,executePackageAccessibleBinary:()=>bpe,executePackageScript:()=>OR,executePackageShellcode:()=>kj,executeWorkspaceAccessibleBinary:()=>nrt,executeWorkspaceLifecycleScript:()=>Spe,executeWorkspaceScript:()=>vpe,getPackageAccessibleBinaries:()=>LR,getWorkspaceAccessibleBinaries:()=>Dpe,hasPackageScript:()=>ert,hasWorkspaceScript:()=>Qj,isNodeScript:()=>Rj,makeScriptEnv:()=>Av,maybeExecuteWorkspaceLifecycleScript:()=>rrt,prepareExternalProject:()=>$tt});async function S0(e,t,r,s=[]){if(process.platform===\"win32\"){let a=`@goto #_undefined_# 2>NUL || @title %COMSPEC% & @setlocal & @\"${r}\" ${s.map(n=>`\"${n.replace('\"','\"\"')}\"`).join(\" \")} %*`;await le.writeFilePromise(K.format({dir:e,name:t,ext:\".cmd\"}),a)}await le.writeFilePromise(K.join(e,t),`#!/bin/sh\nexec \"${r}\" ${s.map(a=>`'${a.replace(/'/g,`'\"'\"'`)}'`).join(\" \")} \"$@\"\n`,{mode:493})}async function wpe(e){let t=await Ut.tryFind(e);if(t?.packageManager){let s=PQ(t.packageManager);if(s?.name){let a=`found ${JSON.stringify({packageManager:t.packageManager})} in manifest`,[n]=s.reference.split(\".\");switch(s.name){case\"yarn\":return{packageManagerField:!0,packageManager:Number(n)===1?\"Yarn Classic\":\"Yarn\",reason:a};case\"npm\":return{packageManagerField:!0,packageManager:\"npm\",reason:a};case\"pnpm\":return{packageManagerField:!0,packageManager:\"pnpm\",reason:a}}}}let r;try{r=await le.readFilePromise(K.join(e,Er.lockfile),\"utf8\")}catch{}return r!==void 0?r.match(/^__metadata:$/m)?{packageManager:\"Yarn\",reason:'\"__metadata\" key found in yarn.lock'}:{packageManager:\"Yarn Classic\",reason:'\"__metadata\" key not found in yarn.lock, must be a Yarn classic lockfile'}:le.existsSync(K.join(e,\"package-lock.json\"))?{packageManager:\"npm\",reason:`found npm's \"package-lock.json\" lockfile`}:le.existsSync(K.join(e,\"pnpm-lock.yaml\"))?{packageManager:\"pnpm\",reason:`found pnpm's \"pnpm-lock.yaml\" lockfile`}:null}async function Av({project:e,locator:t,binFolder:r,ignoreCorepack:s,lifecycleScript:a,baseEnv:n=e?.configuration.env??process.env}){let c={};for(let[E,C]of Object.entries(n))typeof C<\"u\"&&(c[E.toLowerCase()!==\"path\"?E:\"PATH\"]=C);let f=fe.fromPortablePath(r);c.BERRY_BIN_FOLDER=fe.fromPortablePath(f);let p=process.env.COREPACK_ROOT&&!s?fe.join(process.env.COREPACK_ROOT,\"dist/yarn.js\"):process.argv[1];if(await Promise.all([S0(r,\"node\",process.execPath),...An!==null?[S0(r,\"run\",process.execPath,[p,\"run\"]),S0(r,\"yarn\",process.execPath,[p]),S0(r,\"yarnpkg\",process.execPath,[p]),S0(r,\"node-gyp\",process.execPath,[p,\"run\",\"--top-level\",\"node-gyp\"])]:[]]),e&&(c.INIT_CWD=fe.fromPortablePath(e.configuration.startingCwd),c.PROJECT_CWD=fe.fromPortablePath(e.cwd)),c.PATH=c.PATH?`${f}${fe.delimiter}${c.PATH}`:`${f}`,c.npm_execpath=`${f}${fe.sep}yarn`,c.npm_node_execpath=`${f}${fe.sep}node`,t){if(!e)throw new Error(\"Assertion failed: Missing project\");let E=e.tryWorkspaceByLocator(t),C=E?E.manifest.version??\"\":e.storedPackages.get(t.locatorHash).version??\"\";c.npm_package_name=fn(t),c.npm_package_version=C;let S;if(E)S=E.cwd;else{let x=e.storedPackages.get(t.locatorHash);if(!x)throw new Error(`Package for ${Vr(e.configuration,t)} not found in the project`);let I=e.configuration.getLinkers(),T={project:e,report:new Ot({stdout:new D0.PassThrough,configuration:e.configuration})},O=I.find(U=>U.supportsPackage(x,T));if(!O)throw new Error(`The package ${Vr(e.configuration,x)} isn't supported by any of the available linkers`);S=await O.findPackageLocation(x,T)}c.npm_package_json=fe.fromPortablePath(K.join(S,Er.manifest))}let h=An!==null?`yarn/${An}`:`yarn/${xp(\"@yarnpkg/core\").version}-core`;return c.npm_config_user_agent=`${h} npm/? node/${process.version} ${process.platform} ${process.arch}`,a&&(c.npm_lifecycle_event=a),e&&await e.configuration.triggerHook(E=>E.setupScriptEnvironment,e,c,async(E,C,S)=>await S0(r,E,C,S)),c}async function $tt(e,t,{configuration:r,report:s,workspace:a=null,locator:n=null}){await Xtt(async()=>{await le.mktempPromise(async c=>{let f=K.join(c,\"pack.log\"),p=null,{stdout:h,stderr:E}=r.getSubprocessStreams(f,{prefix:fe.fromPortablePath(e),report:s}),C=n&&Hu(n)?sI(n):n,S=C?gl(C):\"an external project\";h.write(`Packing ${S} from sources\n`);let x=await wpe(e),I;x!==null?(h.write(`Using ${x.packageManager} for bootstrap. Reason: ${x.reason}\n\n`),I=x.packageManager):(h.write(`No package manager configuration detected; defaulting to Yarn\n\n`),I=\"Yarn\");let T=I===\"Yarn\"&&!x?.packageManagerField;await le.mktempPromise(async O=>{let U=await Av({binFolder:O,ignoreCorepack:T,baseEnv:{...process.env,COREPACK_ENABLE_AUTO_PIN:\"0\"}}),te=new Map([[\"Yarn Classic\",async()=>{let ue=a!==null?[\"workspace\",a]:[],ae=K.join(e,Er.manifest),de=await le.readFilePromise(ae),Ae=await Gu(process.execPath,[process.argv[1],\"set\",\"version\",\"classic\",\"--only-if-needed\",\"--yarn-path\"],{cwd:e,env:U,stdin:p,stdout:h,stderr:E,end:1});if(Ae.code!==0)return Ae.code;await le.writeFilePromise(ae,de),await le.appendFilePromise(K.join(e,\".npmignore\"),`/.yarn\n`),h.write(`\n`),delete U.NODE_ENV;let Ce=await Gu(\"yarn\",[\"install\"],{cwd:e,env:U,stdin:p,stdout:h,stderr:E,end:1});if(Ce.code!==0)return Ce.code;h.write(`\n`);let Ee=await Gu(\"yarn\",[...ue,\"pack\",\"--filename\",fe.fromPortablePath(t)],{cwd:e,env:U,stdin:p,stdout:h,stderr:E});return Ee.code!==0?Ee.code:0}],[\"Yarn\",async()=>{let ue=a!==null?[\"workspace\",a]:[];U.YARN_ENABLE_INLINE_BUILDS=\"1\";let ae=K.join(e,Er.lockfile);await le.existsPromise(ae)||await le.writeFilePromise(ae,\"\");let de=await Gu(\"yarn\",[...ue,\"pack\",\"--install-if-needed\",\"--filename\",fe.fromPortablePath(t)],{cwd:e,env:U,stdin:p,stdout:h,stderr:E});return de.code!==0?de.code:0}],[\"npm\",async()=>{if(a!==null){let Se=new D0.PassThrough,Be=KE(Se);Se.pipe(h,{end:!1});let me=await Gu(\"npm\",[\"--version\"],{cwd:e,env:U,stdin:p,stdout:Se,stderr:E,end:0});if(Se.end(),me.code!==0)return h.end(),E.end(),me.code;let ce=(await Be).toString().trim();if(!eA(ce,\">=7.x\")){let X=xa(null,\"npm\"),De=Mn(X,ce),Qe=Mn(X,\">=7.x\");throw new Error(`Workspaces aren't supported by ${oi(r,De)}; please upgrade to ${oi(r,Qe)} (npm has been detected as the primary package manager for ${jt(r,e,gt.PATH)})`)}}let ue=a!==null?[\"--workspace\",a]:[];delete U.npm_config_user_agent,delete U.npm_config_production,delete U.NPM_CONFIG_PRODUCTION,delete U.NODE_ENV;let ae=await Gu(\"npm\",[\"install\",\"--legacy-peer-deps\"],{cwd:e,env:U,stdin:p,stdout:h,stderr:E,end:1});if(ae.code!==0)return ae.code;let de=new D0.PassThrough,Ae=KE(de);de.pipe(h);let Ce=await Gu(\"npm\",[\"pack\",\"--silent\",...ue],{cwd:e,env:U,stdin:p,stdout:de,stderr:E});if(Ce.code!==0)return Ce.code;let Ee=(await Ae).toString().trim().replace(/^.*\\n/s,\"\"),g=K.resolve(e,fe.toPortablePath(Ee));return await le.renamePromise(g,t),0}]]).get(I);if(typeof te>\"u\")throw new Error(\"Assertion failed: Unsupported workflow\");let ie=await te();if(!(ie===0||typeof ie>\"u\"))throw le.detachTemp(c),new _t(58,`Packing the package failed (exit code ${ie}, logs can be found here: ${jt(r,f,gt.PATH)})`)})})})}async function ert(e,t,{project:r}){let s=r.tryWorkspaceByLocator(e);if(s!==null)return Qj(s,t);let a=r.storedPackages.get(e.locatorHash);if(!a)throw new Error(`Package for ${Vr(r.configuration,e)} not found in the project`);return await tA.openPromise(async n=>{let c=r.configuration,f=r.configuration.getLinkers(),p={project:r,report:new Ot({stdout:new D0.PassThrough,configuration:c})},h=f.find(x=>x.supportsPackage(a,p));if(!h)throw new Error(`The package ${Vr(r.configuration,a)} isn't supported by any of the available linkers`);let E=await h.findPackageLocation(a,p),C=new bn(E,{baseFs:n});return(await Ut.find(vt.dot,{baseFs:C})).scripts.has(t)})}async function OR(e,t,r,{cwd:s,project:a,stdin:n,stdout:c,stderr:f}){return await le.mktempPromise(async p=>{let{manifest:h,env:E,cwd:C}=await Bpe(e,{project:a,binFolder:p,cwd:s,lifecycleScript:t}),S=h.scripts.get(t);if(typeof S>\"u\")return 1;let x=async()=>await bI(S,r,{cwd:C,env:E,stdin:n,stdout:c,stderr:f});return await(await a.configuration.reduceHook(T=>T.wrapScriptExecution,x,a,e,t,{script:S,args:r,cwd:C,env:E,stdin:n,stdout:c,stderr:f}))()})}async function kj(e,t,r,{cwd:s,project:a,stdin:n,stdout:c,stderr:f}){return await le.mktempPromise(async p=>{let{env:h,cwd:E}=await Bpe(e,{project:a,binFolder:p,cwd:s});return await bI(t,r,{cwd:E,env:h,stdin:n,stdout:c,stderr:f})})}async function trt(e,{binFolder:t,cwd:r,lifecycleScript:s}){let a=await Av({project:e.project,locator:e.anchoredLocator,binFolder:t,lifecycleScript:s});return await Tj(t,await Dpe(e)),typeof r>\"u\"&&(r=K.dirname(await le.realpathPromise(K.join(e.cwd,\"package.json\")))),{manifest:e.manifest,binFolder:t,env:a,cwd:r}}async function Bpe(e,{project:t,binFolder:r,cwd:s,lifecycleScript:a}){let n=t.tryWorkspaceByLocator(e);if(n!==null)return trt(n,{binFolder:r,cwd:s,lifecycleScript:a});let c=t.storedPackages.get(e.locatorHash);if(!c)throw new Error(`Package for ${Vr(t.configuration,e)} not found in the project`);return await tA.openPromise(async f=>{let p=t.configuration,h=t.configuration.getLinkers(),E={project:t,report:new Ot({stdout:new D0.PassThrough,configuration:p})},C=h.find(O=>O.supportsPackage(c,E));if(!C)throw new Error(`The package ${Vr(t.configuration,c)} isn't supported by any of the available linkers`);let S=await Av({project:t,locator:e,binFolder:r,lifecycleScript:a});await Tj(r,await LR(e,{project:t}));let x=await C.findPackageLocation(c,E),I=new bn(x,{baseFs:f}),T=await Ut.find(vt.dot,{baseFs:I});return typeof s>\"u\"&&(s=x),{manifest:T,binFolder:r,env:S,cwd:s}})}async function vpe(e,t,r,{cwd:s,stdin:a,stdout:n,stderr:c}){return await OR(e.anchoredLocator,t,r,{cwd:s,project:e.project,stdin:a,stdout:n,stderr:c})}function Qj(e,t){return e.manifest.scripts.has(t)}async function Spe(e,t,{cwd:r,report:s}){let{configuration:a}=e.project,n=null;await le.mktempPromise(async c=>{let f=K.join(c,`${t}.log`),p=`# This file contains the result of Yarn calling the \"${t}\" lifecycle script inside a workspace (\"${fe.fromPortablePath(e.cwd)}\")\n`,{stdout:h,stderr:E}=a.getSubprocessStreams(f,{report:s,prefix:Vr(a,e.anchoredLocator),header:p});s.reportInfo(36,`Calling the \"${t}\" lifecycle script`);let C=await vpe(e,t,[],{cwd:r,stdin:n,stdout:h,stderr:E});if(h.end(),E.end(),C!==0)throw le.detachTemp(c),new _t(36,`${E2(t)} script failed (exit code ${jt(a,C,gt.NUMBER)}, logs can be found here: ${jt(a,f,gt.PATH)}); run ${jt(a,`yarn ${t}`,gt.CODE)} to investigate`)})}async function rrt(e,t,r){Qj(e,t)&&await Spe(e,t,r)}function Rj(e){let t=K.extname(e);if(t.match(/\\.[cm]?[jt]sx?$/))return!0;if(t===\".exe\"||t===\".bin\")return!1;let r=Buffer.alloc(4),s;try{s=le.openSync(e,\"r\")}catch{return!0}try{le.readSync(s,r,0,r.length,0)}finally{le.closeSync(s)}let a=r.readUint32BE();return!(a===3405691582||a===3489328638||a===2135247942||(a&4294901760)===1297743872)}async function LR(e,{project:t}){let r=t.configuration,s=new Map,a=t.storedPackages.get(e.locatorHash);if(!a)throw new Error(`Package for ${Vr(r,e)} not found in the project`);let n=new D0.Writable,c=r.getLinkers(),f={project:t,report:new Ot({configuration:r,stdout:n})},p=new Set([e.locatorHash]);for(let E of a.dependencies.values()){let C=t.storedResolutions.get(E.descriptorHash);if(!C)throw new Error(`Assertion failed: The resolution (${oi(r,E)}) should have been registered`);p.add(C)}let h=await Promise.all(Array.from(p,async E=>{let C=t.storedPackages.get(E);if(!C)throw new Error(`Assertion failed: The package (${E}) should have been registered`);if(C.bin.size===0)return zl.skip;let S=c.find(I=>I.supportsPackage(C,f));if(!S)return zl.skip;let x=null;try{x=await S.findPackageLocation(C,f)}catch(I){if(I.code===\"LOCATOR_NOT_INSTALLED\")return zl.skip;throw I}return{dependency:C,packageLocation:x}}));for(let E of h){if(E===zl.skip)continue;let{dependency:C,packageLocation:S}=E;for(let[x,I]of C.bin){let T=K.resolve(S,I);s.set(x,[C,fe.fromPortablePath(T),Rj(T)])}}return s}async function Dpe(e){return await LR(e.anchoredLocator,{project:e.project})}async function Tj(e,t){await Promise.all(Array.from(t,([r,[,s,a]])=>a?S0(e,r,process.execPath,[s]):S0(e,r,s,[])))}async function bpe(e,t,r,{cwd:s,project:a,stdin:n,stdout:c,stderr:f,nodeArgs:p=[],packageAccessibleBinaries:h}){h??=await LR(e,{project:a});let E=h.get(t);if(!E)throw new Error(`Binary not found (${t}) for ${Vr(a.configuration,e)}`);return await le.mktempPromise(async C=>{let[,S]=E,x=await Av({project:a,locator:e,binFolder:C});await Tj(x.BERRY_BIN_FOLDER,h);let I=Rj(fe.toPortablePath(S))?Gu(process.execPath,[...p,S,...r],{cwd:s,env:x,stdin:n,stdout:c,stderr:f}):Gu(S,r,{cwd:s,env:x,stdin:n,stdout:c,stderr:f}),T;try{T=await I}finally{await le.removePromise(x.BERRY_BIN_FOLDER)}return T.code})}async function nrt(e,t,r,{cwd:s,stdin:a,stdout:n,stderr:c,packageAccessibleBinaries:f}){return await bpe(e.anchoredLocator,t,r,{project:e.project,cwd:s,stdin:a,stdout:n,stderr:c,packageAccessibleBinaries:f})}var Ipe,D0,Cpe,Ztt,Xtt,Fj=Ze(()=>{Dt();Dt();rA();sv();Jl();Ipe=et(Nd()),D0=Ie(\"stream\");cI();Tc();fv();uv();gR();kc();xc();Fp();Zo();Cpe=(a=>(a.Yarn1=\"Yarn Classic\",a.Yarn2=\"Yarn\",a.Npm=\"npm\",a.Pnpm=\"pnpm\",a))(Cpe||{});Ztt=2,Xtt=(0,Ipe.default)(Ztt)});function dnt(e,t,r){let s=t,a=t?t.next:e.head,n=new M6(r,s,a,e);return n.next===void 0&&(e.tail=n),n.prev===void 0&&(e.head=n),e.length++,n}function mnt(e,t){e.tail=new M6(t,e.tail,void 0,e),e.head||(e.head=e.tail),e.length++}function ynt(e,t){e.head=new M6(t,void 0,e.head,e),e.tail||(e.tail=e.head),e.length++}var ihe,Fa,pT,k6,she,R6,Em,gT,lhe,cT,N0,Rpe,che,ym,ghe,Fv,Yu,A6,Ihe,I6,_6,Dhe,H6,wn,gs,j6,Lv,MI,yl,Qhe,Nv,G6,ml,W6,irt,srt,Ppe,ort,art,lrt,Hp,jp,b0,MR,pv,UR,xpe,_R,kpe,qu,xI,Js,hv,TI,zs,Ta,Zs,Nj,HR,ta,es,Oj,Lj,Qpe,Mj,iA,Uj,jR,gv,cm,ec,dv,crt,urt,frt,Art,ohe,prt,hrt,grt,vm,drt,L0,Ju,mv,Kn,_j,Vp,Hj,l6,c6,bv,GR,LI,UI,jj,FI,M0,Ku,Q0,sA,NI,Gj,Wp,yv,qj,XR,um,$R,Im,Q6,mrt,hT,ahe,yrt,Ert,Irt,Crt,wrt,Brt,vrt,T6,Ov,Srt,lA,Drt,Tpe,brt,Wj,Cm,qR,Vj,F6,uhe,Prt,xrt,fhe,krt,Qrt,Ahe,Rrt,Trt,Frt,Nrt,Ort,Lrt,Mrt,Urt,phe,hhe,_rt,eT,Hrt,dT,N6,wm,jrt,fm,Yj,Grt,R0,qrt,Wrt,Vrt,T0,Yrt,Krt,Jrt,Kj,zrt,Am,uT,Zrt,Xrt,$rt,ent,cn,mhe,mT,tnt,u6,f6,rnt,Mc,pm,Gp,Jj,Fpe,oA,Ev,P0,Npe,Ci,qp,x0,zj,hm,hs,WR,VR,Zj,Ope,Lpe,Iv,Xj,YR,kI,k0,KR,gm,JR,zR,Mpe,nnt,Bm,Pv,int,yhe,snt,ont,yT,Ehe,ant,Upe,O6,ET,L6,lnt,cnt,_pe,unt,Che,fnt,Hpe,jpe,Gpe,p6,qpe,Cv,tT,h6,rT,g6,d6,m6,y6,F0,fT,E6,$j,aA,whe,Ant,pnt,hnt,gnt,M6,Wpe,Vpe,nT,wv,Wu,dm,mm,Bv,e6,Vu,t6,iT,Ype,C6,w6,sT,oT,Kpe,r6,aT,Bhe,n6,IT,U6,Ent,Int,vhe,She,Cnt,wnt,lUt,Bnt,vnt,Snt,Dnt,bnt,bhe,Pnt,xnt,knt,Phe,B6,AT,Qnt,xhe,Rnt,khe,Rhe,CT,Tnt,Fnt,v6,The,Nnt,Ont,i6,Jpe,QI,Lnt,Mnt,Unt,_nt,Hnt,jnt,zpe,S6,Zpe,D6,Uc,b6,P6,lT,Xpe,$pe,Dv,ehe,the,s6,O0,Xs,ZR,rhe,RI,o6,a6,x6,xv,kv,Qv,Rv,Gnt,Tv,qnt,Wnt,Vnt,nhe,q6,vv,Fhe,Ynt,Knt,cUt,Jnt,znt,Znt,Xnt,$nt,Sv,uUt,eit,Nhe=Ze(()=>{ihe=et(Ie(\"events\"),1),Fa=et(Ie(\"fs\"),1),pT=Ie(\"node:events\"),k6=et(Ie(\"node:stream\"),1),she=Ie(\"node:string_decoder\"),R6=et(Ie(\"node:path\"),1),Em=et(Ie(\"node:fs\"),1),gT=Ie(\"path\"),lhe=Ie(\"events\"),cT=et(Ie(\"assert\"),1),N0=Ie(\"buffer\"),Rpe=et(Ie(\"zlib\"),1),che=et(Ie(\"zlib\"),1),ym=Ie(\"node:path\"),ghe=Ie(\"node:path\"),Fv=et(Ie(\"fs\"),1),Yu=et(Ie(\"fs\"),1),A6=et(Ie(\"path\"),1),Ihe=Ie(\"node:path\"),I6=et(Ie(\"path\"),1),_6=et(Ie(\"node:fs\"),1),Dhe=et(Ie(\"node:assert\"),1),H6=Ie(\"node:crypto\"),wn=et(Ie(\"node:fs\"),1),gs=et(Ie(\"node:path\"),1),j6=et(Ie(\"fs\"),1),Lv=et(Ie(\"node:fs\"),1),MI=et(Ie(\"node:path\"),1),yl=et(Ie(\"node:fs\"),1),Qhe=et(Ie(\"node:fs/promises\"),1),Nv=et(Ie(\"node:path\"),1),G6=Ie(\"node:path\"),ml=et(Ie(\"node:fs\"),1),W6=et(Ie(\"node:path\"),1),irt=Object.defineProperty,srt=(e,t)=>{for(var r in t)irt(e,r,{get:t[r],enumerable:!0})},Ppe=typeof process==\"object\"&&process?process:{stdout:null,stderr:null},ort=e=>!!e&&typeof e==\"object\"&&(e instanceof vm||e instanceof k6.default||art(e)||lrt(e)),art=e=>!!e&&typeof e==\"object\"&&e instanceof pT.EventEmitter&&typeof e.pipe==\"function\"&&e.pipe!==k6.default.Writable.prototype.pipe,lrt=e=>!!e&&typeof e==\"object\"&&e instanceof pT.EventEmitter&&typeof e.write==\"function\"&&typeof e.end==\"function\",Hp=Symbol(\"EOF\"),jp=Symbol(\"maybeEmitEnd\"),b0=Symbol(\"emittedEnd\"),MR=Symbol(\"emittingEnd\"),pv=Symbol(\"emittedError\"),UR=Symbol(\"closed\"),xpe=Symbol(\"read\"),_R=Symbol(\"flush\"),kpe=Symbol(\"flushChunk\"),qu=Symbol(\"encoding\"),xI=Symbol(\"decoder\"),Js=Symbol(\"flowing\"),hv=Symbol(\"paused\"),TI=Symbol(\"resume\"),zs=Symbol(\"buffer\"),Ta=Symbol(\"pipes\"),Zs=Symbol(\"bufferLength\"),Nj=Symbol(\"bufferPush\"),HR=Symbol(\"bufferShift\"),ta=Symbol(\"objectMode\"),es=Symbol(\"destroyed\"),Oj=Symbol(\"error\"),Lj=Symbol(\"emitData\"),Qpe=Symbol(\"emitEnd\"),Mj=Symbol(\"emitEnd2\"),iA=Symbol(\"async\"),Uj=Symbol(\"abort\"),jR=Symbol(\"aborted\"),gv=Symbol(\"signal\"),cm=Symbol(\"dataListeners\"),ec=Symbol(\"discarded\"),dv=e=>Promise.resolve().then(e),crt=e=>e(),urt=e=>e===\"end\"||e===\"finish\"||e===\"prefinish\",frt=e=>e instanceof ArrayBuffer||!!e&&typeof e==\"object\"&&e.constructor&&e.constructor.name===\"ArrayBuffer\"&&e.byteLength>=0,Art=e=>!Buffer.isBuffer(e)&&ArrayBuffer.isView(e),ohe=class{src;dest;opts;ondrain;constructor(e,t,r){this.src=e,this.dest=t,this.opts=r,this.ondrain=()=>e[TI](),this.dest.on(\"drain\",this.ondrain)}unpipe(){this.dest.removeListener(\"drain\",this.ondrain)}proxyErrors(e){}end(){this.unpipe(),this.opts.end&&this.dest.end()}},prt=class extends ohe{unpipe(){this.src.removeListener(\"error\",this.proxyErrors),super.unpipe()}constructor(e,t,r){super(e,t,r),this.proxyErrors=s=>t.emit(\"error\",s),e.on(\"error\",this.proxyErrors)}},hrt=e=>!!e.objectMode,grt=e=>!e.objectMode&&!!e.encoding&&e.encoding!==\"buffer\",vm=class extends pT.EventEmitter{[Js]=!1;[hv]=!1;[Ta]=[];[zs]=[];[ta];[qu];[iA];[xI];[Hp]=!1;[b0]=!1;[MR]=!1;[UR]=!1;[pv]=null;[Zs]=0;[es]=!1;[gv];[jR]=!1;[cm]=0;[ec]=!1;writable=!0;readable=!0;constructor(...e){let t=e[0]||{};if(super(),t.objectMode&&typeof t.encoding==\"string\")throw new TypeError(\"Encoding and objectMode may not be used together\");hrt(t)?(this[ta]=!0,this[qu]=null):grt(t)?(this[qu]=t.encoding,this[ta]=!1):(this[ta]=!1,this[qu]=null),this[iA]=!!t.async,this[xI]=this[qu]?new she.StringDecoder(this[qu]):null,t&&t.debugExposeBuffer===!0&&Object.defineProperty(this,\"buffer\",{get:()=>this[zs]}),t&&t.debugExposePipes===!0&&Object.defineProperty(this,\"pipes\",{get:()=>this[Ta]});let{signal:r}=t;r&&(this[gv]=r,r.aborted?this[Uj]():r.addEventListener(\"abort\",()=>this[Uj]()))}get bufferLength(){return this[Zs]}get encoding(){return this[qu]}set encoding(e){throw new Error(\"Encoding must be set at instantiation time\")}setEncoding(e){throw new Error(\"Encoding must be set at instantiation time\")}get objectMode(){return this[ta]}set objectMode(e){throw new Error(\"objectMode must be set at instantiation time\")}get async(){return this[iA]}set async(e){this[iA]=this[iA]||!!e}[Uj](){this[jR]=!0,this.emit(\"abort\",this[gv]?.reason),this.destroy(this[gv]?.reason)}get aborted(){return this[jR]}set aborted(e){}write(e,t,r){if(this[jR])return!1;if(this[Hp])throw new Error(\"write after end\");if(this[es])return this.emit(\"error\",Object.assign(new Error(\"Cannot call write after a stream was destroyed\"),{code:\"ERR_STREAM_DESTROYED\"})),!0;typeof t==\"function\"&&(r=t,t=\"utf8\"),t||(t=\"utf8\");let s=this[iA]?dv:crt;if(!this[ta]&&!Buffer.isBuffer(e)){if(Art(e))e=Buffer.from(e.buffer,e.byteOffset,e.byteLength);else if(frt(e))e=Buffer.from(e);else if(typeof e!=\"string\")throw new Error(\"Non-contiguous data written to non-objectMode stream\")}return this[ta]?(this[Js]&&this[Zs]!==0&&this[_R](!0),this[Js]?this.emit(\"data\",e):this[Nj](e),this[Zs]!==0&&this.emit(\"readable\"),r&&s(r),this[Js]):e.length?(typeof e==\"string\"&&!(t===this[qu]&&!this[xI]?.lastNeed)&&(e=Buffer.from(e,t)),Buffer.isBuffer(e)&&this[qu]&&(e=this[xI].write(e)),this[Js]&&this[Zs]!==0&&this[_R](!0),this[Js]?this.emit(\"data\",e):this[Nj](e),this[Zs]!==0&&this.emit(\"readable\"),r&&s(r),this[Js]):(this[Zs]!==0&&this.emit(\"readable\"),r&&s(r),this[Js])}read(e){if(this[es])return null;if(this[ec]=!1,this[Zs]===0||e===0||e&&e>this[Zs])return this[jp](),null;this[ta]&&(e=null),this[zs].length>1&&!this[ta]&&(this[zs]=[this[qu]?this[zs].join(\"\"):Buffer.concat(this[zs],this[Zs])]);let t=this[xpe](e||null,this[zs][0]);return this[jp](),t}[xpe](e,t){if(this[ta])this[HR]();else{let r=t;e===r.length||e===null?this[HR]():typeof r==\"string\"?(this[zs][0]=r.slice(e),t=r.slice(0,e),this[Zs]-=e):(this[zs][0]=r.subarray(e),t=r.subarray(0,e),this[Zs]-=e)}return this.emit(\"data\",t),!this[zs].length&&!this[Hp]&&this.emit(\"drain\"),t}end(e,t,r){return typeof e==\"function\"&&(r=e,e=void 0),typeof t==\"function\"&&(r=t,t=\"utf8\"),e!==void 0&&this.write(e,t),r&&this.once(\"end\",r),this[Hp]=!0,this.writable=!1,(this[Js]||!this[hv])&&this[jp](),this}[TI](){this[es]||(!this[cm]&&!this[Ta].length&&(this[ec]=!0),this[hv]=!1,this[Js]=!0,this.emit(\"resume\"),this[zs].length?this[_R]():this[Hp]?this[jp]():this.emit(\"drain\"))}resume(){return this[TI]()}pause(){this[Js]=!1,this[hv]=!0,this[ec]=!1}get destroyed(){return this[es]}get flowing(){return this[Js]}get paused(){return this[hv]}[Nj](e){this[ta]?this[Zs]+=1:this[Zs]+=e.length,this[zs].push(e)}[HR](){return this[ta]?this[Zs]-=1:this[Zs]-=this[zs][0].length,this[zs].shift()}[_R](e=!1){do;while(this[kpe](this[HR]())&&this[zs].length);!e&&!this[zs].length&&!this[Hp]&&this.emit(\"drain\")}[kpe](e){return this.emit(\"data\",e),this[Js]}pipe(e,t){if(this[es])return e;this[ec]=!1;let r=this[b0];return t=t||{},e===Ppe.stdout||e===Ppe.stderr?t.end=!1:t.end=t.end!==!1,t.proxyErrors=!!t.proxyErrors,r?t.end&&e.end():(this[Ta].push(t.proxyErrors?new prt(this,e,t):new ohe(this,e,t)),this[iA]?dv(()=>this[TI]()):this[TI]()),e}unpipe(e){let t=this[Ta].find(r=>r.dest===e);t&&(this[Ta].length===1?(this[Js]&&this[cm]===0&&(this[Js]=!1),this[Ta]=[]):this[Ta].splice(this[Ta].indexOf(t),1),t.unpipe())}addListener(e,t){return this.on(e,t)}on(e,t){let r=super.on(e,t);if(e===\"data\")this[ec]=!1,this[cm]++,!this[Ta].length&&!this[Js]&&this[TI]();else if(e===\"readable\"&&this[Zs]!==0)super.emit(\"readable\");else if(urt(e)&&this[b0])super.emit(e),this.removeAllListeners(e);else if(e===\"error\"&&this[pv]){let s=t;this[iA]?dv(()=>s.call(this,this[pv])):s.call(this,this[pv])}return r}removeListener(e,t){return this.off(e,t)}off(e,t){let r=super.off(e,t);return e===\"data\"&&(this[cm]=this.listeners(\"data\").length,this[cm]===0&&!this[ec]&&!this[Ta].length&&(this[Js]=!1)),r}removeAllListeners(e){let t=super.removeAllListeners(e);return(e===\"data\"||e===void 0)&&(this[cm]=0,!this[ec]&&!this[Ta].length&&(this[Js]=!1)),t}get emittedEnd(){return this[b0]}[jp](){!this[MR]&&!this[b0]&&!this[es]&&this[zs].length===0&&this[Hp]&&(this[MR]=!0,this.emit(\"end\"),this.emit(\"prefinish\"),this.emit(\"finish\"),this[UR]&&this.emit(\"close\"),this[MR]=!1)}emit(e,...t){let r=t[0];if(e!==\"error\"&&e!==\"close\"&&e!==es&&this[es])return!1;if(e===\"data\")return!this[ta]&&!r?!1:this[iA]?(dv(()=>this[Lj](r)),!0):this[Lj](r);if(e===\"end\")return this[Qpe]();if(e===\"close\"){if(this[UR]=!0,!this[b0]&&!this[es])return!1;let a=super.emit(\"close\");return this.removeAllListeners(\"close\"),a}else if(e===\"error\"){this[pv]=r,super.emit(Oj,r);let a=!this[gv]||this.listeners(\"error\").length?super.emit(\"error\",r):!1;return this[jp](),a}else if(e===\"resume\"){let a=super.emit(\"resume\");return this[jp](),a}else if(e===\"finish\"||e===\"prefinish\"){let a=super.emit(e);return this.removeAllListeners(e),a}let s=super.emit(e,...t);return this[jp](),s}[Lj](e){for(let r of this[Ta])r.dest.write(e)===!1&&this.pause();let t=this[ec]?!1:super.emit(\"data\",e);return this[jp](),t}[Qpe](){return this[b0]?!1:(this[b0]=!0,this.readable=!1,this[iA]?(dv(()=>this[Mj]()),!0):this[Mj]())}[Mj](){if(this[xI]){let t=this[xI].end();if(t){for(let r of this[Ta])r.dest.write(t);this[ec]||super.emit(\"data\",t)}}for(let t of this[Ta])t.end();let e=super.emit(\"end\");return this.removeAllListeners(\"end\"),e}async collect(){let e=Object.assign([],{dataLength:0});this[ta]||(e.dataLength=0);let t=this.promise();return this.on(\"data\",r=>{e.push(r),this[ta]||(e.dataLength+=r.length)}),await t,e}async concat(){if(this[ta])throw new Error(\"cannot concat in objectMode\");let e=await this.collect();return this[qu]?e.join(\"\"):Buffer.concat(e,e.dataLength)}async promise(){return new Promise((e,t)=>{this.on(es,()=>t(new Error(\"stream destroyed\"))),this.on(\"error\",r=>t(r)),this.on(\"end\",()=>e())})}[Symbol.asyncIterator](){this[ec]=!1;let e=!1,t=async()=>(this.pause(),e=!0,{value:void 0,done:!0});return{next:()=>{if(e)return t();let r=this.read();if(r!==null)return Promise.resolve({done:!1,value:r});if(this[Hp])return t();let s,a,n=h=>{this.off(\"data\",c),this.off(\"end\",f),this.off(es,p),t(),a(h)},c=h=>{this.off(\"error\",n),this.off(\"end\",f),this.off(es,p),this.pause(),s({value:h,done:!!this[Hp]})},f=()=>{this.off(\"error\",n),this.off(\"data\",c),this.off(es,p),t(),s({done:!0,value:void 0})},p=()=>n(new Error(\"stream destroyed\"));return new Promise((h,E)=>{a=E,s=h,this.once(es,p),this.once(\"error\",n),this.once(\"end\",f),this.once(\"data\",c)})},throw:t,return:t,[Symbol.asyncIterator](){return this}}}[Symbol.iterator](){this[ec]=!1;let e=!1,t=()=>(this.pause(),this.off(Oj,t),this.off(es,t),this.off(\"end\",t),e=!0,{done:!0,value:void 0}),r=()=>{if(e)return t();let s=this.read();return s===null?t():{done:!1,value:s}};return this.once(\"end\",t),this.once(Oj,t),this.once(es,t),{next:r,throw:t,return:t,[Symbol.iterator](){return this}}}destroy(e){if(this[es])return e?this.emit(\"error\",e):this.emit(es),this;this[es]=!0,this[ec]=!0,this[zs].length=0,this[Zs]=0;let t=this;return typeof t.close==\"function\"&&!this[UR]&&t.close(),e?this.emit(\"error\",e):this.emit(es),this}static get isStream(){return ort}},drt=Fa.default.writev,L0=Symbol(\"_autoClose\"),Ju=Symbol(\"_close\"),mv=Symbol(\"_ended\"),Kn=Symbol(\"_fd\"),_j=Symbol(\"_finished\"),Vp=Symbol(\"_flags\"),Hj=Symbol(\"_flush\"),l6=Symbol(\"_handleChunk\"),c6=Symbol(\"_makeBuf\"),bv=Symbol(\"_mode\"),GR=Symbol(\"_needDrain\"),LI=Symbol(\"_onerror\"),UI=Symbol(\"_onopen\"),jj=Symbol(\"_onread\"),FI=Symbol(\"_onwrite\"),M0=Symbol(\"_open\"),Ku=Symbol(\"_path\"),Q0=Symbol(\"_pos\"),sA=Symbol(\"_queue\"),NI=Symbol(\"_read\"),Gj=Symbol(\"_readSize\"),Wp=Symbol(\"_reading\"),yv=Symbol(\"_remain\"),qj=Symbol(\"_size\"),XR=Symbol(\"_write\"),um=Symbol(\"_writing\"),$R=Symbol(\"_defaultFlag\"),Im=Symbol(\"_errored\"),Q6=class extends vm{[Im]=!1;[Kn];[Ku];[Gj];[Wp]=!1;[qj];[yv];[L0];constructor(e,t){if(t=t||{},super(t),this.readable=!0,this.writable=!1,typeof e!=\"string\")throw new TypeError(\"path must be a string\");this[Im]=!1,this[Kn]=typeof t.fd==\"number\"?t.fd:void 0,this[Ku]=e,this[Gj]=t.readSize||16*1024*1024,this[Wp]=!1,this[qj]=typeof t.size==\"number\"?t.size:1/0,this[yv]=this[qj],this[L0]=typeof t.autoClose==\"boolean\"?t.autoClose:!0,typeof this[Kn]==\"number\"?this[NI]():this[M0]()}get fd(){return this[Kn]}get path(){return this[Ku]}write(){throw new TypeError(\"this is a readable stream\")}end(){throw new TypeError(\"this is a readable stream\")}[M0](){Fa.default.open(this[Ku],\"r\",(e,t)=>this[UI](e,t))}[UI](e,t){e?this[LI](e):(this[Kn]=t,this.emit(\"open\",t),this[NI]())}[c6](){return Buffer.allocUnsafe(Math.min(this[Gj],this[yv]))}[NI](){if(!this[Wp]){this[Wp]=!0;let e=this[c6]();if(e.length===0)return process.nextTick(()=>this[jj](null,0,e));Fa.default.read(this[Kn],e,0,e.length,null,(t,r,s)=>this[jj](t,r,s))}}[jj](e,t,r){this[Wp]=!1,e?this[LI](e):this[l6](t,r)&&this[NI]()}[Ju](){if(this[L0]&&typeof this[Kn]==\"number\"){let e=this[Kn];this[Kn]=void 0,Fa.default.close(e,t=>t?this.emit(\"error\",t):this.emit(\"close\"))}}[LI](e){this[Wp]=!0,this[Ju](),this.emit(\"error\",e)}[l6](e,t){let r=!1;return this[yv]-=e,e>0&&(r=super.write(e<t.length?t.subarray(0,e):t)),(e===0||this[yv]<=0)&&(r=!1,this[Ju](),super.end()),r}emit(e,...t){switch(e){case\"prefinish\":case\"finish\":return!1;case\"drain\":return typeof this[Kn]==\"number\"&&this[NI](),!1;case\"error\":return this[Im]?!1:(this[Im]=!0,super.emit(e,...t));default:return super.emit(e,...t)}}},mrt=class extends Q6{[M0](){let e=!0;try{this[UI](null,Fa.default.openSync(this[Ku],\"r\")),e=!1}finally{e&&this[Ju]()}}[NI](){let e=!0;try{if(!this[Wp]){this[Wp]=!0;do{let t=this[c6](),r=t.length===0?0:Fa.default.readSync(this[Kn],t,0,t.length,null);if(!this[l6](r,t))break}while(!0);this[Wp]=!1}e=!1}finally{e&&this[Ju]()}}[Ju](){if(this[L0]&&typeof this[Kn]==\"number\"){let e=this[Kn];this[Kn]=void 0,Fa.default.closeSync(e),this.emit(\"close\")}}},hT=class extends ihe.default{readable=!1;writable=!0;[Im]=!1;[um]=!1;[mv]=!1;[sA]=[];[GR]=!1;[Ku];[bv];[L0];[Kn];[$R];[Vp];[_j]=!1;[Q0];constructor(e,t){t=t||{},super(t),this[Ku]=e,this[Kn]=typeof t.fd==\"number\"?t.fd:void 0,this[bv]=t.mode===void 0?438:t.mode,this[Q0]=typeof t.start==\"number\"?t.start:void 0,this[L0]=typeof t.autoClose==\"boolean\"?t.autoClose:!0;let r=this[Q0]!==void 0?\"r+\":\"w\";this[$R]=t.flags===void 0,this[Vp]=t.flags===void 0?r:t.flags,this[Kn]===void 0&&this[M0]()}emit(e,...t){if(e===\"error\"){if(this[Im])return!1;this[Im]=!0}return super.emit(e,...t)}get fd(){return this[Kn]}get path(){return this[Ku]}[LI](e){this[Ju](),this[um]=!0,this.emit(\"error\",e)}[M0](){Fa.default.open(this[Ku],this[Vp],this[bv],(e,t)=>this[UI](e,t))}[UI](e,t){this[$R]&&this[Vp]===\"r+\"&&e&&e.code===\"ENOENT\"?(this[Vp]=\"w\",this[M0]()):e?this[LI](e):(this[Kn]=t,this.emit(\"open\",t),this[um]||this[Hj]())}end(e,t){return e&&this.write(e,t),this[mv]=!0,!this[um]&&!this[sA].length&&typeof this[Kn]==\"number\"&&this[FI](null,0),this}write(e,t){return typeof e==\"string\"&&(e=Buffer.from(e,t)),this[mv]?(this.emit(\"error\",new Error(\"write() after end()\")),!1):this[Kn]===void 0||this[um]||this[sA].length?(this[sA].push(e),this[GR]=!0,!1):(this[um]=!0,this[XR](e),!0)}[XR](e){Fa.default.write(this[Kn],e,0,e.length,this[Q0],(t,r)=>this[FI](t,r))}[FI](e,t){e?this[LI](e):(this[Q0]!==void 0&&typeof t==\"number\"&&(this[Q0]+=t),this[sA].length?this[Hj]():(this[um]=!1,this[mv]&&!this[_j]?(this[_j]=!0,this[Ju](),this.emit(\"finish\")):this[GR]&&(this[GR]=!1,this.emit(\"drain\"))))}[Hj](){if(this[sA].length===0)this[mv]&&this[FI](null,0);else if(this[sA].length===1)this[XR](this[sA].pop());else{let e=this[sA];this[sA]=[],drt(this[Kn],e,this[Q0],(t,r)=>this[FI](t,r))}}[Ju](){if(this[L0]&&typeof this[Kn]==\"number\"){let e=this[Kn];this[Kn]=void 0,Fa.default.close(e,t=>t?this.emit(\"error\",t):this.emit(\"close\"))}}},ahe=class extends hT{[M0](){let e;if(this[$R]&&this[Vp]===\"r+\")try{e=Fa.default.openSync(this[Ku],this[Vp],this[bv])}catch(t){if(t?.code===\"ENOENT\")return this[Vp]=\"w\",this[M0]();throw t}else e=Fa.default.openSync(this[Ku],this[Vp],this[bv]);this[UI](null,e)}[Ju](){if(this[L0]&&typeof this[Kn]==\"number\"){let e=this[Kn];this[Kn]=void 0,Fa.default.closeSync(e),this.emit(\"close\")}}[XR](e){let t=!0;try{this[FI](null,Fa.default.writeSync(this[Kn],e,0,e.length,this[Q0])),t=!1}finally{if(t)try{this[Ju]()}catch{}}}},yrt=new Map([[\"C\",\"cwd\"],[\"f\",\"file\"],[\"z\",\"gzip\"],[\"P\",\"preservePaths\"],[\"U\",\"unlink\"],[\"strip-components\",\"strip\"],[\"stripComponents\",\"strip\"],[\"keep-newer\",\"newer\"],[\"keepNewer\",\"newer\"],[\"keep-newer-files\",\"newer\"],[\"keepNewerFiles\",\"newer\"],[\"k\",\"keep\"],[\"keep-existing\",\"keep\"],[\"keepExisting\",\"keep\"],[\"m\",\"noMtime\"],[\"no-mtime\",\"noMtime\"],[\"p\",\"preserveOwner\"],[\"L\",\"follow\"],[\"h\",\"follow\"],[\"onentry\",\"onReadEntry\"]]),Ert=e=>!!e.sync&&!!e.file,Irt=e=>!e.sync&&!!e.file,Crt=e=>!!e.sync&&!e.file,wrt=e=>!e.sync&&!e.file,Brt=e=>!!e.file,vrt=e=>yrt.get(e)||e,T6=(e={})=>{if(!e)return{};let t={};for(let[r,s]of Object.entries(e)){let a=vrt(r);t[a]=s}return t.chmod===void 0&&t.noChmod===!1&&(t.chmod=!0),delete t.noChmod,t},Ov=(e,t,r,s,a)=>Object.assign((n=[],c,f)=>{Array.isArray(n)&&(c=n,n={}),typeof c==\"function\"&&(f=c,c=void 0),c?c=Array.from(c):c=[];let p=T6(n);if(a?.(p,c),Ert(p)){if(typeof f==\"function\")throw new TypeError(\"callback not supported for sync tar functions\");return e(p,c)}else if(Irt(p)){let h=t(p,c),E=f||void 0;return E?h.then(()=>E(),E):h}else if(Crt(p)){if(typeof f==\"function\")throw new TypeError(\"callback not supported for sync tar functions\");return r(p,c)}else if(wrt(p)){if(typeof f==\"function\")throw new TypeError(\"callback only supported with file option\");return s(p,c)}else throw new Error(\"impossible options??\")},{syncFile:e,asyncFile:t,syncNoFile:r,asyncNoFile:s,validate:a}),Srt=che.default.constants||{ZLIB_VERNUM:4736},lA=Object.freeze(Object.assign(Object.create(null),{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_VERSION_ERROR:-6,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,Z_MIN_WINDOWBITS:8,Z_MAX_WINDOWBITS:15,Z_DEFAULT_WINDOWBITS:15,Z_MIN_CHUNK:64,Z_MAX_CHUNK:1/0,Z_DEFAULT_CHUNK:16384,Z_MIN_MEMLEVEL:1,Z_MAX_MEMLEVEL:9,Z_DEFAULT_MEMLEVEL:8,Z_MIN_LEVEL:-1,Z_MAX_LEVEL:9,Z_DEFAULT_LEVEL:-1,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},Srt)),Drt=N0.Buffer.concat,Tpe=Object.getOwnPropertyDescriptor(N0.Buffer,\"concat\"),brt=e=>e,Wj=Tpe?.writable===!0||Tpe?.set!==void 0?e=>{N0.Buffer.concat=e?brt:Drt}:e=>{},Cm=Symbol(\"_superWrite\"),qR=class extends Error{code;errno;constructor(e,t){super(\"zlib: \"+e.message,{cause:e}),this.code=e.code,this.errno=e.errno,this.code||(this.code=\"ZLIB_ERROR\"),this.message=\"zlib: \"+e.message,Error.captureStackTrace(this,t??this.constructor)}get name(){return\"ZlibError\"}},Vj=Symbol(\"flushFlag\"),F6=class extends vm{#e=!1;#t=!1;#s;#r;#i;#n;#o;get sawError(){return this.#e}get handle(){return this.#n}get flushFlag(){return this.#s}constructor(e,t){if(!e||typeof e!=\"object\")throw new TypeError(\"invalid options for ZlibBase constructor\");if(super(e),this.#s=e.flush??0,this.#r=e.finishFlush??0,this.#i=e.fullFlushFlag??0,typeof Rpe[t]!=\"function\")throw new TypeError(\"Compression method not supported: \"+t);try{this.#n=new Rpe[t](e)}catch(r){throw new qR(r,this.constructor)}this.#o=r=>{this.#e||(this.#e=!0,this.close(),this.emit(\"error\",r))},this.#n?.on(\"error\",r=>this.#o(new qR(r))),this.once(\"end\",()=>this.close)}close(){this.#n&&(this.#n.close(),this.#n=void 0,this.emit(\"close\"))}reset(){if(!this.#e)return(0,cT.default)(this.#n,\"zlib binding closed\"),this.#n.reset?.()}flush(e){this.ended||(typeof e!=\"number\"&&(e=this.#i),this.write(Object.assign(N0.Buffer.alloc(0),{[Vj]:e})))}end(e,t,r){return typeof e==\"function\"&&(r=e,t=void 0,e=void 0),typeof t==\"function\"&&(r=t,t=void 0),e&&(t?this.write(e,t):this.write(e)),this.flush(this.#r),this.#t=!0,super.end(r)}get ended(){return this.#t}[Cm](e){return super.write(e)}write(e,t,r){if(typeof t==\"function\"&&(r=t,t=\"utf8\"),typeof e==\"string\"&&(e=N0.Buffer.from(e,t)),this.#e)return;(0,cT.default)(this.#n,\"zlib binding closed\");let s=this.#n._handle,a=s.close;s.close=()=>{};let n=this.#n.close;this.#n.close=()=>{},Wj(!0);let c;try{let p=typeof e[Vj]==\"number\"?e[Vj]:this.#s;c=this.#n._processChunk(e,p),Wj(!1)}catch(p){Wj(!1),this.#o(new qR(p,this.write))}finally{this.#n&&(this.#n._handle=s,s.close=a,this.#n.close=n,this.#n.removeAllListeners(\"error\"))}this.#n&&this.#n.on(\"error\",p=>this.#o(new qR(p,this.write)));let f;if(c)if(Array.isArray(c)&&c.length>0){let p=c[0];f=this[Cm](N0.Buffer.from(p));for(let h=1;h<c.length;h++)f=this[Cm](c[h])}else f=this[Cm](N0.Buffer.from(c));return r&&r(),f}},uhe=class extends F6{#e;#t;constructor(e,t){e=e||{},e.flush=e.flush||lA.Z_NO_FLUSH,e.finishFlush=e.finishFlush||lA.Z_FINISH,e.fullFlushFlag=lA.Z_FULL_FLUSH,super(e,t),this.#e=e.level,this.#t=e.strategy}params(e,t){if(!this.sawError){if(!this.handle)throw new Error(\"cannot switch params when binding is closed\");if(!this.handle.params)throw new Error(\"not supported in this implementation\");if(this.#e!==e||this.#t!==t){this.flush(lA.Z_SYNC_FLUSH),(0,cT.default)(this.handle,\"zlib binding closed\");let r=this.handle.flush;this.handle.flush=(s,a)=>{typeof s==\"function\"&&(a=s,s=this.flushFlag),this.flush(s),a?.()};try{this.handle.params(e,t)}finally{this.handle.flush=r}this.handle&&(this.#e=e,this.#t=t)}}}},Prt=class extends uhe{#e;constructor(e){super(e,\"Gzip\"),this.#e=e&&!!e.portable}[Cm](e){return this.#e?(this.#e=!1,e[9]=255,super[Cm](e)):super[Cm](e)}},xrt=class extends uhe{constructor(e){super(e,\"Unzip\")}},fhe=class extends F6{constructor(e,t){e=e||{},e.flush=e.flush||lA.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||lA.BROTLI_OPERATION_FINISH,e.fullFlushFlag=lA.BROTLI_OPERATION_FLUSH,super(e,t)}},krt=class extends fhe{constructor(e){super(e,\"BrotliCompress\")}},Qrt=class extends fhe{constructor(e){super(e,\"BrotliDecompress\")}},Ahe=class extends F6{constructor(e,t){e=e||{},e.flush=e.flush||lA.ZSTD_e_continue,e.finishFlush=e.finishFlush||lA.ZSTD_e_end,e.fullFlushFlag=lA.ZSTD_e_flush,super(e,t)}},Rrt=class extends Ahe{constructor(e){super(e,\"ZstdCompress\")}},Trt=class extends Ahe{constructor(e){super(e,\"ZstdDecompress\")}},Frt=(e,t)=>{if(Number.isSafeInteger(e))e<0?Ort(e,t):Nrt(e,t);else throw Error(\"cannot encode number outside of javascript safe integer range\");return t},Nrt=(e,t)=>{t[0]=128;for(var r=t.length;r>1;r--)t[r-1]=e&255,e=Math.floor(e/256)},Ort=(e,t)=>{t[0]=255;var r=!1;e=e*-1;for(var s=t.length;s>1;s--){var a=e&255;e=Math.floor(e/256),r?t[s-1]=phe(a):a===0?t[s-1]=0:(r=!0,t[s-1]=hhe(a))}},Lrt=e=>{let t=e[0],r=t===128?Urt(e.subarray(1,e.length)):t===255?Mrt(e):null;if(r===null)throw Error(\"invalid base256 encoding\");if(!Number.isSafeInteger(r))throw Error(\"parsed number outside of javascript safe integer range\");return r},Mrt=e=>{for(var t=e.length,r=0,s=!1,a=t-1;a>-1;a--){var n=Number(e[a]),c;s?c=phe(n):n===0?c=n:(s=!0,c=hhe(n)),c!==0&&(r-=c*Math.pow(256,t-a-1))}return r},Urt=e=>{for(var t=e.length,r=0,s=t-1;s>-1;s--){var a=Number(e[s]);a!==0&&(r+=a*Math.pow(256,t-s-1))}return r},phe=e=>(255^e)&255,hhe=e=>(255^e)+1&255,_rt={};srt(_rt,{code:()=>N6,isCode:()=>eT,isName:()=>Hrt,name:()=>dT});eT=e=>dT.has(e),Hrt=e=>N6.has(e),dT=new Map([[\"0\",\"File\"],[\"\",\"OldFile\"],[\"1\",\"Link\"],[\"2\",\"SymbolicLink\"],[\"3\",\"CharacterDevice\"],[\"4\",\"BlockDevice\"],[\"5\",\"Directory\"],[\"6\",\"FIFO\"],[\"7\",\"ContiguousFile\"],[\"g\",\"GlobalExtendedHeader\"],[\"x\",\"ExtendedHeader\"],[\"A\",\"SolarisACL\"],[\"D\",\"GNUDumpDir\"],[\"I\",\"Inode\"],[\"K\",\"NextFileHasLongLinkpath\"],[\"L\",\"NextFileHasLongPath\"],[\"M\",\"ContinuationFile\"],[\"N\",\"OldGnuLongPath\"],[\"S\",\"SparseFile\"],[\"V\",\"TapeVolumeHeader\"],[\"X\",\"OldExtendedHeader\"]]),N6=new Map(Array.from(dT).map(e=>[e[1],e[0]])),wm=class{cksumValid=!1;needPax=!1;nullBlock=!1;block;path;mode;uid;gid;size;cksum;#e=\"Unsupported\";linkpath;uname;gname;devmaj=0;devmin=0;atime;ctime;mtime;charset;comment;constructor(e,t=0,r,s){Buffer.isBuffer(e)?this.decode(e,t||0,r,s):e&&this.#t(e)}decode(e,t,r,s){if(t||(t=0),!e||!(e.length>=t+512))throw new Error(\"need 512 bytes for header\");this.path=r?.path??fm(e,t,100),this.mode=r?.mode??s?.mode??R0(e,t+100,8),this.uid=r?.uid??s?.uid??R0(e,t+108,8),this.gid=r?.gid??s?.gid??R0(e,t+116,8),this.size=r?.size??s?.size??R0(e,t+124,12),this.mtime=r?.mtime??s?.mtime??Yj(e,t+136,12),this.cksum=R0(e,t+148,12),s&&this.#t(s,!0),r&&this.#t(r);let a=fm(e,t+156,1);if(eT(a)&&(this.#e=a||\"0\"),this.#e===\"0\"&&this.path.slice(-1)===\"/\"&&(this.#e=\"5\"),this.#e===\"5\"&&(this.size=0),this.linkpath=fm(e,t+157,100),e.subarray(t+257,t+265).toString()===\"ustar\\x0000\")if(this.uname=r?.uname??s?.uname??fm(e,t+265,32),this.gname=r?.gname??s?.gname??fm(e,t+297,32),this.devmaj=r?.devmaj??s?.devmaj??R0(e,t+329,8)??0,this.devmin=r?.devmin??s?.devmin??R0(e,t+337,8)??0,e[t+475]!==0){let c=fm(e,t+345,155);this.path=c+\"/\"+this.path}else{let c=fm(e,t+345,130);c&&(this.path=c+\"/\"+this.path),this.atime=r?.atime??s?.atime??Yj(e,t+476,12),this.ctime=r?.ctime??s?.ctime??Yj(e,t+488,12)}let n=256;for(let c=t;c<t+148;c++)n+=e[c];for(let c=t+156;c<t+512;c++)n+=e[c];this.cksumValid=n===this.cksum,this.cksum===void 0&&n===256&&(this.nullBlock=!0)}#t(e,t=!1){Object.assign(this,Object.fromEntries(Object.entries(e).filter(([r,s])=>!(s==null||r===\"path\"&&t||r===\"linkpath\"&&t||r===\"global\"))))}encode(e,t=0){if(e||(e=this.block=Buffer.alloc(512)),this.#e===\"Unsupported\"&&(this.#e=\"0\"),!(e.length>=t+512))throw new Error(\"need 512 bytes for header\");let r=this.ctime||this.atime?130:155,s=jrt(this.path||\"\",r),a=s[0],n=s[1];this.needPax=!!s[2],this.needPax=Am(e,t,100,a)||this.needPax,this.needPax=T0(e,t+100,8,this.mode)||this.needPax,this.needPax=T0(e,t+108,8,this.uid)||this.needPax,this.needPax=T0(e,t+116,8,this.gid)||this.needPax,this.needPax=T0(e,t+124,12,this.size)||this.needPax,this.needPax=Kj(e,t+136,12,this.mtime)||this.needPax,e[t+156]=this.#e.charCodeAt(0),this.needPax=Am(e,t+157,100,this.linkpath)||this.needPax,e.write(\"ustar\\x0000\",t+257,8),this.needPax=Am(e,t+265,32,this.uname)||this.needPax,this.needPax=Am(e,t+297,32,this.gname)||this.needPax,this.needPax=T0(e,t+329,8,this.devmaj)||this.needPax,this.needPax=T0(e,t+337,8,this.devmin)||this.needPax,this.needPax=Am(e,t+345,r,n)||this.needPax,e[t+475]!==0?this.needPax=Am(e,t+345,155,n)||this.needPax:(this.needPax=Am(e,t+345,130,n)||this.needPax,this.needPax=Kj(e,t+476,12,this.atime)||this.needPax,this.needPax=Kj(e,t+488,12,this.ctime)||this.needPax);let c=256;for(let f=t;f<t+148;f++)c+=e[f];for(let f=t+156;f<t+512;f++)c+=e[f];return this.cksum=c,T0(e,t+148,8,this.cksum),this.cksumValid=!0,this.needPax}get type(){return this.#e===\"Unsupported\"?this.#e:dT.get(this.#e)}get typeKey(){return this.#e}set type(e){let t=String(N6.get(e));if(eT(t)||t===\"Unsupported\")this.#e=t;else if(eT(e))this.#e=e;else throw new TypeError(\"invalid entry type: \"+e)}},jrt=(e,t)=>{let r=e,s=\"\",a,n=ym.posix.parse(e).root||\".\";if(Buffer.byteLength(r)<100)a=[r,s,!1];else{s=ym.posix.dirname(r),r=ym.posix.basename(r);do Buffer.byteLength(r)<=100&&Buffer.byteLength(s)<=t?a=[r,s,!1]:Buffer.byteLength(r)>100&&Buffer.byteLength(s)<=t?a=[r.slice(0,99),s,!0]:(r=ym.posix.join(ym.posix.basename(s),r),s=ym.posix.dirname(s));while(s!==n&&a===void 0);a||(a=[e.slice(0,99),\"\",!0])}return a},fm=(e,t,r)=>e.subarray(t,t+r).toString(\"utf8\").replace(/\\0.*/,\"\"),Yj=(e,t,r)=>Grt(R0(e,t,r)),Grt=e=>e===void 0?void 0:new Date(e*1e3),R0=(e,t,r)=>Number(e[t])&128?Lrt(e.subarray(t,t+r)):Wrt(e,t,r),qrt=e=>isNaN(e)?void 0:e,Wrt=(e,t,r)=>qrt(parseInt(e.subarray(t,t+r).toString(\"utf8\").replace(/\\0.*$/,\"\").trim(),8)),Vrt={12:8589934591,8:2097151},T0=(e,t,r,s)=>s===void 0?!1:s>Vrt[r]||s<0?(Frt(s,e.subarray(t,t+r)),!0):(Yrt(e,t,r,s),!1),Yrt=(e,t,r,s)=>e.write(Krt(s,r),t,r,\"ascii\"),Krt=(e,t)=>Jrt(Math.floor(e).toString(8),t),Jrt=(e,t)=>(e.length===t-1?e:new Array(t-e.length-1).join(\"0\")+e+\" \")+\"\\0\",Kj=(e,t,r,s)=>s===void 0?!1:T0(e,t,r,s.getTime()/1e3),zrt=new Array(156).join(\"\\0\"),Am=(e,t,r,s)=>s===void 0?!1:(e.write(s+zrt,t,r,\"utf8\"),s.length!==Buffer.byteLength(s)||s.length>r),uT=class dhe{atime;mtime;ctime;charset;comment;gid;uid;gname;uname;linkpath;dev;ino;nlink;path;size;mode;global;constructor(t,r=!1){this.atime=t.atime,this.charset=t.charset,this.comment=t.comment,this.ctime=t.ctime,this.dev=t.dev,this.gid=t.gid,this.global=r,this.gname=t.gname,this.ino=t.ino,this.linkpath=t.linkpath,this.mtime=t.mtime,this.nlink=t.nlink,this.path=t.path,this.size=t.size,this.uid=t.uid,this.uname=t.uname}encode(){let t=this.encodeBody();if(t===\"\")return Buffer.allocUnsafe(0);let r=Buffer.byteLength(t),s=512*Math.ceil(1+r/512),a=Buffer.allocUnsafe(s);for(let n=0;n<512;n++)a[n]=0;new wm({path:(\"PaxHeader/\"+(0,ghe.basename)(this.path??\"\")).slice(0,99),mode:this.mode||420,uid:this.uid,gid:this.gid,size:r,mtime:this.mtime,type:this.global?\"GlobalExtendedHeader\":\"ExtendedHeader\",linkpath:\"\",uname:this.uname||\"\",gname:this.gname||\"\",devmaj:0,devmin:0,atime:this.atime,ctime:this.ctime}).encode(a),a.write(t,512,r,\"utf8\");for(let n=r+512;n<a.length;n++)a[n]=0;return a}encodeBody(){return this.encodeField(\"path\")+this.encodeField(\"ctime\")+this.encodeField(\"atime\")+this.encodeField(\"dev\")+this.encodeField(\"ino\")+this.encodeField(\"nlink\")+this.encodeField(\"charset\")+this.encodeField(\"comment\")+this.encodeField(\"gid\")+this.encodeField(\"gname\")+this.encodeField(\"linkpath\")+this.encodeField(\"mtime\")+this.encodeField(\"size\")+this.encodeField(\"uid\")+this.encodeField(\"uname\")}encodeField(t){if(this[t]===void 0)return\"\";let r=this[t],s=r instanceof Date?r.getTime()/1e3:r,a=\" \"+(t===\"dev\"||t===\"ino\"||t===\"nlink\"?\"SCHILY.\":\"\")+t+\"=\"+s+`\n`,n=Buffer.byteLength(a),c=Math.floor(Math.log(n)/Math.log(10))+1;return n+c>=Math.pow(10,c)&&(c+=1),c+n+a}static parse(t,r,s=!1){return new dhe(Zrt(Xrt(t),r),s)}},Zrt=(e,t)=>t?Object.assign({},t,e):e,Xrt=e=>e.replace(/\\n$/,\"\").split(`\n`).reduce($rt,Object.create(null)),$rt=(e,t)=>{let r=parseInt(t,10);if(r!==Buffer.byteLength(t)+1)return e;t=t.slice((r+\" \").length);let s=t.split(\"=\"),a=s.shift();if(!a)return e;let n=a.replace(/^SCHILY\\.(dev|ino|nlink)/,\"$1\"),c=s.join(\"=\");return e[n]=/^([A-Z]+\\.)?([mac]|birth|creation)time$/.test(n)?new Date(Number(c)*1e3):/^[0-9]+$/.test(c)?+c:c,e},ent=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,cn=ent!==\"win32\"?e=>e:e=>e&&e.replace(/\\\\/g,\"/\"),mhe=class extends vm{extended;globalExtended;header;startBlockSize;blockRemain;remain;type;meta=!1;ignore=!1;path;mode;uid;gid;uname;gname;size=0;mtime;atime;ctime;linkpath;dev;ino;nlink;invalid=!1;absolute;unsupported=!1;constructor(e,t,r){switch(super({}),this.pause(),this.extended=t,this.globalExtended=r,this.header=e,this.remain=e.size??0,this.startBlockSize=512*Math.ceil(this.remain/512),this.blockRemain=this.startBlockSize,this.type=e.type,this.type){case\"File\":case\"OldFile\":case\"Link\":case\"SymbolicLink\":case\"CharacterDevice\":case\"BlockDevice\":case\"Directory\":case\"FIFO\":case\"ContiguousFile\":case\"GNUDumpDir\":break;case\"NextFileHasLongLinkpath\":case\"NextFileHasLongPath\":case\"OldGnuLongPath\":case\"GlobalExtendedHeader\":case\"ExtendedHeader\":case\"OldExtendedHeader\":this.meta=!0;break;default:this.ignore=!0}if(!e.path)throw new Error(\"no path provided for tar.ReadEntry\");this.path=cn(e.path),this.mode=e.mode,this.mode&&(this.mode=this.mode&4095),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=this.remain,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=e.linkpath?cn(e.linkpath):void 0,this.uname=e.uname,this.gname=e.gname,t&&this.#e(t),r&&this.#e(r,!0)}write(e){let t=e.length;if(t>this.blockRemain)throw new Error(\"writing more to entry than is appropriate\");let r=this.remain,s=this.blockRemain;return this.remain=Math.max(0,r-t),this.blockRemain=Math.max(0,s-t),this.ignore?!0:r>=t?super.write(e):super.write(e.subarray(0,r))}#e(e,t=!1){e.path&&(e.path=cn(e.path)),e.linkpath&&(e.linkpath=cn(e.linkpath)),Object.assign(this,Object.fromEntries(Object.entries(e).filter(([r,s])=>!(s==null||r===\"path\"&&t))))}},mT=(e,t,r,s={})=>{e.file&&(s.file=e.file),e.cwd&&(s.cwd=e.cwd),s.code=r instanceof Error&&r.code||t,s.tarCode=t,!e.strict&&s.recoverable!==!1?(r instanceof Error&&(s=Object.assign(r,s),r=r.message),e.emit(\"warn\",t,r,s)):r instanceof Error?e.emit(\"error\",Object.assign(r,s)):e.emit(\"error\",Object.assign(new Error(`${t}: ${r}`),s))},tnt=1024*1024,u6=Buffer.from([31,139]),f6=Buffer.from([40,181,47,253]),rnt=Math.max(u6.length,f6.length),Mc=Symbol(\"state\"),pm=Symbol(\"writeEntry\"),Gp=Symbol(\"readEntry\"),Jj=Symbol(\"nextEntry\"),Fpe=Symbol(\"processEntry\"),oA=Symbol(\"extendedHeader\"),Ev=Symbol(\"globalExtendedHeader\"),P0=Symbol(\"meta\"),Npe=Symbol(\"emitMeta\"),Ci=Symbol(\"buffer\"),qp=Symbol(\"queue\"),x0=Symbol(\"ended\"),zj=Symbol(\"emittedEnd\"),hm=Symbol(\"emit\"),hs=Symbol(\"unzip\"),WR=Symbol(\"consumeChunk\"),VR=Symbol(\"consumeChunkSub\"),Zj=Symbol(\"consumeBody\"),Ope=Symbol(\"consumeMeta\"),Lpe=Symbol(\"consumeHeader\"),Iv=Symbol(\"consuming\"),Xj=Symbol(\"bufferConcat\"),YR=Symbol(\"maybeEnd\"),kI=Symbol(\"writing\"),k0=Symbol(\"aborted\"),KR=Symbol(\"onDone\"),gm=Symbol(\"sawValidEntry\"),JR=Symbol(\"sawNullBlock\"),zR=Symbol(\"sawEOF\"),Mpe=Symbol(\"closeStream\"),nnt=()=>!0,Bm=class extends lhe.EventEmitter{file;strict;maxMetaEntrySize;filter;brotli;zstd;writable=!0;readable=!1;[qp]=[];[Ci];[Gp];[pm];[Mc]=\"begin\";[P0]=\"\";[oA];[Ev];[x0]=!1;[hs];[k0]=!1;[gm];[JR]=!1;[zR]=!1;[kI]=!1;[Iv]=!1;[zj]=!1;constructor(e={}){super(),this.file=e.file||\"\",this.on(KR,()=>{(this[Mc]===\"begin\"||this[gm]===!1)&&this.warn(\"TAR_BAD_ARCHIVE\",\"Unrecognized archive format\")}),e.ondone?this.on(KR,e.ondone):this.on(KR,()=>{this.emit(\"prefinish\"),this.emit(\"finish\"),this.emit(\"end\")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||tnt,this.filter=typeof e.filter==\"function\"?e.filter:nnt;let t=e.file&&(e.file.endsWith(\".tar.br\")||e.file.endsWith(\".tbr\"));this.brotli=!(e.gzip||e.zstd)&&e.brotli!==void 0?e.brotli:t?void 0:!1;let r=e.file&&(e.file.endsWith(\".tar.zst\")||e.file.endsWith(\".tzst\"));this.zstd=!(e.gzip||e.brotli)&&e.zstd!==void 0?e.zstd:r?!0:void 0,this.on(\"end\",()=>this[Mpe]()),typeof e.onwarn==\"function\"&&this.on(\"warn\",e.onwarn),typeof e.onReadEntry==\"function\"&&this.on(\"entry\",e.onReadEntry)}warn(e,t,r={}){mT(this,e,t,r)}[Lpe](e,t){this[gm]===void 0&&(this[gm]=!1);let r;try{r=new wm(e,t,this[oA],this[Ev])}catch(s){return this.warn(\"TAR_ENTRY_INVALID\",s)}if(r.nullBlock)this[JR]?(this[zR]=!0,this[Mc]===\"begin\"&&(this[Mc]=\"header\"),this[hm](\"eof\")):(this[JR]=!0,this[hm](\"nullBlock\"));else if(this[JR]=!1,!r.cksumValid)this.warn(\"TAR_ENTRY_INVALID\",\"checksum failure\",{header:r});else if(!r.path)this.warn(\"TAR_ENTRY_INVALID\",\"path is required\",{header:r});else{let s=r.type;if(/^(Symbolic)?Link$/.test(s)&&!r.linkpath)this.warn(\"TAR_ENTRY_INVALID\",\"linkpath required\",{header:r});else if(!/^(Symbolic)?Link$/.test(s)&&!/^(Global)?ExtendedHeader$/.test(s)&&r.linkpath)this.warn(\"TAR_ENTRY_INVALID\",\"linkpath forbidden\",{header:r});else{let a=this[pm]=new mhe(r,this[oA],this[Ev]);if(!this[gm])if(a.remain){let n=()=>{a.invalid||(this[gm]=!0)};a.on(\"end\",n)}else this[gm]=!0;a.meta?a.size>this.maxMetaEntrySize?(a.ignore=!0,this[hm](\"ignoredEntry\",a),this[Mc]=\"ignore\",a.resume()):a.size>0&&(this[P0]=\"\",a.on(\"data\",n=>this[P0]+=n),this[Mc]=\"meta\"):(this[oA]=void 0,a.ignore=a.ignore||!this.filter(a.path,a),a.ignore?(this[hm](\"ignoredEntry\",a),this[Mc]=a.remain?\"ignore\":\"header\",a.resume()):(a.remain?this[Mc]=\"body\":(this[Mc]=\"header\",a.end()),this[Gp]?this[qp].push(a):(this[qp].push(a),this[Jj]())))}}}[Mpe](){queueMicrotask(()=>this.emit(\"close\"))}[Fpe](e){let t=!0;if(!e)this[Gp]=void 0,t=!1;else if(Array.isArray(e)){let[r,...s]=e;this.emit(r,...s)}else this[Gp]=e,this.emit(\"entry\",e),e.emittedEnd||(e.on(\"end\",()=>this[Jj]()),t=!1);return t}[Jj](){do;while(this[Fpe](this[qp].shift()));if(!this[qp].length){let e=this[Gp];!e||e.flowing||e.size===e.remain?this[kI]||this.emit(\"drain\"):e.once(\"drain\",()=>this.emit(\"drain\"))}}[Zj](e,t){let r=this[pm];if(!r)throw new Error(\"attempt to consume body without entry??\");let s=r.blockRemain??0,a=s>=e.length&&t===0?e:e.subarray(t,t+s);return r.write(a),r.blockRemain||(this[Mc]=\"header\",this[pm]=void 0,r.end()),a.length}[Ope](e,t){let r=this[pm],s=this[Zj](e,t);return!this[pm]&&r&&this[Npe](r),s}[hm](e,t,r){!this[qp].length&&!this[Gp]?this.emit(e,t,r):this[qp].push([e,t,r])}[Npe](e){switch(this[hm](\"meta\",this[P0]),e.type){case\"ExtendedHeader\":case\"OldExtendedHeader\":this[oA]=uT.parse(this[P0],this[oA],!1);break;case\"GlobalExtendedHeader\":this[Ev]=uT.parse(this[P0],this[Ev],!0);break;case\"NextFileHasLongPath\":case\"OldGnuLongPath\":{let t=this[oA]??Object.create(null);this[oA]=t,t.path=this[P0].replace(/\\0.*/,\"\");break}case\"NextFileHasLongLinkpath\":{let t=this[oA]||Object.create(null);this[oA]=t,t.linkpath=this[P0].replace(/\\0.*/,\"\");break}default:throw new Error(\"unknown meta: \"+e.type)}}abort(e){this[k0]=!0,this.emit(\"abort\",e),this.warn(\"TAR_ABORT\",e,{recoverable:!1})}write(e,t,r){if(typeof t==\"function\"&&(r=t,t=void 0),typeof e==\"string\"&&(e=Buffer.from(e,typeof t==\"string\"?t:\"utf8\")),this[k0])return r?.(),!1;if((this[hs]===void 0||this.brotli===void 0&&this[hs]===!1)&&e){if(this[Ci]&&(e=Buffer.concat([this[Ci],e]),this[Ci]=void 0),e.length<rnt)return this[Ci]=e,r?.(),!0;for(let c=0;this[hs]===void 0&&c<u6.length;c++)e[c]!==u6[c]&&(this[hs]=!1);let a=!1;if(this[hs]===!1&&this.zstd!==!1){a=!0;for(let c=0;c<f6.length;c++)if(e[c]!==f6[c]){a=!1;break}}let n=this.brotli===void 0&&!a;if(this[hs]===!1&&n)if(e.length<512)if(this[x0])this.brotli=!0;else return this[Ci]=e,r?.(),!0;else try{new wm(e.subarray(0,512)),this.brotli=!1}catch{this.brotli=!0}if(this[hs]===void 0||this[hs]===!1&&(this.brotli||a)){let c=this[x0];this[x0]=!1,this[hs]=this[hs]===void 0?new xrt({}):a?new Trt({}):new Qrt({}),this[hs].on(\"data\",p=>this[WR](p)),this[hs].on(\"error\",p=>this.abort(p)),this[hs].on(\"end\",()=>{this[x0]=!0,this[WR]()}),this[kI]=!0;let f=!!this[hs][c?\"end\":\"write\"](e);return this[kI]=!1,r?.(),f}}this[kI]=!0,this[hs]?this[hs].write(e):this[WR](e),this[kI]=!1;let s=this[qp].length?!1:this[Gp]?this[Gp].flowing:!0;return!s&&!this[qp].length&&this[Gp]?.once(\"drain\",()=>this.emit(\"drain\")),r?.(),s}[Xj](e){e&&!this[k0]&&(this[Ci]=this[Ci]?Buffer.concat([this[Ci],e]):e)}[YR](){if(this[x0]&&!this[zj]&&!this[k0]&&!this[Iv]){this[zj]=!0;let e=this[pm];if(e&&e.blockRemain){let t=this[Ci]?this[Ci].length:0;this.warn(\"TAR_BAD_ARCHIVE\",`Truncated input (needed ${e.blockRemain} more bytes, only ${t} available)`,{entry:e}),this[Ci]&&e.write(this[Ci]),e.end()}this[hm](KR)}}[WR](e){if(this[Iv]&&e)this[Xj](e);else if(!e&&!this[Ci])this[YR]();else if(e){if(this[Iv]=!0,this[Ci]){this[Xj](e);let t=this[Ci];this[Ci]=void 0,this[VR](t)}else this[VR](e);for(;this[Ci]&&this[Ci]?.length>=512&&!this[k0]&&!this[zR];){let t=this[Ci];this[Ci]=void 0,this[VR](t)}this[Iv]=!1}(!this[Ci]||this[x0])&&this[YR]()}[VR](e){let t=0,r=e.length;for(;t+512<=r&&!this[k0]&&!this[zR];)switch(this[Mc]){case\"begin\":case\"header\":this[Lpe](e,t),t+=512;break;case\"ignore\":case\"body\":t+=this[Zj](e,t);break;case\"meta\":t+=this[Ope](e,t);break;default:throw new Error(\"invalid state: \"+this[Mc])}t<r&&(this[Ci]?this[Ci]=Buffer.concat([e.subarray(t),this[Ci]]):this[Ci]=e.subarray(t))}end(e,t,r){return typeof e==\"function\"&&(r=e,t=void 0,e=void 0),typeof t==\"function\"&&(r=t,t=void 0),typeof e==\"string\"&&(e=Buffer.from(e,t)),r&&this.once(\"finish\",r),this[k0]||(this[hs]?(e&&this[hs].write(e),this[hs].end()):(this[x0]=!0,(this.brotli===void 0||this.zstd===void 0)&&(e=e||Buffer.alloc(0)),e&&this.write(e),this[YR]())),this}},Pv=e=>{let t=e.length-1,r=-1;for(;t>-1&&e.charAt(t)===\"/\";)r=t,t--;return r===-1?e:e.slice(0,r)},int=e=>{let t=e.onReadEntry;e.onReadEntry=t?r=>{t(r),r.resume()}:r=>r.resume()},yhe=(e,t)=>{let r=new Map(t.map(n=>[Pv(n),!0])),s=e.filter,a=(n,c=\"\")=>{let f=c||(0,gT.parse)(n).root||\".\",p;if(n===f)p=!1;else{let h=r.get(n);h!==void 0?p=h:p=a((0,gT.dirname)(n),f)}return r.set(n,p),p};e.filter=s?(n,c)=>s(n,c)&&a(Pv(n)):n=>a(Pv(n))},snt=e=>{let t=new Bm(e),r=e.file,s;try{s=Em.default.openSync(r,\"r\");let a=Em.default.fstatSync(s),n=e.maxReadSize||16*1024*1024;if(a.size<n){let c=Buffer.allocUnsafe(a.size),f=Em.default.readSync(s,c,0,a.size,0);t.end(f===c.byteLength?c:c.subarray(0,f))}else{let c=0,f=Buffer.allocUnsafe(n);for(;c<a.size;){let p=Em.default.readSync(s,f,0,n,c);if(p===0)break;c+=p,t.write(f.subarray(0,p))}t.end()}}finally{if(typeof s==\"number\")try{Em.default.closeSync(s)}catch{}}},ont=(e,t)=>{let r=new Bm(e),s=e.maxReadSize||16*1024*1024,a=e.file;return new Promise((n,c)=>{r.on(\"error\",c),r.on(\"end\",n),Em.default.stat(a,(f,p)=>{if(f)c(f);else{let h=new Q6(a,{readSize:s,size:p.size});h.on(\"error\",c),h.pipe(r)}})})},yT=Ov(snt,ont,e=>new Bm(e),e=>new Bm(e),(e,t)=>{t?.length&&yhe(e,t),e.noResume||int(e)}),Ehe=(e,t,r)=>(e&=4095,r&&(e=(e|384)&-19),t&&(e&256&&(e|=64),e&32&&(e|=8),e&4&&(e|=1)),e),{isAbsolute:ant,parse:Upe}=Ihe.win32,O6=e=>{let t=\"\",r=Upe(e);for(;ant(e)||r.root;){let s=e.charAt(0)===\"/\"&&e.slice(0,4)!==\"//?/\"?\"/\":r.root;e=e.slice(s.length),t+=s,r=Upe(e)}return[t,e]},ET=[\"|\",\"<\",\">\",\"?\",\":\"],L6=ET.map(e=>String.fromCharCode(61440+e.charCodeAt(0))),lnt=new Map(ET.map((e,t)=>[e,L6[t]])),cnt=new Map(L6.map((e,t)=>[e,ET[t]])),_pe=e=>ET.reduce((t,r)=>t.split(r).join(lnt.get(r)),e),unt=e=>L6.reduce((t,r)=>t.split(r).join(cnt.get(r)),e),Che=(e,t)=>t?(e=cn(e).replace(/^\\.(\\/|$)/,\"\"),Pv(t)+\"/\"+e):cn(e),fnt=16*1024*1024,Hpe=Symbol(\"process\"),jpe=Symbol(\"file\"),Gpe=Symbol(\"directory\"),p6=Symbol(\"symlink\"),qpe=Symbol(\"hardlink\"),Cv=Symbol(\"header\"),tT=Symbol(\"read\"),h6=Symbol(\"lstat\"),rT=Symbol(\"onlstat\"),g6=Symbol(\"onread\"),d6=Symbol(\"onreadlink\"),m6=Symbol(\"openfile\"),y6=Symbol(\"onopenfile\"),F0=Symbol(\"close\"),fT=Symbol(\"mode\"),E6=Symbol(\"awaitDrain\"),$j=Symbol(\"ondrain\"),aA=Symbol(\"prefix\"),whe=class extends vm{path;portable;myuid=process.getuid&&process.getuid()||0;myuser=process.env.USER||\"\";maxReadSize;linkCache;statCache;preservePaths;cwd;strict;mtime;noPax;noMtime;prefix;fd;blockLen=0;blockRemain=0;buf;pos=0;remain=0;length=0;offset=0;win32;absolute;header;type;linkpath;stat;onWriteEntry;#e=!1;constructor(e,t={}){let r=T6(t);super(),this.path=cn(e),this.portable=!!r.portable,this.maxReadSize=r.maxReadSize||fnt,this.linkCache=r.linkCache||new Map,this.statCache=r.statCache||new Map,this.preservePaths=!!r.preservePaths,this.cwd=cn(r.cwd||process.cwd()),this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.mtime=r.mtime,this.prefix=r.prefix?cn(r.prefix):void 0,this.onWriteEntry=r.onWriteEntry,typeof r.onwarn==\"function\"&&this.on(\"warn\",r.onwarn);let s=!1;if(!this.preservePaths){let[n,c]=O6(this.path);n&&typeof c==\"string\"&&(this.path=c,s=n)}this.win32=!!r.win32||process.platform===\"win32\",this.win32&&(this.path=unt(this.path.replace(/\\\\/g,\"/\")),e=e.replace(/\\\\/g,\"/\")),this.absolute=cn(r.absolute||A6.default.resolve(this.cwd,e)),this.path===\"\"&&(this.path=\"./\"),s&&this.warn(\"TAR_ENTRY_INFO\",`stripping ${s} from absolute path`,{entry:this,path:s+this.path});let a=this.statCache.get(this.absolute);a?this[rT](a):this[h6]()}warn(e,t,r={}){return mT(this,e,t,r)}emit(e,...t){return e===\"error\"&&(this.#e=!0),super.emit(e,...t)}[h6](){Yu.default.lstat(this.absolute,(e,t)=>{if(e)return this.emit(\"error\",e);this[rT](t)})}[rT](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=hnt(e),this.emit(\"stat\",e),this[Hpe]()}[Hpe](){switch(this.type){case\"File\":return this[jpe]();case\"Directory\":return this[Gpe]();case\"SymbolicLink\":return this[p6]();default:return this.end()}}[fT](e){return Ehe(e,this.type===\"Directory\",this.portable)}[aA](e){return Che(e,this.prefix)}[Cv](){if(!this.stat)throw new Error(\"cannot write header before stat\");this.type===\"Directory\"&&this.portable&&(this.noMtime=!0),this.onWriteEntry?.(this),this.header=new wm({path:this[aA](this.path),linkpath:this.type===\"Link\"&&this.linkpath!==void 0?this[aA](this.linkpath):this.linkpath,mode:this[fT](this.stat.mode),uid:this.portable?void 0:this.stat.uid,gid:this.portable?void 0:this.stat.gid,size:this.stat.size,mtime:this.noMtime?void 0:this.mtime||this.stat.mtime,type:this.type===\"Unsupported\"?void 0:this.type,uname:this.portable?void 0:this.stat.uid===this.myuid?this.myuser:\"\",atime:this.portable?void 0:this.stat.atime,ctime:this.portable?void 0:this.stat.ctime}),this.header.encode()&&!this.noPax&&super.write(new uT({atime:this.portable?void 0:this.header.atime,ctime:this.portable?void 0:this.header.ctime,gid:this.portable?void 0:this.header.gid,mtime:this.noMtime?void 0:this.mtime||this.header.mtime,path:this[aA](this.path),linkpath:this.type===\"Link\"&&this.linkpath!==void 0?this[aA](this.linkpath):this.linkpath,size:this.header.size,uid:this.portable?void 0:this.header.uid,uname:this.portable?void 0:this.header.uname,dev:this.portable?void 0:this.stat.dev,ino:this.portable?void 0:this.stat.ino,nlink:this.portable?void 0:this.stat.nlink}).encode());let e=this.header?.block;if(!e)throw new Error(\"failed to encode header\");super.write(e)}[Gpe](){if(!this.stat)throw new Error(\"cannot create directory entry without stat\");this.path.slice(-1)!==\"/\"&&(this.path+=\"/\"),this.stat.size=0,this[Cv](),this.end()}[p6](){Yu.default.readlink(this.absolute,(e,t)=>{if(e)return this.emit(\"error\",e);this[d6](t)})}[d6](e){this.linkpath=cn(e),this[Cv](),this.end()}[qpe](e){if(!this.stat)throw new Error(\"cannot create link entry without stat\");this.type=\"Link\",this.linkpath=cn(A6.default.relative(this.cwd,e)),this.stat.size=0,this[Cv](),this.end()}[jpe](){if(!this.stat)throw new Error(\"cannot create file entry without stat\");if(this.stat.nlink>1){let e=`${this.stat.dev}:${this.stat.ino}`,t=this.linkCache.get(e);if(t?.indexOf(this.cwd)===0)return this[qpe](t);this.linkCache.set(e,this.absolute)}if(this[Cv](),this.stat.size===0)return this.end();this[m6]()}[m6](){Yu.default.open(this.absolute,\"r\",(e,t)=>{if(e)return this.emit(\"error\",e);this[y6](t)})}[y6](e){if(this.fd=e,this.#e)return this[F0]();if(!this.stat)throw new Error(\"should stat before calling onopenfile\");this.blockLen=512*Math.ceil(this.stat.size/512),this.blockRemain=this.blockLen;let t=Math.min(this.blockLen,this.maxReadSize);this.buf=Buffer.allocUnsafe(t),this.offset=0,this.pos=0,this.remain=this.stat.size,this.length=this.buf.length,this[tT]()}[tT](){let{fd:e,buf:t,offset:r,length:s,pos:a}=this;if(e===void 0||t===void 0)throw new Error(\"cannot read file without first opening\");Yu.default.read(e,t,r,s,a,(n,c)=>{if(n)return this[F0](()=>this.emit(\"error\",n));this[g6](c)})}[F0](e=()=>{}){this.fd!==void 0&&Yu.default.close(this.fd,e)}[g6](e){if(e<=0&&this.remain>0){let r=Object.assign(new Error(\"encountered unexpected EOF\"),{path:this.absolute,syscall:\"read\",code:\"EOF\"});return this[F0](()=>this.emit(\"error\",r))}if(e>this.remain){let r=Object.assign(new Error(\"did not encounter expected EOF\"),{path:this.absolute,syscall:\"read\",code:\"EOF\"});return this[F0](()=>this.emit(\"error\",r))}if(!this.buf)throw new Error(\"should have created buffer prior to reading\");if(e===this.remain)for(let r=e;r<this.length&&e<this.blockRemain;r++)this.buf[r+this.offset]=0,e++,this.remain++;let t=this.offset===0&&e===this.buf.length?this.buf:this.buf.subarray(this.offset,this.offset+e);this.write(t)?this[$j]():this[E6](()=>this[$j]())}[E6](e){this.once(\"drain\",e)}write(e,t,r){if(typeof t==\"function\"&&(r=t,t=void 0),typeof e==\"string\"&&(e=Buffer.from(e,typeof t==\"string\"?t:\"utf8\")),this.blockRemain<e.length){let s=Object.assign(new Error(\"writing more data than expected\"),{path:this.absolute});return this.emit(\"error\",s)}return this.remain-=e.length,this.blockRemain-=e.length,this.pos+=e.length,this.offset+=e.length,super.write(e,null,r)}[$j](){if(!this.remain)return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),this[F0](e=>e?this.emit(\"error\",e):this.end());if(!this.buf)throw new Error(\"buffer lost somehow in ONDRAIN\");this.offset>=this.length&&(this.buf=Buffer.allocUnsafe(Math.min(this.blockRemain,this.buf.length)),this.offset=0),this.length=this.buf.length-this.offset,this[tT]()}},Ant=class extends whe{sync=!0;[h6](){this[rT](Yu.default.lstatSync(this.absolute))}[p6](){this[d6](Yu.default.readlinkSync(this.absolute))}[m6](){this[y6](Yu.default.openSync(this.absolute,\"r\"))}[tT](){let e=!0;try{let{fd:t,buf:r,offset:s,length:a,pos:n}=this;if(t===void 0||r===void 0)throw new Error(\"fd and buf must be set in READ method\");let c=Yu.default.readSync(t,r,s,a,n);this[g6](c),e=!1}finally{if(e)try{this[F0](()=>{})}catch{}}}[E6](e){e()}[F0](e=()=>{}){this.fd!==void 0&&Yu.default.closeSync(this.fd),e()}},pnt=class extends vm{blockLen=0;blockRemain=0;buf=0;pos=0;remain=0;length=0;preservePaths;portable;strict;noPax;noMtime;readEntry;type;prefix;path;mode;uid;gid;uname;gname;header;mtime;atime;ctime;linkpath;size;onWriteEntry;warn(e,t,r={}){return mT(this,e,t,r)}constructor(e,t={}){let r=T6(t);super(),this.preservePaths=!!r.preservePaths,this.portable=!!r.portable,this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.onWriteEntry=r.onWriteEntry,this.readEntry=e;let{type:s}=e;if(s===\"Unsupported\")throw new Error(\"writing entry that should be ignored\");this.type=s,this.type===\"Directory\"&&this.portable&&(this.noMtime=!0),this.prefix=r.prefix,this.path=cn(e.path),this.mode=e.mode!==void 0?this[fT](e.mode):void 0,this.uid=this.portable?void 0:e.uid,this.gid=this.portable?void 0:e.gid,this.uname=this.portable?void 0:e.uname,this.gname=this.portable?void 0:e.gname,this.size=e.size,this.mtime=this.noMtime?void 0:r.mtime||e.mtime,this.atime=this.portable?void 0:e.atime,this.ctime=this.portable?void 0:e.ctime,this.linkpath=e.linkpath!==void 0?cn(e.linkpath):void 0,typeof r.onwarn==\"function\"&&this.on(\"warn\",r.onwarn);let a=!1;if(!this.preservePaths){let[c,f]=O6(this.path);c&&typeof f==\"string\"&&(this.path=f,a=c)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.onWriteEntry?.(this),this.header=new wm({path:this[aA](this.path),linkpath:this.type===\"Link\"&&this.linkpath!==void 0?this[aA](this.linkpath):this.linkpath,mode:this.mode,uid:this.portable?void 0:this.uid,gid:this.portable?void 0:this.gid,size:this.size,mtime:this.noMtime?void 0:this.mtime,type:this.type,uname:this.portable?void 0:this.uname,atime:this.portable?void 0:this.atime,ctime:this.portable?void 0:this.ctime}),a&&this.warn(\"TAR_ENTRY_INFO\",`stripping ${a} from absolute path`,{entry:this,path:a+this.path}),this.header.encode()&&!this.noPax&&super.write(new uT({atime:this.portable?void 0:this.atime,ctime:this.portable?void 0:this.ctime,gid:this.portable?void 0:this.gid,mtime:this.noMtime?void 0:this.mtime,path:this[aA](this.path),linkpath:this.type===\"Link\"&&this.linkpath!==void 0?this[aA](this.linkpath):this.linkpath,size:this.size,uid:this.portable?void 0:this.uid,uname:this.portable?void 0:this.uname,dev:this.portable?void 0:this.readEntry.dev,ino:this.portable?void 0:this.readEntry.ino,nlink:this.portable?void 0:this.readEntry.nlink}).encode());let n=this.header?.block;if(!n)throw new Error(\"failed to encode header\");super.write(n),e.pipe(this)}[aA](e){return Che(e,this.prefix)}[fT](e){return Ehe(e,this.type===\"Directory\",this.portable)}write(e,t,r){typeof t==\"function\"&&(r=t,t=void 0),typeof e==\"string\"&&(e=Buffer.from(e,typeof t==\"string\"?t:\"utf8\"));let s=e.length;if(s>this.blockRemain)throw new Error(\"writing more to entry than is appropriate\");return this.blockRemain-=s,super.write(e,r)}end(e,t,r){return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),typeof e==\"function\"&&(r=e,t=void 0,e=void 0),typeof t==\"function\"&&(r=t,t=void 0),typeof e==\"string\"&&(e=Buffer.from(e,t??\"utf8\")),r&&this.once(\"finish\",r),e?super.end(e,r):super.end(r),this}},hnt=e=>e.isFile()?\"File\":e.isDirectory()?\"Directory\":e.isSymbolicLink()?\"SymbolicLink\":\"Unsupported\",gnt=class OI{tail;head;length=0;static create(t=[]){return new OI(t)}constructor(t=[]){for(let r of t)this.push(r)}*[Symbol.iterator](){for(let t=this.head;t;t=t.next)yield t.value}removeNode(t){if(t.list!==this)throw new Error(\"removing node which does not belong to this list\");let r=t.next,s=t.prev;return r&&(r.prev=s),s&&(s.next=r),t===this.head&&(this.head=r),t===this.tail&&(this.tail=s),this.length--,t.next=void 0,t.prev=void 0,t.list=void 0,r}unshiftNode(t){if(t===this.head)return;t.list&&t.list.removeNode(t);let r=this.head;t.list=this,t.next=r,r&&(r.prev=t),this.head=t,this.tail||(this.tail=t),this.length++}pushNode(t){if(t===this.tail)return;t.list&&t.list.removeNode(t);let r=this.tail;t.list=this,t.prev=r,r&&(r.next=t),this.tail=t,this.head||(this.head=t),this.length++}push(...t){for(let r=0,s=t.length;r<s;r++)mnt(this,t[r]);return this.length}unshift(...t){for(var r=0,s=t.length;r<s;r++)ynt(this,t[r]);return this.length}pop(){if(!this.tail)return;let t=this.tail.value,r=this.tail;return this.tail=this.tail.prev,this.tail?this.tail.next=void 0:this.head=void 0,r.list=void 0,this.length--,t}shift(){if(!this.head)return;let t=this.head.value,r=this.head;return this.head=this.head.next,this.head?this.head.prev=void 0:this.tail=void 0,r.list=void 0,this.length--,t}forEach(t,r){r=r||this;for(let s=this.head,a=0;s;a++)t.call(r,s.value,a,this),s=s.next}forEachReverse(t,r){r=r||this;for(let s=this.tail,a=this.length-1;s;a--)t.call(r,s.value,a,this),s=s.prev}get(t){let r=0,s=this.head;for(;s&&r<t;r++)s=s.next;if(r===t&&s)return s.value}getReverse(t){let r=0,s=this.tail;for(;s&&r<t;r++)s=s.prev;if(r===t&&s)return s.value}map(t,r){r=r||this;let s=new OI;for(let a=this.head;a;)s.push(t.call(r,a.value,this)),a=a.next;return s}mapReverse(t,r){r=r||this;var s=new OI;for(let a=this.tail;a;)s.push(t.call(r,a.value,this)),a=a.prev;return s}reduce(t,r){let s,a=this.head;if(arguments.length>1)s=r;else if(this.head)a=this.head.next,s=this.head.value;else throw new TypeError(\"Reduce of empty list with no initial value\");for(var n=0;a;n++)s=t(s,a.value,n),a=a.next;return s}reduceReverse(t,r){let s,a=this.tail;if(arguments.length>1)s=r;else if(this.tail)a=this.tail.prev,s=this.tail.value;else throw new TypeError(\"Reduce of empty list with no initial value\");for(let n=this.length-1;a;n--)s=t(s,a.value,n),a=a.prev;return s}toArray(){let t=new Array(this.length);for(let r=0,s=this.head;s;r++)t[r]=s.value,s=s.next;return t}toArrayReverse(){let t=new Array(this.length);for(let r=0,s=this.tail;s;r++)t[r]=s.value,s=s.prev;return t}slice(t=0,r=this.length){r<0&&(r+=this.length),t<0&&(t+=this.length);let s=new OI;if(r<t||r<0)return s;t<0&&(t=0),r>this.length&&(r=this.length);let a=this.head,n=0;for(n=0;a&&n<t;n++)a=a.next;for(;a&&n<r;n++,a=a.next)s.push(a.value);return s}sliceReverse(t=0,r=this.length){r<0&&(r+=this.length),t<0&&(t+=this.length);let s=new OI;if(r<t||r<0)return s;t<0&&(t=0),r>this.length&&(r=this.length);let a=this.length,n=this.tail;for(;n&&a>r;a--)n=n.prev;for(;n&&a>t;a--,n=n.prev)s.push(n.value);return s}splice(t,r=0,...s){t>this.length&&(t=this.length-1),t<0&&(t=this.length+t);let a=this.head;for(let c=0;a&&c<t;c++)a=a.next;let n=[];for(let c=0;a&&c<r;c++)n.push(a.value),a=this.removeNode(a);a?a!==this.tail&&(a=a.prev):a=this.tail;for(let c of s)a=dnt(this,a,c);return n}reverse(){let t=this.head,r=this.tail;for(let s=t;s;s=s.prev){let a=s.prev;s.prev=s.next,s.next=a}return this.head=r,this.tail=t,this}};M6=class{list;next;prev;value;constructor(e,t,r,s){this.list=s,this.value=e,t?(t.next=this,this.prev=t):this.prev=void 0,r?(r.prev=this,this.next=r):this.next=void 0}},Wpe=class{path;absolute;entry;stat;readdir;pending=!1;ignore=!1;piped=!1;constructor(e,t){this.path=e||\"./\",this.absolute=t}},Vpe=Buffer.alloc(1024),nT=Symbol(\"onStat\"),wv=Symbol(\"ended\"),Wu=Symbol(\"queue\"),dm=Symbol(\"current\"),mm=Symbol(\"process\"),Bv=Symbol(\"processing\"),e6=Symbol(\"processJob\"),Vu=Symbol(\"jobs\"),t6=Symbol(\"jobDone\"),iT=Symbol(\"addFSEntry\"),Ype=Symbol(\"addTarEntry\"),C6=Symbol(\"stat\"),w6=Symbol(\"readdir\"),sT=Symbol(\"onreaddir\"),oT=Symbol(\"pipe\"),Kpe=Symbol(\"entry\"),r6=Symbol(\"entryOpt\"),aT=Symbol(\"writeEntryClass\"),Bhe=Symbol(\"write\"),n6=Symbol(\"ondrain\"),IT=class extends vm{sync=!1;opt;cwd;maxReadSize;preservePaths;strict;noPax;prefix;linkCache;statCache;file;portable;zip;readdirCache;noDirRecurse;follow;noMtime;mtime;filter;jobs;[aT];onWriteEntry;[Wu];[Vu]=0;[Bv]=!1;[wv]=!1;constructor(e={}){if(super(),this.opt=e,this.file=e.file||\"\",this.cwd=e.cwd||process.cwd(),this.maxReadSize=e.maxReadSize,this.preservePaths=!!e.preservePaths,this.strict=!!e.strict,this.noPax=!!e.noPax,this.prefix=cn(e.prefix||\"\"),this.linkCache=e.linkCache||new Map,this.statCache=e.statCache||new Map,this.readdirCache=e.readdirCache||new Map,this.onWriteEntry=e.onWriteEntry,this[aT]=whe,typeof e.onwarn==\"function\"&&this.on(\"warn\",e.onwarn),this.portable=!!e.portable,e.gzip||e.brotli||e.zstd){if((e.gzip?1:0)+(e.brotli?1:0)+(e.zstd?1:0)>1)throw new TypeError(\"gzip, brotli, zstd are mutually exclusive\");if(e.gzip&&(typeof e.gzip!=\"object\"&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new Prt(e.gzip)),e.brotli&&(typeof e.brotli!=\"object\"&&(e.brotli={}),this.zip=new krt(e.brotli)),e.zstd&&(typeof e.zstd!=\"object\"&&(e.zstd={}),this.zip=new Rrt(e.zstd)),!this.zip)throw new Error(\"impossible\");let t=this.zip;t.on(\"data\",r=>super.write(r)),t.on(\"end\",()=>super.end()),t.on(\"drain\",()=>this[n6]()),this.on(\"resume\",()=>t.resume())}else this.on(\"drain\",this[n6]);this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,e.mtime&&(this.mtime=e.mtime),this.filter=typeof e.filter==\"function\"?e.filter:()=>!0,this[Wu]=new gnt,this[Vu]=0,this.jobs=Number(e.jobs)||4,this[Bv]=!1,this[wv]=!1}[Bhe](e){return super.write(e)}add(e){return this.write(e),this}end(e,t,r){return typeof e==\"function\"&&(r=e,e=void 0),typeof t==\"function\"&&(r=t,t=void 0),e&&this.add(e),this[wv]=!0,this[mm](),r&&r(),this}write(e){if(this[wv])throw new Error(\"write after end\");return e instanceof mhe?this[Ype](e):this[iT](e),this.flowing}[Ype](e){let t=cn(I6.default.resolve(this.cwd,e.path));if(!this.filter(e.path,e))e.resume();else{let r=new Wpe(e.path,t);r.entry=new pnt(e,this[r6](r)),r.entry.on(\"end\",()=>this[t6](r)),this[Vu]+=1,this[Wu].push(r)}this[mm]()}[iT](e){let t=cn(I6.default.resolve(this.cwd,e));this[Wu].push(new Wpe(e,t)),this[mm]()}[C6](e){e.pending=!0,this[Vu]+=1;let t=this.follow?\"stat\":\"lstat\";Fv.default[t](e.absolute,(r,s)=>{e.pending=!1,this[Vu]-=1,r?this.emit(\"error\",r):this[nT](e,s)})}[nT](e,t){this.statCache.set(e.absolute,t),e.stat=t,this.filter(e.path,t)?t.isFile()&&t.nlink>1&&e===this[dm]&&!this.linkCache.get(`${t.dev}:${t.ino}`)&&!this.sync&&this[e6](e):e.ignore=!0,this[mm]()}[w6](e){e.pending=!0,this[Vu]+=1,Fv.default.readdir(e.absolute,(t,r)=>{if(e.pending=!1,this[Vu]-=1,t)return this.emit(\"error\",t);this[sT](e,r)})}[sT](e,t){this.readdirCache.set(e.absolute,t),e.readdir=t,this[mm]()}[mm](){if(!this[Bv]){this[Bv]=!0;for(let e=this[Wu].head;e&&this[Vu]<this.jobs;e=e.next)if(this[e6](e.value),e.value.ignore){let t=e.next;this[Wu].removeNode(e),e.next=t}this[Bv]=!1,this[wv]&&!this[Wu].length&&this[Vu]===0&&(this.zip?this.zip.end(Vpe):(super.write(Vpe),super.end()))}}get[dm](){return this[Wu]&&this[Wu].head&&this[Wu].head.value}[t6](e){this[Wu].shift(),this[Vu]-=1,this[mm]()}[e6](e){if(!e.pending){if(e.entry){e===this[dm]&&!e.piped&&this[oT](e);return}if(!e.stat){let t=this.statCache.get(e.absolute);t?this[nT](e,t):this[C6](e)}if(e.stat&&!e.ignore){if(!this.noDirRecurse&&e.stat.isDirectory()&&!e.readdir){let t=this.readdirCache.get(e.absolute);if(t?this[sT](e,t):this[w6](e),!e.readdir)return}if(e.entry=this[Kpe](e),!e.entry){e.ignore=!0;return}e===this[dm]&&!e.piped&&this[oT](e)}}}[r6](e){return{onwarn:(t,r,s)=>this.warn(t,r,s),noPax:this.noPax,cwd:this.cwd,absolute:e.absolute,preservePaths:this.preservePaths,maxReadSize:this.maxReadSize,strict:this.strict,portable:this.portable,linkCache:this.linkCache,statCache:this.statCache,noMtime:this.noMtime,mtime:this.mtime,prefix:this.prefix,onWriteEntry:this.onWriteEntry}}[Kpe](e){this[Vu]+=1;try{return new this[aT](e.path,this[r6](e)).on(\"end\",()=>this[t6](e)).on(\"error\",t=>this.emit(\"error\",t))}catch(t){this.emit(\"error\",t)}}[n6](){this[dm]&&this[dm].entry&&this[dm].entry.resume()}[oT](e){e.piped=!0,e.readdir&&e.readdir.forEach(s=>{let a=e.path,n=a===\"./\"?\"\":a.replace(/\\/*$/,\"/\");this[iT](n+s)});let t=e.entry,r=this.zip;if(!t)throw new Error(\"cannot pipe without source\");r?t.on(\"data\",s=>{r.write(s)||t.pause()}):t.on(\"data\",s=>{super.write(s)||t.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}warn(e,t,r={}){mT(this,e,t,r)}},U6=class extends IT{sync=!0;constructor(e){super(e),this[aT]=Ant}pause(){}resume(){}[C6](e){let t=this.follow?\"statSync\":\"lstatSync\";this[nT](e,Fv.default[t](e.absolute))}[w6](e){this[sT](e,Fv.default.readdirSync(e.absolute))}[oT](e){let t=e.entry,r=this.zip;if(e.readdir&&e.readdir.forEach(s=>{let a=e.path,n=a===\"./\"?\"\":a.replace(/\\/*$/,\"/\");this[iT](n+s)}),!t)throw new Error(\"Cannot pipe without source\");r?t.on(\"data\",s=>{r.write(s)}):t.on(\"data\",s=>{super[Bhe](s)})}},Ent=(e,t)=>{let r=new U6(e),s=new ahe(e.file,{mode:e.mode||438});r.pipe(s),vhe(r,t)},Int=(e,t)=>{let r=new IT(e),s=new hT(e.file,{mode:e.mode||438});r.pipe(s);let a=new Promise((n,c)=>{s.on(\"error\",c),s.on(\"close\",n),r.on(\"error\",c)});return She(r,t),a},vhe=(e,t)=>{t.forEach(r=>{r.charAt(0)===\"@\"?yT({file:R6.default.resolve(e.cwd,r.slice(1)),sync:!0,noResume:!0,onReadEntry:s=>e.add(s)}):e.add(r)}),e.end()},She=async(e,t)=>{for(let r=0;r<t.length;r++){let s=String(t[r]);s.charAt(0)===\"@\"?await yT({file:R6.default.resolve(String(e.cwd),s.slice(1)),noResume:!0,onReadEntry:a=>{e.add(a)}}):e.add(s)}e.end()},Cnt=(e,t)=>{let r=new U6(e);return vhe(r,t),r},wnt=(e,t)=>{let r=new IT(e);return She(r,t),r},lUt=Ov(Ent,Int,Cnt,wnt,(e,t)=>{if(!t?.length)throw new TypeError(\"no paths specified to add to archive\")}),Bnt=process.platform,vnt=Bnt===\"win32\",{O_CREAT:Snt,O_TRUNC:Dnt,O_WRONLY:bnt}=j6.default.constants,bhe=Number(process.env.__FAKE_FS_O_FILENAME__)||j6.default.constants.UV_FS_O_FILEMAP||0,Pnt=vnt&&!!bhe,xnt=512*1024,knt=bhe|Dnt|Snt|bnt,Phe=Pnt?e=>e<xnt?knt:\"w\":()=>\"w\",B6=(e,t,r)=>{try{return Lv.default.lchownSync(e,t,r)}catch(s){if(s?.code!==\"ENOENT\")throw s}},AT=(e,t,r,s)=>{Lv.default.lchown(e,t,r,a=>{s(a&&a?.code!==\"ENOENT\"?a:null)})},Qnt=(e,t,r,s,a)=>{if(t.isDirectory())xhe(MI.default.resolve(e,t.name),r,s,n=>{if(n)return a(n);let c=MI.default.resolve(e,t.name);AT(c,r,s,a)});else{let n=MI.default.resolve(e,t.name);AT(n,r,s,a)}},xhe=(e,t,r,s)=>{Lv.default.readdir(e,{withFileTypes:!0},(a,n)=>{if(a){if(a.code===\"ENOENT\")return s();if(a.code!==\"ENOTDIR\"&&a.code!==\"ENOTSUP\")return s(a)}if(a||!n.length)return AT(e,t,r,s);let c=n.length,f=null,p=h=>{if(!f){if(h)return s(f=h);if(--c===0)return AT(e,t,r,s)}};for(let h of n)Qnt(e,h,t,r,p)})},Rnt=(e,t,r,s)=>{t.isDirectory()&&khe(MI.default.resolve(e,t.name),r,s),B6(MI.default.resolve(e,t.name),r,s)},khe=(e,t,r)=>{let s;try{s=Lv.default.readdirSync(e,{withFileTypes:!0})}catch(a){let n=a;if(n?.code===\"ENOENT\")return;if(n?.code===\"ENOTDIR\"||n?.code===\"ENOTSUP\")return B6(e,t,r);throw n}for(let a of s)Rnt(e,a,t,r);return B6(e,t,r)},Rhe=class extends Error{path;code;syscall=\"chdir\";constructor(e,t){super(`${t}: Cannot cd into '${e}'`),this.path=e,this.code=t}get name(){return\"CwdError\"}},CT=class extends Error{path;symlink;syscall=\"symlink\";code=\"TAR_SYMLINK_ERROR\";constructor(e,t){super(\"TAR_SYMLINK_ERROR: Cannot extract through symbolic link\"),this.symlink=e,this.path=t}get name(){return\"SymlinkError\"}},Tnt=(e,t)=>{yl.default.stat(e,(r,s)=>{(r||!s.isDirectory())&&(r=new Rhe(e,r?.code||\"ENOTDIR\")),t(r)})},Fnt=(e,t,r)=>{e=cn(e);let s=t.umask??18,a=t.mode|448,n=(a&s)!==0,c=t.uid,f=t.gid,p=typeof c==\"number\"&&typeof f==\"number\"&&(c!==t.processUid||f!==t.processGid),h=t.preserve,E=t.unlink,C=cn(t.cwd),S=(I,T)=>{I?r(I):T&&p?xhe(T,c,f,O=>S(O)):n?yl.default.chmod(e,a,r):r()};if(e===C)return Tnt(e,S);if(h)return Qhe.default.mkdir(e,{mode:a,recursive:!0}).then(I=>S(null,I??void 0),S);let x=cn(Nv.default.relative(C,e)).split(\"/\");v6(C,x,a,E,C,void 0,S)},v6=(e,t,r,s,a,n,c)=>{if(!t.length)return c(null,n);let f=t.shift(),p=cn(Nv.default.resolve(e+\"/\"+f));yl.default.mkdir(p,r,The(p,t,r,s,a,n,c))},The=(e,t,r,s,a,n,c)=>f=>{f?yl.default.lstat(e,(p,h)=>{if(p)p.path=p.path&&cn(p.path),c(p);else if(h.isDirectory())v6(e,t,r,s,a,n,c);else if(s)yl.default.unlink(e,E=>{if(E)return c(E);yl.default.mkdir(e,r,The(e,t,r,s,a,n,c))});else{if(h.isSymbolicLink())return c(new CT(e,e+\"/\"+t.join(\"/\")));c(f)}}):(n=n||e,v6(e,t,r,s,a,n,c))},Nnt=e=>{let t=!1,r;try{t=yl.default.statSync(e).isDirectory()}catch(s){r=s?.code}finally{if(!t)throw new Rhe(e,r??\"ENOTDIR\")}},Ont=(e,t)=>{e=cn(e);let r=t.umask??18,s=t.mode|448,a=(s&r)!==0,n=t.uid,c=t.gid,f=typeof n==\"number\"&&typeof c==\"number\"&&(n!==t.processUid||c!==t.processGid),p=t.preserve,h=t.unlink,E=cn(t.cwd),C=I=>{I&&f&&khe(I,n,c),a&&yl.default.chmodSync(e,s)};if(e===E)return Nnt(E),C();if(p)return C(yl.default.mkdirSync(e,{mode:s,recursive:!0})??void 0);let S=cn(Nv.default.relative(E,e)).split(\"/\"),x;for(let I=S.shift(),T=E;I&&(T+=\"/\"+I);I=S.shift()){T=cn(Nv.default.resolve(T));try{yl.default.mkdirSync(T,s),x=x||T}catch{let O=yl.default.lstatSync(T);if(O.isDirectory())continue;if(h){yl.default.unlinkSync(T),yl.default.mkdirSync(T,s),x=x||T;continue}else if(O.isSymbolicLink())return new CT(T,T+\"/\"+S.join(\"/\"))}}return C(x)},i6=Object.create(null),Jpe=1e4,QI=new Set,Lnt=e=>{QI.has(e)?QI.delete(e):i6[e]=e.normalize(\"NFD\").toLocaleLowerCase(\"en\").toLocaleUpperCase(\"en\"),QI.add(e);let t=i6[e],r=QI.size-Jpe;if(r>Jpe/10){for(let s of QI)if(QI.delete(s),delete i6[s],--r<=0)break}return t},Mnt=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,Unt=Mnt===\"win32\",_nt=e=>e.split(\"/\").slice(0,-1).reduce((t,r)=>{let s=t[t.length-1];return s!==void 0&&(r=(0,G6.join)(s,r)),t.push(r||\"/\"),t},[]),Hnt=class{#e=new Map;#t=new Map;#s=new Set;reserve(e,t){e=Unt?[\"win32 parallelization disabled\"]:e.map(s=>Pv((0,G6.join)(Lnt(s))));let r=new Set(e.map(s=>_nt(s)).reduce((s,a)=>s.concat(a)));this.#t.set(t,{dirs:r,paths:e});for(let s of e){let a=this.#e.get(s);a?a.push(t):this.#e.set(s,[t])}for(let s of r){let a=this.#e.get(s);if(!a)this.#e.set(s,[new Set([t])]);else{let n=a[a.length-1];n instanceof Set?n.add(t):a.push(new Set([t]))}}return this.#i(t)}#r(e){let t=this.#t.get(e);if(!t)throw new Error(\"function does not have any path reservations\");return{paths:t.paths.map(r=>this.#e.get(r)),dirs:[...t.dirs].map(r=>this.#e.get(r))}}check(e){let{paths:t,dirs:r}=this.#r(e);return t.every(s=>s&&s[0]===e)&&r.every(s=>s&&s[0]instanceof Set&&s[0].has(e))}#i(e){return this.#s.has(e)||!this.check(e)?!1:(this.#s.add(e),e(()=>this.#n(e)),!0)}#n(e){if(!this.#s.has(e))return!1;let t=this.#t.get(e);if(!t)throw new Error(\"invalid reservation\");let{paths:r,dirs:s}=t,a=new Set;for(let n of r){let c=this.#e.get(n);if(!c||c?.[0]!==e)continue;let f=c[1];if(!f){this.#e.delete(n);continue}if(c.shift(),typeof f==\"function\")a.add(f);else for(let p of f)a.add(p)}for(let n of s){let c=this.#e.get(n),f=c?.[0];if(!(!c||!(f instanceof Set)))if(f.size===1&&c.length===1){this.#e.delete(n);continue}else if(f.size===1){c.shift();let p=c[0];typeof p==\"function\"&&a.add(p)}else f.delete(e)}return this.#s.delete(e),a.forEach(n=>this.#i(n)),!0}},jnt=()=>process.umask(),zpe=Symbol(\"onEntry\"),S6=Symbol(\"checkFs\"),Zpe=Symbol(\"checkFs2\"),D6=Symbol(\"isReusable\"),Uc=Symbol(\"makeFs\"),b6=Symbol(\"file\"),P6=Symbol(\"directory\"),lT=Symbol(\"link\"),Xpe=Symbol(\"symlink\"),$pe=Symbol(\"hardlink\"),Dv=Symbol(\"ensureNoSymlink\"),ehe=Symbol(\"unsupported\"),the=Symbol(\"checkPath\"),s6=Symbol(\"stripAbsolutePath\"),O0=Symbol(\"mkdir\"),Xs=Symbol(\"onError\"),ZR=Symbol(\"pending\"),rhe=Symbol(\"pend\"),RI=Symbol(\"unpend\"),o6=Symbol(\"ended\"),a6=Symbol(\"maybeClose\"),x6=Symbol(\"skip\"),xv=Symbol(\"doChown\"),kv=Symbol(\"uid\"),Qv=Symbol(\"gid\"),Rv=Symbol(\"checkedCwd\"),Gnt=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,Tv=Gnt===\"win32\",qnt=1024,Wnt=(e,t)=>{if(!Tv)return wn.default.unlink(e,t);let r=e+\".DELETE.\"+(0,H6.randomBytes)(16).toString(\"hex\");wn.default.rename(e,r,s=>{if(s)return t(s);wn.default.unlink(r,t)})},Vnt=e=>{if(!Tv)return wn.default.unlinkSync(e);let t=e+\".DELETE.\"+(0,H6.randomBytes)(16).toString(\"hex\");wn.default.renameSync(e,t),wn.default.unlinkSync(t)},nhe=(e,t,r)=>e!==void 0&&e===e>>>0?e:t!==void 0&&t===t>>>0?t:r,q6=class extends Bm{[o6]=!1;[Rv]=!1;[ZR]=0;reservations=new Hnt;transform;writable=!0;readable=!1;uid;gid;setOwner;preserveOwner;processGid;processUid;maxDepth;forceChown;win32;newer;keep;noMtime;preservePaths;unlink;cwd;strip;processUmask;umask;dmode;fmode;chmod;constructor(e={}){if(e.ondone=()=>{this[o6]=!0,this[a6]()},super(e),this.transform=e.transform,this.chmod=!!e.chmod,typeof e.uid==\"number\"||typeof e.gid==\"number\"){if(typeof e.uid!=\"number\"||typeof e.gid!=\"number\")throw new TypeError(\"cannot set owner without number uid and gid\");if(e.preserveOwner)throw new TypeError(\"cannot preserve owner in archive and also set owner explicitly\");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=void 0,this.gid=void 0,this.setOwner=!1;e.preserveOwner===void 0&&typeof e.uid!=\"number\"?this.preserveOwner=!!(process.getuid&&process.getuid()===0):this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():void 0,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():void 0,this.maxDepth=typeof e.maxDepth==\"number\"?e.maxDepth:qnt,this.forceChown=e.forceChown===!0,this.win32=!!e.win32||Tv,this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=cn(gs.default.resolve(e.cwd||process.cwd())),this.strip=Number(e.strip)||0,this.processUmask=this.chmod?typeof e.processUmask==\"number\"?e.processUmask:jnt():0,this.umask=typeof e.umask==\"number\"?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on(\"entry\",t=>this[zpe](t))}warn(e,t,r={}){return(e===\"TAR_BAD_ARCHIVE\"||e===\"TAR_ABORT\")&&(r.recoverable=!1),super.warn(e,t,r)}[a6](){this[o6]&&this[ZR]===0&&(this.emit(\"prefinish\"),this.emit(\"finish\"),this.emit(\"end\"))}[s6](e,t){let r=e[t],{type:s}=e;if(!r||this.preservePaths)return!0;let a=r.split(\"/\");if(a.includes(\"..\")||Tv&&/^[a-z]:\\.\\.$/i.test(a[0]??\"\")){if(t===\"path\"||s===\"Link\")return this.warn(\"TAR_ENTRY_ERROR\",`${t} contains '..'`,{entry:e,[t]:r}),!1;{let f=gs.default.posix.dirname(e.path),p=gs.default.posix.normalize(gs.default.posix.join(f,r));if(p.startsWith(\"../\")||p===\"..\")return this.warn(\"TAR_ENTRY_ERROR\",`${t} escapes extraction directory`,{entry:e,[t]:r}),!1}}let[n,c]=O6(r);return n&&(e[t]=String(c),this.warn(\"TAR_ENTRY_INFO\",`stripping ${n} from absolute ${t}`,{entry:e,[t]:r})),!0}[the](e){let t=cn(e.path),r=t.split(\"/\");if(this.strip){if(r.length<this.strip)return!1;if(e.type===\"Link\"){let s=cn(String(e.linkpath)).split(\"/\");if(s.length>=this.strip)e.linkpath=s.slice(this.strip).join(\"/\");else return!1}r.splice(0,this.strip),e.path=r.join(\"/\")}if(isFinite(this.maxDepth)&&r.length>this.maxDepth)return this.warn(\"TAR_ENTRY_ERROR\",\"path excessively deep\",{entry:e,path:t,depth:r.length,maxDepth:this.maxDepth}),!1;if(!this[s6](e,\"path\")||!this[s6](e,\"linkpath\"))return!1;if(gs.default.isAbsolute(e.path)?e.absolute=cn(gs.default.resolve(e.path)):e.absolute=cn(gs.default.resolve(this.cwd,e.path)),!this.preservePaths&&typeof e.absolute==\"string\"&&e.absolute.indexOf(this.cwd+\"/\")!==0&&e.absolute!==this.cwd)return this.warn(\"TAR_ENTRY_ERROR\",\"path escaped extraction target\",{entry:e,path:cn(e.path),resolvedPath:e.absolute,cwd:this.cwd}),!1;if(e.absolute===this.cwd&&e.type!==\"Directory\"&&e.type!==\"GNUDumpDir\")return!1;if(this.win32){let{root:s}=gs.default.win32.parse(String(e.absolute));e.absolute=s+_pe(String(e.absolute).slice(s.length));let{root:a}=gs.default.win32.parse(e.path);e.path=a+_pe(e.path.slice(a.length))}return!0}[zpe](e){if(!this[the](e))return e.resume();switch(Dhe.default.equal(typeof e.absolute,\"string\"),e.type){case\"Directory\":case\"GNUDumpDir\":e.mode&&(e.mode=e.mode|448);case\"File\":case\"OldFile\":case\"ContiguousFile\":case\"Link\":case\"SymbolicLink\":return this[S6](e);default:return this[ehe](e)}}[Xs](e,t){e.name===\"CwdError\"?this.emit(\"error\",e):(this.warn(\"TAR_ENTRY_ERROR\",e,{entry:t}),this[RI](),t.resume())}[O0](e,t,r){Fnt(cn(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cwd:this.cwd,mode:t},r)}[xv](e){return this.forceChown||this.preserveOwner&&(typeof e.uid==\"number\"&&e.uid!==this.processUid||typeof e.gid==\"number\"&&e.gid!==this.processGid)||typeof this.uid==\"number\"&&this.uid!==this.processUid||typeof this.gid==\"number\"&&this.gid!==this.processGid}[kv](e){return nhe(this.uid,e.uid,this.processUid)}[Qv](e){return nhe(this.gid,e.gid,this.processGid)}[b6](e,t){let r=typeof e.mode==\"number\"?e.mode&4095:this.fmode,s=new hT(String(e.absolute),{flags:Phe(e.size),mode:r,autoClose:!1});s.on(\"error\",f=>{s.fd&&wn.default.close(s.fd,()=>{}),s.write=()=>!0,this[Xs](f,e),t()});let a=1,n=f=>{if(f){s.fd&&wn.default.close(s.fd,()=>{}),this[Xs](f,e),t();return}--a===0&&s.fd!==void 0&&wn.default.close(s.fd,p=>{p?this[Xs](p,e):this[RI](),t()})};s.on(\"finish\",()=>{let f=String(e.absolute),p=s.fd;if(typeof p==\"number\"&&e.mtime&&!this.noMtime){a++;let h=e.atime||new Date,E=e.mtime;wn.default.futimes(p,h,E,C=>C?wn.default.utimes(f,h,E,S=>n(S&&C)):n())}if(typeof p==\"number\"&&this[xv](e)){a++;let h=this[kv](e),E=this[Qv](e);typeof h==\"number\"&&typeof E==\"number\"&&wn.default.fchown(p,h,E,C=>C?wn.default.chown(f,h,E,S=>n(S&&C)):n())}n()});let c=this.transform&&this.transform(e)||e;c!==e&&(c.on(\"error\",f=>{this[Xs](f,e),t()}),e.pipe(c)),c.pipe(s)}[P6](e,t){let r=typeof e.mode==\"number\"?e.mode&4095:this.dmode;this[O0](String(e.absolute),r,s=>{if(s){this[Xs](s,e),t();return}let a=1,n=()=>{--a===0&&(t(),this[RI](),e.resume())};e.mtime&&!this.noMtime&&(a++,wn.default.utimes(String(e.absolute),e.atime||new Date,e.mtime,n)),this[xv](e)&&(a++,wn.default.chown(String(e.absolute),Number(this[kv](e)),Number(this[Qv](e)),n)),n()})}[ehe](e){e.unsupported=!0,this.warn(\"TAR_ENTRY_UNSUPPORTED\",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[Xpe](e,t){let r=cn(gs.default.relative(this.cwd,gs.default.resolve(gs.default.dirname(String(e.absolute)),String(e.linkpath)))).split(\"/\");this[Dv](e,this.cwd,r,()=>this[lT](e,String(e.linkpath),\"symlink\",t),s=>{this[Xs](s,e),t()})}[$pe](e,t){let r=cn(gs.default.resolve(this.cwd,String(e.linkpath))),s=cn(String(e.linkpath)).split(\"/\");this[Dv](e,this.cwd,s,()=>this[lT](e,r,\"link\",t),a=>{this[Xs](a,e),t()})}[Dv](e,t,r,s,a){let n=r.shift();if(this.preservePaths||n===void 0)return s();let c=gs.default.resolve(t,n);wn.default.lstat(c,(f,p)=>{if(f)return s();if(p?.isSymbolicLink())return a(new CT(c,gs.default.resolve(c,r.join(\"/\"))));this[Dv](e,c,r,s,a)})}[rhe](){this[ZR]++}[RI](){this[ZR]--,this[a6]()}[x6](e){this[RI](),e.resume()}[D6](e,t){return e.type===\"File\"&&!this.unlink&&t.isFile()&&t.nlink<=1&&!Tv}[S6](e){this[rhe]();let t=[e.path];e.linkpath&&t.push(e.linkpath),this.reservations.reserve(t,r=>this[Zpe](e,r))}[Zpe](e,t){let r=c=>{t(c)},s=()=>{this[O0](this.cwd,this.dmode,c=>{if(c){this[Xs](c,e),r();return}this[Rv]=!0,a()})},a=()=>{if(e.absolute!==this.cwd){let c=cn(gs.default.dirname(String(e.absolute)));if(c!==this.cwd)return this[O0](c,this.dmode,f=>{if(f){this[Xs](f,e),r();return}n()})}n()},n=()=>{wn.default.lstat(String(e.absolute),(c,f)=>{if(f&&(this.keep||this.newer&&f.mtime>(e.mtime??f.mtime))){this[x6](e),r();return}if(c||this[D6](e,f))return this[Uc](null,e,r);if(f.isDirectory()){if(e.type===\"Directory\"){let p=this.chmod&&e.mode&&(f.mode&4095)!==e.mode,h=E=>this[Uc](E??null,e,r);return p?wn.default.chmod(String(e.absolute),Number(e.mode),h):h()}if(e.absolute!==this.cwd)return wn.default.rmdir(String(e.absolute),p=>this[Uc](p??null,e,r))}if(e.absolute===this.cwd)return this[Uc](null,e,r);Wnt(String(e.absolute),p=>this[Uc](p??null,e,r))})};this[Rv]?a():s()}[Uc](e,t,r){if(e){this[Xs](e,t),r();return}switch(t.type){case\"File\":case\"OldFile\":case\"ContiguousFile\":return this[b6](t,r);case\"Link\":return this[$pe](t,r);case\"SymbolicLink\":return this[Xpe](t,r);case\"Directory\":case\"GNUDumpDir\":return this[P6](t,r)}}[lT](e,t,r,s){wn.default[r](t,String(e.absolute),a=>{a?this[Xs](a,e):(this[RI](),e.resume()),s()})}},vv=e=>{try{return[null,e()]}catch(t){return[t,null]}},Fhe=class extends q6{sync=!0;[Uc](e,t){return super[Uc](e,t,()=>{})}[S6](e){if(!this[Rv]){let a=this[O0](this.cwd,this.dmode);if(a)return this[Xs](a,e);this[Rv]=!0}if(e.absolute!==this.cwd){let a=cn(gs.default.dirname(String(e.absolute)));if(a!==this.cwd){let n=this[O0](a,this.dmode);if(n)return this[Xs](n,e)}}let[t,r]=vv(()=>wn.default.lstatSync(String(e.absolute)));if(r&&(this.keep||this.newer&&r.mtime>(e.mtime??r.mtime)))return this[x6](e);if(t||this[D6](e,r))return this[Uc](null,e);if(r.isDirectory()){if(e.type===\"Directory\"){let n=this.chmod&&e.mode&&(r.mode&4095)!==e.mode,[c]=n?vv(()=>{wn.default.chmodSync(String(e.absolute),Number(e.mode))}):[];return this[Uc](c,e)}let[a]=vv(()=>wn.default.rmdirSync(String(e.absolute)));this[Uc](a,e)}let[s]=e.absolute===this.cwd?[]:vv(()=>Vnt(String(e.absolute)));this[Uc](s,e)}[b6](e,t){let r=typeof e.mode==\"number\"?e.mode&4095:this.fmode,s=c=>{let f;try{wn.default.closeSync(a)}catch(p){f=p}(c||f)&&this[Xs](c||f,e),t()},a;try{a=wn.default.openSync(String(e.absolute),Phe(e.size),r)}catch(c){return s(c)}let n=this.transform&&this.transform(e)||e;n!==e&&(n.on(\"error\",c=>this[Xs](c,e)),e.pipe(n)),n.on(\"data\",c=>{try{wn.default.writeSync(a,c,0,c.length)}catch(f){s(f)}}),n.on(\"end\",()=>{let c=null;if(e.mtime&&!this.noMtime){let f=e.atime||new Date,p=e.mtime;try{wn.default.futimesSync(a,f,p)}catch(h){try{wn.default.utimesSync(String(e.absolute),f,p)}catch{c=h}}}if(this[xv](e)){let f=this[kv](e),p=this[Qv](e);try{wn.default.fchownSync(a,Number(f),Number(p))}catch(h){try{wn.default.chownSync(String(e.absolute),Number(f),Number(p))}catch{c=c||h}}}s(c)})}[P6](e,t){let r=typeof e.mode==\"number\"?e.mode&4095:this.dmode,s=this[O0](String(e.absolute),r);if(s){this[Xs](s,e),t();return}if(e.mtime&&!this.noMtime)try{wn.default.utimesSync(String(e.absolute),e.atime||new Date,e.mtime)}catch{}if(this[xv](e))try{wn.default.chownSync(String(e.absolute),Number(this[kv](e)),Number(this[Qv](e)))}catch{}t(),e.resume()}[O0](e,t){try{return Ont(cn(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cwd:this.cwd,mode:t})}catch(r){return r}}[Dv](e,t,r,s,a){if(this.preservePaths||!r.length)return s();let n=t;for(let c of r){n=gs.default.resolve(n,c);let[f,p]=vv(()=>wn.default.lstatSync(n));if(f)return s();if(p.isSymbolicLink())return a(new CT(n,gs.default.resolve(t,r.join(\"/\"))))}s()}[lT](e,t,r,s){let a=`${r}Sync`;try{wn.default[a](t,String(e.absolute)),s(),e.resume()}catch(n){return this[Xs](n,e)}}},Ynt=e=>{let t=new Fhe(e),r=e.file,s=_6.default.statSync(r),a=e.maxReadSize||16*1024*1024;new mrt(r,{readSize:a,size:s.size}).pipe(t)},Knt=(e,t)=>{let r=new q6(e),s=e.maxReadSize||16*1024*1024,a=e.file;return new Promise((n,c)=>{r.on(\"error\",c),r.on(\"close\",n),_6.default.stat(a,(f,p)=>{if(f)c(f);else{let h=new Q6(a,{readSize:s,size:p.size});h.on(\"error\",c),h.pipe(r)}})})},cUt=Ov(Ynt,Knt,e=>new Fhe(e),e=>new q6(e),(e,t)=>{t?.length&&yhe(e,t)}),Jnt=(e,t)=>{let r=new U6(e),s=!0,a,n;try{try{a=ml.default.openSync(e.file,\"r+\")}catch(p){if(p?.code===\"ENOENT\")a=ml.default.openSync(e.file,\"w+\");else throw p}let c=ml.default.fstatSync(a),f=Buffer.alloc(512);e:for(n=0;n<c.size;n+=512){for(let E=0,C=0;E<512;E+=C){if(C=ml.default.readSync(a,f,E,f.length-E,n+E),n===0&&f[0]===31&&f[1]===139)throw new Error(\"cannot append to compressed archives\");if(!C)break e}let p=new wm(f);if(!p.cksumValid)break;let h=512*Math.ceil((p.size||0)/512);if(n+h+512>c.size)break;n+=h,e.mtimeCache&&p.mtime&&e.mtimeCache.set(String(p.path),p.mtime)}s=!1,znt(e,r,n,a,t)}finally{if(s)try{ml.default.closeSync(a)}catch{}}},znt=(e,t,r,s,a)=>{let n=new ahe(e.file,{fd:s,start:r});t.pipe(n),Xnt(t,a)},Znt=(e,t)=>{t=Array.from(t);let r=new IT(e),s=(a,n,c)=>{let f=(S,x)=>{S?ml.default.close(a,I=>c(S)):c(null,x)},p=0;if(n===0)return f(null,0);let h=0,E=Buffer.alloc(512),C=(S,x)=>{if(S||typeof x>\"u\")return f(S);if(h+=x,h<512&&x)return ml.default.read(a,E,h,E.length-h,p+h,C);if(p===0&&E[0]===31&&E[1]===139)return f(new Error(\"cannot append to compressed archives\"));if(h<512)return f(null,p);let I=new wm(E);if(!I.cksumValid)return f(null,p);let T=512*Math.ceil((I.size??0)/512);if(p+T+512>n||(p+=T+512,p>=n))return f(null,p);e.mtimeCache&&I.mtime&&e.mtimeCache.set(String(I.path),I.mtime),h=0,ml.default.read(a,E,0,512,p,C)};ml.default.read(a,E,0,512,p,C)};return new Promise((a,n)=>{r.on(\"error\",n);let c=\"r+\",f=(p,h)=>{if(p&&p.code===\"ENOENT\"&&c===\"r+\")return c=\"w+\",ml.default.open(e.file,c,f);if(p||!h)return n(p);ml.default.fstat(h,(E,C)=>{if(E)return ml.default.close(h,()=>n(E));s(h,C.size,(S,x)=>{if(S)return n(S);let I=new hT(e.file,{fd:h,start:x});r.pipe(I),I.on(\"error\",n),I.on(\"close\",a),$nt(r,t)})})};ml.default.open(e.file,c,f)})},Xnt=(e,t)=>{t.forEach(r=>{r.charAt(0)===\"@\"?yT({file:W6.default.resolve(e.cwd,r.slice(1)),sync:!0,noResume:!0,onReadEntry:s=>e.add(s)}):e.add(r)}),e.end()},$nt=async(e,t)=>{for(let r=0;r<t.length;r++){let s=String(t[r]);s.charAt(0)===\"@\"?await yT({file:W6.default.resolve(String(e.cwd),s.slice(1)),noResume:!0,onReadEntry:a=>e.add(a)}):e.add(s)}e.end()},Sv=Ov(Jnt,Znt,()=>{throw new TypeError(\"file is required\")},()=>{throw new TypeError(\"file is required\")},(e,t)=>{if(!Brt(e))throw new TypeError(\"file is required\");if(e.gzip||e.brotli||e.zstd||e.file.endsWith(\".br\")||e.file.endsWith(\".tbr\"))throw new TypeError(\"cannot append to compressed archives\");if(!t?.length)throw new TypeError(\"no paths specified to add/replace\")}),uUt=Ov(Sv.syncFile,Sv.asyncFile,Sv.syncNoFile,Sv.asyncNoFile,(e,t=[])=>{Sv.validate?.(e,t),eit(e)}),eit=e=>{let t=e.filter;e.mtimeCache||(e.mtimeCache=new Map),e.filter=t?(r,s)=>t(r,s)&&!((e.mtimeCache?.get(r)??s.mtime??0)>(s.mtime??0)):(r,s)=>!((e.mtimeCache?.get(r)??s.mtime??0)>(s.mtime??0))}});var V6,Ohe,U0,Mv,Uv,Lhe=Ze(()=>{V6=et(Nd()),Ohe=Ie(\"worker_threads\"),U0=Symbol(\"kTaskInfo\"),Mv=class{constructor(t,r){this.fn=t;this.limit=(0,V6.default)(r.poolSize)}run(t){return this.limit(()=>this.fn(t))}},Uv=class{constructor(t,r){this.source=t;this.workers=[];this.limit=(0,V6.default)(r.poolSize),this.cleanupInterval=setInterval(()=>{if(this.limit.pendingCount===0&&this.limit.activeCount===0){let s=this.workers.pop();s?s.terminate():clearInterval(this.cleanupInterval)}},5e3).unref()}createWorker(){this.cleanupInterval.refresh();let t=new Ohe.Worker(this.source,{eval:!0,execArgv:[...process.execArgv,\"--unhandled-rejections=strict\"]});return t.on(\"message\",r=>{if(!t[U0])throw new Error(\"Assertion failed: Worker sent a result without having a task assigned\");t[U0].resolve(r),t[U0]=null,t.unref(),this.workers.push(t)}),t.on(\"error\",r=>{t[U0]?.reject(r),t[U0]=null}),t.on(\"exit\",r=>{r!==0&&t[U0]?.reject(new Error(`Worker exited with code ${r}`)),t[U0]=null}),t}run(t){return this.limit(()=>{let r=this.workers.pop()??this.createWorker();return r.ref(),new Promise((s,a)=>{r[U0]={resolve:s,reject:a},r.postMessage(t)})})}}});var Uhe=G((VUt,Mhe)=>{var Y6;Mhe.exports.getContent=()=>(typeof Y6>\"u\"&&(Y6=Ie(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),Y6)});var ds={};Yt(ds,{convertToZip:()=>sit,convertToZipWorker:()=>z6,extractArchiveTo:()=>Ghe,getDefaultTaskPool:()=>Hhe,getTaskPoolForConfiguration:()=>jhe,makeArchiveFromDirectory:()=>iit});function rit(e,t){switch(e){case\"async\":return new Mv(z6,{poolSize:t});case\"workers\":return new Uv((0,J6.getContent)(),{poolSize:t});default:throw new Error(`Assertion failed: Unknown value ${e} for taskPoolMode`)}}function Hhe(){return typeof K6>\"u\"&&(K6=rit(\"workers\",Ui.availableParallelism())),K6}function jhe(e){return typeof e>\"u\"?Hhe():Zl(nit,e,()=>{let t=e.get(\"taskPoolMode\"),r=e.get(\"taskPoolConcurrency\");switch(t){case\"async\":return new Mv(z6,{poolSize:r});case\"workers\":return new Uv((0,J6.getContent)(),{poolSize:r});default:throw new Error(`Assertion failed: Unknown value ${t} for taskPoolMode`)}})}async function z6(e){let{tmpFile:t,tgz:r,compressionLevel:s,extractBufferOpts:a}=e,n=new ps(t,{create:!0,level:s,stats:sl.makeDefaultStats()}),c=Buffer.from(r.buffer,r.byteOffset,r.byteLength);return await Ghe(c,n,a),n.saveAndClose(),t}async function iit(e,{baseFs:t=new Yn,prefixPath:r=vt.root,compressionLevel:s,inMemory:a=!1}={}){let n;if(a)n=new ps(null,{level:s});else{let f=await le.mktempPromise(),p=K.join(f,\"archive.zip\");n=new ps(p,{create:!0,level:s})}let c=K.resolve(vt.root,r);return await n.copyPromise(c,e,{baseFs:t,stableTime:!0,stableSort:!0}),n}async function sit(e,t={}){let r=await le.mktempPromise(),s=K.join(r,\"archive.zip\"),a=t.compressionLevel??t.configuration?.get(\"compressionLevel\")??\"mixed\",n={prefixPath:t.prefixPath,stripComponents:t.stripComponents};return await(t.taskPool??jhe(t.configuration)).run({tmpFile:s,tgz:e,compressionLevel:a,extractBufferOpts:n}),new ps(s,{level:t.compressionLevel})}async function*oit(e){let t=new Bm,r=new _he.PassThrough({objectMode:!0,autoDestroy:!0,emitClose:!0});t.on(\"entry\",s=>{r.write(s)}),t.on(\"error\",s=>{r.destroy(s)}),t.on(\"close\",()=>{r.destroyed||r.end()}),t.end(e);for await(let s of r){let a=s;yield a,a.resume()}}async function Ghe(e,t,{stripComponents:r=0,prefixPath:s=vt.dot}={}){function a(n){if(n.path[0]===\"/\")return!0;let c=n.path.split(/\\//g);return!!(c.some(f=>f===\"..\")||c.length<=r)}for await(let n of oit(e)){if(a(n))continue;let c=K.normalize(fe.toPortablePath(n.path)).replace(/\\/$/,\"\").split(/\\//g);if(c.length<=r)continue;let f=c.slice(r).join(\"/\"),p=K.join(s,f),h=420;switch((n.type===\"Directory\"||(n.mode??0)&73)&&(h|=73),n.type){case\"Directory\":t.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Ai.SAFE_TIME,Ai.SAFE_TIME]}),t.mkdirSync(p,{mode:h}),t.utimesSync(p,Ai.SAFE_TIME,Ai.SAFE_TIME);break;case\"OldFile\":case\"File\":t.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Ai.SAFE_TIME,Ai.SAFE_TIME]}),t.writeFileSync(p,await KE(n),{mode:h}),t.utimesSync(p,Ai.SAFE_TIME,Ai.SAFE_TIME);break;case\"SymbolicLink\":t.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Ai.SAFE_TIME,Ai.SAFE_TIME]}),t.symlinkSync(n.linkpath,p),t.lutimesSync(p,Ai.SAFE_TIME,Ai.SAFE_TIME);break}}return t}var _he,J6,K6,nit,qhe=Ze(()=>{qe();Dt();rA();_he=Ie(\"stream\");Nhe();Lhe();xc();J6=et(Uhe());nit=new WeakMap});var Vhe=G((Z6,Whe)=>{(function(e,t){typeof Z6==\"object\"?Whe.exports=t():typeof define==\"function\"&&define.amd?define(t):e.treeify=t()})(Z6,function(){function e(a,n){var c=n?\"\\u2514\":\"\\u251C\";return a?c+=\"\\u2500 \":c+=\"\\u2500\\u2500\\u2510\",c}function t(a,n){var c=[];for(var f in a)a.hasOwnProperty(f)&&(n&&typeof a[f]==\"function\"||c.push(f));return c}function r(a,n,c,f,p,h,E){var C=\"\",S=0,x,I,T=f.slice(0);if(T.push([n,c])&&f.length>0&&(f.forEach(function(U,Y){Y>0&&(C+=(U[1]?\" \":\"\\u2502\")+\"  \"),!I&&U[0]===n&&(I=!0)}),C+=e(a,c)+a,p&&(typeof n!=\"object\"||n instanceof Date)&&(C+=\": \"+n),I&&(C+=\" (circular ref.)\"),E(C)),!I&&typeof n==\"object\"){var O=t(n,h);O.forEach(function(U){x=++S===O.length,r(U,n[U],x,T,p,h,E)})}}var s={};return s.asLines=function(a,n,c,f){var p=typeof c!=\"function\"?c:!1;r(\".\",a,!1,[],n,p,f||c)},s.asTree=function(a,n,c){var f=\"\";return r(\".\",a,!1,[],n,c,function(p){f+=p+`\n`}),f},s})});var Rs={};Yt(Rs,{emitList:()=>ait,emitTree:()=>zhe,treeNodeToJson:()=>Jhe,treeNodeToTreeify:()=>Khe});function Khe(e,{configuration:t}){let r={},s=0,a=(n,c)=>{let f=Array.isArray(n)?n.entries():Object.entries(n);for(let[p,h]of f){if(!h)continue;let{label:E,value:C,children:S}=h,x=[];typeof E<\"u\"&&x.push(Kd(t,E,2)),typeof C<\"u\"&&x.push(jt(t,C[0],C[1])),x.length===0&&x.push(Kd(t,`${p}`,2));let I=x.join(\": \").trim(),T=`\\0${s++}\\0`,O=c[`${T}${I}`]={};typeof S<\"u\"&&a(S,O)}};if(typeof e.children>\"u\")throw new Error(\"The root node must only contain children\");return a(e.children,r),r}function Jhe(e){let t=r=>{if(typeof r.children>\"u\"){if(typeof r.value>\"u\")throw new Error(\"Assertion failed: Expected a value to be set if the children are missing\");return Jd(r.value[0],r.value[1])}let s=Array.isArray(r.children)?r.children.entries():Object.entries(r.children??{}),a=Array.isArray(r.children)?[]:{};for(let[n,c]of s)c&&(a[lit(n)]=t(c));return typeof r.value>\"u\"?a:{value:Jd(r.value[0],r.value[1]),children:a}};return t(e)}function ait(e,{configuration:t,stdout:r,json:s}){let a=e.map(n=>({value:n}));zhe({children:a},{configuration:t,stdout:r,json:s})}function zhe(e,{configuration:t,stdout:r,json:s,separators:a=0}){if(s){let c=Array.isArray(e.children)?e.children.values():Object.values(e.children??{});for(let f of c)f&&r.write(`${JSON.stringify(Jhe(f))}\n`);return}let n=(0,Yhe.asTree)(Khe(e,{configuration:t}),!1,!1);if(n=n.replace(/\\0[0-9]+\\0/g,\"\"),a>=1&&(n=n.replace(/^([├└]─)/gm,`\\u2502\n$1`).replace(/^│\\n/,\"\")),a>=2)for(let c=0;c<2;++c)n=n.replace(/^([│ ].{2}[├│ ].{2}[^\\n]+\\n)(([│ ]).{2}[├└].{2}[^\\n]*\\n[│ ].{2}[│ ].{2}[├└]─)/gm,`$1$3  \\u2502 \n$2`).replace(/^│\\n/,\"\");if(a>=3)throw new Error(\"Only the first two levels are accepted by treeUtils.emitTree\");r.write(n)}function lit(e){return typeof e==\"string\"?e.replace(/^\\0[0-9]+\\0/,\"\"):e}var Yhe,Zhe=Ze(()=>{Yhe=et(Vhe());kc()});var wT,Xhe=Ze(()=>{wT=class{constructor(t){this.releaseFunction=t;this.map=new Map}addOrCreate(t,r){let s=this.map.get(t);if(typeof s<\"u\"){if(s.refCount<=0)throw new Error(`Race condition in RefCountedMap. While adding a new key the refCount is: ${s.refCount} for ${JSON.stringify(t)}`);return s.refCount++,{value:s.value,release:()=>this.release(t)}}else{let a=r();return this.map.set(t,{refCount:1,value:a}),{value:a,release:()=>this.release(t)}}}release(t){let r=this.map.get(t);if(!r)throw new Error(`Unbalanced calls to release. No known instances of: ${JSON.stringify(t)}`);let s=r.refCount;if(s<=0)throw new Error(`Unbalanced calls to release. Too many release vs alloc refcount would become: ${s-1} of ${JSON.stringify(t)}`);s==1?(this.map.delete(t),this.releaseFunction(r.value)):r.refCount--}}});function _v(e){let t=e.match(cit);if(!t?.groups)throw new Error(\"Assertion failed: Expected the checksum to match the requested pattern\");let r=t.groups.cacheVersion?parseInt(t.groups.cacheVersion):null;return{cacheKey:t.groups.cacheKey??null,cacheVersion:r,cacheSpec:t.groups.cacheSpec??null,hash:t.groups.hash}}var $he,X6,$6,BT,Jr,cit,eG=Ze(()=>{qe();Dt();Dt();rA();$he=Ie(\"crypto\"),X6=et(Ie(\"fs\"));Xhe();Tc();y0();xc();Zo();$6=JE(process.env.YARN_CACHE_CHECKPOINT_OVERRIDE??process.env.YARN_CACHE_VERSION_OVERRIDE??9),BT=JE(process.env.YARN_CACHE_VERSION_OVERRIDE??10),Jr=class e{constructor(t,{configuration:r,immutable:s=r.get(\"enableImmutableCache\"),check:a=!1}){this.markedFiles=new Set;this.mutexes=new Map;this.refCountedZipFsCache=new wT(t=>{t.discardAndClose()});this.cacheId=`-${(0,$he.randomBytes)(8).toString(\"hex\")}.tmp`;this.configuration=r,this.cwd=t,this.immutable=s,this.check=a;let{cacheSpec:n,cacheKey:c}=e.getCacheKey(r);this.cacheSpec=n,this.cacheKey=c}static async find(t,{immutable:r,check:s}={}){let a=new e(t.get(\"cacheFolder\"),{configuration:t,immutable:r,check:s});return await a.setup(),a}static getCacheKey(t){let r=t.get(\"compressionLevel\"),s=r!==\"mixed\"?`c${r}`:\"\";return{cacheKey:[BT,s].join(\"\"),cacheSpec:s}}get mirrorCwd(){if(!this.configuration.get(\"enableMirror\"))return null;let t=`${this.configuration.get(\"globalFolder\")}/cache`;return t!==this.cwd?t:null}getVersionFilename(t){return`${oI(t)}-${this.cacheKey}.zip`}getChecksumFilename(t,r){let a=_v(r).hash.slice(0,10);return`${oI(t)}-${a}.zip`}isChecksumCompatible(t){if(t===null)return!1;let{cacheVersion:r,cacheSpec:s}=_v(t);if(r===null||r<$6)return!1;let a=this.configuration.get(\"cacheMigrationMode\");return!(r<BT&&a===\"always\"||s!==this.cacheSpec&&a!==\"required-only\")}getLocatorPath(t,r){return this.mirrorCwd===null?K.resolve(this.cwd,this.getVersionFilename(t)):r===null?K.resolve(this.cwd,this.getVersionFilename(t)):K.resolve(this.cwd,this.getChecksumFilename(t,r))}getLocatorMirrorPath(t){let r=this.mirrorCwd;return r!==null?K.resolve(r,this.getVersionFilename(t)):null}async setup(){if(!this.configuration.get(\"enableGlobalCache\"))if(this.immutable){if(!await le.existsPromise(this.cwd))throw new _t(56,\"Cache path does not exist.\")}else{await le.mkdirPromise(this.cwd,{recursive:!0});let t=K.resolve(this.cwd,\".gitignore\");await le.changeFilePromise(t,`/.gitignore\n*.flock\n*.tmp\n`)}(this.mirrorCwd||!this.immutable)&&await le.mkdirPromise(this.mirrorCwd||this.cwd,{recursive:!0})}async fetchPackageFromCache(t,r,{onHit:s,onMiss:a,loader:n,...c}){let f=this.getLocatorMirrorPath(t),p=new Yn,h=()=>{let Ae=new ps,Ce=K.join(vt.root,p8(t));return Ae.mkdirSync(Ce,{recursive:!0}),Ae.writeJsonSync(K.join(Ce,Er.manifest),{name:fn(t),mocked:!0}),Ae},E=async(Ae,{isColdHit:Ce,controlPath:Ee=null})=>{if(Ee===null&&c.unstablePackages?.has(t.locatorHash))return{isValid:!0,hash:null};let g=r&&!Ce?_v(r).cacheKey:this.cacheKey,Se=!c.skipIntegrityCheck||!r?`${g}/${await vQ(Ae)}`:r;if(Ee!==null){let me=!c.skipIntegrityCheck||!r?`${this.cacheKey}/${await vQ(Ee)}`:r;if(Se!==me)throw new _t(18,\"The remote archive doesn't match the local checksum - has the local cache been corrupted?\")}let Be=null;switch(r!==null&&Se!==r&&(this.check?Be=\"throw\":_v(r).cacheKey!==_v(Se).cacheKey?Be=\"update\":Be=this.configuration.get(\"checksumBehavior\")),Be){case null:case\"update\":return{isValid:!0,hash:Se};case\"ignore\":return{isValid:!0,hash:r};case\"reset\":return{isValid:!1,hash:r};default:case\"throw\":throw new _t(18,\"The remote archive doesn't match the expected checksum\")}},C=async Ae=>{if(!n)throw new Error(`Cache check required but no loader configured for ${Vr(this.configuration,t)}`);let Ce=await n(),Ee=Ce.getRealPath();Ce.saveAndClose(),await le.chmodPromise(Ee,420);let g=await E(Ae,{controlPath:Ee,isColdHit:!1});if(!g.isValid)throw new Error(\"Assertion failed: Expected a valid checksum\");return g.hash},S=async()=>{if(f===null||!await le.existsPromise(f)){let Ae=await n(),Ce=Ae.getRealPath();return Ae.saveAndClose(),{source:\"loader\",path:Ce}}return{source:\"mirror\",path:f}},x=async()=>{if(!n)throw new Error(`Cache entry required but missing for ${Vr(this.configuration,t)}`);if(this.immutable)throw new _t(56,`Cache entry required but missing for ${Vr(this.configuration,t)}`);let{path:Ae,source:Ce}=await S(),{hash:Ee}=await E(Ae,{isColdHit:!0}),g=this.getLocatorPath(t,Ee),Se=[];Ce!==\"mirror\"&&f!==null&&Se.push(async()=>{let me=`${f}${this.cacheId}`;await le.copyFilePromise(Ae,me,X6.default.constants.COPYFILE_FICLONE),await le.chmodPromise(me,420),await le.renamePromise(me,f)}),(!c.mirrorWriteOnly||f===null)&&Se.push(async()=>{let me=`${g}${this.cacheId}`;await le.copyFilePromise(Ae,me,X6.default.constants.COPYFILE_FICLONE),await le.chmodPromise(me,420),await le.renamePromise(me,g)});let Be=c.mirrorWriteOnly?f??g:g;return await Promise.all(Se.map(me=>me())),[!1,Be,Ee]},I=async()=>{let Ce=(async()=>{let Ee=c.unstablePackages?.has(t.locatorHash),g=Ee||!r||this.isChecksumCompatible(r)?this.getLocatorPath(t,r):null,Se=g!==null?this.markedFiles.has(g)||await p.existsPromise(g):!1,Be=!!c.mockedPackages?.has(t.locatorHash)&&(!this.check||!Se),me=Be||Se,ce=me?s:a;if(ce&&ce(),me){let X=null,De=g;if(!Be)if(this.check)X=await C(De);else{let Qe=await E(De,{isColdHit:!1});if(Qe.isValid)X=Qe.hash;else return x()}return[Be,De,X]}else{if(this.immutable&&Ee)throw new _t(56,`Cache entry required but missing for ${Vr(this.configuration,t)}; consider defining ${pe.pretty(this.configuration,\"supportedArchitectures\",pe.Type.CODE)} to cache packages for multiple systems`);return x()}})();this.mutexes.set(t.locatorHash,Ce);try{return await Ce}finally{this.mutexes.delete(t.locatorHash)}};for(let Ae;Ae=this.mutexes.get(t.locatorHash);)await Ae;let[T,O,U]=await I();T||this.markedFiles.add(O);let Y=()=>this.refCountedZipFsCache.addOrCreate(O,()=>T?h():new ps(O,{baseFs:p,readOnly:!0})),te,ie=new cE(()=>x4(()=>(te=Y(),te.value),Ae=>`Failed to open the cache entry for ${Vr(this.configuration,t)}: ${Ae}`),K),ue=new jf(O,{baseFs:ie,pathUtils:K}),ae=()=>{te?.release()},de=c.unstablePackages?.has(t.locatorHash)?null:U;return[ue,ae,de]}},cit=/^(?:(?<cacheKey>(?<cacheVersion>[0-9]+)(?<cacheSpec>.*))\\/)?(?<hash>.*)$/});var vT,e0e=Ze(()=>{vT=(r=>(r[r.SCRIPT=0]=\"SCRIPT\",r[r.SHELLCODE=1]=\"SHELLCODE\",r))(vT||{})});var uit,_I,tG=Ze(()=>{Dt();Bc();Fp();Zo();uit=[[/^(git(?:\\+(?:https|ssh))?:\\/\\/.*(?:\\.git)?)#(.*)$/,(e,t,r,s)=>`${r}#commit=${s}`],[/^https:\\/\\/((?:[^/]+?)@)?codeload\\.github\\.com\\/([^/]+\\/[^/]+)\\/tar\\.gz\\/([0-9a-f]+)$/,(e,t,r=\"\",s,a)=>`https://${r}github.com/${s}.git#commit=${a}`],[/^https:\\/\\/((?:[^/]+?)@)?github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?#([0-9a-f]+)$/,(e,t,r=\"\",s,a)=>`https://${r}github.com/${s}.git#commit=${a}`],[/^https?:\\/\\/[^/]+\\/(?:[^/]+\\/)*(?:@.+(?:\\/|(?:%2f)))?([^/]+)\\/(?:-|download)\\/\\1-[^/]+\\.tgz(?:#|$)/,e=>`npm:${e}`],[/^https:\\/\\/npm\\.pkg\\.github\\.com\\/download\\/(?:@[^/]+)\\/(?:[^/]+)\\/(?:[^/]+)\\/(?:[0-9a-f]+)(?:#|$)/,e=>`npm:${e}`],[/^https:\\/\\/npm\\.fontawesome\\.com\\/(?:@[^/]+)\\/([^/]+)\\/-\\/([^/]+)\\/\\1-\\2.tgz(?:#|$)/,e=>`npm:${e}`],[/^https?:\\/\\/[^/]+\\/.*\\/(@[^/]+)\\/([^/]+)\\/-\\/\\1\\/\\2-(?:[.\\d\\w-]+)\\.tgz(?:#|$)/,(e,t)=>xQ({protocol:\"npm:\",source:null,selector:e,params:{__archiveUrl:t}})],[/^[^/]+\\.tgz#[0-9a-f]+$/,e=>`npm:${e}`]],_I=class{constructor(t){this.resolver=t;this.resolutions=null}async setup(t,{report:r}){let s=K.join(t.cwd,Er.lockfile);if(!le.existsSync(s))return;let a=await le.readFilePromise(s,\"utf8\"),n=cs(a);if(Object.hasOwn(n,\"__metadata\"))return;let c=this.resolutions=new Map;for(let f of Object.keys(n)){let p=T2(f);if(!p){r.reportWarning(14,`Failed to parse the string \"${f}\" into a proper descriptor`);continue}let h=dl(p.range)?Mn(p,`npm:${p.range}`):p,{version:E,resolved:C}=n[f];if(!C)continue;let S;for(let[I,T]of uit){let O=C.match(I);if(O){S=T(E,...O);break}}if(!S){r.reportWarning(14,`${oi(t.configuration,h)}: Only some patterns can be imported from legacy lockfiles (not \"${C}\")`);continue}let x=h;try{let I=Xd(h.range),T=T2(I.selector,!0);T&&(x=T)}catch{}c.set(h.descriptorHash,Ks(x,S))}}supportsDescriptor(t,r){return this.resolutions?this.resolutions.has(t.descriptorHash):!1}supportsLocator(t,r){return!1}shouldPersistResolution(t,r){throw new Error(\"Assertion failed: This resolver doesn't support resolving locators to packages\")}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){if(!this.resolutions)throw new Error(\"Assertion failed: The resolution store should have been setup\");let a=this.resolutions.get(t.descriptorHash);if(!a)throw new Error(\"Assertion failed: The resolution should have been registered\");let n=c8(a),c=s.project.configuration.normalizeDependency(n);return await this.resolver.getCandidates(c,r,s)}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){throw new Error(\"Assertion failed: This resolver doesn't support resolving locators to packages\")}}});var cA,t0e=Ze(()=>{Tc();fv();kc();cA=class extends yo{constructor({configuration:r,stdout:s,suggestInstall:a=!0}){super();this.errorCount=0;S2(this,{configuration:r}),this.configuration=r,this.stdout=s,this.suggestInstall=a}static async start(r,s){let a=new this(r);try{await s(a)}catch(n){a.reportExceptionOnce(n)}finally{await a.finalize()}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}reportCacheHit(r){}reportCacheMiss(r){}startSectionSync(r,s){return s()}async startSectionPromise(r,s){return await s()}startTimerSync(r,s,a){return(typeof s==\"function\"?s:a)()}async startTimerPromise(r,s,a){return await(typeof s==\"function\"?s:a)()}reportSeparator(){}reportInfo(r,s){}reportWarning(r,s){}reportError(r,s){this.errorCount+=1,this.stdout.write(`${jt(this.configuration,\"\\u27A4\",\"redBright\")} ${this.formatNameWithHyperlink(r)}: ${s}\n`)}reportProgress(r){return{...Promise.resolve().then(async()=>{for await(let{}of r);}),stop:()=>{}}}reportJson(r){}reportFold(r,s){}async finalize(){this.errorCount>0&&(this.stdout.write(`\n`),this.stdout.write(`${jt(this.configuration,\"\\u27A4\",\"redBright\")} Errors happened when preparing the environment required to run this command.\n`),this.suggestInstall&&this.stdout.write(`${jt(this.configuration,\"\\u27A4\",\"redBright\")} This might be caused by packages being missing from the lockfile, in which case running \"yarn install\" might help.\n`))}formatNameWithHyperlink(r){return xj(r,{configuration:this.configuration,json:!1})}}});var HI,rG=Ze(()=>{Zo();HI=class{constructor(t){this.resolver=t}supportsDescriptor(t,r){return!!(r.project.storedResolutions.get(t.descriptorHash)||r.project.originalPackages.has(DQ(t).locatorHash))}supportsLocator(t,r){return!!(r.project.originalPackages.has(t.locatorHash)&&!r.project.lockfileNeedsRefresh)}shouldPersistResolution(t,r){throw new Error(\"The shouldPersistResolution method shouldn't be called on the lockfile resolver, which would always answer yes\")}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return this.resolver.getResolutionDependencies(t,r)}async getCandidates(t,r,s){let a=s.project.storedResolutions.get(t.descriptorHash);if(a){let c=s.project.originalPackages.get(a);if(c)return[c]}let n=s.project.originalPackages.get(DQ(t).locatorHash);if(n)return[n];throw new Error(\"Resolution expected from the lockfile data\")}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){let s=r.project.originalPackages.get(t.locatorHash);if(!s)throw new Error(\"The lockfile resolver isn't meant to resolve packages - they should already have been stored into a cache\");return s}}});function Yp(){}function fit(e,t,r,s,a){for(var n=0,c=t.length,f=0,p=0;n<c;n++){var h=t[n];if(h.removed){if(h.value=e.join(s.slice(p,p+h.count)),p+=h.count,n&&t[n-1].added){var C=t[n-1];t[n-1]=t[n],t[n]=C}}else{if(!h.added&&a){var E=r.slice(f,f+h.count);E=E.map(function(x,I){var T=s[p+I];return T.length>x.length?T:x}),h.value=e.join(E)}else h.value=e.join(r.slice(f,f+h.count));f+=h.count,h.added||(p+=h.count)}}var S=t[c-1];return c>1&&typeof S.value==\"string\"&&(S.added||S.removed)&&e.equals(\"\",S.value)&&(t[c-2].value+=S.value,t.pop()),t}function Ait(e){return{newPos:e.newPos,components:e.components.slice(0)}}function pit(e,t){if(typeof e==\"function\")t.callback=e;else if(e)for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);return t}function i0e(e,t,r){return r=pit(r,{ignoreWhitespace:!0}),aG.diff(e,t,r)}function hit(e,t,r){return lG.diff(e,t,r)}function ST(e){\"@babel/helpers - typeof\";return typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?ST=function(t){return typeof t}:ST=function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},ST(e)}function nG(e){return mit(e)||yit(e)||Eit(e)||Iit()}function mit(e){if(Array.isArray(e))return iG(e)}function yit(e){if(typeof Symbol<\"u\"&&Symbol.iterator in Object(e))return Array.from(e)}function Eit(e,t){if(e){if(typeof e==\"string\")return iG(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if(r===\"Object\"&&e.constructor&&(r=e.constructor.name),r===\"Map\"||r===\"Set\")return Array.from(e);if(r===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return iG(e,t)}}function iG(e,t){(t==null||t>e.length)&&(t=e.length);for(var r=0,s=new Array(t);r<t;r++)s[r]=e[r];return s}function Iit(){throw new TypeError(`Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function sG(e,t,r,s,a){t=t||[],r=r||[],s&&(e=s(a,e));var n;for(n=0;n<t.length;n+=1)if(t[n]===e)return r[n];var c;if(Cit.call(e)===\"[object Array]\"){for(t.push(e),c=new Array(e.length),r.push(c),n=0;n<e.length;n+=1)c[n]=sG(e[n],t,r,s,a);return t.pop(),r.pop(),c}if(e&&e.toJSON&&(e=e.toJSON()),ST(e)===\"object\"&&e!==null){t.push(e),c={},r.push(c);var f=[],p;for(p in e)e.hasOwnProperty(p)&&f.push(p);for(f.sort(),n=0;n<f.length;n+=1)p=f[n],c[p]=sG(e[p],t,r,s,p);t.pop(),r.pop()}else c=e;return c}function s0e(e,t,r,s,a,n,c){c||(c={}),typeof c.context>\"u\"&&(c.context=4);var f=hit(r,s,c);if(!f)return;f.push({value:\"\",lines:[]});function p(U){return U.map(function(Y){return\" \"+Y})}for(var h=[],E=0,C=0,S=[],x=1,I=1,T=function(Y){var te=f[Y],ie=te.lines||te.value.replace(/\\n$/,\"\").split(`\n`);if(te.lines=ie,te.added||te.removed){var ue;if(!E){var ae=f[Y-1];E=x,C=I,ae&&(S=c.context>0?p(ae.lines.slice(-c.context)):[],E-=S.length,C-=S.length)}(ue=S).push.apply(ue,nG(ie.map(function(me){return(te.added?\"+\":\"-\")+me}))),te.added?I+=ie.length:x+=ie.length}else{if(E)if(ie.length<=c.context*2&&Y<f.length-2){var de;(de=S).push.apply(de,nG(p(ie)))}else{var Ae,Ce=Math.min(ie.length,c.context);(Ae=S).push.apply(Ae,nG(p(ie.slice(0,Ce))));var Ee={oldStart:E,oldLines:x-E+Ce,newStart:C,newLines:I-C+Ce,lines:S};if(Y>=f.length-2&&ie.length<=c.context){var g=/\\n$/.test(r),Se=/\\n$/.test(s),Be=ie.length==0&&S.length>Ee.oldLines;!g&&Be&&r.length>0&&S.splice(Ee.oldLines,0,\"\\\\ No newline at end of file\"),(!g&&!Be||!Se)&&S.push(\"\\\\ No newline at end of file\")}h.push(Ee),E=0,C=0,S=[]}x+=ie.length,I+=ie.length}},O=0;O<f.length;O++)T(O);return{oldFileName:e,newFileName:t,oldHeader:a,newHeader:n,hunks:h}}var w_t,r0e,n0e,aG,lG,git,dit,Cit,Hv,oG,cG=Ze(()=>{Yp.prototype={diff:function(t,r){var s=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=s.callback;typeof s==\"function\"&&(a=s,s={}),this.options=s;var n=this;function c(T){return a?(setTimeout(function(){a(void 0,T)},0),!0):T}t=this.castInput(t),r=this.castInput(r),t=this.removeEmpty(this.tokenize(t)),r=this.removeEmpty(this.tokenize(r));var f=r.length,p=t.length,h=1,E=f+p;s.maxEditLength&&(E=Math.min(E,s.maxEditLength));var C=[{newPos:-1,components:[]}],S=this.extractCommon(C[0],r,t,0);if(C[0].newPos+1>=f&&S+1>=p)return c([{value:this.join(r),count:r.length}]);function x(){for(var T=-1*h;T<=h;T+=2){var O=void 0,U=C[T-1],Y=C[T+1],te=(Y?Y.newPos:0)-T;U&&(C[T-1]=void 0);var ie=U&&U.newPos+1<f,ue=Y&&0<=te&&te<p;if(!ie&&!ue){C[T]=void 0;continue}if(!ie||ue&&U.newPos<Y.newPos?(O=Ait(Y),n.pushComponent(O.components,void 0,!0)):(O=U,O.newPos++,n.pushComponent(O.components,!0,void 0)),te=n.extractCommon(O,r,t,T),O.newPos+1>=f&&te+1>=p)return c(fit(n,O.components,r,t,n.useLongestToken));C[T]=O}h++}if(a)(function T(){setTimeout(function(){if(h>E)return a();x()||T()},0)})();else for(;h<=E;){var I=x();if(I)return I}},pushComponent:function(t,r,s){var a=t[t.length-1];a&&a.added===r&&a.removed===s?t[t.length-1]={count:a.count+1,added:r,removed:s}:t.push({count:1,added:r,removed:s})},extractCommon:function(t,r,s,a){for(var n=r.length,c=s.length,f=t.newPos,p=f-a,h=0;f+1<n&&p+1<c&&this.equals(r[f+1],s[p+1]);)f++,p++,h++;return h&&t.components.push({count:h}),t.newPos=f,p},equals:function(t,r){return this.options.comparator?this.options.comparator(t,r):t===r||this.options.ignoreCase&&t.toLowerCase()===r.toLowerCase()},removeEmpty:function(t){for(var r=[],s=0;s<t.length;s++)t[s]&&r.push(t[s]);return r},castInput:function(t){return t},tokenize:function(t){return t.split(\"\")},join:function(t){return t.join(\"\")}};w_t=new Yp;r0e=/^[A-Za-z\\xC0-\\u02C6\\u02C8-\\u02D7\\u02DE-\\u02FF\\u1E00-\\u1EFF]+$/,n0e=/\\S/,aG=new Yp;aG.equals=function(e,t){return this.options.ignoreCase&&(e=e.toLowerCase(),t=t.toLowerCase()),e===t||this.options.ignoreWhitespace&&!n0e.test(e)&&!n0e.test(t)};aG.tokenize=function(e){for(var t=e.split(/([^\\S\\r\\n]+|[()[\\]{}'\"\\r\\n]|\\b)/),r=0;r<t.length-1;r++)!t[r+1]&&t[r+2]&&r0e.test(t[r])&&r0e.test(t[r+2])&&(t[r]+=t[r+2],t.splice(r+1,2),r--);return t};lG=new Yp;lG.tokenize=function(e){var t=[],r=e.split(/(\\n|\\r\\n)/);r[r.length-1]||r.pop();for(var s=0;s<r.length;s++){var a=r[s];s%2&&!this.options.newlineIsToken?t[t.length-1]+=a:(this.options.ignoreWhitespace&&(a=a.trim()),t.push(a))}return t};git=new Yp;git.tokenize=function(e){return e.split(/(\\S.+?[.!?])(?=\\s+|$)/)};dit=new Yp;dit.tokenize=function(e){return e.split(/([{}:;,]|\\s+)/)};Cit=Object.prototype.toString,Hv=new Yp;Hv.useLongestToken=!0;Hv.tokenize=lG.tokenize;Hv.castInput=function(e){var t=this.options,r=t.undefinedReplacement,s=t.stringifyReplacer,a=s===void 0?function(n,c){return typeof c>\"u\"?r:c}:s;return typeof e==\"string\"?e:JSON.stringify(sG(e,null,null,a),a,\"  \")};Hv.equals=function(e,t){return Yp.prototype.equals.call(Hv,e.replace(/,([\\r\\n])/g,\"$1\"),t.replace(/,([\\r\\n])/g,\"$1\"))};oG=new Yp;oG.tokenize=function(e){return e.slice()};oG.join=oG.removeEmpty=function(e){return e}});var DT,o0e=Ze(()=>{Tc();DT=class{constructor(t){this.resolver=t}supportsDescriptor(t,r){return this.resolver.supportsDescriptor(t,r)}supportsLocator(t,r){return this.resolver.supportsLocator(t,r)}shouldPersistResolution(t,r){return this.resolver.shouldPersistResolution(t,r)}bindDescriptor(t,r,s){return this.resolver.bindDescriptor(t,r,s)}getResolutionDependencies(t,r){return this.resolver.getResolutionDependencies(t,r)}async getCandidates(t,r,s){throw new _t(20,`This package doesn't seem to be present in your lockfile; run \"yarn install\" to update the lockfile`)}async getSatisfying(t,r,s,a){throw new _t(20,`This package doesn't seem to be present in your lockfile; run \"yarn install\" to update the lockfile`)}async resolve(t,r){throw new _t(20,`This package doesn't seem to be present in your lockfile; run \"yarn install\" to update the lockfile`)}}});var ki,uG=Ze(()=>{Tc();ki=class extends yo{reportCacheHit(t){}reportCacheMiss(t){}startSectionSync(t,r){return r()}async startSectionPromise(t,r){return await r()}startTimerSync(t,r,s){return(typeof r==\"function\"?r:s)()}async startTimerPromise(t,r,s){return await(typeof r==\"function\"?r:s)()}reportSeparator(){}reportInfo(t,r){}reportWarning(t,r){}reportError(t,r){}reportProgress(t){return{...Promise.resolve().then(async()=>{for await(let{}of t);}),stop:()=>{}}}reportJson(t){}reportFold(t,r){}async finalize(){}}});var a0e,jI,fG=Ze(()=>{Dt();a0e=et(wQ());cI();$d();kc();y0();Fp();Zo();jI=class{constructor(t,{project:r}){this.workspacesCwds=new Set;this.project=r,this.cwd=t}async setup(){this.manifest=await Ut.tryFind(this.cwd)??new Ut,this.relativeCwd=K.relative(this.project.cwd,this.cwd)||vt.dot;let t=this.manifest.name?this.manifest.name:xa(null,`${this.computeCandidateName()}-${fs(this.relativeCwd).substring(0,6)}`);this.anchoredDescriptor=Mn(t,`${Ii.protocol}${this.relativeCwd}`),this.anchoredLocator=Ks(t,`${Ii.protocol}${this.relativeCwd}`);let r=this.manifest.workspaceDefinitions.map(({pattern:a})=>a);if(r.length===0)return;let s=await(0,a0e.default)(r,{cwd:fe.fromPortablePath(this.cwd),onlyDirectories:!0,ignore:[\"**/node_modules\",\"**/.git\",\"**/.yarn\"]});s.sort(),await s.reduce(async(a,n)=>{let c=K.resolve(this.cwd,fe.toPortablePath(n)),f=await le.existsPromise(K.join(c,\"package.json\"));await a,f&&this.workspacesCwds.add(c)},Promise.resolve())}get anchoredPackage(){let t=this.project.storedPackages.get(this.anchoredLocator.locatorHash);if(!t)throw new Error(`Assertion failed: Expected workspace ${N2(this.project.configuration,this)} (${jt(this.project.configuration,K.join(this.cwd,Er.manifest),gt.PATH)}) to have been resolved. Run \"yarn install\" to update the lockfile`);return t}accepts(t){let r=t.indexOf(\":\"),s=r!==-1?t.slice(0,r+1):null,a=r!==-1?t.slice(r+1):t;if(s===Ii.protocol&&K.normalize(a)===this.relativeCwd||s===Ii.protocol&&(a===\"*\"||a===\"^\"||a===\"~\"))return!0;let n=dl(a);return n?s===Ii.protocol?n.test(this.manifest.version??\"0.0.0\"):this.project.configuration.get(\"enableTransparentWorkspaces\")&&this.manifest.version!==null?n.test(this.manifest.version):!1:!1}computeCandidateName(){return this.cwd===this.project.cwd?\"root-workspace\":`${K.basename(this.cwd)}`||\"unnamed-workspace\"}getRecursiveWorkspaceDependencies({dependencies:t=Ut.hardDependencies}={}){let r=new Set,s=a=>{for(let n of t)for(let c of a.manifest[n].values()){let f=this.project.tryWorkspaceByDescriptor(c);f===null||r.has(f)||(r.add(f),s(f))}};return s(this),r}getRecursiveWorkspaceDependents({dependencies:t=Ut.hardDependencies}={}){let r=new Set,s=a=>{for(let n of this.project.workspaces)t.some(f=>[...n.manifest[f].values()].some(p=>{let h=this.project.tryWorkspaceByDescriptor(p);return h!==null&&R2(h.anchoredLocator,a.anchoredLocator)}))&&!r.has(n)&&(r.add(n),s(n))};return s(this),r}getRecursiveWorkspaceChildren(){let t=new Set([this]);for(let r of t)for(let s of r.workspacesCwds){let a=this.project.workspacesByCwd.get(s);a&&t.add(a)}return t.delete(this),Array.from(t)}async persistManifest(){let t={};this.manifest.exportTo(t);let r=K.join(this.cwd,Ut.fileName),s=`${JSON.stringify(t,null,this.manifest.indent)}\n`;await le.changeFilePromise(r,s,{automaticNewlines:!0}),this.manifest.raw=t}}});function bit({project:e,allDescriptors:t,allResolutions:r,allPackages:s,accessibleLocators:a=new Set,optionalBuilds:n=new Set,peerRequirements:c=new Map,peerWarnings:f=[],peerRequirementNodes:p=new Map,volatileDescriptors:h=new Set}){let E=new Map,C=[],S=new Map,x=new Map,I=new Map,T=new Map,O=new Map,U=new Map(e.workspaces.map(ae=>{let de=ae.anchoredLocator.locatorHash,Ae=s.get(de);if(typeof Ae>\"u\")throw new Error(\"Assertion failed: The workspace should have an associated package\");return[de,x2(Ae)]})),Y=()=>{let ae=le.mktempSync(),de=K.join(ae,\"stacktrace.log\"),Ae=String(C.length+1).length,Ce=C.map((Ee,g)=>`${`${g+1}.`.padStart(Ae,\" \")} ${gl(Ee)}\n`).join(\"\");throw le.writeFileSync(de,Ce),le.detachTemp(ae),new _t(45,`Encountered a stack overflow when resolving peer dependencies; cf ${fe.fromPortablePath(de)}`)},te=ae=>{let de=r.get(ae.descriptorHash);if(typeof de>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");let Ae=s.get(de);if(!Ae)throw new Error(\"Assertion failed: The package could not be found\");return Ae},ie=(ae,de,Ae,{top:Ce,optional:Ee})=>{C.length>1e3&&Y(),C.push(de);let g=ue(ae,de,Ae,{top:Ce,optional:Ee});return C.pop(),g},ue=(ae,de,Ae,{top:Ce,optional:Ee})=>{if(Ee||n.delete(de.locatorHash),a.has(de.locatorHash))return;a.add(de.locatorHash);let g=s.get(de.locatorHash);if(!g)throw new Error(`Assertion failed: The package (${Vr(e.configuration,de)}) should have been registered`);let Se=new Set,Be=new Map,me=[],ce=[],X=[],De=[];for(let Qe of Array.from(g.dependencies.values())){if(g.peerDependencies.has(Qe.identHash)&&g.locatorHash!==Ce)continue;if(Qp(Qe))throw new Error(\"Assertion failed: Virtual packages shouldn't be encountered when virtualizing a branch\");h.delete(Qe.descriptorHash);let it=Ee;if(!it){let Re=g.dependenciesMeta.get(fn(Qe));if(typeof Re<\"u\"){let ct=Re.get(null);typeof ct<\"u\"&&ct.optional&&(it=!0)}}let _=r.get(Qe.descriptorHash);if(!_)throw new Error(`Assertion failed: The resolution (${oi(e.configuration,Qe)}) should have been registered`);let tt=U.get(_)||s.get(_);if(!tt)throw new Error(`Assertion failed: The package (${_}, resolved from ${oi(e.configuration,Qe)}) should have been registered`);if(tt.peerDependencies.size===0){ie(Qe,tt,new Map,{top:Ce,optional:it});continue}let Ne,ke,be=new Set,je=new Map;me.push(()=>{Ne=f8(Qe,de.locatorHash),ke=A8(tt,de.locatorHash),g.dependencies.set(Qe.identHash,Ne),r.set(Ne.descriptorHash,ke.locatorHash),t.set(Ne.descriptorHash,Ne),s.set(ke.locatorHash,ke),Pp(T,ke.locatorHash).add(Ne.descriptorHash),Se.add(ke.locatorHash)}),ce.push(()=>{O.set(ke.locatorHash,je);for(let Re of ke.peerDependencies.values()){let Me=Zl(Be,Re.identHash,()=>{let P=Ae.get(Re.identHash)??null,w=g.dependencies.get(Re.identHash);return!w&&Q2(de,Re)&&(ae.identHash===de.identHash?w=ae:(w=Mn(de,ae.range),t.set(w.descriptorHash,w),r.set(w.descriptorHash,de.locatorHash),h.delete(w.descriptorHash),P=null)),w||(w=Mn(Re,\"missing:\")),{subject:de,ident:Re,provided:w,root:!P,requests:new Map,hash:`p${fs(de.locatorHash,Re.identHash).slice(0,6)}`}}).provided;if(Me.range===\"missing:\"&&ke.dependencies.has(Re.identHash)){ke.peerDependencies.delete(Re.identHash);continue}if(je.set(Re.identHash,{requester:ke,descriptor:Re,meta:ke.peerDependenciesMeta.get(fn(Re)),children:new Map}),ke.dependencies.set(Re.identHash,Me),Qp(Me)){let P=r.get(Me.descriptorHash);Pp(I,P).add(ke.locatorHash)}S.set(Me.identHash,Me),Me.range===\"missing:\"&&be.add(Me.identHash)}ke.dependencies=new Map(Ys(ke.dependencies,([Re,ct])=>fn(ct)))}),X.push(()=>{if(!s.has(ke.locatorHash))return;let Re=E.get(tt.locatorHash);typeof Re==\"number\"&&Re>=2&&Y();let ct=E.get(tt.locatorHash),Me=typeof ct<\"u\"?ct+1:1;E.set(tt.locatorHash,Me),ie(Ne,ke,je,{top:Ce,optional:it}),E.set(tt.locatorHash,Me-1)}),De.push(()=>{let Re=r.get(Ne.descriptorHash);if(typeof Re>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let ct=O.get(Re);if(typeof ct>\"u\")throw new Error(\"Assertion failed: Expected the peer requests to be registered\");for(let Me of Be.values()){let P=ct.get(Me.ident.identHash);P&&(Me.requests.set(Ne.descriptorHash,P),p.set(Me.hash,Me),Me.root||Ae.get(Me.ident.identHash)?.children.set(Ne.descriptorHash,P))}if(s.has(ke.locatorHash))for(let Me of be)ke.dependencies.delete(Me)})}for(let Qe of[...me,...ce])Qe();for(let Qe of Se){Se.delete(Qe);let it=s.get(Qe),_=fs(sI(it).locatorHash,...Array.from(it.dependencies.values(),be=>{let je=be.range!==\"missing:\"?r.get(be.descriptorHash):\"missing:\";if(typeof je>\"u\")throw new Error(`Assertion failed: Expected the resolution for ${oi(e.configuration,be)} to have been registered`);return je===Ce?`${je} (top)`:je})),tt=x.get(_);if(typeof tt>\"u\"){x.set(_,it);continue}let Ne=Pp(T,tt.locatorHash);for(let be of T.get(it.locatorHash)??[])r.set(be,tt.locatorHash),Ne.add(be);s.delete(it.locatorHash),a.delete(it.locatorHash),Se.delete(it.locatorHash);let ke=I.get(it.locatorHash);if(ke!==void 0){let be=Pp(I,tt.locatorHash);for(let je of ke)be.add(je),Se.add(je)}}for(let Qe of[...X,...De])Qe()};for(let ae of e.workspaces){let de=ae.anchoredLocator;h.delete(ae.anchoredDescriptor.descriptorHash),ie(ae.anchoredDescriptor,de,new Map,{top:de.locatorHash,optional:!1})}for(let ae of p.values()){if(!ae.root)continue;let de=s.get(ae.subject.locatorHash);if(typeof de>\"u\")continue;for(let Ce of ae.requests.values()){let Ee=`p${fs(ae.subject.locatorHash,fn(ae.ident),Ce.requester.locatorHash).slice(0,6)}`;c.set(Ee,{subject:ae.subject.locatorHash,requested:ae.ident,rootRequester:Ce.requester.locatorHash,allRequesters:Array.from(O2(Ce),g=>g.requester.locatorHash)})}let Ae=[...O2(ae)];if(ae.provided.range!==\"missing:\"){let Ce=te(ae.provided),Ee=Ce.version??\"0.0.0\",g=Be=>{if(Be.startsWith(Ii.protocol)){if(!e.tryWorkspaceByLocator(Ce))return null;Be=Be.slice(Ii.protocol.length),(Be===\"^\"||Be===\"~\")&&(Be=\"*\")}return Be},Se=!0;for(let Be of Ae){let me=g(Be.descriptor.range);if(me===null){Se=!1;continue}if(!eA(Ee,me)){Se=!1;let ce=`p${fs(ae.subject.locatorHash,fn(ae.ident),Be.requester.locatorHash).slice(0,6)}`;f.push({type:1,subject:de,requested:ae.ident,requester:Be.requester,version:Ee,hash:ce,requirementCount:Ae.length})}}if(!Se){let Be=Ae.map(me=>g(me.descriptor.range));f.push({type:3,node:ae,range:Be.includes(null)?null:g8(Be),hash:ae.hash})}}else{let Ce=!0;for(let Ee of Ae)if(!Ee.meta?.optional){Ce=!1;let g=`p${fs(ae.subject.locatorHash,fn(ae.ident),Ee.requester.locatorHash).slice(0,6)}`;f.push({type:0,subject:de,requested:ae.ident,requester:Ee.requester,hash:g})}Ce||f.push({type:2,node:ae,hash:ae.hash})}}}function*Pit(e){let t=new Map;if(\"children\"in e)t.set(e,e);else for(let r of e.requests.values())t.set(r,r);for(let[r,s]of t){yield{request:r,root:s};for(let a of r.children.values())t.has(a)||t.set(a,s)}}function xit(e,t){let r=[],s=[],a=!1;for(let n of e.peerWarnings)if(!(n.type===1||n.type===0)){if(!e.tryWorkspaceByLocator(n.node.subject)){a=!0;continue}if(n.type===3){let c=e.storedResolutions.get(n.node.provided.descriptorHash);if(typeof c>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let f=e.storedPackages.get(c);if(typeof f>\"u\")throw new Error(\"Assertion failed: Expected the package to be registered\");let p=f0(Pit(n.node),({request:C,root:S})=>eA(f.version??\"0.0.0\",C.descriptor.range)?f0.skip:C===S?$i(e.configuration,C.requester):`${$i(e.configuration,C.requester)} (via ${$i(e.configuration,S.requester)})`),h=[...O2(n.node)].length>1?\"and other dependencies request\":\"requests\",E=n.range?aI(e.configuration,n.range):jt(e.configuration,\"but they have non-overlapping ranges!\",\"redBright\");r.push(`${$i(e.configuration,n.node.ident)} is listed by your project with version ${F2(e.configuration,f.version??\"0.0.0\")} (${jt(e.configuration,n.hash,gt.CODE)}), which doesn't satisfy what ${p} ${h} (${E}).`)}if(n.type===2){let c=n.node.requests.size>1?\" and other dependencies\":\"\";s.push(`${Vr(e.configuration,n.node.subject)} doesn't provide ${$i(e.configuration,n.node.ident)} (${jt(e.configuration,n.hash,gt.CODE)}), requested by ${$i(e.configuration,n.node.requests.values().next().value.requester)}${c}.`)}}t.startSectionSync({reportFooter:()=>{t.reportWarning(86,`Some peer dependencies are incorrectly met by your project; run ${jt(e.configuration,\"yarn explain peer-requirements <hash>\",gt.CODE)} for details, where ${jt(e.configuration,\"<hash>\",gt.CODE)} is the six-letter p-prefixed code.`)},skipIfEmpty:!0},()=>{for(let n of Ys(r,c=>ZE.default(c)))t.reportWarning(60,n);for(let n of Ys(s,c=>ZE.default(c)))t.reportWarning(2,n)}),a&&t.reportWarning(86,`Some peer dependencies are incorrectly met by dependencies; run ${jt(e.configuration,\"yarn explain peer-requirements\",gt.CODE)} for details.`)}var bT,PT,u0e,hG,pG,gG,xT,wit,Bit,l0e,vit,Sit,Dit,Na,AG,kT,c0e,Rt,f0e=Ze(()=>{Dt();Dt();Bc();Vt();bT=Ie(\"crypto\");cG();Jl();PT=et(Nd()),u0e=et(pi()),hG=Ie(\"util\"),pG=et(Ie(\"v8\")),gG=et(Ie(\"zlib\"));eG();$2();tG();rG();cI();y8();Tc();o0e();fv();uG();$d();fG();OQ();kc();y0();xc();hR();Fj();Fp();Zo();xT=JE(process.env.YARN_LOCKFILE_VERSION_OVERRIDE??8),wit=3,Bit=/ *, */g,l0e=/\\/$/,vit=32,Sit=(0,hG.promisify)(gG.default.gzip),Dit=(0,hG.promisify)(gG.default.gunzip),Na=(r=>(r.UpdateLockfile=\"update-lockfile\",r.SkipBuild=\"skip-build\",r))(Na||{}),AG={restoreLinkersCustomData:[\"linkersCustomData\"],restoreResolutions:[\"accessibleLocators\",\"conditionalLocators\",\"disabledLocators\",\"optionalBuilds\",\"storedDescriptors\",\"storedResolutions\",\"storedPackages\",\"lockFileChecksum\"],restoreBuildState:[\"skippedBuilds\",\"storedBuildState\"]},kT=(a=>(a[a.NotProvided=0]=\"NotProvided\",a[a.NotCompatible=1]=\"NotCompatible\",a[a.NodeNotProvided=2]=\"NodeNotProvided\",a[a.NodeNotCompatible=3]=\"NodeNotCompatible\",a))(kT||{}),c0e=e=>fs(`${wit}`,e),Rt=class e{constructor(t,{configuration:r}){this.resolutionAliases=new Map;this.workspaces=[];this.workspacesByCwd=new Map;this.workspacesByIdent=new Map;this.storedResolutions=new Map;this.storedDescriptors=new Map;this.storedPackages=new Map;this.storedChecksums=new Map;this.storedBuildState=new Map;this.accessibleLocators=new Set;this.conditionalLocators=new Set;this.disabledLocators=new Set;this.originalPackages=new Map;this.optionalBuilds=new Set;this.skippedBuilds=new Set;this.lockfileLastVersion=null;this.lockfileNeedsRefresh=!1;this.peerRequirements=new Map;this.peerWarnings=[];this.peerRequirementNodes=new Map;this.linkersCustomData=new Map;this.lockFileChecksum=null;this.installStateChecksum=null;this.configuration=r,this.cwd=t}static async find(t,r){if(!t.projectCwd)throw new st(`No project found in ${r}`);let s=t.projectCwd,a=r,n=null;for(;n!==t.projectCwd;){if(n=a,le.existsSync(K.join(n,Er.manifest))){s=n;break}a=K.dirname(n)}let c=new e(t.projectCwd,{configuration:t});ze.telemetry?.reportProject(c.cwd),await c.setupResolutions(),await c.setupWorkspaces(),ze.telemetry?.reportWorkspaceCount(c.workspaces.length),ze.telemetry?.reportDependencyCount(c.workspaces.reduce((I,T)=>I+T.manifest.dependencies.size+T.manifest.devDependencies.size,0));let f=c.tryWorkspaceByCwd(s);if(f)return{project:c,workspace:f,locator:f.anchoredLocator};let p=await c.findLocatorForLocation(`${s}/`,{strict:!0});if(p)return{project:c,locator:p,workspace:null};let h=jt(t,c.cwd,gt.PATH),E=jt(t,K.relative(c.cwd,s),gt.PATH),C=`- If ${h} isn't intended to be a project, remove any yarn.lock and/or package.json file there.`,S=`- If ${h} is intended to be a project, it might be that you forgot to list ${E} in its workspace configuration.`,x=`- Finally, if ${h} is fine and you intend ${E} to be treated as a completely separate project (not even a workspace), create an empty yarn.lock file in it.`;throw new st(`The nearest package directory (${jt(t,s,gt.PATH)}) doesn't seem to be part of the project declared in ${jt(t,c.cwd,gt.PATH)}.\n\n${[C,S,x].join(`\n`)}`)}async setupResolutions(){this.storedResolutions=new Map,this.storedDescriptors=new Map,this.storedPackages=new Map,this.lockFileChecksum=null;let t=K.join(this.cwd,Er.lockfile),r=this.configuration.get(\"defaultLanguageName\");if(le.existsSync(t)){let s=await le.readFilePromise(t,\"utf8\");this.lockFileChecksum=c0e(s);let a=cs(s);if(a.__metadata){let n=a.__metadata.version,c=a.__metadata.cacheKey;this.lockfileLastVersion=n,this.lockfileNeedsRefresh=n<xT;for(let f of Object.keys(a)){if(f===\"__metadata\")continue;let p=a[f];if(typeof p.resolution>\"u\")throw new Error(`Assertion failed: Expected the lockfile entry to have a resolution field (${f})`);let h=Rp(p.resolution,!0),E=new Ut;E.load(p,{yamlCompatibilityMode:!0});let C=E.version,S=E.languageName||r,x=p.linkType.toUpperCase(),I=p.conditions??null,T=E.dependencies,O=E.peerDependencies,U=E.dependenciesMeta,Y=E.peerDependenciesMeta,te=E.bin;if(p.checksum!=null){let ue=typeof c<\"u\"&&!p.checksum.includes(\"/\")?`${c}/${p.checksum}`:p.checksum;this.storedChecksums.set(h.locatorHash,ue)}let ie={...h,version:C,languageName:S,linkType:x,conditions:I,dependencies:T,peerDependencies:O,dependenciesMeta:U,peerDependenciesMeta:Y,bin:te};this.originalPackages.set(ie.locatorHash,ie);for(let ue of f.split(Bit)){let ae=E0(ue);n<=6&&(ae=this.configuration.normalizeDependency(ae),ae=Mn(ae,ae.range.replace(/^patch:[^@]+@(?!npm(:|%3A))/,\"$1npm%3A\"))),this.storedDescriptors.set(ae.descriptorHash,ae),this.storedResolutions.set(ae.descriptorHash,h.locatorHash)}}}else s.includes(\"yarn lockfile v1\")&&(this.lockfileLastVersion=-1)}}async setupWorkspaces(){this.workspaces=[],this.workspacesByCwd=new Map,this.workspacesByIdent=new Map;let t=new Set,r=(0,PT.default)(4),s=async(a,n)=>{if(t.has(n))return a;t.add(n);let c=new jI(n,{project:this});await r(()=>c.setup());let f=a.then(()=>{this.addWorkspace(c)});return Array.from(c.workspacesCwds).reduce(s,f)};await s(Promise.resolve(),this.cwd)}addWorkspace(t){let r=this.workspacesByIdent.get(t.anchoredLocator.identHash);if(typeof r<\"u\")throw new Error(`Duplicate workspace name ${$i(this.configuration,t.anchoredLocator)}: ${fe.fromPortablePath(t.cwd)} conflicts with ${fe.fromPortablePath(r.cwd)}`);this.workspaces.push(t),this.workspacesByCwd.set(t.cwd,t),this.workspacesByIdent.set(t.anchoredLocator.identHash,t)}get topLevelWorkspace(){return this.getWorkspaceByCwd(this.cwd)}tryWorkspaceByCwd(t){K.isAbsolute(t)||(t=K.resolve(this.cwd,t)),t=K.normalize(t).replace(/\\/+$/,\"\");let r=this.workspacesByCwd.get(t);return r||null}getWorkspaceByCwd(t){let r=this.tryWorkspaceByCwd(t);if(!r)throw new Error(`Workspace not found (${t})`);return r}tryWorkspaceByFilePath(t){let r=null;for(let s of this.workspaces)K.relative(s.cwd,t).startsWith(\"../\")||r&&r.cwd.length>=s.cwd.length||(r=s);return r||null}getWorkspaceByFilePath(t){let r=this.tryWorkspaceByFilePath(t);if(!r)throw new Error(`Workspace not found (${t})`);return r}tryWorkspaceByIdent(t){let r=this.workspacesByIdent.get(t.identHash);return typeof r>\"u\"?null:r}getWorkspaceByIdent(t){let r=this.tryWorkspaceByIdent(t);if(!r)throw new Error(`Workspace not found (${$i(this.configuration,t)})`);return r}tryWorkspaceByDescriptor(t){if(t.range.startsWith(Ii.protocol)){let s=t.range.slice(Ii.protocol.length);if(s!==\"^\"&&s!==\"~\"&&s!==\"*\"&&!dl(s))return this.tryWorkspaceByCwd(s)}let r=this.tryWorkspaceByIdent(t);return r===null||(Qp(t)&&(t=k2(t)),!r.accepts(t.range))?null:r}getWorkspaceByDescriptor(t){let r=this.tryWorkspaceByDescriptor(t);if(r===null)throw new Error(`Workspace not found (${oi(this.configuration,t)})`);return r}tryWorkspaceByLocator(t){let r=this.tryWorkspaceByIdent(t);return r===null||(Hu(t)&&(t=sI(t)),r.anchoredLocator.locatorHash!==t.locatorHash)?null:r}getWorkspaceByLocator(t){let r=this.tryWorkspaceByLocator(t);if(!r)throw new Error(`Workspace not found (${Vr(this.configuration,t)})`);return r}deleteDescriptor(t){this.storedResolutions.delete(t),this.storedDescriptors.delete(t)}deleteLocator(t){this.originalPackages.delete(t),this.storedPackages.delete(t),this.accessibleLocators.delete(t)}forgetResolution(t){if(\"descriptorHash\"in t){let r=this.storedResolutions.get(t.descriptorHash);this.deleteDescriptor(t.descriptorHash);let s=new Set(this.storedResolutions.values());typeof r<\"u\"&&!s.has(r)&&this.deleteLocator(r)}if(\"locatorHash\"in t){this.deleteLocator(t.locatorHash);for(let[r,s]of this.storedResolutions)s===t.locatorHash&&this.deleteDescriptor(r)}}forgetTransientResolutions(){let t=this.configuration.makeResolver(),r=new Map;for(let[s,a]of this.storedResolutions.entries()){let n=r.get(a);n||r.set(a,n=new Set),n.add(s)}for(let s of this.originalPackages.values()){let a;try{a=t.shouldPersistResolution(s,{project:this,resolver:t})}catch{a=!1}if(!a){this.deleteLocator(s.locatorHash);let n=r.get(s.locatorHash);if(n){r.delete(s.locatorHash);for(let c of n)this.deleteDescriptor(c)}}}}forgetVirtualResolutions(){for(let t of this.storedPackages.values())for(let[r,s]of t.dependencies)Qp(s)&&t.dependencies.set(r,k2(s))}getDependencyMeta(t,r){let s={},n=this.topLevelWorkspace.manifest.dependenciesMeta.get(fn(t));if(!n)return s;let c=n.get(null);if(c&&Object.assign(s,c),r===null||!u0e.default.valid(r))return s;for(let[f,p]of n)f!==null&&f===r&&Object.assign(s,p);return s}async findLocatorForLocation(t,{strict:r=!1}={}){let s=new ki,a=this.configuration.getLinkers(),n={project:this,report:s};for(let c of a){let f=await c.findPackageLocator(t,n);if(f){if(r&&(await c.findPackageLocation(f,n)).replace(l0e,\"\")!==t.replace(l0e,\"\"))continue;return f}}return null}async loadUserConfig(){let t=K.join(this.cwd,\".pnp.cjs\");await le.existsPromise(t)&&xp(t).setup();let r=K.join(this.cwd,\"yarn.config.cjs\");return await le.existsPromise(r)?xp(r):null}async preparePackage(t,{resolver:r,resolveOptions:s}){let a=await this.configuration.getPackageExtensions(),n=this.configuration.normalizePackage(t,{packageExtensions:a});for(let[c,f]of n.dependencies){let p=await this.configuration.reduceHook(E=>E.reduceDependency,f,this,n,f,{resolver:r,resolveOptions:s});if(!Q2(f,p))throw new Error(\"Assertion failed: The descriptor ident cannot be changed through aliases\");let h=r.bindDescriptor(p,n,s);n.dependencies.set(c,h)}return n}async resolveEverything(t){if(!this.workspacesByCwd||!this.workspacesByIdent)throw new Error(\"Workspaces must have been setup before calling this function\");this.forgetVirtualResolutions();let r=new Map(this.originalPackages),s=[];t.lockfileOnly||this.forgetTransientResolutions();let a=t.resolver||this.configuration.makeResolver(),n=new _I(a);await n.setup(this,{report:t.report});let c=t.lockfileOnly?[new DT(a)]:[n,a],f=new em([new HI(a),...c]),p=new em([...c]),h=this.configuration.makeFetcher(),E=t.lockfileOnly?{project:this,report:t.report,resolver:f}:{project:this,report:t.report,resolver:f,fetchOptions:{project:this,cache:t.cache,checksums:this.storedChecksums,report:t.report,fetcher:h,cacheOptions:{mirrorWriteOnly:!0}}},C=new Map,S=new Map,x=new Map,I=new Map,T=new Map,O=new Map,U=this.topLevelWorkspace.anchoredLocator,Y=new Set,te=[],ie=KH(),ue=this.configuration.getSupportedArchitectures();await t.report.startProgressPromise(yo.progressViaTitle(),async ce=>{let X=async tt=>{let Ne=await YE(async()=>await f.resolve(tt,E),Re=>`${Vr(this.configuration,tt)}: ${Re}`);if(!R2(tt,Ne))throw new Error(`Assertion failed: The locator cannot be changed by the resolver (went from ${Vr(this.configuration,tt)} to ${Vr(this.configuration,Ne)})`);I.set(Ne.locatorHash,Ne),!r.delete(Ne.locatorHash)&&!this.tryWorkspaceByLocator(Ne)&&s.push(Ne);let be=await this.preparePackage(Ne,{resolver:f,resolveOptions:E}),je=Lu([...be.dependencies.values()].map(Re=>_(Re)));return te.push(je),je.catch(()=>{}),S.set(be.locatorHash,be),be},De=async tt=>{let Ne=T.get(tt.locatorHash);if(typeof Ne<\"u\")return Ne;let ke=Promise.resolve().then(()=>X(tt));return T.set(tt.locatorHash,ke),ke},Qe=async(tt,Ne)=>{let ke=await _(Ne);return C.set(tt.descriptorHash,tt),x.set(tt.descriptorHash,ke.locatorHash),ke},it=async tt=>{ce.setTitle(oi(this.configuration,tt));let Ne=this.resolutionAliases.get(tt.descriptorHash);if(typeof Ne<\"u\")return Qe(tt,this.storedDescriptors.get(Ne));let ke=f.getResolutionDependencies(tt,E),be=Object.fromEntries(await Lu(Object.entries(ke).map(async([ct,Me])=>{let P=f.bindDescriptor(Me,U,E),w=await _(P);return Y.add(w.locatorHash),[ct,w]}))),Re=(await YE(async()=>await f.getCandidates(tt,be,E),ct=>`${oi(this.configuration,tt)}: ${ct}`))[0];if(typeof Re>\"u\")throw new _t(82,`${oi(this.configuration,tt)}: No candidates found`);if(t.checkResolutions){let{locators:ct}=await p.getSatisfying(tt,be,[Re],{...E,resolver:p});if(!ct.find(Me=>Me.locatorHash===Re.locatorHash))throw new _t(78,`Invalid resolution ${D2(this.configuration,tt,Re)}`)}return C.set(tt.descriptorHash,tt),x.set(tt.descriptorHash,Re.locatorHash),De(Re)},_=tt=>{let Ne=O.get(tt.descriptorHash);if(typeof Ne<\"u\")return Ne;C.set(tt.descriptorHash,tt);let ke=Promise.resolve().then(()=>it(tt));return O.set(tt.descriptorHash,ke),ke};for(let tt of this.workspaces){let Ne=tt.anchoredDescriptor;te.push(_(Ne))}for(;te.length>0;){let tt=[...te];te.length=0,await Lu(tt)}});let ae=zl(r.values(),ce=>this.tryWorkspaceByLocator(ce)?zl.skip:ce);if(s.length>0||ae.length>0){let ce=new Set(this.workspaces.flatMap(tt=>{let Ne=S.get(tt.anchoredLocator.locatorHash);if(!Ne)throw new Error(\"Assertion failed: The workspace should have been resolved\");return Array.from(Ne.dependencies.values(),ke=>{let be=x.get(ke.descriptorHash);if(!be)throw new Error(\"Assertion failed: The resolution should have been registered\");return be})})),X=tt=>ce.has(tt.locatorHash)?\"0\":\"1\",De=tt=>gl(tt),Qe=Ys(s,[X,De]),it=Ys(ae,[X,De]),_=t.report.getRecommendedLength();Qe.length>0&&t.report.reportInfo(85,`${jt(this.configuration,\"+\",gt.ADDED)} ${Xk(this.configuration,Qe,_)}`),it.length>0&&t.report.reportInfo(85,`${jt(this.configuration,\"-\",gt.REMOVED)} ${Xk(this.configuration,it,_)}`)}let de=new Set(this.resolutionAliases.values()),Ae=new Set(S.keys()),Ce=new Set,Ee=new Map,g=[],Se=new Map;bit({project:this,accessibleLocators:Ce,volatileDescriptors:de,optionalBuilds:Ae,peerRequirements:Ee,peerWarnings:g,peerRequirementNodes:Se,allDescriptors:C,allResolutions:x,allPackages:S});for(let ce of Y)Ae.delete(ce);for(let ce of de)C.delete(ce),x.delete(ce);let Be=new Set,me=new Set;for(let ce of S.values())ce.conditions!=null&&Ae.has(ce.locatorHash)&&(QQ(ce,ue)||(QQ(ce,ie)&&t.report.reportWarningOnce(77,`${Vr(this.configuration,ce)}: Your current architecture (${process.platform}-${process.arch}) is supported by this package, but is missing from the ${jt(this.configuration,\"supportedArchitectures\",gt.SETTING)} setting`),me.add(ce.locatorHash)),Be.add(ce.locatorHash));this.storedResolutions=x,this.storedDescriptors=C,this.storedPackages=S,this.accessibleLocators=Ce,this.conditionalLocators=Be,this.disabledLocators=me,this.originalPackages=I,this.optionalBuilds=Ae,this.peerRequirements=Ee,this.peerWarnings=g,this.peerRequirementNodes=Se}async fetchEverything({cache:t,report:r,fetcher:s,mode:a,persistProject:n=!0}){let c={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators},f=s||this.configuration.makeFetcher(),p={checksums:this.storedChecksums,project:this,cache:t,fetcher:f,report:r,cacheOptions:c},h=Array.from(new Set(Ys(this.storedResolutions.values(),[I=>{let T=this.storedPackages.get(I);if(!T)throw new Error(\"Assertion failed: The locator should have been registered\");return gl(T)}])));a===\"update-lockfile\"&&(h=h.filter(I=>!this.storedChecksums.has(I)));let E=!1,C=yo.progressViaCounter(h.length);await r.reportProgress(C);let S=(0,PT.default)(vit);if(await Lu(h.map(I=>S(async()=>{let T=this.storedPackages.get(I);if(!T)throw new Error(\"Assertion failed: The locator should have been registered\");if(Hu(T))return;let O;try{O=await f.fetch(T,p)}catch(U){U.message=`${Vr(this.configuration,T)}: ${U.message}`,r.reportExceptionOnce(U),E=U;return}O.checksum!=null?this.storedChecksums.set(T.locatorHash,O.checksum):this.storedChecksums.delete(T.locatorHash),O.releaseFs&&O.releaseFs()}).finally(()=>{C.tick()}))),E)throw E;let x=n&&a!==\"update-lockfile\"?await this.cacheCleanup({cache:t,report:r}):null;if(r.cacheMisses.size>0||x){let T=(await Promise.all([...r.cacheMisses].map(async ae=>{let de=this.storedPackages.get(ae),Ae=this.storedChecksums.get(ae)??null,Ce=t.getLocatorPath(de,Ae);return(await le.statPromise(Ce)).size}))).reduce((ae,de)=>ae+de,0)-(x?.size??0),O=r.cacheMisses.size,U=x?.count??0,Y=`${qk(O,{zero:\"No new packages\",one:\"A package was\",more:`${jt(this.configuration,O,gt.NUMBER)} packages were`})} added to the project`,te=`${qk(U,{zero:\"none were\",one:\"one was\",more:`${jt(this.configuration,U,gt.NUMBER)} were`})} removed`,ie=T!==0?` (${jt(this.configuration,T,gt.SIZE_DIFF)})`:\"\",ue=U>0?O>0?`${Y}, and ${te}${ie}.`:`${Y}, but ${te}${ie}.`:`${Y}${ie}.`;r.reportInfo(13,ue)}}async linkEverything({cache:t,report:r,fetcher:s,mode:a}){let n={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators,skipIntegrityCheck:!0},c=s||this.configuration.makeFetcher(),f={checksums:this.storedChecksums,project:this,cache:t,fetcher:c,report:r,cacheOptions:n},p=this.configuration.getLinkers(),h={project:this,report:r},E=new Map(p.map(Be=>{let me=Be.makeInstaller(h),ce=Be.getCustomDataKey(),X=this.linkersCustomData.get(ce);return typeof X<\"u\"&&me.attachCustomData(X),[Be,me]})),C=new Map,S=new Map,x=new Map,I=new Map(await Lu([...this.accessibleLocators].map(async Be=>{let me=this.storedPackages.get(Be);if(!me)throw new Error(\"Assertion failed: The locator should have been registered\");return[Be,await c.fetch(me,f)]}))),T=[],O=new Set,U=[];for(let Be of this.accessibleLocators){let me=this.storedPackages.get(Be);if(typeof me>\"u\")throw new Error(\"Assertion failed: The locator should have been registered\");let ce=I.get(me.locatorHash);if(typeof ce>\"u\")throw new Error(\"Assertion failed: The fetch result should have been registered\");let X=[],De=it=>{X.push(it)},Qe=this.tryWorkspaceByLocator(me);if(Qe!==null){let it=[],{scripts:_}=Qe.manifest;for(let Ne of[\"preinstall\",\"install\",\"postinstall\"])_.has(Ne)&&it.push({type:0,script:Ne});try{for(let[Ne,ke]of E)if(Ne.supportsPackage(me,h)&&(await ke.installPackage(me,ce,{holdFetchResult:De})).buildRequest!==null)throw new Error(\"Assertion failed: Linkers can't return build directives for workspaces; this responsibility befalls to the Yarn core\")}finally{X.length===0?ce.releaseFs?.():T.push(Lu(X).catch(()=>{}).then(()=>{ce.releaseFs?.()}))}let tt=K.join(ce.packageFs.getRealPath(),ce.prefixPath);S.set(me.locatorHash,tt),!Hu(me)&&it.length>0&&x.set(me.locatorHash,{buildDirectives:it,buildLocations:[tt]})}else{let it=p.find(Ne=>Ne.supportsPackage(me,h));if(!it)throw new _t(12,`${Vr(this.configuration,me)} isn't supported by any available linker`);let _=E.get(it);if(!_)throw new Error(\"Assertion failed: The installer should have been registered\");let tt;try{tt=await _.installPackage(me,ce,{holdFetchResult:De})}finally{X.length===0?ce.releaseFs?.():T.push(Lu(X).then(()=>{}).then(()=>{ce.releaseFs?.()}))}C.set(me.locatorHash,it),S.set(me.locatorHash,tt.packageLocation),tt.buildRequest&&tt.packageLocation&&(tt.buildRequest.skipped?(O.add(me.locatorHash),this.skippedBuilds.has(me.locatorHash)||U.push([me,tt.buildRequest.explain])):x.set(me.locatorHash,{buildDirectives:tt.buildRequest.directives,buildLocations:[tt.packageLocation]}))}}let Y=new Map;for(let Be of this.accessibleLocators){let me=this.storedPackages.get(Be);if(!me)throw new Error(\"Assertion failed: The locator should have been registered\");let ce=this.tryWorkspaceByLocator(me)!==null,X=async(De,Qe)=>{let it=S.get(me.locatorHash);if(typeof it>\"u\")throw new Error(`Assertion failed: The package (${Vr(this.configuration,me)}) should have been registered`);let _=[];for(let tt of me.dependencies.values()){let Ne=this.storedResolutions.get(tt.descriptorHash);if(typeof Ne>\"u\")throw new Error(`Assertion failed: The resolution (${oi(this.configuration,tt)}, from ${Vr(this.configuration,me)})should have been registered`);let ke=this.storedPackages.get(Ne);if(typeof ke>\"u\")throw new Error(`Assertion failed: The package (${Ne}, resolved from ${oi(this.configuration,tt)}) should have been registered`);let be=this.tryWorkspaceByLocator(ke)===null?C.get(Ne):null;if(typeof be>\"u\")throw new Error(`Assertion failed: The package (${Ne}, resolved from ${oi(this.configuration,tt)}) should have been registered`);be===De||be===null?S.get(ke.locatorHash)!==null&&_.push([tt,ke]):!ce&&it!==null&&C2(Y,Ne).push(it)}it!==null&&await Qe.attachInternalDependencies(me,_)};if(ce)for(let[De,Qe]of E)De.supportsPackage(me,h)&&await X(De,Qe);else{let De=C.get(me.locatorHash);if(!De)throw new Error(\"Assertion failed: The linker should have been found\");let Qe=E.get(De);if(!Qe)throw new Error(\"Assertion failed: The installer should have been registered\");await X(De,Qe)}}for(let[Be,me]of Y){let ce=this.storedPackages.get(Be);if(!ce)throw new Error(\"Assertion failed: The package should have been registered\");let X=C.get(ce.locatorHash);if(!X)throw new Error(\"Assertion failed: The linker should have been found\");let De=E.get(X);if(!De)throw new Error(\"Assertion failed: The installer should have been registered\");await De.attachExternalDependents(ce,me)}let te=new Map;for(let[Be,me]of E){let ce=await me.finalizeInstall();for(let X of ce?.records??[])X.buildRequest.skipped?(O.add(X.locator.locatorHash),this.skippedBuilds.has(X.locator.locatorHash)||U.push([X.locator,X.buildRequest.explain])):x.set(X.locator.locatorHash,{buildDirectives:X.buildRequest.directives,buildLocations:X.buildLocations});typeof ce?.customData<\"u\"&&te.set(Be.getCustomDataKey(),ce.customData)}if(this.linkersCustomData=te,await Lu(T),a===\"skip-build\")return;for(let[,Be]of Ys(U,([me])=>gl(me)))Be(r);let ie=new Set(x.keys()),ue=(0,bT.createHash)(\"sha512\");ue.update(process.versions.node),await this.configuration.triggerHook(Be=>Be.globalHashGeneration,this,Be=>{ue.update(\"\\0\"),ue.update(Be)});let ae=ue.digest(\"hex\"),de=new Map,Ae=Be=>{let me=de.get(Be.locatorHash);if(typeof me<\"u\")return me;let ce=this.storedPackages.get(Be.locatorHash);if(typeof ce>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");let X=(0,bT.createHash)(\"sha512\");X.update(Be.locatorHash),de.set(Be.locatorHash,\"<recursive>\");for(let De of ce.dependencies.values()){let Qe=this.storedResolutions.get(De.descriptorHash);if(typeof Qe>\"u\")throw new Error(`Assertion failed: The resolution (${oi(this.configuration,De)}) should have been registered`);let it=this.storedPackages.get(Qe);if(typeof it>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");X.update(Ae(it))}return me=X.digest(\"hex\"),de.set(Be.locatorHash,me),me},Ce=(Be,me)=>{let ce=(0,bT.createHash)(\"sha512\");ce.update(ae),ce.update(Ae(Be));for(let X of me)ce.update(X);return ce.digest(\"hex\")},Ee=new Map,g=!1,Se=Be=>{let me=new Set([Be.locatorHash]);for(let ce of me){let X=this.storedPackages.get(ce);if(!X)throw new Error(\"Assertion failed: The package should have been registered\");for(let De of X.dependencies.values()){let Qe=this.storedResolutions.get(De.descriptorHash);if(!Qe)throw new Error(`Assertion failed: The resolution (${oi(this.configuration,De)}) should have been registered`);if(Qe!==Be.locatorHash&&ie.has(Qe))return!1;let it=this.storedPackages.get(Qe);if(!it)throw new Error(\"Assertion failed: The package should have been registered\");let _=this.tryWorkspaceByLocator(it);if(_){if(_.anchoredLocator.locatorHash!==Be.locatorHash&&ie.has(_.anchoredLocator.locatorHash))return!1;me.add(_.anchoredLocator.locatorHash)}me.add(Qe)}}return!0};for(;ie.size>0;){let Be=ie.size,me=[];for(let ce of ie){let X=this.storedPackages.get(ce);if(!X)throw new Error(\"Assertion failed: The package should have been registered\");if(!Se(X))continue;let De=x.get(X.locatorHash);if(!De)throw new Error(\"Assertion failed: The build directive should have been registered\");let Qe=Ce(X,De.buildLocations);if(this.storedBuildState.get(X.locatorHash)===Qe){Ee.set(X.locatorHash,Qe),ie.delete(ce);continue}g||(await this.persistInstallStateFile(),g=!0),this.storedBuildState.has(X.locatorHash)?r.reportInfo(8,`${Vr(this.configuration,X)} must be rebuilt because its dependency tree changed`):r.reportInfo(7,`${Vr(this.configuration,X)} must be built because it never has been before or the last one failed`);let it=De.buildLocations.map(async _=>{if(!K.isAbsolute(_))throw new Error(`Assertion failed: Expected the build location to be absolute (not ${_})`);for(let tt of De.buildDirectives){let Ne=`# This file contains the result of Yarn building a package (${gl(X)})\n`;switch(tt.type){case 0:Ne+=`# Script name: ${tt.script}\n`;break;case 1:Ne+=`# Script code: ${tt.script}\n`;break}let ke=null;if(!await le.mktempPromise(async je=>{let Re=K.join(je,\"build.log\"),{stdout:ct,stderr:Me}=this.configuration.getSubprocessStreams(Re,{header:Ne,prefix:Vr(this.configuration,X),report:r}),P;try{switch(tt.type){case 0:P=await OR(X,tt.script,[],{cwd:_,project:this,stdin:ke,stdout:ct,stderr:Me});break;case 1:P=await kj(X,tt.script,[],{cwd:_,project:this,stdin:ke,stdout:ct,stderr:Me});break}}catch(y){Me.write(y.stack),P=1}if(ct.end(),Me.end(),P===0)return!0;le.detachTemp(je);let w=`${Vr(this.configuration,X)} couldn't be built successfully (exit code ${jt(this.configuration,P,gt.NUMBER)}, logs can be found here: ${jt(this.configuration,Re,gt.PATH)})`,b=this.optionalBuilds.has(X.locatorHash);return b?r.reportInfo(9,w):r.reportError(9,w),ype&&r.reportFold(fe.fromPortablePath(Re),le.readFileSync(Re,\"utf8\")),b}))return!1}return!0});me.push(...it,Promise.allSettled(it).then(_=>{ie.delete(ce),_.every(tt=>tt.status===\"fulfilled\"&&tt.value===!0)&&Ee.set(X.locatorHash,Qe)}))}if(await Lu(me),Be===ie.size){let ce=Array.from(ie).map(X=>{let De=this.storedPackages.get(X);if(!De)throw new Error(\"Assertion failed: The package should have been registered\");return Vr(this.configuration,De)}).join(\", \");r.reportError(3,`Some packages have circular dependencies that make their build order unsatisfiable - as a result they won't be built (affected packages are: ${ce})`);break}}this.storedBuildState=Ee,this.skippedBuilds=O}async installWithNewReport(t,r){return(await Ot.start({configuration:this.configuration,json:t.json,stdout:t.stdout,forceSectionAlignment:!0,includeLogs:!t.json&&!t.quiet,includeVersion:!0},async a=>{await this.install({...r,report:a})})).exitCode()}async install(t){let r=this.configuration.get(\"nodeLinker\");ze.telemetry?.reportInstall(r);let s=!1;if(await t.report.startTimerPromise(\"Project validation\",{skipIfEmpty:!0},async()=>{this.configuration.get(\"enableOfflineMode\")&&t.report.reportWarning(90,\"Offline work is enabled; Yarn won't fetch packages from the remote registry if it can avoid it\"),await this.configuration.triggerHook(E=>E.validateProject,this,{reportWarning:(E,C)=>{t.report.reportWarning(E,C)},reportError:(E,C)=>{t.report.reportError(E,C),s=!0}})}),s)return;let a=await this.configuration.getPackageExtensions();for(let E of a.values())for(let[,C]of E)for(let S of C)S.status=\"inactive\";let n=K.join(this.cwd,Er.lockfile),c=null;if(t.immutable)try{c=await le.readFilePromise(n,\"utf8\")}catch(E){throw E.code===\"ENOENT\"?new _t(28,\"The lockfile would have been created by this install, which is explicitly forbidden.\"):E}await t.report.startTimerPromise(\"Resolution step\",async()=>{await this.resolveEverything(t)}),await t.report.startTimerPromise(\"Post-resolution validation\",{skipIfEmpty:!0},async()=>{xit(this,t.report);for(let[,E]of a)for(let[,C]of E)for(let S of C)if(S.userProvided){let x=jt(this.configuration,S,gt.PACKAGE_EXTENSION);switch(S.status){case\"inactive\":t.report.reportWarning(68,`${x}: No matching package in the dependency tree; you may not need this rule anymore.`);break;case\"redundant\":t.report.reportWarning(69,`${x}: This rule seems redundant when applied on the original package; the extension may have been applied upstream.`);break}}if(c!==null){let E=md(c,this.generateLockfile());if(E!==c){let C=s0e(n,n,c,E,void 0,void 0,{maxEditLength:100});if(C){t.report.reportSeparator();for(let S of C.hunks){t.report.reportInfo(null,`@@ -${S.oldStart},${S.oldLines} +${S.newStart},${S.newLines} @@`);for(let x of S.lines)x.startsWith(\"+\")?t.report.reportError(28,jt(this.configuration,x,gt.ADDED)):x.startsWith(\"-\")?t.report.reportError(28,jt(this.configuration,x,gt.REMOVED)):t.report.reportInfo(null,jt(this.configuration,x,\"grey\"))}t.report.reportSeparator()}throw new _t(28,\"The lockfile would have been modified by this install, which is explicitly forbidden.\")}}});for(let E of a.values())for(let[,C]of E)for(let S of C)S.userProvided&&S.status===\"active\"&&ze.telemetry?.reportPackageExtension(Jd(S,gt.PACKAGE_EXTENSION));await t.report.startTimerPromise(\"Fetch step\",async()=>{await this.fetchEverything(t)});let f=t.immutable?[...new Set(this.configuration.get(\"immutablePatterns\"))].sort():[],p=await Promise.all(f.map(async E=>SQ(E,{cwd:this.cwd})));(typeof t.persistProject>\"u\"||t.persistProject)&&await this.persist(),await t.report.startTimerPromise(\"Link step\",async()=>{if(t.mode===\"update-lockfile\"){t.report.reportWarning(73,`Skipped due to ${jt(this.configuration,\"mode=update-lockfile\",gt.CODE)}`);return}await this.linkEverything(t);let E=await Promise.all(f.map(async C=>SQ(C,{cwd:this.cwd})));for(let C=0;C<f.length;++C)p[C]!==E[C]&&t.report.reportError(64,`The checksum for ${f[C]} has been modified by this install, which is explicitly forbidden.`)}),await this.persistInstallStateFile();let h=!1;await t.report.startTimerPromise(\"Post-install validation\",{skipIfEmpty:!0},async()=>{await this.configuration.triggerHook(E=>E.validateProjectAfterInstall,this,{reportWarning:(E,C)=>{t.report.reportWarning(E,C)},reportError:(E,C)=>{t.report.reportError(E,C),h=!0}})}),!h&&await this.configuration.triggerHook(E=>E.afterAllInstalled,this,t)}generateLockfile(){let t=new Map;for(let[n,c]of this.storedResolutions.entries()){let f=t.get(c);f||t.set(c,f=new Set),f.add(n)}let r={},{cacheKey:s}=Jr.getCacheKey(this.configuration);r.__metadata={version:xT,cacheKey:s};for(let[n,c]of t.entries()){let f=this.originalPackages.get(n);if(!f)continue;let p=[];for(let C of c){let S=this.storedDescriptors.get(C);if(!S)throw new Error(\"Assertion failed: The descriptor should have been registered\");p.push(S)}let h=p.map(C=>hl(C)).sort().join(\", \"),E=new Ut;E.version=f.linkType===\"HARD\"?f.version:\"0.0.0-use.local\",E.languageName=f.languageName,E.dependencies=new Map(f.dependencies),E.peerDependencies=new Map(f.peerDependencies),E.dependenciesMeta=new Map(f.dependenciesMeta),E.peerDependenciesMeta=new Map(f.peerDependenciesMeta),E.bin=new Map(f.bin),r[h]={...E.exportTo({},{compatibilityMode:!1}),linkType:f.linkType.toLowerCase(),resolution:gl(f),checksum:this.storedChecksums.get(f.locatorHash),conditions:f.conditions||void 0}}return`${[`# This file is generated by running \"yarn install\" inside your project.\n`,`# Manual changes might be lost - proceed with caution!\n`].join(\"\")}\n`+cl(r)}async persistLockfile(){let t=K.join(this.cwd,Er.lockfile),r=\"\";try{r=await le.readFilePromise(t,\"utf8\")}catch{}let s=this.generateLockfile(),a=md(r,s);a!==r&&(await le.writeFilePromise(t,a),this.lockFileChecksum=c0e(a),this.lockfileNeedsRefresh=!1)}async persistInstallStateFile(){let t=[];for(let c of Object.values(AG))t.push(...c);let r=Yd(this,t),s=pG.default.serialize(r),a=fs(s);if(this.installStateChecksum===a)return;let n=this.configuration.get(\"installStatePath\");await le.mkdirPromise(K.dirname(n),{recursive:!0}),await le.writeFilePromise(n,await Sit(s)),this.installStateChecksum=a}async restoreInstallState({restoreLinkersCustomData:t=!0,restoreResolutions:r=!0,restoreBuildState:s=!0}={}){let a=this.configuration.get(\"installStatePath\"),n;try{let c=await Dit(await le.readFilePromise(a));n=pG.default.deserialize(c),this.installStateChecksum=fs(c)}catch{r&&await this.applyLightResolution();return}t&&typeof n.linkersCustomData<\"u\"&&(this.linkersCustomData=n.linkersCustomData),s&&Object.assign(this,Yd(n,AG.restoreBuildState)),r&&(n.lockFileChecksum===this.lockFileChecksum?Object.assign(this,Yd(n,AG.restoreResolutions)):await this.applyLightResolution())}async applyLightResolution(){await this.resolveEverything({lockfileOnly:!0,report:new ki}),await this.persistInstallStateFile()}async persist(){let t=(0,PT.default)(4);await Promise.all([this.persistLockfile(),...this.workspaces.map(r=>t(()=>r.persistManifest()))])}async cacheCleanup({cache:t,report:r}){if(this.configuration.get(\"enableGlobalCache\"))return null;let s=new Set([\".gitignore\"]);if(!P8(t.cwd,this.cwd)||!await le.existsPromise(t.cwd))return null;let a=[];for(let c of await le.readdirPromise(t.cwd)){if(s.has(c))continue;let f=K.resolve(t.cwd,c);t.markedFiles.has(f)||(t.immutable?r.reportError(56,`${jt(this.configuration,K.basename(f),\"magenta\")} appears to be unused and would be marked for deletion, but the cache is immutable`):a.push(le.lstatPromise(f).then(async p=>(await le.removePromise(f),p.size))))}if(a.length===0)return null;let n=await Promise.all(a);return{count:a.length,size:n.reduce((c,f)=>c+f,0)}}}});function kit(e){let s=Math.floor(e.timeNow/864e5),a=e.updateInterval*864e5,n=e.state.lastUpdate??e.timeNow+a+Math.floor(a*e.randomInitialInterval),c=n+a,f=e.state.lastTips??s*864e5,p=f+864e5+8*36e5-e.timeZone,h=c<=e.timeNow,E=p<=e.timeNow,C=null;return(h||E||!e.state.lastUpdate||!e.state.lastTips)&&(C={},C.lastUpdate=h?e.timeNow:n,C.lastTips=f,C.blocks=h?{}:e.state.blocks,C.displayedTips=e.state.displayedTips),{nextState:C,triggerUpdate:h,triggerTips:E,nextTips:E?s*864e5:f}}var GI,A0e=Ze(()=>{Dt();uv();y0();AR();xc();Fp();GI=class{constructor(t,r){this.values=new Map;this.hits=new Map;this.enumerators=new Map;this.nextTips=0;this.displayedTips=[];this.shouldCommitTips=!1;this.configuration=t;let s=this.getRegistryPath();this.isNew=!le.existsSync(s),this.shouldShowTips=!1,this.sendReport(r),this.startBuffer()}commitTips(){this.shouldShowTips&&(this.shouldCommitTips=!0)}selectTip(t){let r=new Set(this.displayedTips),s=f=>f&&An?eA(An,f):!1,a=t.map((f,p)=>p).filter(f=>t[f]&&s(t[f]?.selector));if(a.length===0)return null;let n=a.filter(f=>!r.has(f));if(n.length===0){let f=Math.floor(a.length*.2);this.displayedTips=f>0?this.displayedTips.slice(-f):[],n=a.filter(p=>!r.has(p))}let c=n[Math.floor(Math.random()*n.length)];return this.displayedTips.push(c),this.commitTips(),t[c]}reportVersion(t){this.reportValue(\"version\",t.replace(/-git\\..*/,\"-git\"))}reportCommandName(t){this.reportValue(\"commandName\",t||\"<none>\")}reportPluginName(t){this.reportValue(\"pluginName\",t)}reportProject(t){this.reportEnumerator(\"projectCount\",t)}reportInstall(t){this.reportHit(\"installCount\",t)}reportPackageExtension(t){this.reportValue(\"packageExtension\",t)}reportWorkspaceCount(t){this.reportValue(\"workspaceCount\",String(t))}reportDependencyCount(t){this.reportValue(\"dependencyCount\",String(t))}reportValue(t,r){Pp(this.values,t).add(r)}reportEnumerator(t,r){Pp(this.enumerators,t).add(fs(r))}reportHit(t,r=\"*\"){let s=P4(this.hits,t),a=Zl(s,r,()=>0);s.set(r,a+1)}getRegistryPath(){let t=this.configuration.get(\"globalFolder\");return K.join(t,\"telemetry.json\")}sendReport(t){let r=this.getRegistryPath(),s;try{s=le.readJsonSync(r)}catch{s={}}let{nextState:a,triggerUpdate:n,triggerTips:c,nextTips:f}=kit({state:s,timeNow:Date.now(),timeZone:new Date().getTimezoneOffset()*60*1e3,randomInitialInterval:Math.random(),updateInterval:this.configuration.get(\"telemetryInterval\")});if(this.nextTips=f,this.displayedTips=s.displayedTips??[],a!==null)try{le.mkdirSync(K.dirname(r),{recursive:!0}),le.writeJsonSync(r,a)}catch{return!1}if(c&&this.configuration.get(\"enableTips\")&&(this.shouldShowTips=!0),n){let p=s.blocks??{};if(Object.keys(p).length===0){let h=`https://browser-http-intake.logs.datadoghq.eu/v1/input/${t}?ddsource=yarn`,E=C=>YH(h,C,{configuration:this.configuration}).catch(()=>{});for(let[C,S]of Object.entries(s.blocks??{})){if(Object.keys(S).length===0)continue;let x=S;x.userId=C,x.reportType=\"primary\";for(let O of Object.keys(x.enumerators??{}))x.enumerators[O]=x.enumerators[O].length;E(x);let I=new Map,T=20;for(let[O,U]of Object.entries(x.values))U.length>0&&I.set(O,U.slice(0,T));for(;I.size>0;){let O={};O.userId=C,O.reportType=\"secondary\",O.metrics={};for(let[U,Y]of I)O.metrics[U]=Y.shift(),Y.length===0&&I.delete(U);E(O)}}}}return!0}applyChanges(){let t=this.getRegistryPath(),r;try{r=le.readJsonSync(t)}catch{r={}}let s=this.configuration.get(\"telemetryUserId\")??\"*\",a=r.blocks=r.blocks??{},n=a[s]=a[s]??{};for(let c of this.hits.keys()){let f=n.hits=n.hits??{},p=f[c]=f[c]??{};for(let[h,E]of this.hits.get(c))p[h]=(p[h]??0)+E}for(let c of[\"values\",\"enumerators\"])for(let f of this[c].keys()){let p=n[c]=n[c]??{};p[f]=[...new Set([...p[f]??[],...this[c].get(f)??[]])]}this.shouldCommitTips&&(r.lastTips=this.nextTips,r.displayedTips=this.displayedTips),le.mkdirSync(K.dirname(t),{recursive:!0}),le.writeJsonSync(t,r)}startBuffer(){process.on(\"exit\",()=>{try{this.applyChanges()}catch{}})}}});var jv={};Yt(jv,{BuildDirectiveType:()=>vT,CACHE_CHECKPOINT:()=>$6,CACHE_VERSION:()=>BT,Cache:()=>Jr,Configuration:()=>ze,DEFAULT_RC_FILENAME:()=>ej,DurationUnit:()=>tj,FormatType:()=>PAe,InstallMode:()=>Na,LEGACY_PLUGINS:()=>X2,LOCKFILE_VERSION:()=>xT,LegacyMigrationResolver:()=>_I,LightReport:()=>cA,LinkType:()=>zE,LockfileResolver:()=>HI,Manifest:()=>Ut,MessageName:()=>Br,MultiFetcher:()=>uI,PackageExtensionStatus:()=>R4,PackageExtensionType:()=>Q4,PeerWarningType:()=>kT,Project:()=>Rt,Report:()=>yo,ReportError:()=>_t,SettingsType:()=>SI,StreamReport:()=>Ot,TAG_REGEXP:()=>Up,TelemetryManager:()=>GI,ThrowReport:()=>ki,VirtualFetcher:()=>fI,WindowsLinkType:()=>ER,Workspace:()=>jI,WorkspaceFetcher:()=>AI,WorkspaceResolver:()=>Ii,YarnVersion:()=>An,execUtils:()=>qr,folderUtils:()=>NQ,formatUtils:()=>pe,hashUtils:()=>Ln,httpUtils:()=>nn,miscUtils:()=>Ge,nodeUtils:()=>Ui,parseMessageName:()=>jx,reportOptionDeprecations:()=>PI,scriptUtils:()=>Cn,semverUtils:()=>Fr,stringifyMessageName:()=>Kf,structUtils:()=>j,tgzUtils:()=>ds,treeUtils:()=>Rs});var qe=Ze(()=>{gR();OQ();kc();y0();AR();xc();hR();Fj();Fp();Zo();qhe();Zhe();eG();$2();$2();e0e();tG();t0e();rG();cI();Gx();m8();f0e();Tc();fv();A0e();uG();E8();I8();$d();fG();uv();Rae()});var y0e=G((J4t,qv)=>{\"use strict\";var Rit=process.env.TERM_PROGRAM===\"Hyper\",Tit=process.platform===\"win32\",g0e=process.platform===\"linux\",dG={ballotDisabled:\"\\u2612\",ballotOff:\"\\u2610\",ballotOn:\"\\u2611\",bullet:\"\\u2022\",bulletWhite:\"\\u25E6\",fullBlock:\"\\u2588\",heart:\"\\u2764\",identicalTo:\"\\u2261\",line:\"\\u2500\",mark:\"\\u203B\",middot:\"\\xB7\",minus:\"\\uFF0D\",multiplication:\"\\xD7\",obelus:\"\\xF7\",pencilDownRight:\"\\u270E\",pencilRight:\"\\u270F\",pencilUpRight:\"\\u2710\",percent:\"%\",pilcrow2:\"\\u2761\",pilcrow:\"\\xB6\",plusMinus:\"\\xB1\",section:\"\\xA7\",starsOff:\"\\u2606\",starsOn:\"\\u2605\",upDownArrow:\"\\u2195\"},d0e=Object.assign({},dG,{check:\"\\u221A\",cross:\"\\xD7\",ellipsisLarge:\"...\",ellipsis:\"...\",info:\"i\",question:\"?\",questionSmall:\"?\",pointer:\">\",pointerSmall:\"\\xBB\",radioOff:\"( )\",radioOn:\"(*)\",warning:\"\\u203C\"}),m0e=Object.assign({},dG,{ballotCross:\"\\u2718\",check:\"\\u2714\",cross:\"\\u2716\",ellipsisLarge:\"\\u22EF\",ellipsis:\"\\u2026\",info:\"\\u2139\",question:\"?\",questionFull:\"\\uFF1F\",questionSmall:\"\\uFE56\",pointer:g0e?\"\\u25B8\":\"\\u276F\",pointerSmall:g0e?\"\\u2023\":\"\\u203A\",radioOff:\"\\u25EF\",radioOn:\"\\u25C9\",warning:\"\\u26A0\"});qv.exports=Tit&&!Rit?d0e:m0e;Reflect.defineProperty(qv.exports,\"common\",{enumerable:!1,value:dG});Reflect.defineProperty(qv.exports,\"windows\",{enumerable:!1,value:d0e});Reflect.defineProperty(qv.exports,\"other\",{enumerable:!1,value:m0e})});var zu=G((z4t,mG)=>{\"use strict\";var Fit=e=>e!==null&&typeof e==\"object\"&&!Array.isArray(e),Nit=/[\\u001b\\u009b][[\\]#;?()]*(?:(?:(?:[^\\W_]*;?[^\\W_]*)\\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g,E0e=()=>{let e={enabled:!0,visible:!0,styles:{},keys:{}};\"FORCE_COLOR\"in process.env&&(e.enabled=process.env.FORCE_COLOR!==\"0\");let t=n=>{let c=n.open=`\\x1B[${n.codes[0]}m`,f=n.close=`\\x1B[${n.codes[1]}m`,p=n.regex=new RegExp(`\\\\u001b\\\\[${n.codes[1]}m`,\"g\");return n.wrap=(h,E)=>{h.includes(f)&&(h=h.replace(p,f+c));let C=c+h+f;return E?C.replace(/\\r*\\n/g,`${f}$&${c}`):C},n},r=(n,c,f)=>typeof n==\"function\"?n(c):n.wrap(c,f),s=(n,c)=>{if(n===\"\"||n==null)return\"\";if(e.enabled===!1)return n;if(e.visible===!1)return\"\";let f=\"\"+n,p=f.includes(`\n`),h=c.length;for(h>0&&c.includes(\"unstyle\")&&(c=[...new Set([\"unstyle\",...c])].reverse());h-- >0;)f=r(e.styles[c[h]],f,p);return f},a=(n,c,f)=>{e.styles[n]=t({name:n,codes:c}),(e.keys[f]||(e.keys[f]=[])).push(n),Reflect.defineProperty(e,n,{configurable:!0,enumerable:!0,set(h){e.alias(n,h)},get(){let h=E=>s(E,h.stack);return Reflect.setPrototypeOf(h,e),h.stack=this.stack?this.stack.concat(n):[n],h}})};return a(\"reset\",[0,0],\"modifier\"),a(\"bold\",[1,22],\"modifier\"),a(\"dim\",[2,22],\"modifier\"),a(\"italic\",[3,23],\"modifier\"),a(\"underline\",[4,24],\"modifier\"),a(\"inverse\",[7,27],\"modifier\"),a(\"hidden\",[8,28],\"modifier\"),a(\"strikethrough\",[9,29],\"modifier\"),a(\"black\",[30,39],\"color\"),a(\"red\",[31,39],\"color\"),a(\"green\",[32,39],\"color\"),a(\"yellow\",[33,39],\"color\"),a(\"blue\",[34,39],\"color\"),a(\"magenta\",[35,39],\"color\"),a(\"cyan\",[36,39],\"color\"),a(\"white\",[37,39],\"color\"),a(\"gray\",[90,39],\"color\"),a(\"grey\",[90,39],\"color\"),a(\"bgBlack\",[40,49],\"bg\"),a(\"bgRed\",[41,49],\"bg\"),a(\"bgGreen\",[42,49],\"bg\"),a(\"bgYellow\",[43,49],\"bg\"),a(\"bgBlue\",[44,49],\"bg\"),a(\"bgMagenta\",[45,49],\"bg\"),a(\"bgCyan\",[46,49],\"bg\"),a(\"bgWhite\",[47,49],\"bg\"),a(\"blackBright\",[90,39],\"bright\"),a(\"redBright\",[91,39],\"bright\"),a(\"greenBright\",[92,39],\"bright\"),a(\"yellowBright\",[93,39],\"bright\"),a(\"blueBright\",[94,39],\"bright\"),a(\"magentaBright\",[95,39],\"bright\"),a(\"cyanBright\",[96,39],\"bright\"),a(\"whiteBright\",[97,39],\"bright\"),a(\"bgBlackBright\",[100,49],\"bgBright\"),a(\"bgRedBright\",[101,49],\"bgBright\"),a(\"bgGreenBright\",[102,49],\"bgBright\"),a(\"bgYellowBright\",[103,49],\"bgBright\"),a(\"bgBlueBright\",[104,49],\"bgBright\"),a(\"bgMagentaBright\",[105,49],\"bgBright\"),a(\"bgCyanBright\",[106,49],\"bgBright\"),a(\"bgWhiteBright\",[107,49],\"bgBright\"),e.ansiRegex=Nit,e.hasColor=e.hasAnsi=n=>(e.ansiRegex.lastIndex=0,typeof n==\"string\"&&n!==\"\"&&e.ansiRegex.test(n)),e.alias=(n,c)=>{let f=typeof c==\"string\"?e[c]:c;if(typeof f!=\"function\")throw new TypeError(\"Expected alias to be the name of an existing color (string) or a function\");f.stack||(Reflect.defineProperty(f,\"name\",{value:n}),e.styles[n]=f,f.stack=[n]),Reflect.defineProperty(e,n,{configurable:!0,enumerable:!0,set(p){e.alias(n,p)},get(){let p=h=>s(h,p.stack);return Reflect.setPrototypeOf(p,e),p.stack=this.stack?this.stack.concat(f.stack):f.stack,p}})},e.theme=n=>{if(!Fit(n))throw new TypeError(\"Expected theme to be an object\");for(let c of Object.keys(n))e.alias(c,n[c]);return e},e.alias(\"unstyle\",n=>typeof n==\"string\"&&n!==\"\"?(e.ansiRegex.lastIndex=0,n.replace(e.ansiRegex,\"\")):\"\"),e.alias(\"noop\",n=>n),e.none=e.clear=e.noop,e.stripColor=e.unstyle,e.symbols=y0e(),e.define=a,e};mG.exports=E0e();mG.exports.create=E0e});var ra=G(hn=>{\"use strict\";var Oit=Object.prototype.toString,_c=zu(),I0e=!1,yG=[],C0e={yellow:\"blue\",cyan:\"red\",green:\"magenta\",black:\"white\",blue:\"yellow\",red:\"cyan\",magenta:\"green\",white:\"black\"};hn.longest=(e,t)=>e.reduce((r,s)=>Math.max(r,t?s[t].length:s.length),0);hn.hasColor=e=>!!e&&_c.hasColor(e);var RT=hn.isObject=e=>e!==null&&typeof e==\"object\"&&!Array.isArray(e);hn.nativeType=e=>Oit.call(e).slice(8,-1).toLowerCase().replace(/\\s/g,\"\");hn.isAsyncFn=e=>hn.nativeType(e)===\"asyncfunction\";hn.isPrimitive=e=>e!=null&&typeof e!=\"object\"&&typeof e!=\"function\";hn.resolve=(e,t,...r)=>typeof t==\"function\"?t.call(e,...r):t;hn.scrollDown=(e=[])=>[...e.slice(1),e[0]];hn.scrollUp=(e=[])=>[e.pop(),...e];hn.reorder=(e=[])=>{let t=e.slice();return t.sort((r,s)=>r.index>s.index?1:r.index<s.index?-1:0),t};hn.swap=(e,t,r)=>{let s=e.length,a=r===s?0:r<0?s-1:r,n=e[t];e[t]=e[a],e[a]=n};hn.width=(e,t=80)=>{let r=e&&e.columns?e.columns:t;return e&&typeof e.getWindowSize==\"function\"&&(r=e.getWindowSize()[0]),process.platform===\"win32\"?r-1:r};hn.height=(e,t=20)=>{let r=e&&e.rows?e.rows:t;return e&&typeof e.getWindowSize==\"function\"&&(r=e.getWindowSize()[1]),r};hn.wordWrap=(e,t={})=>{if(!e)return e;typeof t==\"number\"&&(t={width:t});let{indent:r=\"\",newline:s=`\n`+r,width:a=80}=t,n=(s+r).match(/[^\\S\\n]/g)||[];a-=n.length;let c=`.{1,${a}}([\\\\s\\\\u200B]+|$)|[^\\\\s\\\\u200B]+?([\\\\s\\\\u200B]+|$)`,f=e.trim(),p=new RegExp(c,\"g\"),h=f.match(p)||[];return h=h.map(E=>E.replace(/\\n$/,\"\")),t.padEnd&&(h=h.map(E=>E.padEnd(a,\" \"))),t.padStart&&(h=h.map(E=>E.padStart(a,\" \"))),r+h.join(s)};hn.unmute=e=>{let t=e.stack.find(s=>_c.keys.color.includes(s));return t?_c[t]:e.stack.find(s=>s.slice(2)===\"bg\")?_c[t.slice(2)]:s=>s};hn.pascal=e=>e?e[0].toUpperCase()+e.slice(1):\"\";hn.inverse=e=>{if(!e||!e.stack)return e;let t=e.stack.find(s=>_c.keys.color.includes(s));if(t){let s=_c[\"bg\"+hn.pascal(t)];return s?s.black:e}let r=e.stack.find(s=>s.slice(0,2)===\"bg\");return r?_c[r.slice(2).toLowerCase()]||e:_c.none};hn.complement=e=>{if(!e||!e.stack)return e;let t=e.stack.find(s=>_c.keys.color.includes(s)),r=e.stack.find(s=>s.slice(0,2)===\"bg\");if(t&&!r)return _c[C0e[t]||t];if(r){let s=r.slice(2).toLowerCase(),a=C0e[s];return a&&_c[\"bg\"+hn.pascal(a)]||e}return _c.none};hn.meridiem=e=>{let t=e.getHours(),r=e.getMinutes(),s=t>=12?\"pm\":\"am\";t=t%12;let a=t===0?12:t,n=r<10?\"0\"+r:r;return a+\":\"+n+\" \"+s};hn.set=(e={},t=\"\",r)=>t.split(\".\").reduce((s,a,n,c)=>{let f=c.length-1>n?s[a]||{}:r;return!hn.isObject(f)&&n<c.length-1&&(f={}),s[a]=f},e);hn.get=(e={},t=\"\",r)=>{let s=e[t]==null?t.split(\".\").reduce((a,n)=>a&&a[n],e):e[t];return s??r};hn.mixin=(e,t)=>{if(!RT(e))return t;if(!RT(t))return e;for(let r of Object.keys(t)){let s=Object.getOwnPropertyDescriptor(t,r);if(s.hasOwnProperty(\"value\"))if(e.hasOwnProperty(r)&&RT(s.value)){let a=Object.getOwnPropertyDescriptor(e,r);RT(a.value)?e[r]=hn.merge({},e[r],t[r]):Reflect.defineProperty(e,r,s)}else Reflect.defineProperty(e,r,s);else Reflect.defineProperty(e,r,s)}return e};hn.merge=(...e)=>{let t={};for(let r of e)hn.mixin(t,r);return t};hn.mixinEmitter=(e,t)=>{let r=t.constructor.prototype;for(let s of Object.keys(r)){let a=r[s];typeof a==\"function\"?hn.define(e,s,a.bind(t)):hn.define(e,s,a)}};hn.onExit=e=>{let t=(r,s)=>{I0e||(I0e=!0,yG.forEach(a=>a()),r===!0&&process.exit(128+s))};yG.length===0&&(process.once(\"SIGTERM\",t.bind(null,!0,15)),process.once(\"SIGINT\",t.bind(null,!0,2)),process.once(\"exit\",t)),yG.push(e)};hn.define=(e,t,r)=>{Reflect.defineProperty(e,t,{value:r})};hn.defineExport=(e,t,r)=>{let s;Reflect.defineProperty(e,t,{enumerable:!0,configurable:!0,set(a){s=a},get(){return s?s():r()}})}});var w0e=G(YI=>{\"use strict\";YI.ctrl={a:\"first\",b:\"backward\",c:\"cancel\",d:\"deleteForward\",e:\"last\",f:\"forward\",g:\"reset\",i:\"tab\",k:\"cutForward\",l:\"reset\",n:\"newItem\",m:\"cancel\",j:\"submit\",p:\"search\",r:\"remove\",s:\"save\",u:\"undo\",w:\"cutLeft\",x:\"toggleCursor\",v:\"paste\"};YI.shift={up:\"shiftUp\",down:\"shiftDown\",left:\"shiftLeft\",right:\"shiftRight\",tab:\"prev\"};YI.fn={up:\"pageUp\",down:\"pageDown\",left:\"pageLeft\",right:\"pageRight\",delete:\"deleteForward\"};YI.option={b:\"backward\",f:\"forward\",d:\"cutRight\",left:\"cutLeft\",up:\"altUp\",down:\"altDown\"};YI.keys={pageup:\"pageUp\",pagedown:\"pageDown\",home:\"home\",end:\"end\",cancel:\"cancel\",delete:\"deleteForward\",backspace:\"delete\",down:\"down\",enter:\"submit\",escape:\"cancel\",left:\"left\",space:\"space\",number:\"number\",return:\"submit\",right:\"right\",tab:\"next\",up:\"up\"}});var S0e=G(($4t,v0e)=>{\"use strict\";var B0e=Ie(\"readline\"),Lit=w0e(),Mit=/^(?:\\x1b)([a-zA-Z0-9])$/,Uit=/^(?:\\x1b+)(O|N|\\[|\\[\\[)(?:(\\d+)(?:;(\\d+))?([~^$])|(?:1;)?(\\d+)?([a-zA-Z]))/,_it={OP:\"f1\",OQ:\"f2\",OR:\"f3\",OS:\"f4\",\"[11~\":\"f1\",\"[12~\":\"f2\",\"[13~\":\"f3\",\"[14~\":\"f4\",\"[[A\":\"f1\",\"[[B\":\"f2\",\"[[C\":\"f3\",\"[[D\":\"f4\",\"[[E\":\"f5\",\"[15~\":\"f5\",\"[17~\":\"f6\",\"[18~\":\"f7\",\"[19~\":\"f8\",\"[20~\":\"f9\",\"[21~\":\"f10\",\"[23~\":\"f11\",\"[24~\":\"f12\",\"[A\":\"up\",\"[B\":\"down\",\"[C\":\"right\",\"[D\":\"left\",\"[E\":\"clear\",\"[F\":\"end\",\"[H\":\"home\",OA:\"up\",OB:\"down\",OC:\"right\",OD:\"left\",OE:\"clear\",OF:\"end\",OH:\"home\",\"[1~\":\"home\",\"[2~\":\"insert\",\"[3~\":\"delete\",\"[4~\":\"end\",\"[5~\":\"pageup\",\"[6~\":\"pagedown\",\"[[5~\":\"pageup\",\"[[6~\":\"pagedown\",\"[7~\":\"home\",\"[8~\":\"end\",\"[a\":\"up\",\"[b\":\"down\",\"[c\":\"right\",\"[d\":\"left\",\"[e\":\"clear\",\"[2$\":\"insert\",\"[3$\":\"delete\",\"[5$\":\"pageup\",\"[6$\":\"pagedown\",\"[7$\":\"home\",\"[8$\":\"end\",Oa:\"up\",Ob:\"down\",Oc:\"right\",Od:\"left\",Oe:\"clear\",\"[2^\":\"insert\",\"[3^\":\"delete\",\"[5^\":\"pageup\",\"[6^\":\"pagedown\",\"[7^\":\"home\",\"[8^\":\"end\",\"[Z\":\"tab\"};function Hit(e){return[\"[a\",\"[b\",\"[c\",\"[d\",\"[e\",\"[2$\",\"[3$\",\"[5$\",\"[6$\",\"[7$\",\"[8$\",\"[Z\"].includes(e)}function jit(e){return[\"Oa\",\"Ob\",\"Oc\",\"Od\",\"Oe\",\"[2^\",\"[3^\",\"[5^\",\"[6^\",\"[7^\",\"[8^\"].includes(e)}var TT=(e=\"\",t={})=>{let r,s={name:t.name,ctrl:!1,meta:!1,shift:!1,option:!1,sequence:e,raw:e,...t};if(Buffer.isBuffer(e)?e[0]>127&&e[1]===void 0?(e[0]-=128,e=\"\\x1B\"+String(e)):e=String(e):e!==void 0&&typeof e!=\"string\"?e=String(e):e||(e=s.sequence||\"\"),s.sequence=s.sequence||e||s.name,e===\"\\r\")s.raw=void 0,s.name=\"return\";else if(e===`\n`)s.name=\"enter\";else if(e===\"\t\")s.name=\"tab\";else if(e===\"\\b\"||e===\"\\x7F\"||e===\"\\x1B\\x7F\"||e===\"\\x1B\\b\")s.name=\"backspace\",s.meta=e.charAt(0)===\"\\x1B\";else if(e===\"\\x1B\"||e===\"\\x1B\\x1B\")s.name=\"escape\",s.meta=e.length===2;else if(e===\" \"||e===\"\\x1B \")s.name=\"space\",s.meta=e.length===2;else if(e<=\"\u001a\")s.name=String.fromCharCode(e.charCodeAt(0)+97-1),s.ctrl=!0;else if(e.length===1&&e>=\"0\"&&e<=\"9\")s.name=\"number\";else if(e.length===1&&e>=\"a\"&&e<=\"z\")s.name=e;else if(e.length===1&&e>=\"A\"&&e<=\"Z\")s.name=e.toLowerCase(),s.shift=!0;else if(r=Mit.exec(e))s.meta=!0,s.shift=/^[A-Z]$/.test(r[1]);else if(r=Uit.exec(e)){let a=[...e];a[0]===\"\\x1B\"&&a[1]===\"\\x1B\"&&(s.option=!0);let n=[r[1],r[2],r[4],r[6]].filter(Boolean).join(\"\"),c=(r[3]||r[5]||1)-1;s.ctrl=!!(c&4),s.meta=!!(c&10),s.shift=!!(c&1),s.code=n,s.name=_it[n],s.shift=Hit(n)||s.shift,s.ctrl=jit(n)||s.ctrl}return s};TT.listen=(e={},t)=>{let{stdin:r}=e;if(!r||r!==process.stdin&&!r.isTTY)throw new Error(\"Invalid stream passed\");let s=B0e.createInterface({terminal:!0,input:r});B0e.emitKeypressEvents(r,s);let a=(f,p)=>t(f,TT(f,p),s),n=r.isRaw;return r.isTTY&&r.setRawMode(!0),r.on(\"keypress\",a),s.resume(),()=>{r.isTTY&&r.setRawMode(n),r.removeListener(\"keypress\",a),s.pause(),s.close()}};TT.action=(e,t,r)=>{let s={...Lit,...r};return t.ctrl?(t.action=s.ctrl[t.name],t):t.option&&s.option?(t.action=s.option[t.name],t):t.shift?(t.action=s.shift[t.name],t):(t.action=s.keys[t.name],t)};v0e.exports=TT});var b0e=G((e3t,D0e)=>{\"use strict\";D0e.exports=e=>{e.timers=e.timers||{};let t=e.options.timers;if(t)for(let r of Object.keys(t)){let s=t[r];typeof s==\"number\"&&(s={interval:s}),Git(e,r,s)}};function Git(e,t,r={}){let s=e.timers[t]={name:t,start:Date.now(),ms:0,tick:0},a=r.interval||120;s.frames=r.frames||[],s.loading=!0;let n=setInterval(()=>{s.ms=Date.now()-s.start,s.tick++,e.render()},a);return s.stop=()=>{s.loading=!1,clearInterval(n)},Reflect.defineProperty(s,\"interval\",{value:n}),e.once(\"close\",()=>s.stop()),s.stop}});var x0e=G((t3t,P0e)=>{\"use strict\";var{define:qit,width:Wit}=ra(),EG=class{constructor(t){let r=t.options;qit(this,\"_prompt\",t),this.type=t.type,this.name=t.name,this.message=\"\",this.header=\"\",this.footer=\"\",this.error=\"\",this.hint=\"\",this.input=\"\",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt=\"\",this.buffer=\"\",this.width=Wit(r.stdout||process.stdout),Object.assign(this,r),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=t.symbols,this.styles=t.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let t={...this};return t.status=this.status,t.buffer=Buffer.from(t.buffer),delete t.clone,t}set color(t){this._color=t}get color(){let t=this.prompt.styles;if(this.cancelled)return t.cancelled;if(this.submitted)return t.submitted;let r=this._color||t[this.status];return typeof r==\"function\"?r:t.pending}set loading(t){this._loading=t}get loading(){return typeof this._loading==\"boolean\"?this._loading:this.loadingChoices?\"choices\":!1}get status(){return this.cancelled?\"cancelled\":this.submitted?\"submitted\":\"pending\"}};P0e.exports=EG});var Q0e=G((r3t,k0e)=>{\"use strict\";var IG=ra(),Io=zu(),CG={default:Io.noop,noop:Io.noop,set inverse(e){this._inverse=e},get inverse(){return this._inverse||IG.inverse(this.primary)},set complement(e){this._complement=e},get complement(){return this._complement||IG.complement(this.primary)},primary:Io.cyan,success:Io.green,danger:Io.magenta,strong:Io.bold,warning:Io.yellow,muted:Io.dim,disabled:Io.gray,dark:Io.dim.gray,underline:Io.underline,set info(e){this._info=e},get info(){return this._info||this.primary},set em(e){this._em=e},get em(){return this._em||this.primary.underline},set heading(e){this._heading=e},get heading(){return this._heading||this.muted.underline},set pending(e){this._pending=e},get pending(){return this._pending||this.primary},set submitted(e){this._submitted=e},get submitted(){return this._submitted||this.success},set cancelled(e){this._cancelled=e},get cancelled(){return this._cancelled||this.danger},set typing(e){this._typing=e},get typing(){return this._typing||this.dim},set placeholder(e){this._placeholder=e},get placeholder(){return this._placeholder||this.primary.dim},set highlight(e){this._highlight=e},get highlight(){return this._highlight||this.inverse}};CG.merge=(e={})=>{e.styles&&typeof e.styles.enabled==\"boolean\"&&(Io.enabled=e.styles.enabled),e.styles&&typeof e.styles.visible==\"boolean\"&&(Io.visible=e.styles.visible);let t=IG.merge({},CG,e.styles);delete t.merge;for(let r of Object.keys(Io))t.hasOwnProperty(r)||Reflect.defineProperty(t,r,{get:()=>Io[r]});for(let r of Object.keys(Io.styles))t.hasOwnProperty(r)||Reflect.defineProperty(t,r,{get:()=>Io[r]});return t};k0e.exports=CG});var T0e=G((n3t,R0e)=>{\"use strict\";var wG=process.platform===\"win32\",Kp=zu(),Vit=ra(),BG={...Kp.symbols,upDownDoubleArrow:\"\\u21D5\",upDownDoubleArrow2:\"\\u2B0D\",upDownArrow:\"\\u2195\",asterisk:\"*\",asterism:\"\\u2042\",bulletWhite:\"\\u25E6\",electricArrow:\"\\u2301\",ellipsisLarge:\"\\u22EF\",ellipsisSmall:\"\\u2026\",fullBlock:\"\\u2588\",identicalTo:\"\\u2261\",indicator:Kp.symbols.check,leftAngle:\"\\u2039\",mark:\"\\u203B\",minus:\"\\u2212\",multiplication:\"\\xD7\",obelus:\"\\xF7\",percent:\"%\",pilcrow:\"\\xB6\",pilcrow2:\"\\u2761\",pencilUpRight:\"\\u2710\",pencilDownRight:\"\\u270E\",pencilRight:\"\\u270F\",plus:\"+\",plusMinus:\"\\xB1\",pointRight:\"\\u261E\",rightAngle:\"\\u203A\",section:\"\\xA7\",hexagon:{off:\"\\u2B21\",on:\"\\u2B22\",disabled:\"\\u2B22\"},ballot:{on:\"\\u2611\",off:\"\\u2610\",disabled:\"\\u2612\"},stars:{on:\"\\u2605\",off:\"\\u2606\",disabled:\"\\u2606\"},folder:{on:\"\\u25BC\",off:\"\\u25B6\",disabled:\"\\u25B6\"},prefix:{pending:Kp.symbols.question,submitted:Kp.symbols.check,cancelled:Kp.symbols.cross},separator:{pending:Kp.symbols.pointerSmall,submitted:Kp.symbols.middot,cancelled:Kp.symbols.middot},radio:{off:wG?\"( )\":\"\\u25EF\",on:wG?\"(*)\":\"\\u25C9\",disabled:wG?\"(|)\":\"\\u24BE\"},numbers:[\"\\u24EA\",\"\\u2460\",\"\\u2461\",\"\\u2462\",\"\\u2463\",\"\\u2464\",\"\\u2465\",\"\\u2466\",\"\\u2467\",\"\\u2468\",\"\\u2469\",\"\\u246A\",\"\\u246B\",\"\\u246C\",\"\\u246D\",\"\\u246E\",\"\\u246F\",\"\\u2470\",\"\\u2471\",\"\\u2472\",\"\\u2473\",\"\\u3251\",\"\\u3252\",\"\\u3253\",\"\\u3254\",\"\\u3255\",\"\\u3256\",\"\\u3257\",\"\\u3258\",\"\\u3259\",\"\\u325A\",\"\\u325B\",\"\\u325C\",\"\\u325D\",\"\\u325E\",\"\\u325F\",\"\\u32B1\",\"\\u32B2\",\"\\u32B3\",\"\\u32B4\",\"\\u32B5\",\"\\u32B6\",\"\\u32B7\",\"\\u32B8\",\"\\u32B9\",\"\\u32BA\",\"\\u32BB\",\"\\u32BC\",\"\\u32BD\",\"\\u32BE\",\"\\u32BF\"]};BG.merge=e=>{let t=Vit.merge({},Kp.symbols,BG,e.symbols);return delete t.merge,t};R0e.exports=BG});var N0e=G((i3t,F0e)=>{\"use strict\";var Yit=Q0e(),Kit=T0e(),Jit=ra();F0e.exports=e=>{e.options=Jit.merge({},e.options.theme,e.options),e.symbols=Kit.merge(e.options),e.styles=Yit.merge(e.options)}});var _0e=G((M0e,U0e)=>{\"use strict\";var O0e=process.env.TERM_PROGRAM===\"Apple_Terminal\",zit=zu(),vG=ra(),Zu=U0e.exports=M0e,_i=\"\\x1B[\",L0e=\"\\x07\",SG=!1,_0=Zu.code={bell:L0e,beep:L0e,beginning:`${_i}G`,down:`${_i}J`,esc:_i,getPosition:`${_i}6n`,hide:`${_i}?25l`,line:`${_i}2K`,lineEnd:`${_i}K`,lineStart:`${_i}1K`,restorePosition:_i+(O0e?\"8\":\"u\"),savePosition:_i+(O0e?\"7\":\"s\"),screen:`${_i}2J`,show:`${_i}?25h`,up:`${_i}1J`},Sm=Zu.cursor={get hidden(){return SG},hide(){return SG=!0,_0.hide},show(){return SG=!1,_0.show},forward:(e=1)=>`${_i}${e}C`,backward:(e=1)=>`${_i}${e}D`,nextLine:(e=1)=>`${_i}E`.repeat(e),prevLine:(e=1)=>`${_i}F`.repeat(e),up:(e=1)=>e?`${_i}${e}A`:\"\",down:(e=1)=>e?`${_i}${e}B`:\"\",right:(e=1)=>e?`${_i}${e}C`:\"\",left:(e=1)=>e?`${_i}${e}D`:\"\",to(e,t){return t?`${_i}${t+1};${e+1}H`:`${_i}${e+1}G`},move(e=0,t=0){let r=\"\";return r+=e<0?Sm.left(-e):e>0?Sm.right(e):\"\",r+=t<0?Sm.up(-t):t>0?Sm.down(t):\"\",r},restore(e={}){let{after:t,cursor:r,initial:s,input:a,prompt:n,size:c,value:f}=e;if(s=vG.isPrimitive(s)?String(s):\"\",a=vG.isPrimitive(a)?String(a):\"\",f=vG.isPrimitive(f)?String(f):\"\",c){let p=Zu.cursor.up(c)+Zu.cursor.to(n.length),h=a.length-r;return h>0&&(p+=Zu.cursor.left(h)),p}if(f||t){let p=!a&&s?-s.length:-a.length+r;return t&&(p-=t.length),a===\"\"&&s&&!n.includes(s)&&(p+=s.length),Zu.cursor.move(p)}}},DG=Zu.erase={screen:_0.screen,up:_0.up,down:_0.down,line:_0.line,lineEnd:_0.lineEnd,lineStart:_0.lineStart,lines(e){let t=\"\";for(let r=0;r<e;r++)t+=Zu.erase.line+(r<e-1?Zu.cursor.up(1):\"\");return e&&(t+=Zu.code.beginning),t}};Zu.clear=(e=\"\",t=process.stdout.columns)=>{if(!t)return DG.line+Sm.to(0);let r=n=>[...zit.unstyle(n)].length,s=e.split(/\\r?\\n/),a=0;for(let n of s)a+=1+Math.floor(Math.max(r(n)-1,0)/t);return(DG.line+Sm.prevLine()).repeat(a-1)+DG.line+Sm.to(0)}});var KI=G((s3t,j0e)=>{\"use strict\";var Zit=Ie(\"events\"),H0e=zu(),bG=S0e(),Xit=b0e(),$it=x0e(),est=N0e(),El=ra(),Dm=_0e(),PG=class e extends Zit{constructor(t={}){super(),this.name=t.name,this.type=t.type,this.options=t,est(this),Xit(this),this.state=new $it(this),this.initial=[t.initial,t.default].find(r=>r!=null),this.stdout=t.stdout||process.stdout,this.stdin=t.stdin||process.stdin,this.scale=t.scale||1,this.term=this.options.term||process.env.TERM_PROGRAM,this.margin=rst(this.options.margin),this.setMaxListeners(0),tst(this)}async keypress(t,r={}){this.keypressed=!0;let s=bG.action(t,bG(t,r),this.options.actions);this.state.keypress=s,this.emit(\"keypress\",t,s),this.emit(\"state\",this.state.clone());let a=this.options[s.action]||this[s.action]||this.dispatch;if(typeof a==\"function\")return await a.call(this,t,s);this.alert()}alert(){delete this.state.alert,this.options.show===!1?this.emit(\"alert\"):this.stdout.write(Dm.code.beep)}cursorHide(){this.stdout.write(Dm.cursor.hide()),El.onExit(()=>this.cursorShow())}cursorShow(){this.stdout.write(Dm.cursor.show())}write(t){t&&(this.stdout&&this.state.show!==!1&&this.stdout.write(t),this.state.buffer+=t)}clear(t=0){let r=this.state.buffer;this.state.buffer=\"\",!(!r&&!t||this.options.show===!1)&&this.stdout.write(Dm.cursor.down(t)+Dm.clear(r,this.width))}restore(){if(this.state.closed||this.options.show===!1)return;let{prompt:t,after:r,rest:s}=this.sections(),{cursor:a,initial:n=\"\",input:c=\"\",value:f=\"\"}=this,p=this.state.size=s.length,h={after:r,cursor:a,initial:n,input:c,prompt:t,size:p,value:f},E=Dm.cursor.restore(h);E&&this.stdout.write(E)}sections(){let{buffer:t,input:r,prompt:s}=this.state;s=H0e.unstyle(s);let a=H0e.unstyle(t),n=a.indexOf(s),c=a.slice(0,n),p=a.slice(n).split(`\n`),h=p[0],E=p[p.length-1],S=(s+(r?\" \"+r:\"\")).length,x=S<h.length?h.slice(S+1):\"\";return{header:c,prompt:h,after:x,rest:p.slice(1),last:E}}async submit(){this.state.submitted=!0,this.state.validating=!0,this.options.onSubmit&&await this.options.onSubmit.call(this,this.name,this.value,this);let t=this.state.error||await this.validate(this.value,this.state);if(t!==!0){let r=`\n`+this.symbols.pointer+\" \";typeof t==\"string\"?r+=t.trim():r+=\"Invalid input\",this.state.error=`\n`+this.styles.danger(r),this.state.submitted=!1,await this.render(),await this.alert(),this.state.validating=!1,this.state.error=void 0;return}this.state.validating=!1,await this.render(),await this.close(),this.value=await this.result(this.value),this.emit(\"submit\",this.value)}async cancel(t){this.state.cancelled=this.state.submitted=!0,await this.render(),await this.close(),typeof this.options.onCancel==\"function\"&&await this.options.onCancel.call(this,this.name,this.value,this),this.emit(\"cancel\",await this.error(t))}async close(){this.state.closed=!0;try{let t=this.sections(),r=Math.ceil(t.prompt.length/this.width);t.rest&&this.write(Dm.cursor.down(t.rest.length)),this.write(`\n`.repeat(r))}catch{}this.emit(\"close\")}start(){!this.stop&&this.options.show!==!1&&(this.stop=bG.listen(this,this.keypress.bind(this)),this.once(\"close\",this.stop))}async skip(){return this.skipped=this.options.skip===!0,typeof this.options.skip==\"function\"&&(this.skipped=await this.options.skip.call(this,this.name,this.value)),this.skipped}async initialize(){let{format:t,options:r,result:s}=this;if(this.format=()=>t.call(this,this.value),this.result=()=>s.call(this,this.value),typeof r.initial==\"function\"&&(this.initial=await r.initial.call(this,this)),typeof r.onRun==\"function\"&&await r.onRun.call(this,this),typeof r.onSubmit==\"function\"){let a=r.onSubmit.bind(this),n=this.submit.bind(this);delete this.options.onSubmit,this.submit=async()=>(await a(this.name,this.value,this),n())}await this.start(),await this.render()}render(){throw new Error(\"expected prompt to have a custom render method\")}run(){return new Promise(async(t,r)=>{if(this.once(\"submit\",t),this.once(\"cancel\",r),await this.skip())return this.render=()=>{},this.submit();await this.initialize(),this.emit(\"run\")})}async element(t,r,s){let{options:a,state:n,symbols:c,timers:f}=this,p=f&&f[t];n.timer=p;let h=a[t]||n[t]||c[t],E=r&&r[t]!=null?r[t]:await h;if(E===\"\")return E;let C=await this.resolve(E,n,r,s);return!C&&r&&r[t]?this.resolve(h,n,r,s):C}async prefix(){let t=await this.element(\"prefix\")||this.symbols,r=this.timers&&this.timers.prefix,s=this.state;return s.timer=r,El.isObject(t)&&(t=t[s.status]||t.pending),El.hasColor(t)?t:(this.styles[s.status]||this.styles.pending)(t)}async message(){let t=await this.element(\"message\");return El.hasColor(t)?t:this.styles.strong(t)}async separator(){let t=await this.element(\"separator\")||this.symbols,r=this.timers&&this.timers.separator,s=this.state;s.timer=r;let a=t[s.status]||t.pending||s.separator,n=await this.resolve(a,s);return El.isObject(n)&&(n=n[s.status]||n.pending),El.hasColor(n)?n:this.styles.muted(n)}async pointer(t,r){let s=await this.element(\"pointer\",t,r);if(typeof s==\"string\"&&El.hasColor(s))return s;if(s){let a=this.styles,n=this.index===r,c=n?a.primary:h=>h,f=await this.resolve(s[n?\"on\":\"off\"]||s,this.state),p=El.hasColor(f)?f:c(f);return n?p:\" \".repeat(f.length)}}async indicator(t,r){let s=await this.element(\"indicator\",t,r);if(typeof s==\"string\"&&El.hasColor(s))return s;if(s){let a=this.styles,n=t.enabled===!0,c=n?a.success:a.dark,f=s[n?\"on\":\"off\"]||s;return El.hasColor(f)?f:c(f)}return\"\"}body(){return null}footer(){if(this.state.status===\"pending\")return this.element(\"footer\")}header(){if(this.state.status===\"pending\")return this.element(\"header\")}async hint(){if(this.state.status===\"pending\"&&!this.isValue(this.state.input)){let t=await this.element(\"hint\");return El.hasColor(t)?t:this.styles.muted(t)}}error(t){return this.state.submitted?\"\":t||this.state.error}format(t){return t}result(t){return t}validate(t){return this.options.required===!0?this.isValue(t):!0}isValue(t){return t!=null&&t!==\"\"}resolve(t,...r){return El.resolve(this,t,...r)}get base(){return e.prototype}get style(){return this.styles[this.state.status]}get height(){return this.options.rows||El.height(this.stdout,25)}get width(){return this.options.columns||El.width(this.stdout,80)}get size(){return{width:this.width,height:this.height}}set cursor(t){this.state.cursor=t}get cursor(){return this.state.cursor}set input(t){this.state.input=t}get input(){return this.state.input}set value(t){this.state.value=t}get value(){let{input:t,value:r}=this.state,s=[r,t].find(this.isValue.bind(this));return this.isValue(s)?s:this.initial}static get prompt(){return t=>new this(t).run()}};function tst(e){let t=a=>e[a]===void 0||typeof e[a]==\"function\",r=[\"actions\",\"choices\",\"initial\",\"margin\",\"roles\",\"styles\",\"symbols\",\"theme\",\"timers\",\"value\"],s=[\"body\",\"footer\",\"error\",\"header\",\"hint\",\"indicator\",\"message\",\"prefix\",\"separator\",\"skip\"];for(let a of Object.keys(e.options)){if(r.includes(a)||/^on[A-Z]/.test(a))continue;let n=e.options[a];typeof n==\"function\"&&t(a)?s.includes(a)||(e[a]=n.bind(e)):typeof e[a]!=\"function\"&&(e[a]=n)}}function rst(e){typeof e==\"number\"&&(e=[e,e,e,e]);let t=[].concat(e||[]),r=a=>a%2===0?`\n`:\" \",s=[];for(let a=0;a<4;a++){let n=r(a);t[a]?s.push(n.repeat(t[a])):s.push(\"\")}return s}j0e.exports=PG});var W0e=G((o3t,q0e)=>{\"use strict\";var nst=ra(),G0e={default(e,t){return t},checkbox(e,t){throw new Error(\"checkbox role is not implemented yet\")},editable(e,t){throw new Error(\"editable role is not implemented yet\")},expandable(e,t){throw new Error(\"expandable role is not implemented yet\")},heading(e,t){return t.disabled=\"\",t.indicator=[t.indicator,\" \"].find(r=>r!=null),t.message=t.message||\"\",t},input(e,t){throw new Error(\"input role is not implemented yet\")},option(e,t){return G0e.default(e,t)},radio(e,t){throw new Error(\"radio role is not implemented yet\")},separator(e,t){return t.disabled=\"\",t.indicator=[t.indicator,\" \"].find(r=>r!=null),t.message=t.message||e.symbols.line.repeat(5),t},spacer(e,t){return t}};q0e.exports=(e,t={})=>{let r=nst.merge({},G0e,t.roles);return r[e]||r.default}});var Wv=G((a3t,K0e)=>{\"use strict\";var ist=zu(),sst=KI(),ost=W0e(),FT=ra(),{reorder:xG,scrollUp:ast,scrollDown:lst,isObject:V0e,swap:cst}=FT,kG=class extends sst{constructor(t){super(t),this.cursorHide(),this.maxSelected=t.maxSelected||1/0,this.multiple=t.multiple||!1,this.initial=t.initial||0,this.delay=t.delay||0,this.longest=0,this.num=\"\"}async initialize(){typeof this.options.initial==\"function\"&&(this.initial=await this.options.initial.call(this)),await this.reset(!0),await super.initialize()}async reset(){let{choices:t,initial:r,autofocus:s,suggest:a}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(t)),this.choices.forEach(n=>n.enabled=!1),typeof a!=\"function\"&&this.selectable.length===0)throw new Error(\"At least one choice must be selectable\");V0e(r)&&(r=Object.keys(r)),Array.isArray(r)?(s!=null&&(this.index=this.findIndex(s)),r.forEach(n=>this.enable(this.find(n))),await this.render()):(s!=null&&(r=s),typeof r==\"string\"&&(r=this.findIndex(r)),typeof r==\"number\"&&r>-1&&(this.index=Math.max(0,Math.min(r,this.choices.length)),this.enable(this.find(this.index)))),this.isDisabled(this.focused)&&await this.down()}async toChoices(t,r){this.state.loadingChoices=!0;let s=[],a=0,n=async(c,f)=>{typeof c==\"function\"&&(c=await c.call(this)),c instanceof Promise&&(c=await c);for(let p=0;p<c.length;p++){let h=c[p]=await this.toChoice(c[p],a++,f);s.push(h),h.choices&&await n(h.choices,h)}return s};return n(t,r).then(c=>(this.state.loadingChoices=!1,c))}async toChoice(t,r,s){if(typeof t==\"function\"&&(t=await t.call(this,this)),t instanceof Promise&&(t=await t),typeof t==\"string\"&&(t={name:t}),t.normalized)return t;t.normalized=!0;let a=t.value;if(t=ost(t.role,this.options)(this,t),typeof t.disabled==\"string\"&&!t.hint&&(t.hint=t.disabled,t.disabled=!0),t.disabled===!0&&t.hint==null&&(t.hint=\"(disabled)\"),t.index!=null)return t;t.name=t.name||t.key||t.title||t.value||t.message,t.message=t.message||t.name||\"\",t.value=[t.value,t.name].find(this.isValue.bind(this)),t.input=\"\",t.index=r,t.cursor=0,FT.define(t,\"parent\",s),t.level=s?s.level+1:1,t.indent==null&&(t.indent=s?s.indent+\"  \":t.indent||\"\"),t.path=s?s.path+\".\"+t.name:t.name,t.enabled=!!(this.multiple&&!this.isDisabled(t)&&(t.enabled||this.isSelected(t))),this.isDisabled(t)||(this.longest=Math.max(this.longest,ist.unstyle(t.message).length));let c={...t};return t.reset=(f=c.input,p=c.value)=>{for(let h of Object.keys(c))t[h]=c[h];t.input=f,t.value=p},a==null&&typeof t.initial==\"function\"&&(t.input=await t.initial.call(this,this.state,t,r)),t}async onChoice(t,r){this.emit(\"choice\",t,r,this),typeof t.onChoice==\"function\"&&await t.onChoice.call(this,this.state,t,r)}async addChoice(t,r,s){let a=await this.toChoice(t,r,s);return this.choices.push(a),this.index=this.choices.length-1,this.limit=this.choices.length,a}async newItem(t,r,s){let a={name:\"New choice name?\",editable:!0,newChoice:!0,...t},n=await this.addChoice(a,r,s);return n.updateChoice=()=>{delete n.newChoice,n.name=n.message=n.input,n.input=\"\",n.cursor=0},this.render()}indent(t){return t.indent==null?t.level>1?\"  \".repeat(t.level-1):\"\":t.indent}dispatch(t,r){if(this.multiple&&this[r.name])return this[r.name]();this.alert()}focus(t,r){return typeof r!=\"boolean\"&&(r=t.enabled),r&&!t.enabled&&this.selected.length>=this.maxSelected?this.alert():(this.index=t.index,t.enabled=r&&!this.isDisabled(t),t)}space(){return this.multiple?(this.toggle(this.focused),this.render()):this.alert()}a(){if(this.maxSelected<this.choices.length)return this.alert();let t=this.selectable.every(r=>r.enabled);return this.choices.forEach(r=>r.enabled=!t),this.render()}i(){return this.choices.length-this.selected.length>this.maxSelected?this.alert():(this.choices.forEach(t=>t.enabled=!t.enabled),this.render())}g(t=this.focused){return this.choices.some(r=>!!r.parent)?(this.toggle(t.parent&&!t.choices?t.parent:t),this.render()):this.a()}toggle(t,r){if(!t.enabled&&this.selected.length>=this.maxSelected)return this.alert();typeof r!=\"boolean\"&&(r=!t.enabled),t.enabled=r,t.choices&&t.choices.forEach(a=>this.toggle(a,r));let s=t.parent;for(;s;){let a=s.choices.filter(n=>this.isDisabled(n));s.enabled=a.every(n=>n.enabled===!0),s=s.parent}return Y0e(this,this.choices),this.emit(\"toggle\",t,this),t}enable(t){return this.selected.length>=this.maxSelected?this.alert():(t.enabled=!this.isDisabled(t),t.choices&&t.choices.forEach(this.enable.bind(this)),t)}disable(t){return t.enabled=!1,t.choices&&t.choices.forEach(this.disable.bind(this)),t}number(t){this.num+=t;let r=s=>{let a=Number(s);if(a>this.choices.length-1)return this.alert();let n=this.focused,c=this.choices.find(f=>a===f.index);if(!c.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(this.visible.indexOf(c)===-1){let f=xG(this.choices),p=f.indexOf(c);if(n.index>p){let h=f.slice(p,p+this.limit),E=f.filter(C=>!h.includes(C));this.choices=h.concat(E)}else{let h=p-this.limit+1;this.choices=f.slice(h).concat(f.slice(0,h))}}return this.index=this.choices.indexOf(c),this.toggle(this.focused),this.render()};return clearTimeout(this.numberTimeout),new Promise(s=>{let a=this.choices.length,n=this.num,c=(f=!1,p)=>{clearTimeout(this.numberTimeout),f&&(p=r(n)),this.num=\"\",s(p)};if(n===\"0\"||n.length===1&&+(n+\"0\")>a)return c(!0);if(Number(n)>a)return c(!1,this.alert());this.numberTimeout=setTimeout(()=>c(!0),this.delay)})}home(){return this.choices=xG(this.choices),this.index=0,this.render()}end(){let t=this.choices.length-this.limit,r=xG(this.choices);return this.choices=r.slice(t).concat(r.slice(0,t)),this.index=this.limit-1,this.render()}first(){return this.index=0,this.render()}last(){return this.index=this.visible.length-1,this.render()}prev(){return this.visible.length<=1?this.alert():this.up()}next(){return this.visible.length<=1?this.alert():this.down()}right(){return this.cursor>=this.input.length?this.alert():(this.cursor++,this.render())}left(){return this.cursor<=0?this.alert():(this.cursor--,this.render())}up(){let t=this.choices.length,r=this.visible.length,s=this.index;return this.options.scroll===!1&&s===0?this.alert():t>r&&s===0?this.scrollUp():(this.index=(s-1%t+t)%t,this.isDisabled()?this.up():this.render())}down(){let t=this.choices.length,r=this.visible.length,s=this.index;return this.options.scroll===!1&&s===r-1?this.alert():t>r&&s===r-1?this.scrollDown():(this.index=(s+1)%t,this.isDisabled()?this.down():this.render())}scrollUp(t=0){return this.choices=ast(this.choices),this.index=t,this.isDisabled()?this.up():this.render()}scrollDown(t=this.visible.length-1){return this.choices=lst(this.choices),this.index=t,this.isDisabled()?this.down():this.render()}async shiftUp(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index-1),await this.up(),this.sorting=!1;return}return this.scrollUp(this.index)}async shiftDown(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index+1),await this.down(),this.sorting=!1;return}return this.scrollDown(this.index)}pageUp(){return this.visible.length<=1?this.alert():(this.limit=Math.max(this.limit-1,0),this.index=Math.min(this.limit-1,this.index),this._limit=this.limit,this.isDisabled()?this.up():this.render())}pageDown(){return this.visible.length>=this.choices.length?this.alert():(this.index=Math.max(0,this.index),this.limit=Math.min(this.limit+1,this.choices.length),this._limit=this.limit,this.isDisabled()?this.down():this.render())}swap(t){cst(this.choices,this.index,t)}isDisabled(t=this.focused){return t&&[\"disabled\",\"collapsed\",\"hidden\",\"completing\",\"readonly\"].some(s=>t[s]===!0)?!0:t&&t.role===\"heading\"}isEnabled(t=this.focused){if(Array.isArray(t))return t.every(r=>this.isEnabled(r));if(t.choices){let r=t.choices.filter(s=>!this.isDisabled(s));return t.enabled&&r.every(s=>this.isEnabled(s))}return t.enabled&&!this.isDisabled(t)}isChoice(t,r){return t.name===r||t.index===Number(r)}isSelected(t){return Array.isArray(this.initial)?this.initial.some(r=>this.isChoice(t,r)):this.isChoice(t,this.initial)}map(t=[],r=\"value\"){return[].concat(t||[]).reduce((s,a)=>(s[a]=this.find(a,r),s),{})}filter(t,r){let a=typeof t==\"function\"?t:(f,p)=>[f.name,p].includes(t),c=(this.options.multiple?this.state._choices:this.choices).filter(a);return r?c.map(f=>f[r]):c}find(t,r){if(V0e(t))return r?t[r]:t;let a=typeof t==\"function\"?t:(c,f)=>[c.name,f].includes(t),n=this.choices.find(a);if(n)return r?n[r]:n}findIndex(t){return this.choices.indexOf(this.find(t))}async submit(){let t=this.focused;if(!t)return this.alert();if(t.newChoice)return t.input?(t.updateChoice(),this.render()):this.alert();if(this.choices.some(c=>c.newChoice))return this.alert();let{reorder:r,sort:s}=this.options,a=this.multiple===!0,n=this.selected;return n===void 0?this.alert():(Array.isArray(n)&&r!==!1&&s!==!0&&(n=FT.reorder(n)),this.value=a?n.map(c=>c.name):n.name,super.submit())}set choices(t=[]){this.state._choices=this.state._choices||[],this.state.choices=t;for(let r of t)this.state._choices.some(s=>s.name===r.name)||this.state._choices.push(r);if(!this._initial&&this.options.initial){this._initial=!0;let r=this.initial;if(typeof r==\"string\"||typeof r==\"number\"){let s=this.find(r);s&&(this.initial=s.index,this.focus(s,!0))}}}get choices(){return Y0e(this,this.state.choices||[])}set visible(t){this.state.visible=t}get visible(){return(this.state.visible||this.choices).slice(0,this.limit)}set limit(t){this.state.limit=t}get limit(){let{state:t,options:r,choices:s}=this,a=t.limit||this._limit||r.limit||s.length;return Math.min(a,this.height)}set value(t){super.value=t}get value(){return typeof super.value!=\"string\"&&super.value===this.initial?this.input:super.value}set index(t){this.state.index=t}get index(){return Math.max(0,this.state?this.state.index:0)}get enabled(){return this.filter(this.isEnabled.bind(this))}get focused(){let t=this.choices[this.index];return t&&this.state.submitted&&this.multiple!==!0&&(t.enabled=!0),t}get selectable(){return this.choices.filter(t=>!this.isDisabled(t))}get selected(){return this.multiple?this.enabled:this.focused}};function Y0e(e,t){if(t instanceof Promise)return t;if(typeof t==\"function\"){if(FT.isAsyncFn(t))return t;t=t.call(e,e)}for(let r of t){if(Array.isArray(r.choices)){let s=r.choices.filter(a=>!e.isDisabled(a));r.enabled=s.every(a=>a.enabled===!0)}e.isDisabled(r)===!0&&delete r.enabled}return t}K0e.exports=kG});var H0=G((l3t,J0e)=>{\"use strict\";var ust=Wv(),QG=ra(),RG=class extends ust{constructor(t){super(t),this.emptyError=this.options.emptyError||\"No items were selected\"}async dispatch(t,r){if(this.multiple)return this[r.name]?await this[r.name](t,r):await super.dispatch(t,r);this.alert()}separator(){if(this.options.separator)return super.separator();let t=this.styles.muted(this.symbols.ellipsis);return this.state.submitted?super.separator():t}pointer(t,r){return!this.multiple||this.options.pointer?super.pointer(t,r):\"\"}indicator(t,r){return this.multiple?super.indicator(t,r):\"\"}choiceMessage(t,r){let s=this.resolve(t.message,this.state,t,r);return t.role===\"heading\"&&!QG.hasColor(s)&&(s=this.styles.strong(s)),this.resolve(s,this.state,t,r)}choiceSeparator(){return\":\"}async renderChoice(t,r){await this.onChoice(t,r);let s=this.index===r,a=await this.pointer(t,r),n=await this.indicator(t,r)+(t.pad||\"\"),c=await this.resolve(t.hint,this.state,t,r);c&&!QG.hasColor(c)&&(c=this.styles.muted(c));let f=this.indent(t),p=await this.choiceMessage(t,r),h=()=>[this.margin[3],f+a+n,p,this.margin[1],c].filter(Boolean).join(\" \");return t.role===\"heading\"?h():t.disabled?(QG.hasColor(p)||(p=this.styles.disabled(p)),h()):(s&&(p=this.styles.em(p)),h())}async renderChoices(){if(this.state.loading===\"choices\")return this.styles.warning(\"Loading choices\");if(this.state.submitted)return\"\";let t=this.visible.map(async(n,c)=>await this.renderChoice(n,c)),r=await Promise.all(t);r.length||r.push(this.styles.danger(\"No matching choices\"));let s=this.margin[0]+r.join(`\n`),a;return this.options.choicesHeader&&(a=await this.resolve(this.options.choicesHeader,this.state)),[a,s].filter(Boolean).join(`\n`)}format(){return!this.state.submitted||this.state.cancelled?\"\":Array.isArray(this.selected)?this.selected.map(t=>this.styles.primary(t.name)).join(\", \"):this.styles.primary(this.selected.name)}async render(){let{submitted:t,size:r}=this.state,s=\"\",a=await this.header(),n=await this.prefix(),c=await this.separator(),f=await this.message();this.options.promptLine!==!1&&(s=[n,f,c,\"\"].join(\" \"),this.state.prompt=s);let p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),C=await this.footer();p&&(s+=p),h&&!s.includes(h)&&(s+=\" \"+h),t&&!p&&!E.trim()&&this.multiple&&this.emptyError!=null&&(s+=this.styles.danger(this.emptyError)),this.clear(r),this.write([a,s,E,C].filter(Boolean).join(`\n`)),this.write(this.margin[2]),this.restore()}};J0e.exports=RG});var Z0e=G((c3t,z0e)=>{\"use strict\";var fst=H0(),Ast=(e,t)=>{let r=e.toLowerCase();return s=>{let n=s.toLowerCase().indexOf(r),c=t(s.slice(n,n+r.length));return n>=0?s.slice(0,n)+c+s.slice(n+r.length):s}},TG=class extends fst{constructor(t){super(t),this.cursorShow()}moveCursor(t){this.state.cursor+=t}dispatch(t){return this.append(t)}space(t){return this.options.multiple?super.space(t):this.append(t)}append(t){let{cursor:r,input:s}=this.state;return this.input=s.slice(0,r)+t+s.slice(r),this.moveCursor(1),this.complete()}delete(){let{cursor:t,input:r}=this.state;return r?(this.input=r.slice(0,t-1)+r.slice(t),this.moveCursor(-1),this.complete()):this.alert()}deleteForward(){let{cursor:t,input:r}=this.state;return r[t]===void 0?this.alert():(this.input=`${r}`.slice(0,t)+`${r}`.slice(t+1),this.complete())}number(t){return this.append(t)}async complete(){this.completing=!0,this.choices=await this.suggest(this.input,this.state._choices),this.state.limit=void 0,this.index=Math.min(Math.max(this.visible.length-1,0),this.index),await this.render(),this.completing=!1}suggest(t=this.input,r=this.state._choices){if(typeof this.options.suggest==\"function\")return this.options.suggest.call(this,t,r);let s=t.toLowerCase();return r.filter(a=>a.message.toLowerCase().includes(s))}pointer(){return\"\"}format(){if(!this.focused)return this.input;if(this.options.multiple&&this.state.submitted)return this.selected.map(t=>this.styles.primary(t.message)).join(\", \");if(this.state.submitted){let t=this.value=this.input=this.focused.value;return this.styles.primary(t)}return this.input}async render(){if(this.state.status!==\"pending\")return super.render();let t=this.options.highlight?this.options.highlight.bind(this):this.styles.placeholder,r=Ast(this.input,t),s=this.choices;this.choices=s.map(a=>({...a,message:r(a.message)})),await super.render(),this.choices=s}submit(){return this.options.multiple&&(this.value=this.selected.map(t=>t.name)),super.submit()}};z0e.exports=TG});var NG=G((u3t,X0e)=>{\"use strict\";var FG=ra();X0e.exports=(e,t={})=>{e.cursorHide();let{input:r=\"\",initial:s=\"\",pos:a,showCursor:n=!0,color:c}=t,f=c||e.styles.placeholder,p=FG.inverse(e.styles.primary),h=T=>p(e.styles.black(T)),E=r,C=\" \",S=h(C);if(e.blink&&e.blink.off===!0&&(h=T=>T,S=\"\"),n&&a===0&&s===\"\"&&r===\"\")return h(C);if(n&&a===0&&(r===s||r===\"\"))return h(s[0])+f(s.slice(1));s=FG.isPrimitive(s)?`${s}`:\"\",r=FG.isPrimitive(r)?`${r}`:\"\";let x=s&&s.startsWith(r)&&s!==r,I=x?h(s[r.length]):S;if(a!==r.length&&n===!0&&(E=r.slice(0,a)+h(r[a])+r.slice(a+1),I=\"\"),n===!1&&(I=\"\"),x){let T=e.styles.unstyle(E+I);return E+I+f(s.slice(T.length))}return E+I}});var NT=G((f3t,$0e)=>{\"use strict\";var pst=zu(),hst=H0(),gst=NG(),OG=class extends hst{constructor(t){super({...t,multiple:!0}),this.type=\"form\",this.initial=this.options.initial,this.align=[this.options.align,\"right\"].find(r=>r!=null),this.emptyError=\"\",this.values={}}async reset(t){return await super.reset(),t===!0&&(this._index=this.index),this.index=this._index,this.values={},this.choices.forEach(r=>r.reset&&r.reset()),this.render()}dispatch(t){return!!t&&this.append(t)}append(t){let r=this.focused;if(!r)return this.alert();let{cursor:s,input:a}=r;return r.value=r.input=a.slice(0,s)+t+a.slice(s),r.cursor++,this.render()}delete(){let t=this.focused;if(!t||t.cursor<=0)return this.alert();let{cursor:r,input:s}=t;return t.value=t.input=s.slice(0,r-1)+s.slice(r),t.cursor--,this.render()}deleteForward(){let t=this.focused;if(!t)return this.alert();let{cursor:r,input:s}=t;if(s[r]===void 0)return this.alert();let a=`${s}`.slice(0,r)+`${s}`.slice(r+1);return t.value=t.input=a,this.render()}right(){let t=this.focused;return t?t.cursor>=t.input.length?this.alert():(t.cursor++,this.render()):this.alert()}left(){let t=this.focused;return t?t.cursor<=0?this.alert():(t.cursor--,this.render()):this.alert()}space(t,r){return this.dispatch(t,r)}number(t,r){return this.dispatch(t,r)}next(){let t=this.focused;if(!t)return this.alert();let{initial:r,input:s}=t;return r&&r.startsWith(s)&&s!==r?(t.value=t.input=r,t.cursor=t.value.length,this.render()):super.next()}prev(){let t=this.focused;return t?t.cursor===0?super.prev():(t.value=t.input=\"\",t.cursor=0,this.render()):this.alert()}separator(){return\"\"}format(t){return this.state.submitted?\"\":super.format(t)}pointer(){return\"\"}indicator(t){return t.input?\"\\u29BF\":\"\\u2299\"}async choiceSeparator(t,r){let s=await this.resolve(t.separator,this.state,t,r)||\":\";return s?\" \"+this.styles.disabled(s):\"\"}async renderChoice(t,r){await this.onChoice(t,r);let{state:s,styles:a}=this,{cursor:n,initial:c=\"\",name:f,hint:p,input:h=\"\"}=t,{muted:E,submitted:C,primary:S,danger:x}=a,I=p,T=this.index===r,O=t.validate||(()=>!0),U=await this.choiceSeparator(t,r),Y=t.message;this.align===\"right\"&&(Y=Y.padStart(this.longest+1,\" \")),this.align===\"left\"&&(Y=Y.padEnd(this.longest+1,\" \"));let te=this.values[f]=h||c,ie=h?\"success\":\"dark\";await O.call(t,te,this.state)!==!0&&(ie=\"danger\");let ue=a[ie],ae=ue(await this.indicator(t,r))+(t.pad||\"\"),de=this.indent(t),Ae=()=>[de,ae,Y+U,h,I].filter(Boolean).join(\" \");if(s.submitted)return Y=pst.unstyle(Y),h=C(h),I=\"\",Ae();if(t.format)h=await t.format.call(this,h,t,r);else{let Ce=this.styles.muted;h=gst(this,{input:h,initial:c,pos:n,showCursor:T,color:Ce})}return this.isValue(h)||(h=this.styles.muted(this.symbols.ellipsis)),t.result&&(this.values[f]=await t.result.call(this,te,t,r)),T&&(Y=S(Y)),t.error?h+=(h?\" \":\"\")+x(t.error.trim()):t.hint&&(h+=(h?\" \":\"\")+E(t.hint.trim())),Ae()}async submit(){return this.value=this.values,super.base.submit.call(this)}};$0e.exports=OG});var LG=G((A3t,tge)=>{\"use strict\";var dst=NT(),mst=()=>{throw new Error(\"expected prompt to have a custom authenticate method\")},ege=(e=mst)=>{class t extends dst{constructor(s){super(s)}async submit(){this.value=await e.call(this,this.values,this.state),super.base.submit.call(this)}static create(s){return ege(s)}}return t};tge.exports=ege()});var ige=G((p3t,nge)=>{\"use strict\";var yst=LG();function Est(e,t){return e.username===this.options.username&&e.password===this.options.password}var rge=(e=Est)=>{let t=[{name:\"username\",message:\"username\"},{name:\"password\",message:\"password\",format(s){return this.options.showPassword?s:(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(s.length))}}];class r extends yst.create(e){constructor(a){super({...a,choices:t})}static create(a){return rge(a)}}return r};nge.exports=rge()});var OT=G((h3t,sge)=>{\"use strict\";var Ist=KI(),{isPrimitive:Cst,hasColor:wst}=ra(),MG=class extends Ist{constructor(t){super(t),this.cursorHide()}async initialize(){let t=await this.resolve(this.initial,this.state);this.input=await this.cast(t),await super.initialize()}dispatch(t){return this.isValue(t)?(this.input=t,this.submit()):this.alert()}format(t){let{styles:r,state:s}=this;return s.submitted?r.success(t):r.primary(t)}cast(t){return this.isTrue(t)}isTrue(t){return/^[ty1]/i.test(t)}isFalse(t){return/^[fn0]/i.test(t)}isValue(t){return Cst(t)&&(this.isTrue(t)||this.isFalse(t))}async hint(){if(this.state.status===\"pending\"){let t=await this.element(\"hint\");return wst(t)?t:this.styles.muted(t)}}async render(){let{input:t,size:r}=this.state,s=await this.prefix(),a=await this.separator(),n=await this.message(),c=this.styles.muted(this.default),f=[s,n,c,a].filter(Boolean).join(\" \");this.state.prompt=f;let p=await this.header(),h=this.value=this.cast(t),E=await this.format(h),C=await this.error()||await this.hint(),S=await this.footer();C&&!f.includes(C)&&(E+=\" \"+C),f+=\" \"+E,this.clear(r),this.write([p,f,S].filter(Boolean).join(`\n`)),this.restore()}set value(t){super.value=t}get value(){return this.cast(super.value)}};sge.exports=MG});var age=G((g3t,oge)=>{\"use strict\";var Bst=OT(),UG=class extends Bst{constructor(t){super(t),this.default=this.options.default||(this.initial?\"(Y/n)\":\"(y/N)\")}};oge.exports=UG});var cge=G((d3t,lge)=>{\"use strict\";var vst=H0(),Sst=NT(),JI=Sst.prototype,_G=class extends vst{constructor(t){super({...t,multiple:!0}),this.align=[this.options.align,\"left\"].find(r=>r!=null),this.emptyError=\"\",this.values={}}dispatch(t,r){let s=this.focused,a=s.parent||{};return!s.editable&&!a.editable&&(t===\"a\"||t===\"i\")?super[t]():JI.dispatch.call(this,t,r)}append(t,r){return JI.append.call(this,t,r)}delete(t,r){return JI.delete.call(this,t,r)}space(t){return this.focused.editable?this.append(t):super.space()}number(t){return this.focused.editable?this.append(t):super.number(t)}next(){return this.focused.editable?JI.next.call(this):super.next()}prev(){return this.focused.editable?JI.prev.call(this):super.prev()}async indicator(t,r){let s=t.indicator||\"\",a=t.editable?s:super.indicator(t,r);return await this.resolve(a,this.state,t,r)||\"\"}indent(t){return t.role===\"heading\"?\"\":t.editable?\" \":\"  \"}async renderChoice(t,r){return t.indent=\"\",t.editable?JI.renderChoice.call(this,t,r):super.renderChoice(t,r)}error(){return\"\"}footer(){return this.state.error}async validate(){let t=!0;for(let r of this.choices){if(typeof r.validate!=\"function\"||r.role===\"heading\")continue;let s=r.parent?this.value[r.parent.name]:this.value;if(r.editable?s=r.value===r.name?r.initial||\"\":r.value:this.isDisabled(r)||(s=r.enabled===!0),t=await r.validate(s,this.state),t!==!0)break}return t!==!0&&(this.state.error=typeof t==\"string\"?t:\"Invalid Input\"),t}submit(){if(this.focused.newChoice===!0)return super.submit();if(this.choices.some(t=>t.newChoice))return this.alert();this.value={};for(let t of this.choices){let r=t.parent?this.value[t.parent.name]:this.value;if(t.role===\"heading\"){this.value[t.name]={};continue}t.editable?r[t.name]=t.value===t.name?t.initial||\"\":t.value:this.isDisabled(t)||(r[t.name]=t.enabled===!0)}return this.base.submit.call(this)}};lge.exports=_G});var bm=G((m3t,uge)=>{\"use strict\";var Dst=KI(),bst=NG(),{isPrimitive:Pst}=ra(),HG=class extends Dst{constructor(t){super(t),this.initial=Pst(this.initial)?String(this.initial):\"\",this.initial&&this.cursorHide(),this.state.prevCursor=0,this.state.clipboard=[]}async keypress(t,r={}){let s=this.state.prevKeypress;return this.state.prevKeypress=r,this.options.multiline===!0&&r.name===\"return\"&&(!s||s.name!==\"return\")?this.append(`\n`,r):super.keypress(t,r)}moveCursor(t){this.cursor+=t}reset(){return this.input=this.value=\"\",this.cursor=0,this.render()}dispatch(t,r){if(!t||r.ctrl||r.code)return this.alert();this.append(t)}append(t){let{cursor:r,input:s}=this.state;this.input=`${s}`.slice(0,r)+t+`${s}`.slice(r),this.moveCursor(String(t).length),this.render()}insert(t){this.append(t)}delete(){let{cursor:t,input:r}=this.state;if(t<=0)return this.alert();this.input=`${r}`.slice(0,t-1)+`${r}`.slice(t),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:t,input:r}=this.state;if(r[t]===void 0)return this.alert();this.input=`${r}`.slice(0,t)+`${r}`.slice(t+1),this.render()}cutForward(){let t=this.cursor;if(this.input.length<=t)return this.alert();this.state.clipboard.push(this.input.slice(t)),this.input=this.input.slice(0,t),this.render()}cutLeft(){let t=this.cursor;if(t===0)return this.alert();let r=this.input.slice(0,t),s=this.input.slice(t),a=r.split(\" \");this.state.clipboard.push(a.pop()),this.input=a.join(\" \"),this.cursor=this.input.length,this.input+=s,this.render()}paste(){if(!this.state.clipboard.length)return this.alert();this.insert(this.state.clipboard.pop()),this.render()}toggleCursor(){this.state.prevCursor?(this.cursor=this.state.prevCursor,this.state.prevCursor=0):(this.state.prevCursor=this.cursor,this.cursor=0),this.render()}first(){this.cursor=0,this.render()}last(){this.cursor=this.input.length-1,this.render()}next(){let t=this.initial!=null?String(this.initial):\"\";if(!t||!t.startsWith(this.input))return this.alert();this.input=this.initial,this.cursor=this.initial.length,this.render()}prev(){if(!this.input)return this.alert();this.reset()}backward(){return this.left()}forward(){return this.right()}right(){return this.cursor>=this.input.length?this.alert():(this.moveCursor(1),this.render())}left(){return this.cursor<=0?this.alert():(this.moveCursor(-1),this.render())}isValue(t){return!!t}async format(t=this.value){let r=await this.resolve(this.initial,this.state);return this.state.submitted?this.styles.submitted(t||r):bst(this,{input:t,initial:r,pos:this.cursor})}async render(){let t=this.state.size,r=await this.prefix(),s=await this.separator(),a=await this.message(),n=[r,a,s].filter(Boolean).join(\" \");this.state.prompt=n;let c=await this.header(),f=await this.format(),p=await this.error()||await this.hint(),h=await this.footer();p&&!f.includes(p)&&(f+=\" \"+p),n+=\" \"+f,this.clear(t),this.write([c,n,h].filter(Boolean).join(`\n`)),this.restore()}};uge.exports=HG});var Age=G((y3t,fge)=>{\"use strict\";var xst=e=>e.filter((t,r)=>e.lastIndexOf(t)===r),LT=e=>xst(e).filter(Boolean);fge.exports=(e,t={},r=\"\")=>{let{past:s=[],present:a=\"\"}=t,n,c;switch(e){case\"prev\":case\"undo\":return n=s.slice(0,s.length-1),c=s[s.length-1]||\"\",{past:LT([r,...n]),present:c};case\"next\":case\"redo\":return n=s.slice(1),c=s[0]||\"\",{past:LT([...n,r]),present:c};case\"save\":return{past:LT([...s,r]),present:\"\"};case\"remove\":return c=LT(s.filter(f=>f!==r)),a=\"\",c.length&&(a=c.pop()),{past:c,present:a};default:throw new Error(`Invalid action: \"${e}\"`)}}});var GG=G((E3t,hge)=>{\"use strict\";var kst=bm(),pge=Age(),jG=class extends kst{constructor(t){super(t);let r=this.options.history;if(r&&r.store){let s=r.values||this.initial;this.autosave=!!r.autosave,this.store=r.store,this.data=this.store.get(\"values\")||{past:[],present:s},this.initial=this.data.present||this.data.past[this.data.past.length-1]}}completion(t){return this.store?(this.data=pge(t,this.data,this.input),this.data.present?(this.input=this.data.present,this.cursor=this.input.length,this.render()):this.alert()):this.alert()}altUp(){return this.completion(\"prev\")}altDown(){return this.completion(\"next\")}prev(){return this.save(),super.prev()}save(){this.store&&(this.data=pge(\"save\",this.data,this.input),this.store.set(\"values\",this.data))}submit(){return this.store&&this.autosave===!0&&this.save(),super.submit()}};hge.exports=jG});var dge=G((I3t,gge)=>{\"use strict\";var Qst=bm(),qG=class extends Qst{format(){return\"\"}};gge.exports=qG});var yge=G((C3t,mge)=>{\"use strict\";var Rst=bm(),WG=class extends Rst{constructor(t={}){super(t),this.sep=this.options.separator||/, */,this.initial=t.initial||\"\"}split(t=this.value){return t?String(t).split(this.sep):[]}format(){let t=this.state.submitted?this.styles.primary:r=>r;return this.list.map(t).join(\", \")}async submit(t){let r=this.state.error||await this.validate(this.list,this.state);return r!==!0?(this.state.error=r,super.submit()):(this.value=this.list,super.submit())}get list(){return this.split()}};mge.exports=WG});var Ige=G((w3t,Ege)=>{\"use strict\";var Tst=H0(),VG=class extends Tst{constructor(t){super({...t,multiple:!0})}};Ege.exports=VG});var KG=G((B3t,Cge)=>{\"use strict\";var Fst=bm(),YG=class extends Fst{constructor(t={}){super({style:\"number\",...t}),this.min=this.isValue(t.min)?this.toNumber(t.min):-1/0,this.max=this.isValue(t.max)?this.toNumber(t.max):1/0,this.delay=t.delay!=null?t.delay:1e3,this.float=t.float!==!1,this.round=t.round===!0||t.float===!1,this.major=t.major||10,this.minor=t.minor||1,this.initial=t.initial!=null?t.initial:\"\",this.input=String(this.initial),this.cursor=this.input.length,this.cursorShow()}append(t){return!/[-+.]/.test(t)||t===\".\"&&this.input.includes(\".\")?this.alert(\"invalid number\"):super.append(t)}number(t){return super.append(t)}next(){return this.input&&this.input!==this.initial?this.alert():this.isValue(this.initial)?(this.input=this.initial,this.cursor=String(this.initial).length,this.render()):this.alert()}up(t){let r=t||this.minor,s=this.toNumber(this.input);return s>this.max+r?this.alert():(this.input=`${s+r}`,this.render())}down(t){let r=t||this.minor,s=this.toNumber(this.input);return s<this.min-r?this.alert():(this.input=`${s-r}`,this.render())}shiftDown(){return this.down(this.major)}shiftUp(){return this.up(this.major)}format(t=this.input){return typeof this.options.format==\"function\"?this.options.format.call(this,t):this.styles.info(t)}toNumber(t=\"\"){return this.float?+t:Math.round(+t)}isValue(t){return/^[-+]?[0-9]+((\\.)|(\\.[0-9]+))?$/.test(t)}submit(){let t=[this.input,this.initial].find(r=>this.isValue(r));return this.value=this.toNumber(t||0),super.submit()}};Cge.exports=YG});var Bge=G((v3t,wge)=>{wge.exports=KG()});var Sge=G((S3t,vge)=>{\"use strict\";var Nst=bm(),JG=class extends Nst{constructor(t){super(t),this.cursorShow()}format(t=this.input){return this.keypressed?(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(t.length)):\"\"}};vge.exports=JG});var Pge=G((D3t,bge)=>{\"use strict\";var Ost=zu(),Lst=Wv(),Dge=ra(),zG=class extends Lst{constructor(t={}){super(t),this.widths=[].concat(t.messageWidth||50),this.align=[].concat(t.align||\"left\"),this.linebreak=t.linebreak||!1,this.edgeLength=t.edgeLength||3,this.newline=t.newline||`\n   `;let r=t.startNumber||1;typeof this.scale==\"number\"&&(this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((s,a)=>({name:a+r})))}async reset(){return this.tableized=!1,await super.reset(),this.render()}tableize(){if(this.tableized===!0)return;this.tableized=!0;let t=0;for(let r of this.choices){t=Math.max(t,r.message.length),r.scaleIndex=r.initial||2,r.scale=[];for(let s=0;s<this.scale.length;s++)r.scale.push({index:s})}this.widths[0]=Math.min(this.widths[0],t+3)}async dispatch(t,r){if(this.multiple)return this[r.name]?await this[r.name](t,r):await super.dispatch(t,r);this.alert()}heading(t,r,s){return this.styles.strong(t)}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let t=this.focused;return t.scaleIndex>=this.scale.length-1?this.alert():(t.scaleIndex++,this.render())}left(){let t=this.focused;return t.scaleIndex<=0?this.alert():(t.scaleIndex--,this.render())}indent(){return\"\"}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.index)).join(\", \"):\"\"}pointer(){return\"\"}renderScaleKey(){return this.scaleKey===!1||this.state.submitted?\"\":[\"\",...this.scale.map(s=>`   ${s.name} - ${s.message}`)].map(s=>this.styles.muted(s)).join(`\n`)}renderScaleHeading(t){let r=this.scale.map(p=>p.name);typeof this.options.renderScaleHeading==\"function\"&&(r=this.options.renderScaleHeading.call(this,t));let s=this.scaleLength-r.join(\"\").length,a=Math.round(s/(r.length-1)),c=r.map(p=>this.styles.strong(p)).join(\" \".repeat(a)),f=\" \".repeat(this.widths[0]);return this.margin[3]+f+this.margin[1]+c}scaleIndicator(t,r,s){if(typeof this.options.scaleIndicator==\"function\")return this.options.scaleIndicator.call(this,t,r,s);let a=t.scaleIndex===r.index;return r.disabled?this.styles.hint(this.symbols.radio.disabled):a?this.styles.success(this.symbols.radio.on):this.symbols.radio.off}renderScale(t,r){let s=t.scale.map(n=>this.scaleIndicator(t,n,r)),a=this.term===\"Hyper\"?\"\":\" \";return s.join(a+this.symbols.line.repeat(this.edgeLength))}async renderChoice(t,r){await this.onChoice(t,r);let s=this.index===r,a=await this.pointer(t,r),n=await t.hint;n&&!Dge.hasColor(n)&&(n=this.styles.muted(n));let c=I=>this.margin[3]+I.replace(/\\s+$/,\"\").padEnd(this.widths[0],\" \"),f=this.newline,p=this.indent(t),h=await this.resolve(t.message,this.state,t,r),E=await this.renderScale(t,r),C=this.margin[1]+this.margin[3];this.scaleLength=Ost.unstyle(E).length,this.widths[0]=Math.min(this.widths[0],this.width-this.scaleLength-C.length);let x=Dge.wordWrap(h,{width:this.widths[0],newline:f}).split(`\n`).map(I=>c(I)+this.margin[1]);return s&&(E=this.styles.info(E),x=x.map(I=>this.styles.info(I))),x[0]+=E,this.linebreak&&x.push(\"\"),[p+a,x.join(`\n`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return\"\";this.tableize();let t=this.visible.map(async(a,n)=>await this.renderChoice(a,n)),r=await Promise.all(t),s=await this.renderScaleHeading();return this.margin[0]+[s,...r.map(a=>a.join(\" \"))].join(`\n`)}async render(){let{submitted:t,size:r}=this.state,s=await this.prefix(),a=await this.separator(),n=await this.message(),c=\"\";this.options.promptLine!==!1&&(c=[s,n,a,\"\"].join(\" \"),this.state.prompt=c);let f=await this.header(),p=await this.format(),h=await this.renderScaleKey(),E=await this.error()||await this.hint(),C=await this.renderChoices(),S=await this.footer(),x=this.emptyError;p&&(c+=p),E&&!c.includes(E)&&(c+=\" \"+E),t&&!p&&!C.trim()&&this.multiple&&x!=null&&(c+=this.styles.danger(x)),this.clear(r),this.write([f,c,h,C,S].filter(Boolean).join(`\n`)),this.state.submitted||this.write(this.margin[2]),this.restore()}submit(){this.value={};for(let t of this.choices)this.value[t.name]=t.scaleIndex;return this.base.submit.call(this)}};bge.exports=zG});var Qge=G((b3t,kge)=>{\"use strict\";var xge=zu(),Mst=(e=\"\")=>typeof e==\"string\"?e.replace(/^['\"]|['\"]$/g,\"\"):\"\",XG=class{constructor(t){this.name=t.key,this.field=t.field||{},this.value=Mst(t.initial||this.field.initial||\"\"),this.message=t.message||this.name,this.cursor=0,this.input=\"\",this.lines=[]}},Ust=async(e={},t={},r=s=>s)=>{let s=new Set,a=e.fields||[],n=e.template,c=[],f=[],p=[],h=1;typeof n==\"function\"&&(n=await n());let E=-1,C=()=>n[++E],S=()=>n[E+1],x=I=>{I.line=h,c.push(I)};for(x({type:\"bos\",value:\"\"});E<n.length-1;){let I=C();if(/^[^\\S\\n ]$/.test(I)){x({type:\"text\",value:I});continue}if(I===`\n`){x({type:\"newline\",value:I}),h++;continue}if(I===\"\\\\\"){I+=C(),x({type:\"text\",value:I});continue}if((I===\"$\"||I===\"#\"||I===\"{\")&&S()===\"{\"){let O=C();I+=O;let U={type:\"template\",open:I,inner:\"\",close:\"\",value:I},Y;for(;Y=C();){if(Y===\"}\"){S()===\"}\"&&(Y+=C()),U.value+=Y,U.close=Y;break}Y===\":\"?(U.initial=\"\",U.key=U.inner):U.initial!==void 0&&(U.initial+=Y),U.value+=Y,U.inner+=Y}U.template=U.open+(U.initial||U.inner)+U.close,U.key=U.key||U.inner,t.hasOwnProperty(U.key)&&(U.initial=t[U.key]),U=r(U),x(U),p.push(U.key),s.add(U.key);let te=f.find(ie=>ie.name===U.key);U.field=a.find(ie=>ie.name===U.key),te||(te=new XG(U),f.push(te)),te.lines.push(U.line-1);continue}let T=c[c.length-1];T.type===\"text\"&&T.line===h?T.value+=I:x({type:\"text\",value:I})}return x({type:\"eos\",value:\"\"}),{input:n,tabstops:c,unique:s,keys:p,items:f}};kge.exports=async e=>{let t=e.options,r=new Set(t.required===!0?[]:t.required||[]),s={...t.values,...t.initial},{tabstops:a,items:n,keys:c}=await Ust(t,s),f=ZG(\"result\",e,t),p=ZG(\"format\",e,t),h=ZG(\"validate\",e,t,!0),E=e.isValue.bind(e);return async(C={},S=!1)=>{let x=0;C.required=r,C.items=n,C.keys=c,C.output=\"\";let I=async(Y,te,ie,ue)=>{let ae=await h(Y,te,ie,ue);return ae===!1?\"Invalid field \"+ie.name:ae};for(let Y of a){let te=Y.value,ie=Y.key;if(Y.type!==\"template\"){te&&(C.output+=te);continue}if(Y.type===\"template\"){let ue=n.find(Ee=>Ee.name===ie);t.required===!0&&C.required.add(ue.name);let ae=[ue.input,C.values[ue.value],ue.value,te].find(E),Ae=(ue.field||{}).message||Y.inner;if(S){let Ee=await I(C.values[ie],C,ue,x);if(Ee&&typeof Ee==\"string\"||Ee===!1){C.invalid.set(ie,Ee);continue}C.invalid.delete(ie);let g=await f(C.values[ie],C,ue,x);C.output+=xge.unstyle(g);continue}ue.placeholder=!1;let Ce=te;te=await p(te,C,ue,x),ae!==te?(C.values[ie]=ae,te=e.styles.typing(ae),C.missing.delete(Ae)):(C.values[ie]=void 0,ae=`<${Ae}>`,te=e.styles.primary(ae),ue.placeholder=!0,C.required.has(ie)&&C.missing.add(Ae)),C.missing.has(Ae)&&C.validating&&(te=e.styles.warning(ae)),C.invalid.has(ie)&&C.validating&&(te=e.styles.danger(ae)),x===C.index&&(Ce!==te?te=e.styles.underline(te):te=e.styles.heading(xge.unstyle(te))),x++}te&&(C.output+=te)}let T=C.output.split(`\n`).map(Y=>\" \"+Y),O=n.length,U=0;for(let Y of n)C.invalid.has(Y.name)&&Y.lines.forEach(te=>{T[te][0]===\" \"&&(T[te]=C.styles.danger(C.symbols.bullet)+T[te].slice(1))}),e.isValue(C.values[Y.name])&&U++;return C.completed=(U/O*100).toFixed(0),C.output=T.join(`\n`),C.output}};function ZG(e,t,r,s){return(a,n,c,f)=>typeof c.field[e]==\"function\"?c.field[e].call(t,a,n,c,f):[s,a].find(p=>t.isValue(p))}});var Tge=G((P3t,Rge)=>{\"use strict\";var _st=zu(),Hst=Qge(),jst=KI(),$G=class extends jst{constructor(t){super(t),this.cursorHide(),this.reset(!0)}async initialize(){this.interpolate=await Hst(this),await super.initialize()}async reset(t){this.state.keys=[],this.state.invalid=new Map,this.state.missing=new Set,this.state.completed=0,this.state.values={},t!==!0&&(await this.initialize(),await this.render())}moveCursor(t){let r=this.getItem();this.cursor+=t,r.cursor+=t}dispatch(t,r){if(!r.code&&!r.ctrl&&t!=null&&this.getItem()){this.append(t,r);return}this.alert()}append(t,r){let s=this.getItem(),a=s.input.slice(0,this.cursor),n=s.input.slice(this.cursor);this.input=s.input=`${a}${t}${n}`,this.moveCursor(1),this.render()}delete(){let t=this.getItem();if(this.cursor<=0||!t.input)return this.alert();let r=t.input.slice(this.cursor),s=t.input.slice(0,this.cursor-1);this.input=t.input=`${s}${r}`,this.moveCursor(-1),this.render()}increment(t){return t>=this.state.keys.length-1?0:t+1}decrement(t){return t<=0?this.state.keys.length-1:t-1}first(){this.state.index=0,this.render()}last(){this.state.index=this.state.keys.length-1,this.render()}right(){if(this.cursor>=this.input.length)return this.alert();this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();this.moveCursor(-1),this.render()}prev(){this.state.index=this.decrement(this.state.index),this.getItem(),this.render()}next(){this.state.index=this.increment(this.state.index),this.getItem(),this.render()}up(){this.prev()}down(){this.next()}format(t){let r=this.state.completed<100?this.styles.warning:this.styles.success;return this.state.submitted===!0&&this.state.completed!==100&&(r=this.styles.danger),r(`${this.state.completed}% completed`)}async render(){let{index:t,keys:r=[],submitted:s,size:a}=this.state,n=[this.options.newline,`\n`].find(Y=>Y!=null),c=await this.prefix(),f=await this.separator(),p=await this.message(),h=[c,p,f].filter(Boolean).join(\" \");this.state.prompt=h;let E=await this.header(),C=await this.error()||\"\",S=await this.hint()||\"\",x=s?\"\":await this.interpolate(this.state),I=this.state.key=r[t]||\"\",T=await this.format(I),O=await this.footer();T&&(h+=\" \"+T),S&&!T&&this.state.completed===0&&(h+=\" \"+S),this.clear(a);let U=[E,h,x,O,C.trim()];this.write(U.filter(Boolean).join(n)),this.restore()}getItem(t){let{items:r,keys:s,index:a}=this.state,n=r.find(c=>c.name===s[a]);return n&&n.input!=null&&(this.input=n.input,this.cursor=n.cursor),n}async submit(){typeof this.interpolate!=\"function\"&&await this.initialize(),await this.interpolate(this.state,!0);let{invalid:t,missing:r,output:s,values:a}=this.state;if(t.size){let f=\"\";for(let[p,h]of t)f+=`Invalid ${p}: ${h}\n`;return this.state.error=f,super.submit()}if(r.size)return this.state.error=\"Required: \"+[...r.keys()].join(\", \"),super.submit();let c=_st.unstyle(s).split(`\n`).map(f=>f.slice(1)).join(`\n`);return this.value={values:a,result:c},super.submit()}};Rge.exports=$G});var Nge=G((x3t,Fge)=>{\"use strict\";var Gst=\"(Use <shift>+<up/down> to sort)\",qst=H0(),e5=class extends qst{constructor(t){super({...t,reorder:!1,sort:!0,multiple:!0}),this.state.hint=[this.options.hint,Gst].find(this.isValue.bind(this))}indicator(){return\"\"}async renderChoice(t,r){let s=await super.renderChoice(t,r),a=this.symbols.identicalTo+\" \",n=this.index===r&&this.sorting?this.styles.muted(a):\"  \";return this.options.drag===!1&&(n=\"\"),this.options.numbered===!0?n+`${r+1} - `+s:n+s}get selected(){return this.choices}submit(){return this.value=this.choices.map(t=>t.value),super.submit()}};Fge.exports=e5});var Lge=G((k3t,Oge)=>{\"use strict\";var Wst=Wv(),t5=class extends Wst{constructor(t={}){if(super(t),this.emptyError=t.emptyError||\"No items were selected\",this.term=process.env.TERM_PROGRAM,!this.options.header){let r=[\"\",\"4 - Strongly Agree\",\"3 - Agree\",\"2 - Neutral\",\"1 - Disagree\",\"0 - Strongly Disagree\",\"\"];r=r.map(s=>this.styles.muted(s)),this.state.header=r.join(`\n   `)}}async toChoices(...t){if(this.createdScales)return!1;this.createdScales=!0;let r=await super.toChoices(...t);for(let s of r)s.scale=Vst(5,this.options),s.scaleIdx=2;return r}dispatch(){this.alert()}space(){let t=this.focused,r=t.scale[t.scaleIdx],s=r.selected;return t.scale.forEach(a=>a.selected=!1),r.selected=!s,this.render()}indicator(){return\"\"}pointer(){return\"\"}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let t=this.focused;return t.scaleIdx>=t.scale.length-1?this.alert():(t.scaleIdx++,this.render())}left(){let t=this.focused;return t.scaleIdx<=0?this.alert():(t.scaleIdx--,this.render())}indent(){return\"   \"}async renderChoice(t,r){await this.onChoice(t,r);let s=this.index===r,a=this.term===\"Hyper\",n=a?9:8,c=a?\"\":\" \",f=this.symbols.line.repeat(n),p=\" \".repeat(n+(a?0:1)),h=te=>(te?this.styles.success(\"\\u25C9\"):\"\\u25EF\")+c,E=r+1+\".\",C=s?this.styles.heading:this.styles.noop,S=await this.resolve(t.message,this.state,t,r),x=this.indent(t),I=x+t.scale.map((te,ie)=>h(ie===t.scaleIdx)).join(f),T=te=>te===t.scaleIdx?C(te):te,O=x+t.scale.map((te,ie)=>T(ie)).join(p),U=()=>[E,S].filter(Boolean).join(\" \"),Y=()=>[U(),I,O,\" \"].filter(Boolean).join(`\n`);return s&&(I=this.styles.cyan(I),O=this.styles.cyan(O)),Y()}async renderChoices(){if(this.state.submitted)return\"\";let t=this.visible.map(async(s,a)=>await this.renderChoice(s,a)),r=await Promise.all(t);return r.length||r.push(this.styles.danger(\"No matching choices\")),r.join(`\n`)}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.scaleIdx)).join(\", \"):\"\"}async render(){let{submitted:t,size:r}=this.state,s=await this.prefix(),a=await this.separator(),n=await this.message(),c=[s,n,a].filter(Boolean).join(\" \");this.state.prompt=c;let f=await this.header(),p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),C=await this.footer();(p||!h)&&(c+=\" \"+p),h&&!c.includes(h)&&(c+=\" \"+h),t&&!p&&!E&&this.multiple&&this.type!==\"form\"&&(c+=this.styles.danger(this.emptyError)),this.clear(r),this.write([c,f,E,C].filter(Boolean).join(`\n`)),this.restore()}submit(){this.value={};for(let t of this.choices)this.value[t.name]=t.scaleIdx;return this.base.submit.call(this)}};function Vst(e,t={}){if(Array.isArray(t.scale))return t.scale.map(s=>({...s}));let r=[];for(let s=1;s<e+1;s++)r.push({i:s,selected:!1});return r}Oge.exports=t5});var Uge=G((Q3t,Mge)=>{Mge.exports=GG()});var Hge=G((R3t,_ge)=>{\"use strict\";var Yst=OT(),r5=class extends Yst{async initialize(){await super.initialize(),this.value=this.initial=!!this.options.initial,this.disabled=this.options.disabled||\"no\",this.enabled=this.options.enabled||\"yes\",await this.render()}reset(){this.value=this.initial,this.render()}delete(){this.alert()}toggle(){this.value=!this.value,this.render()}enable(){if(this.value===!0)return this.alert();this.value=!0,this.render()}disable(){if(this.value===!1)return this.alert();this.value=!1,this.render()}up(){this.toggle()}down(){this.toggle()}right(){this.toggle()}left(){this.toggle()}next(){this.toggle()}prev(){this.toggle()}dispatch(t=\"\",r){switch(t.toLowerCase()){case\" \":return this.toggle();case\"1\":case\"y\":case\"t\":return this.enable();case\"0\":case\"n\":case\"f\":return this.disable();default:return this.alert()}}format(){let t=s=>this.styles.primary.underline(s);return[this.value?this.disabled:t(this.disabled),this.value?t(this.enabled):this.enabled].join(this.styles.muted(\" / \"))}async render(){let{size:t}=this.state,r=await this.header(),s=await this.prefix(),a=await this.separator(),n=await this.message(),c=await this.format(),f=await this.error()||await this.hint(),p=await this.footer(),h=[s,n,a,c].join(\" \");this.state.prompt=h,f&&!h.includes(f)&&(h+=\" \"+f),this.clear(t),this.write([r,h,p].filter(Boolean).join(`\n`)),this.write(this.margin[2]),this.restore()}};_ge.exports=r5});var Gge=G((T3t,jge)=>{\"use strict\";var Kst=H0(),n5=class extends Kst{constructor(t){if(super(t),typeof this.options.correctChoice!=\"number\"||this.options.correctChoice<0)throw new Error(\"Please specify the index of the correct answer from the list of choices\")}async toChoices(t,r){let s=await super.toChoices(t,r);if(s.length<2)throw new Error(\"Please give at least two choices to the user\");if(this.options.correctChoice>s.length)throw new Error(\"Please specify the index of the correct answer from the list of choices\");return s}check(t){return t.index===this.options.correctChoice}async result(t){return{selectedAnswer:t,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}};jge.exports=n5});var Wge=G(i5=>{\"use strict\";var qge=ra(),Ts=(e,t)=>{qge.defineExport(i5,e,t),qge.defineExport(i5,e.toLowerCase(),t)};Ts(\"AutoComplete\",()=>Z0e());Ts(\"BasicAuth\",()=>ige());Ts(\"Confirm\",()=>age());Ts(\"Editable\",()=>cge());Ts(\"Form\",()=>NT());Ts(\"Input\",()=>GG());Ts(\"Invisible\",()=>dge());Ts(\"List\",()=>yge());Ts(\"MultiSelect\",()=>Ige());Ts(\"Numeral\",()=>Bge());Ts(\"Password\",()=>Sge());Ts(\"Scale\",()=>Pge());Ts(\"Select\",()=>H0());Ts(\"Snippet\",()=>Tge());Ts(\"Sort\",()=>Nge());Ts(\"Survey\",()=>Lge());Ts(\"Text\",()=>Uge());Ts(\"Toggle\",()=>Hge());Ts(\"Quiz\",()=>Gge())});var Yge=G((N3t,Vge)=>{Vge.exports={ArrayPrompt:Wv(),AuthPrompt:LG(),BooleanPrompt:OT(),NumberPrompt:KG(),StringPrompt:bm()}});var Yv=G((O3t,Jge)=>{\"use strict\";var Kge=Ie(\"assert\"),o5=Ie(\"events\"),j0=ra(),Xu=class extends o5{constructor(t,r){super(),this.options=j0.merge({},t),this.answers={...r}}register(t,r){if(j0.isObject(t)){for(let a of Object.keys(t))this.register(a,t[a]);return this}Kge.equal(typeof r,\"function\",\"expected a function\");let s=t.toLowerCase();return r.prototype instanceof this.Prompt?this.prompts[s]=r:this.prompts[s]=r(this.Prompt,this),this}async prompt(t=[]){for(let r of[].concat(t))try{typeof r==\"function\"&&(r=await r.call(this)),await this.ask(j0.merge({},this.options,r))}catch(s){return Promise.reject(s)}return this.answers}async ask(t){typeof t==\"function\"&&(t=await t.call(this));let r=j0.merge({},this.options,t),{type:s,name:a}=t,{set:n,get:c}=j0;if(typeof s==\"function\"&&(s=await s.call(this,t,this.answers)),!s)return this.answers[a];Kge(this.prompts[s],`Prompt \"${s}\" is not registered`);let f=new this.prompts[s](r),p=c(this.answers,a);f.state.answers=this.answers,f.enquirer=this,a&&f.on(\"submit\",E=>{this.emit(\"answer\",a,E,f),n(this.answers,a,E)});let h=f.emit.bind(f);return f.emit=(...E)=>(this.emit.call(this,...E),h(...E)),this.emit(\"prompt\",f,this),r.autofill&&p!=null?(f.value=f.input=p,r.autofill===\"show\"&&await f.submit()):p=f.value=await f.run(),p}use(t){return t.call(this,this),this}set Prompt(t){this._Prompt=t}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(t){this._Prompt=t}static get Prompt(){return this._Prompt||KI()}static get prompts(){return Wge()}static get types(){return Yge()}static get prompt(){let t=(r,...s)=>{let a=new this(...s),n=a.emit.bind(a);return a.emit=(...c)=>(t.emit(...c),n(...c)),a.prompt(r)};return j0.mixinEmitter(t,new o5),t}};j0.mixinEmitter(Xu,new o5);var s5=Xu.prompts;for(let e of Object.keys(s5)){let t=e.toLowerCase(),r=s=>new s5[e](s).run();Xu.prompt[t]=r,Xu[t]=r,Xu[e]||Reflect.defineProperty(Xu,e,{get:()=>s5[e]})}var Vv=e=>{j0.defineExport(Xu,e,()=>Xu.types[e])};Vv(\"ArrayPrompt\");Vv(\"AuthPrompt\");Vv(\"BooleanPrompt\");Vv(\"NumberPrompt\");Vv(\"StringPrompt\");Jge.exports=Xu});var nde=G((sHt,not)=>{not.exports={name:\"@yarnpkg/cli\",version:\"4.13.0\",license:\"BSD-2-Clause\",main:\"./sources/index.ts\",exports:{\".\":\"./sources/index.ts\",\"./polyfills\":\"./sources/polyfills.ts\",\"./package.json\":\"./package.json\"},dependencies:{\"@yarnpkg/core\":\"workspace:^\",\"@yarnpkg/fslib\":\"workspace:^\",\"@yarnpkg/libzip\":\"workspace:^\",\"@yarnpkg/parsers\":\"workspace:^\",\"@yarnpkg/plugin-catalog\":\"workspace:^\",\"@yarnpkg/plugin-compat\":\"workspace:^\",\"@yarnpkg/plugin-constraints\":\"workspace:^\",\"@yarnpkg/plugin-dlx\":\"workspace:^\",\"@yarnpkg/plugin-essentials\":\"workspace:^\",\"@yarnpkg/plugin-exec\":\"workspace:^\",\"@yarnpkg/plugin-file\":\"workspace:^\",\"@yarnpkg/plugin-git\":\"workspace:^\",\"@yarnpkg/plugin-github\":\"workspace:^\",\"@yarnpkg/plugin-http\":\"workspace:^\",\"@yarnpkg/plugin-init\":\"workspace:^\",\"@yarnpkg/plugin-interactive-tools\":\"workspace:^\",\"@yarnpkg/plugin-jsr\":\"workspace:^\",\"@yarnpkg/plugin-link\":\"workspace:^\",\"@yarnpkg/plugin-nm\":\"workspace:^\",\"@yarnpkg/plugin-npm\":\"workspace:^\",\"@yarnpkg/plugin-npm-cli\":\"workspace:^\",\"@yarnpkg/plugin-pack\":\"workspace:^\",\"@yarnpkg/plugin-patch\":\"workspace:^\",\"@yarnpkg/plugin-pnp\":\"workspace:^\",\"@yarnpkg/plugin-pnpm\":\"workspace:^\",\"@yarnpkg/plugin-stage\":\"workspace:^\",\"@yarnpkg/plugin-typescript\":\"workspace:^\",\"@yarnpkg/plugin-version\":\"workspace:^\",\"@yarnpkg/plugin-workspace-tools\":\"workspace:^\",\"@yarnpkg/shell\":\"workspace:^\",\"ci-info\":\"^4.0.0\",clipanion:\"^4.0.0-rc.2\",semver:\"^7.1.2\",tslib:\"^2.4.0\",typanion:\"^3.14.0\"},devDependencies:{\"@types/semver\":\"^7.1.0\",\"@yarnpkg/builder\":\"workspace:^\",\"@yarnpkg/monorepo\":\"workspace:^\",\"@yarnpkg/pnpify\":\"workspace:^\"},peerDependencies:{\"@yarnpkg/core\":\"workspace:^\"},scripts:{postpack:\"rm -rf lib\",prepack:'run build:compile \"$(pwd)\"',\"build:cli+hook\":\"run build:pnp:hook && builder build bundle\",\"build:cli\":\"builder build bundle\",\"run:cli\":\"builder run\",\"update-local\":\"run build:cli --no-git-hash && rsync -a --delete bundles/ bin/\"},publishConfig:{main:\"./lib/index.js\",bin:null,exports:{\".\":\"./lib/index.js\",\"./package.json\":\"./package.json\"}},files:[\"/lib/**/*\",\"!/lib/pluginConfiguration.*\",\"!/lib/cli.*\"],\"@yarnpkg/builder\":{bundles:{standard:[\"@yarnpkg/plugin-essentials\",\"@yarnpkg/plugin-catalog\",\"@yarnpkg/plugin-compat\",\"@yarnpkg/plugin-constraints\",\"@yarnpkg/plugin-dlx\",\"@yarnpkg/plugin-exec\",\"@yarnpkg/plugin-file\",\"@yarnpkg/plugin-git\",\"@yarnpkg/plugin-github\",\"@yarnpkg/plugin-http\",\"@yarnpkg/plugin-init\",\"@yarnpkg/plugin-interactive-tools\",\"@yarnpkg/plugin-jsr\",\"@yarnpkg/plugin-link\",\"@yarnpkg/plugin-nm\",\"@yarnpkg/plugin-npm\",\"@yarnpkg/plugin-npm-cli\",\"@yarnpkg/plugin-pack\",\"@yarnpkg/plugin-patch\",\"@yarnpkg/plugin-pnp\",\"@yarnpkg/plugin-pnpm\",\"@yarnpkg/plugin-stage\",\"@yarnpkg/plugin-typescript\",\"@yarnpkg/plugin-version\",\"@yarnpkg/plugin-workspace-tools\"]}},repository:{type:\"git\",url:\"git+https://github.com/yarnpkg/berry.git\",directory:\"packages/yarnpkg-cli\"},engines:{node:\">=18.12.0\"}}});var C5=G((LGt,gde)=>{\"use strict\";gde.exports=function(t,r){r===!0&&(r=0);var s=\"\";if(typeof t==\"string\")try{s=new URL(t).protocol}catch{}else t&&t.constructor===URL&&(s=t.protocol);var a=s.split(/\\:|\\+/).filter(Boolean);return typeof r==\"number\"?a[r]:a}});var mde=G((MGt,dde)=>{\"use strict\";var Bot=C5();function vot(e){var t={protocols:[],protocol:null,port:null,resource:\"\",host:\"\",user:\"\",password:\"\",pathname:\"\",hash:\"\",search:\"\",href:e,query:{},parse_failed:!1};try{var r=new URL(e);t.protocols=Bot(r),t.protocol=t.protocols[0],t.port=r.port,t.resource=r.hostname,t.host=r.host,t.user=r.username||\"\",t.password=r.password||\"\",t.pathname=r.pathname,t.hash=r.hash.slice(1),t.search=r.search.slice(1),t.href=r.href,t.query=Object.fromEntries(r.searchParams)}catch{t.protocols=[\"file\"],t.protocol=t.protocols[0],t.port=\"\",t.resource=\"\",t.user=\"\",t.pathname=\"\",t.hash=\"\",t.search=\"\",t.href=e,t.query={},t.parse_failed=!0}return t}dde.exports=vot});var Ide=G((UGt,Ede)=>{\"use strict\";var Sot=mde();function Dot(e){return e&&typeof e==\"object\"&&\"default\"in e?e:{default:e}}var bot=Dot(Sot),Pot=\"text/plain\",xot=\"us-ascii\",yde=(e,t)=>t.some(r=>r instanceof RegExp?r.test(e):r===e),kot=(e,{stripHash:t})=>{let r=/^data:(?<type>[^,]*?),(?<data>[^#]*?)(?:#(?<hash>.*))?$/.exec(e);if(!r)throw new Error(`Invalid URL: ${e}`);let{type:s,data:a,hash:n}=r.groups,c=s.split(\";\");n=t?\"\":n;let f=!1;c[c.length-1]===\"base64\"&&(c.pop(),f=!0);let p=(c.shift()||\"\").toLowerCase(),E=[...c.map(C=>{let[S,x=\"\"]=C.split(\"=\").map(I=>I.trim());return S===\"charset\"&&(x=x.toLowerCase(),x===xot)?\"\":`${S}${x?`=${x}`:\"\"}`}).filter(Boolean)];return f&&E.push(\"base64\"),(E.length>0||p&&p!==Pot)&&E.unshift(p),`data:${E.join(\";\")},${f?a.trim():a}${n?`#${n}`:\"\"}`};function Qot(e,t){if(t={defaultProtocol:\"http:\",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripTextFragment:!0,stripWWW:!0,removeQueryParameters:[/^utm_\\w+/i],removeTrailingSlash:!0,removeSingleSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...t},e=e.trim(),/^data:/i.test(e))return kot(e,t);if(/^view-source:/i.test(e))throw new Error(\"`view-source:` is not supported as it is a non-standard protocol\");let r=e.startsWith(\"//\");!r&&/^\\.*\\//.test(e)||(e=e.replace(/^(?!(?:\\w+:)?\\/\\/)|^\\/\\//,t.defaultProtocol));let a=new URL(e);if(t.forceHttp&&t.forceHttps)throw new Error(\"The `forceHttp` and `forceHttps` options cannot be used together\");if(t.forceHttp&&a.protocol===\"https:\"&&(a.protocol=\"http:\"),t.forceHttps&&a.protocol===\"http:\"&&(a.protocol=\"https:\"),t.stripAuthentication&&(a.username=\"\",a.password=\"\"),t.stripHash?a.hash=\"\":t.stripTextFragment&&(a.hash=a.hash.replace(/#?:~:text.*?$/i,\"\")),a.pathname){let c=/\\b[a-z][a-z\\d+\\-.]{1,50}:\\/\\//g,f=0,p=\"\";for(;;){let E=c.exec(a.pathname);if(!E)break;let C=E[0],S=E.index,x=a.pathname.slice(f,S);p+=x.replace(/\\/{2,}/g,\"/\"),p+=C,f=S+C.length}let h=a.pathname.slice(f,a.pathname.length);p+=h.replace(/\\/{2,}/g,\"/\"),a.pathname=p}if(a.pathname)try{a.pathname=decodeURI(a.pathname)}catch{}if(t.removeDirectoryIndex===!0&&(t.removeDirectoryIndex=[/^index\\.[a-z]+$/]),Array.isArray(t.removeDirectoryIndex)&&t.removeDirectoryIndex.length>0){let c=a.pathname.split(\"/\"),f=c[c.length-1];yde(f,t.removeDirectoryIndex)&&(c=c.slice(0,-1),a.pathname=c.slice(1).join(\"/\")+\"/\")}if(a.hostname&&(a.hostname=a.hostname.replace(/\\.$/,\"\"),t.stripWWW&&/^www\\.(?!www\\.)[a-z\\-\\d]{1,63}\\.[a-z.\\-\\d]{2,63}$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\\./,\"\"))),Array.isArray(t.removeQueryParameters))for(let c of[...a.searchParams.keys()])yde(c,t.removeQueryParameters)&&a.searchParams.delete(c);if(t.removeQueryParameters===!0&&(a.search=\"\"),t.sortQueryParameters){a.searchParams.sort();try{a.search=decodeURIComponent(a.search)}catch{}}t.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\\/$/,\"\"));let n=e;return e=a.toString(),!t.removeSingleSlash&&a.pathname===\"/\"&&!n.endsWith(\"/\")&&a.hash===\"\"&&(e=e.replace(/\\/$/,\"\")),(t.removeTrailingSlash||a.pathname===\"/\")&&a.hash===\"\"&&t.removeSingleSlash&&(e=e.replace(/\\/$/,\"\")),r&&!t.normalizeProtocol&&(e=e.replace(/^http:\\/\\//,\"//\")),t.stripProtocol&&(e=e.replace(/^(?:https?:)?\\/\\//,\"\")),e}var w5=(e,t=!1)=>{let r=/^(?:([a-z_][a-z0-9_-]{0,31})@|https?:\\/\\/)([\\w\\.\\-@]+)[\\/:]([\\~,\\.\\w,\\-,\\_,\\/]+?(?:\\.git|\\/)?)$/,s=n=>{let c=new Error(n);throw c.subject_url=e,c};(typeof e!=\"string\"||!e.trim())&&s(\"Invalid url.\"),e.length>w5.MAX_INPUT_LENGTH&&s(\"Input exceeds maximum length. If needed, change the value of parseUrl.MAX_INPUT_LENGTH.\"),t&&(typeof t!=\"object\"&&(t={stripHash:!1}),e=Qot(e,t));let a=bot.default(e);if(a.parse_failed){let n=a.href.match(r);n?(a.protocols=[\"ssh\"],a.protocol=\"ssh\",a.resource=n[2],a.host=n[2],a.user=n[1],a.pathname=`/${n[3]}`,a.parse_failed=!1):s(\"URL parsing failed.\")}return a};w5.MAX_INPUT_LENGTH=2048;Ede.exports=w5});var Bde=G((_Gt,wde)=>{\"use strict\";var Rot=C5();function Cde(e){if(Array.isArray(e))return e.indexOf(\"ssh\")!==-1||e.indexOf(\"rsync\")!==-1;if(typeof e!=\"string\")return!1;var t=Rot(e);if(e=e.substring(e.indexOf(\"://\")+3),Cde(t))return!0;var r=new RegExp(\".([a-zA-Z\\\\d]+):(\\\\d+)/\");return!e.match(r)&&e.indexOf(\"@\")<e.indexOf(\":\")}wde.exports=Cde});var Dde=G((HGt,Sde)=>{\"use strict\";var Tot=Ide(),vde=Bde();function Fot(e){var t=Tot(e);return t.token=\"\",t.password===\"x-oauth-basic\"?t.token=t.user:t.user===\"x-token-auth\"&&(t.token=t.password),vde(t.protocols)||t.protocols.length===0&&vde(e)?t.protocol=\"ssh\":t.protocols.length?t.protocol=t.protocols[0]:(t.protocol=\"file\",t.protocols=[\"file\"]),t.href=t.href.replace(/\\/$/,\"\"),t}Sde.exports=Fot});var Pde=G((jGt,bde)=>{\"use strict\";var Not=Dde();function B5(e){if(typeof e!=\"string\")throw new Error(\"The url must be a string.\");var t=/^([a-z\\d-]{1,39})\\/([-\\.\\w]{1,100})$/i;t.test(e)&&(e=\"https://github.com/\"+e);var r=Not(e),s=r.resource.split(\".\"),a=null;switch(r.toString=function(O){return B5.stringify(this,O)},r.source=s.length>2?s.slice(1-s.length).join(\".\"):r.source=r.resource,r.git_suffix=/\\.git$/.test(r.pathname),r.name=decodeURIComponent((r.pathname||r.href).replace(/(^\\/)|(\\/$)/g,\"\").replace(/\\.git$/,\"\")),r.owner=decodeURIComponent(r.user),r.source){case\"git.cloudforge.com\":r.owner=r.user,r.organization=s[0],r.source=\"cloudforge.com\";break;case\"visualstudio.com\":if(r.resource===\"vs-ssh.visualstudio.com\"){a=r.name.split(\"/\"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3],r.full_name=a[2]+\"/\"+a[3]);break}else{a=r.name.split(\"/\"),a.length===2?(r.owner=a[1],r.name=a[1],r.full_name=\"_git/\"+r.name):a.length===3?(r.name=a[2],a[0]===\"DefaultCollection\"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+\"/_git/\"+r.name):(r.owner=a[0],r.full_name=r.owner+\"/_git/\"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+\"/\"+r.owner+\"/_git/\"+r.name);break}case\"dev.azure.com\":case\"azure.com\":if(r.resource===\"ssh.dev.azure.com\"){a=r.name.split(\"/\"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3]);break}else{a=r.name.split(\"/\"),a.length===5?(r.organization=a[0],r.owner=a[1],r.name=a[4],r.full_name=\"_git/\"+r.name):a.length===3?(r.name=a[2],a[0]===\"DefaultCollection\"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+\"/_git/\"+r.name):(r.owner=a[0],r.full_name=r.owner+\"/_git/\"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+\"/\"+r.owner+\"/_git/\"+r.name),r.query&&r.query.path&&(r.filepath=r.query.path.replace(/^\\/+/g,\"\")),r.query&&r.query.version&&(r.ref=r.query.version.replace(/^GB/,\"\"));break}default:a=r.name.split(\"/\");var n=a.length-1;if(a.length>=2){var c=a.indexOf(\"-\",2),f=a.indexOf(\"blob\",2),p=a.indexOf(\"tree\",2),h=a.indexOf(\"commit\",2),E=a.indexOf(\"src\",2),C=a.indexOf(\"raw\",2),S=a.indexOf(\"edit\",2);n=c>0?c-1:f>0?f-1:p>0?p-1:h>0?h-1:E>0?E-1:C>0?C-1:S>0?S-1:n,r.owner=a.slice(0,n).join(\"/\"),r.name=a[n],h&&(r.commit=a[n+2])}r.ref=\"\",r.filepathtype=\"\",r.filepath=\"\";var x=a.length>n&&a[n+1]===\"-\"?n+1:n;a.length>x+2&&[\"raw\",\"src\",\"blob\",\"tree\",\"edit\"].indexOf(a[x+1])>=0&&(r.filepathtype=a[x+1],r.ref=a[x+2],a.length>x+3&&(r.filepath=a.slice(x+3).join(\"/\"))),r.organization=r.owner;break}r.full_name||(r.full_name=r.owner,r.name&&(r.full_name&&(r.full_name+=\"/\"),r.full_name+=r.name)),r.owner.startsWith(\"scm/\")&&(r.source=\"bitbucket-server\",r.owner=r.owner.replace(\"scm/\",\"\"),r.organization=r.owner,r.full_name=r.owner+\"/\"+r.name);var I=/(projects|users)\\/(.*?)\\/repos\\/(.*?)((\\/.*$)|$)/,T=I.exec(r.pathname);return T!=null&&(r.source=\"bitbucket-server\",T[1]===\"users\"?r.owner=\"~\"+T[2]:r.owner=T[2],r.organization=r.owner,r.name=T[3],a=T[4].split(\"/\"),a.length>1&&([\"raw\",\"browse\"].indexOf(a[1])>=0?(r.filepathtype=a[1],a.length>2&&(r.filepath=a.slice(2).join(\"/\"))):a[1]===\"commits\"&&a.length>2&&(r.commit=a[2])),r.full_name=r.owner+\"/\"+r.name,r.query.at?r.ref=r.query.at:r.ref=\"\"),r}B5.stringify=function(e,t){t=t||(e.protocols&&e.protocols.length?e.protocols.join(\"+\"):e.protocol);var r=e.port?\":\"+e.port:\"\",s=e.user||\"git\",a=e.git_suffix?\".git\":\"\";switch(t){case\"ssh\":return r?\"ssh://\"+s+\"@\"+e.resource+r+\"/\"+e.full_name+a:s+\"@\"+e.resource+\":\"+e.full_name+a;case\"git+ssh\":case\"ssh+git\":case\"ftp\":case\"ftps\":return t+\"://\"+s+\"@\"+e.resource+r+\"/\"+e.full_name+a;case\"http\":case\"https\":var n=e.token?Oot(e):e.user&&(e.protocols.includes(\"http\")||e.protocols.includes(\"https\"))?e.user+\"@\":\"\";return t+\"://\"+n+e.resource+r+\"/\"+Lot(e)+a;default:return e.href}};function Oot(e){switch(e.source){case\"bitbucket.org\":return\"x-token-auth:\"+e.token+\"@\";default:return e.token+\"@\"}}function Lot(e){switch(e.source){case\"bitbucket-server\":return\"scm/\"+e.full_name;default:return\"\"+e.full_name}}bde.exports=B5});function tat(e,t){return t===1&&eat.has(e[0])}function nS(e){let t=Array.isArray(e)?e:Ou(e);return t.map((s,a)=>Xot.test(s)?`[${s}]`:$ot.test(s)&&!tat(t,a)?`.${s}`:`[${JSON.stringify(s)}]`).join(\"\").replace(/^\\./,\"\")}function rat(e,t){let r=[];if(t.methodName!==null&&r.push(pe.pretty(e,t.methodName,pe.Type.CODE)),t.file!==null){let s=[];s.push(pe.pretty(e,t.file,pe.Type.PATH)),t.line!==null&&(s.push(pe.pretty(e,t.line,pe.Type.NUMBER)),t.column!==null&&s.push(pe.pretty(e,t.column,pe.Type.NUMBER))),r.push(`(${s.join(pe.pretty(e,\":\",\"grey\"))})`)}return r.join(\" \")}function jT(e,{manifestUpdates:t,reportedErrors:r},{fix:s}={}){let a=new Map,n=new Map,c=[...r.keys()].map(f=>[f,new Map]);for(let[f,p]of[...c,...t]){let h=r.get(f)?.map(x=>({text:x,fixable:!1}))??[],E=!1,C=e.getWorkspaceByCwd(f),S=C.manifest.exportTo({});for(let[x,I]of p){if(I.size>1){let T=[...I].map(([O,U])=>{let Y=pe.pretty(e.configuration,O,pe.Type.INSPECT),te=U.size>0?rat(e.configuration,U.values().next().value):null;return te!==null?`\n${Y} at ${te}`:`\n${Y}`}).join(\"\");h.push({text:`Conflict detected in constraint targeting ${pe.pretty(e.configuration,x,pe.Type.CODE)}; conflicting values are:${T}`,fixable:!1})}else{let[[T]]=I,O=ba(S,x);if(JSON.stringify(O)===JSON.stringify(T))continue;if(!s){let U=typeof O>\"u\"?`Missing field ${pe.pretty(e.configuration,x,pe.Type.CODE)}; expected ${pe.pretty(e.configuration,T,pe.Type.INSPECT)}`:typeof T>\"u\"?`Extraneous field ${pe.pretty(e.configuration,x,pe.Type.CODE)} currently set to ${pe.pretty(e.configuration,O,pe.Type.INSPECT)}`:`Invalid field ${pe.pretty(e.configuration,x,pe.Type.CODE)}; expected ${pe.pretty(e.configuration,T,pe.Type.INSPECT)}, found ${pe.pretty(e.configuration,O,pe.Type.INSPECT)}`;h.push({text:U,fixable:!0});continue}typeof T>\"u\"?u0(S,x):Vd(S,x,T),E=!0}E&&a.set(C,S)}h.length>0&&n.set(C,h)}return{changedWorkspaces:a,remainingErrors:n}}function Gde(e,{configuration:t}){let r={children:[]};for(let[s,a]of e){let n=[];for(let f of a){let p=f.text.split(/\\n/);f.fixable&&(p[0]=`${pe.pretty(t,\"\\u2699\",\"gray\")} ${p[0]}`),n.push({value:pe.tuple(pe.Type.NO_HINT,p[0]),children:p.slice(1).map(h=>({value:pe.tuple(pe.Type.NO_HINT,h)}))})}let c={value:pe.tuple(pe.Type.LOCATOR,s.anchoredLocator),children:Ge.sortMap(n,f=>f.value[1])};r.children.push(c)}return r.children=Ge.sortMap(r.children,s=>s.value[1]),r}var OC,Xot,$ot,eat,iS=Ze(()=>{qe();Jl();OC=class{constructor(t){this.indexedFields=t;this.items=[];this.indexes={};this.clear()}clear(){this.items=[];for(let t of this.indexedFields)this.indexes[t]=new Map}insert(t){this.items.push(t);for(let r of this.indexedFields){let s=Object.hasOwn(t,r)?t[r]:void 0;if(typeof s>\"u\")continue;Ge.getArrayWithDefault(this.indexes[r],s).push(t)}return t}find(t){if(typeof t>\"u\")return this.items;let r=Object.entries(t);if(r.length===0)return this.items;let s=[],a;for(let[c,f]of r){let p=c,h=Object.hasOwn(this.indexes,p)?this.indexes[p]:void 0;if(typeof h>\"u\"){s.push([p,f]);continue}let E=new Set(h.get(f)??[]);if(E.size===0)return[];if(typeof a>\"u\")a=E;else for(let C of a)E.has(C)||a.delete(C);if(a.size===0)break}let n=[...a??[]];return s.length>0&&(n=n.filter(c=>{for(let[f,p]of s)if(!(typeof p<\"u\"?Object.hasOwn(c,f)&&c[f]===p:Object.hasOwn(c,f)===!1))return!1;return!0})),n}},Xot=/^[0-9]+$/,$ot=/^[a-zA-Z0-9_]+$/,eat=new Set([\"scripts\",...Ut.allDependencies])});var qde=G((qqt,H5)=>{var nat;(function(e){var t=function(){return{\"append/2\":[new e.type.Rule(new e.type.Term(\"append\",[new e.type.Var(\"X\"),new e.type.Var(\"L\")]),new e.type.Term(\"foldl\",[new e.type.Term(\"append\",[]),new e.type.Var(\"X\"),new e.type.Term(\"[]\",[]),new e.type.Var(\"L\")]))],\"append/3\":[new e.type.Rule(new e.type.Term(\"append\",[new e.type.Term(\"[]\",[]),new e.type.Var(\"X\"),new e.type.Var(\"X\")]),null),new e.type.Rule(new e.type.Term(\"append\",[new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"T\")]),new e.type.Var(\"X\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"S\")])]),new e.type.Term(\"append\",[new e.type.Var(\"T\"),new e.type.Var(\"X\"),new e.type.Var(\"S\")]))],\"member/2\":[new e.type.Rule(new e.type.Term(\"member\",[new e.type.Var(\"X\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"_\")])]),null),new e.type.Rule(new e.type.Term(\"member\",[new e.type.Var(\"X\"),new e.type.Term(\".\",[new e.type.Var(\"_\"),new e.type.Var(\"Xs\")])]),new e.type.Term(\"member\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]))],\"permutation/2\":[new e.type.Rule(new e.type.Term(\"permutation\",[new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"permutation\",[new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"T\")]),new e.type.Var(\"S\")]),new e.type.Term(\",\",[new e.type.Term(\"permutation\",[new e.type.Var(\"T\"),new e.type.Var(\"P\")]),new e.type.Term(\",\",[new e.type.Term(\"append\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"P\")]),new e.type.Term(\"append\",[new e.type.Var(\"X\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"Y\")]),new e.type.Var(\"S\")])])]))],\"maplist/2\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"X\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"Xs\")])]))],\"maplist/3\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"A\"),new e.type.Var(\"As\")]),new e.type.Term(\".\",[new e.type.Var(\"B\"),new e.type.Var(\"Bs\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"A\"),new e.type.Var(\"B\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"As\"),new e.type.Var(\"Bs\")])]))],\"maplist/4\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"A\"),new e.type.Var(\"As\")]),new e.type.Term(\".\",[new e.type.Var(\"B\"),new e.type.Var(\"Bs\")]),new e.type.Term(\".\",[new e.type.Var(\"C\"),new e.type.Var(\"Cs\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"A\"),new e.type.Var(\"B\"),new e.type.Var(\"C\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"As\"),new e.type.Var(\"Bs\"),new e.type.Var(\"Cs\")])]))],\"maplist/5\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"A\"),new e.type.Var(\"As\")]),new e.type.Term(\".\",[new e.type.Var(\"B\"),new e.type.Var(\"Bs\")]),new e.type.Term(\".\",[new e.type.Var(\"C\"),new e.type.Var(\"Cs\")]),new e.type.Term(\".\",[new e.type.Var(\"D\"),new e.type.Var(\"Ds\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"A\"),new e.type.Var(\"B\"),new e.type.Var(\"C\"),new e.type.Var(\"D\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"As\"),new e.type.Var(\"Bs\"),new e.type.Var(\"Cs\"),new e.type.Var(\"Ds\")])]))],\"maplist/6\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"A\"),new e.type.Var(\"As\")]),new e.type.Term(\".\",[new e.type.Var(\"B\"),new e.type.Var(\"Bs\")]),new e.type.Term(\".\",[new e.type.Var(\"C\"),new e.type.Var(\"Cs\")]),new e.type.Term(\".\",[new e.type.Var(\"D\"),new e.type.Var(\"Ds\")]),new e.type.Term(\".\",[new e.type.Var(\"E\"),new e.type.Var(\"Es\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"A\"),new e.type.Var(\"B\"),new e.type.Var(\"C\"),new e.type.Var(\"D\"),new e.type.Var(\"E\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"As\"),new e.type.Var(\"Bs\"),new e.type.Var(\"Cs\"),new e.type.Var(\"Ds\"),new e.type.Var(\"Es\")])]))],\"maplist/7\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"A\"),new e.type.Var(\"As\")]),new e.type.Term(\".\",[new e.type.Var(\"B\"),new e.type.Var(\"Bs\")]),new e.type.Term(\".\",[new e.type.Var(\"C\"),new e.type.Var(\"Cs\")]),new e.type.Term(\".\",[new e.type.Var(\"D\"),new e.type.Var(\"Ds\")]),new e.type.Term(\".\",[new e.type.Var(\"E\"),new e.type.Var(\"Es\")]),new e.type.Term(\".\",[new e.type.Var(\"F\"),new e.type.Var(\"Fs\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"A\"),new e.type.Var(\"B\"),new e.type.Var(\"C\"),new e.type.Var(\"D\"),new e.type.Var(\"E\"),new e.type.Var(\"F\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"As\"),new e.type.Var(\"Bs\"),new e.type.Var(\"Cs\"),new e.type.Var(\"Ds\"),new e.type.Var(\"Es\"),new e.type.Var(\"Fs\")])]))],\"maplist/8\":[new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"A\"),new e.type.Var(\"As\")]),new e.type.Term(\".\",[new e.type.Var(\"B\"),new e.type.Var(\"Bs\")]),new e.type.Term(\".\",[new e.type.Var(\"C\"),new e.type.Var(\"Cs\")]),new e.type.Term(\".\",[new e.type.Var(\"D\"),new e.type.Var(\"Ds\")]),new e.type.Term(\".\",[new e.type.Var(\"E\"),new e.type.Var(\"Es\")]),new e.type.Term(\".\",[new e.type.Var(\"F\"),new e.type.Var(\"Fs\")]),new e.type.Term(\".\",[new e.type.Var(\"G\"),new e.type.Var(\"Gs\")])]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P\"),new e.type.Var(\"A\"),new e.type.Var(\"B\"),new e.type.Var(\"C\"),new e.type.Var(\"D\"),new e.type.Var(\"E\"),new e.type.Var(\"F\"),new e.type.Var(\"G\")]),new e.type.Term(\"maplist\",[new e.type.Var(\"P\"),new e.type.Var(\"As\"),new e.type.Var(\"Bs\"),new e.type.Var(\"Cs\"),new e.type.Var(\"Ds\"),new e.type.Var(\"Es\"),new e.type.Var(\"Fs\"),new e.type.Var(\"Gs\")])]))],\"include/3\":[new e.type.Rule(new e.type.Term(\"include\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"include\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"T\")]),new e.type.Var(\"L\")]),new e.type.Term(\",\",[new e.type.Term(\"=..\",[new e.type.Var(\"P\"),new e.type.Var(\"A\")]),new e.type.Term(\",\",[new e.type.Term(\"append\",[new e.type.Var(\"A\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Term(\"[]\",[])]),new e.type.Var(\"B\")]),new e.type.Term(\",\",[new e.type.Term(\"=..\",[new e.type.Var(\"F\"),new e.type.Var(\"B\")]),new e.type.Term(\",\",[new e.type.Term(\";\",[new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"F\")]),new e.type.Term(\",\",[new e.type.Term(\"=\",[new e.type.Var(\"L\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"S\")])]),new e.type.Term(\"!\",[])])]),new e.type.Term(\"=\",[new e.type.Var(\"L\"),new e.type.Var(\"S\")])]),new e.type.Term(\"include\",[new e.type.Var(\"P\"),new e.type.Var(\"T\"),new e.type.Var(\"S\")])])])])]))],\"exclude/3\":[new e.type.Rule(new e.type.Term(\"exclude\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Term(\"[]\",[])]),null),new e.type.Rule(new e.type.Term(\"exclude\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"T\")]),new e.type.Var(\"S\")]),new e.type.Term(\",\",[new e.type.Term(\"exclude\",[new e.type.Var(\"P\"),new e.type.Var(\"T\"),new e.type.Var(\"E\")]),new e.type.Term(\",\",[new e.type.Term(\"=..\",[new e.type.Var(\"P\"),new e.type.Var(\"L\")]),new e.type.Term(\",\",[new e.type.Term(\"append\",[new e.type.Var(\"L\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Term(\"[]\",[])]),new e.type.Var(\"Q\")]),new e.type.Term(\",\",[new e.type.Term(\"=..\",[new e.type.Var(\"R\"),new e.type.Var(\"Q\")]),new e.type.Term(\";\",[new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"R\")]),new e.type.Term(\",\",[new e.type.Term(\"!\",[]),new e.type.Term(\"=\",[new e.type.Var(\"S\"),new e.type.Var(\"E\")])])]),new e.type.Term(\"=\",[new e.type.Var(\"S\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"E\")])])])])])])]))],\"foldl/4\":[new e.type.Rule(new e.type.Term(\"foldl\",[new e.type.Var(\"_\"),new e.type.Term(\"[]\",[]),new e.type.Var(\"I\"),new e.type.Var(\"I\")]),null),new e.type.Rule(new e.type.Term(\"foldl\",[new e.type.Var(\"P\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Var(\"T\")]),new e.type.Var(\"I\"),new e.type.Var(\"R\")]),new e.type.Term(\",\",[new e.type.Term(\"=..\",[new e.type.Var(\"P\"),new e.type.Var(\"L\")]),new e.type.Term(\",\",[new e.type.Term(\"append\",[new e.type.Var(\"L\"),new e.type.Term(\".\",[new e.type.Var(\"I\"),new e.type.Term(\".\",[new e.type.Var(\"H\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Term(\"[]\",[])])])]),new e.type.Var(\"L2\")]),new e.type.Term(\",\",[new e.type.Term(\"=..\",[new e.type.Var(\"P2\"),new e.type.Var(\"L2\")]),new e.type.Term(\",\",[new e.type.Term(\"call\",[new e.type.Var(\"P2\")]),new e.type.Term(\"foldl\",[new e.type.Var(\"P\"),new e.type.Var(\"T\"),new e.type.Var(\"X\"),new e.type.Var(\"R\")])])])])]))],\"select/3\":[new e.type.Rule(new e.type.Term(\"select\",[new e.type.Var(\"E\"),new e.type.Term(\".\",[new e.type.Var(\"E\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"Xs\")]),null),new e.type.Rule(new e.type.Term(\"select\",[new e.type.Var(\"E\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Ys\")])]),new e.type.Term(\"select\",[new e.type.Var(\"E\"),new e.type.Var(\"Xs\"),new e.type.Var(\"Ys\")]))],\"sum_list/2\":[new e.type.Rule(new e.type.Term(\"sum_list\",[new e.type.Term(\"[]\",[]),new e.type.Num(0,!1)]),null),new e.type.Rule(new e.type.Term(\"sum_list\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"S\")]),new e.type.Term(\",\",[new e.type.Term(\"sum_list\",[new e.type.Var(\"Xs\"),new e.type.Var(\"Y\")]),new e.type.Term(\"is\",[new e.type.Var(\"S\"),new e.type.Term(\"+\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\")])])]))],\"max_list/2\":[new e.type.Rule(new e.type.Term(\"max_list\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Term(\"[]\",[])]),new e.type.Var(\"X\")]),null),new e.type.Rule(new e.type.Term(\"max_list\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"S\")]),new e.type.Term(\",\",[new e.type.Term(\"max_list\",[new e.type.Var(\"Xs\"),new e.type.Var(\"Y\")]),new e.type.Term(\";\",[new e.type.Term(\",\",[new e.type.Term(\">=\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\")]),new e.type.Term(\",\",[new e.type.Term(\"=\",[new e.type.Var(\"S\"),new e.type.Var(\"X\")]),new e.type.Term(\"!\",[])])]),new e.type.Term(\"=\",[new e.type.Var(\"S\"),new e.type.Var(\"Y\")])])]))],\"min_list/2\":[new e.type.Rule(new e.type.Term(\"min_list\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Term(\"[]\",[])]),new e.type.Var(\"X\")]),null),new e.type.Rule(new e.type.Term(\"min_list\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"S\")]),new e.type.Term(\",\",[new e.type.Term(\"min_list\",[new e.type.Var(\"Xs\"),new e.type.Var(\"Y\")]),new e.type.Term(\";\",[new e.type.Term(\",\",[new e.type.Term(\"=<\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\")]),new e.type.Term(\",\",[new e.type.Term(\"=\",[new e.type.Var(\"S\"),new e.type.Var(\"X\")]),new e.type.Term(\"!\",[])])]),new e.type.Term(\"=\",[new e.type.Var(\"S\"),new e.type.Var(\"Y\")])])]))],\"prod_list/2\":[new e.type.Rule(new e.type.Term(\"prod_list\",[new e.type.Term(\"[]\",[]),new e.type.Num(1,!1)]),null),new e.type.Rule(new e.type.Term(\"prod_list\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"S\")]),new e.type.Term(\",\",[new e.type.Term(\"prod_list\",[new e.type.Var(\"Xs\"),new e.type.Var(\"Y\")]),new e.type.Term(\"is\",[new e.type.Var(\"S\"),new e.type.Term(\"*\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\")])])]))],\"last/2\":[new e.type.Rule(new e.type.Term(\"last\",[new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Term(\"[]\",[])]),new e.type.Var(\"X\")]),null),new e.type.Rule(new e.type.Term(\"last\",[new e.type.Term(\".\",[new e.type.Var(\"_\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"X\")]),new e.type.Term(\"last\",[new e.type.Var(\"Xs\"),new e.type.Var(\"X\")]))],\"prefix/2\":[new e.type.Rule(new e.type.Term(\"prefix\",[new e.type.Var(\"Part\"),new e.type.Var(\"Whole\")]),new e.type.Term(\"append\",[new e.type.Var(\"Part\"),new e.type.Var(\"_\"),new e.type.Var(\"Whole\")]))],\"nth0/3\":[new e.type.Rule(new e.type.Term(\"nth0\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\")]),new e.type.Term(\";\",[new e.type.Term(\"->\",[new e.type.Term(\"var\",[new e.type.Var(\"X\")]),new e.type.Term(\"nth\",[new e.type.Num(0,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"_\")])]),new e.type.Term(\",\",[new e.type.Term(\">=\",[new e.type.Var(\"X\"),new e.type.Num(0,!1)]),new e.type.Term(\",\",[new e.type.Term(\"nth\",[new e.type.Num(0,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"_\")]),new e.type.Term(\"!\",[])])])]))],\"nth1/3\":[new e.type.Rule(new e.type.Term(\"nth1\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\")]),new e.type.Term(\";\",[new e.type.Term(\"->\",[new e.type.Term(\"var\",[new e.type.Var(\"X\")]),new e.type.Term(\"nth\",[new e.type.Num(1,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"_\")])]),new e.type.Term(\",\",[new e.type.Term(\">\",[new e.type.Var(\"X\"),new e.type.Num(0,!1)]),new e.type.Term(\",\",[new e.type.Term(\"nth\",[new e.type.Num(1,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"_\")]),new e.type.Term(\"!\",[])])])]))],\"nth0/4\":[new e.type.Rule(new e.type.Term(\"nth0\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"W\")]),new e.type.Term(\";\",[new e.type.Term(\"->\",[new e.type.Term(\"var\",[new e.type.Var(\"X\")]),new e.type.Term(\"nth\",[new e.type.Num(0,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"W\")])]),new e.type.Term(\",\",[new e.type.Term(\">=\",[new e.type.Var(\"X\"),new e.type.Num(0,!1)]),new e.type.Term(\",\",[new e.type.Term(\"nth\",[new e.type.Num(0,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"W\")]),new e.type.Term(\"!\",[])])])]))],\"nth1/4\":[new e.type.Rule(new e.type.Term(\"nth1\",[new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"W\")]),new e.type.Term(\";\",[new e.type.Term(\"->\",[new e.type.Term(\"var\",[new e.type.Var(\"X\")]),new e.type.Term(\"nth\",[new e.type.Num(1,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"W\")])]),new e.type.Term(\",\",[new e.type.Term(\">\",[new e.type.Var(\"X\"),new e.type.Num(0,!1)]),new e.type.Term(\",\",[new e.type.Term(\"nth\",[new e.type.Num(1,!1),new e.type.Var(\"X\"),new e.type.Var(\"Y\"),new e.type.Var(\"Z\"),new e.type.Var(\"W\")]),new e.type.Term(\"!\",[])])])]))],\"nth/5\":[new e.type.Rule(new e.type.Term(\"nth\",[new e.type.Var(\"N\"),new e.type.Var(\"N\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),null),new e.type.Rule(new e.type.Term(\"nth\",[new e.type.Var(\"N\"),new e.type.Var(\"O\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Xs\")]),new e.type.Var(\"Y\"),new e.type.Term(\".\",[new e.type.Var(\"X\"),new e.type.Var(\"Ys\")])]),new e.type.Term(\",\",[new e.type.Term(\"is\",[new e.type.Var(\"M\"),new e.type.Term(\"+\",[new e.type.Var(\"N\"),new e.type.Num(1,!1)])]),new e.type.Term(\"nth\",[new e.type.Var(\"M\"),new e.type.Var(\"O\"),new e.type.Var(\"Xs\"),new e.type.Var(\"Y\"),new e.type.Var(\"Ys\")])]))],\"length/2\":function(s,a,n){var c=n.args[0],f=n.args[1];if(!e.type.is_variable(f)&&!e.type.is_integer(f))s.throw_error(e.error.type(\"integer\",f,n.indicator));else if(e.type.is_integer(f)&&f.value<0)s.throw_error(e.error.domain(\"not_less_than_zero\",f,n.indicator));else{var p=new e.type.Term(\"length\",[c,new e.type.Num(0,!1),f]);e.type.is_integer(f)&&(p=new e.type.Term(\",\",[p,new e.type.Term(\"!\",[])])),s.prepend([new e.type.State(a.goal.replace(p),a.substitution,a)])}},\"length/3\":[new e.type.Rule(new e.type.Term(\"length\",[new e.type.Term(\"[]\",[]),new e.type.Var(\"N\"),new e.type.Var(\"N\")]),null),new e.type.Rule(new e.type.Term(\"length\",[new e.type.Term(\".\",[new e.type.Var(\"_\"),new e.type.Var(\"X\")]),new e.type.Var(\"A\"),new e.type.Var(\"N\")]),new e.type.Term(\",\",[new e.type.Term(\"succ\",[new e.type.Var(\"A\"),new e.type.Var(\"B\")]),new e.type.Term(\"length\",[new e.type.Var(\"X\"),new e.type.Var(\"B\"),new e.type.Var(\"N\")])]))],\"replicate/3\":function(s,a,n){var c=n.args[0],f=n.args[1],p=n.args[2];if(e.type.is_variable(f))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_integer(f))s.throw_error(e.error.type(\"integer\",f,n.indicator));else if(f.value<0)s.throw_error(e.error.domain(\"not_less_than_zero\",f,n.indicator));else if(!e.type.is_variable(p)&&!e.type.is_list(p))s.throw_error(e.error.type(\"list\",p,n.indicator));else{for(var h=new e.type.Term(\"[]\"),E=0;E<f.value;E++)h=new e.type.Term(\".\",[c,h]);s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[h,p])),a.substitution,a)])}},\"sort/2\":function(s,a,n){var c=n.args[0],f=n.args[1];if(e.type.is_variable(c))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_variable(f)&&!e.type.is_fully_list(f))s.throw_error(e.error.type(\"list\",f,n.indicator));else{for(var p=[],h=c;h.indicator===\"./2\";)p.push(h.args[0]),h=h.args[1];if(e.type.is_variable(h))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_empty_list(h))s.throw_error(e.error.type(\"list\",c,n.indicator));else{for(var E=p.sort(e.compare),C=E.length-1;C>0;C--)E[C].equals(E[C-1])&&E.splice(C,1);for(var S=new e.type.Term(\"[]\"),C=E.length-1;C>=0;C--)S=new e.type.Term(\".\",[E[C],S]);s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[S,f])),a.substitution,a)])}}},\"msort/2\":function(s,a,n){var c=n.args[0],f=n.args[1];if(e.type.is_variable(c))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_variable(f)&&!e.type.is_fully_list(f))s.throw_error(e.error.type(\"list\",f,n.indicator));else{for(var p=[],h=c;h.indicator===\"./2\";)p.push(h.args[0]),h=h.args[1];if(e.type.is_variable(h))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_empty_list(h))s.throw_error(e.error.type(\"list\",c,n.indicator));else{for(var E=p.sort(e.compare),C=new e.type.Term(\"[]\"),S=E.length-1;S>=0;S--)C=new e.type.Term(\".\",[E[S],C]);s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[C,f])),a.substitution,a)])}}},\"keysort/2\":function(s,a,n){var c=n.args[0],f=n.args[1];if(e.type.is_variable(c))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_variable(f)&&!e.type.is_fully_list(f))s.throw_error(e.error.type(\"list\",f,n.indicator));else{for(var p=[],h,E=c;E.indicator===\"./2\";){if(h=E.args[0],e.type.is_variable(h)){s.throw_error(e.error.instantiation(n.indicator));return}else if(!e.type.is_term(h)||h.indicator!==\"-/2\"){s.throw_error(e.error.type(\"pair\",h,n.indicator));return}h.args[0].pair=h.args[1],p.push(h.args[0]),E=E.args[1]}if(e.type.is_variable(E))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_empty_list(E))s.throw_error(e.error.type(\"list\",c,n.indicator));else{for(var C=p.sort(e.compare),S=new e.type.Term(\"[]\"),x=C.length-1;x>=0;x--)S=new e.type.Term(\".\",[new e.type.Term(\"-\",[C[x],C[x].pair]),S]),delete C[x].pair;s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[S,f])),a.substitution,a)])}}},\"take/3\":function(s,a,n){var c=n.args[0],f=n.args[1],p=n.args[2];if(e.type.is_variable(f)||e.type.is_variable(c))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_list(f))s.throw_error(e.error.type(\"list\",f,n.indicator));else if(!e.type.is_integer(c))s.throw_error(e.error.type(\"integer\",c,n.indicator));else if(!e.type.is_variable(p)&&!e.type.is_list(p))s.throw_error(e.error.type(\"list\",p,n.indicator));else{for(var h=c.value,E=[],C=f;h>0&&C.indicator===\"./2\";)E.push(C.args[0]),C=C.args[1],h--;if(h===0){for(var S=new e.type.Term(\"[]\"),h=E.length-1;h>=0;h--)S=new e.type.Term(\".\",[E[h],S]);s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[S,p])),a.substitution,a)])}}},\"drop/3\":function(s,a,n){var c=n.args[0],f=n.args[1],p=n.args[2];if(e.type.is_variable(f)||e.type.is_variable(c))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_list(f))s.throw_error(e.error.type(\"list\",f,n.indicator));else if(!e.type.is_integer(c))s.throw_error(e.error.type(\"integer\",c,n.indicator));else if(!e.type.is_variable(p)&&!e.type.is_list(p))s.throw_error(e.error.type(\"list\",p,n.indicator));else{for(var h=c.value,E=[],C=f;h>0&&C.indicator===\"./2\";)E.push(C.args[0]),C=C.args[1],h--;h===0&&s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[C,p])),a.substitution,a)])}},\"reverse/2\":function(s,a,n){var c=n.args[0],f=n.args[1],p=e.type.is_instantiated_list(c),h=e.type.is_instantiated_list(f);if(e.type.is_variable(c)&&e.type.is_variable(f))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_variable(c)&&!e.type.is_fully_list(c))s.throw_error(e.error.type(\"list\",c,n.indicator));else if(!e.type.is_variable(f)&&!e.type.is_fully_list(f))s.throw_error(e.error.type(\"list\",f,n.indicator));else if(!p&&!h)s.throw_error(e.error.instantiation(n.indicator));else{for(var E=p?c:f,C=new e.type.Term(\"[]\",[]);E.indicator===\"./2\";)C=new e.type.Term(\".\",[E.args[0],C]),E=E.args[1];s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[C,p?f:c])),a.substitution,a)])}},\"list_to_set/2\":function(s,a,n){var c=n.args[0],f=n.args[1];if(e.type.is_variable(c))s.throw_error(e.error.instantiation(n.indicator));else{for(var p=c,h=[];p.indicator===\"./2\";)h.push(p.args[0]),p=p.args[1];if(e.type.is_variable(p))s.throw_error(e.error.instantiation(n.indicator));else if(!e.type.is_term(p)||p.indicator!==\"[]/0\")s.throw_error(e.error.type(\"list\",c,n.indicator));else{for(var E=[],C=new e.type.Term(\"[]\",[]),S,x=0;x<h.length;x++){S=!1;for(var I=0;I<E.length&&!S;I++)S=e.compare(h[x],E[I])===0;S||E.push(h[x])}for(x=E.length-1;x>=0;x--)C=new e.type.Term(\".\",[E[x],C]);s.prepend([new e.type.State(a.goal.replace(new e.type.Term(\"=\",[f,C])),a.substitution,a)])}}}}},r=[\"append/2\",\"append/3\",\"member/2\",\"permutation/2\",\"maplist/2\",\"maplist/3\",\"maplist/4\",\"maplist/5\",\"maplist/6\",\"maplist/7\",\"maplist/8\",\"include/3\",\"exclude/3\",\"foldl/4\",\"sum_list/2\",\"max_list/2\",\"min_list/2\",\"prod_list/2\",\"last/2\",\"prefix/2\",\"nth0/3\",\"nth1/3\",\"nth0/4\",\"nth1/4\",\"length/2\",\"replicate/3\",\"select/3\",\"sort/2\",\"msort/2\",\"keysort/2\",\"take/3\",\"drop/3\",\"reverse/2\",\"list_to_set/2\"];typeof H5<\"u\"?H5.exports=function(s){e=s,new e.type.Module(\"lists\",t(),r)}:new e.type.Module(\"lists\",t(),r)})(nat)});var sme=G($r=>{\"use strict\";var km=process.platform===\"win32\",j5=\"aes-256-cbc\",iat=\"sha256\",Yde=\"The current environment doesn't support interactive reading from TTY.\",ai=Ie(\"fs\"),Wde=process.binding(\"tty_wrap\").TTY,q5=Ie(\"child_process\"),W0=Ie(\"path\"),W5={prompt:\"> \",hideEchoBack:!1,mask:\"*\",limit:[],limitMessage:\"Input another, please.$<( [)limit(])>\",defaultInput:\"\",trueValue:[],falseValue:[],caseSensitive:!1,keepWhitespace:!1,encoding:\"utf8\",bufferSize:1024,print:void 0,history:!0,cd:!1,phContent:void 0,preCheck:void 0},Jp=\"none\",ef,MC,Vde=!1,q0,qT,G5,sat=0,z5=\"\",xm=[],WT,Kde=!1,V5=!1,sS=!1;function Jde(e){function t(r){return r.replace(/[^\\w\\u0080-\\uFFFF]/g,function(s){return\"#\"+s.charCodeAt(0)+\";\"})}return qT.concat(function(r){var s=[];return Object.keys(r).forEach(function(a){r[a]===\"boolean\"?e[a]&&s.push(\"--\"+a):r[a]===\"string\"&&e[a]&&s.push(\"--\"+a,t(e[a]))}),s}({display:\"string\",displayOnly:\"boolean\",keyIn:\"boolean\",hideEchoBack:\"boolean\",mask:\"string\",limit:\"string\",caseSensitive:\"boolean\"}))}function oat(e,t){function r(U){var Y,te=\"\",ie;for(G5=G5||Ie(\"os\").tmpdir();;){Y=W0.join(G5,U+te);try{ie=ai.openSync(Y,\"wx\")}catch(ue){if(ue.code===\"EEXIST\"){te++;continue}else throw ue}ai.closeSync(ie);break}return Y}var s,a,n,c={},f,p,h=r(\"readline-sync.stdout\"),E=r(\"readline-sync.stderr\"),C=r(\"readline-sync.exit\"),S=r(\"readline-sync.done\"),x=Ie(\"crypto\"),I,T,O;I=x.createHash(iat),I.update(\"\"+process.pid+sat+++Math.random()),O=I.digest(\"hex\"),T=x.createDecipher(j5,O),s=Jde(e),km?(a=process.env.ComSpec||\"cmd.exe\",process.env.Q='\"',n=[\"/V:ON\",\"/S\",\"/C\",\"(%Q%\"+a+\"%Q% /V:ON /S /C %Q%%Q%\"+q0+\"%Q%\"+s.map(function(U){return\" %Q%\"+U+\"%Q%\"}).join(\"\")+\" & (echo !ERRORLEVEL!)>%Q%\"+C+\"%Q%%Q%) 2>%Q%\"+E+\"%Q% |%Q%\"+process.execPath+\"%Q% %Q%\"+__dirname+\"\\\\encrypt.js%Q% %Q%\"+j5+\"%Q% %Q%\"+O+\"%Q% >%Q%\"+h+\"%Q% & (echo 1)>%Q%\"+S+\"%Q%\"]):(a=\"/bin/sh\",n=[\"-c\",'(\"'+q0+'\"'+s.map(function(U){return\" '\"+U.replace(/'/g,\"'\\\\''\")+\"'\"}).join(\"\")+'; echo $?>\"'+C+'\") 2>\"'+E+'\" |\"'+process.execPath+'\" \"'+__dirname+'/encrypt.js\" \"'+j5+'\" \"'+O+'\" >\"'+h+'\"; echo 1 >\"'+S+'\"']),sS&&sS(\"_execFileSync\",s);try{q5.spawn(a,n,t)}catch(U){c.error=new Error(U.message),c.error.method=\"_execFileSync - spawn\",c.error.program=a,c.error.args=n}for(;ai.readFileSync(S,{encoding:e.encoding}).trim()!==\"1\";);return(f=ai.readFileSync(C,{encoding:e.encoding}).trim())===\"0\"?c.input=T.update(ai.readFileSync(h,{encoding:\"binary\"}),\"hex\",e.encoding)+T.final(e.encoding):(p=ai.readFileSync(E,{encoding:e.encoding}).trim(),c.error=new Error(Yde+(p?`\n`+p:\"\")),c.error.method=\"_execFileSync\",c.error.program=a,c.error.args=n,c.error.extMessage=p,c.error.exitCode=+f),ai.unlinkSync(h),ai.unlinkSync(E),ai.unlinkSync(C),ai.unlinkSync(S),c}function aat(e){var t,r={},s,a={env:process.env,encoding:e.encoding};if(q0||(km?process.env.PSModulePath?(q0=\"powershell.exe\",qT=[\"-ExecutionPolicy\",\"Bypass\",\"-File\",__dirname+\"\\\\read.ps1\"]):(q0=\"cscript.exe\",qT=[\"//nologo\",__dirname+\"\\\\read.cs.js\"]):(q0=\"/bin/sh\",qT=[__dirname+\"/read.sh\"])),km&&!process.env.PSModulePath&&(a.stdio=[process.stdin]),q5.execFileSync){t=Jde(e),sS&&sS(\"execFileSync\",t);try{r.input=q5.execFileSync(q0,t,a)}catch(n){s=n.stderr?(n.stderr+\"\").trim():\"\",r.error=new Error(Yde+(s?`\n`+s:\"\")),r.error.method=\"execFileSync\",r.error.program=q0,r.error.args=t,r.error.extMessage=s,r.error.exitCode=n.status,r.error.code=n.code,r.error.signal=n.signal}}else r=oat(e,a);return r.error||(r.input=r.input.replace(/^\\s*'|'\\s*$/g,\"\"),e.display=\"\"),r}function Y5(e){var t=\"\",r=e.display,s=!e.display&&e.keyIn&&e.hideEchoBack&&!e.mask;function a(){var n=aat(e);if(n.error)throw n.error;return n.input}return V5&&V5(e),function(){var n,c,f;function p(){return n||(n=process.binding(\"fs\"),c=process.binding(\"constants\")),n}if(typeof Jp==\"string\")if(Jp=null,km){if(f=function(h){var E=h.replace(/^\\D+/,\"\").split(\".\"),C=0;return(E[0]=+E[0])&&(C+=E[0]*1e4),(E[1]=+E[1])&&(C+=E[1]*100),(E[2]=+E[2])&&(C+=E[2]),C}(process.version),!(f>=20302&&f<40204||f>=5e4&&f<50100||f>=50600&&f<60200)&&process.stdin.isTTY)process.stdin.pause(),Jp=process.stdin.fd,MC=process.stdin._handle;else try{Jp=p().open(\"CONIN$\",c.O_RDWR,parseInt(\"0666\",8)),MC=new Wde(Jp,!0)}catch{}if(process.stdout.isTTY)ef=process.stdout.fd;else{try{ef=ai.openSync(\"\\\\\\\\.\\\\CON\",\"w\")}catch{}if(typeof ef!=\"number\")try{ef=p().open(\"CONOUT$\",c.O_RDWR,parseInt(\"0666\",8))}catch{}}}else{if(process.stdin.isTTY){process.stdin.pause();try{Jp=ai.openSync(\"/dev/tty\",\"r\"),MC=process.stdin._handle}catch{}}else try{Jp=ai.openSync(\"/dev/tty\",\"r\"),MC=new Wde(Jp,!1)}catch{}if(process.stdout.isTTY)ef=process.stdout.fd;else try{ef=ai.openSync(\"/dev/tty\",\"w\")}catch{}}}(),function(){var n,c,f=!e.hideEchoBack&&!e.keyIn,p,h,E,C,S;WT=\"\";function x(I){return I===Vde?!0:MC.setRawMode(I)!==0?!1:(Vde=I,!0)}if(Kde||!MC||typeof ef!=\"number\"&&(e.display||!f)){t=a();return}if(e.display&&(ai.writeSync(ef,e.display),e.display=\"\"),!e.displayOnly){if(!x(!f)){t=a();return}for(h=e.keyIn?1:e.bufferSize,p=Buffer.allocUnsafe&&Buffer.alloc?Buffer.alloc(h):new Buffer(h),e.keyIn&&e.limit&&(c=new RegExp(\"[^\"+e.limit+\"]\",\"g\"+(e.caseSensitive?\"\":\"i\")));;){E=0;try{E=ai.readSync(Jp,p,0,h)}catch(I){if(I.code!==\"EOF\"){x(!1),t+=a();return}}if(E>0?(C=p.toString(e.encoding,0,E),WT+=C):(C=`\n`,WT+=\"\\0\"),C&&typeof(S=(C.match(/^(.*?)[\\r\\n]/)||[])[1])==\"string\"&&(C=S,n=!0),C&&(C=C.replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/g,\"\")),C&&c&&(C=C.replace(c,\"\")),C&&(f||(e.hideEchoBack?e.mask&&ai.writeSync(ef,new Array(C.length+1).join(e.mask)):ai.writeSync(ef,C)),t+=C),!e.keyIn&&n||e.keyIn&&t.length>=h)break}!f&&!s&&ai.writeSync(ef,`\n`),x(!1)}}(),e.print&&!s&&e.print(r+(e.displayOnly?\"\":(e.hideEchoBack?new Array(t.length+1).join(e.mask):t)+`\n`),e.encoding),e.displayOnly?\"\":z5=e.keepWhitespace||e.keyIn?t:t.trim()}function lat(e,t){var r=[];function s(a){a!=null&&(Array.isArray(a)?a.forEach(s):(!t||t(a))&&r.push(a))}return s(e),r}function Z5(e){return e.replace(/[\\x00-\\x7f]/g,function(t){return\"\\\\x\"+(\"00\"+t.charCodeAt().toString(16)).substr(-2)})}function $s(){var e=Array.prototype.slice.call(arguments),t,r;return e.length&&typeof e[0]==\"boolean\"&&(r=e.shift(),r&&(t=Object.keys(W5),e.unshift(W5))),e.reduce(function(s,a){return a==null||(a.hasOwnProperty(\"noEchoBack\")&&!a.hasOwnProperty(\"hideEchoBack\")&&(a.hideEchoBack=a.noEchoBack,delete a.noEchoBack),a.hasOwnProperty(\"noTrim\")&&!a.hasOwnProperty(\"keepWhitespace\")&&(a.keepWhitespace=a.noTrim,delete a.noTrim),r||(t=Object.keys(a)),t.forEach(function(n){var c;if(a.hasOwnProperty(n))switch(c=a[n],n){case\"mask\":case\"limitMessage\":case\"defaultInput\":case\"encoding\":c=c!=null?c+\"\":\"\",c&&n!==\"limitMessage\"&&(c=c.replace(/[\\r\\n]/g,\"\")),s[n]=c;break;case\"bufferSize\":!isNaN(c=parseInt(c,10))&&typeof c==\"number\"&&(s[n]=c);break;case\"displayOnly\":case\"keyIn\":case\"hideEchoBack\":case\"caseSensitive\":case\"keepWhitespace\":case\"history\":case\"cd\":s[n]=!!c;break;case\"limit\":case\"trueValue\":case\"falseValue\":s[n]=lat(c,function(f){var p=typeof f;return p===\"string\"||p===\"number\"||p===\"function\"||f instanceof RegExp}).map(function(f){return typeof f==\"string\"?f.replace(/[\\r\\n]/g,\"\"):f});break;case\"print\":case\"phContent\":case\"preCheck\":s[n]=typeof c==\"function\"?c:void 0;break;case\"prompt\":case\"display\":s[n]=c??\"\";break}})),s},{})}function K5(e,t,r){return t.some(function(s){var a=typeof s;return a===\"string\"?r?e===s:e.toLowerCase()===s.toLowerCase():a===\"number\"?parseFloat(e)===s:a===\"function\"?s(e):s instanceof RegExp?s.test(e):!1})}function X5(e,t){var r=W0.normalize(km?(process.env.HOMEDRIVE||\"\")+(process.env.HOMEPATH||\"\"):process.env.HOME||\"\").replace(/[\\/\\\\]+$/,\"\");return e=W0.normalize(e),t?e.replace(/^~(?=\\/|\\\\|$)/,r):e.replace(new RegExp(\"^\"+Z5(r)+\"(?=\\\\/|\\\\\\\\|$)\",km?\"i\":\"\"),\"~\")}function UC(e,t){var r=\"(?:\\\\(([\\\\s\\\\S]*?)\\\\))?(\\\\w+|.-.)(?:\\\\(([\\\\s\\\\S]*?)\\\\))?\",s=new RegExp(\"(\\\\$)?(\\\\$<\"+r+\">)\",\"g\"),a=new RegExp(\"(\\\\$)?(\\\\$\\\\{\"+r+\"\\\\})\",\"g\");function n(c,f,p,h,E,C){var S;return f||typeof(S=t(E))!=\"string\"?p:S?(h||\"\")+S+(C||\"\"):\"\"}return e.replace(s,n).replace(a,n)}function zde(e,t,r){var s,a=[],n=-1,c=0,f=\"\",p;function h(E,C){return C.length>3?(E.push(C[0]+\"...\"+C[C.length-1]),p=!0):C.length&&(E=E.concat(C)),E}return s=e.reduce(function(E,C){return E.concat((C+\"\").split(\"\"))},[]).reduce(function(E,C){var S,x;return t||(C=C.toLowerCase()),S=/^\\d$/.test(C)?1:/^[A-Z]$/.test(C)?2:/^[a-z]$/.test(C)?3:0,r&&S===0?f+=C:(x=C.charCodeAt(0),S&&S===n&&x===c+1?a.push(C):(E=h(E,a),a=[C],n=S),c=x),E},[]),s=h(s,a),f&&(s.push(f),p=!0),{values:s,suppressed:p}}function Zde(e,t){return e.join(e.length>2?\", \":t?\" / \":\"/\")}function Xde(e,t){var r,s,a={},n;if(t.phContent&&(r=t.phContent(e,t)),typeof r!=\"string\")switch(e){case\"hideEchoBack\":case\"mask\":case\"defaultInput\":case\"caseSensitive\":case\"keepWhitespace\":case\"encoding\":case\"bufferSize\":case\"history\":case\"cd\":r=t.hasOwnProperty(e)?typeof t[e]==\"boolean\"?t[e]?\"on\":\"off\":t[e]+\"\":\"\";break;case\"limit\":case\"trueValue\":case\"falseValue\":s=t[t.hasOwnProperty(e+\"Src\")?e+\"Src\":e],t.keyIn?(a=zde(s,t.caseSensitive),s=a.values):s=s.filter(function(c){var f=typeof c;return f===\"string\"||f===\"number\"}),r=Zde(s,a.suppressed);break;case\"limitCount\":case\"limitCountNotZero\":r=t[t.hasOwnProperty(\"limitSrc\")?\"limitSrc\":\"limit\"].length,r=r||e!==\"limitCountNotZero\"?r+\"\":\"\";break;case\"lastInput\":r=z5;break;case\"cwd\":case\"CWD\":case\"cwdHome\":r=process.cwd(),e===\"CWD\"?r=W0.basename(r):e===\"cwdHome\"&&(r=X5(r));break;case\"date\":case\"time\":case\"localeDate\":case\"localeTime\":r=new Date()[\"to\"+e.replace(/^./,function(c){return c.toUpperCase()})+\"String\"]();break;default:typeof(n=(e.match(/^history_m(\\d+)$/)||[])[1])==\"string\"&&(r=xm[xm.length-n]||\"\")}return r}function $de(e){var t=/^(.)-(.)$/.exec(e),r=\"\",s,a,n,c;if(!t)return null;for(s=t[1].charCodeAt(0),a=t[2].charCodeAt(0),c=s<a?1:-1,n=s;n!==a+c;n+=c)r+=String.fromCharCode(n);return r}function J5(e){var t=new RegExp(/(\\s*)(?:(\"|')(.*?)(?:\\2|$)|(\\S+))/g),r,s=\"\",a=[],n;for(e=e.trim();r=t.exec(e);)n=r[3]||r[4]||\"\",r[1]&&(a.push(s),s=\"\"),s+=n;return s&&a.push(s),a}function eme(e,t){return t.trueValue.length&&K5(e,t.trueValue,t.caseSensitive)?!0:t.falseValue.length&&K5(e,t.falseValue,t.caseSensitive)?!1:e}function tme(e){var t,r,s,a,n,c,f;function p(E){return Xde(E,e)}function h(E){e.display+=(/[^\\r\\n]$/.test(e.display)?`\n`:\"\")+E}for(e.limitSrc=e.limit,e.displaySrc=e.display,e.limit=\"\",e.display=UC(e.display+\"\",p);;){if(t=Y5(e),r=!1,s=\"\",e.defaultInput&&!t&&(t=e.defaultInput),e.history&&((a=/^\\s*\\!(?:\\!|-1)(:p)?\\s*$/.exec(t))?(n=xm[0]||\"\",a[1]?r=!0:t=n,h(n+`\n`),r||(e.displayOnly=!0,Y5(e),e.displayOnly=!1)):t&&t!==xm[xm.length-1]&&(xm=[t])),!r&&e.cd&&t)switch(c=J5(t),c[0].toLowerCase()){case\"cd\":if(c[1])try{process.chdir(X5(c[1],!0))}catch(E){h(E+\"\")}r=!0;break;case\"pwd\":h(process.cwd()),r=!0;break}if(!r&&e.preCheck&&(f=e.preCheck(t,e),t=f.res,f.forceNext&&(r=!0)),!r){if(!e.limitSrc.length||K5(t,e.limitSrc,e.caseSensitive))break;e.limitMessage&&(s=UC(e.limitMessage,p))}h((s?s+`\n`:\"\")+UC(e.displaySrc+\"\",p))}return eme(t,e)}$r._DBG_set_useExt=function(e){Kde=e};$r._DBG_set_checkOptions=function(e){V5=e};$r._DBG_set_checkMethod=function(e){sS=e};$r._DBG_clearHistory=function(){z5=\"\",xm=[]};$r.setDefaultOptions=function(e){return W5=$s(!0,e),$s(!0)};$r.question=function(e,t){return tme($s($s(!0,t),{display:e}))};$r.prompt=function(e){var t=$s(!0,e);return t.display=t.prompt,tme(t)};$r.keyIn=function(e,t){var r=$s($s(!0,t),{display:e,keyIn:!0,keepWhitespace:!0});return r.limitSrc=r.limit.filter(function(s){var a=typeof s;return a===\"string\"||a===\"number\"}).map(function(s){return UC(s+\"\",$de)}),r.limit=Z5(r.limitSrc.join(\"\")),[\"trueValue\",\"falseValue\"].forEach(function(s){r[s]=r[s].reduce(function(a,n){var c=typeof n;return c===\"string\"||c===\"number\"?a=a.concat((n+\"\").split(\"\")):a.push(n),a},[])}),r.display=UC(r.display+\"\",function(s){return Xde(s,r)}),eme(Y5(r),r)};$r.questionEMail=function(e,t){return e==null&&(e=\"Input e-mail address: \"),$r.question(e,$s({hideEchoBack:!1,limit:/^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,limitMessage:\"Input valid e-mail address, please.\",trueValue:null,falseValue:null},t,{keepWhitespace:!1,cd:!1}))};$r.questionNewPassword=function(e,t){var r,s,a,n=$s({hideEchoBack:!0,mask:\"*\",limitMessage:`It can include: $<charlist>\nAnd the length must be: $<length>`,trueValue:null,falseValue:null,caseSensitive:!0},t,{history:!1,cd:!1,phContent:function(x){return x===\"charlist\"?r.text:x===\"length\"?s+\"...\"+a:null}}),c,f,p,h,E,C,S;for(t=t||{},c=UC(t.charlist?t.charlist+\"\":\"$<!-~>\",$de),(isNaN(s=parseInt(t.min,10))||typeof s!=\"number\")&&(s=12),(isNaN(a=parseInt(t.max,10))||typeof a!=\"number\")&&(a=24),h=new RegExp(\"^[\"+Z5(c)+\"]{\"+s+\",\"+a+\"}$\"),r=zde([c],n.caseSensitive,!0),r.text=Zde(r.values,r.suppressed),f=t.confirmMessage!=null?t.confirmMessage:\"Reinput a same one to confirm it: \",p=t.unmatchMessage!=null?t.unmatchMessage:\"It differs from first one. Hit only the Enter key if you want to retry from first one.\",e==null&&(e=\"Input new password: \"),E=n.limitMessage;!S;)n.limit=h,n.limitMessage=E,C=$r.question(e,n),n.limit=[C,\"\"],n.limitMessage=p,S=$r.question(f,n);return C};function rme(e,t,r){var s;function a(n){return s=r(n),!isNaN(s)&&typeof s==\"number\"}return $r.question(e,$s({limitMessage:\"Input valid number, please.\"},t,{limit:a,cd:!1})),s}$r.questionInt=function(e,t){return rme(e,t,function(r){return parseInt(r,10)})};$r.questionFloat=function(e,t){return rme(e,t,parseFloat)};$r.questionPath=function(e,t){var r,s=\"\",a=$s({hideEchoBack:!1,limitMessage:`$<error(\n)>Input valid path, please.$<( Min:)min>$<( Max:)max>`,history:!0,cd:!0},t,{keepWhitespace:!1,limit:function(n){var c,f,p;n=X5(n,!0),s=\"\";function h(E){E.split(/\\/|\\\\/).reduce(function(C,S){var x=W0.resolve(C+=S+W0.sep);if(!ai.existsSync(x))ai.mkdirSync(x);else if(!ai.statSync(x).isDirectory())throw new Error(\"Non directory already exists: \"+x);return C},\"\")}try{if(c=ai.existsSync(n),r=c?ai.realpathSync(n):W0.resolve(n),!t.hasOwnProperty(\"exists\")&&!c||typeof t.exists==\"boolean\"&&t.exists!==c)return s=(c?\"Already exists\":\"No such file or directory\")+\": \"+r,!1;if(!c&&t.create&&(t.isDirectory?h(r):(h(W0.dirname(r)),ai.closeSync(ai.openSync(r,\"w\"))),r=ai.realpathSync(r)),c&&(t.min||t.max||t.isFile||t.isDirectory)){if(f=ai.statSync(r),t.isFile&&!f.isFile())return s=\"Not file: \"+r,!1;if(t.isDirectory&&!f.isDirectory())return s=\"Not directory: \"+r,!1;if(t.min&&f.size<+t.min||t.max&&f.size>+t.max)return s=\"Size \"+f.size+\" is out of range: \"+r,!1}if(typeof t.validate==\"function\"&&(p=t.validate(r))!==!0)return typeof p==\"string\"&&(s=p),!1}catch(E){return s=E+\"\",!1}return!0},phContent:function(n){return n===\"error\"?s:n!==\"min\"&&n!==\"max\"?null:t.hasOwnProperty(n)?t[n]+\"\":\"\"}});return t=t||{},e==null&&(e='Input path (you can \"cd\" and \"pwd\"): '),$r.question(e,a),r};function nme(e,t){var r={},s={};return typeof e==\"object\"?(Object.keys(e).forEach(function(a){typeof e[a]==\"function\"&&(s[t.caseSensitive?a:a.toLowerCase()]=e[a])}),r.preCheck=function(a){var n;return r.args=J5(a),n=r.args[0]||\"\",t.caseSensitive||(n=n.toLowerCase()),r.hRes=n!==\"_\"&&s.hasOwnProperty(n)?s[n].apply(a,r.args.slice(1)):s.hasOwnProperty(\"_\")?s._.apply(a,r.args):null,{res:a,forceNext:!1}},s.hasOwnProperty(\"_\")||(r.limit=function(){var a=r.args[0]||\"\";return t.caseSensitive||(a=a.toLowerCase()),s.hasOwnProperty(a)})):r.preCheck=function(a){return r.args=J5(a),r.hRes=typeof e==\"function\"?e.apply(a,r.args):!0,{res:a,forceNext:!1}},r}$r.promptCL=function(e,t){var r=$s({hideEchoBack:!1,limitMessage:\"Requested command is not available.\",caseSensitive:!1,history:!0},t),s=nme(e,r);return r.limit=s.limit,r.preCheck=s.preCheck,$r.prompt(r),s.args};$r.promptLoop=function(e,t){for(var r=$s({hideEchoBack:!1,trueValue:null,falseValue:null,caseSensitive:!1,history:!0},t);!e($r.prompt(r)););};$r.promptCLLoop=function(e,t){var r=$s({hideEchoBack:!1,limitMessage:\"Requested command is not available.\",caseSensitive:!1,history:!0},t),s=nme(e,r);for(r.limit=s.limit,r.preCheck=s.preCheck;$r.prompt(r),!s.hRes;);};$r.promptSimShell=function(e){return $r.prompt($s({hideEchoBack:!1,history:!0},e,{prompt:function(){return km?\"$<cwd>>\":(process.env.USER||\"\")+(process.env.HOSTNAME?\"@\"+process.env.HOSTNAME.replace(/\\..*$/,\"\"):\"\")+\":$<cwdHome>$ \"}()}))};function ime(e,t,r){var s;return e==null&&(e=\"Are you sure? \"),(!t||t.guide!==!1)&&(e+=\"\")&&(e=e.replace(/\\s*:?\\s*$/,\"\")+\" [y/n]: \"),s=$r.keyIn(e,$s(t,{hideEchoBack:!1,limit:r,trueValue:\"y\",falseValue:\"n\",caseSensitive:!1})),typeof s==\"boolean\"?s:\"\"}$r.keyInYN=function(e,t){return ime(e,t)};$r.keyInYNStrict=function(e,t){return ime(e,t,\"yn\")};$r.keyInPause=function(e,t){e==null&&(e=\"Continue...\"),(!t||t.guide!==!1)&&(e+=\"\")&&(e=e.replace(/\\s+$/,\"\")+\" (Hit any key)\"),$r.keyIn(e,$s({limit:null},t,{hideEchoBack:!0,mask:\"\"}))};$r.keyInSelect=function(e,t,r){var s=$s({hideEchoBack:!1},r,{trueValue:null,falseValue:null,caseSensitive:!1,phContent:function(p){return p===\"itemsCount\"?e.length+\"\":p===\"firstItem\"?(e[0]+\"\").trim():p===\"lastItem\"?(e[e.length-1]+\"\").trim():null}}),a=\"\",n={},c=49,f=`\n`;if(!Array.isArray(e)||!e.length||e.length>35)throw\"`items` must be Array (max length: 35).\";return e.forEach(function(p,h){var E=String.fromCharCode(c);a+=E,n[E]=h,f+=\"[\"+E+\"] \"+(p+\"\").trim()+`\n`,c=c===57?97:c+1}),(!r||r.cancel!==!1)&&(a+=\"0\",n[0]=-1,f+=\"[0] \"+(r&&r.cancel!=null&&typeof r.cancel!=\"boolean\"?(r.cancel+\"\").trim():\"CANCEL\")+`\n`),s.limit=a,f+=`\n`,t==null&&(t=\"Choose one from list: \"),(t+=\"\")&&((!r||r.guide!==!1)&&(t=t.replace(/\\s*:?\\s*$/,\"\")+\" [$<limit>]: \"),f+=t),n[$r.keyIn(f,s).toLowerCase()]};$r.getRawInput=function(){return WT};function oS(e,t){var r;return t.length&&(r={},r[e]=t[0]),$r.setDefaultOptions(r)[e]}$r.setPrint=function(){return oS(\"print\",arguments)};$r.setPrompt=function(){return oS(\"prompt\",arguments)};$r.setEncoding=function(){return oS(\"encoding\",arguments)};$r.setMask=function(){return oS(\"mask\",arguments)};$r.setBufferSize=function(){return oS(\"bufferSize\",arguments)}});var $5=G((Vqt,tc)=>{(function(){var e={major:0,minor:2,patch:66,status:\"beta\"};tau_file_system={files:{},open:function(w,b,y){var F=tau_file_system.files[w];if(!F){if(y===\"read\")return null;F={path:w,text:\"\",type:b,get:function(z,Z){return Z===this.text.length||Z>this.text.length?\"end_of_file\":this.text.substring(Z,Z+z)},put:function(z,Z){return Z===\"end_of_file\"?(this.text+=z,!0):Z===\"past_end_of_file\"?null:(this.text=this.text.substring(0,Z)+z+this.text.substring(Z+z.length),!0)},get_byte:function(z){if(z===\"end_of_stream\")return-1;var Z=Math.floor(z/2);if(this.text.length<=Z)return-1;var $=n(this.text[Math.floor(z/2)],0);return z%2===0?$&255:$/256>>>0},put_byte:function(z,Z){var $=Z===\"end_of_stream\"?this.text.length:Math.floor(Z/2);if(this.text.length<$)return null;var se=this.text.length===$?-1:n(this.text[Math.floor(Z/2)],0);return Z%2===0?(se=se/256>>>0,se=(se&255)<<8|z&255):(se=se&255,se=(z&255)<<8|se&255),this.text.length===$?this.text+=c(se):this.text=this.text.substring(0,$)+c(se)+this.text.substring($+1),!0},flush:function(){return!0},close:function(){var z=tau_file_system.files[this.path];return z?!0:null}},tau_file_system.files[w]=F}return y===\"write\"&&(F.text=\"\"),F}},tau_user_input={buffer:\"\",get:function(w,b){for(var y;tau_user_input.buffer.length<w;)y=window.prompt(),y&&(tau_user_input.buffer+=y);return y=tau_user_input.buffer.substr(0,w),tau_user_input.buffer=tau_user_input.buffer.substr(w),y}},tau_user_output={put:function(w,b){return console.log(w),!0},flush:function(){return!0}},nodejs_file_system={open:function(w,b,y){var F=Ie(\"fs\"),z=F.openSync(w,y[0]);return y===\"read\"&&!F.existsSync(w)?null:{get:function(Z,$){var se=new Buffer(Z);return F.readSync(z,se,0,Z,$),se.toString()},put:function(Z,$){var se=Buffer.from(Z);if($===\"end_of_file\")F.writeSync(z,se);else{if($===\"past_end_of_file\")return null;F.writeSync(z,se,0,se.length,$)}return!0},get_byte:function(Z){return null},put_byte:function(Z,$){return null},flush:function(){return!0},close:function(){return F.closeSync(z),!0}}}},nodejs_user_input={buffer:\"\",get:function(w,b){for(var y,F=sme();nodejs_user_input.buffer.length<w;)nodejs_user_input.buffer+=F.question();return y=nodejs_user_input.buffer.substr(0,w),nodejs_user_input.buffer=nodejs_user_input.buffer.substr(w),y}},nodejs_user_output={put:function(w,b){return process.stdout.write(w),!0},flush:function(){return!0}};var t;Array.prototype.indexOf?t=function(w,b){return w.indexOf(b)}:t=function(w,b){for(var y=w.length,F=0;F<y;F++)if(b===w[F])return F;return-1};var r=function(w,b){if(w.length!==0){for(var y=w[0],F=w.length,z=1;z<F;z++)y=b(y,w[z]);return y}},s;Array.prototype.map?s=function(w,b){return w.map(b)}:s=function(w,b){for(var y=[],F=w.length,z=0;z<F;z++)y.push(b(w[z]));return y};var a;Array.prototype.filter?a=function(w,b){return w.filter(b)}:a=function(w,b){for(var y=[],F=w.length,z=0;z<F;z++)b(w[z])&&y.push(w[z]);return y};var n;String.prototype.codePointAt?n=function(w,b){return w.codePointAt(b)}:n=function(w,b){return w.charCodeAt(b)};var c;String.fromCodePoint?c=function(){return String.fromCodePoint.apply(null,arguments)}:c=function(){return String.fromCharCode.apply(null,arguments)};var f=0,p=1,h=/(\\\\a)|(\\\\b)|(\\\\f)|(\\\\n)|(\\\\r)|(\\\\t)|(\\\\v)|\\\\x([0-9a-fA-F]+)\\\\|\\\\([0-7]+)\\\\|(\\\\\\\\)|(\\\\')|('')|(\\\\\")|(\\\\`)|(\\\\.)|(.)/g,E={\"\\\\a\":7,\"\\\\b\":8,\"\\\\f\":12,\"\\\\n\":10,\"\\\\r\":13,\"\\\\t\":9,\"\\\\v\":11};function C(w){var b=[],y=!1;return w.replace(h,function(F,z,Z,$,se,xe,Fe,ut,Ct,qt,ir,Pt,dn,Pr,Ir,Or,on){switch(!0){case Ct!==void 0:return b.push(parseInt(Ct,16)),\"\";case qt!==void 0:return b.push(parseInt(qt,8)),\"\";case ir!==void 0:case Pt!==void 0:case dn!==void 0:case Pr!==void 0:case Ir!==void 0:return b.push(n(F.substr(1),0)),\"\";case on!==void 0:return b.push(n(on,0)),\"\";case Or!==void 0:y=!0;default:return b.push(E[F]),\"\"}}),y?null:b}function S(w,b){var y=\"\";if(w.length<2)return w;try{w=w.replace(/\\\\([0-7]+)\\\\/g,function($,se){return c(parseInt(se,8))}),w=w.replace(/\\\\x([0-9a-fA-F]+)\\\\/g,function($,se){return c(parseInt(se,16))})}catch{return null}for(var F=0;F<w.length;F++){var z=w.charAt(F),Z=w.charAt(F+1);if(z===b&&Z===b)F++,y+=b;else if(z===\"\\\\\")if([\"a\",\"b\",\"f\",\"n\",\"r\",\"t\",\"v\",\"'\",'\"',\"\\\\\",\"a\",\"\\b\",\"\\f\",`\n`,\"\\r\",\"\t\",\"\\v\"].indexOf(Z)!==-1)switch(F+=1,Z){case\"a\":y+=\"a\";break;case\"b\":y+=\"\\b\";break;case\"f\":y+=\"\\f\";break;case\"n\":y+=`\n`;break;case\"r\":y+=\"\\r\";break;case\"t\":y+=\"\t\";break;case\"v\":y+=\"\\v\";break;case\"'\":y+=\"'\";break;case'\"':y+='\"';break;case\"\\\\\":y+=\"\\\\\";break}else return null;else y+=z}return y}function x(w){for(var b=\"\",y=0;y<w.length;y++)switch(w.charAt(y)){case\"'\":b+=\"\\\\'\";break;case\"\\\\\":b+=\"\\\\\\\\\";break;case\"\\b\":b+=\"\\\\b\";break;case\"\\f\":b+=\"\\\\f\";break;case`\n`:b+=\"\\\\n\";break;case\"\\r\":b+=\"\\\\r\";break;case\"\t\":b+=\"\\\\t\";break;case\"\\v\":b+=\"\\\\v\";break;default:b+=w.charAt(y);break}return b}function I(w){var b=w.substr(2);switch(w.substr(0,2).toLowerCase()){case\"0x\":return parseInt(b,16);case\"0b\":return parseInt(b,2);case\"0o\":return parseInt(b,8);case\"0'\":return C(b)[0];default:return parseFloat(w)}}var T={whitespace:/^\\s*(?:(?:%.*)|(?:\\/\\*(?:\\n|\\r|.)*?\\*\\/)|(?:\\s+))\\s*/,variable:/^(?:[A-Z_][a-zA-Z0-9_]*)/,atom:/^(\\!|,|;|[a-z][0-9a-zA-Z_]*|[#\\$\\&\\*\\+\\-\\.\\/\\:\\<\\=\\>\\?\\@\\^\\~\\\\]+|'(?:[^']*?(?:\\\\(?:x?\\d+)?\\\\)*(?:'')*(?:\\\\')*)*')/,number:/^(?:0o[0-7]+|0x[0-9a-fA-F]+|0b[01]+|0'(?:''|\\\\[abfnrtv\\\\'\"`]|\\\\x?\\d+\\\\|[^\\\\])|\\d+(?:\\.\\d+(?:[eE][+-]?\\d+)?)?)/,string:/^(?:\"([^\"]|\"\"|\\\\\")*\"|`([^`]|``|\\\\`)*`)/,l_brace:/^(?:\\[)/,r_brace:/^(?:\\])/,l_bracket:/^(?:\\{)/,r_bracket:/^(?:\\})/,bar:/^(?:\\|)/,l_paren:/^(?:\\()/,r_paren:/^(?:\\))/};function O(w,b){return w.get_flag(\"char_conversion\").id===\"on\"?b.replace(/./g,function(y){return w.get_char_conversion(y)}):b}function U(w){this.thread=w,this.text=\"\",this.tokens=[]}U.prototype.set_last_tokens=function(w){return this.tokens=w},U.prototype.new_text=function(w){this.text=w,this.tokens=[]},U.prototype.get_tokens=function(w){var b,y=0,F=0,z=0,Z=[],$=!1;if(w){var se=this.tokens[w-1];y=se.len,b=O(this.thread,this.text.substr(se.len)),F=se.line,z=se.start}else b=this.text;if(/^\\s*$/.test(b))return null;for(;b!==\"\";){var xe=[],Fe=!1;if(/^\\n/.exec(b)!==null){F++,z=0,y++,b=b.replace(/\\n/,\"\"),$=!0;continue}for(var ut in T)if(T.hasOwnProperty(ut)){var Ct=T[ut].exec(b);Ct&&xe.push({value:Ct[0],name:ut,matches:Ct})}if(!xe.length)return this.set_last_tokens([{value:b,matches:[],name:\"lexical\",line:F,start:z}]);var se=r(xe,function(Pr,Ir){return Pr.value.length>=Ir.value.length?Pr:Ir});switch(se.start=z,se.line=F,b=b.replace(se.value,\"\"),z+=se.value.length,y+=se.value.length,se.name){case\"atom\":se.raw=se.value,se.value.charAt(0)===\"'\"&&(se.value=S(se.value.substr(1,se.value.length-2),\"'\"),se.value===null&&(se.name=\"lexical\",se.value=\"unknown escape sequence\"));break;case\"number\":se.float=se.value.substring(0,2)!==\"0x\"&&se.value.match(/[.eE]/)!==null&&se.value!==\"0'.\",se.value=I(se.value),se.blank=Fe;break;case\"string\":var qt=se.value.charAt(0);se.value=S(se.value.substr(1,se.value.length-2),qt),se.value===null&&(se.name=\"lexical\",se.value=\"unknown escape sequence\");break;case\"whitespace\":var ir=Z[Z.length-1];ir&&(ir.space=!0),Fe=!0;continue;case\"r_bracket\":Z.length>0&&Z[Z.length-1].name===\"l_bracket\"&&(se=Z.pop(),se.name=\"atom\",se.value=\"{}\",se.raw=\"{}\",se.space=!1);break;case\"r_brace\":Z.length>0&&Z[Z.length-1].name===\"l_brace\"&&(se=Z.pop(),se.name=\"atom\",se.value=\"[]\",se.raw=\"[]\",se.space=!1);break}se.len=y,Z.push(se),Fe=!1}var Pt=this.set_last_tokens(Z);return Pt.length===0?null:Pt};function Y(w,b,y,F,z){if(!b[y])return{type:f,value:P.error.syntax(b[y-1],\"expression expected\",!0)};var Z;if(F===\"0\"){var $=b[y];switch($.name){case\"number\":return{type:p,len:y+1,value:new P.type.Num($.value,$.float)};case\"variable\":return{type:p,len:y+1,value:new P.type.Var($.value)};case\"string\":var se;switch(w.get_flag(\"double_quotes\").id){case\"atom\":se=new _($.value,[]);break;case\"codes\":se=new _(\"[]\",[]);for(var xe=$.value.length-1;xe>=0;xe--)se=new _(\".\",[new P.type.Num(n($.value,xe),!1),se]);break;case\"chars\":se=new _(\"[]\",[]);for(var xe=$.value.length-1;xe>=0;xe--)se=new _(\".\",[new P.type.Term($.value.charAt(xe),[]),se]);break}return{type:p,len:y+1,value:se};case\"l_paren\":var Pt=Y(w,b,y+1,w.__get_max_priority(),!0);return Pt.type!==p?Pt:b[Pt.len]&&b[Pt.len].name===\"r_paren\"?(Pt.len++,Pt):{type:f,derived:!0,value:P.error.syntax(b[Pt.len]?b[Pt.len]:b[Pt.len-1],\") or operator expected\",!b[Pt.len])};case\"l_bracket\":var Pt=Y(w,b,y+1,w.__get_max_priority(),!0);return Pt.type!==p?Pt:b[Pt.len]&&b[Pt.len].name===\"r_bracket\"?(Pt.len++,Pt.value=new _(\"{}\",[Pt.value]),Pt):{type:f,derived:!0,value:P.error.syntax(b[Pt.len]?b[Pt.len]:b[Pt.len-1],\"} or operator expected\",!b[Pt.len])}}var Fe=te(w,b,y,z);return Fe.type===p||Fe.derived||(Fe=ie(w,b,y),Fe.type===p||Fe.derived)?Fe:{type:f,derived:!1,value:P.error.syntax(b[y],\"unexpected token\")}}var ut=w.__get_max_priority(),Ct=w.__get_next_priority(F),qt=y;if(b[y].name===\"atom\"&&b[y+1]&&(b[y].space||b[y+1].name!==\"l_paren\")){var $=b[y++],ir=w.__lookup_operator_classes(F,$.value);if(ir&&ir.indexOf(\"fy\")>-1){var Pt=Y(w,b,y,F,z);if(Pt.type!==f)return $.value===\"-\"&&!$.space&&P.type.is_number(Pt.value)?{value:new P.type.Num(-Pt.value.value,Pt.value.is_float),len:Pt.len,type:p}:{value:new P.type.Term($.value,[Pt.value]),len:Pt.len,type:p};Z=Pt}else if(ir&&ir.indexOf(\"fx\")>-1){var Pt=Y(w,b,y,Ct,z);if(Pt.type!==f)return{value:new P.type.Term($.value,[Pt.value]),len:Pt.len,type:p};Z=Pt}}y=qt;var Pt=Y(w,b,y,Ct,z);if(Pt.type===p){y=Pt.len;var $=b[y];if(b[y]&&(b[y].name===\"atom\"&&w.__lookup_operator_classes(F,$.value)||b[y].name===\"bar\"&&w.__lookup_operator_classes(F,\"|\"))){var dn=Ct,Pr=F,ir=w.__lookup_operator_classes(F,$.value);if(ir.indexOf(\"xf\")>-1)return{value:new P.type.Term($.value,[Pt.value]),len:++Pt.len,type:p};if(ir.indexOf(\"xfx\")>-1){var Ir=Y(w,b,y+1,dn,z);return Ir.type===p?{value:new P.type.Term($.value,[Pt.value,Ir.value]),len:Ir.len,type:p}:(Ir.derived=!0,Ir)}else if(ir.indexOf(\"xfy\")>-1){var Ir=Y(w,b,y+1,Pr,z);return Ir.type===p?{value:new P.type.Term($.value,[Pt.value,Ir.value]),len:Ir.len,type:p}:(Ir.derived=!0,Ir)}else if(Pt.type!==f)for(;;){y=Pt.len;var $=b[y];if($&&$.name===\"atom\"&&w.__lookup_operator_classes(F,$.value)){var ir=w.__lookup_operator_classes(F,$.value);if(ir.indexOf(\"yf\")>-1)Pt={value:new P.type.Term($.value,[Pt.value]),len:++y,type:p};else if(ir.indexOf(\"yfx\")>-1){var Ir=Y(w,b,++y,dn,z);if(Ir.type===f)return Ir.derived=!0,Ir;y=Ir.len,Pt={value:new P.type.Term($.value,[Pt.value,Ir.value]),len:y,type:p}}else break}else break}}else Z={type:f,value:P.error.syntax(b[Pt.len-1],\"operator expected\")};return Pt}return Pt}function te(w,b,y,F){if(!b[y]||b[y].name===\"atom\"&&b[y].raw===\".\"&&!F&&(b[y].space||!b[y+1]||b[y+1].name!==\"l_paren\"))return{type:f,derived:!1,value:P.error.syntax(b[y-1],\"unfounded token\")};var z=b[y],Z=[];if(b[y].name===\"atom\"&&b[y].raw!==\",\"){if(y++,b[y-1].space)return{type:p,len:y,value:new P.type.Term(z.value,Z)};if(b[y]&&b[y].name===\"l_paren\"){if(b[y+1]&&b[y+1].name===\"r_paren\")return{type:f,derived:!0,value:P.error.syntax(b[y+1],\"argument expected\")};var $=Y(w,b,++y,\"999\",!0);if($.type===f)return $.derived?$:{type:f,derived:!0,value:P.error.syntax(b[y]?b[y]:b[y-1],\"argument expected\",!b[y])};for(Z.push($.value),y=$.len;b[y]&&b[y].name===\"atom\"&&b[y].value===\",\";){if($=Y(w,b,y+1,\"999\",!0),$.type===f)return $.derived?$:{type:f,derived:!0,value:P.error.syntax(b[y+1]?b[y+1]:b[y],\"argument expected\",!b[y+1])};Z.push($.value),y=$.len}if(b[y]&&b[y].name===\"r_paren\")y++;else return{type:f,derived:!0,value:P.error.syntax(b[y]?b[y]:b[y-1],\", or ) expected\",!b[y])}}return{type:p,len:y,value:new P.type.Term(z.value,Z)}}return{type:f,derived:!1,value:P.error.syntax(b[y],\"term expected\")}}function ie(w,b,y){if(!b[y])return{type:f,derived:!1,value:P.error.syntax(b[y-1],\"[ expected\")};if(b[y]&&b[y].name===\"l_brace\"){var F=Y(w,b,++y,\"999\",!0),z=[F.value],Z=void 0;if(F.type===f)return b[y]&&b[y].name===\"r_brace\"?{type:p,len:y+1,value:new P.type.Term(\"[]\",[])}:{type:f,derived:!0,value:P.error.syntax(b[y],\"] expected\")};for(y=F.len;b[y]&&b[y].name===\"atom\"&&b[y].value===\",\";){if(F=Y(w,b,y+1,\"999\",!0),F.type===f)return F.derived?F:{type:f,derived:!0,value:P.error.syntax(b[y+1]?b[y+1]:b[y],\"argument expected\",!b[y+1])};z.push(F.value),y=F.len}var $=!1;if(b[y]&&b[y].name===\"bar\"){if($=!0,F=Y(w,b,y+1,\"999\",!0),F.type===f)return F.derived?F:{type:f,derived:!0,value:P.error.syntax(b[y+1]?b[y+1]:b[y],\"argument expected\",!b[y+1])};Z=F.value,y=F.len}return b[y]&&b[y].name===\"r_brace\"?{type:p,len:y+1,value:g(z,Z)}:{type:f,derived:!0,value:P.error.syntax(b[y]?b[y]:b[y-1],$?\"] expected\":\", or | or ] expected\",!b[y])}}return{type:f,derived:!1,value:P.error.syntax(b[y],\"list expected\")}}function ue(w,b,y){var F=b[y].line,z=Y(w,b,y,w.__get_max_priority(),!1),Z=null,$;if(z.type!==f)if(y=z.len,b[y]&&b[y].name===\"atom\"&&b[y].raw===\".\")if(y++,P.type.is_term(z.value)){if(z.value.indicator===\":-/2\"?(Z=new P.type.Rule(z.value.args[0],Ee(z.value.args[1])),$={value:Z,len:y,type:p}):z.value.indicator===\"-->/2\"?(Z=Ae(new P.type.Rule(z.value.args[0],z.value.args[1]),w),Z.body=Ee(Z.body),$={value:Z,len:y,type:P.type.is_rule(Z)?p:f}):(Z=new P.type.Rule(z.value,null),$={value:Z,len:y,type:p}),Z){var se=Z.singleton_variables();se.length>0&&w.throw_warning(P.warning.singleton(se,Z.head.indicator,F))}return $}else return{type:f,value:P.error.syntax(b[y],\"callable expected\")};else return{type:f,value:P.error.syntax(b[y]?b[y]:b[y-1],\". or operator expected\")};return z}function ae(w,b,y){y=y||{},y.from=y.from?y.from:\"$tau-js\",y.reconsult=y.reconsult!==void 0?y.reconsult:!0;var F=new U(w),z={},Z;F.new_text(b);var $=0,se=F.get_tokens($);do{if(se===null||!se[$])break;var xe=ue(w,se,$);if(xe.type===f)return new _(\"throw\",[xe.value]);if(xe.value.body===null&&xe.value.head.indicator===\"?-/1\"){var Fe=new ct(w.session);Fe.add_goal(xe.value.head.args[0]),Fe.answer(function(Ct){P.type.is_error(Ct)?w.throw_warning(Ct.args[0]):(Ct===!1||Ct===null)&&w.throw_warning(P.warning.failed_goal(xe.value.head.args[0],xe.len))}),$=xe.len;var ut=!0}else if(xe.value.body===null&&xe.value.head.indicator===\":-/1\"){var ut=w.run_directive(xe.value.head.args[0]);$=xe.len,xe.value.head.args[0].indicator===\"char_conversion/2\"&&(se=F.get_tokens($),$=0)}else{Z=xe.value.head.indicator,y.reconsult!==!1&&z[Z]!==!0&&!w.is_multifile_predicate(Z)&&(w.session.rules[Z]=a(w.session.rules[Z]||[],function(qt){return qt.dynamic}),z[Z]=!0);var ut=w.add_rule(xe.value,y);$=xe.len}if(!ut)return ut}while(!0);return!0}function de(w,b){var y=new U(w);y.new_text(b);var F=0;do{var z=y.get_tokens(F);if(z===null)break;var Z=Y(w,z,0,w.__get_max_priority(),!1);if(Z.type!==f){var $=Z.len,se=$;if(z[$]&&z[$].name===\"atom\"&&z[$].raw===\".\")w.add_goal(Ee(Z.value));else{var xe=z[$];return new _(\"throw\",[P.error.syntax(xe||z[$-1],\". or operator expected\",!xe)])}F=Z.len+1}else return new _(\"throw\",[Z.value])}while(!0);return!0}function Ae(w,b){w=w.rename(b);var y=b.next_free_variable(),F=Ce(w.body,y,b);return F.error?F.value:(w.body=F.value,w.head.args=w.head.args.concat([y,F.variable]),w.head=new _(w.head.id,w.head.args),w)}function Ce(w,b,y){var F;if(P.type.is_term(w)&&w.indicator===\"!/0\")return{value:w,variable:b,error:!1};if(P.type.is_term(w)&&w.indicator===\",/2\"){var z=Ce(w.args[0],b,y);if(z.error)return z;var Z=Ce(w.args[1],z.variable,y);return Z.error?Z:{value:new _(\",\",[z.value,Z.value]),variable:Z.variable,error:!1}}else{if(P.type.is_term(w)&&w.indicator===\"{}/1\")return{value:w.args[0],variable:b,error:!1};if(P.type.is_empty_list(w))return{value:new _(\"true\",[]),variable:b,error:!1};if(P.type.is_list(w)){F=y.next_free_variable();for(var $=w,se;$.indicator===\"./2\";)se=$,$=$.args[1];return P.type.is_variable($)?{value:P.error.instantiation(\"DCG\"),variable:b,error:!0}:P.type.is_empty_list($)?(se.args[1]=F,{value:new _(\"=\",[b,w]),variable:F,error:!1}):{value:P.error.type(\"list\",w,\"DCG\"),variable:b,error:!0}}else return P.type.is_callable(w)?(F=y.next_free_variable(),w.args=w.args.concat([b,F]),w=new _(w.id,w.args),{value:w,variable:F,error:!1}):{value:P.error.type(\"callable\",w,\"DCG\"),variable:b,error:!0}}}function Ee(w){return P.type.is_variable(w)?new _(\"call\",[w]):P.type.is_term(w)&&[\",/2\",\";/2\",\"->/2\"].indexOf(w.indicator)!==-1?new _(w.id,[Ee(w.args[0]),Ee(w.args[1])]):w}function g(w,b){for(var y=b||new P.type.Term(\"[]\",[]),F=w.length-1;F>=0;F--)y=new P.type.Term(\".\",[w[F],y]);return y}function Se(w,b){for(var y=w.length-1;y>=0;y--)w[y]===b&&w.splice(y,1)}function Be(w){for(var b={},y=[],F=0;F<w.length;F++)w[F]in b||(y.push(w[F]),b[w[F]]=!0);return y}function me(w,b,y,F){if(w.session.rules[y]!==null){for(var z=0;z<w.session.rules[y].length;z++)if(w.session.rules[y][z]===F){w.session.rules[y].splice(z,1),w.success(b);break}}}function ce(w){return function(b,y,F){var z=F.args[0],Z=F.args.slice(1,w);if(P.type.is_variable(z))b.throw_error(P.error.instantiation(b.level));else if(!P.type.is_callable(z))b.throw_error(P.error.type(\"callable\",z,b.level));else{var $=new _(z.id,z.args.concat(Z));b.prepend([new be(y.goal.replace($),y.substitution,y)])}}}function X(w){for(var b=w.length-1;b>=0;b--)if(w.charAt(b)===\"/\")return new _(\"/\",[new _(w.substring(0,b)),new Qe(parseInt(w.substring(b+1)),!1)])}function De(w){this.id=w}function Qe(w,b){this.is_float=b!==void 0?b:parseInt(w)!==w,this.value=this.is_float?w:parseInt(w)}var it=0;function _(w,b,y){this.ref=y||++it,this.id=w,this.args=b||[],this.indicator=w+\"/\"+this.args.length}var tt=0;function Ne(w,b,y,F,z,Z){this.id=tt++,this.stream=w,this.mode=b,this.alias=y,this.type=F!==void 0?F:\"text\",this.reposition=z!==void 0?z:!0,this.eof_action=Z!==void 0?Z:\"eof_code\",this.position=this.mode===\"append\"?\"end_of_stream\":0,this.output=this.mode===\"write\"||this.mode===\"append\",this.input=this.mode===\"read\"}function ke(w){w=w||{},this.links=w}function be(w,b,y){b=b||new ke,y=y||null,this.goal=w,this.substitution=b,this.parent=y}function je(w,b,y){this.head=w,this.body=b,this.dynamic=y||!1}function Re(w){w=w===void 0||w<=0?1e3:w,this.rules={},this.src_predicates={},this.rename=0,this.modules=[],this.thread=new ct(this),this.total_threads=1,this.renamed_variables={},this.public_predicates={},this.multifile_predicates={},this.limit=w,this.streams={user_input:new Ne(typeof tc<\"u\"&&tc.exports?nodejs_user_input:tau_user_input,\"read\",\"user_input\",\"text\",!1,\"reset\"),user_output:new Ne(typeof tc<\"u\"&&tc.exports?nodejs_user_output:tau_user_output,\"write\",\"user_output\",\"text\",!1,\"eof_code\")},this.file_system=typeof tc<\"u\"&&tc.exports?nodejs_file_system:tau_file_system,this.standard_input=this.streams.user_input,this.standard_output=this.streams.user_output,this.current_input=this.streams.user_input,this.current_output=this.streams.user_output,this.format_success=function(b){return b.substitution},this.format_error=function(b){return b.goal},this.flag={bounded:P.flag.bounded.value,max_integer:P.flag.max_integer.value,min_integer:P.flag.min_integer.value,integer_rounding_function:P.flag.integer_rounding_function.value,char_conversion:P.flag.char_conversion.value,debug:P.flag.debug.value,max_arity:P.flag.max_arity.value,unknown:P.flag.unknown.value,double_quotes:P.flag.double_quotes.value,occurs_check:P.flag.occurs_check.value,dialect:P.flag.dialect.value,version_data:P.flag.version_data.value,nodejs:P.flag.nodejs.value},this.__loaded_modules=[],this.__char_conversion={},this.__operators={1200:{\":-\":[\"fx\",\"xfx\"],\"-->\":[\"xfx\"],\"?-\":[\"fx\"]},1100:{\";\":[\"xfy\"]},1050:{\"->\":[\"xfy\"]},1e3:{\",\":[\"xfy\"]},900:{\"\\\\+\":[\"fy\"]},700:{\"=\":[\"xfx\"],\"\\\\=\":[\"xfx\"],\"==\":[\"xfx\"],\"\\\\==\":[\"xfx\"],\"@<\":[\"xfx\"],\"@=<\":[\"xfx\"],\"@>\":[\"xfx\"],\"@>=\":[\"xfx\"],\"=..\":[\"xfx\"],is:[\"xfx\"],\"=:=\":[\"xfx\"],\"=\\\\=\":[\"xfx\"],\"<\":[\"xfx\"],\"=<\":[\"xfx\"],\">\":[\"xfx\"],\">=\":[\"xfx\"]},600:{\":\":[\"xfy\"]},500:{\"+\":[\"yfx\"],\"-\":[\"yfx\"],\"/\\\\\":[\"yfx\"],\"\\\\/\":[\"yfx\"]},400:{\"*\":[\"yfx\"],\"/\":[\"yfx\"],\"//\":[\"yfx\"],rem:[\"yfx\"],mod:[\"yfx\"],\"<<\":[\"yfx\"],\">>\":[\"yfx\"]},200:{\"**\":[\"xfx\"],\"^\":[\"xfy\"],\"-\":[\"fy\"],\"+\":[\"fy\"],\"\\\\\":[\"fy\"]}}}function ct(w){this.epoch=Date.now(),this.session=w,this.session.total_threads++,this.total_steps=0,this.cpu_time=0,this.cpu_time_last=0,this.points=[],this.debugger=!1,this.debugger_states=[],this.level=\"top_level/0\",this.__calls=[],this.current_limit=this.session.limit,this.warnings=[]}function Me(w,b,y){this.id=w,this.rules=b,this.exports=y,P.module[w]=this}Me.prototype.exports_predicate=function(w){return this.exports.indexOf(w)!==-1},De.prototype.unify=function(w,b){if(b&&t(w.variables(),this.id)!==-1&&!P.type.is_variable(w))return null;var y={};return y[this.id]=w,new ke(y)},Qe.prototype.unify=function(w,b){return P.type.is_number(w)&&this.value===w.value&&this.is_float===w.is_float?new ke:null},_.prototype.unify=function(w,b){if(P.type.is_term(w)&&this.indicator===w.indicator){for(var y=new ke,F=0;F<this.args.length;F++){var z=P.unify(this.args[F].apply(y),w.args[F].apply(y),b);if(z===null)return null;for(var Z in z.links)y.links[Z]=z.links[Z];y=y.apply(z)}return y}return null},Ne.prototype.unify=function(w,b){return P.type.is_stream(w)&&this.id===w.id?new ke:null},De.prototype.toString=function(w){return this.id},Qe.prototype.toString=function(w){return this.is_float&&t(this.value.toString(),\".\")===-1?this.value+\".0\":this.value.toString()},_.prototype.toString=function(w,b,y){if(w=w||{},w.quoted=w.quoted===void 0?!0:w.quoted,w.ignore_ops=w.ignore_ops===void 0?!1:w.ignore_ops,w.numbervars=w.numbervars===void 0?!1:w.numbervars,b=b===void 0?1200:b,y=y===void 0?\"\":y,w.numbervars&&this.indicator===\"$VAR/1\"&&P.type.is_integer(this.args[0])&&this.args[0].value>=0){var F=this.args[0].value,z=Math.floor(F/26),Z=F%26;return\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"[Z]+(z!==0?z:\"\")}switch(this.indicator){case\"[]/0\":case\"{}/0\":case\"!/0\":return this.id;case\"{}/1\":return\"{\"+this.args[0].toString(w)+\"}\";case\"./2\":for(var $=\"[\"+this.args[0].toString(w),se=this.args[1];se.indicator===\"./2\";)$+=\", \"+se.args[0].toString(w),se=se.args[1];return se.indicator!==\"[]/0\"&&($+=\"|\"+se.toString(w)),$+=\"]\",$;case\",/2\":return\"(\"+this.args[0].toString(w)+\", \"+this.args[1].toString(w)+\")\";default:var xe=this.id,Fe=w.session?w.session.lookup_operator(this.id,this.args.length):null;if(w.session===void 0||w.ignore_ops||Fe===null)return w.quoted&&!/^(!|,|;|[a-z][0-9a-zA-Z_]*)$/.test(xe)&&xe!==\"{}\"&&xe!==\"[]\"&&(xe=\"'\"+x(xe)+\"'\"),xe+(this.args.length?\"(\"+s(this.args,function(ir){return ir.toString(w)}).join(\", \")+\")\":\"\");var ut=Fe.priority>b.priority||Fe.priority===b.priority&&(Fe.class===\"xfy\"&&this.indicator!==b.indicator||Fe.class===\"yfx\"&&this.indicator!==b.indicator||this.indicator===b.indicator&&Fe.class===\"yfx\"&&y===\"right\"||this.indicator===b.indicator&&Fe.class===\"xfy\"&&y===\"left\");Fe.indicator=this.indicator;var Ct=ut?\"(\":\"\",qt=ut?\")\":\"\";return this.args.length===0?\"(\"+this.id+\")\":[\"fy\",\"fx\"].indexOf(Fe.class)!==-1?Ct+xe+\" \"+this.args[0].toString(w,Fe)+qt:[\"yf\",\"xf\"].indexOf(Fe.class)!==-1?Ct+this.args[0].toString(w,Fe)+\" \"+xe+qt:Ct+this.args[0].toString(w,Fe,\"left\")+\" \"+this.id+\" \"+this.args[1].toString(w,Fe,\"right\")+qt}},Ne.prototype.toString=function(w){return\"<stream>(\"+this.id+\")\"},ke.prototype.toString=function(w){var b=\"{\";for(var y in this.links)this.links.hasOwnProperty(y)&&(b!==\"{\"&&(b+=\", \"),b+=y+\"/\"+this.links[y].toString(w));return b+=\"}\",b},be.prototype.toString=function(w){return this.goal===null?\"<\"+this.substitution.toString(w)+\">\":\"<\"+this.goal.toString(w)+\", \"+this.substitution.toString(w)+\">\"},je.prototype.toString=function(w){return this.body?this.head.toString(w)+\" :- \"+this.body.toString(w)+\".\":this.head.toString(w)+\".\"},Re.prototype.toString=function(w){for(var b=\"\",y=0;y<this.modules.length;y++)b+=\":- use_module(library(\"+this.modules[y]+`)).\n`;b+=`\n`;for(key in this.rules)for(y=0;y<this.rules[key].length;y++)b+=this.rules[key][y].toString(w),b+=`\n`;return b},De.prototype.clone=function(){return new De(this.id)},Qe.prototype.clone=function(){return new Qe(this.value,this.is_float)},_.prototype.clone=function(){return new _(this.id,s(this.args,function(w){return w.clone()}))},Ne.prototype.clone=function(){return new Stram(this.stream,this.mode,this.alias,this.type,this.reposition,this.eof_action)},ke.prototype.clone=function(){var w={};for(var b in this.links)this.links.hasOwnProperty(b)&&(w[b]=this.links[b].clone());return new ke(w)},be.prototype.clone=function(){return new be(this.goal.clone(),this.substitution.clone(),this.parent)},je.prototype.clone=function(){return new je(this.head.clone(),this.body!==null?this.body.clone():null)},De.prototype.equals=function(w){return P.type.is_variable(w)&&this.id===w.id},Qe.prototype.equals=function(w){return P.type.is_number(w)&&this.value===w.value&&this.is_float===w.is_float},_.prototype.equals=function(w){if(!P.type.is_term(w)||this.indicator!==w.indicator)return!1;for(var b=0;b<this.args.length;b++)if(!this.args[b].equals(w.args[b]))return!1;return!0},Ne.prototype.equals=function(w){return P.type.is_stream(w)&&this.id===w.id},ke.prototype.equals=function(w){var b;if(!P.type.is_substitution(w))return!1;for(b in this.links)if(this.links.hasOwnProperty(b)&&(!w.links[b]||!this.links[b].equals(w.links[b])))return!1;for(b in w.links)if(w.links.hasOwnProperty(b)&&!this.links[b])return!1;return!0},be.prototype.equals=function(w){return P.type.is_state(w)&&this.goal.equals(w.goal)&&this.substitution.equals(w.substitution)&&this.parent===w.parent},je.prototype.equals=function(w){return P.type.is_rule(w)&&this.head.equals(w.head)&&(this.body===null&&w.body===null||this.body!==null&&this.body.equals(w.body))},De.prototype.rename=function(w){return w.get_free_variable(this)},Qe.prototype.rename=function(w){return this},_.prototype.rename=function(w){return new _(this.id,s(this.args,function(b){return b.rename(w)}))},Ne.prototype.rename=function(w){return this},je.prototype.rename=function(w){return new je(this.head.rename(w),this.body!==null?this.body.rename(w):null)},De.prototype.variables=function(){return[this.id]},Qe.prototype.variables=function(){return[]},_.prototype.variables=function(){return[].concat.apply([],s(this.args,function(w){return w.variables()}))},Ne.prototype.variables=function(){return[]},je.prototype.variables=function(){return this.body===null?this.head.variables():this.head.variables().concat(this.body.variables())},De.prototype.apply=function(w){return w.lookup(this.id)?w.lookup(this.id):this},Qe.prototype.apply=function(w){return this},_.prototype.apply=function(w){if(this.indicator===\"./2\"){for(var b=[],y=this;y.indicator===\"./2\";)b.push(y.args[0].apply(w)),y=y.args[1];for(var F=y.apply(w),z=b.length-1;z>=0;z--)F=new _(\".\",[b[z],F]);return F}return new _(this.id,s(this.args,function(Z){return Z.apply(w)}),this.ref)},Ne.prototype.apply=function(w){return this},je.prototype.apply=function(w){return new je(this.head.apply(w),this.body!==null?this.body.apply(w):null)},ke.prototype.apply=function(w){var b,y={};for(b in this.links)this.links.hasOwnProperty(b)&&(y[b]=this.links[b].apply(w));return new ke(y)},_.prototype.select=function(){for(var w=this;w.indicator===\",/2\";)w=w.args[0];return w},_.prototype.replace=function(w){return this.indicator===\",/2\"?this.args[0].indicator===\",/2\"?new _(\",\",[this.args[0].replace(w),this.args[1]]):w===null?this.args[1]:new _(\",\",[w,this.args[1]]):w},_.prototype.search=function(w){if(P.type.is_term(w)&&w.ref!==void 0&&this.ref===w.ref)return!0;for(var b=0;b<this.args.length;b++)if(P.type.is_term(this.args[b])&&this.args[b].search(w))return!0;return!1},Re.prototype.get_current_input=function(){return this.current_input},ct.prototype.get_current_input=function(){return this.session.get_current_input()},Re.prototype.get_current_output=function(){return this.current_output},ct.prototype.get_current_output=function(){return this.session.get_current_output()},Re.prototype.set_current_input=function(w){this.current_input=w},ct.prototype.set_current_input=function(w){return this.session.set_current_input(w)},Re.prototype.set_current_output=function(w){this.current_input=w},ct.prototype.set_current_output=function(w){return this.session.set_current_output(w)},Re.prototype.get_stream_by_alias=function(w){return this.streams[w]},ct.prototype.get_stream_by_alias=function(w){return this.session.get_stream_by_alias(w)},Re.prototype.file_system_open=function(w,b,y){return this.file_system.open(w,b,y)},ct.prototype.file_system_open=function(w,b,y){return this.session.file_system_open(w,b,y)},Re.prototype.get_char_conversion=function(w){return this.__char_conversion[w]||w},ct.prototype.get_char_conversion=function(w){return this.session.get_char_conversion(w)},Re.prototype.parse=function(w){return this.thread.parse(w)},ct.prototype.parse=function(w){var b=new U(this);b.new_text(w);var y=b.get_tokens();if(y===null)return!1;var F=Y(this,y,0,this.__get_max_priority(),!1);return F.len!==y.length?!1:{value:F.value,expr:F,tokens:y}},Re.prototype.get_flag=function(w){return this.flag[w]},ct.prototype.get_flag=function(w){return this.session.get_flag(w)},Re.prototype.add_rule=function(w,b){return b=b||{},b.from=b.from?b.from:\"$tau-js\",this.src_predicates[w.head.indicator]=b.from,this.rules[w.head.indicator]||(this.rules[w.head.indicator]=[]),this.rules[w.head.indicator].push(w),this.public_predicates.hasOwnProperty(w.head.indicator)||(this.public_predicates[w.head.indicator]=!1),!0},ct.prototype.add_rule=function(w,b){return this.session.add_rule(w,b)},Re.prototype.run_directive=function(w){this.thread.run_directive(w)},ct.prototype.run_directive=function(w){return P.type.is_directive(w)?(P.directive[w.indicator](this,w),!0):!1},Re.prototype.__get_max_priority=function(){return\"1200\"},ct.prototype.__get_max_priority=function(){return this.session.__get_max_priority()},Re.prototype.__get_next_priority=function(w){var b=0;w=parseInt(w);for(var y in this.__operators)if(this.__operators.hasOwnProperty(y)){var F=parseInt(y);F>b&&F<w&&(b=F)}return b.toString()},ct.prototype.__get_next_priority=function(w){return this.session.__get_next_priority(w)},Re.prototype.__lookup_operator_classes=function(w,b){return this.__operators.hasOwnProperty(w)&&this.__operators[w][b]instanceof Array&&this.__operators[w][b]||!1},ct.prototype.__lookup_operator_classes=function(w,b){return this.session.__lookup_operator_classes(w,b)},Re.prototype.lookup_operator=function(w,b){for(var y in this.__operators)if(this.__operators[y][w]){for(var F=0;F<this.__operators[y][w].length;F++)if(b===0||this.__operators[y][w][F].length===b+1)return{priority:y,class:this.__operators[y][w][F]}}return null},ct.prototype.lookup_operator=function(w,b){return this.session.lookup_operator(w,b)},Re.prototype.throw_warning=function(w){this.thread.throw_warning(w)},ct.prototype.throw_warning=function(w){this.warnings.push(w)},Re.prototype.get_warnings=function(){return this.thread.get_warnings()},ct.prototype.get_warnings=function(){return this.warnings},Re.prototype.add_goal=function(w,b){this.thread.add_goal(w,b)},ct.prototype.add_goal=function(w,b,y){y=y||null,b===!0&&(this.points=[]);for(var F=w.variables(),z={},Z=0;Z<F.length;Z++)z[F[Z]]=new De(F[Z]);this.points.push(new be(w,new ke(z),y))},Re.prototype.consult=function(w,b){return this.thread.consult(w,b)},ct.prototype.consult=function(w,b){var y=\"\";if(typeof w==\"string\"){y=w;var F=y.length;if(y.substring(F-3,F)===\".pl\"&&document.getElementById(y)){var z=document.getElementById(y),Z=z.getAttribute(\"type\");Z!==null&&Z.replace(/ /g,\"\").toLowerCase()===\"text/prolog\"&&(y=z.text)}}else if(w.nodeName)switch(w.nodeName.toLowerCase()){case\"input\":case\"textarea\":y=w.value;break;default:y=w.innerHTML;break}else return!1;return this.warnings=[],ae(this,y,b)},Re.prototype.query=function(w){return this.thread.query(w)},ct.prototype.query=function(w){return this.points=[],this.debugger_points=[],de(this,w)},Re.prototype.head_point=function(){return this.thread.head_point()},ct.prototype.head_point=function(){return this.points[this.points.length-1]},Re.prototype.get_free_variable=function(w){return this.thread.get_free_variable(w)},ct.prototype.get_free_variable=function(w){var b=[];if(w.id===\"_\"||this.session.renamed_variables[w.id]===void 0){for(this.session.rename++,this.points.length>0&&(b=this.head_point().substitution.domain());t(b,P.format_variable(this.session.rename))!==-1;)this.session.rename++;if(w.id===\"_\")return new De(P.format_variable(this.session.rename));this.session.renamed_variables[w.id]=P.format_variable(this.session.rename)}return new De(this.session.renamed_variables[w.id])},Re.prototype.next_free_variable=function(){return this.thread.next_free_variable()},ct.prototype.next_free_variable=function(){this.session.rename++;var w=[];for(this.points.length>0&&(w=this.head_point().substitution.domain());t(w,P.format_variable(this.session.rename))!==-1;)this.session.rename++;return new De(P.format_variable(this.session.rename))},Re.prototype.is_public_predicate=function(w){return!this.public_predicates.hasOwnProperty(w)||this.public_predicates[w]===!0},ct.prototype.is_public_predicate=function(w){return this.session.is_public_predicate(w)},Re.prototype.is_multifile_predicate=function(w){return this.multifile_predicates.hasOwnProperty(w)&&this.multifile_predicates[w]===!0},ct.prototype.is_multifile_predicate=function(w){return this.session.is_multifile_predicate(w)},Re.prototype.prepend=function(w){return this.thread.prepend(w)},ct.prototype.prepend=function(w){for(var b=w.length-1;b>=0;b--)this.points.push(w[b])},Re.prototype.success=function(w,b){return this.thread.success(w,b)},ct.prototype.success=function(w,y){var y=typeof y>\"u\"?w:y;this.prepend([new be(w.goal.replace(null),w.substitution,y)])},Re.prototype.throw_error=function(w){return this.thread.throw_error(w)},ct.prototype.throw_error=function(w){this.prepend([new be(new _(\"throw\",[w]),new ke,null,null)])},Re.prototype.step_rule=function(w,b){return this.thread.step_rule(w,b)},ct.prototype.step_rule=function(w,b){var y=b.indicator;if(w===\"user\"&&(w=null),w===null&&this.session.rules.hasOwnProperty(y))return this.session.rules[y];for(var F=w===null?this.session.modules:t(this.session.modules,w)===-1?[]:[w],z=0;z<F.length;z++){var Z=P.module[F[z]];if(Z.rules.hasOwnProperty(y)&&(Z.rules.hasOwnProperty(this.level)||Z.exports_predicate(y)))return P.module[F[z]].rules[y]}return null},Re.prototype.step=function(){return this.thread.step()},ct.prototype.step=function(){if(this.points.length!==0){var w=!1,b=this.points.pop();if(this.debugger&&this.debugger_states.push(b),P.type.is_term(b.goal)){var y=b.goal.select(),F=null,z=[];if(y!==null){this.total_steps++;for(var Z=b;Z.parent!==null&&Z.parent.goal.search(y);)Z=Z.parent;if(this.level=Z.parent===null?\"top_level/0\":Z.parent.goal.select().indicator,P.type.is_term(y)&&y.indicator===\":/2\"&&(F=y.args[0].id,y=y.args[1]),F===null&&P.type.is_builtin(y))this.__call_indicator=y.indicator,w=P.predicate[y.indicator](this,b,y);else{var $=this.step_rule(F,y);if($===null)this.session.rules.hasOwnProperty(y.indicator)||(this.get_flag(\"unknown\").id===\"error\"?this.throw_error(P.error.existence(\"procedure\",y.indicator,this.level)):this.get_flag(\"unknown\").id===\"warning\"&&this.throw_warning(\"unknown procedure \"+y.indicator+\" (from \"+this.level+\")\"));else if($ instanceof Function)w=$(this,b,y);else{for(var se in $)if($.hasOwnProperty(se)){var xe=$[se];this.session.renamed_variables={},xe=xe.rename(this);var Fe=this.get_flag(\"occurs_check\").indicator===\"true/0\",ut=new be,Ct=P.unify(y,xe.head,Fe);Ct!==null&&(ut.goal=b.goal.replace(xe.body),ut.goal!==null&&(ut.goal=ut.goal.apply(Ct)),ut.substitution=b.substitution.apply(Ct),ut.parent=b,z.push(ut))}this.prepend(z)}}}}else P.type.is_variable(b.goal)?this.throw_error(P.error.instantiation(this.level)):this.throw_error(P.error.type(\"callable\",b.goal,this.level));return w}},Re.prototype.answer=function(w){return this.thread.answer(w)},ct.prototype.answer=function(w){w=w||function(b){},this.__calls.push(w),!(this.__calls.length>1)&&this.again()},Re.prototype.answers=function(w,b,y){return this.thread.answers(w,b,y)},ct.prototype.answers=function(w,b,y){var F=b||1e3,z=this;if(b<=0){y&&y();return}this.answer(function(Z){w(Z),Z!==!1?setTimeout(function(){z.answers(w,b-1,y)},1):y&&y()})},Re.prototype.again=function(w){return this.thread.again(w)},ct.prototype.again=function(w){for(var b,y=Date.now();this.__calls.length>0;){for(this.warnings=[],w!==!1&&(this.current_limit=this.session.limit);this.current_limit>0&&this.points.length>0&&this.head_point().goal!==null&&!P.type.is_error(this.head_point().goal);)if(this.current_limit--,this.step()===!0)return;var F=Date.now();this.cpu_time_last=F-y,this.cpu_time+=this.cpu_time_last;var z=this.__calls.shift();this.current_limit<=0?z(null):this.points.length===0?z(!1):P.type.is_error(this.head_point().goal)?(b=this.session.format_error(this.points.pop()),this.points=[],z(b)):(this.debugger&&this.debugger_states.push(this.head_point()),b=this.session.format_success(this.points.pop()),z(b))}},Re.prototype.unfold=function(w){if(w.body===null)return!1;var b=w.head,y=w.body,F=y.select(),z=new ct(this),Z=[];z.add_goal(F),z.step();for(var $=z.points.length-1;$>=0;$--){var se=z.points[$],xe=b.apply(se.substitution),Fe=y.replace(se.goal);Fe!==null&&(Fe=Fe.apply(se.substitution)),Z.push(new je(xe,Fe))}var ut=this.rules[b.indicator],Ct=t(ut,w);return Z.length>0&&Ct!==-1?(ut.splice.apply(ut,[Ct,1].concat(Z)),!0):!1},ct.prototype.unfold=function(w){return this.session.unfold(w)},De.prototype.interpret=function(w){return P.error.instantiation(w.level)},Qe.prototype.interpret=function(w){return this},_.prototype.interpret=function(w){return P.type.is_unitary_list(this)?this.args[0].interpret(w):P.operate(w,this)},De.prototype.compare=function(w){return this.id<w.id?-1:this.id>w.id?1:0},Qe.prototype.compare=function(w){if(this.value===w.value&&this.is_float===w.is_float)return 0;if(this.value<w.value||this.value===w.value&&this.is_float&&!w.is_float)return-1;if(this.value>w.value)return 1},_.prototype.compare=function(w){if(this.args.length<w.args.length||this.args.length===w.args.length&&this.id<w.id)return-1;if(this.args.length>w.args.length||this.args.length===w.args.length&&this.id>w.id)return 1;for(var b=0;b<this.args.length;b++){var y=P.compare(this.args[b],w.args[b]);if(y!==0)return y}return 0},ke.prototype.lookup=function(w){return this.links[w]?this.links[w]:null},ke.prototype.filter=function(w){var b={};for(var y in this.links)if(this.links.hasOwnProperty(y)){var F=this.links[y];w(y,F)&&(b[y]=F)}return new ke(b)},ke.prototype.exclude=function(w){var b={};for(var y in this.links)this.links.hasOwnProperty(y)&&t(w,y)===-1&&(b[y]=this.links[y]);return new ke(b)},ke.prototype.add=function(w,b){this.links[w]=b},ke.prototype.domain=function(w){var b=w===!0?function(z){return z}:function(z){return new De(z)},y=[];for(var F in this.links)y.push(b(F));return y},De.prototype.compile=function(){return'new pl.type.Var(\"'+this.id.toString()+'\")'},Qe.prototype.compile=function(){return\"new pl.type.Num(\"+this.value.toString()+\", \"+this.is_float.toString()+\")\"},_.prototype.compile=function(){return'new pl.type.Term(\"'+this.id.replace(/\"/g,'\\\\\"')+'\", ['+s(this.args,function(w){return w.compile()})+\"])\"},je.prototype.compile=function(){return\"new pl.type.Rule(\"+this.head.compile()+\", \"+(this.body===null?\"null\":this.body.compile())+\")\"},Re.prototype.compile=function(){var w,b=[],y;for(var F in this.rules)if(this.rules.hasOwnProperty(F)){var z=this.rules[F];y=[],w='\"'+F+'\": [';for(var Z=0;Z<z.length;Z++)y.push(z[Z].compile());w+=y.join(),w+=\"]\",b.push(w)}return\"{\"+b.join()+\"};\"},De.prototype.toJavaScript=function(){},Qe.prototype.toJavaScript=function(){return this.value},_.prototype.toJavaScript=function(){if(this.args.length===0&&this.indicator!==\"[]/0\")return this.id;if(P.type.is_list(this)){for(var w=[],b=this,y;b.indicator===\"./2\";){if(y=b.args[0].toJavaScript(),y===void 0)return;w.push(y),b=b.args[1]}if(b.indicator===\"[]/0\")return w}},je.prototype.singleton_variables=function(){var w=this.head.variables(),b={},y=[];this.body!==null&&(w=w.concat(this.body.variables()));for(var F=0;F<w.length;F++)b[w[F]]===void 0&&(b[w[F]]=0),b[w[F]]++;for(var z in b)z!==\"_\"&&b[z]===1&&y.push(z);return y};var P={__env:typeof tc<\"u\"&&tc.exports?global:window,module:{},version:e,parser:{tokenizer:U,expression:Y},utils:{str_indicator:X,codePointAt:n,fromCodePoint:c},statistics:{getCountTerms:function(){return it}},fromJavaScript:{test:{boolean:function(w){return w===!0||w===!1},number:function(w){return typeof w==\"number\"},string:function(w){return typeof w==\"string\"},list:function(w){return w instanceof Array},variable:function(w){return w===void 0},any:function(w){return!0}},conversion:{boolean:function(w){return new _(w?\"true\":\"false\",[])},number:function(w){return new Qe(w,w%1!==0)},string:function(w){return new _(w,[])},list:function(w){for(var b=[],y,F=0;F<w.length;F++){if(y=P.fromJavaScript.apply(w[F]),y===void 0)return;b.push(y)}return g(b)},variable:function(w){return new De(\"_\")},any:function(w){}},apply:function(w){for(var b in P.fromJavaScript.test)if(b!==\"any\"&&P.fromJavaScript.test[b](w))return P.fromJavaScript.conversion[b](w);return P.fromJavaScript.conversion.any(w)}},type:{Var:De,Num:Qe,Term:_,Rule:je,State:be,Stream:Ne,Module:Me,Thread:ct,Session:Re,Substitution:ke,order:[De,Qe,_,Ne],compare:function(w,b){var y=t(P.type.order,w.constructor),F=t(P.type.order,b.constructor);if(y<F)return-1;if(y>F)return 1;if(w.constructor===Qe){if(w.is_float&&b.is_float)return 0;if(w.is_float)return-1;if(b.is_float)return 1}return 0},is_substitution:function(w){return w instanceof ke},is_state:function(w){return w instanceof be},is_rule:function(w){return w instanceof je},is_variable:function(w){return w instanceof De},is_stream:function(w){return w instanceof Ne},is_anonymous_var:function(w){return w instanceof De&&w.id===\"_\"},is_callable:function(w){return w instanceof _},is_number:function(w){return w instanceof Qe},is_integer:function(w){return w instanceof Qe&&!w.is_float},is_float:function(w){return w instanceof Qe&&w.is_float},is_term:function(w){return w instanceof _},is_atom:function(w){return w instanceof _&&w.args.length===0},is_ground:function(w){if(w instanceof De)return!1;if(w instanceof _){for(var b=0;b<w.args.length;b++)if(!P.type.is_ground(w.args[b]))return!1}return!0},is_atomic:function(w){return w instanceof _&&w.args.length===0||w instanceof Qe},is_compound:function(w){return w instanceof _&&w.args.length>0},is_list:function(w){return w instanceof _&&(w.indicator===\"[]/0\"||w.indicator===\"./2\")},is_empty_list:function(w){return w instanceof _&&w.indicator===\"[]/0\"},is_non_empty_list:function(w){return w instanceof _&&w.indicator===\"./2\"},is_fully_list:function(w){for(;w instanceof _&&w.indicator===\"./2\";)w=w.args[1];return w instanceof De||w instanceof _&&w.indicator===\"[]/0\"},is_instantiated_list:function(w){for(;w instanceof _&&w.indicator===\"./2\";)w=w.args[1];return w instanceof _&&w.indicator===\"[]/0\"},is_unitary_list:function(w){return w instanceof _&&w.indicator===\"./2\"&&w.args[1]instanceof _&&w.args[1].indicator===\"[]/0\"},is_character:function(w){return w instanceof _&&(w.id.length===1||w.id.length>0&&w.id.length<=2&&n(w.id,0)>=65536)},is_character_code:function(w){return w instanceof Qe&&!w.is_float&&w.value>=0&&w.value<=1114111},is_byte:function(w){return w instanceof Qe&&!w.is_float&&w.value>=0&&w.value<=255},is_operator:function(w){return w instanceof _&&P.arithmetic.evaluation[w.indicator]},is_directive:function(w){return w instanceof _&&P.directive[w.indicator]!==void 0},is_builtin:function(w){return w instanceof _&&P.predicate[w.indicator]!==void 0},is_error:function(w){return w instanceof _&&w.indicator===\"throw/1\"},is_predicate_indicator:function(w){return w instanceof _&&w.indicator===\"//2\"&&w.args[0]instanceof _&&w.args[0].args.length===0&&w.args[1]instanceof Qe&&w.args[1].is_float===!1},is_flag:function(w){return w instanceof _&&w.args.length===0&&P.flag[w.id]!==void 0},is_value_flag:function(w,b){if(!P.type.is_flag(w))return!1;for(var y in P.flag[w.id].allowed)if(P.flag[w.id].allowed.hasOwnProperty(y)&&P.flag[w.id].allowed[y].equals(b))return!0;return!1},is_io_mode:function(w){return P.type.is_atom(w)&&[\"read\",\"write\",\"append\"].indexOf(w.id)!==-1},is_stream_option:function(w){return P.type.is_term(w)&&(w.indicator===\"alias/1\"&&P.type.is_atom(w.args[0])||w.indicator===\"reposition/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"true\"||w.args[0].id===\"false\")||w.indicator===\"type/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"text\"||w.args[0].id===\"binary\")||w.indicator===\"eof_action/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"error\"||w.args[0].id===\"eof_code\"||w.args[0].id===\"reset\"))},is_stream_position:function(w){return P.type.is_integer(w)&&w.value>=0||P.type.is_atom(w)&&(w.id===\"end_of_stream\"||w.id===\"past_end_of_stream\")},is_stream_property:function(w){return P.type.is_term(w)&&(w.indicator===\"input/0\"||w.indicator===\"output/0\"||w.indicator===\"alias/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0]))||w.indicator===\"file_name/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0]))||w.indicator===\"position/1\"&&(P.type.is_variable(w.args[0])||P.type.is_stream_position(w.args[0]))||w.indicator===\"reposition/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0])&&(w.args[0].id===\"true\"||w.args[0].id===\"false\"))||w.indicator===\"type/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0])&&(w.args[0].id===\"text\"||w.args[0].id===\"binary\"))||w.indicator===\"mode/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0])&&(w.args[0].id===\"read\"||w.args[0].id===\"write\"||w.args[0].id===\"append\"))||w.indicator===\"eof_action/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0])&&(w.args[0].id===\"error\"||w.args[0].id===\"eof_code\"||w.args[0].id===\"reset\"))||w.indicator===\"end_of_stream/1\"&&(P.type.is_variable(w.args[0])||P.type.is_atom(w.args[0])&&(w.args[0].id===\"at\"||w.args[0].id===\"past\"||w.args[0].id===\"not\")))},is_streamable:function(w){return w.__proto__.stream!==void 0},is_read_option:function(w){return P.type.is_term(w)&&[\"variables/1\",\"variable_names/1\",\"singletons/1\"].indexOf(w.indicator)!==-1},is_write_option:function(w){return P.type.is_term(w)&&(w.indicator===\"quoted/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"true\"||w.args[0].id===\"false\")||w.indicator===\"ignore_ops/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"true\"||w.args[0].id===\"false\")||w.indicator===\"numbervars/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"true\"||w.args[0].id===\"false\"))},is_close_option:function(w){return P.type.is_term(w)&&w.indicator===\"force/1\"&&P.type.is_atom(w.args[0])&&(w.args[0].id===\"true\"||w.args[0].id===\"false\")},is_modifiable_flag:function(w){return P.type.is_flag(w)&&P.flag[w.id].changeable},is_module:function(w){return w instanceof _&&w.indicator===\"library/1\"&&w.args[0]instanceof _&&w.args[0].args.length===0&&P.module[w.args[0].id]!==void 0}},arithmetic:{evaluation:{\"e/0\":{type_args:null,type_result:!0,fn:function(w){return Math.E}},\"pi/0\":{type_args:null,type_result:!0,fn:function(w){return Math.PI}},\"tau/0\":{type_args:null,type_result:!0,fn:function(w){return 2*Math.PI}},\"epsilon/0\":{type_args:null,type_result:!0,fn:function(w){return Number.EPSILON}},\"+/1\":{type_args:null,type_result:null,fn:function(w,b){return w}},\"-/1\":{type_args:null,type_result:null,fn:function(w,b){return-w}},\"\\\\/1\":{type_args:!1,type_result:!1,fn:function(w,b){return~w}},\"abs/1\":{type_args:null,type_result:null,fn:function(w,b){return Math.abs(w)}},\"sign/1\":{type_args:null,type_result:null,fn:function(w,b){return Math.sign(w)}},\"float_integer_part/1\":{type_args:!0,type_result:!1,fn:function(w,b){return parseInt(w)}},\"float_fractional_part/1\":{type_args:!0,type_result:!0,fn:function(w,b){return w-parseInt(w)}},\"float/1\":{type_args:null,type_result:!0,fn:function(w,b){return parseFloat(w)}},\"floor/1\":{type_args:!0,type_result:!1,fn:function(w,b){return Math.floor(w)}},\"truncate/1\":{type_args:!0,type_result:!1,fn:function(w,b){return parseInt(w)}},\"round/1\":{type_args:!0,type_result:!1,fn:function(w,b){return Math.round(w)}},\"ceiling/1\":{type_args:!0,type_result:!1,fn:function(w,b){return Math.ceil(w)}},\"sin/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.sin(w)}},\"cos/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.cos(w)}},\"tan/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.tan(w)}},\"asin/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.asin(w)}},\"acos/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.acos(w)}},\"atan/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.atan(w)}},\"atan2/2\":{type_args:null,type_result:!0,fn:function(w,b,y){return Math.atan2(w,b)}},\"exp/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.exp(w)}},\"sqrt/1\":{type_args:null,type_result:!0,fn:function(w,b){return Math.sqrt(w)}},\"log/1\":{type_args:null,type_result:!0,fn:function(w,b){return w>0?Math.log(w):P.error.evaluation(\"undefined\",b.__call_indicator)}},\"+/2\":{type_args:null,type_result:null,fn:function(w,b,y){return w+b}},\"-/2\":{type_args:null,type_result:null,fn:function(w,b,y){return w-b}},\"*/2\":{type_args:null,type_result:null,fn:function(w,b,y){return w*b}},\"//2\":{type_args:null,type_result:!0,fn:function(w,b,y){return b?w/b:P.error.evaluation(\"zero_division\",y.__call_indicator)}},\"///2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return b?parseInt(w/b):P.error.evaluation(\"zero_division\",y.__call_indicator)}},\"**/2\":{type_args:null,type_result:!0,fn:function(w,b,y){return Math.pow(w,b)}},\"^/2\":{type_args:null,type_result:null,fn:function(w,b,y){return Math.pow(w,b)}},\"<</2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return w<<b}},\">>/2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return w>>b}},\"/\\\\/2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return w&b}},\"\\\\//2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return w|b}},\"xor/2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return w^b}},\"rem/2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return b?w%b:P.error.evaluation(\"zero_division\",y.__call_indicator)}},\"mod/2\":{type_args:!1,type_result:!1,fn:function(w,b,y){return b?w-parseInt(w/b)*b:P.error.evaluation(\"zero_division\",y.__call_indicator)}},\"max/2\":{type_args:null,type_result:null,fn:function(w,b,y){return Math.max(w,b)}},\"min/2\":{type_args:null,type_result:null,fn:function(w,b,y){return Math.min(w,b)}}}},directive:{\"dynamic/1\":function(w,b){var y=b.args[0];if(P.type.is_variable(y))w.throw_error(P.error.instantiation(b.indicator));else if(!P.type.is_compound(y)||y.indicator!==\"//2\")w.throw_error(P.error.type(\"predicate_indicator\",y,b.indicator));else if(P.type.is_variable(y.args[0])||P.type.is_variable(y.args[1]))w.throw_error(P.error.instantiation(b.indicator));else if(!P.type.is_atom(y.args[0]))w.throw_error(P.error.type(\"atom\",y.args[0],b.indicator));else if(!P.type.is_integer(y.args[1]))w.throw_error(P.error.type(\"integer\",y.args[1],b.indicator));else{var F=b.args[0].args[0].id+\"/\"+b.args[0].args[1].value;w.session.public_predicates[F]=!0,w.session.rules[F]||(w.session.rules[F]=[])}},\"multifile/1\":function(w,b){var y=b.args[0];P.type.is_variable(y)?w.throw_error(P.error.instantiation(b.indicator)):!P.type.is_compound(y)||y.indicator!==\"//2\"?w.throw_error(P.error.type(\"predicate_indicator\",y,b.indicator)):P.type.is_variable(y.args[0])||P.type.is_variable(y.args[1])?w.throw_error(P.error.instantiation(b.indicator)):P.type.is_atom(y.args[0])?P.type.is_integer(y.args[1])?w.session.multifile_predicates[b.args[0].args[0].id+\"/\"+b.args[0].args[1].value]=!0:w.throw_error(P.error.type(\"integer\",y.args[1],b.indicator)):w.throw_error(P.error.type(\"atom\",y.args[0],b.indicator))},\"set_prolog_flag/2\":function(w,b){var y=b.args[0],F=b.args[1];P.type.is_variable(y)||P.type.is_variable(F)?w.throw_error(P.error.instantiation(b.indicator)):P.type.is_atom(y)?P.type.is_flag(y)?P.type.is_value_flag(y,F)?P.type.is_modifiable_flag(y)?w.session.flag[y.id]=F:w.throw_error(P.error.permission(\"modify\",\"flag\",y)):w.throw_error(P.error.domain(\"flag_value\",new _(\"+\",[y,F]),b.indicator)):w.throw_error(P.error.domain(\"prolog_flag\",y,b.indicator)):w.throw_error(P.error.type(\"atom\",y,b.indicator))},\"use_module/1\":function(w,b){var y=b.args[0];if(P.type.is_variable(y))w.throw_error(P.error.instantiation(b.indicator));else if(!P.type.is_term(y))w.throw_error(P.error.type(\"term\",y,b.indicator));else if(P.type.is_module(y)){var F=y.args[0].id;t(w.session.modules,F)===-1&&w.session.modules.push(F)}},\"char_conversion/2\":function(w,b){var y=b.args[0],F=b.args[1];P.type.is_variable(y)||P.type.is_variable(F)?w.throw_error(P.error.instantiation(b.indicator)):P.type.is_character(y)?P.type.is_character(F)?y.id===F.id?delete w.session.__char_conversion[y.id]:w.session.__char_conversion[y.id]=F.id:w.throw_error(P.error.type(\"character\",F,b.indicator)):w.throw_error(P.error.type(\"character\",y,b.indicator))},\"op/3\":function(w,b){var y=b.args[0],F=b.args[1],z=b.args[2];if(P.type.is_variable(y)||P.type.is_variable(F)||P.type.is_variable(z))w.throw_error(P.error.instantiation(b.indicator));else if(!P.type.is_integer(y))w.throw_error(P.error.type(\"integer\",y,b.indicator));else if(!P.type.is_atom(F))w.throw_error(P.error.type(\"atom\",F,b.indicator));else if(!P.type.is_atom(z))w.throw_error(P.error.type(\"atom\",z,b.indicator));else if(y.value<0||y.value>1200)w.throw_error(P.error.domain(\"operator_priority\",y,b.indicator));else if(z.id===\",\")w.throw_error(P.error.permission(\"modify\",\"operator\",z,b.indicator));else if(z.id===\"|\"&&(y.value<1001||F.id.length!==3))w.throw_error(P.error.permission(\"modify\",\"operator\",z,b.indicator));else if([\"fy\",\"fx\",\"yf\",\"xf\",\"xfx\",\"yfx\",\"xfy\"].indexOf(F.id)===-1)w.throw_error(P.error.domain(\"operator_specifier\",F,b.indicator));else{var Z={prefix:null,infix:null,postfix:null};for(var $ in w.session.__operators)if(w.session.__operators.hasOwnProperty($)){var se=w.session.__operators[$][z.id];se&&(t(se,\"fx\")!==-1&&(Z.prefix={priority:$,type:\"fx\"}),t(se,\"fy\")!==-1&&(Z.prefix={priority:$,type:\"fy\"}),t(se,\"xf\")!==-1&&(Z.postfix={priority:$,type:\"xf\"}),t(se,\"yf\")!==-1&&(Z.postfix={priority:$,type:\"yf\"}),t(se,\"xfx\")!==-1&&(Z.infix={priority:$,type:\"xfx\"}),t(se,\"xfy\")!==-1&&(Z.infix={priority:$,type:\"xfy\"}),t(se,\"yfx\")!==-1&&(Z.infix={priority:$,type:\"yfx\"}))}var xe;switch(F.id){case\"fy\":case\"fx\":xe=\"prefix\";break;case\"yf\":case\"xf\":xe=\"postfix\";break;default:xe=\"infix\";break}if(((Z.prefix&&xe===\"prefix\"||Z.postfix&&xe===\"postfix\"||Z.infix&&xe===\"infix\")&&Z[xe].type!==F.id||Z.infix&&xe===\"postfix\"||Z.postfix&&xe===\"infix\")&&y.value!==0)w.throw_error(P.error.permission(\"create\",\"operator\",z,b.indicator));else return Z[xe]&&(Se(w.session.__operators[Z[xe].priority][z.id],F.id),w.session.__operators[Z[xe].priority][z.id].length===0&&delete w.session.__operators[Z[xe].priority][z.id]),y.value>0&&(w.session.__operators[y.value]||(w.session.__operators[y.value.toString()]={}),w.session.__operators[y.value][z.id]||(w.session.__operators[y.value][z.id]=[]),w.session.__operators[y.value][z.id].push(F.id)),!0}}},predicate:{\"op/3\":function(w,b,y){P.directive[\"op/3\"](w,y)&&w.success(b)},\"current_op/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2],$=[];for(var se in w.session.__operators)for(var xe in w.session.__operators[se])for(var Fe=0;Fe<w.session.__operators[se][xe].length;Fe++)$.push(new be(b.goal.replace(new _(\",\",[new _(\"=\",[new Qe(se,!1),F]),new _(\",\",[new _(\"=\",[new _(w.session.__operators[se][xe][Fe],[]),z]),new _(\"=\",[new _(xe,[]),Z])])])),b.substitution,b));w.prepend($)},\";/2\":function(w,b,y){if(P.type.is_term(y.args[0])&&y.args[0].indicator===\"->/2\"){var F=w.points,z=w.session.format_success,Z=w.session.format_error;w.session.format_success=function(Fe){return Fe.substitution},w.session.format_error=function(Fe){return Fe.goal},w.points=[new be(y.args[0].args[0],b.substitution,b)];var $=function(Fe){w.points=F,w.session.format_success=z,w.session.format_error=Z,Fe===!1?w.prepend([new be(b.goal.replace(y.args[1]),b.substitution,b)]):P.type.is_error(Fe)?w.throw_error(Fe.args[0]):Fe===null?(w.prepend([b]),w.__calls.shift()(null)):w.prepend([new be(b.goal.replace(y.args[0].args[1]).apply(Fe),b.substitution.apply(Fe),b)])};w.__calls.unshift($)}else{var se=new be(b.goal.replace(y.args[0]),b.substitution,b),xe=new be(b.goal.replace(y.args[1]),b.substitution,b);w.prepend([se,xe])}},\"!/0\":function(w,b,y){var F,z,Z=[];for(F=b,z=null;F.parent!==null&&F.parent.goal.search(y);)if(z=F,F=F.parent,F.goal!==null){var $=F.goal.select();if($&&$.id===\"call\"&&$.search(y)){F=z;break}}for(var se=w.points.length-1;se>=0;se--){for(var xe=w.points[se],Fe=xe.parent;Fe!==null&&Fe!==F.parent;)Fe=Fe.parent;Fe===null&&Fe!==F.parent&&Z.push(xe)}w.points=Z.reverse(),w.success(b)},\"\\\\+/1\":function(w,b,y){var F=y.args[0];P.type.is_variable(F)?w.throw_error(P.error.instantiation(w.level)):P.type.is_callable(F)?w.prepend([new be(b.goal.replace(new _(\",\",[new _(\",\",[new _(\"call\",[F]),new _(\"!\",[])]),new _(\"fail\",[])])),b.substitution,b),new be(b.goal.replace(null),b.substitution,b)]):w.throw_error(P.error.type(\"callable\",F,w.level))},\"->/2\":function(w,b,y){var F=b.goal.replace(new _(\",\",[y.args[0],new _(\",\",[new _(\"!\"),y.args[1]])]));w.prepend([new be(F,b.substitution,b)])},\"fail/0\":function(w,b,y){},\"false/0\":function(w,b,y){},\"true/0\":function(w,b,y){w.success(b)},\"call/1\":ce(1),\"call/2\":ce(2),\"call/3\":ce(3),\"call/4\":ce(4),\"call/5\":ce(5),\"call/6\":ce(6),\"call/7\":ce(7),\"call/8\":ce(8),\"once/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"call\",[F]),new _(\"!\",[])])),b.substitution,b)])},\"forall/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\"\\\\+\",[new _(\",\",[new _(\"call\",[F]),new _(\"\\\\+\",[new _(\"call\",[z])])])])),b.substitution,b)])},\"repeat/0\":function(w,b,y){w.prepend([new be(b.goal.replace(null),b.substitution,b),b])},\"throw/1\":function(w,b,y){P.type.is_variable(y.args[0])?w.throw_error(P.error.instantiation(w.level)):w.throw_error(y.args[0])},\"catch/3\":function(w,b,y){var F=w.points;w.points=[],w.prepend([new be(y.args[0],b.substitution,b)]);var z=w.session.format_success,Z=w.session.format_error;w.session.format_success=function(se){return se.substitution},w.session.format_error=function(se){return se.goal};var $=function(se){var xe=w.points;if(w.points=F,w.session.format_success=z,w.session.format_error=Z,P.type.is_error(se)){for(var Fe=[],ut=w.points.length-1;ut>=0;ut--){for(var ir=w.points[ut],Ct=ir.parent;Ct!==null&&Ct!==b.parent;)Ct=Ct.parent;Ct===null&&Ct!==b.parent&&Fe.push(ir)}w.points=Fe;var qt=w.get_flag(\"occurs_check\").indicator===\"true/0\",ir=new be,Pt=P.unify(se.args[0],y.args[1],qt);Pt!==null?(ir.substitution=b.substitution.apply(Pt),ir.goal=b.goal.replace(y.args[2]).apply(Pt),ir.parent=b,w.prepend([ir])):w.throw_error(se.args[0])}else if(se!==!1){for(var dn=se===null?[]:[new be(b.goal.apply(se).replace(null),b.substitution.apply(se),b)],Pr=[],ut=xe.length-1;ut>=0;ut--){Pr.push(xe[ut]);var Ir=xe[ut].goal!==null?xe[ut].goal.select():null;if(P.type.is_term(Ir)&&Ir.indicator===\"!/0\")break}var Or=s(Pr,function(on){return on.goal===null&&(on.goal=new _(\"true\",[])),on=new be(b.goal.replace(new _(\"catch\",[on.goal,y.args[1],y.args[2]])),b.substitution.apply(on.substitution),on.parent),on.exclude=y.args[0].variables(),on}).reverse();w.prepend(Or),w.prepend(dn),se===null&&(this.current_limit=0,w.__calls.shift()(null))}};w.__calls.unshift($)},\"=/2\":function(w,b,y){var F=w.get_flag(\"occurs_check\").indicator===\"true/0\",z=new be,Z=P.unify(y.args[0],y.args[1],F);Z!==null&&(z.goal=b.goal.apply(Z).replace(null),z.substitution=b.substitution.apply(Z),z.parent=b,w.prepend([z]))},\"unify_with_occurs_check/2\":function(w,b,y){var F=new be,z=P.unify(y.args[0],y.args[1],!0);z!==null&&(F.goal=b.goal.apply(z).replace(null),F.substitution=b.substitution.apply(z),F.parent=b,w.prepend([F]))},\"\\\\=/2\":function(w,b,y){var F=w.get_flag(\"occurs_check\").indicator===\"true/0\",z=P.unify(y.args[0],y.args[1],F);z===null&&w.success(b)},\"subsumes_term/2\":function(w,b,y){var F=w.get_flag(\"occurs_check\").indicator===\"true/0\",z=P.unify(y.args[1],y.args[0],F);z!==null&&y.args[1].apply(z).equals(y.args[1])&&w.success(b)},\"findall/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2];if(P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(z))w.throw_error(P.error.type(\"callable\",z,y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_list(Z))w.throw_error(P.error.type(\"list\",Z,y.indicator));else{var $=w.next_free_variable(),se=new _(\",\",[z,new _(\"=\",[$,F])]),xe=w.points,Fe=w.session.limit,ut=w.session.format_success;w.session.format_success=function(ir){return ir.substitution},w.add_goal(se,!0,b);var Ct=[],qt=function(ir){if(ir!==!1&&ir!==null&&!P.type.is_error(ir))w.__calls.unshift(qt),Ct.push(ir.links[$.id]),w.session.limit=w.current_limit;else if(w.points=xe,w.session.limit=Fe,w.session.format_success=ut,P.type.is_error(ir))w.throw_error(ir.args[0]);else if(w.current_limit>0){for(var Pt=new _(\"[]\"),dn=Ct.length-1;dn>=0;dn--)Pt=new _(\".\",[Ct[dn],Pt]);w.prepend([new be(b.goal.replace(new _(\"=\",[Z,Pt])),b.substitution,b)])}};w.__calls.unshift(qt)}},\"bagof/3\":function(w,b,y){var F,z=y.args[0],Z=y.args[1],$=y.args[2];if(P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(Z))w.throw_error(P.error.type(\"callable\",Z,y.indicator));else if(!P.type.is_variable($)&&!P.type.is_list($))w.throw_error(P.error.type(\"list\",$,y.indicator));else{var se=w.next_free_variable(),xe;Z.indicator===\"^/2\"?(xe=Z.args[0].variables(),Z=Z.args[1]):xe=[],xe=xe.concat(z.variables());for(var Fe=Z.variables().filter(function(Or){return t(xe,Or)===-1}),ut=new _(\"[]\"),Ct=Fe.length-1;Ct>=0;Ct--)ut=new _(\".\",[new De(Fe[Ct]),ut]);var qt=new _(\",\",[Z,new _(\"=\",[se,new _(\",\",[ut,z])])]),ir=w.points,Pt=w.session.limit,dn=w.session.format_success;w.session.format_success=function(Or){return Or.substitution},w.add_goal(qt,!0,b);var Pr=[],Ir=function(Or){if(Or!==!1&&Or!==null&&!P.type.is_error(Or)){w.__calls.unshift(Ir);var on=!1,li=Or.links[se.id].args[0],So=Or.links[se.id].args[1];for(var ns in Pr)if(Pr.hasOwnProperty(ns)){var so=Pr[ns];if(so.variables.equals(li)){so.answers.push(So),on=!0;break}}on||Pr.push({variables:li,answers:[So]}),w.session.limit=w.current_limit}else if(w.points=ir,w.session.limit=Pt,w.session.format_success=dn,P.type.is_error(Or))w.throw_error(Or.args[0]);else if(w.current_limit>0){for(var Do=[],ji=0;ji<Pr.length;ji++){Or=Pr[ji].answers;for(var oo=new _(\"[]\"),bo=Or.length-1;bo>=0;bo--)oo=new _(\".\",[Or[bo],oo]);Do.push(new be(b.goal.replace(new _(\",\",[new _(\"=\",[ut,Pr[ji].variables]),new _(\"=\",[$,oo])])),b.substitution,b))}w.prepend(Do)}};w.__calls.unshift(Ir)}},\"setof/3\":function(w,b,y){var F,z=y.args[0],Z=y.args[1],$=y.args[2];if(P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(Z))w.throw_error(P.error.type(\"callable\",Z,y.indicator));else if(!P.type.is_variable($)&&!P.type.is_list($))w.throw_error(P.error.type(\"list\",$,y.indicator));else{var se=w.next_free_variable(),xe;Z.indicator===\"^/2\"?(xe=Z.args[0].variables(),Z=Z.args[1]):xe=[],xe=xe.concat(z.variables());for(var Fe=Z.variables().filter(function(Or){return t(xe,Or)===-1}),ut=new _(\"[]\"),Ct=Fe.length-1;Ct>=0;Ct--)ut=new _(\".\",[new De(Fe[Ct]),ut]);var qt=new _(\",\",[Z,new _(\"=\",[se,new _(\",\",[ut,z])])]),ir=w.points,Pt=w.session.limit,dn=w.session.format_success;w.session.format_success=function(Or){return Or.substitution},w.add_goal(qt,!0,b);var Pr=[],Ir=function(Or){if(Or!==!1&&Or!==null&&!P.type.is_error(Or)){w.__calls.unshift(Ir);var on=!1,li=Or.links[se.id].args[0],So=Or.links[se.id].args[1];for(var ns in Pr)if(Pr.hasOwnProperty(ns)){var so=Pr[ns];if(so.variables.equals(li)){so.answers.push(So),on=!0;break}}on||Pr.push({variables:li,answers:[So]}),w.session.limit=w.current_limit}else if(w.points=ir,w.session.limit=Pt,w.session.format_success=dn,P.type.is_error(Or))w.throw_error(Or.args[0]);else if(w.current_limit>0){for(var Do=[],ji=0;ji<Pr.length;ji++){Or=Pr[ji].answers.sort(P.compare);for(var oo=new _(\"[]\"),bo=Or.length-1;bo>=0;bo--)oo=new _(\".\",[Or[bo],oo]);Do.push(new be(b.goal.replace(new _(\",\",[new _(\"=\",[ut,Pr[ji].variables]),new _(\"=\",[$,oo])])),b.substitution,b))}w.prepend(Do)}};w.__calls.unshift(Ir)}},\"functor/3\":function(w,b,y){var F,z=y.args[0],Z=y.args[1],$=y.args[2];if(P.type.is_variable(z)&&(P.type.is_variable(Z)||P.type.is_variable($)))w.throw_error(P.error.instantiation(\"functor/3\"));else if(!P.type.is_variable($)&&!P.type.is_integer($))w.throw_error(P.error.type(\"integer\",y.args[2],\"functor/3\"));else if(!P.type.is_variable(Z)&&!P.type.is_atomic(Z))w.throw_error(P.error.type(\"atomic\",y.args[1],\"functor/3\"));else if(P.type.is_integer(Z)&&P.type.is_integer($)&&$.value!==0)w.throw_error(P.error.type(\"atom\",y.args[1],\"functor/3\"));else if(P.type.is_variable(z)){if(y.args[2].value>=0){for(var se=[],xe=0;xe<$.value;xe++)se.push(w.next_free_variable());var Fe=P.type.is_integer(Z)?Z:new _(Z.id,se);w.prepend([new be(b.goal.replace(new _(\"=\",[z,Fe])),b.substitution,b)])}}else{var ut=P.type.is_integer(z)?z:new _(z.id,[]),Ct=P.type.is_integer(z)?new Qe(0,!1):new Qe(z.args.length,!1),qt=new _(\",\",[new _(\"=\",[ut,Z]),new _(\"=\",[Ct,$])]);w.prepend([new be(b.goal.replace(qt),b.substitution,b)])}},\"arg/3\":function(w,b,y){if(P.type.is_variable(y.args[0])||P.type.is_variable(y.args[1]))w.throw_error(P.error.instantiation(y.indicator));else if(y.args[0].value<0)w.throw_error(P.error.domain(\"not_less_than_zero\",y.args[0],y.indicator));else if(!P.type.is_compound(y.args[1]))w.throw_error(P.error.type(\"compound\",y.args[1],y.indicator));else{var F=y.args[0].value;if(F>0&&F<=y.args[1].args.length){var z=new _(\"=\",[y.args[1].args[F-1],y.args[2]]);w.prepend([new be(b.goal.replace(z),b.substitution,b)])}}},\"=../2\":function(w,b,y){var F;if(P.type.is_variable(y.args[0])&&(P.type.is_variable(y.args[1])||P.type.is_non_empty_list(y.args[1])&&P.type.is_variable(y.args[1].args[0])))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_fully_list(y.args[1]))w.throw_error(P.error.type(\"list\",y.args[1],y.indicator));else if(P.type.is_variable(y.args[0])){if(!P.type.is_variable(y.args[1])){var Z=[];for(F=y.args[1].args[1];F.indicator===\"./2\";)Z.push(F.args[0]),F=F.args[1];P.type.is_variable(y.args[0])&&P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):Z.length===0&&P.type.is_compound(y.args[1].args[0])?w.throw_error(P.error.type(\"atomic\",y.args[1].args[0],y.indicator)):Z.length>0&&(P.type.is_compound(y.args[1].args[0])||P.type.is_number(y.args[1].args[0]))?w.throw_error(P.error.type(\"atom\",y.args[1].args[0],y.indicator)):Z.length===0?w.prepend([new be(b.goal.replace(new _(\"=\",[y.args[1].args[0],y.args[0]],b)),b.substitution,b)]):w.prepend([new be(b.goal.replace(new _(\"=\",[new _(y.args[1].args[0].id,Z),y.args[0]])),b.substitution,b)])}}else{if(P.type.is_atomic(y.args[0]))F=new _(\".\",[y.args[0],new _(\"[]\")]);else{F=new _(\"[]\");for(var z=y.args[0].args.length-1;z>=0;z--)F=new _(\".\",[y.args[0].args[z],F]);F=new _(\".\",[new _(y.args[0].id),F])}w.prepend([new be(b.goal.replace(new _(\"=\",[F,y.args[1]])),b.substitution,b)])}},\"copy_term/2\":function(w,b,y){var F=y.args[0].rename(w);w.prepend([new be(b.goal.replace(new _(\"=\",[F,y.args[1]])),b.substitution,b.parent)])},\"term_variables/2\":function(w,b,y){var F=y.args[0],z=y.args[1];if(!P.type.is_fully_list(z))w.throw_error(P.error.type(\"list\",z,y.indicator));else{var Z=g(s(Be(F.variables()),function($){return new De($)}));w.prepend([new be(b.goal.replace(new _(\"=\",[z,Z])),b.substitution,b)])}},\"clause/2\":function(w,b,y){if(P.type.is_variable(y.args[0]))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(y.args[0]))w.throw_error(P.error.type(\"callable\",y.args[0],y.indicator));else if(!P.type.is_variable(y.args[1])&&!P.type.is_callable(y.args[1]))w.throw_error(P.error.type(\"callable\",y.args[1],y.indicator));else if(w.session.rules[y.args[0].indicator]!==void 0)if(w.is_public_predicate(y.args[0].indicator)){var F=[];for(var z in w.session.rules[y.args[0].indicator])if(w.session.rules[y.args[0].indicator].hasOwnProperty(z)){var Z=w.session.rules[y.args[0].indicator][z];w.session.renamed_variables={},Z=Z.rename(w),Z.body===null&&(Z.body=new _(\"true\"));var $=new _(\",\",[new _(\"=\",[Z.head,y.args[0]]),new _(\"=\",[Z.body,y.args[1]])]);F.push(new be(b.goal.replace($),b.substitution,b))}w.prepend(F)}else w.throw_error(P.error.permission(\"access\",\"private_procedure\",y.args[0].indicator,y.indicator))},\"current_predicate/1\":function(w,b,y){var F=y.args[0];if(!P.type.is_variable(F)&&(!P.type.is_compound(F)||F.indicator!==\"//2\"))w.throw_error(P.error.type(\"predicate_indicator\",F,y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_variable(F.args[0])&&!P.type.is_atom(F.args[0]))w.throw_error(P.error.type(\"atom\",F.args[0],y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_variable(F.args[1])&&!P.type.is_integer(F.args[1]))w.throw_error(P.error.type(\"integer\",F.args[1],y.indicator));else{var z=[];for(var Z in w.session.rules)if(w.session.rules.hasOwnProperty(Z)){var $=Z.lastIndexOf(\"/\"),se=Z.substr(0,$),xe=parseInt(Z.substr($+1,Z.length-($+1))),Fe=new _(\"/\",[new _(se),new Qe(xe,!1)]),ut=new _(\"=\",[Fe,F]);z.push(new be(b.goal.replace(ut),b.substitution,b))}w.prepend(z)}},\"asserta/1\":function(w,b,y){if(P.type.is_variable(y.args[0]))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(y.args[0]))w.throw_error(P.error.type(\"callable\",y.args[0],y.indicator));else{var F,z;y.args[0].indicator===\":-/2\"?(F=y.args[0].args[0],z=Ee(y.args[0].args[1])):(F=y.args[0],z=null),P.type.is_callable(F)?z!==null&&!P.type.is_callable(z)?w.throw_error(P.error.type(\"callable\",z,y.indicator)):w.is_public_predicate(F.indicator)?(w.session.rules[F.indicator]===void 0&&(w.session.rules[F.indicator]=[]),w.session.public_predicates[F.indicator]=!0,w.session.rules[F.indicator]=[new je(F,z,!0)].concat(w.session.rules[F.indicator]),w.success(b)):w.throw_error(P.error.permission(\"modify\",\"static_procedure\",F.indicator,y.indicator)):w.throw_error(P.error.type(\"callable\",F,y.indicator))}},\"assertz/1\":function(w,b,y){if(P.type.is_variable(y.args[0]))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(y.args[0]))w.throw_error(P.error.type(\"callable\",y.args[0],y.indicator));else{var F,z;y.args[0].indicator===\":-/2\"?(F=y.args[0].args[0],z=Ee(y.args[0].args[1])):(F=y.args[0],z=null),P.type.is_callable(F)?z!==null&&!P.type.is_callable(z)?w.throw_error(P.error.type(\"callable\",z,y.indicator)):w.is_public_predicate(F.indicator)?(w.session.rules[F.indicator]===void 0&&(w.session.rules[F.indicator]=[]),w.session.public_predicates[F.indicator]=!0,w.session.rules[F.indicator].push(new je(F,z,!0)),w.success(b)):w.throw_error(P.error.permission(\"modify\",\"static_procedure\",F.indicator,y.indicator)):w.throw_error(P.error.type(\"callable\",F,y.indicator))}},\"retract/1\":function(w,b,y){if(P.type.is_variable(y.args[0]))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_callable(y.args[0]))w.throw_error(P.error.type(\"callable\",y.args[0],y.indicator));else{var F,z;if(y.args[0].indicator===\":-/2\"?(F=y.args[0].args[0],z=y.args[0].args[1]):(F=y.args[0],z=new _(\"true\")),typeof b.retract>\"u\")if(w.is_public_predicate(F.indicator)){if(w.session.rules[F.indicator]!==void 0){for(var Z=[],$=0;$<w.session.rules[F.indicator].length;$++){w.session.renamed_variables={};var se=w.session.rules[F.indicator][$],xe=se.rename(w);xe.body===null&&(xe.body=new _(\"true\",[]));var Fe=w.get_flag(\"occurs_check\").indicator===\"true/0\",ut=P.unify(new _(\",\",[F,z]),new _(\",\",[xe.head,xe.body]),Fe);if(ut!==null){var Ct=new be(b.goal.replace(new _(\",\",[new _(\"retract\",[new _(\":-\",[F,z])]),new _(\",\",[new _(\"=\",[F,xe.head]),new _(\"=\",[z,xe.body])])])),b.substitution,b);Ct.retract=se,Z.push(Ct)}}w.prepend(Z)}}else w.throw_error(P.error.permission(\"modify\",\"static_procedure\",F.indicator,y.indicator));else me(w,b,F.indicator,b.retract)}},\"retractall/1\":function(w,b,y){var F=y.args[0];P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_callable(F)?w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"retract\",[new P.type.Term(\":-\",[F,new De(\"_\")])]),new _(\"fail\",[])])),b.substitution,b),new be(b.goal.replace(null),b.substitution,b)]):w.throw_error(P.error.type(\"callable\",F,y.indicator))},\"abolish/1\":function(w,b,y){if(P.type.is_variable(y.args[0])||P.type.is_term(y.args[0])&&y.args[0].indicator===\"//2\"&&(P.type.is_variable(y.args[0].args[0])||P.type.is_variable(y.args[0].args[1])))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_term(y.args[0])||y.args[0].indicator!==\"//2\")w.throw_error(P.error.type(\"predicate_indicator\",y.args[0],y.indicator));else if(!P.type.is_atom(y.args[0].args[0]))w.throw_error(P.error.type(\"atom\",y.args[0].args[0],y.indicator));else if(!P.type.is_integer(y.args[0].args[1]))w.throw_error(P.error.type(\"integer\",y.args[0].args[1],y.indicator));else if(y.args[0].args[1].value<0)w.throw_error(P.error.domain(\"not_less_than_zero\",y.args[0].args[1],y.indicator));else if(P.type.is_number(w.get_flag(\"max_arity\"))&&y.args[0].args[1].value>w.get_flag(\"max_arity\").value)w.throw_error(P.error.representation(\"max_arity\",y.indicator));else{var F=y.args[0].args[0].id+\"/\"+y.args[0].args[1].value;w.is_public_predicate(F)?(delete w.session.rules[F],w.success(b)):w.throw_error(P.error.permission(\"modify\",\"static_procedure\",F,y.indicator))}},\"atom_length/2\":function(w,b,y){if(P.type.is_variable(y.args[0]))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_atom(y.args[0]))w.throw_error(P.error.type(\"atom\",y.args[0],y.indicator));else if(!P.type.is_variable(y.args[1])&&!P.type.is_integer(y.args[1]))w.throw_error(P.error.type(\"integer\",y.args[1],y.indicator));else if(P.type.is_integer(y.args[1])&&y.args[1].value<0)w.throw_error(P.error.domain(\"not_less_than_zero\",y.args[1],y.indicator));else{var F=new Qe(y.args[0].id.length,!1);w.prepend([new be(b.goal.replace(new _(\"=\",[F,y.args[1]])),b.substitution,b)])}},\"atom_concat/3\":function(w,b,y){var F,z,Z=y.args[0],$=y.args[1],se=y.args[2];if(P.type.is_variable(se)&&(P.type.is_variable(Z)||P.type.is_variable($)))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_atom(Z))w.throw_error(P.error.type(\"atom\",Z,y.indicator));else if(!P.type.is_variable($)&&!P.type.is_atom($))w.throw_error(P.error.type(\"atom\",$,y.indicator));else if(!P.type.is_variable(se)&&!P.type.is_atom(se))w.throw_error(P.error.type(\"atom\",se,y.indicator));else{var xe=P.type.is_variable(Z),Fe=P.type.is_variable($);if(!xe&&!Fe)z=new _(\"=\",[se,new _(Z.id+$.id)]),w.prepend([new be(b.goal.replace(z),b.substitution,b)]);else if(xe&&!Fe)F=se.id.substr(0,se.id.length-$.id.length),F+$.id===se.id&&(z=new _(\"=\",[Z,new _(F)]),w.prepend([new be(b.goal.replace(z),b.substitution,b)]));else if(Fe&&!xe)F=se.id.substr(Z.id.length),Z.id+F===se.id&&(z=new _(\"=\",[$,new _(F)]),w.prepend([new be(b.goal.replace(z),b.substitution,b)]));else{for(var ut=[],Ct=0;Ct<=se.id.length;Ct++){var qt=new _(se.id.substr(0,Ct)),ir=new _(se.id.substr(Ct));z=new _(\",\",[new _(\"=\",[qt,Z]),new _(\"=\",[ir,$])]),ut.push(new be(b.goal.replace(z),b.substitution,b))}w.prepend(ut)}}},\"sub_atom/5\":function(w,b,y){var F,z=y.args[0],Z=y.args[1],$=y.args[2],se=y.args[3],xe=y.args[4];if(P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_integer(Z))w.throw_error(P.error.type(\"integer\",Z,y.indicator));else if(!P.type.is_variable($)&&!P.type.is_integer($))w.throw_error(P.error.type(\"integer\",$,y.indicator));else if(!P.type.is_variable(se)&&!P.type.is_integer(se))w.throw_error(P.error.type(\"integer\",se,y.indicator));else if(P.type.is_integer(Z)&&Z.value<0)w.throw_error(P.error.domain(\"not_less_than_zero\",Z,y.indicator));else if(P.type.is_integer($)&&$.value<0)w.throw_error(P.error.domain(\"not_less_than_zero\",$,y.indicator));else if(P.type.is_integer(se)&&se.value<0)w.throw_error(P.error.domain(\"not_less_than_zero\",se,y.indicator));else{var Fe=[],ut=[],Ct=[];if(P.type.is_variable(Z))for(F=0;F<=z.id.length;F++)Fe.push(F);else Fe.push(Z.value);if(P.type.is_variable($))for(F=0;F<=z.id.length;F++)ut.push(F);else ut.push($.value);if(P.type.is_variable(se))for(F=0;F<=z.id.length;F++)Ct.push(F);else Ct.push(se.value);var qt=[];for(var ir in Fe)if(Fe.hasOwnProperty(ir)){F=Fe[ir];for(var Pt in ut)if(ut.hasOwnProperty(Pt)){var dn=ut[Pt],Pr=z.id.length-F-dn;if(t(Ct,Pr)!==-1&&F+dn+Pr===z.id.length){var Ir=z.id.substr(F,dn);if(z.id===z.id.substr(0,F)+Ir+z.id.substr(F+dn,Pr)){var Or=new _(\"=\",[new _(Ir),xe]),on=new _(\"=\",[Z,new Qe(F)]),li=new _(\"=\",[$,new Qe(dn)]),So=new _(\"=\",[se,new Qe(Pr)]),ns=new _(\",\",[new _(\",\",[new _(\",\",[on,li]),So]),Or]);qt.push(new be(b.goal.replace(ns),b.substitution,b))}}}}w.prepend(qt)}},\"atom_chars/2\":function(w,b,y){var F=y.args[0],z=y.args[1];if(P.type.is_variable(F)&&P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_atom(F))w.throw_error(P.error.type(\"atom\",F,y.indicator));else if(P.type.is_variable(F)){for(var se=z,xe=P.type.is_variable(F),Fe=\"\";se.indicator===\"./2\";){if(P.type.is_character(se.args[0]))Fe+=se.args[0].id;else if(P.type.is_variable(se.args[0])&&xe){w.throw_error(P.error.instantiation(y.indicator));return}else if(!P.type.is_variable(se.args[0])){w.throw_error(P.error.type(\"character\",se.args[0],y.indicator));return}se=se.args[1]}P.type.is_variable(se)&&xe?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_empty_list(se)&&!P.type.is_variable(se)?w.throw_error(P.error.type(\"list\",z,y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[new _(Fe),F])),b.substitution,b)])}else{for(var Z=new _(\"[]\"),$=F.id.length-1;$>=0;$--)Z=new _(\".\",[new _(F.id.charAt($)),Z]);w.prepend([new be(b.goal.replace(new _(\"=\",[z,Z])),b.substitution,b)])}},\"atom_codes/2\":function(w,b,y){var F=y.args[0],z=y.args[1];if(P.type.is_variable(F)&&P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_atom(F))w.throw_error(P.error.type(\"atom\",F,y.indicator));else if(P.type.is_variable(F)){for(var se=z,xe=P.type.is_variable(F),Fe=\"\";se.indicator===\"./2\";){if(P.type.is_character_code(se.args[0]))Fe+=c(se.args[0].value);else if(P.type.is_variable(se.args[0])&&xe){w.throw_error(P.error.instantiation(y.indicator));return}else if(!P.type.is_variable(se.args[0])){w.throw_error(P.error.representation(\"character_code\",y.indicator));return}se=se.args[1]}P.type.is_variable(se)&&xe?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_empty_list(se)&&!P.type.is_variable(se)?w.throw_error(P.error.type(\"list\",z,y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[new _(Fe),F])),b.substitution,b)])}else{for(var Z=new _(\"[]\"),$=F.id.length-1;$>=0;$--)Z=new _(\".\",[new Qe(n(F.id,$),!1),Z]);w.prepend([new be(b.goal.replace(new _(\"=\",[z,Z])),b.substitution,b)])}},\"char_code/2\":function(w,b,y){var F=y.args[0],z=y.args[1];if(P.type.is_variable(F)&&P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_character(F))w.throw_error(P.error.type(\"character\",F,y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_integer(z))w.throw_error(P.error.type(\"integer\",z,y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_character_code(z))w.throw_error(P.error.representation(\"character_code\",y.indicator));else if(P.type.is_variable(z)){var Z=new Qe(n(F.id,0),!1);w.prepend([new be(b.goal.replace(new _(\"=\",[Z,z])),b.substitution,b)])}else{var $=new _(c(z.value));w.prepend([new be(b.goal.replace(new _(\"=\",[$,F])),b.substitution,b)])}},\"number_chars/2\":function(w,b,y){var F,z=y.args[0],Z=y.args[1];if(P.type.is_variable(z)&&P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_number(z))w.throw_error(P.error.type(\"number\",z,y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_list(Z))w.throw_error(P.error.type(\"list\",Z,y.indicator));else{var $=P.type.is_variable(z);if(!P.type.is_variable(Z)){var se=Z,xe=!0;for(F=\"\";se.indicator===\"./2\";){if(P.type.is_character(se.args[0]))F+=se.args[0].id;else if(P.type.is_variable(se.args[0]))xe=!1;else if(!P.type.is_variable(se.args[0])){w.throw_error(P.error.type(\"character\",se.args[0],y.indicator));return}se=se.args[1]}if(xe=xe&&P.type.is_empty_list(se),!P.type.is_empty_list(se)&&!P.type.is_variable(se)){w.throw_error(P.error.type(\"list\",Z,y.indicator));return}if(!xe&&$){w.throw_error(P.error.instantiation(y.indicator));return}else if(xe)if(P.type.is_variable(se)&&$){w.throw_error(P.error.instantiation(y.indicator));return}else{var Fe=w.parse(F),ut=Fe.value;!P.type.is_number(ut)||Fe.tokens[Fe.tokens.length-1].space?w.throw_error(P.error.syntax_by_predicate(\"parseable_number\",y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[z,ut])),b.substitution,b)]);return}}if(!$){F=z.toString();for(var Ct=new _(\"[]\"),qt=F.length-1;qt>=0;qt--)Ct=new _(\".\",[new _(F.charAt(qt)),Ct]);w.prepend([new be(b.goal.replace(new _(\"=\",[Z,Ct])),b.substitution,b)])}}},\"number_codes/2\":function(w,b,y){var F,z=y.args[0],Z=y.args[1];if(P.type.is_variable(z)&&P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_number(z))w.throw_error(P.error.type(\"number\",z,y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_list(Z))w.throw_error(P.error.type(\"list\",Z,y.indicator));else{var $=P.type.is_variable(z);if(!P.type.is_variable(Z)){var se=Z,xe=!0;for(F=\"\";se.indicator===\"./2\";){if(P.type.is_character_code(se.args[0]))F+=c(se.args[0].value);else if(P.type.is_variable(se.args[0]))xe=!1;else if(!P.type.is_variable(se.args[0])){w.throw_error(P.error.type(\"character_code\",se.args[0],y.indicator));return}se=se.args[1]}if(xe=xe&&P.type.is_empty_list(se),!P.type.is_empty_list(se)&&!P.type.is_variable(se)){w.throw_error(P.error.type(\"list\",Z,y.indicator));return}if(!xe&&$){w.throw_error(P.error.instantiation(y.indicator));return}else if(xe)if(P.type.is_variable(se)&&$){w.throw_error(P.error.instantiation(y.indicator));return}else{var Fe=w.parse(F),ut=Fe.value;!P.type.is_number(ut)||Fe.tokens[Fe.tokens.length-1].space?w.throw_error(P.error.syntax_by_predicate(\"parseable_number\",y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[z,ut])),b.substitution,b)]);return}}if(!$){F=z.toString();for(var Ct=new _(\"[]\"),qt=F.length-1;qt>=0;qt--)Ct=new _(\".\",[new Qe(n(F,qt),!1),Ct]);w.prepend([new be(b.goal.replace(new _(\"=\",[Z,Ct])),b.substitution,b)])}}},\"upcase_atom/2\":function(w,b,y){var F=y.args[0],z=y.args[1];P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_atom(F)?!P.type.is_variable(z)&&!P.type.is_atom(z)?w.throw_error(P.error.type(\"atom\",z,y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[z,new _(F.id.toUpperCase(),[])])),b.substitution,b)]):w.throw_error(P.error.type(\"atom\",F,y.indicator))},\"downcase_atom/2\":function(w,b,y){var F=y.args[0],z=y.args[1];P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_atom(F)?!P.type.is_variable(z)&&!P.type.is_atom(z)?w.throw_error(P.error.type(\"atom\",z,y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[z,new _(F.id.toLowerCase(),[])])),b.substitution,b)]):w.throw_error(P.error.type(\"atom\",F,y.indicator))},\"atomic_list_concat/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\"atomic_list_concat\",[F,new _(\"\",[]),z])),b.substitution,b)])},\"atomic_list_concat/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2];if(P.type.is_variable(z)||P.type.is_variable(F)&&P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_list(F))w.throw_error(P.error.type(\"list\",F,y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_atom(Z))w.throw_error(P.error.type(\"atom\",Z,y.indicator));else if(P.type.is_variable(Z)){for(var se=\"\",xe=F;P.type.is_term(xe)&&xe.indicator===\"./2\";){if(!P.type.is_atom(xe.args[0])&&!P.type.is_number(xe.args[0])){w.throw_error(P.error.type(\"atomic\",xe.args[0],y.indicator));return}se!==\"\"&&(se+=z.id),P.type.is_atom(xe.args[0])?se+=xe.args[0].id:se+=\"\"+xe.args[0].value,xe=xe.args[1]}se=new _(se,[]),P.type.is_variable(xe)?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_term(xe)||xe.indicator!==\"[]/0\"?w.throw_error(P.error.type(\"list\",F,y.indicator)):w.prepend([new be(b.goal.replace(new _(\"=\",[se,Z])),b.substitution,b)])}else{var $=g(s(Z.id.split(z.id),function(Fe){return new _(Fe,[])}));w.prepend([new be(b.goal.replace(new _(\"=\",[$,F])),b.substitution,b)])}},\"@=</2\":function(w,b,y){P.compare(y.args[0],y.args[1])<=0&&w.success(b)},\"==/2\":function(w,b,y){P.compare(y.args[0],y.args[1])===0&&w.success(b)},\"\\\\==/2\":function(w,b,y){P.compare(y.args[0],y.args[1])!==0&&w.success(b)},\"@</2\":function(w,b,y){P.compare(y.args[0],y.args[1])<0&&w.success(b)},\"@>/2\":function(w,b,y){P.compare(y.args[0],y.args[1])>0&&w.success(b)},\"@>=/2\":function(w,b,y){P.compare(y.args[0],y.args[1])>=0&&w.success(b)},\"compare/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2];if(!P.type.is_variable(F)&&!P.type.is_atom(F))w.throw_error(P.error.type(\"atom\",F,y.indicator));else if(P.type.is_atom(F)&&[\"<\",\">\",\"=\"].indexOf(F.id)===-1)w.throw_error(P.type.domain(\"order\",F,y.indicator));else{var $=P.compare(z,Z);$=$===0?\"=\":$===-1?\"<\":\">\",w.prepend([new be(b.goal.replace(new _(\"=\",[F,new _($,[])])),b.substitution,b)])}},\"is/2\":function(w,b,y){var F=y.args[1].interpret(w);P.type.is_number(F)?w.prepend([new be(b.goal.replace(new _(\"=\",[y.args[0],F],w.level)),b.substitution,b)]):w.throw_error(F)},\"between/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2];if(P.type.is_variable(F)||P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_integer(F))w.throw_error(P.error.type(\"integer\",F,y.indicator));else if(!P.type.is_integer(z))w.throw_error(P.error.type(\"integer\",z,y.indicator));else if(!P.type.is_variable(Z)&&!P.type.is_integer(Z))w.throw_error(P.error.type(\"integer\",Z,y.indicator));else if(P.type.is_variable(Z)){var $=[new be(b.goal.replace(new _(\"=\",[Z,F])),b.substitution,b)];F.value<z.value&&$.push(new be(b.goal.replace(new _(\"between\",[new Qe(F.value+1,!1),z,Z])),b.substitution,b)),w.prepend($)}else F.value<=Z.value&&z.value>=Z.value&&w.success(b)},\"succ/2\":function(w,b,y){var F=y.args[0],z=y.args[1];P.type.is_variable(F)&&P.type.is_variable(z)?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_variable(F)&&!P.type.is_integer(F)?w.throw_error(P.error.type(\"integer\",F,y.indicator)):!P.type.is_variable(z)&&!P.type.is_integer(z)?w.throw_error(P.error.type(\"integer\",z,y.indicator)):!P.type.is_variable(F)&&F.value<0?w.throw_error(P.error.domain(\"not_less_than_zero\",F,y.indicator)):!P.type.is_variable(z)&&z.value<0?w.throw_error(P.error.domain(\"not_less_than_zero\",z,y.indicator)):(P.type.is_variable(z)||z.value>0)&&(P.type.is_variable(F)?w.prepend([new be(b.goal.replace(new _(\"=\",[F,new Qe(z.value-1,!1)])),b.substitution,b)]):w.prepend([new be(b.goal.replace(new _(\"=\",[z,new Qe(F.value+1,!1)])),b.substitution,b)]))},\"=:=/2\":function(w,b,y){var F=P.arithmetic_compare(w,y.args[0],y.args[1]);P.type.is_term(F)?w.throw_error(F):F===0&&w.success(b)},\"=\\\\=/2\":function(w,b,y){var F=P.arithmetic_compare(w,y.args[0],y.args[1]);P.type.is_term(F)?w.throw_error(F):F!==0&&w.success(b)},\"</2\":function(w,b,y){var F=P.arithmetic_compare(w,y.args[0],y.args[1]);P.type.is_term(F)?w.throw_error(F):F<0&&w.success(b)},\"=</2\":function(w,b,y){var F=P.arithmetic_compare(w,y.args[0],y.args[1]);P.type.is_term(F)?w.throw_error(F):F<=0&&w.success(b)},\">/2\":function(w,b,y){var F=P.arithmetic_compare(w,y.args[0],y.args[1]);P.type.is_term(F)?w.throw_error(F):F>0&&w.success(b)},\">=/2\":function(w,b,y){var F=P.arithmetic_compare(w,y.args[0],y.args[1]);P.type.is_term(F)?w.throw_error(F):F>=0&&w.success(b)},\"var/1\":function(w,b,y){P.type.is_variable(y.args[0])&&w.success(b)},\"atom/1\":function(w,b,y){P.type.is_atom(y.args[0])&&w.success(b)},\"atomic/1\":function(w,b,y){P.type.is_atomic(y.args[0])&&w.success(b)},\"compound/1\":function(w,b,y){P.type.is_compound(y.args[0])&&w.success(b)},\"integer/1\":function(w,b,y){P.type.is_integer(y.args[0])&&w.success(b)},\"float/1\":function(w,b,y){P.type.is_float(y.args[0])&&w.success(b)},\"number/1\":function(w,b,y){P.type.is_number(y.args[0])&&w.success(b)},\"nonvar/1\":function(w,b,y){P.type.is_variable(y.args[0])||w.success(b)},\"ground/1\":function(w,b,y){y.variables().length===0&&w.success(b)},\"acyclic_term/1\":function(w,b,y){for(var F=b.substitution.apply(b.substitution),z=y.args[0].variables(),Z=0;Z<z.length;Z++)if(b.substitution.links[z[Z]]!==void 0&&!b.substitution.links[z[Z]].equals(F.links[z[Z]]))return;w.success(b)},\"callable/1\":function(w,b,y){P.type.is_callable(y.args[0])&&w.success(b)},\"is_list/1\":function(w,b,y){for(var F=y.args[0];P.type.is_term(F)&&F.indicator===\"./2\";)F=F.args[1];P.type.is_term(F)&&F.indicator===\"[]/0\"&&w.success(b)},\"current_input/1\":function(w,b,y){var F=y.args[0];!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream\",F,y.indicator)):(P.type.is_atom(F)&&w.get_stream_by_alias(F.id)&&(F=w.get_stream_by_alias(F.id)),w.prepend([new be(b.goal.replace(new _(\"=\",[F,w.get_current_input()])),b.substitution,b)]))},\"current_output/1\":function(w,b,y){var F=y.args[0];!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):(P.type.is_atom(F)&&w.get_stream_by_alias(F.id)&&(F=w.get_stream_by_alias(F.id)),w.prepend([new be(b.goal.replace(new _(\"=\",[F,w.get_current_output()])),b.substitution,b)]))},\"set_input/1\":function(w,b,y){var F=y.args[0],z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):P.type.is_stream(z)?z.output===!0?w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator)):(w.set_current_input(z),w.success(b)):w.throw_error(P.error.existence(\"stream\",F,y.indicator))},\"set_output/1\":function(w,b,y){var F=y.args[0],z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):P.type.is_stream(z)?z.input===!0?w.throw_error(P.error.permission(\"output\",\"stream\",F,y.indicator)):(w.set_current_output(z),w.success(b)):w.throw_error(P.error.existence(\"stream\",F,y.indicator))},\"open/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2];w.prepend([new be(b.goal.replace(new _(\"open\",[F,z,Z,new _(\"[]\",[])])),b.substitution,b)])},\"open/4\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2],$=y.args[3];if(P.type.is_variable(F)||P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_atom(z))w.throw_error(P.error.type(\"atom\",z,y.indicator));else if(!P.type.is_list($))w.throw_error(P.error.type(\"list\",$,y.indicator));else if(!P.type.is_variable(Z))w.throw_error(P.error.type(\"variable\",Z,y.indicator));else if(!P.type.is_atom(F)&&!P.type.is_streamable(F))w.throw_error(P.error.domain(\"source_sink\",F,y.indicator));else if(!P.type.is_io_mode(z))w.throw_error(P.error.domain(\"io_mode\",z,y.indicator));else{for(var se={},xe=$,Fe;P.type.is_term(xe)&&xe.indicator===\"./2\";){if(Fe=xe.args[0],P.type.is_variable(Fe)){w.throw_error(P.error.instantiation(y.indicator));return}else if(!P.type.is_stream_option(Fe)){w.throw_error(P.error.domain(\"stream_option\",Fe,y.indicator));return}se[Fe.id]=Fe.args[0].id,xe=xe.args[1]}if(xe.indicator!==\"[]/0\"){P.type.is_variable(xe)?w.throw_error(P.error.instantiation(y.indicator)):w.throw_error(P.error.type(\"list\",$,y.indicator));return}else{var ut=se.alias;if(ut&&w.get_stream_by_alias(ut)){w.throw_error(P.error.permission(\"open\",\"source_sink\",new _(\"alias\",[new _(ut,[])]),y.indicator));return}se.type||(se.type=\"text\");var Ct;if(P.type.is_atom(F)?Ct=w.file_system_open(F.id,se.type,z.id):Ct=F.stream(se.type,z.id),Ct===!1){w.throw_error(P.error.permission(\"open\",\"source_sink\",F,y.indicator));return}else if(Ct===null){w.throw_error(P.error.existence(\"source_sink\",F,y.indicator));return}var qt=new Ne(Ct,z.id,se.alias,se.type,se.reposition===\"true\",se.eof_action);ut?w.session.streams[ut]=qt:w.session.streams[qt.id]=qt,w.prepend([new be(b.goal.replace(new _(\"=\",[Z,qt])),b.substitution,b)])}}},\"close/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\"close\",[F,new _(\"[]\",[])])),b.substitution,b)])},\"close/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F)||P.type.is_variable(z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_list(z))w.throw_error(P.error.type(\"list\",z,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else{for(var $={},se=z,xe;P.type.is_term(se)&&se.indicator===\"./2\";){if(xe=se.args[0],P.type.is_variable(xe)){w.throw_error(P.error.instantiation(y.indicator));return}else if(!P.type.is_close_option(xe)){w.throw_error(P.error.domain(\"close_option\",xe,y.indicator));return}$[xe.id]=xe.args[0].id===\"true\",se=se.args[1]}if(se.indicator!==\"[]/0\"){P.type.is_variable(se)?w.throw_error(P.error.instantiation(y.indicator)):w.throw_error(P.error.type(\"list\",z,y.indicator));return}else{if(Z===w.session.standard_input||Z===w.session.standard_output){w.success(b);return}else Z===w.session.current_input?w.session.current_input=w.session.standard_input:Z===w.session.current_output&&(w.session.current_output=w.session.current_output);Z.alias!==null?delete w.session.streams[Z.alias]:delete w.session.streams[Z.id],Z.output&&Z.stream.flush();var Fe=Z.stream.close();Z.stream=null,($.force===!0||Fe===!0)&&w.success(b)}}},\"flush_output/0\":function(w,b,y){w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"flush_output\",[new De(\"S\")])])),b.substitution,b)])},\"flush_output/1\":function(w,b,y){var F=y.args[0],z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):!P.type.is_stream(z)||z.stream===null?w.throw_error(P.error.existence(\"stream\",F,y.indicator)):F.input===!0?w.throw_error(P.error.permission(\"output\",\"stream\",output,y.indicator)):(z.stream.flush(),w.success(b))},\"stream_property/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_variable(F)&&(!P.type.is_stream(Z)||Z.stream===null))w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_stream_property(z))w.throw_error(P.error.domain(\"stream_property\",z,y.indicator));else{var $=[],se=[];if(!P.type.is_variable(F))$.push(Z);else for(var xe in w.session.streams)$.push(w.session.streams[xe]);for(var Fe=0;Fe<$.length;Fe++){var ut=[];$[Fe].filename&&ut.push(new _(\"file_name\",[new _($[Fe].file_name,[])])),ut.push(new _(\"mode\",[new _($[Fe].mode,[])])),ut.push(new _($[Fe].input?\"input\":\"output\",[])),$[Fe].alias&&ut.push(new _(\"alias\",[new _($[Fe].alias,[])])),ut.push(new _(\"position\",[typeof $[Fe].position==\"number\"?new Qe($[Fe].position,!1):new _($[Fe].position,[])])),ut.push(new _(\"end_of_stream\",[new _($[Fe].position===\"end_of_stream\"?\"at\":$[Fe].position===\"past_end_of_stream\"?\"past\":\"not\",[])])),ut.push(new _(\"eof_action\",[new _($[Fe].eof_action,[])])),ut.push(new _(\"reposition\",[new _($[Fe].reposition?\"true\":\"false\",[])])),ut.push(new _(\"type\",[new _($[Fe].type,[])]));for(var Ct=0;Ct<ut.length;Ct++)se.push(new be(b.goal.replace(new _(\",\",[new _(\"=\",[P.type.is_variable(F)?F:Z,$[Fe]]),new _(\"=\",[z,ut[Ct]])])),b.substitution,b))}w.prepend(se)}},\"at_end_of_stream/0\":function(w,b,y){w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\",\",[new _(\"stream_property\",[new De(\"S\"),new _(\"end_of_stream\",[new De(\"E\")])]),new _(\",\",[new _(\"!\",[]),new _(\";\",[new _(\"=\",[new De(\"E\"),new _(\"at\",[])]),new _(\"=\",[new De(\"E\"),new _(\"past\",[])])])])])])),b.substitution,b)])},\"at_end_of_stream/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"stream_property\",[F,new _(\"end_of_stream\",[new De(\"E\")])]),new _(\",\",[new _(\"!\",[]),new _(\";\",[new _(\"=\",[new De(\"E\"),new _(\"at\",[])]),new _(\"=\",[new De(\"E\"),new _(\"past\",[])])])])])),b.substitution,b)])},\"set_stream_position/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)||P.type.is_variable(z)?w.throw_error(P.error.instantiation(y.indicator)):!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):!P.type.is_stream(Z)||Z.stream===null?w.throw_error(P.error.existence(\"stream\",F,y.indicator)):P.type.is_stream_position(z)?Z.reposition===!1?w.throw_error(P.error.permission(\"reposition\",\"stream\",F,y.indicator)):(P.type.is_integer(z)?Z.position=z.value:Z.position=z.id,w.success(b)):w.throw_error(P.error.domain(\"stream_position\",z,y.indicator))},\"get_char/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"get_char\",[new De(\"S\"),F])])),b.substitution,b)])},\"get_char/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_character(z))w.throw_error(P.error.type(\"in_character\",z,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(Z.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if(Z.type===\"binary\")w.throw_error(P.error.permission(\"input\",\"binary_stream\",F,y.indicator));else if(Z.position===\"past_end_of_stream\"&&Z.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{var $;if(Z.position===\"end_of_stream\")$=\"end_of_file\",Z.position=\"past_end_of_stream\";else{if($=Z.stream.get(1,Z.position),$===null){w.throw_error(P.error.representation(\"character\",y.indicator));return}Z.position++}w.prepend([new be(b.goal.replace(new _(\"=\",[new _($,[]),z])),b.substitution,b)])}},\"get_code/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"get_code\",[new De(\"S\"),F])])),b.substitution,b)])},\"get_code/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_integer(z))w.throw_error(P.error.type(\"integer\",char,y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(Z.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if(Z.type===\"binary\")w.throw_error(P.error.permission(\"input\",\"binary_stream\",F,y.indicator));else if(Z.position===\"past_end_of_stream\"&&Z.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{var $;if(Z.position===\"end_of_stream\")$=-1,Z.position=\"past_end_of_stream\";else{if($=Z.stream.get(1,Z.position),$===null){w.throw_error(P.error.representation(\"character\",y.indicator));return}$=n($,0),Z.position++}w.prepend([new be(b.goal.replace(new _(\"=\",[new Qe($,!1),z])),b.substitution,b)])}},\"peek_char/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"peek_char\",[new De(\"S\"),F])])),b.substitution,b)])},\"peek_char/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_character(z))w.throw_error(P.error.type(\"in_character\",z,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(Z.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if(Z.type===\"binary\")w.throw_error(P.error.permission(\"input\",\"binary_stream\",F,y.indicator));else if(Z.position===\"past_end_of_stream\"&&Z.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{var $;if(Z.position===\"end_of_stream\")$=\"end_of_file\",Z.position=\"past_end_of_stream\";else if($=Z.stream.get(1,Z.position),$===null){w.throw_error(P.error.representation(\"character\",y.indicator));return}w.prepend([new be(b.goal.replace(new _(\"=\",[new _($,[]),z])),b.substitution,b)])}},\"peek_code/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"peek_code\",[new De(\"S\"),F])])),b.substitution,b)])},\"peek_code/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_integer(z))w.throw_error(P.error.type(\"integer\",char,y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(Z.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if(Z.type===\"binary\")w.throw_error(P.error.permission(\"input\",\"binary_stream\",F,y.indicator));else if(Z.position===\"past_end_of_stream\"&&Z.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{var $;if(Z.position===\"end_of_stream\")$=-1,Z.position=\"past_end_of_stream\";else{if($=Z.stream.get(1,Z.position),$===null){w.throw_error(P.error.representation(\"character\",y.indicator));return}$=n($,0)}w.prepend([new be(b.goal.replace(new _(\"=\",[new Qe($,!1),z])),b.substitution,b)])}},\"put_char/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"put_char\",[new De(\"S\"),F])])),b.substitution,b)])},\"put_char/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)||P.type.is_variable(z)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_character(z)?!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):!P.type.is_stream(Z)||Z.stream===null?w.throw_error(P.error.existence(\"stream\",F,y.indicator)):Z.input?w.throw_error(P.error.permission(\"output\",\"stream\",F,y.indicator)):Z.type===\"binary\"?w.throw_error(P.error.permission(\"output\",\"binary_stream\",F,y.indicator)):Z.stream.put(z.id,Z.position)&&(typeof Z.position==\"number\"&&Z.position++,w.success(b)):w.throw_error(P.error.type(\"character\",z,y.indicator))},\"put_code/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"put_code\",[new De(\"S\"),F])])),b.substitution,b)])},\"put_code/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)||P.type.is_variable(z)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_integer(z)?P.type.is_character_code(z)?!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):!P.type.is_stream(Z)||Z.stream===null?w.throw_error(P.error.existence(\"stream\",F,y.indicator)):Z.input?w.throw_error(P.error.permission(\"output\",\"stream\",F,y.indicator)):Z.type===\"binary\"?w.throw_error(P.error.permission(\"output\",\"binary_stream\",F,y.indicator)):Z.stream.put_char(c(z.value),Z.position)&&(typeof Z.position==\"number\"&&Z.position++,w.success(b)):w.throw_error(P.error.representation(\"character_code\",y.indicator)):w.throw_error(P.error.type(\"integer\",z,y.indicator))},\"nl/0\":function(w,b,y){w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"put_char\",[new De(\"S\"),new _(`\n`,[])])])),b.substitution,b)])},\"nl/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\"put_char\",[F,new _(`\n`,[])])),b.substitution,b)])},\"get_byte/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"get_byte\",[new De(\"S\"),F])])),b.substitution,b)])},\"get_byte/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_byte(z))w.throw_error(P.error.type(\"in_byte\",char,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(Z.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if(Z.type===\"text\")w.throw_error(P.error.permission(\"input\",\"text_stream\",F,y.indicator));else if(Z.position===\"past_end_of_stream\"&&Z.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{var $;if(Z.position===\"end_of_stream\")$=\"end_of_file\",Z.position=\"past_end_of_stream\";else{if($=Z.stream.get_byte(Z.position),$===null){w.throw_error(P.error.representation(\"byte\",y.indicator));return}Z.position++}w.prepend([new be(b.goal.replace(new _(\"=\",[new Qe($,!1),z])),b.substitution,b)])}},\"peek_byte/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"peek_byte\",[new De(\"S\"),F])])),b.substitution,b)])},\"peek_byte/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_variable(z)&&!P.type.is_byte(z))w.throw_error(P.error.type(\"in_byte\",char,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream(Z)||Z.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if(Z.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if(Z.type===\"text\")w.throw_error(P.error.permission(\"input\",\"text_stream\",F,y.indicator));else if(Z.position===\"past_end_of_stream\"&&Z.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{var $;if(Z.position===\"end_of_stream\")$=\"end_of_file\",Z.position=\"past_end_of_stream\";else if($=Z.stream.get_byte(Z.position),$===null){w.throw_error(P.error.representation(\"byte\",y.indicator));return}w.prepend([new be(b.goal.replace(new _(\"=\",[new Qe($,!1),z])),b.substitution,b)])}},\"put_byte/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"put_byte\",[new De(\"S\"),F])])),b.substitution,b)])},\"put_byte/2\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);P.type.is_variable(F)||P.type.is_variable(z)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_byte(z)?!P.type.is_variable(F)&&!P.type.is_stream(F)&&!P.type.is_atom(F)?w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator)):!P.type.is_stream(Z)||Z.stream===null?w.throw_error(P.error.existence(\"stream\",F,y.indicator)):Z.input?w.throw_error(P.error.permission(\"output\",\"stream\",F,y.indicator)):Z.type===\"text\"?w.throw_error(P.error.permission(\"output\",\"text_stream\",F,y.indicator)):Z.stream.put_byte(z.value,Z.position)&&(typeof Z.position==\"number\"&&Z.position++,w.success(b)):w.throw_error(P.error.type(\"byte\",z,y.indicator))},\"read/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"read_term\",[new De(\"S\"),F,new _(\"[]\",[])])])),b.substitution,b)])},\"read/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\"read_term\",[F,z,new _(\"[]\",[])])),b.substitution,b)])},\"read_term/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_input\",[new De(\"S\")]),new _(\"read_term\",[new De(\"S\"),F,z])])),b.substitution,b)])},\"read_term/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2],$=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F)||P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_list(Z))w.throw_error(P.error.type(\"list\",Z,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream($)||$.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if($.output)w.throw_error(P.error.permission(\"input\",\"stream\",F,y.indicator));else if($.type===\"binary\")w.throw_error(P.error.permission(\"input\",\"binary_stream\",F,y.indicator));else if($.position===\"past_end_of_stream\"&&$.eof_action===\"error\")w.throw_error(P.error.permission(\"input\",\"past_end_of_stream\",F,y.indicator));else{for(var se={},xe=Z,Fe;P.type.is_term(xe)&&xe.indicator===\"./2\";){if(Fe=xe.args[0],P.type.is_variable(Fe)){w.throw_error(P.error.instantiation(y.indicator));return}else if(!P.type.is_read_option(Fe)){w.throw_error(P.error.domain(\"read_option\",Fe,y.indicator));return}se[Fe.id]=Fe.args[0],xe=xe.args[1]}if(xe.indicator!==\"[]/0\"){P.type.is_variable(xe)?w.throw_error(P.error.instantiation(y.indicator)):w.throw_error(P.error.type(\"list\",Z,y.indicator));return}else{for(var ut,Ct,qt,ir=\"\",Pt=[],dn=null;dn===null||dn.name!==\"atom\"||dn.value!==\".\"||qt.type===f&&P.flatten_error(new _(\"throw\",[qt.value])).found===\"token_not_found\";){if(ut=$.stream.get(1,$.position),ut===null){w.throw_error(P.error.representation(\"character\",y.indicator));return}if(ut===\"end_of_file\"||ut===\"past_end_of_file\"){qt?w.throw_error(P.error.syntax(Pt[qt.len-1],\". or expression expected\",!1)):w.throw_error(P.error.syntax(null,\"token not found\",!0));return}$.position++,ir+=ut,Ct=new U(w),Ct.new_text(ir),Pt=Ct.get_tokens(),dn=Pt!==null&&Pt.length>0?Pt[Pt.length-1]:null,Pt!==null&&(qt=Y(w,Pt,0,w.__get_max_priority(),!1))}if(qt.type===p&&qt.len===Pt.length-1&&dn.value===\".\"){qt=qt.value.rename(w);var Pr=new _(\"=\",[z,qt]);if(se.variables){var Ir=g(s(Be(qt.variables()),function(Or){return new De(Or)}));Pr=new _(\",\",[Pr,new _(\"=\",[se.variables,Ir])])}if(se.variable_names){var Ir=g(s(Be(qt.variables()),function(on){var li;for(li in w.session.renamed_variables)if(w.session.renamed_variables.hasOwnProperty(li)&&w.session.renamed_variables[li]===on)break;return new _(\"=\",[new _(li,[]),new De(on)])}));Pr=new _(\",\",[Pr,new _(\"=\",[se.variable_names,Ir])])}if(se.singletons){var Ir=g(s(new je(qt,null).singleton_variables(),function(on){var li;for(li in w.session.renamed_variables)if(w.session.renamed_variables.hasOwnProperty(li)&&w.session.renamed_variables[li]===on)break;return new _(\"=\",[new _(li,[]),new De(on)])}));Pr=new _(\",\",[Pr,new _(\"=\",[se.singletons,Ir])])}w.prepend([new be(b.goal.replace(Pr),b.substitution,b)])}else qt.type===p?w.throw_error(P.error.syntax(Pt[qt.len],\"unexpected token\",!1)):w.throw_error(qt.value)}}},\"write/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"write\",[new De(\"S\"),F])])),b.substitution,b)])},\"write/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\"write_term\",[F,z,new _(\".\",[new _(\"quoted\",[new _(\"false\",[])]),new _(\".\",[new _(\"ignore_ops\",[new _(\"false\")]),new _(\".\",[new _(\"numbervars\",[new _(\"true\")]),new _(\"[]\",[])])])])])),b.substitution,b)])},\"writeq/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"writeq\",[new De(\"S\"),F])])),b.substitution,b)])},\"writeq/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\"write_term\",[F,z,new _(\".\",[new _(\"quoted\",[new _(\"true\",[])]),new _(\".\",[new _(\"ignore_ops\",[new _(\"false\")]),new _(\".\",[new _(\"numbervars\",[new _(\"true\")]),new _(\"[]\",[])])])])])),b.substitution,b)])},\"write_canonical/1\":function(w,b,y){var F=y.args[0];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"write_canonical\",[new De(\"S\"),F])])),b.substitution,b)])},\"write_canonical/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\"write_term\",[F,z,new _(\".\",[new _(\"quoted\",[new _(\"true\",[])]),new _(\".\",[new _(\"ignore_ops\",[new _(\"true\")]),new _(\".\",[new _(\"numbervars\",[new _(\"false\")]),new _(\"[]\",[])])])])])),b.substitution,b)])},\"write_term/2\":function(w,b,y){var F=y.args[0],z=y.args[1];w.prepend([new be(b.goal.replace(new _(\",\",[new _(\"current_output\",[new De(\"S\")]),new _(\"write_term\",[new De(\"S\"),F,z])])),b.substitution,b)])},\"write_term/3\":function(w,b,y){var F=y.args[0],z=y.args[1],Z=y.args[2],$=P.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(P.type.is_variable(F)||P.type.is_variable(Z))w.throw_error(P.error.instantiation(y.indicator));else if(!P.type.is_list(Z))w.throw_error(P.error.type(\"list\",Z,y.indicator));else if(!P.type.is_stream(F)&&!P.type.is_atom(F))w.throw_error(P.error.domain(\"stream_or_alias\",F,y.indicator));else if(!P.type.is_stream($)||$.stream===null)w.throw_error(P.error.existence(\"stream\",F,y.indicator));else if($.input)w.throw_error(P.error.permission(\"output\",\"stream\",F,y.indicator));else if($.type===\"binary\")w.throw_error(P.error.permission(\"output\",\"binary_stream\",F,y.indicator));else if($.position===\"past_end_of_stream\"&&$.eof_action===\"error\")w.throw_error(P.error.permission(\"output\",\"past_end_of_stream\",F,y.indicator));else{for(var se={},xe=Z,Fe;P.type.is_term(xe)&&xe.indicator===\"./2\";){if(Fe=xe.args[0],P.type.is_variable(Fe)){w.throw_error(P.error.instantiation(y.indicator));return}else if(!P.type.is_write_option(Fe)){w.throw_error(P.error.domain(\"write_option\",Fe,y.indicator));return}se[Fe.id]=Fe.args[0].id===\"true\",xe=xe.args[1]}if(xe.indicator!==\"[]/0\"){P.type.is_variable(xe)?w.throw_error(P.error.instantiation(y.indicator)):w.throw_error(P.error.type(\"list\",Z,y.indicator));return}else{se.session=w.session;var ut=z.toString(se);$.stream.put(ut,$.position),typeof $.position==\"number\"&&($.position+=ut.length),w.success(b)}}},\"halt/0\":function(w,b,y){w.points=[]},\"halt/1\":function(w,b,y){var F=y.args[0];P.type.is_variable(F)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_integer(F)?w.points=[]:w.throw_error(P.error.type(\"integer\",F,y.indicator))},\"current_prolog_flag/2\":function(w,b,y){var F=y.args[0],z=y.args[1];if(!P.type.is_variable(F)&&!P.type.is_atom(F))w.throw_error(P.error.type(\"atom\",F,y.indicator));else if(!P.type.is_variable(F)&&!P.type.is_flag(F))w.throw_error(P.error.domain(\"prolog_flag\",F,y.indicator));else{var Z=[];for(var $ in P.flag)if(P.flag.hasOwnProperty($)){var se=new _(\",\",[new _(\"=\",[new _($),F]),new _(\"=\",[w.get_flag($),z])]);Z.push(new be(b.goal.replace(se),b.substitution,b))}w.prepend(Z)}},\"set_prolog_flag/2\":function(w,b,y){var F=y.args[0],z=y.args[1];P.type.is_variable(F)||P.type.is_variable(z)?w.throw_error(P.error.instantiation(y.indicator)):P.type.is_atom(F)?P.type.is_flag(F)?P.type.is_value_flag(F,z)?P.type.is_modifiable_flag(F)?(w.session.flag[F.id]=z,w.success(b)):w.throw_error(P.error.permission(\"modify\",\"flag\",F)):w.throw_error(P.error.domain(\"flag_value\",new _(\"+\",[F,z]),y.indicator)):w.throw_error(P.error.domain(\"prolog_flag\",F,y.indicator)):w.throw_error(P.error.type(\"atom\",F,y.indicator))}},flag:{bounded:{allowed:[new _(\"true\"),new _(\"false\")],value:new _(\"true\"),changeable:!1},max_integer:{allowed:[new Qe(Number.MAX_SAFE_INTEGER)],value:new Qe(Number.MAX_SAFE_INTEGER),changeable:!1},min_integer:{allowed:[new Qe(Number.MIN_SAFE_INTEGER)],value:new Qe(Number.MIN_SAFE_INTEGER),changeable:!1},integer_rounding_function:{allowed:[new _(\"down\"),new _(\"toward_zero\")],value:new _(\"toward_zero\"),changeable:!1},char_conversion:{allowed:[new _(\"on\"),new _(\"off\")],value:new _(\"on\"),changeable:!0},debug:{allowed:[new _(\"on\"),new _(\"off\")],value:new _(\"off\"),changeable:!0},max_arity:{allowed:[new _(\"unbounded\")],value:new _(\"unbounded\"),changeable:!1},unknown:{allowed:[new _(\"error\"),new _(\"fail\"),new _(\"warning\")],value:new _(\"error\"),changeable:!0},double_quotes:{allowed:[new _(\"chars\"),new _(\"codes\"),new _(\"atom\")],value:new _(\"codes\"),changeable:!0},occurs_check:{allowed:[new _(\"false\"),new _(\"true\")],value:new _(\"false\"),changeable:!0},dialect:{allowed:[new _(\"tau\")],value:new _(\"tau\"),changeable:!1},version_data:{allowed:[new _(\"tau\",[new Qe(e.major,!1),new Qe(e.minor,!1),new Qe(e.patch,!1),new _(e.status)])],value:new _(\"tau\",[new Qe(e.major,!1),new Qe(e.minor,!1),new Qe(e.patch,!1),new _(e.status)]),changeable:!1},nodejs:{allowed:[new _(\"yes\"),new _(\"no\")],value:new _(typeof tc<\"u\"&&tc.exports?\"yes\":\"no\"),changeable:!1}},unify:function(w,b,y){y=y===void 0?!1:y;for(var F=[{left:w,right:b}],z={};F.length!==0;){var Z=F.pop();if(w=Z.left,b=Z.right,P.type.is_term(w)&&P.type.is_term(b)){if(w.indicator!==b.indicator)return null;for(var $=0;$<w.args.length;$++)F.push({left:w.args[$],right:b.args[$]})}else if(P.type.is_number(w)&&P.type.is_number(b)){if(w.value!==b.value||w.is_float!==b.is_float)return null}else if(P.type.is_variable(w)){if(P.type.is_variable(b)&&w.id===b.id)continue;if(y===!0&&b.variables().indexOf(w.id)!==-1)return null;if(w.id!==\"_\"){var se=new ke;se.add(w.id,b);for(var $=0;$<F.length;$++)F[$].left=F[$].left.apply(se),F[$].right=F[$].right.apply(se);for(var $ in z)z[$]=z[$].apply(se);z[w.id]=b}}else if(P.type.is_variable(b))F.push({left:b,right:w});else if(w.unify!==void 0){if(!w.unify(b))return null}else return null}return new ke(z)},compare:function(w,b){var y=P.type.compare(w,b);return y!==0?y:w.compare(b)},arithmetic_compare:function(w,b,y){var F=b.interpret(w);if(P.type.is_number(F)){var z=y.interpret(w);return P.type.is_number(z)?F.value<z.value?-1:F.value>z.value?1:0:z}else return F},operate:function(w,b){if(P.type.is_operator(b)){for(var y=P.type.is_operator(b),F=[],z,Z=!1,$=0;$<b.args.length;$++){if(z=b.args[$].interpret(w),P.type.is_number(z)){if(y.type_args!==null&&z.is_float!==y.type_args)return P.error.type(y.type_args?\"float\":\"integer\",z,w.__call_indicator);F.push(z.value)}else return z;Z=Z||z.is_float}return F.push(w),z=P.arithmetic.evaluation[b.indicator].fn.apply(this,F),Z=y.type_result===null?Z:y.type_result,P.type.is_term(z)?z:z===Number.POSITIVE_INFINITY||z===Number.NEGATIVE_INFINITY?P.error.evaluation(\"overflow\",w.__call_indicator):Z===!1&&w.get_flag(\"bounded\").id===\"true\"&&(z>w.get_flag(\"max_integer\").value||z<w.get_flag(\"min_integer\").value)?P.error.evaluation(\"int_overflow\",w.__call_indicator):new Qe(z,Z)}else return P.error.type(\"evaluable\",b.indicator,w.__call_indicator)},error:{existence:function(w,b,y){return typeof b==\"string\"&&(b=X(b)),new _(\"error\",[new _(\"existence_error\",[new _(w),b]),X(y)])},type:function(w,b,y){return new _(\"error\",[new _(\"type_error\",[new _(w),b]),X(y)])},instantiation:function(w){return new _(\"error\",[new _(\"instantiation_error\"),X(w)])},domain:function(w,b,y){return new _(\"error\",[new _(\"domain_error\",[new _(w),b]),X(y)])},representation:function(w,b){return new _(\"error\",[new _(\"representation_error\",[new _(w)]),X(b)])},permission:function(w,b,y,F){return new _(\"error\",[new _(\"permission_error\",[new _(w),new _(b),y]),X(F)])},evaluation:function(w,b){return new _(\"error\",[new _(\"evaluation_error\",[new _(w)]),X(b)])},syntax:function(w,b,y){w=w||{value:\"\",line:0,column:0,matches:[\"\"],start:0};var F=y&&w.matches.length>0?w.start+w.matches[0].length:w.start,z=y?new _(\"token_not_found\"):new _(\"found\",[new _(w.value.toString())]),Z=new _(\".\",[new _(\"line\",[new Qe(w.line+1)]),new _(\".\",[new _(\"column\",[new Qe(F+1)]),new _(\".\",[z,new _(\"[]\",[])])])]);return new _(\"error\",[new _(\"syntax_error\",[new _(b)]),Z])},syntax_by_predicate:function(w,b){return new _(\"error\",[new _(\"syntax_error\",[new _(w)]),X(b)])}},warning:{singleton:function(w,b,y){for(var F=new _(\"[]\"),z=w.length-1;z>=0;z--)F=new _(\".\",[new De(w[z]),F]);return new _(\"warning\",[new _(\"singleton_variables\",[F,X(b)]),new _(\".\",[new _(\"line\",[new Qe(y,!1)]),new _(\"[]\")])])},failed_goal:function(w,b){return new _(\"warning\",[new _(\"failed_goal\",[w]),new _(\".\",[new _(\"line\",[new Qe(b,!1)]),new _(\"[]\")])])}},format_variable:function(w){return\"_\"+w},format_answer:function(w,b,F){b instanceof Re&&(b=b.thread);var F=F||{};if(F.session=b?b.session:void 0,P.type.is_error(w))return\"uncaught exception: \"+w.args[0].toString();if(w===!1)return\"false.\";if(w===null)return\"limit exceeded ;\";var z=0,Z=\"\";if(P.type.is_substitution(w)){var $=w.domain(!0);w=w.filter(function(Fe,ut){return!P.type.is_variable(ut)||$.indexOf(ut.id)!==-1&&Fe!==ut.id})}for(var se in w.links)w.links.hasOwnProperty(se)&&(z++,Z!==\"\"&&(Z+=\", \"),Z+=se.toString(F)+\" = \"+w.links[se].toString(F));var xe=typeof b>\"u\"||b.points.length>0?\" ;\":\".\";return z===0?\"true\"+xe:Z+xe},flatten_error:function(w){if(!P.type.is_error(w))return null;w=w.args[0];var b={};return b.type=w.args[0].id,b.thrown=b.type===\"syntax_error\"?null:w.args[1].id,b.expected=null,b.found=null,b.representation=null,b.existence=null,b.existence_type=null,b.line=null,b.column=null,b.permission_operation=null,b.permission_type=null,b.evaluation_type=null,b.type===\"type_error\"||b.type===\"domain_error\"?(b.expected=w.args[0].args[0].id,b.found=w.args[0].args[1].toString()):b.type===\"syntax_error\"?w.args[1].indicator===\"./2\"?(b.expected=w.args[0].args[0].id,b.found=w.args[1].args[1].args[1].args[0],b.found=b.found.id===\"token_not_found\"?b.found.id:b.found.args[0].id,b.line=w.args[1].args[0].args[0].value,b.column=w.args[1].args[1].args[0].args[0].value):b.thrown=w.args[1].id:b.type===\"permission_error\"?(b.found=w.args[0].args[2].toString(),b.permission_operation=w.args[0].args[0].id,b.permission_type=w.args[0].args[1].id):b.type===\"evaluation_error\"?b.evaluation_type=w.args[0].args[0].id:b.type===\"representation_error\"?b.representation=w.args[0].args[0].id:b.type===\"existence_error\"&&(b.existence=w.args[0].args[1].toString(),b.existence_type=w.args[0].args[0].id),b},create:function(w){return new P.type.Session(w)}};typeof tc<\"u\"?tc.exports=P:window.pl=P})()});function ome(e,t,r){e.prepend(r.map(s=>new Il.default.type.State(t.goal.replace(s),t.substitution,t)))}function eq(e){let t=lme.get(e.session);if(t==null)throw new Error(\"Assertion failed: A project should have been registered for the active session\");return t}function cme(e,t){lme.set(e,t),e.consult(`:- use_module(library(${fat.id})).`)}var Il,ame,V0,cat,uat,lme,fat,ume=Ze(()=>{qe();Jl();Il=et($5()),ame=et(Ie(\"vm\")),{is_atom:V0,is_variable:cat,is_instantiated_list:uat}=Il.default.type;lme=new WeakMap;fat=new Il.default.type.Module(\"constraints\",{\"project_workspaces_by_descriptor/3\":(e,t,r)=>{let[s,a,n]=r.args;if(!V0(s)||!V0(a)){e.throw_error(Il.default.error.instantiation(r.indicator));return}let c=j.parseIdent(s.id),f=j.makeDescriptor(c,a.id),h=eq(e).tryWorkspaceByDescriptor(f);cat(n)&&h!==null&&ome(e,t,[new Il.default.type.Term(\"=\",[n,new Il.default.type.Term(String(h.relativeCwd))])]),V0(n)&&h!==null&&h.relativeCwd===n.id&&e.success(t)},\"workspace_field/3\":(e,t,r)=>{let[s,a,n]=r.args;if(!V0(s)||!V0(a)){e.throw_error(Il.default.error.instantiation(r.indicator));return}let f=eq(e).tryWorkspaceByCwd(s.id);if(f==null)return;let p=ba(f.manifest.raw,a.id);typeof p>\"u\"||ome(e,t,[new Il.default.type.Term(\"=\",[n,new Il.default.type.Term(typeof p==\"object\"?JSON.stringify(p):p)])])},\"workspace_field_test/3\":(e,t,r)=>{let[s,a,n]=r.args;e.prepend([new Il.default.type.State(t.goal.replace(new Il.default.type.Term(\"workspace_field_test\",[s,a,n,new Il.default.type.Term(\"[]\",[])])),t.substitution,t)])},\"workspace_field_test/4\":(e,t,r)=>{let[s,a,n,c]=r.args;if(!V0(s)||!V0(a)||!V0(n)||!uat(c)){e.throw_error(Il.default.error.instantiation(r.indicator));return}let p=eq(e).tryWorkspaceByCwd(s.id);if(p==null)return;let h=ba(p.manifest.raw,a.id);if(typeof h>\"u\")return;let E={$$:h};for(let[S,x]of c.toJavaScript().entries())E[`$${S}`]=x;ame.default.runInNewContext(n.id,E)&&e.success(t)}},[\"project_workspaces_by_descriptor/3\",\"workspace_field/3\",\"workspace_field_test/3\",\"workspace_field_test/4\"])});var aS={};Yt(aS,{Constraints:()=>rq,DependencyType:()=>hme});function Co(e){if(e instanceof _C.default.type.Num)return e.value;if(e instanceof _C.default.type.Term)switch(e.indicator){case\"throw/1\":return Co(e.args[0]);case\"error/1\":return Co(e.args[0]);case\"error/2\":if(e.args[0]instanceof _C.default.type.Term&&e.args[0].indicator===\"syntax_error/1\")return Object.assign(Co(e.args[0]),...Co(e.args[1]));{let t=Co(e.args[0]);return t.message+=` (in ${Co(e.args[1])})`,t}case\"syntax_error/1\":return new _t(43,`Syntax error: ${Co(e.args[0])}`);case\"existence_error/2\":return new _t(44,`Existence error: ${Co(e.args[0])} ${Co(e.args[1])} not found`);case\"instantiation_error/0\":return new _t(75,\"Instantiation error: an argument is variable when an instantiated argument was expected\");case\"line/1\":return{line:Co(e.args[0])};case\"column/1\":return{column:Co(e.args[0])};case\"found/1\":return{found:Co(e.args[0])};case\"./2\":return[Co(e.args[0])].concat(Co(e.args[1]));case\"//2\":return`${Co(e.args[0])}/${Co(e.args[1])}`;default:return e.id}throw`couldn't pretty print because of unsupported node ${e}`}function Ame(e){let t;try{t=Co(e)}catch(r){throw typeof r==\"string\"?new _t(42,`Unknown error: ${e} (note: ${r})`):r}return typeof t.line<\"u\"&&typeof t.column<\"u\"&&(t.message+=` at line ${t.line}, column ${t.column}`),t}function Qm(e){return e.id===\"null\"?null:`${e.toJavaScript()}`}function Aat(e){if(e.id===\"null\")return null;{let t=e.toJavaScript();if(typeof t!=\"string\")return JSON.stringify(t);try{return JSON.stringify(JSON.parse(t))}catch{return JSON.stringify(t)}}}function Y0(e){return typeof e==\"string\"?`'${e}'`:\"[]\"}var pme,_C,hme,fme,tq,rq,lS=Ze(()=>{qe();qe();Dt();pme=et(qde()),_C=et($5());iS();ume();(0,pme.default)(_C.default);hme=(s=>(s.Dependencies=\"dependencies\",s.DevDependencies=\"devDependencies\",s.PeerDependencies=\"peerDependencies\",s))(hme||{}),fme=[\"dependencies\",\"devDependencies\",\"peerDependencies\"];tq=class{constructor(t,r){let s=1e3*t.workspaces.length;this.session=_C.default.create(s),cme(this.session,t),this.session.consult(\":- use_module(library(lists)).\"),this.session.consult(r)}fetchNextAnswer(){return new Promise(t=>{this.session.answer(r=>{t(r)})})}async*makeQuery(t){let r=this.session.query(t);if(r!==!0)throw Ame(r);for(;;){let s=await this.fetchNextAnswer();if(s===null)throw new _t(79,\"Resolution limit exceeded\");if(!s)break;if(s.id===\"throw\")throw Ame(s);yield s}}};rq=class e{constructor(t){this.source=\"\";this.project=t;let r=t.configuration.get(\"constraintsPath\");le.existsSync(r)&&(this.source=le.readFileSync(r,\"utf8\"))}static async find(t){return new e(t)}getProjectDatabase(){let t=\"\";for(let r of fme)t+=`dependency_type(${r}).\n`;for(let r of this.project.workspacesByCwd.values()){let s=r.relativeCwd;t+=`workspace(${Y0(s)}).\n`,t+=`workspace_ident(${Y0(s)}, ${Y0(j.stringifyIdent(r.anchoredLocator))}).\n`,t+=`workspace_version(${Y0(s)}, ${Y0(r.manifest.version)}).\n`;for(let a of fme)for(let n of r.manifest[a].values())t+=`workspace_has_dependency(${Y0(s)}, ${Y0(j.stringifyIdent(n))}, ${Y0(n.range)}, ${a}).\n`}return t+=`workspace(_) :- false.\n`,t+=`workspace_ident(_, _) :- false.\n`,t+=`workspace_version(_, _) :- false.\n`,t+=`workspace_has_dependency(_, _, _, _) :- false.\n`,t}getDeclarations(){let t=\"\";return t+=`gen_enforced_dependency(_, _, _, _) :- false.\n`,t+=`gen_enforced_field(_, _, _) :- false.\n`,t}get fullSource(){return`${this.getProjectDatabase()}\n${this.source}\n${this.getDeclarations()}`}createSession(){return new tq(this.project,this.fullSource)}async processClassic(){let t=this.createSession();return{enforcedDependencies:await this.genEnforcedDependencies(t),enforcedFields:await this.genEnforcedFields(t)}}async process(){let{enforcedDependencies:t,enforcedFields:r}=await this.processClassic(),s=new Map;for(let{workspace:a,dependencyIdent:n,dependencyRange:c,dependencyType:f}of t){let p=nS([f,j.stringifyIdent(n)]),h=Ge.getMapWithDefault(s,a.cwd);Ge.getMapWithDefault(h,p).set(c??void 0,new Set)}for(let{workspace:a,fieldPath:n,fieldValue:c}of r){let f=nS(n),p=Ge.getMapWithDefault(s,a.cwd);Ge.getMapWithDefault(p,f).set(JSON.parse(c)??void 0,new Set)}return{manifestUpdates:s,reportedErrors:new Map}}async genEnforcedDependencies(t){let r=[];for await(let s of t.makeQuery(\"workspace(WorkspaceCwd), dependency_type(DependencyType), gen_enforced_dependency(WorkspaceCwd, DependencyIdent, DependencyRange, DependencyType).\")){let a=K.resolve(this.project.cwd,Qm(s.links.WorkspaceCwd)),n=Qm(s.links.DependencyIdent),c=Qm(s.links.DependencyRange),f=Qm(s.links.DependencyType);if(a===null||n===null)throw new Error(\"Invalid rule\");let p=this.project.getWorkspaceByCwd(a),h=j.parseIdent(n);r.push({workspace:p,dependencyIdent:h,dependencyRange:c,dependencyType:f})}return Ge.sortMap(r,[({dependencyRange:s})=>s!==null?\"0\":\"1\",({workspace:s})=>j.stringifyIdent(s.anchoredLocator),({dependencyIdent:s})=>j.stringifyIdent(s)])}async genEnforcedFields(t){let r=[];for await(let s of t.makeQuery(\"workspace(WorkspaceCwd), gen_enforced_field(WorkspaceCwd, FieldPath, FieldValue).\")){let a=K.resolve(this.project.cwd,Qm(s.links.WorkspaceCwd)),n=Qm(s.links.FieldPath),c=Aat(s.links.FieldValue);if(a===null||n===null)throw new Error(\"Invalid rule\");let f=this.project.getWorkspaceByCwd(a);r.push({workspace:f,fieldPath:n,fieldValue:c})}return Ge.sortMap(r,[({workspace:s})=>j.stringifyIdent(s.anchoredLocator),({fieldPath:s})=>s])}async*query(t){let r=this.createSession();for await(let s of r.makeQuery(t)){let a={};for(let[n,c]of Object.entries(s.links))n!==\"_\"&&(a[n]=Qm(c));yield a}}}});var Bme=G(JT=>{\"use strict\";Object.defineProperty(JT,\"__esModule\",{value:!0});function BS(e){let t=[...e.caches],r=t.shift();return r===void 0?wme():{get(s,a,n={miss:()=>Promise.resolve()}){return r.get(s,a,n).catch(()=>BS({caches:t}).get(s,a,n))},set(s,a){return r.set(s,a).catch(()=>BS({caches:t}).set(s,a))},delete(s){return r.delete(s).catch(()=>BS({caches:t}).delete(s))},clear(){return r.clear().catch(()=>BS({caches:t}).clear())}}}function wme(){return{get(e,t,r={miss:()=>Promise.resolve()}){return t().then(a=>Promise.all([a,r.miss(a)])).then(([a])=>a)},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}JT.createFallbackableCache=BS;JT.createNullCache=wme});var Sme=G((bVt,vme)=>{vme.exports=Bme()});var Dme=G(dq=>{\"use strict\";Object.defineProperty(dq,\"__esModule\",{value:!0});function Qat(e={serializable:!0}){let t={};return{get(r,s,a={miss:()=>Promise.resolve()}){let n=JSON.stringify(r);if(n in t)return Promise.resolve(e.serializable?JSON.parse(t[n]):t[n]);let c=s(),f=a&&a.miss||(()=>Promise.resolve());return c.then(p=>f(p)).then(()=>c)},set(r,s){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(s):s,Promise.resolve(s)},delete(r){return delete t[JSON.stringify(r)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}dq.createInMemoryCache=Qat});var Pme=G((xVt,bme)=>{bme.exports=Dme()});var kme=G(tf=>{\"use strict\";Object.defineProperty(tf,\"__esModule\",{value:!0});function Rat(e,t,r){let s={\"x-algolia-api-key\":r,\"x-algolia-application-id\":t};return{headers(){return e===mq.WithinHeaders?s:{}},queryParameters(){return e===mq.WithinQueryParameters?s:{}}}}function Tat(e){let t=0,r=()=>(t++,new Promise(s=>{setTimeout(()=>{s(e(r))},Math.min(100*t,1e3))}));return e(r)}function xme(e,t=(r,s)=>Promise.resolve()){return Object.assign(e,{wait(r){return xme(e.then(s=>Promise.all([t(s,r),s])).then(s=>s[1]))}})}function Fat(e){let t=e.length-1;for(t;t>0;t--){let r=Math.floor(Math.random()*(t+1)),s=e[t];e[t]=e[r],e[r]=s}return e}function Nat(e,t){return t&&Object.keys(t).forEach(r=>{e[r]=t[r](e)}),e}function Oat(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}var Lat=\"4.22.1\",Mat=e=>()=>e.transporter.requester.destroy(),mq={WithinQueryParameters:0,WithinHeaders:1};tf.AuthMode=mq;tf.addMethods=Nat;tf.createAuth=Rat;tf.createRetryablePromise=Tat;tf.createWaitablePromise=xme;tf.destroy=Mat;tf.encode=Oat;tf.shuffle=Fat;tf.version=Lat});var vS=G((QVt,Qme)=>{Qme.exports=kme()});var Rme=G(yq=>{\"use strict\";Object.defineProperty(yq,\"__esModule\",{value:!0});var Uat={Delete:\"DELETE\",Get:\"GET\",Post:\"POST\",Put:\"PUT\"};yq.MethodEnum=Uat});var SS=G((TVt,Tme)=>{Tme.exports=Rme()});var Kme=G(Vi=>{\"use strict\";Object.defineProperty(Vi,\"__esModule\",{value:!0});var Nme=SS();function Eq(e,t){let r=e||{},s=r.data||{};return Object.keys(r).forEach(a=>{[\"timeout\",\"headers\",\"queryParameters\",\"data\",\"cacheable\"].indexOf(a)===-1&&(s[a]=r[a])}),{data:Object.entries(s).length>0?s:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var DS={Read:1,Write:2,Any:3},zC={Up:1,Down:2,Timeouted:3},Ome=2*60*1e3;function Cq(e,t=zC.Up){return{...e,status:t,lastUpdate:Date.now()}}function Lme(e){return e.status===zC.Up||Date.now()-e.lastUpdate>Ome}function Mme(e){return e.status===zC.Timeouted&&Date.now()-e.lastUpdate<=Ome}function wq(e){return typeof e==\"string\"?{protocol:\"https\",url:e,accept:DS.Any}:{protocol:e.protocol||\"https\",url:e.url,accept:e.accept||DS.Any}}function _at(e,t){return Promise.all(t.map(r=>e.get(r,()=>Promise.resolve(Cq(r))))).then(r=>{let s=r.filter(f=>Lme(f)),a=r.filter(f=>Mme(f)),n=[...s,...a],c=n.length>0?n.map(f=>wq(f)):t;return{getTimeout(f,p){return(a.length===0&&f===0?1:a.length+3+f)*p},statelessHosts:c}})}var Hat=({isTimedOut:e,status:t})=>!e&&~~t===0,jat=e=>{let t=e.status;return e.isTimedOut||Hat(e)||~~(t/100)!==2&&~~(t/100)!==4},Gat=({status:e})=>~~(e/100)===2,qat=(e,t)=>jat(e)?t.onRetry(e):Gat(e)?t.onSuccess(e):t.onFail(e);function Fme(e,t,r,s){let a=[],n=Gme(r,s),c=qme(e,s),f=r.method,p=r.method!==Nme.MethodEnum.Get?{}:{...r.data,...s.data},h={\"x-algolia-agent\":e.userAgent.value,...e.queryParameters,...p,...s.queryParameters},E=0,C=(S,x)=>{let I=S.pop();if(I===void 0)throw Yme(Iq(a));let T={data:n,headers:c,method:f,url:Hme(I,r.path,h),connectTimeout:x(E,e.timeouts.connect),responseTimeout:x(E,s.timeout)},O=Y=>{let te={request:T,response:Y,host:I,triesLeft:S.length};return a.push(te),te},U={onSuccess:Y=>Ume(Y),onRetry(Y){let te=O(Y);return Y.isTimedOut&&E++,Promise.all([e.logger.info(\"Retryable failure\",Bq(te)),e.hostsCache.set(I,Cq(I,Y.isTimedOut?zC.Timeouted:zC.Down))]).then(()=>C(S,x))},onFail(Y){throw O(Y),_me(Y,Iq(a))}};return e.requester.send(T).then(Y=>qat(Y,U))};return _at(e.hostsCache,t).then(S=>C([...S.statelessHosts].reverse(),S.getTimeout))}function Wat(e){let{hostsCache:t,logger:r,requester:s,requestsCache:a,responsesCache:n,timeouts:c,userAgent:f,hosts:p,queryParameters:h,headers:E}=e,C={hostsCache:t,logger:r,requester:s,requestsCache:a,responsesCache:n,timeouts:c,userAgent:f,headers:E,queryParameters:h,hosts:p.map(S=>wq(S)),read(S,x){let I=Eq(x,C.timeouts.read),T=()=>Fme(C,C.hosts.filter(Y=>(Y.accept&DS.Read)!==0),S,I);if((I.cacheable!==void 0?I.cacheable:S.cacheable)!==!0)return T();let U={request:S,mappedRequestOptions:I,transporter:{queryParameters:C.queryParameters,headers:C.headers}};return C.responsesCache.get(U,()=>C.requestsCache.get(U,()=>C.requestsCache.set(U,T()).then(Y=>Promise.all([C.requestsCache.delete(U),Y]),Y=>Promise.all([C.requestsCache.delete(U),Promise.reject(Y)])).then(([Y,te])=>te)),{miss:Y=>C.responsesCache.set(U,Y)})},write(S,x){return Fme(C,C.hosts.filter(I=>(I.accept&DS.Write)!==0),S,Eq(x,C.timeouts.write))}};return C}function Vat(e){let t={value:`Algolia for JavaScript (${e})`,add(r){let s=`; ${r.segment}${r.version!==void 0?` (${r.version})`:\"\"}`;return t.value.indexOf(s)===-1&&(t.value=`${t.value}${s}`),t}};return t}function Ume(e){try{return JSON.parse(e.content)}catch(t){throw Vme(t.message,e)}}function _me({content:e,status:t},r){let s=e;try{s=JSON.parse(e).message}catch{}return Wme(s,t,r)}function Yat(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}function Hme(e,t,r){let s=jme(r),a=`${e.protocol}://${e.url}/${t.charAt(0)===\"/\"?t.substr(1):t}`;return s.length&&(a+=`?${s}`),a}function jme(e){let t=r=>Object.prototype.toString.call(r)===\"[object Object]\"||Object.prototype.toString.call(r)===\"[object Array]\";return Object.keys(e).map(r=>Yat(\"%s=%s\",r,t(e[r])?JSON.stringify(e[r]):e[r])).join(\"&\")}function Gme(e,t){if(e.method===Nme.MethodEnum.Get||e.data===void 0&&t.data===void 0)return;let r=Array.isArray(e.data)?e.data:{...e.data,...t.data};return JSON.stringify(r)}function qme(e,t){let r={...e.headers,...t.headers},s={};return Object.keys(r).forEach(a=>{let n=r[a];s[a.toLowerCase()]=n}),s}function Iq(e){return e.map(t=>Bq(t))}function Bq(e){let t=e.request.headers[\"x-algolia-api-key\"]?{\"x-algolia-api-key\":\"*****\"}:{};return{...e,request:{...e.request,headers:{...e.request.headers,...t}}}}function Wme(e,t,r){return{name:\"ApiError\",message:e,status:t,transporterStackTrace:r}}function Vme(e,t){return{name:\"DeserializationError\",message:e,response:t}}function Yme(e){return{name:\"RetryError\",message:\"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.\",transporterStackTrace:e}}Vi.CallEnum=DS;Vi.HostStatusEnum=zC;Vi.createApiError=Wme;Vi.createDeserializationError=Vme;Vi.createMappedRequestOptions=Eq;Vi.createRetryError=Yme;Vi.createStatefulHost=Cq;Vi.createStatelessHost=wq;Vi.createTransporter=Wat;Vi.createUserAgent=Vat;Vi.deserializeFailure=_me;Vi.deserializeSuccess=Ume;Vi.isStatefulHostTimeouted=Mme;Vi.isStatefulHostUp=Lme;Vi.serializeData=Gme;Vi.serializeHeaders=qme;Vi.serializeQueryParameters=jme;Vi.serializeUrl=Hme;Vi.stackFrameWithoutCredentials=Bq;Vi.stackTraceWithoutCredentials=Iq});var bS=G((NVt,Jme)=>{Jme.exports=Kme()});var zme=G(J0=>{\"use strict\";Object.defineProperty(J0,\"__esModule\",{value:!0});var ZC=vS(),Kat=bS(),PS=SS(),Jat=e=>{let t=e.region||\"us\",r=ZC.createAuth(ZC.AuthMode.WithinHeaders,e.appId,e.apiKey),s=Kat.createTransporter({hosts:[{url:`analytics.${t}.algolia.com`}],...e,headers:{...r.headers(),\"content-type\":\"application/json\",...e.headers},queryParameters:{...r.queryParameters(),...e.queryParameters}}),a=e.appId;return ZC.addMethods({appId:a,transporter:s},e.methods)},zat=e=>(t,r)=>e.transporter.write({method:PS.MethodEnum.Post,path:\"2/abtests\",data:t},r),Zat=e=>(t,r)=>e.transporter.write({method:PS.MethodEnum.Delete,path:ZC.encode(\"2/abtests/%s\",t)},r),Xat=e=>(t,r)=>e.transporter.read({method:PS.MethodEnum.Get,path:ZC.encode(\"2/abtests/%s\",t)},r),$at=e=>t=>e.transporter.read({method:PS.MethodEnum.Get,path:\"2/abtests\"},t),elt=e=>(t,r)=>e.transporter.write({method:PS.MethodEnum.Post,path:ZC.encode(\"2/abtests/%s/stop\",t)},r);J0.addABTest=zat;J0.createAnalyticsClient=Jat;J0.deleteABTest=Zat;J0.getABTest=Xat;J0.getABTests=$at;J0.stopABTest=elt});var Xme=G((LVt,Zme)=>{Zme.exports=zme()});var eye=G(xS=>{\"use strict\";Object.defineProperty(xS,\"__esModule\",{value:!0});var vq=vS(),tlt=bS(),$me=SS(),rlt=e=>{let t=e.region||\"us\",r=vq.createAuth(vq.AuthMode.WithinHeaders,e.appId,e.apiKey),s=tlt.createTransporter({hosts:[{url:`personalization.${t}.algolia.com`}],...e,headers:{...r.headers(),\"content-type\":\"application/json\",...e.headers},queryParameters:{...r.queryParameters(),...e.queryParameters}});return vq.addMethods({appId:e.appId,transporter:s},e.methods)},nlt=e=>t=>e.transporter.read({method:$me.MethodEnum.Get,path:\"1/strategies/personalization\"},t),ilt=e=>(t,r)=>e.transporter.write({method:$me.MethodEnum.Post,path:\"1/strategies/personalization\",data:t},r);xS.createPersonalizationClient=rlt;xS.getPersonalizationStrategy=nlt;xS.setPersonalizationStrategy=ilt});var rye=G((UVt,tye)=>{tye.exports=eye()});var dye=G(Ft=>{\"use strict\";Object.defineProperty(Ft,\"__esModule\",{value:!0});var Kt=vS(),Cl=bS(),br=SS(),slt=Ie(\"crypto\");function zT(e){let t=r=>e.request(r).then(s=>{if(e.batch!==void 0&&e.batch(s.hits),!e.shouldStop(s))return s.cursor?t({cursor:s.cursor}):t({page:(r.page||0)+1})});return t({})}var olt=e=>{let t=e.appId,r=Kt.createAuth(e.authMode!==void 0?e.authMode:Kt.AuthMode.WithinHeaders,t,e.apiKey),s=Cl.createTransporter({hosts:[{url:`${t}-dsn.algolia.net`,accept:Cl.CallEnum.Read},{url:`${t}.algolia.net`,accept:Cl.CallEnum.Write}].concat(Kt.shuffle([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}])),...e,headers:{...r.headers(),\"content-type\":\"application/x-www-form-urlencoded\",...e.headers},queryParameters:{...r.queryParameters(),...e.queryParameters}}),a={transporter:s,appId:t,addAlgoliaAgent(n,c){s.userAgent.add({segment:n,version:c})},clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then(()=>{})}};return Kt.addMethods(a,e.methods)};function nye(){return{name:\"MissingObjectIDError\",message:\"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option.\"}}function iye(){return{name:\"ObjectNotFoundError\",message:\"Object not found.\"}}function sye(){return{name:\"ValidUntilNotFoundError\",message:\"ValidUntil not found in given secured api key.\"}}var alt=e=>(t,r)=>{let{queryParameters:s,...a}=r||{},n={acl:t,...s!==void 0?{queryParameters:s}:{}},c=(f,p)=>Kt.createRetryablePromise(h=>kS(e)(f.key,p).catch(E=>{if(E.status!==404)throw E;return h()}));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:\"1/keys\",data:n},a),c)},llt=e=>(t,r,s)=>{let a=Cl.createMappedRequestOptions(s);return a.queryParameters[\"X-Algolia-User-ID\"]=t,e.transporter.write({method:br.MethodEnum.Post,path:\"1/clusters/mapping\",data:{cluster:r}},a)},clt=e=>(t,r,s)=>e.transporter.write({method:br.MethodEnum.Post,path:\"1/clusters/mapping/batch\",data:{users:t,cluster:r}},s),ult=e=>(t,r)=>Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"/1/dictionaries/%s/batch\",t),data:{clearExistingDictionaryEntries:!0,requests:{action:\"addEntry\",body:[]}}},r),(s,a)=>XC(e)(s.taskID,a)),ZT=e=>(t,r,s)=>{let a=(n,c)=>QS(e)(t,{methods:{waitTask:ms}}).waitTask(n.taskID,c);return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/operation\",t),data:{operation:\"copy\",destination:r}},s),a)},flt=e=>(t,r,s)=>ZT(e)(t,r,{...s,scope:[$T.Rules]}),Alt=e=>(t,r,s)=>ZT(e)(t,r,{...s,scope:[$T.Settings]}),plt=e=>(t,r,s)=>ZT(e)(t,r,{...s,scope:[$T.Synonyms]}),hlt=e=>(t,r)=>t.method===br.MethodEnum.Get?e.transporter.read(t,r):e.transporter.write(t,r),glt=e=>(t,r)=>{let s=(a,n)=>Kt.createRetryablePromise(c=>kS(e)(t,n).then(c).catch(f=>{if(f.status!==404)throw f}));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Delete,path:Kt.encode(\"1/keys/%s\",t)},r),s)},dlt=e=>(t,r,s)=>{let a=r.map(n=>({action:\"deleteEntry\",body:{objectID:n}}));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"/1/dictionaries/%s/batch\",t),data:{clearExistingDictionaryEntries:!1,requests:a}},s),(n,c)=>XC(e)(n.taskID,c))},mlt=()=>(e,t)=>{let r=Cl.serializeQueryParameters(t),s=slt.createHmac(\"sha256\",e).update(r).digest(\"hex\");return Buffer.from(s+r).toString(\"base64\")},kS=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/keys/%s\",t)},r),oye=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/task/%s\",t.toString())},r),ylt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"/1/dictionaries/*/settings\"},t),Elt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"1/logs\"},t),Ilt=()=>e=>{let t=Buffer.from(e,\"base64\").toString(\"ascii\"),r=/validUntil=(\\d+)/,s=t.match(r);if(s===null)throw sye();return parseInt(s[1],10)-Math.round(new Date().getTime()/1e3)},Clt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"1/clusters/mapping/top\"},t),wlt=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/clusters/mapping/%s\",t)},r),Blt=e=>t=>{let{retrieveMappings:r,...s}=t||{};return r===!0&&(s.getClusters=!0),e.transporter.read({method:br.MethodEnum.Get,path:\"1/clusters/mapping/pending\"},s)},QS=e=>(t,r={})=>{let s={transporter:e.transporter,appId:e.appId,indexName:t};return Kt.addMethods(s,r.methods)},vlt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"1/keys\"},t),Slt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"1/clusters\"},t),Dlt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"1/indexes\"},t),blt=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:\"1/clusters/mapping\"},t),Plt=e=>(t,r,s)=>{let a=(n,c)=>QS(e)(t,{methods:{waitTask:ms}}).waitTask(n.taskID,c);return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/operation\",t),data:{operation:\"move\",destination:r}},s),a)},xlt=e=>(t,r)=>{let s=(a,n)=>Promise.all(Object.keys(a.taskID).map(c=>QS(e)(c,{methods:{waitTask:ms}}).waitTask(a.taskID[c],n)));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:\"1/indexes/*/batch\",data:{requests:t}},r),s)},klt=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Post,path:\"1/indexes/*/objects\",data:{requests:t}},r),Qlt=e=>(t,r)=>{let s=t.map(a=>({...a,params:Cl.serializeQueryParameters(a.params||{})}));return e.transporter.read({method:br.MethodEnum.Post,path:\"1/indexes/*/queries\",data:{requests:s},cacheable:!0},r)},Rlt=e=>(t,r)=>Promise.all(t.map(s=>{let{facetName:a,facetQuery:n,...c}=s.params;return QS(e)(s.indexName,{methods:{searchForFacetValues:pye}}).searchForFacetValues(a,n,{...r,...c})})),Tlt=e=>(t,r)=>{let s=Cl.createMappedRequestOptions(r);return s.queryParameters[\"X-Algolia-User-ID\"]=t,e.transporter.write({method:br.MethodEnum.Delete,path:\"1/clusters/mapping\"},s)},Flt=e=>(t,r,s)=>{let a=r.map(n=>({action:\"addEntry\",body:n}));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"/1/dictionaries/%s/batch\",t),data:{clearExistingDictionaryEntries:!0,requests:a}},s),(n,c)=>XC(e)(n.taskID,c))},Nlt=e=>(t,r)=>{let s=(a,n)=>Kt.createRetryablePromise(c=>kS(e)(t,n).catch(f=>{if(f.status!==404)throw f;return c()}));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/keys/%s/restore\",t)},r),s)},Olt=e=>(t,r,s)=>{let a=r.map(n=>({action:\"addEntry\",body:n}));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"/1/dictionaries/%s/batch\",t),data:{clearExistingDictionaryEntries:!1,requests:a}},s),(n,c)=>XC(e)(n.taskID,c))},Llt=e=>(t,r,s)=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"/1/dictionaries/%s/search\",t),data:{query:r},cacheable:!0},s),Mlt=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Post,path:\"1/clusters/mapping/search\",data:{query:t}},r),Ult=e=>(t,r)=>Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Put,path:\"/1/dictionaries/*/settings\",data:t},r),(s,a)=>XC(e)(s.taskID,a)),_lt=e=>(t,r)=>{let s=Object.assign({},r),{queryParameters:a,...n}=r||{},c=a?{queryParameters:a}:{},f=[\"acl\",\"indexes\",\"referers\",\"restrictSources\",\"queryParameters\",\"description\",\"maxQueriesPerIPPerHour\",\"maxHitsPerQuery\"],p=E=>Object.keys(s).filter(C=>f.indexOf(C)!==-1).every(C=>{if(Array.isArray(E[C])&&Array.isArray(s[C])){let S=E[C];return S.length===s[C].length&&S.every((x,I)=>x===s[C][I])}else return E[C]===s[C]}),h=(E,C)=>Kt.createRetryablePromise(S=>kS(e)(t,C).then(x=>p(x)?Promise.resolve():S()));return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Put,path:Kt.encode(\"1/keys/%s\",t),data:c},n),h)},XC=e=>(t,r)=>Kt.createRetryablePromise(s=>oye(e)(t,r).then(a=>a.status!==\"published\"?s():void 0)),aye=e=>(t,r)=>{let s=(a,n)=>ms(e)(a.taskID,n);return Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/batch\",e.indexName),data:{requests:t}},r),s)},Hlt=e=>t=>zT({shouldStop:r=>r.cursor===void 0,...t,request:r=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/browse\",e.indexName),data:r},t)}),jlt=e=>t=>{let r={hitsPerPage:1e3,...t};return zT({shouldStop:s=>s.hits.length<r.hitsPerPage,...r,request(s){return hye(e)(\"\",{...r,...s}).then(a=>({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},Glt=e=>t=>{let r={hitsPerPage:1e3,...t};return zT({shouldStop:s=>s.hits.length<r.hitsPerPage,...r,request(s){return gye(e)(\"\",{...r,...s}).then(a=>({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},XT=e=>(t,r,s)=>{let{batchSize:a,...n}=s||{},c={taskIDs:[],objectIDs:[]},f=(p=0)=>{let h=[],E;for(E=p;E<t.length&&(h.push(t[E]),h.length!==(a||1e3));E++);return h.length===0?Promise.resolve(c):aye(e)(h.map(C=>({action:r,body:C})),n).then(C=>(c.objectIDs=c.objectIDs.concat(C.objectIDs),c.taskIDs.push(C.taskID),E++,f(E)))};return Kt.createWaitablePromise(f(),(p,h)=>Promise.all(p.taskIDs.map(E=>ms(e)(E,h))))},qlt=e=>t=>Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/clear\",e.indexName)},t),(r,s)=>ms(e)(r.taskID,s)),Wlt=e=>t=>{let{forwardToReplicas:r,...s}=t||{},a=Cl.createMappedRequestOptions(s);return r&&(a.queryParameters.forwardToReplicas=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/rules/clear\",e.indexName)},a),(n,c)=>ms(e)(n.taskID,c))},Vlt=e=>t=>{let{forwardToReplicas:r,...s}=t||{},a=Cl.createMappedRequestOptions(s);return r&&(a.queryParameters.forwardToReplicas=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/synonyms/clear\",e.indexName)},a),(n,c)=>ms(e)(n.taskID,c))},Ylt=e=>(t,r)=>Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/deleteByQuery\",e.indexName),data:t},r),(s,a)=>ms(e)(s.taskID,a)),Klt=e=>t=>Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Delete,path:Kt.encode(\"1/indexes/%s\",e.indexName)},t),(r,s)=>ms(e)(r.taskID,s)),Jlt=e=>(t,r)=>Kt.createWaitablePromise(lye(e)([t],r).then(s=>({taskID:s.taskIDs[0]})),(s,a)=>ms(e)(s.taskID,a)),lye=e=>(t,r)=>{let s=t.map(a=>({objectID:a}));return XT(e)(s,Tm.DeleteObject,r)},zlt=e=>(t,r)=>{let{forwardToReplicas:s,...a}=r||{},n=Cl.createMappedRequestOptions(a);return s&&(n.queryParameters.forwardToReplicas=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Delete,path:Kt.encode(\"1/indexes/%s/rules/%s\",e.indexName,t)},n),(c,f)=>ms(e)(c.taskID,f))},Zlt=e=>(t,r)=>{let{forwardToReplicas:s,...a}=r||{},n=Cl.createMappedRequestOptions(a);return s&&(n.queryParameters.forwardToReplicas=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Delete,path:Kt.encode(\"1/indexes/%s/synonyms/%s\",e.indexName,t)},n),(c,f)=>ms(e)(c.taskID,f))},Xlt=e=>t=>cye(e)(t).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),$lt=e=>(t,r,s)=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"1/answers/%s/prediction\",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},s),ect=e=>(t,r)=>{let{query:s,paginate:a,...n}=r||{},c=0,f=()=>Aye(e)(s||\"\",{...n,page:c}).then(p=>{for(let[h,E]of Object.entries(p.hits))if(t(E))return{object:E,position:parseInt(h,10),page:c};if(c++,a===!1||c>=p.nbPages)throw iye();return f()});return f()},tct=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/indexes/%s/%s\",e.indexName,t)},r),rct=()=>(e,t)=>{for(let[r,s]of Object.entries(e.hits))if(s.objectID===t)return parseInt(r,10);return-1},nct=e=>(t,r)=>{let{attributesToRetrieve:s,...a}=r||{},n=t.map(c=>({indexName:e.indexName,objectID:c,...s?{attributesToRetrieve:s}:{}}));return e.transporter.read({method:br.MethodEnum.Post,path:\"1/indexes/*/objects\",data:{requests:n}},a)},ict=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/indexes/%s/rules/%s\",e.indexName,t)},r),cye=e=>t=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/indexes/%s/settings\",e.indexName),data:{getVersion:2}},t),sct=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/indexes/%s/synonyms/%s\",e.indexName,t)},r),uye=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Get,path:Kt.encode(\"1/indexes/%s/task/%s\",e.indexName,t.toString())},r),oct=e=>(t,r)=>Kt.createWaitablePromise(fye(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,a)=>ms(e)(s.taskID,a)),fye=e=>(t,r)=>{let{createIfNotExists:s,...a}=r||{},n=s?Tm.PartialUpdateObject:Tm.PartialUpdateObjectNoCreate;return XT(e)(t,n,a)},act=e=>(t,r)=>{let{safe:s,autoGenerateObjectIDIfNotExist:a,batchSize:n,...c}=r||{},f=(I,T,O,U)=>Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/operation\",I),data:{operation:O,destination:T}},U),(Y,te)=>ms(e)(Y.taskID,te)),p=Math.random().toString(36).substring(7),h=`${e.indexName}_tmp_${p}`,E=Sq({appId:e.appId,transporter:e.transporter,indexName:h}),C=[],S=f(e.indexName,h,\"copy\",{...c,scope:[\"settings\",\"synonyms\",\"rules\"]});C.push(S);let x=(s?S.wait(c):S).then(()=>{let I=E(t,{...c,autoGenerateObjectIDIfNotExist:a,batchSize:n});return C.push(I),s?I.wait(c):I}).then(()=>{let I=f(h,e.indexName,\"move\",c);return C.push(I),s?I.wait(c):I}).then(()=>Promise.all(C)).then(([I,T,O])=>({objectIDs:T.objectIDs,taskIDs:[I.taskID,...T.taskIDs,O.taskID]}));return Kt.createWaitablePromise(x,(I,T)=>Promise.all(C.map(O=>O.wait(T))))},lct=e=>(t,r)=>Dq(e)(t,{...r,clearExistingRules:!0}),cct=e=>(t,r)=>bq(e)(t,{...r,clearExistingSynonyms:!0}),uct=e=>(t,r)=>Kt.createWaitablePromise(Sq(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,a)=>ms(e)(s.taskID,a)),Sq=e=>(t,r)=>{let{autoGenerateObjectIDIfNotExist:s,...a}=r||{},n=s?Tm.AddObject:Tm.UpdateObject;if(n===Tm.UpdateObject){for(let c of t)if(c.objectID===void 0)return Kt.createWaitablePromise(Promise.reject(nye()))}return XT(e)(t,n,a)},fct=e=>(t,r)=>Dq(e)([t],r),Dq=e=>(t,r)=>{let{forwardToReplicas:s,clearExistingRules:a,...n}=r||{},c=Cl.createMappedRequestOptions(n);return s&&(c.queryParameters.forwardToReplicas=1),a&&(c.queryParameters.clearExistingRules=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/rules/batch\",e.indexName),data:t},c),(f,p)=>ms(e)(f.taskID,p))},Act=e=>(t,r)=>bq(e)([t],r),bq=e=>(t,r)=>{let{forwardToReplicas:s,clearExistingSynonyms:a,replaceExistingSynonyms:n,...c}=r||{},f=Cl.createMappedRequestOptions(c);return s&&(f.queryParameters.forwardToReplicas=1),(n||a)&&(f.queryParameters.replaceExistingSynonyms=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/synonyms/batch\",e.indexName),data:t},f),(p,h)=>ms(e)(p.taskID,h))},Aye=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/query\",e.indexName),data:{query:t},cacheable:!0},r),pye=e=>(t,r,s)=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/facets/%s/query\",e.indexName,t),data:{facetQuery:r},cacheable:!0},s),hye=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/rules/search\",e.indexName),data:{query:t}},r),gye=e=>(t,r)=>e.transporter.read({method:br.MethodEnum.Post,path:Kt.encode(\"1/indexes/%s/synonyms/search\",e.indexName),data:{query:t}},r),pct=e=>(t,r)=>{let{forwardToReplicas:s,...a}=r||{},n=Cl.createMappedRequestOptions(a);return s&&(n.queryParameters.forwardToReplicas=1),Kt.createWaitablePromise(e.transporter.write({method:br.MethodEnum.Put,path:Kt.encode(\"1/indexes/%s/settings\",e.indexName),data:t},n),(c,f)=>ms(e)(c.taskID,f))},ms=e=>(t,r)=>Kt.createRetryablePromise(s=>uye(e)(t,r).then(a=>a.status!==\"published\"?s():void 0)),hct={AddObject:\"addObject\",Analytics:\"analytics\",Browser:\"browse\",DeleteIndex:\"deleteIndex\",DeleteObject:\"deleteObject\",EditSettings:\"editSettings\",Inference:\"inference\",ListIndexes:\"listIndexes\",Logs:\"logs\",Personalization:\"personalization\",Recommendation:\"recommendation\",Search:\"search\",SeeUnretrievableAttributes:\"seeUnretrievableAttributes\",Settings:\"settings\",Usage:\"usage\"},Tm={AddObject:\"addObject\",UpdateObject:\"updateObject\",PartialUpdateObject:\"partialUpdateObject\",PartialUpdateObjectNoCreate:\"partialUpdateObjectNoCreate\",DeleteObject:\"deleteObject\",DeleteIndex:\"delete\",ClearIndex:\"clear\"},$T={Settings:\"settings\",Synonyms:\"synonyms\",Rules:\"rules\"},gct={None:\"none\",StopIfEnoughMatches:\"stopIfEnoughMatches\"},dct={Synonym:\"synonym\",OneWaySynonym:\"oneWaySynonym\",AltCorrection1:\"altCorrection1\",AltCorrection2:\"altCorrection2\",Placeholder:\"placeholder\"};Ft.ApiKeyACLEnum=hct;Ft.BatchActionEnum=Tm;Ft.ScopeEnum=$T;Ft.StrategyEnum=gct;Ft.SynonymEnum=dct;Ft.addApiKey=alt;Ft.assignUserID=llt;Ft.assignUserIDs=clt;Ft.batch=aye;Ft.browseObjects=Hlt;Ft.browseRules=jlt;Ft.browseSynonyms=Glt;Ft.chunkedBatch=XT;Ft.clearDictionaryEntries=ult;Ft.clearObjects=qlt;Ft.clearRules=Wlt;Ft.clearSynonyms=Vlt;Ft.copyIndex=ZT;Ft.copyRules=flt;Ft.copySettings=Alt;Ft.copySynonyms=plt;Ft.createBrowsablePromise=zT;Ft.createMissingObjectIDError=nye;Ft.createObjectNotFoundError=iye;Ft.createSearchClient=olt;Ft.createValidUntilNotFoundError=sye;Ft.customRequest=hlt;Ft.deleteApiKey=glt;Ft.deleteBy=Ylt;Ft.deleteDictionaryEntries=dlt;Ft.deleteIndex=Klt;Ft.deleteObject=Jlt;Ft.deleteObjects=lye;Ft.deleteRule=zlt;Ft.deleteSynonym=Zlt;Ft.exists=Xlt;Ft.findAnswers=$lt;Ft.findObject=ect;Ft.generateSecuredApiKey=mlt;Ft.getApiKey=kS;Ft.getAppTask=oye;Ft.getDictionarySettings=ylt;Ft.getLogs=Elt;Ft.getObject=tct;Ft.getObjectPosition=rct;Ft.getObjects=nct;Ft.getRule=ict;Ft.getSecuredApiKeyRemainingValidity=Ilt;Ft.getSettings=cye;Ft.getSynonym=sct;Ft.getTask=uye;Ft.getTopUserIDs=Clt;Ft.getUserID=wlt;Ft.hasPendingMappings=Blt;Ft.initIndex=QS;Ft.listApiKeys=vlt;Ft.listClusters=Slt;Ft.listIndices=Dlt;Ft.listUserIDs=blt;Ft.moveIndex=Plt;Ft.multipleBatch=xlt;Ft.multipleGetObjects=klt;Ft.multipleQueries=Qlt;Ft.multipleSearchForFacetValues=Rlt;Ft.partialUpdateObject=oct;Ft.partialUpdateObjects=fye;Ft.removeUserID=Tlt;Ft.replaceAllObjects=act;Ft.replaceAllRules=lct;Ft.replaceAllSynonyms=cct;Ft.replaceDictionaryEntries=Flt;Ft.restoreApiKey=Nlt;Ft.saveDictionaryEntries=Olt;Ft.saveObject=uct;Ft.saveObjects=Sq;Ft.saveRule=fct;Ft.saveRules=Dq;Ft.saveSynonym=Act;Ft.saveSynonyms=bq;Ft.search=Aye;Ft.searchDictionaryEntries=Llt;Ft.searchForFacetValues=pye;Ft.searchRules=hye;Ft.searchSynonyms=gye;Ft.searchUserIDs=Mlt;Ft.setDictionarySettings=Ult;Ft.setSettings=pct;Ft.updateApiKey=_lt;Ft.waitAppTask=XC;Ft.waitTask=ms});var yye=G((HVt,mye)=>{mye.exports=dye()});var Eye=G(eF=>{\"use strict\";Object.defineProperty(eF,\"__esModule\",{value:!0});function mct(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var yct={Debug:1,Info:2,Error:3};eF.LogLevelEnum=yct;eF.createNullLogger=mct});var Cye=G((GVt,Iye)=>{Iye.exports=Eye()});var Sye=G(Pq=>{\"use strict\";Object.defineProperty(Pq,\"__esModule\",{value:!0});var wye=Ie(\"http\"),Bye=Ie(\"https\"),Ect=Ie(\"url\"),vye={keepAlive:!0},Ict=new wye.Agent(vye),Cct=new Bye.Agent(vye);function wct({agent:e,httpAgent:t,httpsAgent:r,requesterOptions:s={}}={}){let a=t||e||Ict,n=r||e||Cct;return{send(c){return new Promise(f=>{let p=Ect.parse(c.url),h=p.query===null?p.pathname:`${p.pathname}?${p.query}`,E={...s,agent:p.protocol===\"https:\"?n:a,hostname:p.hostname,path:h,method:c.method,headers:{...s&&s.headers?s.headers:{},...c.headers},...p.port!==void 0?{port:p.port||\"\"}:{}},C=(p.protocol===\"https:\"?Bye:wye).request(E,T=>{let O=[];T.on(\"data\",U=>{O=O.concat(U)}),T.on(\"end\",()=>{clearTimeout(x),clearTimeout(I),f({status:T.statusCode||0,content:Buffer.concat(O).toString(),isTimedOut:!1})})}),S=(T,O)=>setTimeout(()=>{C.abort(),f({status:0,content:O,isTimedOut:!0})},T*1e3),x=S(c.connectTimeout,\"Connection timeout\"),I;C.on(\"error\",T=>{clearTimeout(x),clearTimeout(I),f({status:0,content:T.message,isTimedOut:!1})}),C.once(\"response\",()=>{clearTimeout(x),I=S(c.responseTimeout,\"Socket timeout\")}),c.data!==void 0&&C.write(c.data),C.end()})},destroy(){return a.destroy(),n.destroy(),Promise.resolve()}}}Pq.createNodeHttpRequester=wct});var bye=G((WVt,Dye)=>{Dye.exports=Sye()});var Qye=G((VVt,kye)=>{\"use strict\";var Pye=Sme(),Bct=Pme(),$C=Xme(),kq=vS(),xq=rye(),Gt=yye(),vct=Cye(),Sct=bye(),Dct=bS();function xye(e,t,r){let s={appId:e,apiKey:t,timeouts:{connect:2,read:5,write:30},requester:Sct.createNodeHttpRequester(),logger:vct.createNullLogger(),responsesCache:Pye.createNullCache(),requestsCache:Pye.createNullCache(),hostsCache:Bct.createInMemoryCache(),userAgent:Dct.createUserAgent(kq.version).add({segment:\"Node.js\",version:process.versions.node})},a={...s,...r},n=()=>c=>xq.createPersonalizationClient({...s,...c,methods:{getPersonalizationStrategy:xq.getPersonalizationStrategy,setPersonalizationStrategy:xq.setPersonalizationStrategy}});return Gt.createSearchClient({...a,methods:{search:Gt.multipleQueries,searchForFacetValues:Gt.multipleSearchForFacetValues,multipleBatch:Gt.multipleBatch,multipleGetObjects:Gt.multipleGetObjects,multipleQueries:Gt.multipleQueries,copyIndex:Gt.copyIndex,copySettings:Gt.copySettings,copyRules:Gt.copyRules,copySynonyms:Gt.copySynonyms,moveIndex:Gt.moveIndex,listIndices:Gt.listIndices,getLogs:Gt.getLogs,listClusters:Gt.listClusters,multipleSearchForFacetValues:Gt.multipleSearchForFacetValues,getApiKey:Gt.getApiKey,addApiKey:Gt.addApiKey,listApiKeys:Gt.listApiKeys,updateApiKey:Gt.updateApiKey,deleteApiKey:Gt.deleteApiKey,restoreApiKey:Gt.restoreApiKey,assignUserID:Gt.assignUserID,assignUserIDs:Gt.assignUserIDs,getUserID:Gt.getUserID,searchUserIDs:Gt.searchUserIDs,listUserIDs:Gt.listUserIDs,getTopUserIDs:Gt.getTopUserIDs,removeUserID:Gt.removeUserID,hasPendingMappings:Gt.hasPendingMappings,generateSecuredApiKey:Gt.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:Gt.getSecuredApiKeyRemainingValidity,destroy:kq.destroy,clearDictionaryEntries:Gt.clearDictionaryEntries,deleteDictionaryEntries:Gt.deleteDictionaryEntries,getDictionarySettings:Gt.getDictionarySettings,getAppTask:Gt.getAppTask,replaceDictionaryEntries:Gt.replaceDictionaryEntries,saveDictionaryEntries:Gt.saveDictionaryEntries,searchDictionaryEntries:Gt.searchDictionaryEntries,setDictionarySettings:Gt.setDictionarySettings,waitAppTask:Gt.waitAppTask,customRequest:Gt.customRequest,initIndex:c=>f=>Gt.initIndex(c)(f,{methods:{batch:Gt.batch,delete:Gt.deleteIndex,findAnswers:Gt.findAnswers,getObject:Gt.getObject,getObjects:Gt.getObjects,saveObject:Gt.saveObject,saveObjects:Gt.saveObjects,search:Gt.search,searchForFacetValues:Gt.searchForFacetValues,waitTask:Gt.waitTask,setSettings:Gt.setSettings,getSettings:Gt.getSettings,partialUpdateObject:Gt.partialUpdateObject,partialUpdateObjects:Gt.partialUpdateObjects,deleteObject:Gt.deleteObject,deleteObjects:Gt.deleteObjects,deleteBy:Gt.deleteBy,clearObjects:Gt.clearObjects,browseObjects:Gt.browseObjects,getObjectPosition:Gt.getObjectPosition,findObject:Gt.findObject,exists:Gt.exists,saveSynonym:Gt.saveSynonym,saveSynonyms:Gt.saveSynonyms,getSynonym:Gt.getSynonym,searchSynonyms:Gt.searchSynonyms,browseSynonyms:Gt.browseSynonyms,deleteSynonym:Gt.deleteSynonym,clearSynonyms:Gt.clearSynonyms,replaceAllObjects:Gt.replaceAllObjects,replaceAllSynonyms:Gt.replaceAllSynonyms,searchRules:Gt.searchRules,getRule:Gt.getRule,deleteRule:Gt.deleteRule,saveRule:Gt.saveRule,saveRules:Gt.saveRules,replaceAllRules:Gt.replaceAllRules,browseRules:Gt.browseRules,clearRules:Gt.clearRules}}),initAnalytics:()=>c=>$C.createAnalyticsClient({...s,...c,methods:{addABTest:$C.addABTest,getABTest:$C.getABTest,getABTests:$C.getABTests,stopABTest:$C.stopABTest,deleteABTest:$C.deleteABTest}}),initPersonalization:n,initRecommendation:()=>c=>(a.logger.info(\"The `initRecommendation` method is deprecated. Use `initPersonalization` instead.\"),n()(c))}})}xye.version=kq.version;kye.exports=xye});var Rq=G((YVt,Qq)=>{var Rye=Qye();Qq.exports=Rye;Qq.exports.default=Rye});var Nq=G((JVt,Nye)=>{\"use strict\";var Fye=Object.getOwnPropertySymbols,Pct=Object.prototype.hasOwnProperty,xct=Object.prototype.propertyIsEnumerable;function kct(e){if(e==null)throw new TypeError(\"Object.assign cannot be called with null or undefined\");return Object(e)}function Qct(){try{if(!Object.assign)return!1;var e=new String(\"abc\");if(e[5]=\"de\",Object.getOwnPropertyNames(e)[0]===\"5\")return!1;for(var t={},r=0;r<10;r++)t[\"_\"+String.fromCharCode(r)]=r;var s=Object.getOwnPropertyNames(t).map(function(n){return t[n]});if(s.join(\"\")!==\"0123456789\")return!1;var a={};return\"abcdefghijklmnopqrst\".split(\"\").forEach(function(n){a[n]=n}),Object.keys(Object.assign({},a)).join(\"\")===\"abcdefghijklmnopqrst\"}catch{return!1}}Nye.exports=Qct()?Object.assign:function(e,t){for(var r,s=kct(e),a,n=1;n<arguments.length;n++){r=Object(arguments[n]);for(var c in r)Pct.call(r,c)&&(s[c]=r[c]);if(Fye){a=Fye(r);for(var f=0;f<a.length;f++)xct.call(r,a[f])&&(s[a[f]]=r[a[f]])}}return s}});var Zye=G(Pn=>{\"use strict\";var Lq=Nq(),ew=60103,Mye=60106;Pn.Fragment=60107;Pn.StrictMode=60108;Pn.Profiler=60114;var Uye=60109,_ye=60110,Hye=60112;Pn.Suspense=60113;var jye=60115,Gye=60116;typeof Symbol==\"function\"&&Symbol.for&&(Hc=Symbol.for,ew=Hc(\"react.element\"),Mye=Hc(\"react.portal\"),Pn.Fragment=Hc(\"react.fragment\"),Pn.StrictMode=Hc(\"react.strict_mode\"),Pn.Profiler=Hc(\"react.profiler\"),Uye=Hc(\"react.provider\"),_ye=Hc(\"react.context\"),Hye=Hc(\"react.forward_ref\"),Pn.Suspense=Hc(\"react.suspense\"),jye=Hc(\"react.memo\"),Gye=Hc(\"react.lazy\"));var Hc,Oye=typeof Symbol==\"function\"&&Symbol.iterator;function Rct(e){return e===null||typeof e!=\"object\"?null:(e=Oye&&e[Oye]||e[\"@@iterator\"],typeof e==\"function\"?e:null)}function RS(e){for(var t=\"https://reactjs.org/docs/error-decoder.html?invariant=\"+e,r=1;r<arguments.length;r++)t+=\"&args[]=\"+encodeURIComponent(arguments[r]);return\"Minified React error #\"+e+\"; visit \"+t+\" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"}var qye={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Wye={};function tw(e,t,r){this.props=e,this.context=t,this.refs=Wye,this.updater=r||qye}tw.prototype.isReactComponent={};tw.prototype.setState=function(e,t){if(typeof e!=\"object\"&&typeof e!=\"function\"&&e!=null)throw Error(RS(85));this.updater.enqueueSetState(this,e,t,\"setState\")};tw.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,\"forceUpdate\")};function Vye(){}Vye.prototype=tw.prototype;function Mq(e,t,r){this.props=e,this.context=t,this.refs=Wye,this.updater=r||qye}var Uq=Mq.prototype=new Vye;Uq.constructor=Mq;Lq(Uq,tw.prototype);Uq.isPureReactComponent=!0;var _q={current:null},Yye=Object.prototype.hasOwnProperty,Kye={key:!0,ref:!0,__self:!0,__source:!0};function Jye(e,t,r){var s,a={},n=null,c=null;if(t!=null)for(s in t.ref!==void 0&&(c=t.ref),t.key!==void 0&&(n=\"\"+t.key),t)Yye.call(t,s)&&!Kye.hasOwnProperty(s)&&(a[s]=t[s]);var f=arguments.length-2;if(f===1)a.children=r;else if(1<f){for(var p=Array(f),h=0;h<f;h++)p[h]=arguments[h+2];a.children=p}if(e&&e.defaultProps)for(s in f=e.defaultProps,f)a[s]===void 0&&(a[s]=f[s]);return{$$typeof:ew,type:e,key:n,ref:c,props:a,_owner:_q.current}}function Tct(e,t){return{$$typeof:ew,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}function Hq(e){return typeof e==\"object\"&&e!==null&&e.$$typeof===ew}function Fct(e){var t={\"=\":\"=0\",\":\":\"=2\"};return\"$\"+e.replace(/[=:]/g,function(r){return t[r]})}var Lye=/\\/+/g;function Oq(e,t){return typeof e==\"object\"&&e!==null&&e.key!=null?Fct(\"\"+e.key):t.toString(36)}function rF(e,t,r,s,a){var n=typeof e;(n===\"undefined\"||n===\"boolean\")&&(e=null);var c=!1;if(e===null)c=!0;else switch(n){case\"string\":case\"number\":c=!0;break;case\"object\":switch(e.$$typeof){case ew:case Mye:c=!0}}if(c)return c=e,a=a(c),e=s===\"\"?\".\"+Oq(c,0):s,Array.isArray(a)?(r=\"\",e!=null&&(r=e.replace(Lye,\"$&/\")+\"/\"),rF(a,t,r,\"\",function(h){return h})):a!=null&&(Hq(a)&&(a=Tct(a,r+(!a.key||c&&c.key===a.key?\"\":(\"\"+a.key).replace(Lye,\"$&/\")+\"/\")+e)),t.push(a)),1;if(c=0,s=s===\"\"?\".\":s+\":\",Array.isArray(e))for(var f=0;f<e.length;f++){n=e[f];var p=s+Oq(n,f);c+=rF(n,t,r,p,a)}else if(p=Rct(e),typeof p==\"function\")for(e=p.call(e),f=0;!(n=e.next()).done;)n=n.value,p=s+Oq(n,f++),c+=rF(n,t,r,p,a);else if(n===\"object\")throw t=\"\"+e,Error(RS(31,t===\"[object Object]\"?\"object with keys {\"+Object.keys(e).join(\", \")+\"}\":t));return c}function tF(e,t,r){if(e==null)return e;var s=[],a=0;return rF(e,s,\"\",\"\",function(n){return t.call(r,n,a++)}),s}function Nct(e){if(e._status===-1){var t=e._result;t=t(),e._status=0,e._result=t,t.then(function(r){e._status===0&&(r=r.default,e._status=1,e._result=r)},function(r){e._status===0&&(e._status=2,e._result=r)})}if(e._status===1)return e._result;throw e._result}var zye={current:null};function zp(){var e=zye.current;if(e===null)throw Error(RS(321));return e}var Oct={ReactCurrentDispatcher:zye,ReactCurrentBatchConfig:{transition:0},ReactCurrentOwner:_q,IsSomeRendererActing:{current:!1},assign:Lq};Pn.Children={map:tF,forEach:function(e,t,r){tF(e,function(){t.apply(this,arguments)},r)},count:function(e){var t=0;return tF(e,function(){t++}),t},toArray:function(e){return tF(e,function(t){return t})||[]},only:function(e){if(!Hq(e))throw Error(RS(143));return e}};Pn.Component=tw;Pn.PureComponent=Mq;Pn.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Oct;Pn.cloneElement=function(e,t,r){if(e==null)throw Error(RS(267,e));var s=Lq({},e.props),a=e.key,n=e.ref,c=e._owner;if(t!=null){if(t.ref!==void 0&&(n=t.ref,c=_q.current),t.key!==void 0&&(a=\"\"+t.key),e.type&&e.type.defaultProps)var f=e.type.defaultProps;for(p in t)Yye.call(t,p)&&!Kye.hasOwnProperty(p)&&(s[p]=t[p]===void 0&&f!==void 0?f[p]:t[p])}var p=arguments.length-2;if(p===1)s.children=r;else if(1<p){f=Array(p);for(var h=0;h<p;h++)f[h]=arguments[h+2];s.children=f}return{$$typeof:ew,type:e.type,key:a,ref:n,props:s,_owner:c}};Pn.createContext=function(e,t){return t===void 0&&(t=null),e={$$typeof:_ye,_calculateChangedBits:t,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null},e.Provider={$$typeof:Uye,_context:e},e.Consumer=e};Pn.createElement=Jye;Pn.createFactory=function(e){var t=Jye.bind(null,e);return t.type=e,t};Pn.createRef=function(){return{current:null}};Pn.forwardRef=function(e){return{$$typeof:Hye,render:e}};Pn.isValidElement=Hq;Pn.lazy=function(e){return{$$typeof:Gye,_payload:{_status:-1,_result:e},_init:Nct}};Pn.memo=function(e,t){return{$$typeof:jye,type:e,compare:t===void 0?null:t}};Pn.useCallback=function(e,t){return zp().useCallback(e,t)};Pn.useContext=function(e,t){return zp().useContext(e,t)};Pn.useDebugValue=function(){};Pn.useEffect=function(e,t){return zp().useEffect(e,t)};Pn.useImperativeHandle=function(e,t,r){return zp().useImperativeHandle(e,t,r)};Pn.useLayoutEffect=function(e,t){return zp().useLayoutEffect(e,t)};Pn.useMemo=function(e,t){return zp().useMemo(e,t)};Pn.useReducer=function(e,t,r){return zp().useReducer(e,t,r)};Pn.useRef=function(e){return zp().useRef(e)};Pn.useState=function(e){return zp().useState(e)};Pn.version=\"17.0.2\"});var gn=G((ZVt,Xye)=>{\"use strict\";Xye.exports=Zye()});var nF=G((XVt,$ye)=>{function Lct(e){var t=typeof e;return e!=null&&(t==\"object\"||t==\"function\")}$ye.exports=Lct});var tEe=G(($Vt,eEe)=>{var Mct=typeof global==\"object\"&&global&&global.Object===Object&&global;eEe.exports=Mct});var jq=G((eYt,rEe)=>{var Uct=tEe(),_ct=typeof self==\"object\"&&self&&self.Object===Object&&self,Hct=Uct||_ct||Function(\"return this\")();rEe.exports=Hct});var iEe=G((tYt,nEe)=>{var jct=jq(),Gct=function(){return jct.Date.now()};nEe.exports=Gct});var oEe=G((rYt,sEe)=>{var qct=/\\s/;function Wct(e){for(var t=e.length;t--&&qct.test(e.charAt(t)););return t}sEe.exports=Wct});var lEe=G((nYt,aEe)=>{var Vct=oEe(),Yct=/^\\s+/;function Kct(e){return e&&e.slice(0,Vct(e)+1).replace(Yct,\"\")}aEe.exports=Kct});var Gq=G((iYt,cEe)=>{var Jct=jq(),zct=Jct.Symbol;cEe.exports=zct});var pEe=G((sYt,AEe)=>{var uEe=Gq(),fEe=Object.prototype,Zct=fEe.hasOwnProperty,Xct=fEe.toString,TS=uEe?uEe.toStringTag:void 0;function $ct(e){var t=Zct.call(e,TS),r=e[TS];try{e[TS]=void 0;var s=!0}catch{}var a=Xct.call(e);return s&&(t?e[TS]=r:delete e[TS]),a}AEe.exports=$ct});var gEe=G((oYt,hEe)=>{var eut=Object.prototype,tut=eut.toString;function rut(e){return tut.call(e)}hEe.exports=rut});var EEe=G((aYt,yEe)=>{var dEe=Gq(),nut=pEe(),iut=gEe(),sut=\"[object Null]\",out=\"[object Undefined]\",mEe=dEe?dEe.toStringTag:void 0;function aut(e){return e==null?e===void 0?out:sut:mEe&&mEe in Object(e)?nut(e):iut(e)}yEe.exports=aut});var CEe=G((lYt,IEe)=>{function lut(e){return e!=null&&typeof e==\"object\"}IEe.exports=lut});var BEe=G((cYt,wEe)=>{var cut=EEe(),uut=CEe(),fut=\"[object Symbol]\";function Aut(e){return typeof e==\"symbol\"||uut(e)&&cut(e)==fut}wEe.exports=Aut});var bEe=G((uYt,DEe)=>{var put=lEe(),vEe=nF(),hut=BEe(),SEe=NaN,gut=/^[-+]0x[0-9a-f]+$/i,dut=/^0b[01]+$/i,mut=/^0o[0-7]+$/i,yut=parseInt;function Eut(e){if(typeof e==\"number\")return e;if(hut(e))return SEe;if(vEe(e)){var t=typeof e.valueOf==\"function\"?e.valueOf():e;e=vEe(t)?t+\"\":t}if(typeof e!=\"string\")return e===0?e:+e;e=put(e);var r=dut.test(e);return r||mut.test(e)?yut(e.slice(2),r?2:8):gut.test(e)?SEe:+e}DEe.exports=Eut});var kEe=G((fYt,xEe)=>{var Iut=nF(),qq=iEe(),PEe=bEe(),Cut=\"Expected a function\",wut=Math.max,But=Math.min;function vut(e,t,r){var s,a,n,c,f,p,h=0,E=!1,C=!1,S=!0;if(typeof e!=\"function\")throw new TypeError(Cut);t=PEe(t)||0,Iut(r)&&(E=!!r.leading,C=\"maxWait\"in r,n=C?wut(PEe(r.maxWait)||0,t):n,S=\"trailing\"in r?!!r.trailing:S);function x(ae){var de=s,Ae=a;return s=a=void 0,h=ae,c=e.apply(Ae,de),c}function I(ae){return h=ae,f=setTimeout(U,t),E?x(ae):c}function T(ae){var de=ae-p,Ae=ae-h,Ce=t-de;return C?But(Ce,n-Ae):Ce}function O(ae){var de=ae-p,Ae=ae-h;return p===void 0||de>=t||de<0||C&&Ae>=n}function U(){var ae=qq();if(O(ae))return Y(ae);f=setTimeout(U,T(ae))}function Y(ae){return f=void 0,S&&s?x(ae):(s=a=void 0,c)}function te(){f!==void 0&&clearTimeout(f),h=0,s=p=a=f=void 0}function ie(){return f===void 0?c:Y(qq())}function ue(){var ae=qq(),de=O(ae);if(s=arguments,a=this,p=ae,de){if(f===void 0)return I(p);if(C)return clearTimeout(f),f=setTimeout(U,t),x(p)}return f===void 0&&(f=setTimeout(U,t)),c}return ue.cancel=te,ue.flush=ie,ue}xEe.exports=vut});var REe=G((AYt,QEe)=>{var Sut=kEe(),Dut=nF(),but=\"Expected a function\";function Put(e,t,r){var s=!0,a=!0;if(typeof e!=\"function\")throw new TypeError(but);return Dut(r)&&(s=\"leading\"in r?!!r.leading:s,a=\"trailing\"in r?!!r.trailing:a),Sut(e,t,{leading:s,maxWait:t,trailing:a})}QEe.exports=Put});var Vq=G((pYt,Wq)=>{\"use strict\";var Bn=Wq.exports;Wq.exports.default=Bn;var $n=\"\\x1B[\",NS=\"\\x1B]\",rw=\"\\x07\",iF=\";\",TEe=process.env.TERM_PROGRAM===\"Apple_Terminal\";Bn.cursorTo=(e,t)=>{if(typeof e!=\"number\")throw new TypeError(\"The `x` argument is required\");return typeof t!=\"number\"?$n+(e+1)+\"G\":$n+(t+1)+\";\"+(e+1)+\"H\"};Bn.cursorMove=(e,t)=>{if(typeof e!=\"number\")throw new TypeError(\"The `x` argument is required\");let r=\"\";return e<0?r+=$n+-e+\"D\":e>0&&(r+=$n+e+\"C\"),t<0?r+=$n+-t+\"A\":t>0&&(r+=$n+t+\"B\"),r};Bn.cursorUp=(e=1)=>$n+e+\"A\";Bn.cursorDown=(e=1)=>$n+e+\"B\";Bn.cursorForward=(e=1)=>$n+e+\"C\";Bn.cursorBackward=(e=1)=>$n+e+\"D\";Bn.cursorLeft=$n+\"G\";Bn.cursorSavePosition=TEe?\"\\x1B7\":$n+\"s\";Bn.cursorRestorePosition=TEe?\"\\x1B8\":$n+\"u\";Bn.cursorGetPosition=$n+\"6n\";Bn.cursorNextLine=$n+\"E\";Bn.cursorPrevLine=$n+\"F\";Bn.cursorHide=$n+\"?25l\";Bn.cursorShow=$n+\"?25h\";Bn.eraseLines=e=>{let t=\"\";for(let r=0;r<e;r++)t+=Bn.eraseLine+(r<e-1?Bn.cursorUp():\"\");return e&&(t+=Bn.cursorLeft),t};Bn.eraseEndLine=$n+\"K\";Bn.eraseStartLine=$n+\"1K\";Bn.eraseLine=$n+\"2K\";Bn.eraseDown=$n+\"J\";Bn.eraseUp=$n+\"1J\";Bn.eraseScreen=$n+\"2J\";Bn.scrollUp=$n+\"S\";Bn.scrollDown=$n+\"T\";Bn.clearScreen=\"\\x1Bc\";Bn.clearTerminal=process.platform===\"win32\"?`${Bn.eraseScreen}${$n}0f`:`${Bn.eraseScreen}${$n}3J${$n}H`;Bn.beep=rw;Bn.link=(e,t)=>[NS,\"8\",iF,iF,t,rw,e,NS,\"8\",iF,iF,rw].join(\"\");Bn.image=(e,t={})=>{let r=`${NS}1337;File=inline=1`;return t.width&&(r+=`;width=${t.width}`),t.height&&(r+=`;height=${t.height}`),t.preserveAspectRatio===!1&&(r+=\";preserveAspectRatio=0\"),r+\":\"+e.toString(\"base64\")+rw};Bn.iTerm={setCwd:(e=process.cwd())=>`${NS}50;CurrentDir=${e}${rw}`,annotation:(e,t={})=>{let r=`${NS}1337;`,s=typeof t.x<\"u\",a=typeof t.y<\"u\";if((s||a)&&!(s&&a&&typeof t.length<\"u\"))throw new Error(\"`x`, `y` and `length` must be defined when `x` or `y` is defined\");return e=e.replace(/\\|/g,\"\"),r+=t.isHidden?\"AddHiddenAnnotation=\":\"AddAnnotation=\",t.length>0?r+=(s?[e,t.length,t.x,t.y]:[t.length,e]).join(\"|\"):r+=e,r+rw}}});var NEe=G((hYt,Yq)=>{\"use strict\";var FEe=(e,t)=>{for(let r of Reflect.ownKeys(t))Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));return e};Yq.exports=FEe;Yq.exports.default=FEe});var LEe=G((gYt,oF)=>{\"use strict\";var xut=NEe(),sF=new WeakMap,OEe=(e,t={})=>{if(typeof e!=\"function\")throw new TypeError(\"Expected a function\");let r,s=0,a=e.displayName||e.name||\"<anonymous>\",n=function(...c){if(sF.set(n,++s),s===1)r=e.apply(this,c),e=null;else if(t.throw===!0)throw new Error(`Function \\`${a}\\` can only be called once`);return r};return xut(n,e),sF.set(n,s),n};oF.exports=OEe;oF.exports.default=OEe;oF.exports.callCount=e=>{if(!sF.has(e))throw new Error(`The given function \\`${e.name}\\` is not wrapped by the \\`onetime\\` package`);return sF.get(e)}});var MEe=G((dYt,aF)=>{aF.exports=[\"SIGABRT\",\"SIGALRM\",\"SIGHUP\",\"SIGINT\",\"SIGTERM\"];process.platform!==\"win32\"&&aF.exports.push(\"SIGVTALRM\",\"SIGXCPU\",\"SIGXFSZ\",\"SIGUSR2\",\"SIGTRAP\",\"SIGSYS\",\"SIGQUIT\",\"SIGIOT\");process.platform===\"linux\"&&aF.exports.push(\"SIGIO\",\"SIGPOLL\",\"SIGPWR\",\"SIGSTKFLT\",\"SIGUNUSED\")});var zq=G((mYt,sw)=>{var Qi=global.process,Fm=function(e){return e&&typeof e==\"object\"&&typeof e.removeListener==\"function\"&&typeof e.emit==\"function\"&&typeof e.reallyExit==\"function\"&&typeof e.listeners==\"function\"&&typeof e.kill==\"function\"&&typeof e.pid==\"number\"&&typeof e.on==\"function\"};Fm(Qi)?(UEe=Ie(\"assert\"),nw=MEe(),_Ee=/^win/i.test(Qi.platform),OS=Ie(\"events\"),typeof OS!=\"function\"&&(OS=OS.EventEmitter),Qi.__signal_exit_emitter__?eo=Qi.__signal_exit_emitter__:(eo=Qi.__signal_exit_emitter__=new OS,eo.count=0,eo.emitted={}),eo.infinite||(eo.setMaxListeners(1/0),eo.infinite=!0),sw.exports=function(e,t){if(!Fm(global.process))return function(){};UEe.equal(typeof e,\"function\",\"a callback must be provided for exit handler\"),iw===!1&&Kq();var r=\"exit\";t&&t.alwaysLast&&(r=\"afterexit\");var s=function(){eo.removeListener(r,e),eo.listeners(\"exit\").length===0&&eo.listeners(\"afterexit\").length===0&&lF()};return eo.on(r,e),s},lF=function(){!iw||!Fm(global.process)||(iw=!1,nw.forEach(function(t){try{Qi.removeListener(t,cF[t])}catch{}}),Qi.emit=uF,Qi.reallyExit=Jq,eo.count-=1)},sw.exports.unload=lF,Nm=function(t,r,s){eo.emitted[t]||(eo.emitted[t]=!0,eo.emit(t,r,s))},cF={},nw.forEach(function(e){cF[e]=function(){if(Fm(global.process)){var r=Qi.listeners(e);r.length===eo.count&&(lF(),Nm(\"exit\",null,e),Nm(\"afterexit\",null,e),_Ee&&e===\"SIGHUP\"&&(e=\"SIGINT\"),Qi.kill(Qi.pid,e))}}}),sw.exports.signals=function(){return nw},iw=!1,Kq=function(){iw||!Fm(global.process)||(iw=!0,eo.count+=1,nw=nw.filter(function(t){try{return Qi.on(t,cF[t]),!0}catch{return!1}}),Qi.emit=jEe,Qi.reallyExit=HEe)},sw.exports.load=Kq,Jq=Qi.reallyExit,HEe=function(t){Fm(global.process)&&(Qi.exitCode=t||0,Nm(\"exit\",Qi.exitCode,null),Nm(\"afterexit\",Qi.exitCode,null),Jq.call(Qi,Qi.exitCode))},uF=Qi.emit,jEe=function(t,r){if(t===\"exit\"&&Fm(global.process)){r!==void 0&&(Qi.exitCode=r);var s=uF.apply(this,arguments);return Nm(\"exit\",Qi.exitCode,null),Nm(\"afterexit\",Qi.exitCode,null),s}else return uF.apply(this,arguments)}):sw.exports=function(){return function(){}};var UEe,nw,_Ee,OS,eo,lF,Nm,cF,iw,Kq,Jq,HEe,uF,jEe});var qEe=G((yYt,GEe)=>{\"use strict\";var kut=LEe(),Qut=zq();GEe.exports=kut(()=>{Qut(()=>{process.stderr.write(\"\\x1B[?25h\")},{alwaysLast:!0})})});var Zq=G(ow=>{\"use strict\";var Rut=qEe(),fF=!1;ow.show=(e=process.stderr)=>{e.isTTY&&(fF=!1,e.write(\"\\x1B[?25h\"))};ow.hide=(e=process.stderr)=>{e.isTTY&&(Rut(),fF=!0,e.write(\"\\x1B[?25l\"))};ow.toggle=(e,t)=>{e!==void 0&&(fF=e),fF?ow.show(t):ow.hide(t)}});var KEe=G(LS=>{\"use strict\";var YEe=LS&&LS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(LS,\"__esModule\",{value:!0});var WEe=YEe(Vq()),VEe=YEe(Zq()),Tut=(e,{showCursor:t=!1}={})=>{let r=0,s=\"\",a=!1,n=c=>{!t&&!a&&(VEe.default.hide(),a=!0);let f=c+`\n`;f!==s&&(s=f,e.write(WEe.default.eraseLines(r)+f),r=f.split(`\n`).length)};return n.clear=()=>{e.write(WEe.default.eraseLines(r)),s=\"\",r=0},n.done=()=>{s=\"\",r=0,t||(VEe.default.show(),a=!1)},n};LS.default={create:Tut}});var JEe=G((CYt,Fut)=>{Fut.exports=[{name:\"AppVeyor\",constant:\"APPVEYOR\",env:\"APPVEYOR\",pr:\"APPVEYOR_PULL_REQUEST_NUMBER\"},{name:\"Azure Pipelines\",constant:\"AZURE_PIPELINES\",env:\"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI\",pr:\"SYSTEM_PULLREQUEST_PULLREQUESTID\"},{name:\"Bamboo\",constant:\"BAMBOO\",env:\"bamboo_planKey\"},{name:\"Bitbucket Pipelines\",constant:\"BITBUCKET\",env:\"BITBUCKET_COMMIT\",pr:\"BITBUCKET_PR_ID\"},{name:\"Bitrise\",constant:\"BITRISE\",env:\"BITRISE_IO\",pr:\"BITRISE_PULL_REQUEST\"},{name:\"Buddy\",constant:\"BUDDY\",env:\"BUDDY_WORKSPACE_ID\",pr:\"BUDDY_EXECUTION_PULL_REQUEST_ID\"},{name:\"Buildkite\",constant:\"BUILDKITE\",env:\"BUILDKITE\",pr:{env:\"BUILDKITE_PULL_REQUEST\",ne:\"false\"}},{name:\"CircleCI\",constant:\"CIRCLE\",env:\"CIRCLECI\",pr:\"CIRCLE_PULL_REQUEST\"},{name:\"Cirrus CI\",constant:\"CIRRUS\",env:\"CIRRUS_CI\",pr:\"CIRRUS_PR\"},{name:\"AWS CodeBuild\",constant:\"CODEBUILD\",env:\"CODEBUILD_BUILD_ARN\"},{name:\"Codeship\",constant:\"CODESHIP\",env:{CI_NAME:\"codeship\"}},{name:\"Drone\",constant:\"DRONE\",env:\"DRONE\",pr:{DRONE_BUILD_EVENT:\"pull_request\"}},{name:\"dsari\",constant:\"DSARI\",env:\"DSARI\"},{name:\"GitLab CI\",constant:\"GITLAB\",env:\"GITLAB_CI\"},{name:\"GoCD\",constant:\"GOCD\",env:\"GO_PIPELINE_LABEL\"},{name:\"Hudson\",constant:\"HUDSON\",env:\"HUDSON_URL\"},{name:\"Jenkins\",constant:\"JENKINS\",env:[\"JENKINS_URL\",\"BUILD_ID\"],pr:{any:[\"ghprbPullId\",\"CHANGE_ID\"]}},{name:\"Magnum CI\",constant:\"MAGNUM\",env:\"MAGNUM\"},{name:\"Netlify CI\",constant:\"NETLIFY\",env:\"NETLIFY_BUILD_BASE\",pr:{env:\"PULL_REQUEST\",ne:\"false\"}},{name:\"Sail CI\",constant:\"SAIL\",env:\"SAILCI\",pr:\"SAIL_PULL_REQUEST_NUMBER\"},{name:\"Semaphore\",constant:\"SEMAPHORE\",env:\"SEMAPHORE\",pr:\"PULL_REQUEST_NUMBER\"},{name:\"Shippable\",constant:\"SHIPPABLE\",env:\"SHIPPABLE\",pr:{IS_PULL_REQUEST:\"true\"}},{name:\"Solano CI\",constant:\"SOLANO\",env:\"TDDIUM\",pr:\"TDDIUM_PR_ID\"},{name:\"Strider CD\",constant:\"STRIDER\",env:\"STRIDER\"},{name:\"TaskCluster\",constant:\"TASKCLUSTER\",env:[\"TASK_ID\",\"RUN_ID\"]},{name:\"TeamCity\",constant:\"TEAMCITY\",env:\"TEAMCITY_VERSION\"},{name:\"Travis CI\",constant:\"TRAVIS\",env:\"TRAVIS\",pr:{env:\"TRAVIS_PULL_REQUEST\",ne:\"false\"}}]});var XEe=G(rc=>{\"use strict\";var ZEe=JEe(),fA=process.env;Object.defineProperty(rc,\"_vendors\",{value:ZEe.map(function(e){return e.constant})});rc.name=null;rc.isPR=null;ZEe.forEach(function(e){var t=Array.isArray(e.env)?e.env:[e.env],r=t.every(function(s){return zEe(s)});if(rc[e.constant]=r,r)switch(rc.name=e.name,typeof e.pr){case\"string\":rc.isPR=!!fA[e.pr];break;case\"object\":\"env\"in e.pr?rc.isPR=e.pr.env in fA&&fA[e.pr.env]!==e.pr.ne:\"any\"in e.pr?rc.isPR=e.pr.any.some(function(s){return!!fA[s]}):rc.isPR=zEe(e.pr);break;default:rc.isPR=null}});rc.isCI=!!(fA.CI||fA.CONTINUOUS_INTEGRATION||fA.BUILD_NUMBER||fA.RUN_ID||rc.name);function zEe(e){return typeof e==\"string\"?!!fA[e]:Object.keys(e).every(function(t){return fA[t]===e[t]})}});var eIe=G((BYt,$Ee)=>{\"use strict\";$Ee.exports=XEe().isCI});var rIe=G((vYt,tIe)=>{\"use strict\";var Nut=e=>{let t=new Set;do for(let r of Reflect.ownKeys(e))t.add([e,r]);while((e=Reflect.getPrototypeOf(e))&&e!==Object.prototype);return t};tIe.exports=(e,{include:t,exclude:r}={})=>{let s=a=>{let n=c=>typeof c==\"string\"?a===c:c.test(a);return t?t.some(n):r?!r.some(n):!0};for(let[a,n]of Nut(e.constructor.prototype)){if(n===\"constructor\"||!s(n))continue;let c=Reflect.getOwnPropertyDescriptor(a,n);c&&typeof c.value==\"function\"&&(e[n]=e[n].bind(e))}return e}});var lIe=G(Jn=>{\"use strict\";var lw,_S,gF,i9;typeof performance==\"object\"&&typeof performance.now==\"function\"?(nIe=performance,Jn.unstable_now=function(){return nIe.now()}):(Xq=Date,iIe=Xq.now(),Jn.unstable_now=function(){return Xq.now()-iIe});var nIe,Xq,iIe;typeof window>\"u\"||typeof MessageChannel!=\"function\"?(aw=null,$q=null,e9=function(){if(aw!==null)try{var e=Jn.unstable_now();aw(!0,e),aw=null}catch(t){throw setTimeout(e9,0),t}},lw=function(e){aw!==null?setTimeout(lw,0,e):(aw=e,setTimeout(e9,0))},_S=function(e,t){$q=setTimeout(e,t)},gF=function(){clearTimeout($q)},Jn.unstable_shouldYield=function(){return!1},i9=Jn.unstable_forceFrameRate=function(){}):(sIe=window.setTimeout,oIe=window.clearTimeout,typeof console<\"u\"&&(aIe=window.cancelAnimationFrame,typeof window.requestAnimationFrame!=\"function\"&&console.error(\"This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills\"),typeof aIe!=\"function\"&&console.error(\"This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills\")),MS=!1,US=null,AF=-1,t9=5,r9=0,Jn.unstable_shouldYield=function(){return Jn.unstable_now()>=r9},i9=function(){},Jn.unstable_forceFrameRate=function(e){0>e||125<e?console.error(\"forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported\"):t9=0<e?Math.floor(1e3/e):5},n9=new MessageChannel,pF=n9.port2,n9.port1.onmessage=function(){if(US!==null){var e=Jn.unstable_now();r9=e+t9;try{US(!0,e)?pF.postMessage(null):(MS=!1,US=null)}catch(t){throw pF.postMessage(null),t}}else MS=!1},lw=function(e){US=e,MS||(MS=!0,pF.postMessage(null))},_S=function(e,t){AF=sIe(function(){e(Jn.unstable_now())},t)},gF=function(){oIe(AF),AF=-1});var aw,$q,e9,sIe,oIe,aIe,MS,US,AF,t9,r9,n9,pF;function s9(e,t){var r=e.length;e.push(t);e:for(;;){var s=r-1>>>1,a=e[s];if(a!==void 0&&0<hF(a,t))e[s]=t,e[r]=a,r=s;else break e}}function rf(e){return e=e[0],e===void 0?null:e}function dF(e){var t=e[0];if(t!==void 0){var r=e.pop();if(r!==t){e[0]=r;e:for(var s=0,a=e.length;s<a;){var n=2*(s+1)-1,c=e[n],f=n+1,p=e[f];if(c!==void 0&&0>hF(c,r))p!==void 0&&0>hF(p,c)?(e[s]=p,e[f]=r,s=f):(e[s]=c,e[n]=r,s=n);else if(p!==void 0&&0>hF(p,r))e[s]=p,e[f]=r,s=f;else break e}}return t}return null}function hF(e,t){var r=e.sortIndex-t.sortIndex;return r!==0?r:e.id-t.id}var AA=[],z0=[],Out=1,jc=null,na=3,mF=!1,Om=!1,HS=!1;function o9(e){for(var t=rf(z0);t!==null;){if(t.callback===null)dF(z0);else if(t.startTime<=e)dF(z0),t.sortIndex=t.expirationTime,s9(AA,t);else break;t=rf(z0)}}function a9(e){if(HS=!1,o9(e),!Om)if(rf(AA)!==null)Om=!0,lw(l9);else{var t=rf(z0);t!==null&&_S(a9,t.startTime-e)}}function l9(e,t){Om=!1,HS&&(HS=!1,gF()),mF=!0;var r=na;try{for(o9(t),jc=rf(AA);jc!==null&&(!(jc.expirationTime>t)||e&&!Jn.unstable_shouldYield());){var s=jc.callback;if(typeof s==\"function\"){jc.callback=null,na=jc.priorityLevel;var a=s(jc.expirationTime<=t);t=Jn.unstable_now(),typeof a==\"function\"?jc.callback=a:jc===rf(AA)&&dF(AA),o9(t)}else dF(AA);jc=rf(AA)}if(jc!==null)var n=!0;else{var c=rf(z0);c!==null&&_S(a9,c.startTime-t),n=!1}return n}finally{jc=null,na=r,mF=!1}}var Lut=i9;Jn.unstable_IdlePriority=5;Jn.unstable_ImmediatePriority=1;Jn.unstable_LowPriority=4;Jn.unstable_NormalPriority=3;Jn.unstable_Profiling=null;Jn.unstable_UserBlockingPriority=2;Jn.unstable_cancelCallback=function(e){e.callback=null};Jn.unstable_continueExecution=function(){Om||mF||(Om=!0,lw(l9))};Jn.unstable_getCurrentPriorityLevel=function(){return na};Jn.unstable_getFirstCallbackNode=function(){return rf(AA)};Jn.unstable_next=function(e){switch(na){case 1:case 2:case 3:var t=3;break;default:t=na}var r=na;na=t;try{return e()}finally{na=r}};Jn.unstable_pauseExecution=function(){};Jn.unstable_requestPaint=Lut;Jn.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var r=na;na=e;try{return t()}finally{na=r}};Jn.unstable_scheduleCallback=function(e,t,r){var s=Jn.unstable_now();switch(typeof r==\"object\"&&r!==null?(r=r.delay,r=typeof r==\"number\"&&0<r?s+r:s):r=s,e){case 1:var a=-1;break;case 2:a=250;break;case 5:a=1073741823;break;case 4:a=1e4;break;default:a=5e3}return a=r+a,e={id:Out++,callback:t,priorityLevel:e,startTime:r,expirationTime:a,sortIndex:-1},r>s?(e.sortIndex=r,s9(z0,e),rf(AA)===null&&e===rf(z0)&&(HS?gF():HS=!0,_S(a9,r-s))):(e.sortIndex=a,s9(AA,e),Om||mF||(Om=!0,lw(l9))),e};Jn.unstable_wrapCallback=function(e){var t=na;return function(){var r=na;na=t;try{return e.apply(this,arguments)}finally{na=r}}}});var c9=G((DYt,cIe)=>{\"use strict\";cIe.exports=lIe()});var uIe=G((bYt,jS)=>{jS.exports=function(t){var r={},s=Nq(),a=gn(),n=c9();function c(v){for(var D=\"https://reactjs.org/docs/error-decoder.html?invariant=\"+v,Q=1;Q<arguments.length;Q++)D+=\"&args[]=\"+encodeURIComponent(arguments[Q]);return\"Minified React error #\"+v+\"; visit \"+D+\" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"}var f=a.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,p=60103,h=60106,E=60107,C=60108,S=60114,x=60109,I=60110,T=60112,O=60113,U=60120,Y=60115,te=60116,ie=60121,ue=60129,ae=60130,de=60131;if(typeof Symbol==\"function\"&&Symbol.for){var Ae=Symbol.for;p=Ae(\"react.element\"),h=Ae(\"react.portal\"),E=Ae(\"react.fragment\"),C=Ae(\"react.strict_mode\"),S=Ae(\"react.profiler\"),x=Ae(\"react.provider\"),I=Ae(\"react.context\"),T=Ae(\"react.forward_ref\"),O=Ae(\"react.suspense\"),U=Ae(\"react.suspense_list\"),Y=Ae(\"react.memo\"),te=Ae(\"react.lazy\"),ie=Ae(\"react.block\"),Ae(\"react.scope\"),ue=Ae(\"react.debug_trace_mode\"),ae=Ae(\"react.offscreen\"),de=Ae(\"react.legacy_hidden\")}var Ce=typeof Symbol==\"function\"&&Symbol.iterator;function Ee(v){return v===null||typeof v!=\"object\"?null:(v=Ce&&v[Ce]||v[\"@@iterator\"],typeof v==\"function\"?v:null)}function g(v){if(v==null)return null;if(typeof v==\"function\")return v.displayName||v.name||null;if(typeof v==\"string\")return v;switch(v){case E:return\"Fragment\";case h:return\"Portal\";case S:return\"Profiler\";case C:return\"StrictMode\";case O:return\"Suspense\";case U:return\"SuspenseList\"}if(typeof v==\"object\")switch(v.$$typeof){case I:return(v.displayName||\"Context\")+\".Consumer\";case x:return(v._context.displayName||\"Context\")+\".Provider\";case T:var D=v.render;return D=D.displayName||D.name||\"\",v.displayName||(D!==\"\"?\"ForwardRef(\"+D+\")\":\"ForwardRef\");case Y:return g(v.type);case ie:return g(v._render);case te:D=v._payload,v=v._init;try{return g(v(D))}catch{}}return null}function Se(v){var D=v,Q=v;if(v.alternate)for(;D.return;)D=D.return;else{v=D;do D=v,D.flags&1026&&(Q=D.return),v=D.return;while(v)}return D.tag===3?Q:null}function Be(v){if(Se(v)!==v)throw Error(c(188))}function me(v){var D=v.alternate;if(!D){if(D=Se(v),D===null)throw Error(c(188));return D!==v?null:v}for(var Q=v,H=D;;){var V=Q.return;if(V===null)break;var ne=V.alternate;if(ne===null){if(H=V.return,H!==null){Q=H;continue}break}if(V.child===ne.child){for(ne=V.child;ne;){if(ne===Q)return Be(V),v;if(ne===H)return Be(V),D;ne=ne.sibling}throw Error(c(188))}if(Q.return!==H.return)Q=V,H=ne;else{for(var ve=!1,_e=V.child;_e;){if(_e===Q){ve=!0,Q=V,H=ne;break}if(_e===H){ve=!0,H=V,Q=ne;break}_e=_e.sibling}if(!ve){for(_e=ne.child;_e;){if(_e===Q){ve=!0,Q=ne,H=V;break}if(_e===H){ve=!0,H=ne,Q=V;break}_e=_e.sibling}if(!ve)throw Error(c(189))}}if(Q.alternate!==H)throw Error(c(190))}if(Q.tag!==3)throw Error(c(188));return Q.stateNode.current===Q?v:D}function ce(v){if(v=me(v),!v)return null;for(var D=v;;){if(D.tag===5||D.tag===6)return D;if(D.child)D.child.return=D,D=D.child;else{if(D===v)break;for(;!D.sibling;){if(!D.return||D.return===v)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}}return null}function X(v){if(v=me(v),!v)return null;for(var D=v;;){if(D.tag===5||D.tag===6)return D;if(D.child&&D.tag!==4)D.child.return=D,D=D.child;else{if(D===v)break;for(;!D.sibling;){if(!D.return||D.return===v)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}}return null}function De(v,D){for(var Q=v.alternate;D!==null;){if(D===v||D===Q)return!0;D=D.return}return!1}var Qe=t.getPublicInstance,it=t.getRootHostContext,_=t.getChildHostContext,tt=t.prepareForCommit,Ne=t.resetAfterCommit,ke=t.createInstance,be=t.appendInitialChild,je=t.finalizeInitialChildren,Re=t.prepareUpdate,ct=t.shouldSetTextContent,Me=t.createTextInstance,P=t.scheduleTimeout,w=t.cancelTimeout,b=t.noTimeout,y=t.isPrimaryRenderer,F=t.supportsMutation,z=t.supportsPersistence,Z=t.supportsHydration,$=t.getInstanceFromNode,se=t.makeOpaqueHydratingObject,xe=t.makeClientId,Fe=t.beforeActiveInstanceBlur,ut=t.afterActiveInstanceBlur,Ct=t.preparePortalMount,qt=t.supportsTestSelectors,ir=t.findFiberRoot,Pt=t.getBoundingRect,dn=t.getTextContent,Pr=t.isHiddenSubtree,Ir=t.matchAccessibilityRole,Or=t.setFocusIfFocusable,on=t.setupIntersectionObserver,li=t.appendChild,So=t.appendChildToContainer,ns=t.commitTextUpdate,so=t.commitMount,Do=t.commitUpdate,ji=t.insertBefore,oo=t.insertInContainerBefore,bo=t.removeChild,RA=t.removeChildFromContainer,hf=t.resetTextContent,hh=t.hideInstance,gh=t.hideTextInstance,ao=t.unhideInstance,Gn=t.unhideTextInstance,Ns=t.clearContainer,lo=t.cloneInstance,iu=t.createContainerChildSet,su=t.appendChildToContainerChildSet,ou=t.finalizeContainerChildren,TA=t.replaceContainerChildren,FA=t.cloneHiddenInstance,ua=t.cloneHiddenTextInstance,fa=t.canHydrateInstance,NA=t.canHydrateTextInstance,gr=t.isSuspenseInstancePending,Po=t.isSuspenseInstanceFallback,Ue=t.getNextHydratableSibling,au=t.getFirstHydratableChild,Cr=t.hydrateInstance,gf=t.hydrateTextInstance,OA=t.getNextHydratableInstanceAfterSuspenseInstance,LA=t.commitHydratedContainer,lu=t.commitHydratedSuspenseInstance,cu;function ac(v){if(cu===void 0)try{throw Error()}catch(Q){var D=Q.stack.trim().match(/\\n( *(at )?)/);cu=D&&D[1]||\"\"}return`\n`+cu+v}var we=!1;function Nt(v,D){if(!v||we)return\"\";we=!0;var Q=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(D)if(D=function(){throw Error()},Object.defineProperty(D.prototype,\"props\",{set:function(){throw Error()}}),typeof Reflect==\"object\"&&Reflect.construct){try{Reflect.construct(D,[])}catch(ht){var H=ht}Reflect.construct(v,[],D)}else{try{D.call()}catch(ht){H=ht}v.call(D.prototype)}else{try{throw Error()}catch(ht){H=ht}v()}}catch(ht){if(ht&&H&&typeof ht.stack==\"string\"){for(var V=ht.stack.split(`\n`),ne=H.stack.split(`\n`),ve=V.length-1,_e=ne.length-1;1<=ve&&0<=_e&&V[ve]!==ne[_e];)_e--;for(;1<=ve&&0<=_e;ve--,_e--)if(V[ve]!==ne[_e]){if(ve!==1||_e!==1)do if(ve--,_e--,0>_e||V[ve]!==ne[_e])return`\n`+V[ve].replace(\" at new \",\" at \");while(1<=ve&&0<=_e);break}}}finally{we=!1,Error.prepareStackTrace=Q}return(v=v?v.displayName||v.name:\"\")?ac(v):\"\"}var lc=[],Oi=-1;function co(v){return{current:v}}function Tt(v){0>Oi||(v.current=lc[Oi],lc[Oi]=null,Oi--)}function Qn(v,D){Oi++,lc[Oi]=v.current,v.current=D}var Aa={},Gi=co(Aa),Li=co(!1),ja=Aa;function mn(v,D){var Q=v.type.contextTypes;if(!Q)return Aa;var H=v.stateNode;if(H&&H.__reactInternalMemoizedUnmaskedChildContext===D)return H.__reactInternalMemoizedMaskedChildContext;var V={},ne;for(ne in Q)V[ne]=D[ne];return H&&(v=v.stateNode,v.__reactInternalMemoizedUnmaskedChildContext=D,v.__reactInternalMemoizedMaskedChildContext=V),V}function Zn(v){return v=v.childContextTypes,v!=null}function uu(){Tt(Li),Tt(Gi)}function dh(v,D,Q){if(Gi.current!==Aa)throw Error(c(168));Qn(Gi,D),Qn(Li,Q)}function Ga(v,D,Q){var H=v.stateNode;if(v=D.childContextTypes,typeof H.getChildContext!=\"function\")return Q;H=H.getChildContext();for(var V in H)if(!(V in v))throw Error(c(108,g(D)||\"Unknown\",V));return s({},Q,H)}function qa(v){return v=(v=v.stateNode)&&v.__reactInternalMemoizedMergedChildContext||Aa,ja=Gi.current,Qn(Gi,v),Qn(Li,Li.current),!0}function Wa(v,D,Q){var H=v.stateNode;if(!H)throw Error(c(169));Q?(v=Ga(v,D,ja),H.__reactInternalMemoizedMergedChildContext=v,Tt(Li),Tt(Gi),Qn(Gi,v)):Tt(Li),Qn(Li,Q)}var $e=null,Va=null,df=n.unstable_now;df();var cc=0,vn=8;function pa(v){if(1&v)return vn=15,1;if(2&v)return vn=14,2;if(4&v)return vn=13,4;var D=24&v;return D!==0?(vn=12,D):v&32?(vn=11,32):(D=192&v,D!==0?(vn=10,D):v&256?(vn=9,256):(D=3584&v,D!==0?(vn=8,D):v&4096?(vn=7,4096):(D=4186112&v,D!==0?(vn=6,D):(D=62914560&v,D!==0?(vn=5,D):v&67108864?(vn=4,67108864):v&134217728?(vn=3,134217728):(D=805306368&v,D!==0?(vn=2,D):1073741824&v?(vn=1,1073741824):(vn=8,v))))))}function MA(v){switch(v){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}function UA(v){switch(v){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(c(358,v))}}function ha(v,D){var Q=v.pendingLanes;if(Q===0)return vn=0;var H=0,V=0,ne=v.expiredLanes,ve=v.suspendedLanes,_e=v.pingedLanes;if(ne!==0)H=ne,V=vn=15;else if(ne=Q&134217727,ne!==0){var ht=ne&~ve;ht!==0?(H=pa(ht),V=vn):(_e&=ne,_e!==0&&(H=pa(_e),V=vn))}else ne=Q&~ve,ne!==0?(H=pa(ne),V=vn):_e!==0&&(H=pa(_e),V=vn);if(H===0)return 0;if(H=31-is(H),H=Q&((0>H?0:1<<H)<<1)-1,D!==0&&D!==H&&!(D&ve)){if(pa(D),V<=vn)return D;vn=V}if(D=v.entangledLanes,D!==0)for(v=v.entanglements,D&=H;0<D;)Q=31-is(D),V=1<<Q,H|=v[Q],D&=~V;return H}function xl(v){return v=v.pendingLanes&-1073741825,v!==0?v:v&1073741824?1073741824:0}function Mt(v,D){switch(v){case 15:return 1;case 14:return 2;case 12:return v=Rn(24&~D),v===0?Mt(10,D):v;case 10:return v=Rn(192&~D),v===0?Mt(8,D):v;case 8:return v=Rn(3584&~D),v===0&&(v=Rn(4186112&~D),v===0&&(v=512)),v;case 2:return D=Rn(805306368&~D),D===0&&(D=268435456),D}throw Error(c(358,v))}function Rn(v){return v&-v}function ga(v){for(var D=[],Q=0;31>Q;Q++)D.push(v);return D}function Ya(v,D,Q){v.pendingLanes|=D;var H=D-1;v.suspendedLanes&=H,v.pingedLanes&=H,v=v.eventTimes,D=31-is(D),v[D]=Q}var is=Math.clz32?Math.clz32:fc,uc=Math.log,fu=Math.LN2;function fc(v){return v===0?32:31-(uc(v)/fu|0)|0}var Ka=n.unstable_runWithPriority,Mi=n.unstable_scheduleCallback,Bs=n.unstable_cancelCallback,kl=n.unstable_shouldYield,mf=n.unstable_requestPaint,Ac=n.unstable_now,Bi=n.unstable_getCurrentPriorityLevel,Tn=n.unstable_ImmediatePriority,pc=n.unstable_UserBlockingPriority,Je=n.unstable_NormalPriority,ot=n.unstable_LowPriority,St=n.unstable_IdlePriority,lr={},ee=mf!==void 0?mf:function(){},ye=null,Oe=null,mt=!1,Et=Ac(),bt=1e4>Et?Ac:function(){return Ac()-Et};function tr(){switch(Bi()){case Tn:return 99;case pc:return 98;case Je:return 97;case ot:return 96;case St:return 95;default:throw Error(c(332))}}function pn(v){switch(v){case 99:return Tn;case 98:return pc;case 97:return Je;case 96:return ot;case 95:return St;default:throw Error(c(332))}}function ci(v,D){return v=pn(v),Ka(v,D)}function qi(v,D,Q){return v=pn(v),Mi(v,D,Q)}function Fn(){if(Oe!==null){var v=Oe;Oe=null,Bs(v)}Ja()}function Ja(){if(!mt&&ye!==null){mt=!0;var v=0;try{var D=ye;ci(99,function(){for(;v<D.length;v++){var Q=D[v];do Q=Q(!0);while(Q!==null)}}),ye=null}catch(Q){throw ye!==null&&(ye=ye.slice(v+1)),Mi(Tn,Fn),Q}finally{mt=!1}}}var Iy=f.ReactCurrentBatchConfig;function q1(v,D){return v===D&&(v!==0||1/v===1/D)||v!==v&&D!==D}var xo=typeof Object.is==\"function\"?Object.is:q1,Cy=Object.prototype.hasOwnProperty;function mh(v,D){if(xo(v,D))return!0;if(typeof v!=\"object\"||v===null||typeof D!=\"object\"||D===null)return!1;var Q=Object.keys(v),H=Object.keys(D);if(Q.length!==H.length)return!1;for(H=0;H<Q.length;H++)if(!Cy.call(D,Q[H])||!xo(v[Q[H]],D[Q[H]]))return!1;return!0}function W1(v){switch(v.tag){case 5:return ac(v.type);case 16:return ac(\"Lazy\");case 13:return ac(\"Suspense\");case 19:return ac(\"SuspenseList\");case 0:case 2:case 15:return v=Nt(v.type,!1),v;case 11:return v=Nt(v.type.render,!1),v;case 22:return v=Nt(v.type._render,!1),v;case 1:return v=Nt(v.type,!0),v;default:return\"\"}}function ko(v,D){if(v&&v.defaultProps){D=s({},D),v=v.defaultProps;for(var Q in v)D[Q]===void 0&&(D[Q]=v[Q]);return D}return D}var yh=co(null),Eh=null,Au=null,Ih=null;function Rg(){Ih=Au=Eh=null}function Tg(v,D){v=v.type._context,y?(Qn(yh,v._currentValue),v._currentValue=D):(Qn(yh,v._currentValue2),v._currentValue2=D)}function Fg(v){var D=yh.current;Tt(yh),v=v.type._context,y?v._currentValue=D:v._currentValue2=D}function wy(v,D){for(;v!==null;){var Q=v.alternate;if((v.childLanes&D)===D){if(Q===null||(Q.childLanes&D)===D)break;Q.childLanes|=D}else v.childLanes|=D,Q!==null&&(Q.childLanes|=D);v=v.return}}function yf(v,D){Eh=v,Ih=Au=null,v=v.dependencies,v!==null&&v.firstContext!==null&&(v.lanes&D&&(Ke=!0),v.firstContext=null)}function Qo(v,D){if(Ih!==v&&D!==!1&&D!==0)if((typeof D!=\"number\"||D===1073741823)&&(Ih=v,D=1073741823),D={context:v,observedBits:D,next:null},Au===null){if(Eh===null)throw Error(c(308));Au=D,Eh.dependencies={lanes:0,firstContext:D,responders:null}}else Au=Au.next=D;return y?v._currentValue:v._currentValue2}var Ql=!1;function Ch(v){v.updateQueue={baseState:v.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null},effects:null}}function Ng(v,D){v=v.updateQueue,D.updateQueue===v&&(D.updateQueue={baseState:v.baseState,firstBaseUpdate:v.firstBaseUpdate,lastBaseUpdate:v.lastBaseUpdate,shared:v.shared,effects:v.effects})}function Rl(v,D){return{eventTime:v,lane:D,tag:0,payload:null,callback:null,next:null}}function Tl(v,D){if(v=v.updateQueue,v!==null){v=v.shared;var Q=v.pending;Q===null?D.next=D:(D.next=Q.next,Q.next=D),v.pending=D}}function By(v,D){var Q=v.updateQueue,H=v.alternate;if(H!==null&&(H=H.updateQueue,Q===H)){var V=null,ne=null;if(Q=Q.firstBaseUpdate,Q!==null){do{var ve={eventTime:Q.eventTime,lane:Q.lane,tag:Q.tag,payload:Q.payload,callback:Q.callback,next:null};ne===null?V=ne=ve:ne=ne.next=ve,Q=Q.next}while(Q!==null);ne===null?V=ne=D:ne=ne.next=D}else V=ne=D;Q={baseState:H.baseState,firstBaseUpdate:V,lastBaseUpdate:ne,shared:H.shared,effects:H.effects},v.updateQueue=Q;return}v=Q.lastBaseUpdate,v===null?Q.firstBaseUpdate=D:v.next=D,Q.lastBaseUpdate=D}function _A(v,D,Q,H){var V=v.updateQueue;Ql=!1;var ne=V.firstBaseUpdate,ve=V.lastBaseUpdate,_e=V.shared.pending;if(_e!==null){V.shared.pending=null;var ht=_e,Wt=ht.next;ht.next=null,ve===null?ne=Wt:ve.next=Wt,ve=ht;var Sr=v.alternate;if(Sr!==null){Sr=Sr.updateQueue;var Lr=Sr.lastBaseUpdate;Lr!==ve&&(Lr===null?Sr.firstBaseUpdate=Wt:Lr.next=Wt,Sr.lastBaseUpdate=ht)}}if(ne!==null){Lr=V.baseState,ve=0,Sr=Wt=ht=null;do{_e=ne.lane;var Xt=ne.eventTime;if((H&_e)===_e){Sr!==null&&(Sr=Sr.next={eventTime:Xt,lane:0,tag:ne.tag,payload:ne.payload,callback:ne.callback,next:null});e:{var Xn=v,Ei=ne;switch(_e=D,Xt=Q,Ei.tag){case 1:if(Xn=Ei.payload,typeof Xn==\"function\"){Lr=Xn.call(Xt,Lr,_e);break e}Lr=Xn;break e;case 3:Xn.flags=Xn.flags&-4097|64;case 0:if(Xn=Ei.payload,_e=typeof Xn==\"function\"?Xn.call(Xt,Lr,_e):Xn,_e==null)break e;Lr=s({},Lr,_e);break e;case 2:Ql=!0}}ne.callback!==null&&(v.flags|=32,_e=V.effects,_e===null?V.effects=[ne]:_e.push(ne))}else Xt={eventTime:Xt,lane:_e,tag:ne.tag,payload:ne.payload,callback:ne.callback,next:null},Sr===null?(Wt=Sr=Xt,ht=Lr):Sr=Sr.next=Xt,ve|=_e;if(ne=ne.next,ne===null){if(_e=V.shared.pending,_e===null)break;ne=_e.next,_e.next=null,V.lastBaseUpdate=_e,V.shared.pending=null}}while(!0);Sr===null&&(ht=Lr),V.baseState=ht,V.firstBaseUpdate=Wt,V.lastBaseUpdate=Sr,zg|=ve,v.lanes=ve,v.memoizedState=Lr}}function vy(v,D,Q){if(v=D.effects,D.effects=null,v!==null)for(D=0;D<v.length;D++){var H=v[D],V=H.callback;if(V!==null){if(H.callback=null,H=Q,typeof V!=\"function\")throw Error(c(191,V));V.call(H)}}}var Sy=new a.Component().refs;function HA(v,D,Q,H){D=v.memoizedState,Q=Q(H,D),Q=Q==null?D:s({},D,Q),v.memoizedState=Q,v.lanes===0&&(v.updateQueue.baseState=Q)}var jA={isMounted:function(v){return(v=v._reactInternals)?Se(v)===v:!1},enqueueSetState:function(v,D,Q){v=v._reactInternals;var H=No(),V=Ds(v),ne=Rl(H,V);ne.payload=D,Q!=null&&(ne.callback=Q),Tl(v,ne),Ml(v,V,H)},enqueueReplaceState:function(v,D,Q){v=v._reactInternals;var H=No(),V=Ds(v),ne=Rl(H,V);ne.tag=1,ne.payload=D,Q!=null&&(ne.callback=Q),Tl(v,ne),Ml(v,V,H)},enqueueForceUpdate:function(v,D){v=v._reactInternals;var Q=No(),H=Ds(v),V=Rl(Q,H);V.tag=2,D!=null&&(V.callback=D),Tl(v,V),Ml(v,H,Q)}};function W(v,D,Q,H,V,ne,ve){return v=v.stateNode,typeof v.shouldComponentUpdate==\"function\"?v.shouldComponentUpdate(H,ne,ve):D.prototype&&D.prototype.isPureReactComponent?!mh(Q,H)||!mh(V,ne):!0}function xt(v,D,Q){var H=!1,V=Aa,ne=D.contextType;return typeof ne==\"object\"&&ne!==null?ne=Qo(ne):(V=Zn(D)?ja:Gi.current,H=D.contextTypes,ne=(H=H!=null)?mn(v,V):Aa),D=new D(Q,ne),v.memoizedState=D.state!==null&&D.state!==void 0?D.state:null,D.updater=jA,v.stateNode=D,D._reactInternals=v,H&&(v=v.stateNode,v.__reactInternalMemoizedUnmaskedChildContext=V,v.__reactInternalMemoizedMaskedChildContext=ne),D}function GA(v,D,Q,H){v=D.state,typeof D.componentWillReceiveProps==\"function\"&&D.componentWillReceiveProps(Q,H),typeof D.UNSAFE_componentWillReceiveProps==\"function\"&&D.UNSAFE_componentWillReceiveProps(Q,H),D.state!==v&&jA.enqueueReplaceState(D,D.state,null)}function Ro(v,D,Q,H){var V=v.stateNode;V.props=Q,V.state=v.memoizedState,V.refs=Sy,Ch(v);var ne=D.contextType;typeof ne==\"object\"&&ne!==null?V.context=Qo(ne):(ne=Zn(D)?ja:Gi.current,V.context=mn(v,ne)),_A(v,Q,V,H),V.state=v.memoizedState,ne=D.getDerivedStateFromProps,typeof ne==\"function\"&&(HA(v,D,ne,Q),V.state=v.memoizedState),typeof D.getDerivedStateFromProps==\"function\"||typeof V.getSnapshotBeforeUpdate==\"function\"||typeof V.UNSAFE_componentWillMount!=\"function\"&&typeof V.componentWillMount!=\"function\"||(D=V.state,typeof V.componentWillMount==\"function\"&&V.componentWillMount(),typeof V.UNSAFE_componentWillMount==\"function\"&&V.UNSAFE_componentWillMount(),D!==V.state&&jA.enqueueReplaceState(V,V.state,null),_A(v,Q,V,H),V.state=v.memoizedState),typeof V.componentDidMount==\"function\"&&(v.flags|=4)}var Ef=Array.isArray;function yt(v,D,Q){if(v=Q.ref,v!==null&&typeof v!=\"function\"&&typeof v!=\"object\"){if(Q._owner){if(Q=Q._owner,Q){if(Q.tag!==1)throw Error(c(309));var H=Q.stateNode}if(!H)throw Error(c(147,v));var V=\"\"+v;return D!==null&&D.ref!==null&&typeof D.ref==\"function\"&&D.ref._stringRef===V?D.ref:(D=function(ne){var ve=H.refs;ve===Sy&&(ve=H.refs={}),ne===null?delete ve[V]:ve[V]=ne},D._stringRef=V,D)}if(typeof v!=\"string\")throw Error(c(284));if(!Q._owner)throw Error(c(290,v))}return v}function pu(v,D){if(v.type!==\"textarea\")throw Error(c(31,Object.prototype.toString.call(D)===\"[object Object]\"?\"object with keys {\"+Object.keys(D).join(\", \")+\"}\":D))}function Dy(v){function D(rt,We){if(v){var dt=rt.lastEffect;dt!==null?(dt.nextEffect=We,rt.lastEffect=We):rt.firstEffect=rt.lastEffect=We,We.nextEffect=null,We.flags=8}}function Q(rt,We){if(!v)return null;for(;We!==null;)D(rt,We),We=We.sibling;return null}function H(rt,We){for(rt=new Map;We!==null;)We.key!==null?rt.set(We.key,We):rt.set(We.index,We),We=We.sibling;return rt}function V(rt,We){return rt=Bu(rt,We),rt.index=0,rt.sibling=null,rt}function ne(rt,We,dt){return rt.index=dt,v?(dt=rt.alternate,dt!==null?(dt=dt.index,dt<We?(rt.flags=2,We):dt):(rt.flags=2,We)):We}function ve(rt){return v&&rt.alternate===null&&(rt.flags=2),rt}function _e(rt,We,dt,Zt){return We===null||We.tag!==6?(We=EB(dt,rt.mode,Zt),We.return=rt,We):(We=V(We,dt),We.return=rt,We)}function ht(rt,We,dt,Zt){return We!==null&&We.elementType===dt.type?(Zt=V(We,dt.props),Zt.ref=yt(rt,We,dt),Zt.return=rt,Zt):(Zt=nd(dt.type,dt.key,dt.props,null,rt.mode,Zt),Zt.ref=yt(rt,We,dt),Zt.return=rt,Zt)}function Wt(rt,We,dt,Zt){return We===null||We.tag!==4||We.stateNode.containerInfo!==dt.containerInfo||We.stateNode.implementation!==dt.implementation?(We=Oo(dt,rt.mode,Zt),We.return=rt,We):(We=V(We,dt.children||[]),We.return=rt,We)}function Sr(rt,We,dt,Zt,Dr){return We===null||We.tag!==7?(We=Rf(dt,rt.mode,Zt,Dr),We.return=rt,We):(We=V(We,dt),We.return=rt,We)}function Lr(rt,We,dt){if(typeof We==\"string\"||typeof We==\"number\")return We=EB(\"\"+We,rt.mode,dt),We.return=rt,We;if(typeof We==\"object\"&&We!==null){switch(We.$$typeof){case p:return dt=nd(We.type,We.key,We.props,null,rt.mode,dt),dt.ref=yt(rt,null,We),dt.return=rt,dt;case h:return We=Oo(We,rt.mode,dt),We.return=rt,We}if(Ef(We)||Ee(We))return We=Rf(We,rt.mode,dt,null),We.return=rt,We;pu(rt,We)}return null}function Xt(rt,We,dt,Zt){var Dr=We!==null?We.key:null;if(typeof dt==\"string\"||typeof dt==\"number\")return Dr!==null?null:_e(rt,We,\"\"+dt,Zt);if(typeof dt==\"object\"&&dt!==null){switch(dt.$$typeof){case p:return dt.key===Dr?dt.type===E?Sr(rt,We,dt.props.children,Zt,Dr):ht(rt,We,dt,Zt):null;case h:return dt.key===Dr?Wt(rt,We,dt,Zt):null}if(Ef(dt)||Ee(dt))return Dr!==null?null:Sr(rt,We,dt,Zt,null);pu(rt,dt)}return null}function Xn(rt,We,dt,Zt,Dr){if(typeof Zt==\"string\"||typeof Zt==\"number\")return rt=rt.get(dt)||null,_e(We,rt,\"\"+Zt,Dr);if(typeof Zt==\"object\"&&Zt!==null){switch(Zt.$$typeof){case p:return rt=rt.get(Zt.key===null?dt:Zt.key)||null,Zt.type===E?Sr(We,rt,Zt.props.children,Dr,Zt.key):ht(We,rt,Zt,Dr);case h:return rt=rt.get(Zt.key===null?dt:Zt.key)||null,Wt(We,rt,Zt,Dr)}if(Ef(Zt)||Ee(Zt))return rt=rt.get(dt)||null,Sr(We,rt,Zt,Dr,null);pu(We,Zt)}return null}function Ei(rt,We,dt,Zt){for(var Dr=null,ti=null,kr=We,Nn=We=0,Hn=null;kr!==null&&Nn<dt.length;Nn++){kr.index>Nn?(Hn=kr,kr=null):Hn=kr.sibling;var zr=Xt(rt,kr,dt[Nn],Zt);if(zr===null){kr===null&&(kr=Hn);break}v&&kr&&zr.alternate===null&&D(rt,kr),We=ne(zr,We,Nn),ti===null?Dr=zr:ti.sibling=zr,ti=zr,kr=Hn}if(Nn===dt.length)return Q(rt,kr),Dr;if(kr===null){for(;Nn<dt.length;Nn++)kr=Lr(rt,dt[Nn],Zt),kr!==null&&(We=ne(kr,We,Nn),ti===null?Dr=kr:ti.sibling=kr,ti=kr);return Dr}for(kr=H(rt,kr);Nn<dt.length;Nn++)Hn=Xn(kr,rt,Nn,dt[Nn],Zt),Hn!==null&&(v&&Hn.alternate!==null&&kr.delete(Hn.key===null?Nn:Hn.key),We=ne(Hn,We,Nn),ti===null?Dr=Hn:ti.sibling=Hn,ti=Hn);return v&&kr.forEach(function(ui){return D(rt,ui)}),Dr}function rl(rt,We,dt,Zt){var Dr=Ee(dt);if(typeof Dr!=\"function\")throw Error(c(150));if(dt=Dr.call(dt),dt==null)throw Error(c(151));for(var ti=Dr=null,kr=We,Nn=We=0,Hn=null,zr=dt.next();kr!==null&&!zr.done;Nn++,zr=dt.next()){kr.index>Nn?(Hn=kr,kr=null):Hn=kr.sibling;var ui=Xt(rt,kr,zr.value,Zt);if(ui===null){kr===null&&(kr=Hn);break}v&&kr&&ui.alternate===null&&D(rt,kr),We=ne(ui,We,Nn),ti===null?Dr=ui:ti.sibling=ui,ti=ui,kr=Hn}if(zr.done)return Q(rt,kr),Dr;if(kr===null){for(;!zr.done;Nn++,zr=dt.next())zr=Lr(rt,zr.value,Zt),zr!==null&&(We=ne(zr,We,Nn),ti===null?Dr=zr:ti.sibling=zr,ti=zr);return Dr}for(kr=H(rt,kr);!zr.done;Nn++,zr=dt.next())zr=Xn(kr,rt,Nn,zr.value,Zt),zr!==null&&(v&&zr.alternate!==null&&kr.delete(zr.key===null?Nn:zr.key),We=ne(zr,We,Nn),ti===null?Dr=zr:ti.sibling=zr,ti=zr);return v&&kr.forEach(function(vu){return D(rt,vu)}),Dr}return function(rt,We,dt,Zt){var Dr=typeof dt==\"object\"&&dt!==null&&dt.type===E&&dt.key===null;Dr&&(dt=dt.props.children);var ti=typeof dt==\"object\"&&dt!==null;if(ti)switch(dt.$$typeof){case p:e:{for(ti=dt.key,Dr=We;Dr!==null;){if(Dr.key===ti){switch(Dr.tag){case 7:if(dt.type===E){Q(rt,Dr.sibling),We=V(Dr,dt.props.children),We.return=rt,rt=We;break e}break;default:if(Dr.elementType===dt.type){Q(rt,Dr.sibling),We=V(Dr,dt.props),We.ref=yt(rt,Dr,dt),We.return=rt,rt=We;break e}}Q(rt,Dr);break}else D(rt,Dr);Dr=Dr.sibling}dt.type===E?(We=Rf(dt.props.children,rt.mode,Zt,dt.key),We.return=rt,rt=We):(Zt=nd(dt.type,dt.key,dt.props,null,rt.mode,Zt),Zt.ref=yt(rt,We,dt),Zt.return=rt,rt=Zt)}return ve(rt);case h:e:{for(Dr=dt.key;We!==null;){if(We.key===Dr)if(We.tag===4&&We.stateNode.containerInfo===dt.containerInfo&&We.stateNode.implementation===dt.implementation){Q(rt,We.sibling),We=V(We,dt.children||[]),We.return=rt,rt=We;break e}else{Q(rt,We);break}else D(rt,We);We=We.sibling}We=Oo(dt,rt.mode,Zt),We.return=rt,rt=We}return ve(rt)}if(typeof dt==\"string\"||typeof dt==\"number\")return dt=\"\"+dt,We!==null&&We.tag===6?(Q(rt,We.sibling),We=V(We,dt),We.return=rt,rt=We):(Q(rt,We),We=EB(dt,rt.mode,Zt),We.return=rt,rt=We),ve(rt);if(Ef(dt))return Ei(rt,We,dt,Zt);if(Ee(dt))return rl(rt,We,dt,Zt);if(ti&&pu(rt,dt),typeof dt>\"u\"&&!Dr)switch(rt.tag){case 1:case 22:case 0:case 11:case 15:throw Error(c(152,g(rt.type)||\"Component\"))}return Q(rt,We)}}var Og=Dy(!0),V1=Dy(!1),wh={},ur=co(wh),zi=co(wh),If=co(wh);function za(v){if(v===wh)throw Error(c(174));return v}function Lg(v,D){Qn(If,D),Qn(zi,v),Qn(ur,wh),v=it(D),Tt(ur),Qn(ur,v)}function hu(){Tt(ur),Tt(zi),Tt(If)}function Cf(v){var D=za(If.current),Q=za(ur.current);D=_(Q,v.type,D),Q!==D&&(Qn(zi,v),Qn(ur,D))}function wt(v){zi.current===v&&(Tt(ur),Tt(zi))}var mi=co(0);function qA(v){for(var D=v;D!==null;){if(D.tag===13){var Q=D.memoizedState;if(Q!==null&&(Q=Q.dehydrated,Q===null||gr(Q)||Po(Q)))return D}else if(D.tag===19&&D.memoizedProps.revealOrder!==void 0){if(D.flags&64)return D}else if(D.child!==null){D.child.return=D,D=D.child;continue}if(D===v)break;for(;D.sibling===null;){if(D.return===null||D.return===v)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}return null}var Za=null,da=null,Xa=!1;function Mg(v,D){var Q=tl(5,null,null,0);Q.elementType=\"DELETED\",Q.type=\"DELETED\",Q.stateNode=D,Q.return=v,Q.flags=8,v.lastEffect!==null?(v.lastEffect.nextEffect=Q,v.lastEffect=Q):v.firstEffect=v.lastEffect=Q}function Bh(v,D){switch(v.tag){case 5:return D=fa(D,v.type,v.pendingProps),D!==null?(v.stateNode=D,!0):!1;case 6:return D=NA(D,v.pendingProps),D!==null?(v.stateNode=D,!0):!1;case 13:return!1;default:return!1}}function Ug(v){if(Xa){var D=da;if(D){var Q=D;if(!Bh(v,D)){if(D=Ue(Q),!D||!Bh(v,D)){v.flags=v.flags&-1025|2,Xa=!1,Za=v;return}Mg(Za,Q)}Za=v,da=au(D)}else v.flags=v.flags&-1025|2,Xa=!1,Za=v}}function by(v){for(v=v.return;v!==null&&v.tag!==5&&v.tag!==3&&v.tag!==13;)v=v.return;Za=v}function WA(v){if(!Z||v!==Za)return!1;if(!Xa)return by(v),Xa=!0,!1;var D=v.type;if(v.tag!==5||D!==\"head\"&&D!==\"body\"&&!ct(D,v.memoizedProps))for(D=da;D;)Mg(v,D),D=Ue(D);if(by(v),v.tag===13){if(!Z)throw Error(c(316));if(v=v.memoizedState,v=v!==null?v.dehydrated:null,!v)throw Error(c(317));da=OA(v)}else da=Za?Ue(v.stateNode):null;return!0}function _g(){Z&&(da=Za=null,Xa=!1)}var gu=[];function du(){for(var v=0;v<gu.length;v++){var D=gu[v];y?D._workInProgressVersionPrimary=null:D._workInProgressVersionSecondary=null}gu.length=0}var wf=f.ReactCurrentDispatcher,Os=f.ReactCurrentBatchConfig,mu=0,qn=null,ss=null,Pi=null,VA=!1,Bf=!1;function yn(){throw Error(c(321))}function Hg(v,D){if(D===null)return!1;for(var Q=0;Q<D.length&&Q<v.length;Q++)if(!xo(v[Q],D[Q]))return!1;return!0}function jg(v,D,Q,H,V,ne){if(mu=ne,qn=D,D.memoizedState=null,D.updateQueue=null,D.lanes=0,wf.current=v===null||v.memoizedState===null?N:J,v=Q(H,V),Bf){ne=0;do{if(Bf=!1,!(25>ne))throw Error(c(301));ne+=1,Pi=ss=null,D.updateQueue=null,wf.current=re,v=Q(H,V)}while(Bf)}if(wf.current=kt,D=ss!==null&&ss.next!==null,mu=0,Pi=ss=qn=null,VA=!1,D)throw Error(c(300));return v}function os(){var v={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return Pi===null?qn.memoizedState=Pi=v:Pi=Pi.next=v,Pi}function Fl(){if(ss===null){var v=qn.alternate;v=v!==null?v.memoizedState:null}else v=ss.next;var D=Pi===null?qn.memoizedState:Pi.next;if(D!==null)Pi=D,ss=v;else{if(v===null)throw Error(c(310));ss=v,v={memoizedState:ss.memoizedState,baseState:ss.baseState,baseQueue:ss.baseQueue,queue:ss.queue,next:null},Pi===null?qn.memoizedState=Pi=v:Pi=Pi.next=v}return Pi}function To(v,D){return typeof D==\"function\"?D(v):D}function vf(v){var D=Fl(),Q=D.queue;if(Q===null)throw Error(c(311));Q.lastRenderedReducer=v;var H=ss,V=H.baseQueue,ne=Q.pending;if(ne!==null){if(V!==null){var ve=V.next;V.next=ne.next,ne.next=ve}H.baseQueue=V=ne,Q.pending=null}if(V!==null){V=V.next,H=H.baseState;var _e=ve=ne=null,ht=V;do{var Wt=ht.lane;if((mu&Wt)===Wt)_e!==null&&(_e=_e.next={lane:0,action:ht.action,eagerReducer:ht.eagerReducer,eagerState:ht.eagerState,next:null}),H=ht.eagerReducer===v?ht.eagerState:v(H,ht.action);else{var Sr={lane:Wt,action:ht.action,eagerReducer:ht.eagerReducer,eagerState:ht.eagerState,next:null};_e===null?(ve=_e=Sr,ne=H):_e=_e.next=Sr,qn.lanes|=Wt,zg|=Wt}ht=ht.next}while(ht!==null&&ht!==V);_e===null?ne=H:_e.next=ve,xo(H,D.memoizedState)||(Ke=!0),D.memoizedState=H,D.baseState=ne,D.baseQueue=_e,Q.lastRenderedState=H}return[D.memoizedState,Q.dispatch]}function Sf(v){var D=Fl(),Q=D.queue;if(Q===null)throw Error(c(311));Q.lastRenderedReducer=v;var H=Q.dispatch,V=Q.pending,ne=D.memoizedState;if(V!==null){Q.pending=null;var ve=V=V.next;do ne=v(ne,ve.action),ve=ve.next;while(ve!==V);xo(ne,D.memoizedState)||(Ke=!0),D.memoizedState=ne,D.baseQueue===null&&(D.baseState=ne),Q.lastRenderedState=ne}return[ne,H]}function Nl(v,D,Q){var H=D._getVersion;H=H(D._source);var V=y?D._workInProgressVersionPrimary:D._workInProgressVersionSecondary;if(V!==null?v=V===H:(v=v.mutableReadLanes,(v=(mu&v)===v)&&(y?D._workInProgressVersionPrimary=H:D._workInProgressVersionSecondary=H,gu.push(D))),v)return Q(D._source);throw gu.push(D),Error(c(350))}function En(v,D,Q,H){var V=fo;if(V===null)throw Error(c(349));var ne=D._getVersion,ve=ne(D._source),_e=wf.current,ht=_e.useState(function(){return Nl(V,D,Q)}),Wt=ht[1],Sr=ht[0];ht=Pi;var Lr=v.memoizedState,Xt=Lr.refs,Xn=Xt.getSnapshot,Ei=Lr.source;Lr=Lr.subscribe;var rl=qn;return v.memoizedState={refs:Xt,source:D,subscribe:H},_e.useEffect(function(){Xt.getSnapshot=Q,Xt.setSnapshot=Wt;var rt=ne(D._source);if(!xo(ve,rt)){rt=Q(D._source),xo(Sr,rt)||(Wt(rt),rt=Ds(rl),V.mutableReadLanes|=rt&V.pendingLanes),rt=V.mutableReadLanes,V.entangledLanes|=rt;for(var We=V.entanglements,dt=rt;0<dt;){var Zt=31-is(dt),Dr=1<<Zt;We[Zt]|=rt,dt&=~Dr}}},[Q,D,H]),_e.useEffect(function(){return H(D._source,function(){var rt=Xt.getSnapshot,We=Xt.setSnapshot;try{We(rt(D._source));var dt=Ds(rl);V.mutableReadLanes|=dt&V.pendingLanes}catch(Zt){We(function(){throw Zt})}})},[D,H]),xo(Xn,Q)&&xo(Ei,D)&&xo(Lr,H)||(v={pending:null,dispatch:null,lastRenderedReducer:To,lastRenderedState:Sr},v.dispatch=Wt=bh.bind(null,qn,v),ht.queue=v,ht.baseQueue=null,Sr=Nl(V,D,Q),ht.memoizedState=ht.baseState=Sr),Sr}function Fo(v,D,Q){var H=Fl();return En(H,v,D,Q)}function yu(v){var D=os();return typeof v==\"function\"&&(v=v()),D.memoizedState=D.baseState=v,v=D.queue={pending:null,dispatch:null,lastRenderedReducer:To,lastRenderedState:v},v=v.dispatch=bh.bind(null,qn,v),[D.memoizedState,v]}function ma(v,D,Q,H){return v={tag:v,create:D,destroy:Q,deps:H,next:null},D=qn.updateQueue,D===null?(D={lastEffect:null},qn.updateQueue=D,D.lastEffect=v.next=v):(Q=D.lastEffect,Q===null?D.lastEffect=v.next=v:(H=Q.next,Q.next=v,v.next=H,D.lastEffect=v)),v}function Ls(v){var D=os();return v={current:v},D.memoizedState=v}function vh(){return Fl().memoizedState}function YA(v,D,Q,H){var V=os();qn.flags|=v,V.memoizedState=ma(1|D,Q,void 0,H===void 0?null:H)}function Df(v,D,Q,H){var V=Fl();H=H===void 0?null:H;var ne=void 0;if(ss!==null){var ve=ss.memoizedState;if(ne=ve.destroy,H!==null&&Hg(H,ve.deps)){ma(D,Q,ne,H);return}}qn.flags|=v,V.memoizedState=ma(1|D,Q,ne,H)}function uo(v,D){return YA(516,4,v,D)}function Xr(v,D){return Df(516,4,v,D)}function Sh(v,D){return Df(4,2,v,D)}function KA(v,D){if(typeof D==\"function\")return v=v(),D(v),function(){D(null)};if(D!=null)return v=v(),D.current=v,function(){D.current=null}}function Py(v,D,Q){return Q=Q!=null?Q.concat([v]):null,Df(4,2,KA.bind(null,D,v),Q)}function Gg(){}function Dh(v,D){var Q=Fl();D=D===void 0?null:D;var H=Q.memoizedState;return H!==null&&D!==null&&Hg(D,H[1])?H[0]:(Q.memoizedState=[v,D],v)}function hc(v,D){var Q=Fl();D=D===void 0?null:D;var H=Q.memoizedState;return H!==null&&D!==null&&Hg(D,H[1])?H[0]:(v=v(),Q.memoizedState=[v,D],v)}function xy(v,D){var Q=tr();ci(98>Q?98:Q,function(){v(!0)}),ci(97<Q?97:Q,function(){var H=Os.transition;Os.transition=1;try{v(!1),D()}finally{Os.transition=H}})}function bh(v,D,Q){var H=No(),V=Ds(v),ne={lane:V,action:Q,eagerReducer:null,eagerState:null,next:null},ve=D.pending;if(ve===null?ne.next=ne:(ne.next=ve.next,ve.next=ne),D.pending=ne,ve=v.alternate,v===qn||ve!==null&&ve===qn)Bf=VA=!0;else{if(v.lanes===0&&(ve===null||ve.lanes===0)&&(ve=D.lastRenderedReducer,ve!==null))try{var _e=D.lastRenderedState,ht=ve(_e,Q);if(ne.eagerReducer=ve,ne.eagerState=ht,xo(ht,_e))return}catch{}finally{}Ml(v,V,H)}}var kt={readContext:Qo,useCallback:yn,useContext:yn,useEffect:yn,useImperativeHandle:yn,useLayoutEffect:yn,useMemo:yn,useReducer:yn,useRef:yn,useState:yn,useDebugValue:yn,useDeferredValue:yn,useTransition:yn,useMutableSource:yn,useOpaqueIdentifier:yn,unstable_isNewReconciler:!1},N={readContext:Qo,useCallback:function(v,D){return os().memoizedState=[v,D===void 0?null:D],v},useContext:Qo,useEffect:uo,useImperativeHandle:function(v,D,Q){return Q=Q!=null?Q.concat([v]):null,YA(4,2,KA.bind(null,D,v),Q)},useLayoutEffect:function(v,D){return YA(4,2,v,D)},useMemo:function(v,D){var Q=os();return D=D===void 0?null:D,v=v(),Q.memoizedState=[v,D],v},useReducer:function(v,D,Q){var H=os();return D=Q!==void 0?Q(D):D,H.memoizedState=H.baseState=D,v=H.queue={pending:null,dispatch:null,lastRenderedReducer:v,lastRenderedState:D},v=v.dispatch=bh.bind(null,qn,v),[H.memoizedState,v]},useRef:Ls,useState:yu,useDebugValue:Gg,useDeferredValue:function(v){var D=yu(v),Q=D[0],H=D[1];return uo(function(){var V=Os.transition;Os.transition=1;try{H(v)}finally{Os.transition=V}},[v]),Q},useTransition:function(){var v=yu(!1),D=v[0];return v=xy.bind(null,v[1]),Ls(v),[v,D]},useMutableSource:function(v,D,Q){var H=os();return H.memoizedState={refs:{getSnapshot:D,setSnapshot:null},source:v,subscribe:Q},En(H,v,D,Q)},useOpaqueIdentifier:function(){if(Xa){var v=!1,D=se(function(){throw v||(v=!0,Q(xe())),Error(c(355))}),Q=yu(D)[1];return!(qn.mode&2)&&(qn.flags|=516,ma(5,function(){Q(xe())},void 0,null)),D}return D=xe(),yu(D),D},unstable_isNewReconciler:!1},J={readContext:Qo,useCallback:Dh,useContext:Qo,useEffect:Xr,useImperativeHandle:Py,useLayoutEffect:Sh,useMemo:hc,useReducer:vf,useRef:vh,useState:function(){return vf(To)},useDebugValue:Gg,useDeferredValue:function(v){var D=vf(To),Q=D[0],H=D[1];return Xr(function(){var V=Os.transition;Os.transition=1;try{H(v)}finally{Os.transition=V}},[v]),Q},useTransition:function(){var v=vf(To)[0];return[vh().current,v]},useMutableSource:Fo,useOpaqueIdentifier:function(){return vf(To)[0]},unstable_isNewReconciler:!1},re={readContext:Qo,useCallback:Dh,useContext:Qo,useEffect:Xr,useImperativeHandle:Py,useLayoutEffect:Sh,useMemo:hc,useReducer:Sf,useRef:vh,useState:function(){return Sf(To)},useDebugValue:Gg,useDeferredValue:function(v){var D=Sf(To),Q=D[0],H=D[1];return Xr(function(){var V=Os.transition;Os.transition=1;try{H(v)}finally{Os.transition=V}},[v]),Q},useTransition:function(){var v=Sf(To)[0];return[vh().current,v]},useMutableSource:Fo,useOpaqueIdentifier:function(){return Sf(To)[0]},unstable_isNewReconciler:!1},ge=f.ReactCurrentOwner,Ke=!1;function pt(v,D,Q,H){D.child=v===null?V1(D,null,Q,H):Og(D,v.child,Q,H)}function dr(v,D,Q,H,V){Q=Q.render;var ne=D.ref;return yf(D,V),H=jg(v,D,Q,H,ne,V),v!==null&&!Ke?(D.updateQueue=v.updateQueue,D.flags&=-517,v.lanes&=~V,Wn(v,D,V)):(D.flags|=1,pt(v,D,H,V),D.child)}function vr(v,D,Q,H,V,ne){if(v===null){var ve=Q.type;return typeof ve==\"function\"&&!mB(ve)&&ve.defaultProps===void 0&&Q.compare===null&&Q.defaultProps===void 0?(D.tag=15,D.type=ve,_n(v,D,ve,H,V,ne)):(v=nd(Q.type,null,H,D,D.mode,ne),v.ref=D.ref,v.return=D,D.child=v)}return ve=v.child,!(V&ne)&&(V=ve.memoizedProps,Q=Q.compare,Q=Q!==null?Q:mh,Q(V,H)&&v.ref===D.ref)?Wn(v,D,ne):(D.flags|=1,v=Bu(ve,H),v.ref=D.ref,v.return=D,D.child=v)}function _n(v,D,Q,H,V,ne){if(v!==null&&mh(v.memoizedProps,H)&&v.ref===D.ref)if(Ke=!1,(ne&V)!==0)v.flags&16384&&(Ke=!0);else return D.lanes=v.lanes,Wn(v,D,ne);return JA(v,D,Q,H,ne)}function yi(v,D,Q){var H=D.pendingProps,V=H.children,ne=v!==null?v.memoizedState:null;if(H.mode===\"hidden\"||H.mode===\"unstable-defer-without-hiding\")if(!(D.mode&4))D.memoizedState={baseLanes:0},Yy(D,Q);else if(Q&1073741824)D.memoizedState={baseLanes:0},Yy(D,ne!==null?ne.baseLanes:Q);else return v=ne!==null?ne.baseLanes|Q:Q,D.lanes=D.childLanes=1073741824,D.memoizedState={baseLanes:v},Yy(D,v),null;else ne!==null?(H=ne.baseLanes|Q,D.memoizedState=null):H=Q,Yy(D,H);return pt(v,D,V,Q),D.child}function vs(v,D){var Q=D.ref;(v===null&&Q!==null||v!==null&&v.ref!==Q)&&(D.flags|=128)}function JA(v,D,Q,H,V){var ne=Zn(Q)?ja:Gi.current;return ne=mn(D,ne),yf(D,V),Q=jg(v,D,Q,H,ne,V),v!==null&&!Ke?(D.updateQueue=v.updateQueue,D.flags&=-517,v.lanes&=~V,Wn(v,D,V)):(D.flags|=1,pt(v,D,Q,V),D.child)}function lP(v,D,Q,H,V){if(Zn(Q)){var ne=!0;qa(D)}else ne=!1;if(yf(D,V),D.stateNode===null)v!==null&&(v.alternate=null,D.alternate=null,D.flags|=2),xt(D,Q,H),Ro(D,Q,H,V),H=!0;else if(v===null){var ve=D.stateNode,_e=D.memoizedProps;ve.props=_e;var ht=ve.context,Wt=Q.contextType;typeof Wt==\"object\"&&Wt!==null?Wt=Qo(Wt):(Wt=Zn(Q)?ja:Gi.current,Wt=mn(D,Wt));var Sr=Q.getDerivedStateFromProps,Lr=typeof Sr==\"function\"||typeof ve.getSnapshotBeforeUpdate==\"function\";Lr||typeof ve.UNSAFE_componentWillReceiveProps!=\"function\"&&typeof ve.componentWillReceiveProps!=\"function\"||(_e!==H||ht!==Wt)&&GA(D,ve,H,Wt),Ql=!1;var Xt=D.memoizedState;ve.state=Xt,_A(D,H,ve,V),ht=D.memoizedState,_e!==H||Xt!==ht||Li.current||Ql?(typeof Sr==\"function\"&&(HA(D,Q,Sr,H),ht=D.memoizedState),(_e=Ql||W(D,Q,_e,H,Xt,ht,Wt))?(Lr||typeof ve.UNSAFE_componentWillMount!=\"function\"&&typeof ve.componentWillMount!=\"function\"||(typeof ve.componentWillMount==\"function\"&&ve.componentWillMount(),typeof ve.UNSAFE_componentWillMount==\"function\"&&ve.UNSAFE_componentWillMount()),typeof ve.componentDidMount==\"function\"&&(D.flags|=4)):(typeof ve.componentDidMount==\"function\"&&(D.flags|=4),D.memoizedProps=H,D.memoizedState=ht),ve.props=H,ve.state=ht,ve.context=Wt,H=_e):(typeof ve.componentDidMount==\"function\"&&(D.flags|=4),H=!1)}else{ve=D.stateNode,Ng(v,D),_e=D.memoizedProps,Wt=D.type===D.elementType?_e:ko(D.type,_e),ve.props=Wt,Lr=D.pendingProps,Xt=ve.context,ht=Q.contextType,typeof ht==\"object\"&&ht!==null?ht=Qo(ht):(ht=Zn(Q)?ja:Gi.current,ht=mn(D,ht));var Xn=Q.getDerivedStateFromProps;(Sr=typeof Xn==\"function\"||typeof ve.getSnapshotBeforeUpdate==\"function\")||typeof ve.UNSAFE_componentWillReceiveProps!=\"function\"&&typeof ve.componentWillReceiveProps!=\"function\"||(_e!==Lr||Xt!==ht)&&GA(D,ve,H,ht),Ql=!1,Xt=D.memoizedState,ve.state=Xt,_A(D,H,ve,V);var Ei=D.memoizedState;_e!==Lr||Xt!==Ei||Li.current||Ql?(typeof Xn==\"function\"&&(HA(D,Q,Xn,H),Ei=D.memoizedState),(Wt=Ql||W(D,Q,Wt,H,Xt,Ei,ht))?(Sr||typeof ve.UNSAFE_componentWillUpdate!=\"function\"&&typeof ve.componentWillUpdate!=\"function\"||(typeof ve.componentWillUpdate==\"function\"&&ve.componentWillUpdate(H,Ei,ht),typeof ve.UNSAFE_componentWillUpdate==\"function\"&&ve.UNSAFE_componentWillUpdate(H,Ei,ht)),typeof ve.componentDidUpdate==\"function\"&&(D.flags|=4),typeof ve.getSnapshotBeforeUpdate==\"function\"&&(D.flags|=256)):(typeof ve.componentDidUpdate!=\"function\"||_e===v.memoizedProps&&Xt===v.memoizedState||(D.flags|=4),typeof ve.getSnapshotBeforeUpdate!=\"function\"||_e===v.memoizedProps&&Xt===v.memoizedState||(D.flags|=256),D.memoizedProps=H,D.memoizedState=Ei),ve.props=H,ve.state=Ei,ve.context=ht,H=Wt):(typeof ve.componentDidUpdate!=\"function\"||_e===v.memoizedProps&&Xt===v.memoizedState||(D.flags|=4),typeof ve.getSnapshotBeforeUpdate!=\"function\"||_e===v.memoizedProps&&Xt===v.memoizedState||(D.flags|=256),H=!1)}return Y1(v,D,Q,H,ne,V)}function Y1(v,D,Q,H,V,ne){vs(v,D);var ve=(D.flags&64)!==0;if(!H&&!ve)return V&&Wa(D,Q,!1),Wn(v,D,ne);H=D.stateNode,ge.current=D;var _e=ve&&typeof Q.getDerivedStateFromError!=\"function\"?null:H.render();return D.flags|=1,v!==null&&ve?(D.child=Og(D,v.child,null,ne),D.child=Og(D,null,_e,ne)):pt(v,D,_e,ne),D.memoizedState=H.state,V&&Wa(D,Q,!0),D.child}function ky(v){var D=v.stateNode;D.pendingContext?dh(v,D.pendingContext,D.pendingContext!==D.context):D.context&&dh(v,D.context,!1),Lg(v,D.containerInfo)}var Ph={dehydrated:null,retryLane:0};function K1(v,D,Q){var H=D.pendingProps,V=mi.current,ne=!1,ve;return(ve=(D.flags&64)!==0)||(ve=v!==null&&v.memoizedState===null?!1:(V&2)!==0),ve?(ne=!0,D.flags&=-65):v!==null&&v.memoizedState===null||H.fallback===void 0||H.unstable_avoidThisFallback===!0||(V|=1),Qn(mi,V&1),v===null?(H.fallback!==void 0&&Ug(D),v=H.children,V=H.fallback,ne?(v=$a(D,v,V,Q),D.child.memoizedState={baseLanes:Q},D.memoizedState=Ph,v):typeof H.unstable_expectedLoadTime==\"number\"?(v=$a(D,v,V,Q),D.child.memoizedState={baseLanes:Q},D.memoizedState=Ph,D.lanes=33554432,v):(Q=yB({mode:\"visible\",children:v},D.mode,Q,null),Q.return=D,D.child=Q)):v.memoizedState!==null?ne?(H=zA(v,D,H.children,H.fallback,Q),ne=D.child,V=v.child.memoizedState,ne.memoizedState=V===null?{baseLanes:Q}:{baseLanes:V.baseLanes|Q},ne.childLanes=v.childLanes&~Q,D.memoizedState=Ph,H):(Q=J1(v,D,H.children,Q),D.memoizedState=null,Q):ne?(H=zA(v,D,H.children,H.fallback,Q),ne=D.child,V=v.child.memoizedState,ne.memoizedState=V===null?{baseLanes:Q}:{baseLanes:V.baseLanes|Q},ne.childLanes=v.childLanes&~Q,D.memoizedState=Ph,H):(Q=J1(v,D,H.children,Q),D.memoizedState=null,Q)}function $a(v,D,Q,H){var V=v.mode,ne=v.child;return D={mode:\"hidden\",children:D},!(V&2)&&ne!==null?(ne.childLanes=0,ne.pendingProps=D):ne=yB(D,V,0,null),Q=Rf(Q,V,H,null),ne.return=v,Q.return=v,ne.sibling=Q,v.child=ne,Q}function J1(v,D,Q,H){var V=v.child;return v=V.sibling,Q=Bu(V,{mode:\"visible\",children:Q}),!(D.mode&2)&&(Q.lanes=H),Q.return=D,Q.sibling=null,v!==null&&(v.nextEffect=null,v.flags=8,D.firstEffect=D.lastEffect=v),D.child=Q}function zA(v,D,Q,H,V){var ne=D.mode,ve=v.child;v=ve.sibling;var _e={mode:\"hidden\",children:Q};return!(ne&2)&&D.child!==ve?(Q=D.child,Q.childLanes=0,Q.pendingProps=_e,ve=Q.lastEffect,ve!==null?(D.firstEffect=Q.firstEffect,D.lastEffect=ve,ve.nextEffect=null):D.firstEffect=D.lastEffect=null):Q=Bu(ve,_e),v!==null?H=Bu(v,H):(H=Rf(H,ne,V,null),H.flags|=2),H.return=D,Q.return=D,Q.sibling=H,D.child=Q,H}function xh(v,D){v.lanes|=D;var Q=v.alternate;Q!==null&&(Q.lanes|=D),wy(v.return,D)}function Qy(v,D,Q,H,V,ne){var ve=v.memoizedState;ve===null?v.memoizedState={isBackwards:D,rendering:null,renderingStartTime:0,last:H,tail:Q,tailMode:V,lastEffect:ne}:(ve.isBackwards=D,ve.rendering=null,ve.renderingStartTime=0,ve.last=H,ve.tail=Q,ve.tailMode=V,ve.lastEffect=ne)}function cP(v,D,Q){var H=D.pendingProps,V=H.revealOrder,ne=H.tail;if(pt(v,D,H.children,Q),H=mi.current,H&2)H=H&1|2,D.flags|=64;else{if(v!==null&&v.flags&64)e:for(v=D.child;v!==null;){if(v.tag===13)v.memoizedState!==null&&xh(v,Q);else if(v.tag===19)xh(v,Q);else if(v.child!==null){v.child.return=v,v=v.child;continue}if(v===D)break e;for(;v.sibling===null;){if(v.return===null||v.return===D)break e;v=v.return}v.sibling.return=v.return,v=v.sibling}H&=1}if(Qn(mi,H),!(D.mode&2))D.memoizedState=null;else switch(V){case\"forwards\":for(Q=D.child,V=null;Q!==null;)v=Q.alternate,v!==null&&qA(v)===null&&(V=Q),Q=Q.sibling;Q=V,Q===null?(V=D.child,D.child=null):(V=Q.sibling,Q.sibling=null),Qy(D,!1,V,Q,ne,D.lastEffect);break;case\"backwards\":for(Q=null,V=D.child,D.child=null;V!==null;){if(v=V.alternate,v!==null&&qA(v)===null){D.child=V;break}v=V.sibling,V.sibling=Q,Q=V,V=v}Qy(D,!0,Q,null,ne,D.lastEffect);break;case\"together\":Qy(D,!1,null,null,void 0,D.lastEffect);break;default:D.memoizedState=null}return D.child}function Wn(v,D,Q){if(v!==null&&(D.dependencies=v.dependencies),zg|=D.lanes,Q&D.childLanes){if(v!==null&&D.child!==v.child)throw Error(c(153));if(D.child!==null){for(v=D.child,Q=Bu(v,v.pendingProps),D.child=Q,Q.return=D;v.sibling!==null;)v=v.sibling,Q=Q.sibling=Bu(v,v.pendingProps),Q.return=D;Q.sibling=null}return D.child}return null}function as(v){v.flags|=4}var Ol,Ll,Eu,ya;if(F)Ol=function(v,D){for(var Q=D.child;Q!==null;){if(Q.tag===5||Q.tag===6)be(v,Q.stateNode);else if(Q.tag!==4&&Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===D)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===D)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}},Ll=function(){},Eu=function(v,D,Q,H,V){if(v=v.memoizedProps,v!==H){var ne=D.stateNode,ve=za(ur.current);Q=Re(ne,Q,v,H,V,ve),(D.updateQueue=Q)&&as(D)}},ya=function(v,D,Q,H){Q!==H&&as(D)};else if(z){Ol=function(v,D,Q,H){for(var V=D.child;V!==null;){if(V.tag===5){var ne=V.stateNode;Q&&H&&(ne=FA(ne,V.type,V.memoizedProps,V)),be(v,ne)}else if(V.tag===6)ne=V.stateNode,Q&&H&&(ne=ua(ne,V.memoizedProps,V)),be(v,ne);else if(V.tag!==4){if(V.tag===13&&V.flags&4&&(ne=V.memoizedState!==null)){var ve=V.child;if(ve!==null&&(ve.child!==null&&(ve.child.return=ve,Ol(v,ve,!0,ne)),ne=ve.sibling,ne!==null)){ne.return=V,V=ne;continue}}if(V.child!==null){V.child.return=V,V=V.child;continue}}if(V===D)break;for(;V.sibling===null;){if(V.return===null||V.return===D)return;V=V.return}V.sibling.return=V.return,V=V.sibling}};var ZA=function(v,D,Q,H){for(var V=D.child;V!==null;){if(V.tag===5){var ne=V.stateNode;Q&&H&&(ne=FA(ne,V.type,V.memoizedProps,V)),su(v,ne)}else if(V.tag===6)ne=V.stateNode,Q&&H&&(ne=ua(ne,V.memoizedProps,V)),su(v,ne);else if(V.tag!==4){if(V.tag===13&&V.flags&4&&(ne=V.memoizedState!==null)){var ve=V.child;if(ve!==null&&(ve.child!==null&&(ve.child.return=ve,ZA(v,ve,!0,ne)),ne=ve.sibling,ne!==null)){ne.return=V,V=ne;continue}}if(V.child!==null){V.child.return=V,V=V.child;continue}}if(V===D)break;for(;V.sibling===null;){if(V.return===null||V.return===D)return;V=V.return}V.sibling.return=V.return,V=V.sibling}};Ll=function(v){var D=v.stateNode;if(v.firstEffect!==null){var Q=D.containerInfo,H=iu(Q);ZA(H,v,!1,!1),D.pendingChildren=H,as(v),ou(Q,H)}},Eu=function(v,D,Q,H,V){var ne=v.stateNode,ve=v.memoizedProps;if((v=D.firstEffect===null)&&ve===H)D.stateNode=ne;else{var _e=D.stateNode,ht=za(ur.current),Wt=null;ve!==H&&(Wt=Re(_e,Q,ve,H,V,ht)),v&&Wt===null?D.stateNode=ne:(ne=lo(ne,Wt,Q,ve,H,D,v,_e),je(ne,Q,H,V,ht)&&as(D),D.stateNode=ne,v?as(D):Ol(ne,D,!1,!1))}},ya=function(v,D,Q,H){Q!==H?(v=za(If.current),Q=za(ur.current),D.stateNode=Me(H,v,Q,D),as(D)):D.stateNode=v.stateNode}}else Ll=function(){},Eu=function(){},ya=function(){};function XA(v,D){if(!Xa)switch(v.tailMode){case\"hidden\":D=v.tail;for(var Q=null;D!==null;)D.alternate!==null&&(Q=D),D=D.sibling;Q===null?v.tail=null:Q.sibling=null;break;case\"collapsed\":Q=v.tail;for(var H=null;Q!==null;)Q.alternate!==null&&(H=Q),Q=Q.sibling;H===null?D||v.tail===null?v.tail=null:v.tail.sibling=null:H.sibling=null}}function DL(v,D,Q){var H=D.pendingProps;switch(D.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:return Zn(D.type)&&uu(),null;case 3:return hu(),Tt(Li),Tt(Gi),du(),H=D.stateNode,H.pendingContext&&(H.context=H.pendingContext,H.pendingContext=null),(v===null||v.child===null)&&(WA(D)?as(D):H.hydrate||(D.flags|=256)),Ll(D),null;case 5:wt(D);var V=za(If.current);if(Q=D.type,v!==null&&D.stateNode!=null)Eu(v,D,Q,H,V),v.ref!==D.ref&&(D.flags|=128);else{if(!H){if(D.stateNode===null)throw Error(c(166));return null}if(v=za(ur.current),WA(D)){if(!Z)throw Error(c(175));v=Cr(D.stateNode,D.type,D.memoizedProps,V,v,D),D.updateQueue=v,v!==null&&as(D)}else{var ne=ke(Q,H,V,v,D);Ol(ne,D,!1,!1),D.stateNode=ne,je(ne,Q,H,V,v)&&as(D)}D.ref!==null&&(D.flags|=128)}return null;case 6:if(v&&D.stateNode!=null)ya(v,D,v.memoizedProps,H);else{if(typeof H!=\"string\"&&D.stateNode===null)throw Error(c(166));if(v=za(If.current),V=za(ur.current),WA(D)){if(!Z)throw Error(c(176));gf(D.stateNode,D.memoizedProps,D)&&as(D)}else D.stateNode=Me(H,v,V,D)}return null;case 13:return Tt(mi),H=D.memoizedState,D.flags&64?(D.lanes=Q,D):(H=H!==null,V=!1,v===null?D.memoizedProps.fallback!==void 0&&WA(D):V=v.memoizedState!==null,H&&!V&&D.mode&2&&(v===null&&D.memoizedProps.unstable_avoidThisFallback!==!0||mi.current&1?Ss===0&&(Ss=3):((Ss===0||Ss===3)&&(Ss=4),fo===null||!(zg&134217727)&&!(Rh&134217727)||Th(fo,Ms))),z&&H&&(D.flags|=4),F&&(H||V)&&(D.flags|=4),null);case 4:return hu(),Ll(D),v===null&&Ct(D.stateNode.containerInfo),null;case 10:return Fg(D),null;case 17:return Zn(D.type)&&uu(),null;case 19:if(Tt(mi),H=D.memoizedState,H===null)return null;if(V=(D.flags&64)!==0,ne=H.rendering,ne===null)if(V)XA(H,!1);else{if(Ss!==0||v!==null&&v.flags&64)for(v=D.child;v!==null;){if(ne=qA(v),ne!==null){for(D.flags|=64,XA(H,!1),v=ne.updateQueue,v!==null&&(D.updateQueue=v,D.flags|=4),H.lastEffect===null&&(D.firstEffect=null),D.lastEffect=H.lastEffect,v=Q,H=D.child;H!==null;)V=H,Q=v,V.flags&=2,V.nextEffect=null,V.firstEffect=null,V.lastEffect=null,ne=V.alternate,ne===null?(V.childLanes=0,V.lanes=Q,V.child=null,V.memoizedProps=null,V.memoizedState=null,V.updateQueue=null,V.dependencies=null,V.stateNode=null):(V.childLanes=ne.childLanes,V.lanes=ne.lanes,V.child=ne.child,V.memoizedProps=ne.memoizedProps,V.memoizedState=ne.memoizedState,V.updateQueue=ne.updateQueue,V.type=ne.type,Q=ne.dependencies,V.dependencies=Q===null?null:{lanes:Q.lanes,firstContext:Q.firstContext}),H=H.sibling;return Qn(mi,mi.current&1|2),D.child}v=v.sibling}H.tail!==null&&bt()>cB&&(D.flags|=64,V=!0,XA(H,!1),D.lanes=33554432)}else{if(!V)if(v=qA(ne),v!==null){if(D.flags|=64,V=!0,v=v.updateQueue,v!==null&&(D.updateQueue=v,D.flags|=4),XA(H,!0),H.tail===null&&H.tailMode===\"hidden\"&&!ne.alternate&&!Xa)return D=D.lastEffect=H.lastEffect,D!==null&&(D.nextEffect=null),null}else 2*bt()-H.renderingStartTime>cB&&Q!==1073741824&&(D.flags|=64,V=!0,XA(H,!1),D.lanes=33554432);H.isBackwards?(ne.sibling=D.child,D.child=ne):(v=H.last,v!==null?v.sibling=ne:D.child=ne,H.last=ne)}return H.tail!==null?(v=H.tail,H.rendering=v,H.tail=v.sibling,H.lastEffect=D.lastEffect,H.renderingStartTime=bt(),v.sibling=null,D=mi.current,Qn(mi,V?D&1|2:D&1),v):null;case 23:case 24:return gB(),v!==null&&v.memoizedState!==null!=(D.memoizedState!==null)&&H.mode!==\"unstable-defer-without-hiding\"&&(D.flags|=4),null}throw Error(c(156,D.tag))}function bL(v){switch(v.tag){case 1:Zn(v.type)&&uu();var D=v.flags;return D&4096?(v.flags=D&-4097|64,v):null;case 3:if(hu(),Tt(Li),Tt(Gi),du(),D=v.flags,D&64)throw Error(c(285));return v.flags=D&-4097|64,v;case 5:return wt(v),null;case 13:return Tt(mi),D=v.flags,D&4096?(v.flags=D&-4097|64,v):null;case 19:return Tt(mi),null;case 4:return hu(),null;case 10:return Fg(v),null;case 23:case 24:return gB(),null;default:return null}}function qg(v,D){try{var Q=\"\",H=D;do Q+=W1(H),H=H.return;while(H);var V=Q}catch(ne){V=`\nError generating stack: `+ne.message+`\n`+ne.stack}return{value:v,source:D,stack:V}}function Wg(v,D){try{console.error(D.value)}catch(Q){setTimeout(function(){throw Q})}}var PL=typeof WeakMap==\"function\"?WeakMap:Map;function z1(v,D,Q){Q=Rl(-1,Q),Q.tag=3,Q.payload={element:null};var H=D.value;return Q.callback=function(){Gy||(Gy=!0,uB=H),Wg(v,D)},Q}function Vg(v,D,Q){Q=Rl(-1,Q),Q.tag=3;var H=v.type.getDerivedStateFromError;if(typeof H==\"function\"){var V=D.value;Q.payload=function(){return Wg(v,D),H(V)}}var ne=v.stateNode;return ne!==null&&typeof ne.componentDidCatch==\"function\"&&(Q.callback=function(){typeof H!=\"function\"&&(gc===null?gc=new Set([this]):gc.add(this),Wg(v,D));var ve=D.stack;this.componentDidCatch(D.value,{componentStack:ve!==null?ve:\"\"})}),Q}var xL=typeof WeakSet==\"function\"?WeakSet:Set;function Z1(v){var D=v.ref;if(D!==null)if(typeof D==\"function\")try{D(null)}catch(Q){Qf(v,Q)}else D.current=null}function Ry(v,D){switch(D.tag){case 0:case 11:case 15:case 22:return;case 1:if(D.flags&256&&v!==null){var Q=v.memoizedProps,H=v.memoizedState;v=D.stateNode,D=v.getSnapshotBeforeUpdate(D.elementType===D.type?Q:ko(D.type,Q),H),v.__reactInternalSnapshotBeforeUpdate=D}return;case 3:F&&D.flags&256&&Ns(D.stateNode.containerInfo);return;case 5:case 6:case 4:case 17:return}throw Error(c(163))}function kh(v,D){if(D=D.updateQueue,D=D!==null?D.lastEffect:null,D!==null){var Q=D=D.next;do{if((Q.tag&v)===v){var H=Q.destroy;Q.destroy=void 0,H!==void 0&&H()}Q=Q.next}while(Q!==D)}}function uP(v,D,Q){switch(Q.tag){case 0:case 11:case 15:case 22:if(D=Q.updateQueue,D=D!==null?D.lastEffect:null,D!==null){v=D=D.next;do{if((v.tag&3)===3){var H=v.create;v.destroy=H()}v=v.next}while(v!==D)}if(D=Q.updateQueue,D=D!==null?D.lastEffect:null,D!==null){v=D=D.next;do{var V=v;H=V.next,V=V.tag,V&4&&V&1&&(vP(Q,v),ML(Q,v)),v=H}while(v!==D)}return;case 1:v=Q.stateNode,Q.flags&4&&(D===null?v.componentDidMount():(H=Q.elementType===Q.type?D.memoizedProps:ko(Q.type,D.memoizedProps),v.componentDidUpdate(H,D.memoizedState,v.__reactInternalSnapshotBeforeUpdate))),D=Q.updateQueue,D!==null&&vy(Q,D,v);return;case 3:if(D=Q.updateQueue,D!==null){if(v=null,Q.child!==null)switch(Q.child.tag){case 5:v=Qe(Q.child.stateNode);break;case 1:v=Q.child.stateNode}vy(Q,D,v)}return;case 5:v=Q.stateNode,D===null&&Q.flags&4&&so(v,Q.type,Q.memoizedProps,Q);return;case 6:return;case 4:return;case 12:return;case 13:Z&&Q.memoizedState===null&&(Q=Q.alternate,Q!==null&&(Q=Q.memoizedState,Q!==null&&(Q=Q.dehydrated,Q!==null&&lu(Q))));return;case 19:case 17:case 20:case 21:case 23:case 24:return}throw Error(c(163))}function fP(v,D){if(F)for(var Q=v;;){if(Q.tag===5){var H=Q.stateNode;D?hh(H):ao(Q.stateNode,Q.memoizedProps)}else if(Q.tag===6)H=Q.stateNode,D?gh(H):Gn(H,Q.memoizedProps);else if((Q.tag!==23&&Q.tag!==24||Q.memoizedState===null||Q===v)&&Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===v)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===v)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}}function Ty(v,D){if(Va&&typeof Va.onCommitFiberUnmount==\"function\")try{Va.onCommitFiberUnmount($e,D)}catch{}switch(D.tag){case 0:case 11:case 14:case 15:case 22:if(v=D.updateQueue,v!==null&&(v=v.lastEffect,v!==null)){var Q=v=v.next;do{var H=Q,V=H.destroy;if(H=H.tag,V!==void 0)if(H&4)vP(D,Q);else{H=D;try{V()}catch(ne){Qf(H,ne)}}Q=Q.next}while(Q!==v)}break;case 1:if(Z1(D),v=D.stateNode,typeof v.componentWillUnmount==\"function\")try{v.props=D.memoizedProps,v.state=D.memoizedState,v.componentWillUnmount()}catch(ne){Qf(D,ne)}break;case 5:Z1(D);break;case 4:F?gP(v,D):z&&z&&(D=D.stateNode.containerInfo,v=iu(D),TA(D,v))}}function AP(v,D){for(var Q=D;;)if(Ty(v,Q),Q.child===null||F&&Q.tag===4){if(Q===D)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===D)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}else Q.child.return=Q,Q=Q.child}function Fy(v){v.alternate=null,v.child=null,v.dependencies=null,v.firstEffect=null,v.lastEffect=null,v.memoizedProps=null,v.memoizedState=null,v.pendingProps=null,v.return=null,v.updateQueue=null}function pP(v){return v.tag===5||v.tag===3||v.tag===4}function hP(v){if(F){e:{for(var D=v.return;D!==null;){if(pP(D))break e;D=D.return}throw Error(c(160))}var Q=D;switch(D=Q.stateNode,Q.tag){case 5:var H=!1;break;case 3:D=D.containerInfo,H=!0;break;case 4:D=D.containerInfo,H=!0;break;default:throw Error(c(161))}Q.flags&16&&(hf(D),Q.flags&=-17);e:t:for(Q=v;;){for(;Q.sibling===null;){if(Q.return===null||pP(Q.return)){Q=null;break e}Q=Q.return}for(Q.sibling.return=Q.return,Q=Q.sibling;Q.tag!==5&&Q.tag!==6&&Q.tag!==18;){if(Q.flags&2||Q.child===null||Q.tag===4)continue t;Q.child.return=Q,Q=Q.child}if(!(Q.flags&2)){Q=Q.stateNode;break e}}H?X1(v,Q,D):$1(v,Q,D)}}function X1(v,D,Q){var H=v.tag,V=H===5||H===6;if(V)v=V?v.stateNode:v.stateNode.instance,D?oo(Q,v,D):So(Q,v);else if(H!==4&&(v=v.child,v!==null))for(X1(v,D,Q),v=v.sibling;v!==null;)X1(v,D,Q),v=v.sibling}function $1(v,D,Q){var H=v.tag,V=H===5||H===6;if(V)v=V?v.stateNode:v.stateNode.instance,D?ji(Q,v,D):li(Q,v);else if(H!==4&&(v=v.child,v!==null))for($1(v,D,Q),v=v.sibling;v!==null;)$1(v,D,Q),v=v.sibling}function gP(v,D){for(var Q=D,H=!1,V,ne;;){if(!H){H=Q.return;e:for(;;){if(H===null)throw Error(c(160));switch(V=H.stateNode,H.tag){case 5:ne=!1;break e;case 3:V=V.containerInfo,ne=!0;break e;case 4:V=V.containerInfo,ne=!0;break e}H=H.return}H=!0}if(Q.tag===5||Q.tag===6)AP(v,Q),ne?RA(V,Q.stateNode):bo(V,Q.stateNode);else if(Q.tag===4){if(Q.child!==null){V=Q.stateNode.containerInfo,ne=!0,Q.child.return=Q,Q=Q.child;continue}}else if(Ty(v,Q),Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===D)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===D)return;Q=Q.return,Q.tag===4&&(H=!1)}Q.sibling.return=Q.return,Q=Q.sibling}}function eB(v,D){if(F){switch(D.tag){case 0:case 11:case 14:case 15:case 22:kh(3,D);return;case 1:return;case 5:var Q=D.stateNode;if(Q!=null){var H=D.memoizedProps;v=v!==null?v.memoizedProps:H;var V=D.type,ne=D.updateQueue;D.updateQueue=null,ne!==null&&Do(Q,ne,V,v,H,D)}return;case 6:if(D.stateNode===null)throw Error(c(162));Q=D.memoizedProps,ns(D.stateNode,v!==null?v.memoizedProps:Q,Q);return;case 3:Z&&(D=D.stateNode,D.hydrate&&(D.hydrate=!1,LA(D.containerInfo)));return;case 12:return;case 13:dP(D),Yg(D);return;case 19:Yg(D);return;case 17:return;case 23:case 24:fP(D,D.memoizedState!==null);return}throw Error(c(163))}switch(D.tag){case 0:case 11:case 14:case 15:case 22:kh(3,D);return;case 12:return;case 13:dP(D),Yg(D);return;case 19:Yg(D);return;case 3:Z&&(Q=D.stateNode,Q.hydrate&&(Q.hydrate=!1,LA(Q.containerInfo)));break;case 23:case 24:return}e:if(z){switch(D.tag){case 1:case 5:case 6:case 20:break e;case 3:case 4:D=D.stateNode,TA(D.containerInfo,D.pendingChildren);break e}throw Error(c(163))}}function dP(v){v.memoizedState!==null&&(lB=bt(),F&&fP(v.child,!0))}function Yg(v){var D=v.updateQueue;if(D!==null){v.updateQueue=null;var Q=v.stateNode;Q===null&&(Q=v.stateNode=new xL),D.forEach(function(H){var V=_L.bind(null,v,H);Q.has(H)||(Q.add(H),H.then(V,V))})}}function kL(v,D){return v!==null&&(v=v.memoizedState,v===null||v.dehydrated!==null)?(D=D.memoizedState,D!==null&&D.dehydrated===null):!1}var Ny=0,Oy=1,Ly=2,Kg=3,My=4;if(typeof Symbol==\"function\"&&Symbol.for){var Jg=Symbol.for;Ny=Jg(\"selector.component\"),Oy=Jg(\"selector.has_pseudo_class\"),Ly=Jg(\"selector.role\"),Kg=Jg(\"selector.test_id\"),My=Jg(\"selector.text\")}function Uy(v){var D=$(v);if(D!=null){if(typeof D.memoizedProps[\"data-testname\"]!=\"string\")throw Error(c(364));return D}if(v=ir(v),v===null)throw Error(c(362));return v.stateNode.current}function bf(v,D){switch(D.$$typeof){case Ny:if(v.type===D.value)return!0;break;case Oy:e:{D=D.value,v=[v,0];for(var Q=0;Q<v.length;){var H=v[Q++],V=v[Q++],ne=D[V];if(H.tag!==5||!Pr(H)){for(;ne!=null&&bf(H,ne);)V++,ne=D[V];if(V===D.length){D=!0;break e}else for(H=H.child;H!==null;)v.push(H,V),H=H.sibling}}D=!1}return D;case Ly:if(v.tag===5&&Ir(v.stateNode,D.value))return!0;break;case My:if((v.tag===5||v.tag===6)&&(v=dn(v),v!==null&&0<=v.indexOf(D.value)))return!0;break;case Kg:if(v.tag===5&&(v=v.memoizedProps[\"data-testname\"],typeof v==\"string\"&&v.toLowerCase()===D.value.toLowerCase()))return!0;break;default:throw Error(c(365,D))}return!1}function Pf(v){switch(v.$$typeof){case Ny:return\"<\"+(g(v.value)||\"Unknown\")+\">\";case Oy:return\":has(\"+(Pf(v)||\"\")+\")\";case Ly:return'[role=\"'+v.value+'\"]';case My:return'\"'+v.value+'\"';case Kg:return'[data-testname=\"'+v.value+'\"]';default:throw Error(c(365,v))}}function tB(v,D){var Q=[];v=[v,0];for(var H=0;H<v.length;){var V=v[H++],ne=v[H++],ve=D[ne];if(V.tag!==5||!Pr(V)){for(;ve!=null&&bf(V,ve);)ne++,ve=D[ne];if(ne===D.length)Q.push(V);else for(V=V.child;V!==null;)v.push(V,ne),V=V.sibling}}return Q}function rB(v,D){if(!qt)throw Error(c(363));v=Uy(v),v=tB(v,D),D=[],v=Array.from(v);for(var Q=0;Q<v.length;){var H=v[Q++];if(H.tag===5)Pr(H)||D.push(H.stateNode);else for(H=H.child;H!==null;)v.push(H),H=H.sibling}return D}var _y=null;function QL(v){if(_y===null)try{var D=(\"require\"+Math.random()).slice(0,7);_y=(jS&&jS[D]).call(jS,\"timers\").setImmediate}catch{_y=function(H){var V=new MessageChannel;V.port1.onmessage=H,V.port2.postMessage(void 0)}}return _y(v)}var RL=Math.ceil,Hy=f.ReactCurrentDispatcher,nB=f.ReactCurrentOwner,iB=f.IsSomeRendererActing,xr=0,fo=null,Zi=null,Ms=0,$A=0,sB=co(0),Ss=0,jy=null,Qh=0,zg=0,Rh=0,oB=0,aB=null,lB=0,cB=1/0;function xf(){cB=bt()+500}var sr=null,Gy=!1,uB=null,gc=null,kf=!1,Zg=null,Xg=90,fB=[],AB=[],Iu=null,$g=0,pB=null,qy=-1,Cu=0,Wy=0,ed=null,td=!1;function No(){return xr&48?bt():qy!==-1?qy:qy=bt()}function Ds(v){if(v=v.mode,!(v&2))return 1;if(!(v&4))return tr()===99?1:2;if(Cu===0&&(Cu=Qh),Iy.transition!==0){Wy!==0&&(Wy=aB!==null?aB.pendingLanes:0),v=Cu;var D=4186112&~Wy;return D&=-D,D===0&&(v=4186112&~v,D=v&-v,D===0&&(D=8192)),D}return v=tr(),xr&4&&v===98?v=Mt(12,Cu):(v=MA(v),v=Mt(v,Cu)),v}function Ml(v,D,Q){if(50<$g)throw $g=0,pB=null,Error(c(185));if(v=Vy(v,D),v===null)return null;Ya(v,D,Q),v===fo&&(Rh|=D,Ss===4&&Th(v,Ms));var H=tr();D===1?xr&8&&!(xr&48)?hB(v):(Ea(v,Q),xr===0&&(xf(),Fn())):(!(xr&4)||H!==98&&H!==99||(Iu===null?Iu=new Set([v]):Iu.add(v)),Ea(v,Q)),aB=v}function Vy(v,D){v.lanes|=D;var Q=v.alternate;for(Q!==null&&(Q.lanes|=D),Q=v,v=v.return;v!==null;)v.childLanes|=D,Q=v.alternate,Q!==null&&(Q.childLanes|=D),Q=v,v=v.return;return Q.tag===3?Q.stateNode:null}function Ea(v,D){for(var Q=v.callbackNode,H=v.suspendedLanes,V=v.pingedLanes,ne=v.expirationTimes,ve=v.pendingLanes;0<ve;){var _e=31-is(ve),ht=1<<_e,Wt=ne[_e];if(Wt===-1){if(!(ht&H)||ht&V){Wt=D,pa(ht);var Sr=vn;ne[_e]=10<=Sr?Wt+250:6<=Sr?Wt+5e3:-1}}else Wt<=D&&(v.expiredLanes|=ht);ve&=~ht}if(H=ha(v,v===fo?Ms:0),D=vn,H===0)Q!==null&&(Q!==lr&&Bs(Q),v.callbackNode=null,v.callbackPriority=0);else{if(Q!==null){if(v.callbackPriority===D)return;Q!==lr&&Bs(Q)}D===15?(Q=hB.bind(null,v),ye===null?(ye=[Q],Oe=Mi(Tn,Ja)):ye.push(Q),Q=lr):D===14?Q=qi(99,hB.bind(null,v)):(Q=UA(D),Q=qi(Q,mP.bind(null,v))),v.callbackPriority=D,v.callbackNode=Q}}function mP(v){if(qy=-1,Wy=Cu=0,xr&48)throw Error(c(327));var D=v.callbackNode;if(wu()&&v.callbackNode!==D)return null;var Q=ha(v,v===fo?Ms:0);if(Q===0)return null;var H=Q,V=xr;xr|=16;var ne=CP();(fo!==v||Ms!==H)&&(xf(),Fh(v,H));do try{NL();break}catch(_e){IP(v,_e)}while(!0);if(Rg(),Hy.current=ne,xr=V,Zi!==null?H=0:(fo=null,Ms=0,H=Ss),Qh&Rh)Fh(v,0);else if(H!==0){if(H===2&&(xr|=64,v.hydrate&&(v.hydrate=!1,Ns(v.containerInfo)),Q=xl(v),Q!==0&&(H=rd(v,Q))),H===1)throw D=jy,Fh(v,0),Th(v,Q),Ea(v,bt()),D;switch(v.finishedWork=v.current.alternate,v.finishedLanes=Q,H){case 0:case 1:throw Error(c(345));case 2:ep(v);break;case 3:if(Th(v,Q),(Q&62914560)===Q&&(H=lB+500-bt(),10<H)){if(ha(v,0)!==0)break;if(V=v.suspendedLanes,(V&Q)!==Q){No(),v.pingedLanes|=v.suspendedLanes&V;break}v.timeoutHandle=P(ep.bind(null,v),H);break}ep(v);break;case 4:if(Th(v,Q),(Q&4186112)===Q)break;for(H=v.eventTimes,V=-1;0<Q;){var ve=31-is(Q);ne=1<<ve,ve=H[ve],ve>V&&(V=ve),Q&=~ne}if(Q=V,Q=bt()-Q,Q=(120>Q?120:480>Q?480:1080>Q?1080:1920>Q?1920:3e3>Q?3e3:4320>Q?4320:1960*RL(Q/1960))-Q,10<Q){v.timeoutHandle=P(ep.bind(null,v),Q);break}ep(v);break;case 5:ep(v);break;default:throw Error(c(329))}}return Ea(v,bt()),v.callbackNode===D?mP.bind(null,v):null}function Th(v,D){for(D&=~oB,D&=~Rh,v.suspendedLanes|=D,v.pingedLanes&=~D,v=v.expirationTimes;0<D;){var Q=31-is(D),H=1<<Q;v[Q]=-1,D&=~H}}function hB(v){if(xr&48)throw Error(c(327));if(wu(),v===fo&&v.expiredLanes&Ms){var D=Ms,Q=rd(v,D);Qh&Rh&&(D=ha(v,D),Q=rd(v,D))}else D=ha(v,0),Q=rd(v,D);if(v.tag!==0&&Q===2&&(xr|=64,v.hydrate&&(v.hydrate=!1,Ns(v.containerInfo)),D=xl(v),D!==0&&(Q=rd(v,D))),Q===1)throw Q=jy,Fh(v,0),Th(v,D),Ea(v,bt()),Q;return v.finishedWork=v.current.alternate,v.finishedLanes=D,ep(v),Ea(v,bt()),null}function TL(){if(Iu!==null){var v=Iu;Iu=null,v.forEach(function(D){D.expiredLanes|=24&D.pendingLanes,Ea(D,bt())})}Fn()}function yP(v,D){var Q=xr;xr|=1;try{return v(D)}finally{xr=Q,xr===0&&(xf(),Fn())}}function EP(v,D){var Q=xr;if(Q&48)return v(D);xr|=1;try{if(v)return ci(99,v.bind(null,D))}finally{xr=Q,Fn()}}function Yy(v,D){Qn(sB,$A),$A|=D,Qh|=D}function gB(){$A=sB.current,Tt(sB)}function Fh(v,D){v.finishedWork=null,v.finishedLanes=0;var Q=v.timeoutHandle;if(Q!==b&&(v.timeoutHandle=b,w(Q)),Zi!==null)for(Q=Zi.return;Q!==null;){var H=Q;switch(H.tag){case 1:H=H.type.childContextTypes,H!=null&&uu();break;case 3:hu(),Tt(Li),Tt(Gi),du();break;case 5:wt(H);break;case 4:hu();break;case 13:Tt(mi);break;case 19:Tt(mi);break;case 10:Fg(H);break;case 23:case 24:gB()}Q=Q.return}fo=v,Zi=Bu(v.current,null),Ms=$A=Qh=D,Ss=0,jy=null,oB=Rh=zg=0}function IP(v,D){do{var Q=Zi;try{if(Rg(),wf.current=kt,VA){for(var H=qn.memoizedState;H!==null;){var V=H.queue;V!==null&&(V.pending=null),H=H.next}VA=!1}if(mu=0,Pi=ss=qn=null,Bf=!1,nB.current=null,Q===null||Q.return===null){Ss=1,jy=D,Zi=null;break}e:{var ne=v,ve=Q.return,_e=Q,ht=D;if(D=Ms,_e.flags|=2048,_e.firstEffect=_e.lastEffect=null,ht!==null&&typeof ht==\"object\"&&typeof ht.then==\"function\"){var Wt=ht;if(!(_e.mode&2)){var Sr=_e.alternate;Sr?(_e.updateQueue=Sr.updateQueue,_e.memoizedState=Sr.memoizedState,_e.lanes=Sr.lanes):(_e.updateQueue=null,_e.memoizedState=null)}var Lr=(mi.current&1)!==0,Xt=ve;do{var Xn;if(Xn=Xt.tag===13){var Ei=Xt.memoizedState;if(Ei!==null)Xn=Ei.dehydrated!==null;else{var rl=Xt.memoizedProps;Xn=rl.fallback===void 0?!1:rl.unstable_avoidThisFallback!==!0?!0:!Lr}}if(Xn){var rt=Xt.updateQueue;if(rt===null){var We=new Set;We.add(Wt),Xt.updateQueue=We}else rt.add(Wt);if(!(Xt.mode&2)){if(Xt.flags|=64,_e.flags|=16384,_e.flags&=-2981,_e.tag===1)if(_e.alternate===null)_e.tag=17;else{var dt=Rl(-1,1);dt.tag=2,Tl(_e,dt)}_e.lanes|=1;break e}ht=void 0,_e=D;var Zt=ne.pingCache;if(Zt===null?(Zt=ne.pingCache=new PL,ht=new Set,Zt.set(Wt,ht)):(ht=Zt.get(Wt),ht===void 0&&(ht=new Set,Zt.set(Wt,ht))),!ht.has(_e)){ht.add(_e);var Dr=DP.bind(null,ne,Wt,_e);Wt.then(Dr,Dr)}Xt.flags|=4096,Xt.lanes=D;break e}Xt=Xt.return}while(Xt!==null);ht=Error((g(_e.type)||\"A React component\")+` suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.`)}Ss!==5&&(Ss=2),ht=qg(ht,_e),Xt=ve;do{switch(Xt.tag){case 3:ne=ht,Xt.flags|=4096,D&=-D,Xt.lanes|=D;var ti=z1(Xt,ne,D);By(Xt,ti);break e;case 1:ne=ht;var kr=Xt.type,Nn=Xt.stateNode;if(!(Xt.flags&64)&&(typeof kr.getDerivedStateFromError==\"function\"||Nn!==null&&typeof Nn.componentDidCatch==\"function\"&&(gc===null||!gc.has(Nn)))){Xt.flags|=4096,D&=-D,Xt.lanes|=D;var Hn=Vg(Xt,ne,D);By(Xt,Hn);break e}}Xt=Xt.return}while(Xt!==null)}BP(Q)}catch(zr){D=zr,Zi===Q&&Q!==null&&(Zi=Q=Q.return);continue}break}while(!0)}function CP(){var v=Hy.current;return Hy.current=kt,v===null?kt:v}function rd(v,D){var Q=xr;xr|=16;var H=CP();fo===v&&Ms===D||Fh(v,D);do try{FL();break}catch(V){IP(v,V)}while(!0);if(Rg(),xr=Q,Hy.current=H,Zi!==null)throw Error(c(261));return fo=null,Ms=0,Ss}function FL(){for(;Zi!==null;)wP(Zi)}function NL(){for(;Zi!==null&&!kl();)wP(Zi)}function wP(v){var D=bP(v.alternate,v,$A);v.memoizedProps=v.pendingProps,D===null?BP(v):Zi=D,nB.current=null}function BP(v){var D=v;do{var Q=D.alternate;if(v=D.return,D.flags&2048){if(Q=bL(D),Q!==null){Q.flags&=2047,Zi=Q;return}v!==null&&(v.firstEffect=v.lastEffect=null,v.flags|=2048)}else{if(Q=DL(Q,D,$A),Q!==null){Zi=Q;return}if(Q=D,Q.tag!==24&&Q.tag!==23||Q.memoizedState===null||$A&1073741824||!(Q.mode&4)){for(var H=0,V=Q.child;V!==null;)H|=V.lanes|V.childLanes,V=V.sibling;Q.childLanes=H}v!==null&&!(v.flags&2048)&&(v.firstEffect===null&&(v.firstEffect=D.firstEffect),D.lastEffect!==null&&(v.lastEffect!==null&&(v.lastEffect.nextEffect=D.firstEffect),v.lastEffect=D.lastEffect),1<D.flags&&(v.lastEffect!==null?v.lastEffect.nextEffect=D:v.firstEffect=D,v.lastEffect=D))}if(D=D.sibling,D!==null){Zi=D;return}Zi=D=v}while(D!==null);Ss===0&&(Ss=5)}function ep(v){var D=tr();return ci(99,OL.bind(null,v,D)),null}function OL(v,D){do wu();while(Zg!==null);if(xr&48)throw Error(c(327));var Q=v.finishedWork;if(Q===null)return null;if(v.finishedWork=null,v.finishedLanes=0,Q===v.current)throw Error(c(177));v.callbackNode=null;var H=Q.lanes|Q.childLanes,V=H,ne=v.pendingLanes&~V;v.pendingLanes=V,v.suspendedLanes=0,v.pingedLanes=0,v.expiredLanes&=V,v.mutableReadLanes&=V,v.entangledLanes&=V,V=v.entanglements;for(var ve=v.eventTimes,_e=v.expirationTimes;0<ne;){var ht=31-is(ne),Wt=1<<ht;V[ht]=0,ve[ht]=-1,_e[ht]=-1,ne&=~Wt}if(Iu!==null&&!(H&24)&&Iu.has(v)&&Iu.delete(v),v===fo&&(Zi=fo=null,Ms=0),1<Q.flags?Q.lastEffect!==null?(Q.lastEffect.nextEffect=Q,H=Q.firstEffect):H=Q:H=Q.firstEffect,H!==null){V=xr,xr|=32,nB.current=null,ed=tt(v.containerInfo),td=!1,sr=H;do try{LL()}catch(We){if(sr===null)throw Error(c(330));Qf(sr,We),sr=sr.nextEffect}while(sr!==null);ed=null,sr=H;do try{for(ve=v;sr!==null;){var Sr=sr.flags;if(Sr&16&&F&&hf(sr.stateNode),Sr&128){var Lr=sr.alternate;if(Lr!==null){var Xt=Lr.ref;Xt!==null&&(typeof Xt==\"function\"?Xt(null):Xt.current=null)}}switch(Sr&1038){case 2:hP(sr),sr.flags&=-3;break;case 6:hP(sr),sr.flags&=-3,eB(sr.alternate,sr);break;case 1024:sr.flags&=-1025;break;case 1028:sr.flags&=-1025,eB(sr.alternate,sr);break;case 4:eB(sr.alternate,sr);break;case 8:_e=ve,ne=sr,F?gP(_e,ne):AP(_e,ne);var Xn=ne.alternate;Fy(ne),Xn!==null&&Fy(Xn)}sr=sr.nextEffect}}catch(We){if(sr===null)throw Error(c(330));Qf(sr,We),sr=sr.nextEffect}while(sr!==null);td&&ut(),Ne(v.containerInfo),v.current=Q,sr=H;do try{for(Sr=v;sr!==null;){var Ei=sr.flags;if(Ei&36&&uP(Sr,sr.alternate,sr),Ei&128){Lr=void 0;var rl=sr.ref;if(rl!==null){var rt=sr.stateNode;switch(sr.tag){case 5:Lr=Qe(rt);break;default:Lr=rt}typeof rl==\"function\"?rl(Lr):rl.current=Lr}}sr=sr.nextEffect}}catch(We){if(sr===null)throw Error(c(330));Qf(sr,We),sr=sr.nextEffect}while(sr!==null);sr=null,ee(),xr=V}else v.current=Q;if(kf)kf=!1,Zg=v,Xg=D;else for(sr=H;sr!==null;)D=sr.nextEffect,sr.nextEffect=null,sr.flags&8&&(Ei=sr,Ei.sibling=null,Ei.stateNode=null),sr=D;if(H=v.pendingLanes,H===0&&(gc=null),H===1?v===pB?$g++:($g=0,pB=v):$g=0,Q=Q.stateNode,Va&&typeof Va.onCommitFiberRoot==\"function\")try{Va.onCommitFiberRoot($e,Q,void 0,(Q.current.flags&64)===64)}catch{}if(Ea(v,bt()),Gy)throw Gy=!1,v=uB,uB=null,v;return xr&8||Fn(),null}function LL(){for(;sr!==null;){var v=sr.alternate;td||ed===null||(sr.flags&8?De(sr,ed)&&(td=!0,Fe()):sr.tag===13&&kL(v,sr)&&De(sr,ed)&&(td=!0,Fe()));var D=sr.flags;D&256&&Ry(v,sr),!(D&512)||kf||(kf=!0,qi(97,function(){return wu(),null})),sr=sr.nextEffect}}function wu(){if(Xg!==90){var v=97<Xg?97:Xg;return Xg=90,ci(v,UL)}return!1}function ML(v,D){fB.push(D,v),kf||(kf=!0,qi(97,function(){return wu(),null}))}function vP(v,D){AB.push(D,v),kf||(kf=!0,qi(97,function(){return wu(),null}))}function UL(){if(Zg===null)return!1;var v=Zg;if(Zg=null,xr&48)throw Error(c(331));var D=xr;xr|=32;var Q=AB;AB=[];for(var H=0;H<Q.length;H+=2){var V=Q[H],ne=Q[H+1],ve=V.destroy;if(V.destroy=void 0,typeof ve==\"function\")try{ve()}catch(ht){if(ne===null)throw Error(c(330));Qf(ne,ht)}}for(Q=fB,fB=[],H=0;H<Q.length;H+=2){V=Q[H],ne=Q[H+1];try{var _e=V.create;V.destroy=_e()}catch(ht){if(ne===null)throw Error(c(330));Qf(ne,ht)}}for(_e=v.current.firstEffect;_e!==null;)v=_e.nextEffect,_e.nextEffect=null,_e.flags&8&&(_e.sibling=null,_e.stateNode=null),_e=v;return xr=D,Fn(),!0}function SP(v,D,Q){D=qg(Q,D),D=z1(v,D,1),Tl(v,D),D=No(),v=Vy(v,1),v!==null&&(Ya(v,1,D),Ea(v,D))}function Qf(v,D){if(v.tag===3)SP(v,v,D);else for(var Q=v.return;Q!==null;){if(Q.tag===3){SP(Q,v,D);break}else if(Q.tag===1){var H=Q.stateNode;if(typeof Q.type.getDerivedStateFromError==\"function\"||typeof H.componentDidCatch==\"function\"&&(gc===null||!gc.has(H))){v=qg(D,v);var V=Vg(Q,v,1);if(Tl(Q,V),V=No(),Q=Vy(Q,1),Q!==null)Ya(Q,1,V),Ea(Q,V);else if(typeof H.componentDidCatch==\"function\"&&(gc===null||!gc.has(H)))try{H.componentDidCatch(D,v)}catch{}break}}Q=Q.return}}function DP(v,D,Q){var H=v.pingCache;H!==null&&H.delete(D),D=No(),v.pingedLanes|=v.suspendedLanes&Q,fo===v&&(Ms&Q)===Q&&(Ss===4||Ss===3&&(Ms&62914560)===Ms&&500>bt()-lB?Fh(v,0):oB|=Q),Ea(v,D)}function _L(v,D){var Q=v.stateNode;Q!==null&&Q.delete(D),D=0,D===0&&(D=v.mode,D&2?D&4?(Cu===0&&(Cu=Qh),D=Rn(62914560&~Cu),D===0&&(D=4194304)):D=tr()===99?1:2:D=1),Q=No(),v=Vy(v,D),v!==null&&(Ya(v,D,Q),Ea(v,Q))}var bP;bP=function(v,D,Q){var H=D.lanes;if(v!==null)if(v.memoizedProps!==D.pendingProps||Li.current)Ke=!0;else if(Q&H)Ke=!!(v.flags&16384);else{switch(Ke=!1,D.tag){case 3:ky(D),_g();break;case 5:Cf(D);break;case 1:Zn(D.type)&&qa(D);break;case 4:Lg(D,D.stateNode.containerInfo);break;case 10:Tg(D,D.memoizedProps.value);break;case 13:if(D.memoizedState!==null)return Q&D.child.childLanes?K1(v,D,Q):(Qn(mi,mi.current&1),D=Wn(v,D,Q),D!==null?D.sibling:null);Qn(mi,mi.current&1);break;case 19:if(H=(Q&D.childLanes)!==0,v.flags&64){if(H)return cP(v,D,Q);D.flags|=64}var V=D.memoizedState;if(V!==null&&(V.rendering=null,V.tail=null,V.lastEffect=null),Qn(mi,mi.current),H)break;return null;case 23:case 24:return D.lanes=0,yi(v,D,Q)}return Wn(v,D,Q)}else Ke=!1;switch(D.lanes=0,D.tag){case 2:if(H=D.type,v!==null&&(v.alternate=null,D.alternate=null,D.flags|=2),v=D.pendingProps,V=mn(D,Gi.current),yf(D,Q),V=jg(null,D,H,v,V,Q),D.flags|=1,typeof V==\"object\"&&V!==null&&typeof V.render==\"function\"&&V.$$typeof===void 0){if(D.tag=1,D.memoizedState=null,D.updateQueue=null,Zn(H)){var ne=!0;qa(D)}else ne=!1;D.memoizedState=V.state!==null&&V.state!==void 0?V.state:null,Ch(D);var ve=H.getDerivedStateFromProps;typeof ve==\"function\"&&HA(D,H,ve,v),V.updater=jA,D.stateNode=V,V._reactInternals=D,Ro(D,H,v,Q),D=Y1(null,D,H,!0,ne,Q)}else D.tag=0,pt(null,D,V,Q),D=D.child;return D;case 16:V=D.elementType;e:{switch(v!==null&&(v.alternate=null,D.alternate=null,D.flags|=2),v=D.pendingProps,ne=V._init,V=ne(V._payload),D.type=V,ne=D.tag=jL(V),v=ko(V,v),ne){case 0:D=JA(null,D,V,v,Q);break e;case 1:D=lP(null,D,V,v,Q);break e;case 11:D=dr(null,D,V,v,Q);break e;case 14:D=vr(null,D,V,ko(V.type,v),H,Q);break e}throw Error(c(306,V,\"\"))}return D;case 0:return H=D.type,V=D.pendingProps,V=D.elementType===H?V:ko(H,V),JA(v,D,H,V,Q);case 1:return H=D.type,V=D.pendingProps,V=D.elementType===H?V:ko(H,V),lP(v,D,H,V,Q);case 3:if(ky(D),H=D.updateQueue,v===null||H===null)throw Error(c(282));if(H=D.pendingProps,V=D.memoizedState,V=V!==null?V.element:null,Ng(v,D),_A(D,H,null,Q),H=D.memoizedState.element,H===V)_g(),D=Wn(v,D,Q);else{if(V=D.stateNode,(ne=V.hydrate)&&(Z?(da=au(D.stateNode.containerInfo),Za=D,ne=Xa=!0):ne=!1),ne){if(Z&&(v=V.mutableSourceEagerHydrationData,v!=null))for(V=0;V<v.length;V+=2)ne=v[V],ve=v[V+1],y?ne._workInProgressVersionPrimary=ve:ne._workInProgressVersionSecondary=ve,gu.push(ne);for(Q=V1(D,null,H,Q),D.child=Q;Q;)Q.flags=Q.flags&-3|1024,Q=Q.sibling}else pt(v,D,H,Q),_g();D=D.child}return D;case 5:return Cf(D),v===null&&Ug(D),H=D.type,V=D.pendingProps,ne=v!==null?v.memoizedProps:null,ve=V.children,ct(H,V)?ve=null:ne!==null&&ct(H,ne)&&(D.flags|=16),vs(v,D),pt(v,D,ve,Q),D.child;case 6:return v===null&&Ug(D),null;case 13:return K1(v,D,Q);case 4:return Lg(D,D.stateNode.containerInfo),H=D.pendingProps,v===null?D.child=Og(D,null,H,Q):pt(v,D,H,Q),D.child;case 11:return H=D.type,V=D.pendingProps,V=D.elementType===H?V:ko(H,V),dr(v,D,H,V,Q);case 7:return pt(v,D,D.pendingProps,Q),D.child;case 8:return pt(v,D,D.pendingProps.children,Q),D.child;case 12:return pt(v,D,D.pendingProps.children,Q),D.child;case 10:e:{if(H=D.type._context,V=D.pendingProps,ve=D.memoizedProps,ne=V.value,Tg(D,ne),ve!==null){var _e=ve.value;if(ne=xo(_e,ne)?0:(typeof H._calculateChangedBits==\"function\"?H._calculateChangedBits(_e,ne):1073741823)|0,ne===0){if(ve.children===V.children&&!Li.current){D=Wn(v,D,Q);break e}}else for(_e=D.child,_e!==null&&(_e.return=D);_e!==null;){var ht=_e.dependencies;if(ht!==null){ve=_e.child;for(var Wt=ht.firstContext;Wt!==null;){if(Wt.context===H&&Wt.observedBits&ne){_e.tag===1&&(Wt=Rl(-1,Q&-Q),Wt.tag=2,Tl(_e,Wt)),_e.lanes|=Q,Wt=_e.alternate,Wt!==null&&(Wt.lanes|=Q),wy(_e.return,Q),ht.lanes|=Q;break}Wt=Wt.next}}else ve=_e.tag===10&&_e.type===D.type?null:_e.child;if(ve!==null)ve.return=_e;else for(ve=_e;ve!==null;){if(ve===D){ve=null;break}if(_e=ve.sibling,_e!==null){_e.return=ve.return,ve=_e;break}ve=ve.return}_e=ve}}pt(v,D,V.children,Q),D=D.child}return D;case 9:return V=D.type,ne=D.pendingProps,H=ne.children,yf(D,Q),V=Qo(V,ne.unstable_observedBits),H=H(V),D.flags|=1,pt(v,D,H,Q),D.child;case 14:return V=D.type,ne=ko(V,D.pendingProps),ne=ko(V.type,ne),vr(v,D,V,ne,H,Q);case 15:return _n(v,D,D.type,D.pendingProps,H,Q);case 17:return H=D.type,V=D.pendingProps,V=D.elementType===H?V:ko(H,V),v!==null&&(v.alternate=null,D.alternate=null,D.flags|=2),D.tag=1,Zn(H)?(v=!0,qa(D)):v=!1,yf(D,Q),xt(D,H,V),Ro(D,H,V,Q),Y1(null,D,H,!0,v,Q);case 19:return cP(v,D,Q);case 23:return yi(v,D,Q);case 24:return yi(v,D,Q)}throw Error(c(156,D.tag))};var Ky={current:!1},Us=n.unstable_flushAllWithoutAsserting,PP=typeof Us==\"function\";function dB(){if(Us!==void 0)return Us();for(var v=!1;wu();)v=!0;return v}function Ia(v){try{dB(),QL(function(){dB()?Ia(v):v()})}catch(D){v(D)}}var el=0,Jy=!1;function HL(v,D,Q,H){this.tag=v,this.key=Q,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=D,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=H,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function tl(v,D,Q,H){return new HL(v,D,Q,H)}function mB(v){return v=v.prototype,!(!v||!v.isReactComponent)}function jL(v){if(typeof v==\"function\")return mB(v)?1:0;if(v!=null){if(v=v.$$typeof,v===T)return 11;if(v===Y)return 14}return 2}function Bu(v,D){var Q=v.alternate;return Q===null?(Q=tl(v.tag,D,v.key,v.mode),Q.elementType=v.elementType,Q.type=v.type,Q.stateNode=v.stateNode,Q.alternate=v,v.alternate=Q):(Q.pendingProps=D,Q.type=v.type,Q.flags=0,Q.nextEffect=null,Q.firstEffect=null,Q.lastEffect=null),Q.childLanes=v.childLanes,Q.lanes=v.lanes,Q.child=v.child,Q.memoizedProps=v.memoizedProps,Q.memoizedState=v.memoizedState,Q.updateQueue=v.updateQueue,D=v.dependencies,Q.dependencies=D===null?null:{lanes:D.lanes,firstContext:D.firstContext},Q.sibling=v.sibling,Q.index=v.index,Q.ref=v.ref,Q}function nd(v,D,Q,H,V,ne){var ve=2;if(H=v,typeof v==\"function\")mB(v)&&(ve=1);else if(typeof v==\"string\")ve=5;else e:switch(v){case E:return Rf(Q.children,V,ne,D);case ue:ve=8,V|=16;break;case C:ve=8,V|=1;break;case S:return v=tl(12,Q,D,V|8),v.elementType=S,v.type=S,v.lanes=ne,v;case O:return v=tl(13,Q,D,V),v.type=O,v.elementType=O,v.lanes=ne,v;case U:return v=tl(19,Q,D,V),v.elementType=U,v.lanes=ne,v;case ae:return yB(Q,V,ne,D);case de:return v=tl(24,Q,D,V),v.elementType=de,v.lanes=ne,v;default:if(typeof v==\"object\"&&v!==null)switch(v.$$typeof){case x:ve=10;break e;case I:ve=9;break e;case T:ve=11;break e;case Y:ve=14;break e;case te:ve=16,H=null;break e;case ie:ve=22;break e}throw Error(c(130,v==null?v:typeof v,\"\"))}return D=tl(ve,Q,D,V),D.elementType=v,D.type=H,D.lanes=ne,D}function Rf(v,D,Q,H){return v=tl(7,v,H,D),v.lanes=Q,v}function yB(v,D,Q,H){return v=tl(23,v,H,D),v.elementType=ae,v.lanes=Q,v}function EB(v,D,Q){return v=tl(6,v,null,D),v.lanes=Q,v}function Oo(v,D,Q){return D=tl(4,v.children!==null?v.children:[],v.key,D),D.lanes=Q,D.stateNode={containerInfo:v.containerInfo,pendingChildren:null,implementation:v.implementation},D}function qL(v,D,Q){this.tag=D,this.containerInfo=v,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=b,this.pendingContext=this.context=null,this.hydrate=Q,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=ga(0),this.expirationTimes=ga(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=ga(0),Z&&(this.mutableSourceEagerHydrationData=null)}function xP(v){var D=v._reactInternals;if(D===void 0)throw typeof v.render==\"function\"?Error(c(188)):Error(c(268,Object.keys(v)));return v=ce(D),v===null?null:v.stateNode}function kP(v,D){if(v=v.memoizedState,v!==null&&v.dehydrated!==null){var Q=v.retryLane;v.retryLane=Q!==0&&Q<D?Q:D}}function zy(v,D){kP(v,D),(v=v.alternate)&&kP(v,D)}function WL(v){return v=ce(v),v===null?null:v.stateNode}function VL(){return null}return r.IsThisRendererActing=Ky,r.act=function(v){function D(){el--,iB.current=Q,Ky.current=H}Jy===!1&&(Jy=!0,console.error(\"act(...) is not supported in production builds of React, and might not behave as expected.\")),el++;var Q=iB.current,H=Ky.current;iB.current=!0,Ky.current=!0;try{var V=yP(v)}catch(ne){throw D(),ne}if(V!==null&&typeof V==\"object\"&&typeof V.then==\"function\")return{then:function(ne,ve){V.then(function(){1<el||PP===!0&&Q===!0?(D(),ne()):Ia(function(_e){D(),_e?ve(_e):ne()})},function(_e){D(),ve(_e)})}};try{el!==1||PP!==!1&&Q!==!1||dB(),D()}catch(ne){throw D(),ne}return{then:function(ne){ne()}}},r.attemptContinuousHydration=function(v){if(v.tag===13){var D=No();Ml(v,67108864,D),zy(v,67108864)}},r.attemptHydrationAtCurrentPriority=function(v){if(v.tag===13){var D=No(),Q=Ds(v);Ml(v,Q,D),zy(v,Q)}},r.attemptSynchronousHydration=function(v){switch(v.tag){case 3:var D=v.stateNode;if(D.hydrate){var Q=pa(D.pendingLanes);D.expiredLanes|=Q&D.pendingLanes,Ea(D,bt()),!(xr&48)&&(xf(),Fn())}break;case 13:var H=No();EP(function(){return Ml(v,1,H)}),zy(v,4)}},r.attemptUserBlockingHydration=function(v){if(v.tag===13){var D=No();Ml(v,4,D),zy(v,4)}},r.batchedEventUpdates=function(v,D){var Q=xr;xr|=2;try{return v(D)}finally{xr=Q,xr===0&&(xf(),Fn())}},r.batchedUpdates=yP,r.createComponentSelector=function(v){return{$$typeof:Ny,value:v}},r.createContainer=function(v,D,Q){return v=new qL(v,D,Q),D=tl(3,null,null,D===2?7:D===1?3:0),v.current=D,D.stateNode=v,Ch(D),v},r.createHasPsuedoClassSelector=function(v){return{$$typeof:Oy,value:v}},r.createPortal=function(v,D,Q){var H=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:h,key:H==null?null:\"\"+H,children:v,containerInfo:D,implementation:Q}},r.createRoleSelector=function(v){return{$$typeof:Ly,value:v}},r.createTestNameSelector=function(v){return{$$typeof:Kg,value:v}},r.createTextSelector=function(v){return{$$typeof:My,value:v}},r.deferredUpdates=function(v){return ci(97,v)},r.discreteUpdates=function(v,D,Q,H,V){var ne=xr;xr|=4;try{return ci(98,v.bind(null,D,Q,H,V))}finally{xr=ne,xr===0&&(xf(),Fn())}},r.findAllNodes=rB,r.findBoundingRects=function(v,D){if(!qt)throw Error(c(363));D=rB(v,D),v=[];for(var Q=0;Q<D.length;Q++)v.push(Pt(D[Q]));for(D=v.length-1;0<D;D--){Q=v[D];for(var H=Q.x,V=H+Q.width,ne=Q.y,ve=ne+Q.height,_e=D-1;0<=_e;_e--)if(D!==_e){var ht=v[_e],Wt=ht.x,Sr=Wt+ht.width,Lr=ht.y,Xt=Lr+ht.height;if(H>=Wt&&ne>=Lr&&V<=Sr&&ve<=Xt){v.splice(D,1);break}else if(H!==Wt||Q.width!==ht.width||Xt<ne||Lr>ve){if(!(ne!==Lr||Q.height!==ht.height||Sr<H||Wt>V)){Wt>H&&(ht.width+=Wt-H,ht.x=H),Sr<V&&(ht.width=V-Wt),v.splice(D,1);break}}else{Lr>ne&&(ht.height+=Lr-ne,ht.y=ne),Xt<ve&&(ht.height=ve-Lr),v.splice(D,1);break}}}return v},r.findHostInstance=xP,r.findHostInstanceWithNoPortals=function(v){return v=X(v),v===null?null:v.tag===20?v.stateNode.instance:v.stateNode},r.findHostInstanceWithWarning=function(v){return xP(v)},r.flushControlled=function(v){var D=xr;xr|=1;try{ci(99,v)}finally{xr=D,xr===0&&(xf(),Fn())}},r.flushDiscreteUpdates=function(){!(xr&49)&&(TL(),wu())},r.flushPassiveEffects=wu,r.flushSync=EP,r.focusWithin=function(v,D){if(!qt)throw Error(c(363));for(v=Uy(v),D=tB(v,D),D=Array.from(D),v=0;v<D.length;){var Q=D[v++];if(!Pr(Q)){if(Q.tag===5&&Or(Q.stateNode))return!0;for(Q=Q.child;Q!==null;)D.push(Q),Q=Q.sibling}}return!1},r.getCurrentUpdateLanePriority=function(){return cc},r.getFindAllNodesFailureDescription=function(v,D){if(!qt)throw Error(c(363));var Q=0,H=[];v=[Uy(v),0];for(var V=0;V<v.length;){var ne=v[V++],ve=v[V++],_e=D[ve];if((ne.tag!==5||!Pr(ne))&&(bf(ne,_e)&&(H.push(Pf(_e)),ve++,ve>Q&&(Q=ve)),ve<D.length))for(ne=ne.child;ne!==null;)v.push(ne,ve),ne=ne.sibling}if(Q<D.length){for(v=[];Q<D.length;Q++)v.push(Pf(D[Q]));return`findAllNodes was able to match part of the selector:\n  `+(H.join(\" > \")+`\n\nNo matching component was found for:\n  `)+v.join(\" > \")}return null},r.getPublicRootInstance=function(v){if(v=v.current,!v.child)return null;switch(v.child.tag){case 5:return Qe(v.child.stateNode);default:return v.child.stateNode}},r.injectIntoDevTools=function(v){if(v={bundleType:v.bundleType,version:v.version,rendererPackageName:v.rendererPackageName,rendererConfig:v.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:f.ReactCurrentDispatcher,findHostInstanceByFiber:WL,findFiberByHostInstance:v.findFiberByHostInstance||VL,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>\"u\")v=!1;else{var D=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!D.isDisabled&&D.supportsFiber)try{$e=D.inject(v),Va=D}catch{}v=!0}return v},r.observeVisibleRects=function(v,D,Q,H){if(!qt)throw Error(c(363));v=rB(v,D);var V=on(v,Q,H).disconnect;return{disconnect:function(){V()}}},r.registerMutableSourceForHydration=function(v,D){var Q=D._getVersion;Q=Q(D._source),v.mutableSourceEagerHydrationData==null?v.mutableSourceEagerHydrationData=[D,Q]:v.mutableSourceEagerHydrationData.push(D,Q)},r.runWithPriority=function(v,D){var Q=cc;try{return cc=v,D()}finally{cc=Q}},r.shouldSuspend=function(){return!1},r.unbatchedUpdates=function(v,D){var Q=xr;xr&=-2,xr|=8;try{return v(D)}finally{xr=Q,xr===0&&(xf(),Fn())}},r.updateContainer=function(v,D,Q,H){var V=D.current,ne=No(),ve=Ds(V);e:if(Q){Q=Q._reactInternals;t:{if(Se(Q)!==Q||Q.tag!==1)throw Error(c(170));var _e=Q;do{switch(_e.tag){case 3:_e=_e.stateNode.context;break t;case 1:if(Zn(_e.type)){_e=_e.stateNode.__reactInternalMemoizedMergedChildContext;break t}}_e=_e.return}while(_e!==null);throw Error(c(171))}if(Q.tag===1){var ht=Q.type;if(Zn(ht)){Q=Ga(Q,ht,_e);break e}}Q=_e}else Q=Aa;return D.context===null?D.context=Q:D.pendingContext=Q,D=Rl(ne,ve),D.payload={element:v},H=H===void 0?null:H,H!==null&&(D.callback=H),Tl(V,D),Ml(V,ve,ne),ve},r}});var AIe=G((PYt,fIe)=>{\"use strict\";fIe.exports=uIe()});var hIe=G((xYt,pIe)=>{\"use strict\";var Mut={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};pIe.exports=Mut});var yIe=G((kYt,mIe)=>{\"use strict\";var Uut=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var s in r)Object.prototype.hasOwnProperty.call(r,s)&&(e[s]=r[s])}return e},yF=function(){function e(t,r){for(var s=0;s<r.length;s++){var a=r[s];a.enumerable=a.enumerable||!1,a.configurable=!0,\"value\"in a&&(a.writable=!0),Object.defineProperty(t,a.key,a)}}return function(t,r,s){return r&&e(t.prototype,r),s&&e(t,s),t}}();function u9(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function f9(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}var nf=hIe(),_ut=function(){function e(t,r,s,a,n,c){f9(this,e),this.left=t,this.right=r,this.top=s,this.bottom=a,this.width=n,this.height=c}return yF(e,[{key:\"fromJS\",value:function(r){r(this.left,this.right,this.top,this.bottom,this.width,this.height)}},{key:\"toString\",value:function(){return\"<Layout#\"+this.left+\":\"+this.right+\";\"+this.top+\":\"+this.bottom+\";\"+this.width+\":\"+this.height+\">\"}}]),e}(),gIe=function(){yF(e,null,[{key:\"fromJS\",value:function(r){var s=r.width,a=r.height;return new e(s,a)}}]);function e(t,r){f9(this,e),this.width=t,this.height=r}return yF(e,[{key:\"fromJS\",value:function(r){r(this.width,this.height)}},{key:\"toString\",value:function(){return\"<Size#\"+this.width+\"x\"+this.height+\">\"}}]),e}(),dIe=function(){function e(t,r){f9(this,e),this.unit=t,this.value=r}return yF(e,[{key:\"fromJS\",value:function(r){r(this.unit,this.value)}},{key:\"toString\",value:function(){switch(this.unit){case nf.UNIT_POINT:return String(this.value);case nf.UNIT_PERCENT:return this.value+\"%\";case nf.UNIT_AUTO:return\"auto\";default:return this.value+\"?\"}}},{key:\"valueOf\",value:function(){return this.value}}]),e}();mIe.exports=function(e,t){function r(c,f,p){var h=c[f];c[f]=function(){for(var E=arguments.length,C=Array(E),S=0;S<E;S++)C[S]=arguments[S];return p.call.apply(p,[this,h].concat(C))}}for(var s=[\"setPosition\",\"setMargin\",\"setFlexBasis\",\"setWidth\",\"setHeight\",\"setMinWidth\",\"setMinHeight\",\"setMaxWidth\",\"setMaxHeight\",\"setPadding\"],a=function(){var f,p=s[n],h=(f={},u9(f,nf.UNIT_POINT,t.Node.prototype[p]),u9(f,nf.UNIT_PERCENT,t.Node.prototype[p+\"Percent\"]),u9(f,nf.UNIT_AUTO,t.Node.prototype[p+\"Auto\"]),f);r(t.Node.prototype,p,function(E){for(var C=arguments.length,S=Array(C>1?C-1:0),x=1;x<C;x++)S[x-1]=arguments[x];var I=S.pop(),T=void 0,O=void 0;if(I===\"auto\")T=nf.UNIT_AUTO,O=void 0;else if(I instanceof dIe)T=I.unit,O=I.valueOf();else if(T=typeof I==\"string\"&&I.endsWith(\"%\")?nf.UNIT_PERCENT:nf.UNIT_POINT,O=parseFloat(I),!Number.isNaN(I)&&Number.isNaN(O))throw new Error(\"Invalid value \"+I+\" for \"+p);if(!h[T])throw new Error('Failed to execute \"'+p+`\": Unsupported unit '`+I+\"'\");if(O!==void 0){var U;return(U=h[T]).call.apply(U,[this].concat(S,[O]))}else{var Y;return(Y=h[T]).call.apply(Y,[this].concat(S))}})},n=0;n<s.length;n++)a();return r(t.Config.prototype,\"free\",function(){t.Config.destroy(this)}),r(t.Node,\"create\",function(c,f){return f?t.Node.createWithConfig(f):t.Node.createDefault()}),r(t.Node.prototype,\"free\",function(){t.Node.destroy(this)}),r(t.Node.prototype,\"freeRecursive\",function(){for(var c=0,f=this.getChildCount();c<f;++c)this.getChild(0).freeRecursive();this.free()}),r(t.Node.prototype,\"setMeasureFunc\",function(c,f){return f?c.call(this,function(){return gIe.fromJS(f.apply(void 0,arguments))}):this.unsetMeasureFunc()}),r(t.Node.prototype,\"calculateLayout\",function(c){var f=arguments.length>1&&arguments[1]!==void 0?arguments[1]:NaN,p=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,h=arguments.length>3&&arguments[3]!==void 0?arguments[3]:nf.DIRECTION_LTR;return c.call(this,f,p,h)}),Uut({Config:t.Config,Node:t.Node,Layout:e(\"Layout\",_ut),Size:e(\"Size\",gIe),Value:e(\"Value\",dIe),getInstanceCount:function(){return t.getInstanceCount.apply(t,arguments)}},nf)}});var EIe=G((exports,module)=>{(function(e,t){typeof define==\"function\"&&define.amd?define([],function(){return t}):typeof module==\"object\"&&module.exports?module.exports=t:(e.nbind=e.nbind||{}).init=t})(exports,function(Module,cb){typeof Module==\"function\"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(e,t){return function(){e&&e.apply(this,arguments);try{Module.ccall(\"nbind_init\")}catch(r){t(r);return}t(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module<\"u\"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT===\"WEB\")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT===\"WORKER\")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT===\"NODE\")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT===\"SHELL\")ENVIRONMENT_IS_SHELL=!0;else throw new Error(\"The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.\");else ENVIRONMENT_IS_WEB=typeof window==\"object\",ENVIRONMENT_IS_WORKER=typeof importScripts==\"function\",ENVIRONMENT_IS_NODE=typeof process==\"object\"&&typeof Ie==\"function\"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(t,r){nodeFS||(nodeFS={}(\"\")),nodePath||(nodePath={}(\"\")),t=nodePath.normalize(t);var s=nodeFS.readFileSync(t);return r?s:s.toString()},Module.readBinary=function(t){var r=Module.read(t,!0);return r.buffer||(r=new Uint8Array(r)),assert(r.buffer),r},Module.load=function(t){globalEval(read(t))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\\\/g,\"/\"):Module.thisProgram=\"unknown-program\"),Module.arguments=process.argv.slice(2),typeof module<\"u\"&&(module.exports=Module),Module.inspect=function(){return\"[Emscripten Module object]\"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr<\"u\"&&(Module.printErr=printErr),typeof read<\"u\"?Module.read=read:Module.read=function(){throw\"no read() available\"},Module.readBinary=function(t){if(typeof readbuffer==\"function\")return new Uint8Array(readbuffer(t));var r=read(t,\"binary\");return assert(typeof r==\"object\"),r},typeof scriptArgs<\"u\"?Module.arguments=scriptArgs:typeof arguments<\"u\"&&(Module.arguments=arguments),typeof quit==\"function\"&&(Module.quit=function(e,t){quit(e)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(t){var r=new XMLHttpRequest;return r.open(\"GET\",t,!1),r.send(null),r.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(t){var r=new XMLHttpRequest;return r.open(\"GET\",t,!1),r.responseType=\"arraybuffer\",r.send(null),new Uint8Array(r.response)}),Module.readAsync=function(t,r,s){var a=new XMLHttpRequest;a.open(\"GET\",t,!0),a.responseType=\"arraybuffer\",a.onload=function(){a.status==200||a.status==0&&a.response?r(a.response):s()},a.onerror=s,a.send(null)},typeof arguments<\"u\"&&(Module.arguments=arguments),typeof console<\"u\")Module.print||(Module.print=function(t){console.log(t)}),Module.printErr||(Module.printErr=function(t){console.warn(t)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump<\"u\"?function(e){dump(e)}:function(e){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle>\"u\"&&(Module.setWindowTitle=function(e){document.title=e})}else throw\"Unknown runtime environment. Where are we?\";function globalEval(e){eval.call(null,e)}!Module.load&&Module.read&&(Module.load=function(t){globalEval(Module.read(t))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram=\"./this.program\"),Module.quit||(Module.quit=function(e,t){throw t}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(e){return tempRet0=e,e},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(e){STACKTOP=e},getNativeTypeSize:function(e){switch(e){case\"i1\":case\"i8\":return 1;case\"i16\":return 2;case\"i32\":return 4;case\"i64\":return 8;case\"float\":return 4;case\"double\":return 8;default:{if(e[e.length-1]===\"*\")return Runtime.QUANTUM_SIZE;if(e[0]===\"i\"){var t=parseInt(e.substr(1));return assert(t%8===0),t/8}else return 0}}},getNativeFieldSize:function(e){return Math.max(Runtime.getNativeTypeSize(e),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(e,t){return t===\"double\"||t===\"i64\"?e&7&&(assert((e&7)===4),e+=4):assert((e&3)===0),e},getAlignSize:function(e,t,r){return!r&&(e==\"i64\"||e==\"double\")?8:e?Math.min(t||(e?Runtime.getNativeFieldSize(e):0),Runtime.QUANTUM_SIZE):Math.min(t,8)},dynCall:function(e,t,r){return r&&r.length?Module[\"dynCall_\"+e].apply(null,[t].concat(r)):Module[\"dynCall_\"+e].call(null,t)},functionPointers:[],addFunction:function(e){for(var t=0;t<Runtime.functionPointers.length;t++)if(!Runtime.functionPointers[t])return Runtime.functionPointers[t]=e,2*(1+t);throw\"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.\"},removeFunction:function(e){Runtime.functionPointers[(e-2)/2]=null},warnOnce:function(e){Runtime.warnOnce.shown||(Runtime.warnOnce.shown={}),Runtime.warnOnce.shown[e]||(Runtime.warnOnce.shown[e]=1,Module.printErr(e))},funcWrappers:{},getFuncWrapper:function(e,t){if(e){assert(t),Runtime.funcWrappers[t]||(Runtime.funcWrappers[t]={});var r=Runtime.funcWrappers[t];return r[e]||(t.length===1?r[e]=function(){return Runtime.dynCall(t,e)}:t.length===2?r[e]=function(a){return Runtime.dynCall(t,e,[a])}:r[e]=function(){return Runtime.dynCall(t,e,Array.prototype.slice.call(arguments))}),r[e]}},getCompilerSetting:function(e){throw\"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work\"},stackAlloc:function(e){var t=STACKTOP;return STACKTOP=STACKTOP+e|0,STACKTOP=STACKTOP+15&-16,t},staticAlloc:function(e){var t=STATICTOP;return STATICTOP=STATICTOP+e|0,STATICTOP=STATICTOP+15&-16,t},dynamicAlloc:function(e){var t=HEAP32[DYNAMICTOP_PTR>>2],r=(t+e+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=r,r>=TOTAL_MEMORY){var s=enlargeMemory();if(!s)return HEAP32[DYNAMICTOP_PTR>>2]=t,0}return t},alignMemory:function(e,t){var r=e=Math.ceil(e/(t||16))*(t||16);return r},makeBigInt:function(e,t,r){var s=r?+(e>>>0)+ +(t>>>0)*4294967296:+(e>>>0)+ +(t|0)*4294967296;return s},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(e,t){e||abort(\"Assertion failed: \"+t)}function getCFunc(ident){var func=Module[\"_\"+ident];if(!func)try{func=eval(\"_\"+ident)}catch(e){}return assert(func,\"Cannot call unknown function \"+ident+\" (perhaps LLVM optimizations or closure removed it?)\"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(e){var t=Runtime.stackAlloc(e.length);return writeArrayToMemory(e,t),t},stringToC:function(e){var t=0;if(e!=null&&e!==0){var r=(e.length<<2)+1;t=Runtime.stackAlloc(r),stringToUTF8(e,t,r)}return t}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(t,r,s,a,n){var c=getCFunc(t),f=[],p=0;if(a)for(var h=0;h<a.length;h++){var E=toC[s[h]];E?(p===0&&(p=Runtime.stackSave()),f[h]=E(a[h])):f[h]=a[h]}var C=c.apply(null,f);if(r===\"string\"&&(C=Pointer_stringify(C)),p!==0){if(n&&n.async){EmterpreterAsync.asyncFinalizers.push(function(){Runtime.stackRestore(p)});return}Runtime.stackRestore(p)}return C};var sourceRegex=/^function\\s*[a-zA-Z$_0-9]*\\s*\\(([^)]*)\\)\\s*{\\s*([^*]*?)[\\s;]*(?:return\\s*(.*?)[;\\s]*)?}$/;function parseJSFunc(e){var t=e.toString().match(sourceRegex).slice(1);return{arguments:t[0],body:t[1],returnValue:t[2]}}var JSsource=null;function ensureJSsource(){if(!JSsource){JSsource={};for(var e in JSfuncs)JSfuncs.hasOwnProperty(e)&&(JSsource[e]=parseJSFunc(JSfuncs[e]))}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident),numericArgs=argTypes.every(function(e){return e===\"number\"}),numericRet=returnType!==\"string\";if(numericRet&&numericArgs)return cfunc;var argNames=argTypes.map(function(e,t){return\"$\"+t}),funcstr=\"(function(\"+argNames.join(\",\")+\") {\",nargs=argTypes.length;if(!numericArgs){ensureJSsource(),funcstr+=\"var stack = \"+JSsource.stackSave.body+\";\";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type!==\"number\"){var convertCode=JSsource[type+\"ToC\"];funcstr+=\"var \"+convertCode.arguments+\" = \"+arg+\";\",funcstr+=convertCode.body+\";\",funcstr+=arg+\"=(\"+convertCode.returnValue+\");\"}}}var cfuncname=parseJSFunc(function(){return cfunc}).returnValue;if(funcstr+=\"var ret = \"+cfuncname+\"(\"+argNames.join(\",\")+\");\",!numericRet){var strgfy=parseJSFunc(function(){return Pointer_stringify}).returnValue;funcstr+=\"ret = \"+strgfy+\"(ret);\"}return numericArgs||(ensureJSsource(),funcstr+=JSsource.stackRestore.body.replace(\"()\",\"(stack)\")+\";\"),funcstr+=\"return ret})\",eval(funcstr)}})(),Module.ccall=ccall,Module.cwrap=cwrap;function setValue(e,t,r,s){switch(r=r||\"i8\",r.charAt(r.length-1)===\"*\"&&(r=\"i32\"),r){case\"i1\":HEAP8[e>>0]=t;break;case\"i8\":HEAP8[e>>0]=t;break;case\"i16\":HEAP16[e>>1]=t;break;case\"i32\":HEAP32[e>>2]=t;break;case\"i64\":tempI64=[t>>>0,(tempDouble=t,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[e>>2]=tempI64[0],HEAP32[e+4>>2]=tempI64[1];break;case\"float\":HEAPF32[e>>2]=t;break;case\"double\":HEAPF64[e>>3]=t;break;default:abort(\"invalid type for setValue: \"+r)}}Module.setValue=setValue;function getValue(e,t,r){switch(t=t||\"i8\",t.charAt(t.length-1)===\"*\"&&(t=\"i32\"),t){case\"i1\":return HEAP8[e>>0];case\"i8\":return HEAP8[e>>0];case\"i16\":return HEAP16[e>>1];case\"i32\":return HEAP32[e>>2];case\"i64\":return HEAP32[e>>2];case\"float\":return HEAPF32[e>>2];case\"double\":return HEAPF64[e>>3];default:abort(\"invalid type for setValue: \"+t)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(e,t,r,s){var a,n;typeof e==\"number\"?(a=!0,n=e):(a=!1,n=e.length);var c=typeof t==\"string\"?t:null,f;if(r==ALLOC_NONE?f=s:f=[typeof _malloc==\"function\"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][r===void 0?ALLOC_STATIC:r](Math.max(n,c?1:t.length)),a){var s=f,p;for(assert((f&3)==0),p=f+(n&-4);s<p;s+=4)HEAP32[s>>2]=0;for(p=f+n;s<p;)HEAP8[s++>>0]=0;return f}if(c===\"i8\")return e.subarray||e.slice?HEAPU8.set(e,f):HEAPU8.set(new Uint8Array(e),f),f;for(var h=0,E,C,S;h<n;){var x=e[h];if(typeof x==\"function\"&&(x=Runtime.getFunctionIndex(x)),E=c||t[h],E===0){h++;continue}E==\"i64\"&&(E=\"i32\"),setValue(f+h,x,E),S!==E&&(C=Runtime.getNativeTypeSize(E),S=E),h+=C}return f}Module.allocate=allocate;function getMemory(e){return staticSealed?runtimeInitialized?_malloc(e):Runtime.dynamicAlloc(e):Runtime.staticAlloc(e)}Module.getMemory=getMemory;function Pointer_stringify(e,t){if(t===0||!e)return\"\";for(var r=0,s,a=0;s=HEAPU8[e+a>>0],r|=s,!(s==0&&!t||(a++,t&&a==t)););t||(t=a);var n=\"\";if(r<128){for(var c=1024,f;t>0;)f=String.fromCharCode.apply(String,HEAPU8.subarray(e,e+Math.min(t,c))),n=n?n+f:f,e+=c,t-=c;return n}return Module.UTF8ToString(e)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(e){for(var t=\"\";;){var r=HEAP8[e++>>0];if(!r)return t;t+=String.fromCharCode(r)}}Module.AsciiToString=AsciiToString;function stringToAscii(e,t){return writeAsciiToMemory(e,t,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder<\"u\"?new TextDecoder(\"utf8\"):void 0;function UTF8ArrayToString(e,t){for(var r=t;e[r];)++r;if(r-t>16&&e.subarray&&UTF8Decoder)return UTF8Decoder.decode(e.subarray(t,r));for(var s,a,n,c,f,p,h=\"\";;){if(s=e[t++],!s)return h;if(!(s&128)){h+=String.fromCharCode(s);continue}if(a=e[t++]&63,(s&224)==192){h+=String.fromCharCode((s&31)<<6|a);continue}if(n=e[t++]&63,(s&240)==224?s=(s&15)<<12|a<<6|n:(c=e[t++]&63,(s&248)==240?s=(s&7)<<18|a<<12|n<<6|c:(f=e[t++]&63,(s&252)==248?s=(s&3)<<24|a<<18|n<<12|c<<6|f:(p=e[t++]&63,s=(s&1)<<30|a<<24|n<<18|c<<12|f<<6|p))),s<65536)h+=String.fromCharCode(s);else{var E=s-65536;h+=String.fromCharCode(55296|E>>10,56320|E&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(e){return UTF8ArrayToString(HEAPU8,e)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(e,t,r,s){if(!(s>0))return 0;for(var a=r,n=r+s-1,c=0;c<e.length;++c){var f=e.charCodeAt(c);if(f>=55296&&f<=57343&&(f=65536+((f&1023)<<10)|e.charCodeAt(++c)&1023),f<=127){if(r>=n)break;t[r++]=f}else if(f<=2047){if(r+1>=n)break;t[r++]=192|f>>6,t[r++]=128|f&63}else if(f<=65535){if(r+2>=n)break;t[r++]=224|f>>12,t[r++]=128|f>>6&63,t[r++]=128|f&63}else if(f<=2097151){if(r+3>=n)break;t[r++]=240|f>>18,t[r++]=128|f>>12&63,t[r++]=128|f>>6&63,t[r++]=128|f&63}else if(f<=67108863){if(r+4>=n)break;t[r++]=248|f>>24,t[r++]=128|f>>18&63,t[r++]=128|f>>12&63,t[r++]=128|f>>6&63,t[r++]=128|f&63}else{if(r+5>=n)break;t[r++]=252|f>>30,t[r++]=128|f>>24&63,t[r++]=128|f>>18&63,t[r++]=128|f>>12&63,t[r++]=128|f>>6&63,t[r++]=128|f&63}}return t[r]=0,r-a}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(e,t,r){return stringToUTF8Array(e,HEAPU8,t,r)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(e){for(var t=0,r=0;r<e.length;++r){var s=e.charCodeAt(r);s>=55296&&s<=57343&&(s=65536+((s&1023)<<10)|e.charCodeAt(++r)&1023),s<=127?++t:s<=2047?t+=2:s<=65535?t+=3:s<=2097151?t+=4:s<=67108863?t+=5:t+=6}return t}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder<\"u\"?new TextDecoder(\"utf-16le\"):void 0;function demangle(e){var t=Module.___cxa_demangle||Module.__cxa_demangle;if(t){try{var r=e.substr(1),s=lengthBytesUTF8(r)+1,a=_malloc(s);stringToUTF8(r,a,s);var n=_malloc(4),c=t(a,0,0,n);if(getValue(n,\"i32\")===0&&c)return Pointer_stringify(c)}catch{}finally{a&&_free(a),n&&_free(n),c&&_free(c)}return e}return Runtime.warnOnce(\"warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling\"),e}function demangleAll(e){var t=/__Z[\\w\\d_]+/g;return e.replace(t,function(r){var s=demangle(r);return r===s?r:r+\" [\"+s+\"]\"})}function jsStackTrace(){var e=new Error;if(!e.stack){try{throw new Error(0)}catch(t){e=t}if(!e.stack)return\"(no stack trace available)\"}return e.stack.toString()}function stackTrace(){var e=jsStackTrace();return Module.extraStackTrace&&(e+=`\n`+Module.extraStackTrace()),demangleAll(e)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort(\"Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value \"+TOTAL_MEMORY+\", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 \")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY<TOTAL_STACK&&Module.printErr(\"TOTAL_MEMORY should be larger than TOTAL_STACK, was \"+TOTAL_MEMORY+\"! (TOTAL_STACK=\"+TOTAL_STACK+\")\"),Module.buffer?buffer=Module.buffer:buffer=new ArrayBuffer(TOTAL_MEMORY),updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}if(HEAP32[0]=1668509029,HEAP16[1]=25459,HEAPU8[2]!==115||HEAPU8[3]!==99)throw\"Runtime error: expected the system to be little-endian!\";Module.HEAP=HEAP,Module.buffer=buffer,Module.HEAP8=HEAP8,Module.HEAP16=HEAP16,Module.HEAP32=HEAP32,Module.HEAPU8=HEAPU8,Module.HEAPU16=HEAPU16,Module.HEAPU32=HEAPU32,Module.HEAPF32=HEAPF32,Module.HEAPF64=HEAPF64;function callRuntimeCallbacks(e){for(;e.length>0;){var t=e.shift();if(typeof t==\"function\"){t();continue}var r=t.func;typeof r==\"number\"?t.arg===void 0?Module.dynCall_v(r):Module.dynCall_vi(r,t.arg):r(t.arg===void 0?null:t.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun==\"function\"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun==\"function\"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(e){__ATPRERUN__.unshift(e)}Module.addOnPreRun=addOnPreRun;function addOnInit(e){__ATINIT__.unshift(e)}Module.addOnInit=addOnInit;function addOnPreMain(e){__ATMAIN__.unshift(e)}Module.addOnPreMain=addOnPreMain;function addOnExit(e){__ATEXIT__.unshift(e)}Module.addOnExit=addOnExit;function addOnPostRun(e){__ATPOSTRUN__.unshift(e)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(e,t,r){var s=r>0?r:lengthBytesUTF8(e)+1,a=new Array(s),n=stringToUTF8Array(e,a,0,a.length);return t&&(a.length=n),a}Module.intArrayFromString=intArrayFromString;function intArrayToString(e){for(var t=[],r=0;r<e.length;r++){var s=e[r];s>255&&(s&=255),t.push(String.fromCharCode(s))}return t.join(\"\")}Module.intArrayToString=intArrayToString;function writeStringToMemory(e,t,r){Runtime.warnOnce(\"writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!\");var s,a;r&&(a=t+lengthBytesUTF8(e),s=HEAP8[a]),stringToUTF8(e,t,1/0),r&&(HEAP8[a]=s)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(e,t){HEAP8.set(e,t)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(e,t,r){for(var s=0;s<e.length;++s)HEAP8[t++>>0]=e.charCodeAt(s);r||(HEAP8[t>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function e(t,r){var s=t>>>16,a=t&65535,n=r>>>16,c=r&65535;return a*c+(s*c+a*n<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(e){return froundBuffer[0]=e,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(e){e=e>>>0;for(var t=0;t<32;t++)if(e&1<<31-t)return t;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(e){return e<0?Math.ceil(e):Math.floor(e)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(e){return e}function addRunDependency(e){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(e){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var t=dependenciesFulfilled;dependenciesFulfilled=null,t()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(e,t,r,s,a,n,c,f){return _nbind.callbackSignatureList[e].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(e,t,r,s,a,n,c,f){return ASM_CONSTS[e](t,r,s,a,n,c,f)}function _emscripten_asm_const_iiiii(e,t,r,s,a){return ASM_CONSTS[e](t,r,s,a)}function _emscripten_asm_const_iiidddddd(e,t,r,s,a,n,c,f,p){return ASM_CONSTS[e](t,r,s,a,n,c,f,p)}function _emscripten_asm_const_iiididi(e,t,r,s,a,n,c){return ASM_CONSTS[e](t,r,s,a,n,c)}function _emscripten_asm_const_iiii(e,t,r,s){return ASM_CONSTS[e](t,r,s)}function _emscripten_asm_const_iiiid(e,t,r,s,a){return ASM_CONSTS[e](t,r,s,a)}function _emscripten_asm_const_iiiiii(e,t,r,s,a,n){return ASM_CONSTS[e](t,r,s,a,n)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],\"i8\",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(e,t){__ATEXIT__.unshift({func:e,arg:t})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr(\"missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj\"),abort(-1)}function __decorate(e,t,r,s){var a=arguments.length,n=a<3?t:s===null?s=Object.getOwnPropertyDescriptor(t,r):s,c;if(typeof Reflect==\"object\"&&typeof Reflect.decorate==\"function\")n=Reflect.decorate(e,t,r,s);else for(var f=e.length-1;f>=0;f--)(c=e[f])&&(n=(a<3?c(n):a>3?c(t,r,n):c(t,r))||n);return a>3&&n&&Object.defineProperty(t,r,n),n}function _defineHidden(e){return function(t,r){Object.defineProperty(t,r,{configurable:!1,enumerable:!1,value:e,writable:!0})}}var _nbind={};function __nbind_free_external(e){_nbind.externalList[e].dereference(e)}function __nbind_reference_external(e){_nbind.externalList[e].reference()}function _llvm_stackrestore(e){var t=_llvm_stacksave,r=t.LLVM_SAVEDSTACKS[e];t.LLVM_SAVEDSTACKS.splice(e,1),Runtime.stackRestore(r)}function __nbind_register_pool(e,t,r,s){_nbind.Pool.pageSize=e,_nbind.Pool.usedPtr=t/4,_nbind.Pool.rootPtr=r,_nbind.Pool.pagePtr=s/4,HEAP32[t/4]=16909060,HEAP8[t]==1&&(_nbind.bigEndian=!0),HEAP32[t/4]=0,_nbind.makeTypeKindTbl=(n={},n[1024]=_nbind.PrimitiveType,n[64]=_nbind.Int64Type,n[2048]=_nbind.BindClass,n[3072]=_nbind.BindClassPtr,n[4096]=_nbind.SharedClassPtr,n[5120]=_nbind.ArrayType,n[6144]=_nbind.ArrayType,n[7168]=_nbind.CStringType,n[9216]=_nbind.CallbackType,n[10240]=_nbind.BindType,n),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,\"cbFunction &\":_nbind.CallbackType,\"const cbFunction &\":_nbind.CallbackType,\"const std::string &\":_nbind.StringType,\"std::string\":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var a=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:\"\"});a.proto=Module,_nbind.BindClass.list.push(a);var n}function _emscripten_set_main_loop_timing(e,t){if(Browser.mainLoop.timingMode=e,Browser.mainLoop.timingValue=t,!Browser.mainLoop.func)return 1;if(e==0)Browser.mainLoop.scheduler=function(){var c=Math.max(0,Browser.mainLoop.tickStartTime+t-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,c)},Browser.mainLoop.method=\"timeout\";else if(e==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method=\"rAF\";else if(e==2){if(!window.setImmediate){let n=function(c){c.source===window&&c.data===s&&(c.stopPropagation(),r.shift()())};var a=n,r=[],s=\"setimmediate\";window.addEventListener(\"message\",n,!0),window.setImmediate=function(f){r.push(f),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(f),window.postMessage({target:s})):window.postMessage(s,\"*\")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method=\"immediate\"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(e,t,r,s,a){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,\"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.\"),Browser.mainLoop.func=e,Browser.mainLoop.arg=s;var n;typeof s<\"u\"?n=function(){Module.dynCall_vi(e,s)}:n=function(){Module.dynCall_v(e)};var c=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var p=Date.now(),h=Browser.mainLoop.queue.shift();if(h.func(h.arg),Browser.mainLoop.remainingBlockers){var E=Browser.mainLoop.remainingBlockers,C=E%1==0?E-1:Math.floor(E);h.counted?Browser.mainLoop.remainingBlockers=C:(C=C+.5,Browser.mainLoop.remainingBlockers=(8*E+C)/9)}if(console.log('main loop blocker \"'+h.name+'\" took '+(Date.now()-p)+\" ms\"),Browser.mainLoop.updateStatus(),c<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(!(c<Browser.mainLoop.currentlyRunningMainloop)){if(Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0,Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method===\"timeout\"&&Module.ctx&&(Module.printErr(\"Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!\"),Browser.mainLoop.method=\"\"),Browser.mainLoop.runIter(n),!(c<Browser.mainLoop.currentlyRunningMainloop)&&(typeof SDL==\"object\"&&SDL.audio&&SDL.audio.queueNewAudioData&&SDL.audio.queueNewAudioData(),Browser.mainLoop.scheduler())}}},a||(t&&t>0?_emscripten_set_main_loop_timing(0,1e3/t):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),r)throw\"SimulateInfiniteLoop\"}var Browser={mainLoop:{scheduler:null,method:\"\",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var e=Browser.mainLoop.timingMode,t=Browser.mainLoop.timingValue,r=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(r,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(e,t),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var e=Module.statusMessage||\"Please wait...\",t=Browser.mainLoop.remainingBlockers,r=Browser.mainLoop.expectedBlockers;t?t<r?Module.setStatus(e+\" (\"+(r-t)+\"/\"+r+\")\"):Module.setStatus(e):Module.setStatus(\"\")}},runIter:function(e){if(!ABORT){if(Module.preMainLoop){var t=Module.preMainLoop();if(t===!1)return}try{e()}catch(r){if(r instanceof ExitStatus)return;throw r&&typeof r==\"object\"&&r.stack&&Module.printErr(\"exception thrown: \"+[r,r.stack]),r}Module.postMainLoop&&Module.postMainLoop()}}},isFullscreen:!1,pointerLock:!1,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(Module.preloadPlugins||(Module.preloadPlugins=[]),Browser.initted)return;Browser.initted=!0;try{new Blob,Browser.hasBlobConstructor=!0}catch{Browser.hasBlobConstructor=!1,console.log(\"warning: no blob constructor, cannot create blobs with mimetypes\")}Browser.BlobBuilder=typeof MozBlobBuilder<\"u\"?MozBlobBuilder:typeof WebKitBlobBuilder<\"u\"?WebKitBlobBuilder:Browser.hasBlobConstructor?null:console.log(\"warning: no BlobBuilder\"),Browser.URLObject=typeof window<\"u\"?window.URL?window.URL:window.webkitURL:void 0,!Module.noImageDecoding&&typeof Browser.URLObject>\"u\"&&(console.log(\"warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.\"),Module.noImageDecoding=!0);var e={};e.canHandle=function(n){return!Module.noImageDecoding&&/\\.(jpg|jpeg|png|bmp)$/i.test(n)},e.handle=function(n,c,f,p){var h=null;if(Browser.hasBlobConstructor)try{h=new Blob([n],{type:Browser.getMimetype(c)}),h.size!==n.length&&(h=new Blob([new Uint8Array(n).buffer],{type:Browser.getMimetype(c)}))}catch(x){Runtime.warnOnce(\"Blob constructor present but fails: \"+x+\"; falling back to blob builder\")}if(!h){var E=new Browser.BlobBuilder;E.append(new Uint8Array(n).buffer),h=E.getBlob()}var C=Browser.URLObject.createObjectURL(h),S=new Image;S.onload=function(){assert(S.complete,\"Image \"+c+\" could not be decoded\");var I=document.createElement(\"canvas\");I.width=S.width,I.height=S.height;var T=I.getContext(\"2d\");T.drawImage(S,0,0),Module.preloadedImages[c]=I,Browser.URLObject.revokeObjectURL(C),f&&f(n)},S.onerror=function(I){console.log(\"Image \"+C+\" could not be decoded\"),p&&p()},S.src=C},Module.preloadPlugins.push(e);var t={};t.canHandle=function(n){return!Module.noAudioDecoding&&n.substr(-4)in{\".ogg\":1,\".wav\":1,\".mp3\":1}},t.handle=function(n,c,f,p){var h=!1;function E(T){h||(h=!0,Module.preloadedAudios[c]=T,f&&f(n))}function C(){h||(h=!0,Module.preloadedAudios[c]=new Audio,p&&p())}if(Browser.hasBlobConstructor){try{var S=new Blob([n],{type:Browser.getMimetype(c)})}catch{return C()}var x=Browser.URLObject.createObjectURL(S),I=new Audio;I.addEventListener(\"canplaythrough\",function(){E(I)},!1),I.onerror=function(O){if(h)return;console.log(\"warning: browser could not fully decode audio \"+c+\", trying slower base64 approach\");function U(Y){for(var te=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",ie=\"=\",ue=\"\",ae=0,de=0,Ae=0;Ae<Y.length;Ae++)for(ae=ae<<8|Y[Ae],de+=8;de>=6;){var Ce=ae>>de-6&63;de-=6,ue+=te[Ce]}return de==2?(ue+=te[(ae&3)<<4],ue+=ie+ie):de==4&&(ue+=te[(ae&15)<<2],ue+=ie),ue}I.src=\"data:audio/x-\"+c.substr(-3)+\";base64,\"+U(n),E(I)},I.src=x,Browser.safeSetTimeout(function(){E(I)},1e4)}else return C()},Module.preloadPlugins.push(t);function r(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var s=Module.canvas;s&&(s.requestPointerLock=s.requestPointerLock||s.mozRequestPointerLock||s.webkitRequestPointerLock||s.msRequestPointerLock||function(){},s.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},s.exitPointerLock=s.exitPointerLock.bind(document),document.addEventListener(\"pointerlockchange\",r,!1),document.addEventListener(\"mozpointerlockchange\",r,!1),document.addEventListener(\"webkitpointerlockchange\",r,!1),document.addEventListener(\"mspointerlockchange\",r,!1),Module.elementPointerLock&&s.addEventListener(\"click\",function(a){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),a.preventDefault())},!1))},createContext:function(e,t,r,s){if(t&&Module.ctx&&e==Module.canvas)return Module.ctx;var a,n;if(t){var c={antialias:!1,alpha:!1};if(s)for(var f in s)c[f]=s[f];n=GL.createContext(e,c),n&&(a=GL.getContext(n).GLctx)}else a=e.getContext(\"2d\");return a?(r&&(t||assert(typeof GLctx>\"u\",\"cannot set in module if GLctx is used, but we are a non-GL context that would replace it\"),Module.ctx=a,t&&GL.makeContextCurrent(n),Module.useWebGL=t,Browser.moduleContextCreatedCallbacks.forEach(function(p){p()}),Browser.init()),a):null},destroyContext:function(e,t,r){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(e,t,r){Browser.lockPointer=e,Browser.resizeCanvas=t,Browser.vrDevice=r,typeof Browser.lockPointer>\"u\"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas>\"u\"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice>\"u\"&&(Browser.vrDevice=null);var s=Module.canvas;function a(){Browser.isFullscreen=!1;var c=s.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===c?(s.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},s.exitFullscreen=s.exitFullscreen.bind(document),Browser.lockPointer&&s.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(c.parentNode.insertBefore(s,c),c.parentNode.removeChild(c),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(s)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener(\"fullscreenchange\",a,!1),document.addEventListener(\"mozfullscreenchange\",a,!1),document.addEventListener(\"webkitfullscreenchange\",a,!1),document.addEventListener(\"MSFullscreenChange\",a,!1));var n=document.createElement(\"div\");s.parentNode.insertBefore(n,s),n.appendChild(s),n.requestFullscreen=n.requestFullscreen||n.mozRequestFullScreen||n.msRequestFullscreen||(n.webkitRequestFullscreen?function(){n.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(n.webkitRequestFullScreen?function(){n.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),r?n.requestFullscreen({vrDisplay:r}):n.requestFullscreen()},requestFullScreen:function(e,t,r){return Module.printErr(\"Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.\"),Browser.requestFullScreen=function(s,a,n){return Browser.requestFullscreen(s,a,n)},Browser.requestFullscreen(e,t,r)},nextRAF:0,fakeRequestAnimationFrame:function(e){var t=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=t+1e3/60;else for(;t+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var r=Math.max(Browser.nextRAF-t,0);setTimeout(e,r)},requestAnimationFrame:function e(t){typeof window>\"u\"?Browser.fakeRequestAnimationFrame(t):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(t))},safeCallback:function(e){return function(){if(!ABORT)return e.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var e=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],e.forEach(function(t){t()})}},safeRequestAnimationFrame:function(e){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?e():Browser.queuedAsyncCallbacks.push(e))})},safeSetTimeout:function(e,t){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?e():Browser.queuedAsyncCallbacks.push(e))},t)},safeSetInterval:function(e,t){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&e()},t)},getMimetype:function(e){return{jpg:\"image/jpeg\",jpeg:\"image/jpeg\",png:\"image/png\",bmp:\"image/bmp\",ogg:\"audio/ogg\",wav:\"audio/wav\",mp3:\"audio/mpeg\"}[e.substr(e.lastIndexOf(\".\")+1)]},getUserMedia:function(e){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(e)},getMovementX:function(e){return e.movementX||e.mozMovementX||e.webkitMovementX||0},getMovementY:function(e){return e.movementY||e.mozMovementY||e.webkitMovementY||0},getMouseWheelDelta:function(e){var t=0;switch(e.type){case\"DOMMouseScroll\":t=e.detail;break;case\"mousewheel\":t=e.wheelDelta;break;case\"wheel\":t=e.deltaY;break;default:throw\"unrecognized mouse wheel event: \"+e.type}return t},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(e){if(Browser.pointerLock)e.type!=\"mousemove\"&&\"mozMovementX\"in e?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(e),Browser.mouseMovementY=Browser.getMovementY(e)),typeof SDL<\"u\"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var t=Module.canvas.getBoundingClientRect(),r=Module.canvas.width,s=Module.canvas.height,a=typeof window.scrollX<\"u\"?window.scrollX:window.pageXOffset,n=typeof window.scrollY<\"u\"?window.scrollY:window.pageYOffset;if(e.type===\"touchstart\"||e.type===\"touchend\"||e.type===\"touchmove\"){var c=e.touch;if(c===void 0)return;var f=c.pageX-(a+t.left),p=c.pageY-(n+t.top);f=f*(r/t.width),p=p*(s/t.height);var h={x:f,y:p};if(e.type===\"touchstart\")Browser.lastTouches[c.identifier]=h,Browser.touches[c.identifier]=h;else if(e.type===\"touchend\"||e.type===\"touchmove\"){var E=Browser.touches[c.identifier];E||(E=h),Browser.lastTouches[c.identifier]=E,Browser.touches[c.identifier]=h}return}var C=e.pageX-(a+t.left),S=e.pageY-(n+t.top);C=C*(r/t.width),S=S*(s/t.height),Browser.mouseMovementX=C-Browser.mouseX,Browser.mouseMovementY=S-Browser.mouseY,Browser.mouseX=C,Browser.mouseY=S}},asyncLoad:function(e,t,r,s){var a=s?\"\":\"al \"+e;Module.readAsync(e,function(n){assert(n,'Loading data file \"'+e+'\" failed (no arrayBuffer).'),t(new Uint8Array(n)),a&&removeRunDependency(a)},function(n){if(r)r();else throw'Loading data file \"'+e+'\" failed.'}),a&&addRunDependency(a)},resizeListeners:[],updateResizeListeners:function(){var e=Module.canvas;Browser.resizeListeners.forEach(function(t){t(e.width,e.height)})},setCanvasSize:function(e,t,r){var s=Module.canvas;Browser.updateCanvasDimensions(s,e,t),r||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL<\"u\"){var e=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];e=e|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=e}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL<\"u\"){var e=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];e=e&-8388609,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=e}Browser.updateResizeListeners()},updateCanvasDimensions:function(e,t,r){t&&r?(e.widthNative=t,e.heightNative=r):(t=e.widthNative,r=e.heightNative);var s=t,a=r;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(s/a<Module.forcedAspectRatio?s=Math.round(a*Module.forcedAspectRatio):a=Math.round(s/Module.forcedAspectRatio)),(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===e.parentNode&&typeof screen<\"u\"){var n=Math.min(screen.width/s,screen.height/a);s=Math.round(s*n),a=Math.round(a*n)}Browser.resizeCanvas?(e.width!=s&&(e.width=s),e.height!=a&&(e.height=a),typeof e.style<\"u\"&&(e.style.removeProperty(\"width\"),e.style.removeProperty(\"height\"))):(e.width!=t&&(e.width=t),e.height!=r&&(e.height=r),typeof e.style<\"u\"&&(s!=t||a!=r?(e.style.setProperty(\"width\",s+\"px\",\"important\"),e.style.setProperty(\"height\",a+\"px\",\"important\")):(e.style.removeProperty(\"width\"),e.style.removeProperty(\"height\"))))},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function(){var e=Browser.nextWgetRequestHandle;return Browser.nextWgetRequestHandle++,e}},SYSCALLS={varargs:0,get:function(e){SYSCALLS.varargs+=4;var t=HEAP32[SYSCALLS.varargs-4>>2];return t},getStr:function(){var e=Pointer_stringify(SYSCALLS.get());return e},get64:function(){var e=SYSCALLS.get(),t=SYSCALLS.get();return e>=0?assert(t===0):assert(t===-1),e},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(e,t){SYSCALLS.varargs=t;try{var r=SYSCALLS.getStreamFromFD();return FS.close(r),0}catch(s){return(typeof FS>\"u\"||!(s instanceof FS.ErrnoError))&&abort(s),-s.errno}}function ___syscall54(e,t){SYSCALLS.varargs=t;try{return 0}catch(r){return(typeof FS>\"u\"||!(r instanceof FS.ErrnoError))&&abort(r),-r.errno}}function _typeModule(e){var t=[[0,1,\"X\"],[1,1,\"const X\"],[128,1,\"X *\"],[256,1,\"X &\"],[384,1,\"X &&\"],[512,1,\"std::shared_ptr<X>\"],[640,1,\"std::unique_ptr<X>\"],[5120,1,\"std::vector<X>\"],[6144,2,\"std::array<X, Y>\"],[9216,-1,\"std::function<X (Y)>\"]];function r(p,h,E,C,S,x){if(h==1){var I=C&896;(I==128||I==256||I==384)&&(p=\"X const\")}var T;return x?T=E.replace(\"X\",p).replace(\"Y\",S):T=p.replace(\"X\",E).replace(\"Y\",S),T.replace(/([*&]) (?=[*&])/g,\"$1\")}function s(p,h,E,C,S){throw new Error(p+\" type \"+E.replace(\"X\",h+\"?\")+(C?\" with flag \"+C:\"\")+\" in \"+S)}function a(p,h,E,C,S,x,I,T){x===void 0&&(x=\"X\"),T===void 0&&(T=1);var O=E(p);if(O)return O;var U=C(p),Y=U.placeholderFlag,te=t[Y];I&&te&&(x=r(I[2],I[0],x,te[0],\"?\",!0));var ie;Y==0&&(ie=\"Unbound\"),Y>=10&&(ie=\"Corrupt\"),T>20&&(ie=\"Deeply nested\"),ie&&s(ie,p,x,Y,S||\"?\");var ue=U.paramList[0],ae=a(ue,h,E,C,S,x,te,T+1),de,Ae={flags:te[0],id:p,name:\"\",paramList:[ae]},Ce=[],Ee=\"?\";switch(U.placeholderFlag){case 1:de=ae.spec;break;case 2:if((ae.flags&15360)==1024&&ae.spec.ptrSize==1){Ae.flags=7168;break}case 3:case 6:case 5:de=ae.spec,ae.flags&15360;break;case 8:Ee=\"\"+U.paramList[1],Ae.paramList.push(U.paramList[1]);break;case 9:for(var g=0,Se=U.paramList[1];g<Se.length;g++){var Be=Se[g],me=a(Be,h,E,C,S,x,te,T+1);Ce.push(me.name),Ae.paramList.push(me)}Ee=Ce.join(\", \");break;default:break}if(Ae.name=r(te[2],te[0],ae.name,ae.flags,Ee),de){for(var ce=0,X=Object.keys(de);ce<X.length;ce++){var De=X[ce];Ae[De]=Ae[De]||de[De]}Ae.flags|=de.flags}return n(h,Ae)}function n(p,h){var E=h.flags,C=E&896,S=E&15360;return!h.name&&S==1024&&(h.ptrSize==1?h.name=(E&16?\"\":(E&8?\"un\":\"\")+\"signed \")+\"char\":h.name=(E&8?\"u\":\"\")+(E&32?\"float\":\"int\")+(h.ptrSize*8+\"_t\")),h.ptrSize==8&&!(E&32)&&(S=64),S==2048&&(C==512||C==640?S=4096:C&&(S=3072)),p(S,h)}var c=function(){function p(h){this.id=h.id,this.name=h.name,this.flags=h.flags,this.spec=h}return p.prototype.toString=function(){return this.name},p}(),f={Type:c,getComplexType:a,makeType:n,structureList:t};return e.output=f,e.output||f}function __nbind_register_type(e,t){var r=_nbind.readAsciiString(t),s={flags:10240,id:e,name:r};_nbind.makeType(_nbind.constructType,s)}function __nbind_register_callback_signature(e,t){var r=_nbind.readTypeIdList(e,t),s=_nbind.callbackSignatureList.length;return _nbind.callbackSignatureList[s]=_nbind.makeJSCaller(r),s}function __extends(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);function s(){this.constructor=e}s.prototype=t.prototype,e.prototype=new s}function __nbind_register_class(e,t,r,s,a,n,c){var f=_nbind.readAsciiString(c),p=_nbind.readPolicyList(t),h=HEAPU32.subarray(e/4,e/4+2),E={flags:2048|(p.Value?2:0),id:h[0],name:f},C=_nbind.makeType(_nbind.constructType,E);C.ptrType=_nbind.getComplexType(h[1],_nbind.constructType,_nbind.getType,_nbind.queryType),C.destroy=_nbind.makeMethodCaller(C.ptrType,{boundID:E.id,flags:0,name:\"destroy\",num:0,ptr:n,title:C.name+\".free\",typeList:[\"void\",\"uint32_t\",\"uint32_t\"]}),a&&(C.superIdList=Array.prototype.slice.call(HEAPU32.subarray(r/4,r/4+a)),C.upcastList=Array.prototype.slice.call(HEAPU32.subarray(s/4,s/4+a))),Module[C.name]=C.makeBound(p),_nbind.BindClass.list.push(C)}function _removeAccessorPrefix(e){var t=/^[Gg]et_?([A-Z]?([A-Z]?))/;return e.replace(t,function(r,s,a){return a?s:s.toLowerCase()})}function __nbind_register_function(e,t,r,s,a,n,c,f,p,h){var E=_nbind.getType(e),C=_nbind.readPolicyList(t),S=_nbind.readTypeIdList(r,s),x;if(c==5)x=[{direct:a,name:\"__nbindConstructor\",ptr:0,title:E.name+\" constructor\",typeList:[\"uint32_t\"].concat(S.slice(1))},{direct:n,name:\"__nbindValueConstructor\",ptr:0,title:E.name+\" value constructor\",typeList:[\"void\",\"uint32_t\"].concat(S.slice(1))}];else{var I=_nbind.readAsciiString(f),T=(E.name&&E.name+\".\")+I;(c==3||c==4)&&(I=_removeAccessorPrefix(I)),x=[{boundID:e,direct:n,name:I,ptr:a,title:T,typeList:S}]}for(var O=0,U=x;O<U.length;O++){var Y=U[O];Y.signatureType=c,Y.policyTbl=C,Y.num=p,Y.flags=h,E.addMethod(Y)}}function _nbind_value(e,t){_nbind.typeNameTbl[e]||_nbind.throwError(\"Unknown value type \"+e),Module.NBind.bind_value(e,t),_defineHidden(_nbind.typeNameTbl[e].proto.prototype.__nbindValueConstructor)(t.prototype,\"__nbindValueConstructor\")}Module._nbind_value=_nbind_value;function __nbind_get_value_object(e,t){var r=_nbind.popValue(e);if(!r.fromJS)throw new Error(\"Object \"+r+\" has no fromJS function\");r.fromJS(function(){r.__nbindValueConstructor.apply(this,Array.prototype.concat.apply([t],arguments))})}function _emscripten_memcpy_big(e,t,r){return HEAPU8.set(HEAPU8.subarray(t,t+r),e),e}function __nbind_register_primitive(e,t,r){var s={flags:1024|r,id:e,ptrSize:t};_nbind.makeType(_nbind.constructType,s)}var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],\"i8\",ALLOC_STATIC);function ___setErrNo(e){return Module.___errno_location&&(HEAP32[Module.___errno_location()>>2]=e),e}function _llvm_stacksave(){var e=_llvm_stacksave;return e.LLVM_SAVEDSTACKS||(e.LLVM_SAVEDSTACKS=[]),e.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),e.LLVM_SAVEDSTACKS.length-1}function ___syscall140(e,t){SYSCALLS.varargs=t;try{var r=SYSCALLS.getStreamFromFD(),s=SYSCALLS.get(),a=SYSCALLS.get(),n=SYSCALLS.get(),c=SYSCALLS.get(),f=a;return FS.llseek(r,f,c),HEAP32[n>>2]=r.position,r.getdents&&f===0&&c===0&&(r.getdents=null),0}catch(p){return(typeof FS>\"u\"||!(p instanceof FS.ErrnoError))&&abort(p),-p.errno}}function ___syscall146(e,t){SYSCALLS.varargs=t;try{var r=SYSCALLS.get(),s=SYSCALLS.get(),a=SYSCALLS.get(),n=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(E,C){var S=___syscall146.buffers[E];assert(S),C===0||C===10?((E===1?Module.print:Module.printErr)(UTF8ArrayToString(S,0)),S.length=0):S.push(C)});for(var c=0;c<a;c++){for(var f=HEAP32[s+c*8>>2],p=HEAP32[s+(c*8+4)>>2],h=0;h<p;h++)___syscall146.printChar(r,HEAPU8[f+h]);n+=p}return n}catch(E){return(typeof FS>\"u\"||!(E instanceof FS.ErrnoError))&&abort(E),-E.errno}}function __nbind_finish(){for(var e=0,t=_nbind.BindClass.list;e<t.length;e++){var r=t[e];r.finish()}}var ___dso_handle=STATICTOP;STATICTOP+=16,function(_nbind){var typeIdTbl={};_nbind.typeNameTbl={};var Pool=function(){function e(){}return e.lalloc=function(t){t=t+7&-8;var r=HEAPU32[e.usedPtr];if(t>e.pageSize/2||t>e.pageSize-r){var s=_nbind.typeNameTbl.NBind.proto;return s.lalloc(t)}else return HEAPU32[e.usedPtr]=r+t,e.rootPtr+r},e.lreset=function(t,r){var s=HEAPU32[e.pagePtr];if(s){var a=_nbind.typeNameTbl.NBind.proto;a.lreset(t,r)}else HEAPU32[e.usedPtr]=t},e}();_nbind.Pool=Pool;function constructType(e,t){var r=e==10240?_nbind.makeTypeNameTbl[t.name]||_nbind.BindType:_nbind.makeTypeKindTbl[e],s=new r(t);return typeIdTbl[t.id]=s,_nbind.typeNameTbl[t.name]=s,s}_nbind.constructType=constructType;function getType(e){return typeIdTbl[e]}_nbind.getType=getType;function queryType(e){var t=HEAPU8[e],r=_nbind.structureList[t][1];e/=4,r<0&&(++e,r=HEAPU32[e]+1);var s=Array.prototype.slice.call(HEAPU32.subarray(e+1,e+1+r));return t==9&&(s=[s[0],s.slice(1)]),{paramList:s,placeholderFlag:t}}_nbind.queryType=queryType;function getTypes(e,t){return e.map(function(r){return typeof r==\"number\"?_nbind.getComplexType(r,constructType,getType,queryType,t):_nbind.typeNameTbl[r]})}_nbind.getTypes=getTypes;function readTypeIdList(e,t){return Array.prototype.slice.call(HEAPU32,e/4,e/4+t)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(e){for(var t=e;HEAPU8[t++];);return String.fromCharCode.apply(\"\",HEAPU8.subarray(e,t-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(e){var t={};if(e)for(;;){var r=HEAPU32[e/4];if(!r)break;t[readAsciiString(r)]=!0,e+=4}return t}_nbind.readPolicyList=readPolicyList;function getDynCall(e,t){var r={float32_t:\"d\",float64_t:\"d\",int64_t:\"d\",uint64_t:\"d\",void:\"v\"},s=e.map(function(n){return r[n.name]||\"i\"}).join(\"\"),a=Module[\"dynCall_\"+s];if(!a)throw new Error(\"dynCall_\"+s+\" not found for \"+t+\"(\"+e.map(function(n){return n.name}).join(\", \")+\")\");return a}_nbind.getDynCall=getDynCall;function addMethod(e,t,r,s){var a=e[t];e.hasOwnProperty(t)&&a?((a.arity||a.arity===0)&&(a=_nbind.makeOverloader(a,a.arity),e[t]=a),a.addMethod(r,s)):(r.arity=s,e[t]=r)}_nbind.addMethod=addMethod;function throwError(e){throw new Error(e)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.heap=HEAPU32,r.ptrSize=4,r}return t.prototype.needsWireRead=function(r){return!!this.wireRead||!!this.makeWireRead},t.prototype.needsWireWrite=function(r){return!!this.wireWrite||!!this.makeWireWrite},t}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(e){__extends(t,e);function t(r){var s=e.call(this,r)||this,a=r.flags&32?{32:HEAPF32,64:HEAPF64}:r.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return s.heap=a[r.ptrSize*8],s.ptrSize=r.ptrSize,s}return t.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},t.prototype.makeWireWrite=function(r,s){return s&&s.Strict&&function(a){if(typeof a==\"number\")return a;throw new Error(\"Type mismatch\")}},t}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(e,t){if(e==null){if(t&&t.Nullable)return 0;throw new Error(\"Type mismatch\")}if(t&&t.Strict){if(typeof e!=\"string\")throw new Error(\"Type mismatch\")}else e=e.toString();var r=Module.lengthBytesUTF8(e)+1,s=_nbind.Pool.lalloc(r);return Module.stringToUTF8Array(e,HEAPU8,s,r),s}_nbind.pushCString=pushCString;function popCString(e){return e===0?null:Module.Pointer_stringify(e)}_nbind.popCString=popCString;var CStringType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireRead=popCString,r.wireWrite=pushCString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return t.prototype.makeWireWrite=function(r,s){return function(a){return pushCString(a,s)}},t}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireRead=function(s){return!!s},r}return t.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},t.prototype.makeWireRead=function(r){return\"!!(\"+r+\")\"},t.prototype.makeWireWrite=function(r,s){return s&&s.Strict&&function(a){if(typeof a==\"boolean\")return a;throw new Error(\"Type mismatch\")}||r},t}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function e(){}return e.prototype.persist=function(){this.__nbindState|=1},e}();_nbind.Wrapper=Wrapper;function makeBound(e,t){var r=function(s){__extends(a,s);function a(n,c,f,p){var h=s.call(this)||this;if(!(h instanceof a))return new(Function.prototype.bind.apply(a,Array.prototype.concat.apply([null],arguments)));var E=c,C=f,S=p;if(n!==_nbind.ptrMarker){var x=h.__nbindConstructor.apply(h,arguments);E=4608,S=HEAPU32[x/4],C=HEAPU32[x/4+1]}var I={configurable:!0,enumerable:!1,value:null,writable:!1},T={__nbindFlags:E,__nbindPtr:C};S&&(T.__nbindShared=S,_nbind.mark(h));for(var O=0,U=Object.keys(T);O<U.length;O++){var Y=U[O];I.value=T[Y],Object.defineProperty(h,Y,I)}return _defineHidden(0)(h,\"__nbindState\"),h}return a.prototype.free=function(){t.destroy.call(this,this.__nbindShared,this.__nbindFlags),this.__nbindState|=2,disableMember(this,\"__nbindShared\"),disableMember(this,\"__nbindPtr\")},a}(Wrapper);return __decorate([_defineHidden()],r.prototype,\"__nbindConstructor\",void 0),__decorate([_defineHidden()],r.prototype,\"__nbindValueConstructor\",void 0),__decorate([_defineHidden(e)],r.prototype,\"__nbindPolicies\",void 0),r}_nbind.makeBound=makeBound;function disableMember(e,t){function r(){throw new Error(\"Accessing deleted object\")}Object.defineProperty(e,t,{configurable:!1,enumerable:!1,get:r,set:r})}_nbind.ptrMarker={};var BindClass=function(e){__extends(t,e);function t(r){var s=e.call(this,r)||this;return s.wireRead=function(a){return _nbind.popValue(a,s.ptrType)},s.wireWrite=function(a){return pushPointer(a,s.ptrType,!0)},s.pendingSuperCount=0,s.ready=!1,s.methodTbl={},r.paramList?(s.classType=r.paramList[0].classType,s.proto=s.classType.proto):s.classType=s,s}return t.prototype.makeBound=function(r){var s=_nbind.makeBound(r,this);return this.proto=s,this.ptrType.proto=s,s},t.prototype.addMethod=function(r){var s=this.methodTbl[r.name]||[];s.push(r),this.methodTbl[r.name]=s},t.prototype.registerMethods=function(r,s){for(var a,n=0,c=Object.keys(r.methodTbl);n<c.length;n++)for(var f=c[n],p=r.methodTbl[f],h=0,E=p;h<E.length;h++){var C=E[h],S=void 0,x=void 0;if(S=this.proto.prototype,!(s&&C.signatureType!=1))switch(C.signatureType){case 1:S=this.proto;case 5:x=_nbind.makeCaller(C),_nbind.addMethod(S,C.name,x,C.typeList.length-1);break;case 4:a=_nbind.makeMethodCaller(r.ptrType,C);break;case 3:Object.defineProperty(S,C.name,{configurable:!0,enumerable:!1,get:_nbind.makeMethodCaller(r.ptrType,C),set:a});break;case 2:x=_nbind.makeMethodCaller(r.ptrType,C),_nbind.addMethod(S,C.name,x,C.typeList.length-1);break;default:break}}},t.prototype.registerSuperMethods=function(r,s,a){if(!a[r.name]){a[r.name]=!0;for(var n=0,c,f=0,p=r.superIdList||[];f<p.length;f++){var h=p[f],E=_nbind.getType(h);n++<s||s<0?c=-1:c=0,this.registerSuperMethods(E,c,a)}this.registerMethods(r,s<0)}},t.prototype.finish=function(){if(this.ready)return this;this.ready=!0,this.superList=(this.superIdList||[]).map(function(a){return _nbind.getType(a).finish()});var r=this.proto;if(this.superList.length){var s=function(){this.constructor=r};s.prototype=this.superList[0].proto.prototype,r.prototype=new s}return r!=Module&&(r.prototype.__nbindType=this),this.registerSuperMethods(this,1,{}),this},t.prototype.upcastStep=function(r,s){if(r==this)return s;for(var a=0;a<this.superList.length;++a){var n=this.superList[a].upcastStep(r,_nbind.callUpcast(this.upcastList[a],s));if(n)return n}return 0},t}(_nbind.BindType);BindClass.list=[],_nbind.BindClass=BindClass;function popPointer(e,t){return e?new t.proto(_nbind.ptrMarker,t.flags,e):null}_nbind.popPointer=popPointer;function pushPointer(e,t,r){if(!(e instanceof _nbind.Wrapper)){if(r)return _nbind.pushValue(e);throw new Error(\"Type mismatch\")}var s=e.__nbindPtr,a=e.__nbindType.classType,n=t.classType;if(e instanceof t.proto)for(;a!=n;)s=_nbind.callUpcast(a.upcastList[0],s),a=a.superList[0];else if(s=a.upcastStep(n,s),!s)throw new Error(\"Type mismatch\");return s}_nbind.pushPointer=pushPointer;function pushMutablePointer(e,t){var r=pushPointer(e,t);if(e.__nbindFlags&1)throw new Error(\"Passing a const value as a non-const argument\");return r}var BindClassPtr=function(e){__extends(t,e);function t(r){var s=e.call(this,r)||this;s.classType=r.paramList[0].classType,s.proto=s.classType.proto;var a=r.flags&1,n=(s.flags&896)==256&&r.flags&2,c=a?pushPointer:pushMutablePointer,f=n?_nbind.popValue:popPointer;return s.makeWireWrite=function(p,h){return h.Nullable?function(E){return E?c(E,s):0}:function(E){return c(E,s)}},s.wireRead=function(p){return f(p,s)},s.wireWrite=function(p){return c(p,s)},s}return t}(_nbind.BindType);_nbind.BindClassPtr=BindClassPtr;function popShared(e,t){var r=HEAPU32[e/4],s=HEAPU32[e/4+1];return s?new t.proto(_nbind.ptrMarker,t.flags,s,r):null}_nbind.popShared=popShared;function pushShared(e,t){if(!(e instanceof t.proto))throw new Error(\"Type mismatch\");return e.__nbindShared}function pushMutableShared(e,t){if(!(e instanceof t.proto))throw new Error(\"Type mismatch\");if(e.__nbindFlags&1)throw new Error(\"Passing a const value as a non-const argument\");return e.__nbindShared}var SharedClassPtr=function(e){__extends(t,e);function t(r){var s=e.call(this,r)||this;s.readResources=[_nbind.resources.pool],s.classType=r.paramList[0].classType,s.proto=s.classType.proto;var a=r.flags&1,n=a?pushShared:pushMutableShared;return s.wireRead=function(c){return popShared(c,s)},s.wireWrite=function(c){return n(c,s)},s}return t}(_nbind.BindType);_nbind.SharedClassPtr=SharedClassPtr,_nbind.externalList=[0];var firstFreeExternal=0,External=function(){function e(t){this.refCount=1,this.data=t}return e.prototype.register=function(){var t=firstFreeExternal;return t?firstFreeExternal=_nbind.externalList[t]:t=_nbind.externalList.length,_nbind.externalList[t]=this,t},e.prototype.reference=function(){++this.refCount},e.prototype.dereference=function(t){--this.refCount==0&&(this.free&&this.free(),_nbind.externalList[t]=firstFreeExternal,firstFreeExternal=t)},e}();_nbind.External=External;function popExternal(e){var t=_nbind.externalList[e];return t.dereference(e),t.data}function pushExternal(e){var t=new External(e);return t.reference(),t.register()}var ExternalType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireRead=popExternal,r.wireWrite=pushExternal,r}return t}(_nbind.BindType);_nbind.ExternalType=ExternalType,_nbind.callbackSignatureList=[];var CallbackType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireWrite=function(s){return typeof s!=\"function\"&&_nbind.throwError(\"Type mismatch\"),new _nbind.External(s).register()},r}return t}(_nbind.BindType);_nbind.CallbackType=CallbackType,_nbind.valueList=[0];var firstFreeValue=0;function pushValue(e){var t=firstFreeValue;return t?firstFreeValue=_nbind.valueList[t]:t=_nbind.valueList.length,_nbind.valueList[t]=e,t*2+1}_nbind.pushValue=pushValue;function popValue(e,t){if(e||_nbind.throwError(\"Value type JavaScript class is missing or not registered\"),e&1){e>>=1;var r=_nbind.valueList[e];return _nbind.valueList[e]=firstFreeValue,firstFreeValue=e,r}else{if(t)return _nbind.popShared(e,t);throw new Error(\"Invalid value slot \"+e)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(e){return typeof e==\"number\"?e:pushValue(e)*4096+valueBase}function pop64(e){return e<valueBase?e:popValue((e-valueBase)/4096)}var CreateValueType=function(e){__extends(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.makeWireWrite=function(r){return\"(_nbind.pushValue(new \"+r+\"))\"},t}(_nbind.BindType);_nbind.CreateValueType=CreateValueType;var Int64Type=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireWrite=push64,r.wireRead=pop64,r}return t}(_nbind.BindType);_nbind.Int64Type=Int64Type;function pushArray(e,t){if(!e)return 0;var r=e.length;if((t.size||t.size===0)&&r<t.size)throw new Error(\"Type mismatch\");var s=t.memberType.ptrSize,a=_nbind.Pool.lalloc(4+r*s);HEAPU32[a/4]=r;var n=t.memberType.heap,c=(a+4)/s,f=t.memberType.wireWrite,p=0;if(f)for(;p<r;)n[c++]=f(e[p++]);else for(;p<r;)n[c++]=e[p++];return a}_nbind.pushArray=pushArray;function popArray(e,t){if(e===0)return null;var r=HEAPU32[e/4],s=new Array(r),a=t.memberType.heap;e=(e+4)/t.memberType.ptrSize;var n=t.memberType.wireRead,c=0;if(n)for(;c<r;)s[c++]=n(a[e++]);else for(;c<r;)s[c++]=a[e++];return s}_nbind.popArray=popArray;var ArrayType=function(e){__extends(t,e);function t(r){var s=e.call(this,r)||this;return s.wireRead=function(a){return popArray(a,s)},s.wireWrite=function(a){return pushArray(a,s)},s.readResources=[_nbind.resources.pool],s.writeResources=[_nbind.resources.pool],s.memberType=r.paramList[0],r.paramList[1]&&(s.size=r.paramList[1]),s}return t}(_nbind.BindType);_nbind.ArrayType=ArrayType;function pushString(e,t){if(e==null)if(t&&t.Nullable)e=\"\";else throw new Error(\"Type mismatch\");if(t&&t.Strict){if(typeof e!=\"string\")throw new Error(\"Type mismatch\")}else e=e.toString();var r=Module.lengthBytesUTF8(e),s=_nbind.Pool.lalloc(4+r+1);return HEAPU32[s/4]=r,Module.stringToUTF8Array(e,HEAPU8,s+4,r+1),s}_nbind.pushString=pushString;function popString(e){if(e===0)return null;var t=HEAPU32[e/4];return Module.Pointer_stringify(e+4,t)}_nbind.popString=popString;var StringType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireRead=popString,r.wireWrite=pushString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return t.prototype.makeWireWrite=function(r,s){return function(a){return pushString(a,s)}},t}(_nbind.BindType);_nbind.StringType=StringType;function makeArgList(e){return Array.apply(null,Array(e)).map(function(t,r){return\"a\"+(r+1)})}function anyNeedsWireWrite(e,t){return e.reduce(function(r,s){return r||s.needsWireWrite(t)},!1)}function anyNeedsWireRead(e,t){return e.reduce(function(r,s){return r||!!s.needsWireRead(t)},!1)}function makeWireRead(e,t,r,s){var a=e.length;return r.makeWireRead?r.makeWireRead(s,e,a):r.wireRead?(e[a]=r.wireRead,\"(convertParamList[\"+a+\"](\"+s+\"))\"):s}function makeWireWrite(e,t,r,s){var a,n=e.length;return r.makeWireWrite?a=r.makeWireWrite(s,t,e,n):a=r.wireWrite,a?typeof a==\"string\"?a:(e[n]=a,\"(convertParamList[\"+n+\"](\"+s+\"))\"):s}function buildCallerFunction(dynCall,ptrType,ptr,num,policyTbl,needsWireWrite,prefix,returnType,argTypeList,mask,err){var argList=makeArgList(argTypeList.length),convertParamList=[],callExpression=makeWireRead(convertParamList,policyTbl,returnType,\"dynCall(\"+[prefix].concat(argList.map(function(e,t){return makeWireWrite(convertParamList,policyTbl,argTypeList[t],e)})).join(\",\")+\")\"),resourceSet=_nbind.listResources([returnType],argTypeList),sourceCode=\"function(\"+argList.join(\",\")+\"){\"+(mask?\"this.__nbindFlags&mask&&err();\":\"\")+resourceSet.makeOpen()+\"var r=\"+callExpression+\";\"+resourceSet.makeClose()+\"return r;}\";return eval(\"(\"+sourceCode+\")\")}function buildJSCallerFunction(returnType,argTypeList){var argList=makeArgList(argTypeList.length),convertParamList=[],callExpression=makeWireWrite(convertParamList,null,returnType,\"_nbind.externalList[num].data(\"+argList.map(function(e,t){return makeWireRead(convertParamList,null,argTypeList[t],e)}).join(\",\")+\")\"),resourceSet=_nbind.listResources(argTypeList,[returnType]);resourceSet.remove(_nbind.resources.pool);var sourceCode=\"function(\"+[\"dummy\",\"num\"].concat(argList).join(\",\")+\"){\"+resourceSet.makeOpen()+\"var r=\"+callExpression+\";\"+resourceSet.makeClose()+\"return r;}\";return eval(\"(\"+sourceCode+\")\")}_nbind.buildJSCallerFunction=buildJSCallerFunction;function makeJSCaller(e){var t=e.length-1,r=_nbind.getTypes(e,\"callback\"),s=r[0],a=r.slice(1),n=anyNeedsWireRead(a,null),c=s.needsWireWrite(null);if(!c&&!n)switch(t){case 0:return function(f,p){return _nbind.externalList[p].data()};case 1:return function(f,p,h){return _nbind.externalList[p].data(h)};case 2:return function(f,p,h,E){return _nbind.externalList[p].data(h,E)};case 3:return function(f,p,h,E,C){return _nbind.externalList[p].data(h,E,C)};default:break}return buildJSCallerFunction(s,a)}_nbind.makeJSCaller=makeJSCaller;function makeMethodCaller(e,t){var r=t.typeList.length-1,s=t.typeList.slice(0);s.splice(1,0,\"uint32_t\",t.boundID);var a=_nbind.getTypes(s,t.title),n=a[0],c=a.slice(3),f=n.needsWireRead(t.policyTbl),p=anyNeedsWireWrite(c,t.policyTbl),h=t.ptr,E=t.num,C=_nbind.getDynCall(a,t.title),S=~t.flags&1;function x(){throw new Error(\"Calling a non-const method on a const object\")}if(!f&&!p)switch(r){case 0:return function(){return this.__nbindFlags&S?x():C(h,E,_nbind.pushPointer(this,e))};case 1:return function(I){return this.__nbindFlags&S?x():C(h,E,_nbind.pushPointer(this,e),I)};case 2:return function(I,T){return this.__nbindFlags&S?x():C(h,E,_nbind.pushPointer(this,e),I,T)};case 3:return function(I,T,O){return this.__nbindFlags&S?x():C(h,E,_nbind.pushPointer(this,e),I,T,O)};default:break}return buildCallerFunction(C,e,h,E,t.policyTbl,p,\"ptr,num,pushPointer(this,ptrType)\",n,c,S,x)}_nbind.makeMethodCaller=makeMethodCaller;function makeCaller(e){var t=e.typeList.length-1,r=_nbind.getTypes(e.typeList,e.title),s=r[0],a=r.slice(1),n=s.needsWireRead(e.policyTbl),c=anyNeedsWireWrite(a,e.policyTbl),f=e.direct,p=e.ptr;if(e.direct&&!n&&!c){var h=_nbind.getDynCall(r,e.title);switch(t){case 0:return function(){return h(f)};case 1:return function(x){return h(f,x)};case 2:return function(x,I){return h(f,x,I)};case 3:return function(x,I,T){return h(f,x,I,T)};default:break}p=0}var E;if(p){var C=e.typeList.slice(0);C.splice(1,0,\"uint32_t\"),r=_nbind.getTypes(C,e.title),E=\"ptr,num\"}else p=f,E=\"ptr\";var S=_nbind.getDynCall(r,e.title);return buildCallerFunction(S,null,p,e.num,e.policyTbl,c,E,s,a)}_nbind.makeCaller=makeCaller;function makeOverloader(e,t){var r=[];function s(){return r[arguments.length].apply(this,arguments)}return s.addMethod=function(a,n){r[n]=a},s.addMethod(e,t),s}_nbind.makeOverloader=makeOverloader;var Resource=function(){function e(t,r){var s=this;this.makeOpen=function(){return Object.keys(s.openTbl).join(\"\")},this.makeClose=function(){return Object.keys(s.closeTbl).join(\"\")},this.openTbl={},this.closeTbl={},t&&(this.openTbl[t]=!0),r&&(this.closeTbl[r]=!0)}return e.prototype.add=function(t){for(var r=0,s=Object.keys(t.openTbl);r<s.length;r++){var a=s[r];this.openTbl[a]=!0}for(var n=0,c=Object.keys(t.closeTbl);n<c.length;n++){var a=c[n];this.closeTbl[a]=!0}},e.prototype.remove=function(t){for(var r=0,s=Object.keys(t.openTbl);r<s.length;r++){var a=s[r];delete this.openTbl[a]}for(var n=0,c=Object.keys(t.closeTbl);n<c.length;n++){var a=c[n];delete this.closeTbl[a]}},e}();_nbind.Resource=Resource;function listResources(e,t){for(var r=new Resource,s=0,a=e;s<a.length;s++)for(var n=a[s],c=0,f=n.readResources||[];c<f.length;c++){var p=f[c];r.add(p)}for(var h=0,E=t;h<E.length;h++)for(var n=E[h],C=0,S=n.writeResources||[];C<S.length;C++){var p=S[C];r.add(p)}return r}_nbind.listResources=listResources,_nbind.resources={pool:new Resource(\"var used=HEAPU32[_nbind.Pool.usedPtr],page=HEAPU32[_nbind.Pool.pagePtr];\",\"_nbind.Pool.lreset(used,page);\")};var ExternalBuffer=function(e){__extends(t,e);function t(r,s){var a=e.call(this,r)||this;return a.ptr=s,a}return t.prototype.free=function(){_free(this.ptr)},t}(_nbind.External);function getBuffer(e){return e instanceof ArrayBuffer?new Uint8Array(e):e instanceof DataView?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):e}function pushBuffer(e,t){if(e==null&&t&&t.Nullable&&(e=[]),typeof e!=\"object\")throw new Error(\"Type mismatch\");var r=e,s=r.byteLength||r.length;if(!s&&s!==0&&r.byteLength!==0)throw new Error(\"Type mismatch\");var a=_nbind.Pool.lalloc(8),n=_malloc(s),c=a/4;return HEAPU32[c++]=s,HEAPU32[c++]=n,HEAPU32[c++]=new ExternalBuffer(e,n).register(),HEAPU8.set(getBuffer(e),n),a}var BufferType=function(e){__extends(t,e);function t(){var r=e!==null&&e.apply(this,arguments)||this;return r.wireWrite=pushBuffer,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return t.prototype.makeWireWrite=function(r,s){return function(a){return pushBuffer(a,s)}},t}(_nbind.BindType);_nbind.BufferType=BufferType;function commitBuffer(e,t,r){var s=_nbind.externalList[e].data,a=Buffer;if(typeof Buffer!=\"function\"&&(a=function(){}),!(s instanceof Array)){var n=HEAPU8.subarray(t,t+r);if(s instanceof a){var c=void 0;typeof Buffer.from==\"function\"&&Buffer.from.length>=3?c=Buffer.from(n):c=new Buffer(n),c.copy(s)}else getBuffer(s).set(n)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var e=0,t=dirtyList;e<t.length;e++){var r=t[e];r.__nbindState&3||r.free()}dirtyList=[],gcTimer=0}_nbind.mark=function(e){};function toggleLightGC(e){e?_nbind.mark=function(t){dirtyList.push(t),gcTimer||(gcTimer=setTimeout(sweep,0))}:_nbind.mark=function(t){}}_nbind.toggleLightGC=toggleLightGC}(_nbind),Module.requestFullScreen=function e(t,r,s){Module.printErr(\"Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead.\"),Module.requestFullScreen=Module.requestFullscreen,Browser.requestFullScreen(t,r,s)},Module.requestFullscreen=function e(t,r,s){Browser.requestFullscreen(t,r,s)},Module.requestAnimationFrame=function e(t){Browser.requestAnimationFrame(t)},Module.setCanvasSize=function e(t,r,s){Browser.setCanvasSize(t,r,s)},Module.pauseMainLoop=function e(){Browser.mainLoop.pause()},Module.resumeMainLoop=function e(){Browser.mainLoop.resume()},Module.getUserMedia=function e(){Browser.getUserMedia()},Module.createContext=function e(t,r,s,a){return Browser.createContext(t,r,s,a)},ENVIRONMENT_IS_NODE?_emscripten_get_now=function(){var t=process.hrtime();return t[0]*1e3+t[1]/1e6}:typeof dateNow<\"u\"?_emscripten_get_now=dateNow:typeof self==\"object\"&&self.performance&&typeof self.performance.now==\"function\"?_emscripten_get_now=function(){return self.performance.now()}:typeof performance==\"object\"&&typeof performance.now==\"function\"?_emscripten_get_now=function(){return performance.now()}:_emscripten_get_now=Date.now,__ATEXIT__.push(function(){var e=Module._fflush;e&&e(0);var t=___syscall146.printChar;if(t){var r=___syscall146.buffers;r[1].length&&t(1,10),r[2].length&&t(2,10)}}),DYNAMICTOP_PTR=allocate(1,\"i32\",ALLOC_STATIC),STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP),STACK_MAX=STACK_BASE+TOTAL_STACK,DYNAMIC_BASE=Runtime.alignMemory(STACK_MAX),HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(e,t,r,s,a,n){try{Module.dynCall_viiiii(e,t,r,s,a,n)}catch(c){if(typeof c!=\"number\"&&c!==\"longjmp\")throw c;Module.setThrew(1,0)}}function invoke_vif(e,t,r){try{Module.dynCall_vif(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_vid(e,t,r){try{Module.dynCall_vid(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_fiff(e,t,r,s){try{return Module.dynCall_fiff(e,t,r,s)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_vi(e,t){try{Module.dynCall_vi(e,t)}catch(r){if(typeof r!=\"number\"&&r!==\"longjmp\")throw r;Module.setThrew(1,0)}}function invoke_vii(e,t,r){try{Module.dynCall_vii(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_ii(e,t){try{return Module.dynCall_ii(e,t)}catch(r){if(typeof r!=\"number\"&&r!==\"longjmp\")throw r;Module.setThrew(1,0)}}function invoke_viddi(e,t,r,s,a){try{Module.dynCall_viddi(e,t,r,s,a)}catch(n){if(typeof n!=\"number\"&&n!==\"longjmp\")throw n;Module.setThrew(1,0)}}function invoke_vidd(e,t,r,s){try{Module.dynCall_vidd(e,t,r,s)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_iiii(e,t,r,s){try{return Module.dynCall_iiii(e,t,r,s)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_diii(e,t,r,s){try{return Module.dynCall_diii(e,t,r,s)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_di(e,t){try{return Module.dynCall_di(e,t)}catch(r){if(typeof r!=\"number\"&&r!==\"longjmp\")throw r;Module.setThrew(1,0)}}function invoke_iid(e,t,r){try{return Module.dynCall_iid(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_iii(e,t,r){try{return Module.dynCall_iii(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_viiddi(e,t,r,s,a,n){try{Module.dynCall_viiddi(e,t,r,s,a,n)}catch(c){if(typeof c!=\"number\"&&c!==\"longjmp\")throw c;Module.setThrew(1,0)}}function invoke_viiiiii(e,t,r,s,a,n,c){try{Module.dynCall_viiiiii(e,t,r,s,a,n,c)}catch(f){if(typeof f!=\"number\"&&f!==\"longjmp\")throw f;Module.setThrew(1,0)}}function invoke_dii(e,t,r){try{return Module.dynCall_dii(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_i(e){try{return Module.dynCall_i(e)}catch(t){if(typeof t!=\"number\"&&t!==\"longjmp\")throw t;Module.setThrew(1,0)}}function invoke_iiiiii(e,t,r,s,a,n){try{return Module.dynCall_iiiiii(e,t,r,s,a,n)}catch(c){if(typeof c!=\"number\"&&c!==\"longjmp\")throw c;Module.setThrew(1,0)}}function invoke_viiid(e,t,r,s,a){try{Module.dynCall_viiid(e,t,r,s,a)}catch(n){if(typeof n!=\"number\"&&n!==\"longjmp\")throw n;Module.setThrew(1,0)}}function invoke_viififi(e,t,r,s,a,n,c){try{Module.dynCall_viififi(e,t,r,s,a,n,c)}catch(f){if(typeof f!=\"number\"&&f!==\"longjmp\")throw f;Module.setThrew(1,0)}}function invoke_viii(e,t,r,s){try{Module.dynCall_viii(e,t,r,s)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_v(e){try{Module.dynCall_v(e)}catch(t){if(typeof t!=\"number\"&&t!==\"longjmp\")throw t;Module.setThrew(1,0)}}function invoke_viid(e,t,r,s){try{Module.dynCall_viid(e,t,r,s)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_idd(e,t,r){try{return Module.dynCall_idd(e,t,r)}catch(s){if(typeof s!=\"number\"&&s!==\"longjmp\")throw s;Module.setThrew(1,0)}}function invoke_viiii(e,t,r,s,a){try{Module.dynCall_viiii(e,t,r,s,a)}catch(n){if(typeof n!=\"number\"&&n!==\"longjmp\")throw n;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:1/0},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(e,t,r){var s=new e.Int8Array(r),a=new e.Int16Array(r),n=new e.Int32Array(r),c=new e.Uint8Array(r),f=new e.Uint16Array(r),p=new e.Uint32Array(r),h=new e.Float32Array(r),E=new e.Float64Array(r),C=t.DYNAMICTOP_PTR|0,S=t.tempDoublePtr|0,x=t.ABORT|0,I=t.STACKTOP|0,T=t.STACK_MAX|0,O=t.cttz_i8|0,U=t.___dso_handle|0,Y=0,te=0,ie=0,ue=0,ae=e.NaN,de=e.Infinity,Ae=0,Ce=0,Ee=0,g=0,Se=0,Be=0,me=e.Math.floor,ce=e.Math.abs,X=e.Math.sqrt,De=e.Math.pow,Qe=e.Math.cos,it=e.Math.sin,_=e.Math.tan,tt=e.Math.acos,Ne=e.Math.asin,ke=e.Math.atan,be=e.Math.atan2,je=e.Math.exp,Re=e.Math.log,ct=e.Math.ceil,Me=e.Math.imul,P=e.Math.min,w=e.Math.max,b=e.Math.clz32,y=e.Math.fround,F=t.abort,z=t.assert,Z=t.enlargeMemory,$=t.getTotalMemory,se=t.abortOnCannotGrowMemory,xe=t.invoke_viiiii,Fe=t.invoke_vif,ut=t.invoke_vid,Ct=t.invoke_fiff,qt=t.invoke_vi,ir=t.invoke_vii,Pt=t.invoke_ii,dn=t.invoke_viddi,Pr=t.invoke_vidd,Ir=t.invoke_iiii,Or=t.invoke_diii,on=t.invoke_di,li=t.invoke_iid,So=t.invoke_iii,ns=t.invoke_viiddi,so=t.invoke_viiiiii,Do=t.invoke_dii,ji=t.invoke_i,oo=t.invoke_iiiiii,bo=t.invoke_viiid,RA=t.invoke_viififi,hf=t.invoke_viii,hh=t.invoke_v,gh=t.invoke_viid,ao=t.invoke_idd,Gn=t.invoke_viiii,Ns=t._emscripten_asm_const_iiiii,lo=t._emscripten_asm_const_iiidddddd,iu=t._emscripten_asm_const_iiiid,su=t.__nbind_reference_external,ou=t._emscripten_asm_const_iiiiiiii,TA=t._removeAccessorPrefix,FA=t._typeModule,ua=t.__nbind_register_pool,fa=t.__decorate,NA=t._llvm_stackrestore,gr=t.___cxa_atexit,Po=t.__extends,Ue=t.__nbind_get_value_object,au=t.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,Cr=t._emscripten_set_main_loop_timing,gf=t.__nbind_register_primitive,OA=t.__nbind_register_type,LA=t._emscripten_memcpy_big,lu=t.__nbind_register_function,cu=t.___setErrNo,ac=t.__nbind_register_class,we=t.__nbind_finish,Nt=t._abort,lc=t._nbind_value,Oi=t._llvm_stacksave,co=t.___syscall54,Tt=t._defineHidden,Qn=t._emscripten_set_main_loop,Aa=t._emscripten_get_now,Gi=t.__nbind_register_callback_signature,Li=t._emscripten_asm_const_iiiiii,ja=t.__nbind_free_external,mn=t._emscripten_asm_const_iiii,Zn=t._emscripten_asm_const_iiididi,uu=t.___syscall6,dh=t._atexit,Ga=t.___syscall140,qa=t.___syscall146,Wa=y(0);let $e=y(0);function Va(o){o=o|0;var l=0;return l=I,I=I+o|0,I=I+15&-16,l|0}function df(){return I|0}function cc(o){o=o|0,I=o}function vn(o,l){o=o|0,l=l|0,I=o,T=l}function pa(o,l){o=o|0,l=l|0,Y||(Y=o,te=l)}function MA(o){o=o|0,Be=o}function UA(){return Be|0}function ha(){var o=0,l=0;Qr(8104,8,400)|0,Qr(8504,408,540)|0,o=9044,l=o+44|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));s[9088]=0,s[9089]=1,n[2273]=0,n[2274]=948,n[2275]=948,gr(17,8104,U|0)|0}function xl(o){o=o|0,mt(o+948|0)}function Mt(o){return o=y(o),((fP(o)|0)&2147483647)>>>0>2139095040|0}function Rn(o,l,u){o=o|0,l=l|0,u=u|0;e:do if(n[o+(l<<3)+4>>2]|0)o=o+(l<<3)|0;else{if((l|2|0)==3&&n[o+60>>2]|0){o=o+56|0;break}switch(l|0){case 0:case 2:case 4:case 5:{if(n[o+52>>2]|0){o=o+48|0;break e}break}default:}if(n[o+68>>2]|0){o=o+64|0;break}else{o=(l|1|0)==5?948:u;break}}while(!1);return o|0}function ga(o){o=o|0;var l=0;return l=_P(1e3)|0,Ya(o,(l|0)!=0,2456),n[2276]=(n[2276]|0)+1,Qr(l|0,8104,1e3)|0,s[o+2>>0]|0&&(n[l+4>>2]=2,n[l+12>>2]=4),n[l+976>>2]=o,l|0}function Ya(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;d=I,I=I+16|0,A=d,l||(n[A>>2]=u,Gg(o,5,3197,A)),I=d}function is(){return ga(956)|0}function uc(o){o=o|0;var l=0;return l=Jt(1e3)|0,fu(l,o),Ya(n[o+976>>2]|0,1,2456),n[2276]=(n[2276]|0)+1,n[l+944>>2]=0,l|0}function fu(o,l){o=o|0,l=l|0;var u=0;Qr(o|0,l|0,948)|0,xy(o+948|0,l+948|0),u=o+960|0,o=l+960|0,l=u+40|0;do n[u>>2]=n[o>>2],u=u+4|0,o=o+4|0;while((u|0)<(l|0))}function fc(o){o=o|0;var l=0,u=0,A=0,d=0;if(l=o+944|0,u=n[l>>2]|0,u|0&&(Ka(u+948|0,o)|0,n[l>>2]=0),u=Mi(o)|0,u|0){l=0;do n[(Bs(o,l)|0)+944>>2]=0,l=l+1|0;while((l|0)!=(u|0))}u=o+948|0,A=n[u>>2]|0,d=o+952|0,l=n[d>>2]|0,(l|0)!=(A|0)&&(n[d>>2]=l+(~((l+-4-A|0)>>>2)<<2)),kl(u),HP(o),n[2276]=(n[2276]|0)+-1}function Ka(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0;A=n[o>>2]|0,k=o+4|0,u=n[k>>2]|0,m=u;e:do if((A|0)==(u|0))d=A,B=4;else for(o=A;;){if((n[o>>2]|0)==(l|0)){d=o,B=4;break e}if(o=o+4|0,(o|0)==(u|0)){o=0;break}}while(!1);return(B|0)==4&&((d|0)!=(u|0)?(A=d+4|0,o=m-A|0,l=o>>2,l&&(BB(d|0,A|0,o|0)|0,u=n[k>>2]|0),o=d+(l<<2)|0,(u|0)==(o|0)||(n[k>>2]=u+(~((u+-4-o|0)>>>2)<<2)),o=1):o=0),o|0}function Mi(o){return o=o|0,(n[o+952>>2]|0)-(n[o+948>>2]|0)>>2|0}function Bs(o,l){o=o|0,l=l|0;var u=0;return u=n[o+948>>2]|0,(n[o+952>>2]|0)-u>>2>>>0>l>>>0?o=n[u+(l<<2)>>2]|0:o=0,o|0}function kl(o){o=o|0;var l=0,u=0,A=0,d=0;A=I,I=I+32|0,l=A,d=n[o>>2]|0,u=(n[o+4>>2]|0)-d|0,((n[o+8>>2]|0)-d|0)>>>0>u>>>0&&(d=u>>2,Ty(l,d,d,o+8|0),AP(o,l),Fy(l)),I=A}function mf(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0;M=Mi(o)|0;do if(M|0){if((n[(Bs(o,0)|0)+944>>2]|0)==(o|0)){if(!(Ka(o+948|0,l)|0))break;Qr(l+400|0,8504,540)|0,n[l+944>>2]=0,Oe(o);break}B=n[(n[o+976>>2]|0)+12>>2]|0,k=o+948|0,R=(B|0)==0,u=0,m=0;do A=n[(n[k>>2]|0)+(m<<2)>>2]|0,(A|0)==(l|0)?Oe(o):(d=uc(A)|0,n[(n[k>>2]|0)+(u<<2)>>2]=d,n[d+944>>2]=o,R||eU[B&15](A,d,o,u),u=u+1|0),m=m+1|0;while((m|0)!=(M|0));if(u>>>0<M>>>0){R=o+948|0,k=o+952|0,B=u,u=n[k>>2]|0;do m=(n[R>>2]|0)+(B<<2)|0,A=m+4|0,d=u-A|0,l=d>>2,l&&(BB(m|0,A|0,d|0)|0,u=n[k>>2]|0),d=u,A=m+(l<<2)|0,(d|0)!=(A|0)&&(u=d+(~((d+-4-A|0)>>>2)<<2)|0,n[k>>2]=u),B=B+1|0;while((B|0)!=(M|0))}}while(!1)}function Ac(o){o=o|0;var l=0,u=0,A=0,d=0;Bi(o,(Mi(o)|0)==0,2491),Bi(o,(n[o+944>>2]|0)==0,2545),l=o+948|0,u=n[l>>2]|0,A=o+952|0,d=n[A>>2]|0,(d|0)!=(u|0)&&(n[A>>2]=d+(~((d+-4-u|0)>>>2)<<2)),kl(l),l=o+976|0,u=n[l>>2]|0,Qr(o|0,8104,1e3)|0,s[u+2>>0]|0&&(n[o+4>>2]=2,n[o+12>>2]=4),n[l>>2]=u}function Bi(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;d=I,I=I+16|0,A=d,l||(n[A>>2]=u,Fo(o,5,3197,A)),I=d}function Tn(){return n[2276]|0}function pc(){var o=0;return o=_P(20)|0,Je((o|0)!=0,2592),n[2277]=(n[2277]|0)+1,n[o>>2]=n[239],n[o+4>>2]=n[240],n[o+8>>2]=n[241],n[o+12>>2]=n[242],n[o+16>>2]=n[243],o|0}function Je(o,l){o=o|0,l=l|0;var u=0,A=0;A=I,I=I+16|0,u=A,o||(n[u>>2]=l,Fo(0,5,3197,u)),I=A}function ot(o){o=o|0,HP(o),n[2277]=(n[2277]|0)+-1}function St(o,l){o=o|0,l=l|0;var u=0;l?(Bi(o,(Mi(o)|0)==0,2629),u=1):(u=0,l=0),n[o+964>>2]=l,n[o+988>>2]=u}function lr(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,m=A+8|0,d=A+4|0,B=A,n[d>>2]=l,Bi(o,(n[l+944>>2]|0)==0,2709),Bi(o,(n[o+964>>2]|0)==0,2763),ee(o),l=o+948|0,n[B>>2]=(n[l>>2]|0)+(u<<2),n[m>>2]=n[B>>2],ye(l,m,d)|0,n[(n[d>>2]|0)+944>>2]=o,Oe(o),I=A}function ee(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0;if(u=Mi(o)|0,u|0&&(n[(Bs(o,0)|0)+944>>2]|0)!=(o|0)){A=n[(n[o+976>>2]|0)+12>>2]|0,d=o+948|0,m=(A|0)==0,l=0;do B=n[(n[d>>2]|0)+(l<<2)>>2]|0,k=uc(B)|0,n[(n[d>>2]|0)+(l<<2)>>2]=k,n[k+944>>2]=o,m||eU[A&15](B,k,o,l),l=l+1|0;while((l|0)!=(u|0))}}function ye(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0,nt=0,Xe=0;nt=I,I=I+64|0,q=nt+52|0,k=nt+48|0,oe=nt+28|0,Ye=nt+24|0,Le=nt+20|0,Te=nt,A=n[o>>2]|0,m=A,l=A+((n[l>>2]|0)-m>>2<<2)|0,A=o+4|0,d=n[A>>2]|0,B=o+8|0;do if(d>>>0<(n[B>>2]|0)>>>0){if((l|0)==(d|0)){n[l>>2]=n[u>>2],n[A>>2]=(n[A>>2]|0)+4;break}pP(o,l,d,l+4|0),l>>>0<=u>>>0&&(u=(n[A>>2]|0)>>>0>u>>>0?u+4|0:u),n[l>>2]=n[u>>2]}else{A=(d-m>>2)+1|0,d=N(o)|0,d>>>0<A>>>0&&an(o),L=n[o>>2]|0,M=(n[B>>2]|0)-L|0,m=M>>1,Ty(Te,M>>2>>>0<d>>>1>>>0?m>>>0<A>>>0?A:m:d,l-L>>2,o+8|0),L=Te+8|0,A=n[L>>2]|0,m=Te+12|0,M=n[m>>2]|0,B=M,R=A;do if((A|0)==(M|0)){if(M=Te+4|0,A=n[M>>2]|0,Xe=n[Te>>2]|0,d=Xe,A>>>0<=Xe>>>0){A=B-d>>1,A=A|0?A:1,Ty(oe,A,A>>>2,n[Te+16>>2]|0),n[Ye>>2]=n[M>>2],n[Le>>2]=n[L>>2],n[k>>2]=n[Ye>>2],n[q>>2]=n[Le>>2],X1(oe,k,q),A=n[Te>>2]|0,n[Te>>2]=n[oe>>2],n[oe>>2]=A,A=oe+4|0,Xe=n[M>>2]|0,n[M>>2]=n[A>>2],n[A>>2]=Xe,A=oe+8|0,Xe=n[L>>2]|0,n[L>>2]=n[A>>2],n[A>>2]=Xe,A=oe+12|0,Xe=n[m>>2]|0,n[m>>2]=n[A>>2],n[A>>2]=Xe,Fy(oe),A=n[L>>2]|0;break}m=A,B=((m-d>>2)+1|0)/-2|0,k=A+(B<<2)|0,d=R-m|0,m=d>>2,m&&(BB(k|0,A|0,d|0)|0,A=n[M>>2]|0),Xe=k+(m<<2)|0,n[L>>2]=Xe,n[M>>2]=A+(B<<2),A=Xe}while(!1);n[A>>2]=n[u>>2],n[L>>2]=(n[L>>2]|0)+4,l=hP(o,Te,l)|0,Fy(Te)}while(!1);return I=nt,l|0}function Oe(o){o=o|0;var l=0;do{if(l=o+984|0,s[l>>0]|0)break;s[l>>0]=1,h[o+504>>2]=y(ae),o=n[o+944>>2]|0}while(o|0)}function mt(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-4-A|0)>>>2)<<2)),It(u))}function Et(o){return o=o|0,n[o+944>>2]|0}function bt(o){o=o|0,Bi(o,(n[o+964>>2]|0)!=0,2832),Oe(o)}function tr(o){return o=o|0,(s[o+984>>0]|0)!=0|0}function pn(o,l){o=o|0,l=l|0,K8e(o,l,400)|0&&(Qr(o|0,l|0,400)|0,Oe(o))}function ci(o){o=o|0;var l=$e;return l=y(h[o+44>>2]),o=Mt(l)|0,y(o?y(0):l)}function qi(o){o=o|0;var l=$e;return l=y(h[o+48>>2]),Mt(l)|0&&(l=s[(n[o+976>>2]|0)+2>>0]|0?y(1):y(0)),y(l)}function Fn(o,l){o=o|0,l=l|0,n[o+980>>2]=l}function Ja(o){return o=o|0,n[o+980>>2]|0}function Iy(o,l){o=o|0,l=l|0;var u=0;u=o+4|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function q1(o){return o=o|0,n[o+4>>2]|0}function xo(o,l){o=o|0,l=l|0;var u=0;u=o+8|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function Cy(o){return o=o|0,n[o+8>>2]|0}function mh(o,l){o=o|0,l=l|0;var u=0;u=o+12|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function W1(o){return o=o|0,n[o+12>>2]|0}function ko(o,l){o=o|0,l=l|0;var u=0;u=o+16|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function yh(o){return o=o|0,n[o+16>>2]|0}function Eh(o,l){o=o|0,l=l|0;var u=0;u=o+20|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function Au(o){return o=o|0,n[o+20>>2]|0}function Ih(o,l){o=o|0,l=l|0;var u=0;u=o+24|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function Rg(o){return o=o|0,n[o+24>>2]|0}function Tg(o,l){o=o|0,l=l|0;var u=0;u=o+28|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function Fg(o){return o=o|0,n[o+28>>2]|0}function wy(o,l){o=o|0,l=l|0;var u=0;u=o+32|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function yf(o){return o=o|0,n[o+32>>2]|0}function Qo(o,l){o=o|0,l=l|0;var u=0;u=o+36|0,(n[u>>2]|0)!=(l|0)&&(n[u>>2]=l,Oe(o))}function Ql(o){return o=o|0,n[o+36>>2]|0}function Ch(o,l){o=o|0,l=y(l);var u=0;u=o+40|0,y(h[u>>2])!=l&&(h[u>>2]=l,Oe(o))}function Ng(o,l){o=o|0,l=y(l);var u=0;u=o+44|0,y(h[u>>2])!=l&&(h[u>>2]=l,Oe(o))}function Rl(o,l){o=o|0,l=y(l);var u=0;u=o+48|0,y(h[u>>2])!=l&&(h[u>>2]=l,Oe(o))}function Tl(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+52|0,d=o+56|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function By(o,l){o=o|0,l=y(l);var u=0,A=0;A=o+52|0,u=o+56|0,y(h[A>>2])==l&&(n[u>>2]|0)==2||(h[A>>2]=l,A=Mt(l)|0,n[u>>2]=A?3:2,Oe(o))}function _A(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+52|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function vy(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=(m^1)&1,d=o+132+(l<<3)|0,l=o+132+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function Sy(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=m?0:2,d=o+132+(l<<3)|0,l=o+132+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function HA(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=l+132+(u<<3)|0,l=n[A+4>>2]|0,u=o,n[u>>2]=n[A>>2],n[u+4>>2]=l}function jA(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=(m^1)&1,d=o+60+(l<<3)|0,l=o+60+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function W(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=m?0:2,d=o+60+(l<<3)|0,l=o+60+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function xt(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=l+60+(u<<3)|0,l=n[A+4>>2]|0,u=o,n[u>>2]=n[A>>2],n[u+4>>2]=l}function GA(o,l){o=o|0,l=l|0;var u=0;u=o+60+(l<<3)+4|0,(n[u>>2]|0)!=3&&(h[o+60+(l<<3)>>2]=y(ae),n[u>>2]=3,Oe(o))}function Ro(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=(m^1)&1,d=o+204+(l<<3)|0,l=o+204+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function Ef(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=m?0:2,d=o+204+(l<<3)|0,l=o+204+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function yt(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=l+204+(u<<3)|0,l=n[A+4>>2]|0,u=o,n[u>>2]=n[A>>2],n[u+4>>2]=l}function pu(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0,m=0;m=Mt(u)|0,A=(m^1)&1,d=o+276+(l<<3)|0,l=o+276+(l<<3)+4|0,m|y(h[d>>2])==u&&(n[l>>2]|0)==(A|0)||(h[d>>2]=u,n[l>>2]=A,Oe(o))}function Dy(o,l){return o=o|0,l=l|0,y(h[o+276+(l<<3)>>2])}function Og(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+348|0,d=o+352|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function V1(o,l){o=o|0,l=y(l);var u=0,A=0;A=o+348|0,u=o+352|0,y(h[A>>2])==l&&(n[u>>2]|0)==2||(h[A>>2]=l,A=Mt(l)|0,n[u>>2]=A?3:2,Oe(o))}function wh(o){o=o|0;var l=0;l=o+352|0,(n[l>>2]|0)!=3&&(h[o+348>>2]=y(ae),n[l>>2]=3,Oe(o))}function ur(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+348|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function zi(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+356|0,d=o+360|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function If(o,l){o=o|0,l=y(l);var u=0,A=0;A=o+356|0,u=o+360|0,y(h[A>>2])==l&&(n[u>>2]|0)==2||(h[A>>2]=l,A=Mt(l)|0,n[u>>2]=A?3:2,Oe(o))}function za(o){o=o|0;var l=0;l=o+360|0,(n[l>>2]|0)!=3&&(h[o+356>>2]=y(ae),n[l>>2]=3,Oe(o))}function Lg(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+356|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function hu(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+364|0,d=o+368|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function Cf(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=m?0:2,A=o+364|0,d=o+368|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function wt(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+364|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function mi(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+372|0,d=o+376|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function qA(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=m?0:2,A=o+372|0,d=o+376|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function Za(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+372|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function da(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+380|0,d=o+384|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function Xa(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=m?0:2,A=o+380|0,d=o+384|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function Mg(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+380|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function Bh(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=(m^1)&1,A=o+388|0,d=o+392|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function Ug(o,l){o=o|0,l=y(l);var u=0,A=0,d=0,m=0;m=Mt(l)|0,u=m?0:2,A=o+388|0,d=o+392|0,m|y(h[A>>2])==l&&(n[d>>2]|0)==(u|0)||(h[A>>2]=l,n[d>>2]=u,Oe(o))}function by(o,l){o=o|0,l=l|0;var u=0,A=0;A=l+388|0,u=n[A+4>>2]|0,l=o,n[l>>2]=n[A>>2],n[l+4>>2]=u}function WA(o,l){o=o|0,l=y(l);var u=0;u=o+396|0,y(h[u>>2])!=l&&(h[u>>2]=l,Oe(o))}function _g(o){return o=o|0,y(h[o+396>>2])}function gu(o){return o=o|0,y(h[o+400>>2])}function du(o){return o=o|0,y(h[o+404>>2])}function wf(o){return o=o|0,y(h[o+408>>2])}function Os(o){return o=o|0,y(h[o+412>>2])}function mu(o){return o=o|0,y(h[o+416>>2])}function qn(o){return o=o|0,y(h[o+420>>2])}function ss(o,l){switch(o=o|0,l=l|0,Bi(o,(l|0)<6,2918),l|0){case 0:{l=(n[o+496>>2]|0)==2?5:4;break}case 2:{l=(n[o+496>>2]|0)==2?4:5;break}default:}return y(h[o+424+(l<<2)>>2])}function Pi(o,l){switch(o=o|0,l=l|0,Bi(o,(l|0)<6,2918),l|0){case 0:{l=(n[o+496>>2]|0)==2?5:4;break}case 2:{l=(n[o+496>>2]|0)==2?4:5;break}default:}return y(h[o+448+(l<<2)>>2])}function VA(o,l){switch(o=o|0,l=l|0,Bi(o,(l|0)<6,2918),l|0){case 0:{l=(n[o+496>>2]|0)==2?5:4;break}case 2:{l=(n[o+496>>2]|0)==2?4:5;break}default:}return y(h[o+472+(l<<2)>>2])}function Bf(o,l){o=o|0,l=l|0;var u=0,A=$e;return u=n[o+4>>2]|0,(u|0)==(n[l+4>>2]|0)?u?(A=y(h[o>>2]),o=y(ce(y(A-y(h[l>>2]))))<y(999999974e-13)):o=1:o=0,o|0}function yn(o,l){o=y(o),l=y(l);var u=0;return Mt(o)|0?u=Mt(l)|0:u=y(ce(y(o-l)))<y(999999974e-13),u|0}function Hg(o,l){o=o|0,l=l|0,jg(o,l)}function jg(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u+4|0,n[A>>2]=0,n[A+4>>2]=0,n[A+8>>2]=0,au(A|0,o|0,l|0,0),Fo(o,3,(s[A+11>>0]|0)<0?n[A>>2]|0:A,u),mHe(A),I=u}function os(o,l,u,A){o=y(o),l=y(l),u=u|0,A=A|0;var d=$e;o=y(o*l),d=y(KM(o,y(1)));do if(yn(d,y(0))|0)o=y(o-d);else{if(o=y(o-d),yn(d,y(1))|0){o=y(o+y(1));break}if(u){o=y(o+y(1));break}A||(d>y(.5)?d=y(1):(A=yn(d,y(.5))|0,d=y(A?1:0)),o=y(o+d))}while(!1);return y(o/l)}function Fl(o,l,u,A,d,m,B,k,R,M,L,q,oe){o=o|0,l=y(l),u=u|0,A=y(A),d=d|0,m=y(m),B=B|0,k=y(k),R=y(R),M=y(M),L=y(L),q=y(q),oe=oe|0;var Ye=0,Le=$e,Te=$e,nt=$e,Xe=$e,ft=$e,He=$e;return R<y(0)|M<y(0)?oe=0:(oe|0&&(Le=y(h[oe+4>>2]),Le!=y(0))?(nt=y(os(l,Le,0,0)),Xe=y(os(A,Le,0,0)),Te=y(os(m,Le,0,0)),Le=y(os(k,Le,0,0))):(Te=m,nt=l,Le=k,Xe=A),(d|0)==(o|0)?Ye=yn(Te,nt)|0:Ye=0,(B|0)==(u|0)?oe=yn(Le,Xe)|0:oe=0,!Ye&&(ft=y(l-L),!(To(o,ft,R)|0))&&!(vf(o,ft,d,R)|0)?Ye=Sf(o,ft,d,m,R)|0:Ye=1,!oe&&(He=y(A-q),!(To(u,He,M)|0))&&!(vf(u,He,B,M)|0)?oe=Sf(u,He,B,k,M)|0:oe=1,oe=Ye&oe),oe|0}function To(o,l,u){return o=o|0,l=y(l),u=y(u),(o|0)==1?o=yn(l,u)|0:o=0,o|0}function vf(o,l,u,A){return o=o|0,l=y(l),u=u|0,A=y(A),(o|0)==2&(u|0)==0?l>=A?o=1:o=yn(l,A)|0:o=0,o|0}function Sf(o,l,u,A,d){return o=o|0,l=y(l),u=u|0,A=y(A),d=y(d),(o|0)==2&(u|0)==2&A>l?d<=l?o=1:o=yn(l,d)|0:o=0,o|0}function Nl(o,l,u,A,d,m,B,k,R,M,L){o=o|0,l=y(l),u=y(u),A=A|0,d=d|0,m=m|0,B=y(B),k=y(k),R=R|0,M=M|0,L=L|0;var q=0,oe=0,Ye=0,Le=0,Te=$e,nt=$e,Xe=0,ft=0,He=0,Ve=0,Lt=0,Gr=0,fr=0,$t=0,Rr=0,Hr=0,cr=0,jn=$e,Lo=$e,Mo=$e,Uo=0,il=0;cr=I,I=I+160|0,$t=cr+152|0,fr=cr+120|0,Gr=cr+104|0,He=cr+72|0,Le=cr+56|0,Lt=cr+8|0,ft=cr,Ve=(n[2279]|0)+1|0,n[2279]=Ve,Rr=o+984|0,s[Rr>>0]|0&&(n[o+512>>2]|0)!=(n[2278]|0)?Xe=4:(n[o+516>>2]|0)==(A|0)?Hr=0:Xe=4,(Xe|0)==4&&(n[o+520>>2]=0,n[o+924>>2]=-1,n[o+928>>2]=-1,h[o+932>>2]=y(-1),h[o+936>>2]=y(-1),Hr=1);e:do if(n[o+964>>2]|0)if(Te=y(En(o,2,B)),nt=y(En(o,0,B)),q=o+916|0,Mo=y(h[q>>2]),Lo=y(h[o+920>>2]),jn=y(h[o+932>>2]),Fl(d,l,m,u,n[o+924>>2]|0,Mo,n[o+928>>2]|0,Lo,jn,y(h[o+936>>2]),Te,nt,L)|0)Xe=22;else if(Ye=n[o+520>>2]|0,!Ye)Xe=21;else for(oe=0;;){if(q=o+524+(oe*24|0)|0,jn=y(h[q>>2]),Lo=y(h[o+524+(oe*24|0)+4>>2]),Mo=y(h[o+524+(oe*24|0)+16>>2]),Fl(d,l,m,u,n[o+524+(oe*24|0)+8>>2]|0,jn,n[o+524+(oe*24|0)+12>>2]|0,Lo,Mo,y(h[o+524+(oe*24|0)+20>>2]),Te,nt,L)|0){Xe=22;break e}if(oe=oe+1|0,oe>>>0>=Ye>>>0){Xe=21;break}}else{if(R){if(q=o+916|0,!(yn(y(h[q>>2]),l)|0)){Xe=21;break}if(!(yn(y(h[o+920>>2]),u)|0)){Xe=21;break}if((n[o+924>>2]|0)!=(d|0)){Xe=21;break}q=(n[o+928>>2]|0)==(m|0)?q:0,Xe=22;break}if(Ye=n[o+520>>2]|0,!Ye)Xe=21;else for(oe=0;;){if(q=o+524+(oe*24|0)|0,yn(y(h[q>>2]),l)|0&&yn(y(h[o+524+(oe*24|0)+4>>2]),u)|0&&(n[o+524+(oe*24|0)+8>>2]|0)==(d|0)&&(n[o+524+(oe*24|0)+12>>2]|0)==(m|0)){Xe=22;break e}if(oe=oe+1|0,oe>>>0>=Ye>>>0){Xe=21;break}}}while(!1);do if((Xe|0)==21)s[11697]|0?(q=0,Xe=28):(q=0,Xe=31);else if((Xe|0)==22){if(oe=(s[11697]|0)!=0,!((q|0)!=0&(Hr^1)))if(oe){Xe=28;break}else{Xe=31;break}Le=q+16|0,n[o+908>>2]=n[Le>>2],Ye=q+20|0,n[o+912>>2]=n[Ye>>2],(s[11698]|0)==0|oe^1||(n[ft>>2]=yu(Ve)|0,n[ft+4>>2]=Ve,Fo(o,4,2972,ft),oe=n[o+972>>2]|0,oe|0&&sp[oe&127](o),d=ma(d,R)|0,m=ma(m,R)|0,il=+y(h[Le>>2]),Uo=+y(h[Ye>>2]),n[Lt>>2]=d,n[Lt+4>>2]=m,E[Lt+8>>3]=+l,E[Lt+16>>3]=+u,E[Lt+24>>3]=il,E[Lt+32>>3]=Uo,n[Lt+40>>2]=M,Fo(o,4,2989,Lt))}while(!1);return(Xe|0)==28&&(oe=yu(Ve)|0,n[Le>>2]=oe,n[Le+4>>2]=Ve,n[Le+8>>2]=Hr?3047:11699,Fo(o,4,3038,Le),oe=n[o+972>>2]|0,oe|0&&sp[oe&127](o),Lt=ma(d,R)|0,Xe=ma(m,R)|0,n[He>>2]=Lt,n[He+4>>2]=Xe,E[He+8>>3]=+l,E[He+16>>3]=+u,n[He+24>>2]=M,Fo(o,4,3049,He),Xe=31),(Xe|0)==31&&(Ls(o,l,u,A,d,m,B,k,R,L),s[11697]|0&&(oe=n[2279]|0,Lt=yu(oe)|0,n[Gr>>2]=Lt,n[Gr+4>>2]=oe,n[Gr+8>>2]=Hr?3047:11699,Fo(o,4,3083,Gr),oe=n[o+972>>2]|0,oe|0&&sp[oe&127](o),Lt=ma(d,R)|0,Gr=ma(m,R)|0,Uo=+y(h[o+908>>2]),il=+y(h[o+912>>2]),n[fr>>2]=Lt,n[fr+4>>2]=Gr,E[fr+8>>3]=Uo,E[fr+16>>3]=il,n[fr+24>>2]=M,Fo(o,4,3092,fr)),n[o+516>>2]=A,q||(oe=o+520|0,q=n[oe>>2]|0,(q|0)==16&&(s[11697]|0&&Fo(o,4,3124,$t),n[oe>>2]=0,q=0),R?q=o+916|0:(n[oe>>2]=q+1,q=o+524+(q*24|0)|0),h[q>>2]=l,h[q+4>>2]=u,n[q+8>>2]=d,n[q+12>>2]=m,n[q+16>>2]=n[o+908>>2],n[q+20>>2]=n[o+912>>2],q=0)),R&&(n[o+416>>2]=n[o+908>>2],n[o+420>>2]=n[o+912>>2],s[o+985>>0]=1,s[Rr>>0]=0),n[2279]=(n[2279]|0)+-1,n[o+512>>2]=n[2278],I=cr,Hr|(q|0)==0|0}function En(o,l,u){o=o|0,l=l|0,u=y(u);var A=$e;return A=y(J(o,l,u)),y(A+y(re(o,l,u)))}function Fo(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=I,I=I+16|0,d=m,n[d>>2]=A,o?A=n[o+976>>2]|0:A=0,Dh(A,o,l,u,d),I=m}function yu(o){return o=o|0,(o>>>0>60?3201:3201+(60-o)|0)|0}function ma(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;return d=I,I=I+32|0,u=d+12|0,A=d,n[u>>2]=n[254],n[u+4>>2]=n[255],n[u+8>>2]=n[256],n[A>>2]=n[257],n[A+4>>2]=n[258],n[A+8>>2]=n[259],(o|0)>2?o=11699:o=n[(l?A:u)+(o<<2)>>2]|0,I=d,o|0}function Ls(o,l,u,A,d,m,B,k,R,M){o=o|0,l=y(l),u=y(u),A=A|0,d=d|0,m=m|0,B=y(B),k=y(k),R=R|0,M=M|0;var L=0,q=0,oe=0,Ye=0,Le=$e,Te=$e,nt=$e,Xe=$e,ft=$e,He=$e,Ve=$e,Lt=0,Gr=0,fr=0,$t=$e,Rr=$e,Hr=0,cr=$e,jn=0,Lo=0,Mo=0,Uo=0,il=0,Gh=0,qh=0,dc=0,Wh=0,Nf=0,Of=0,Vh=0,Yh=0,Kh=0,ln=0,mc=0,Jh=0,Du=0,zh=$e,Zh=$e,Lf=$e,Mf=$e,bu=$e,Ao=0,Gl=0,Ca=0,yc=0,ap=0,lp=$e,Uf=$e,cp=$e,up=$e,po=$e,Hs=$e,Ec=0,Vn=$e,fp=$e,_o=$e,Pu=$e,Ho=$e,xu=$e,Ap=0,pp=0,ku=$e,ho=$e,Ic=0,hp=0,gp=0,dp=0,Nr=$e,fi=0,js=0,jo=0,go=0,Mr=0,Ar=0,Cc=0,zt=$e,mp=0,vi=0;Cc=I,I=I+16|0,Ao=Cc+12|0,Gl=Cc+8|0,Ca=Cc+4|0,yc=Cc,Bi(o,(d|0)==0|(Mt(l)|0)^1,3326),Bi(o,(m|0)==0|(Mt(u)|0)^1,3406),js=pt(o,A)|0,n[o+496>>2]=js,Mr=dr(2,js)|0,Ar=dr(0,js)|0,h[o+440>>2]=y(J(o,Mr,B)),h[o+444>>2]=y(re(o,Mr,B)),h[o+428>>2]=y(J(o,Ar,B)),h[o+436>>2]=y(re(o,Ar,B)),h[o+464>>2]=y(vr(o,Mr)),h[o+468>>2]=y(_n(o,Mr)),h[o+452>>2]=y(vr(o,Ar)),h[o+460>>2]=y(_n(o,Ar)),h[o+488>>2]=y(yi(o,Mr,B)),h[o+492>>2]=y(vs(o,Mr,B)),h[o+476>>2]=y(yi(o,Ar,B)),h[o+484>>2]=y(vs(o,Ar,B));do if(n[o+964>>2]|0)JA(o,l,u,d,m,B,k);else{if(jo=o+948|0,go=(n[o+952>>2]|0)-(n[jo>>2]|0)>>2,!go){lP(o,l,u,d,m,B,k);break}if(!R&&Y1(o,l,u,d,m,B,k)|0)break;ee(o),mc=o+508|0,s[mc>>0]=0,Mr=dr(n[o+4>>2]|0,js)|0,Ar=ky(Mr,js)|0,fi=ge(Mr)|0,Jh=n[o+8>>2]|0,hp=o+28|0,Du=(n[hp>>2]|0)!=0,Ho=fi?B:k,ku=fi?k:B,zh=y(Ph(o,Mr,B)),Zh=y(K1(o,Mr,B)),Le=y(Ph(o,Ar,B)),xu=y($a(o,Mr,B)),ho=y($a(o,Ar,B)),fr=fi?d:m,Ic=fi?m:d,Nr=fi?xu:ho,ft=fi?ho:xu,Pu=y(En(o,2,B)),Xe=y(En(o,0,B)),Te=y(y(Xr(o+364|0,B))-Nr),nt=y(y(Xr(o+380|0,B))-Nr),He=y(y(Xr(o+372|0,k))-ft),Ve=y(y(Xr(o+388|0,k))-ft),Lf=fi?Te:He,Mf=fi?nt:Ve,Pu=y(l-Pu),l=y(Pu-Nr),Mt(l)|0?Nr=l:Nr=y(ri(y(fd(l,nt)),Te)),fp=y(u-Xe),l=y(fp-ft),Mt(l)|0?_o=l:_o=y(ri(y(fd(l,Ve)),He)),Te=fi?Nr:_o,Vn=fi?_o:Nr;e:do if((fr|0)==1)for(A=0,q=0;;){if(L=Bs(o,q)|0,!A)y(zA(L))>y(0)&&y(xh(L))>y(0)?A=L:A=0;else if(J1(L)|0){Ye=0;break e}if(q=q+1|0,q>>>0>=go>>>0){Ye=A;break}}else Ye=0;while(!1);Lt=Ye+500|0,Gr=Ye+504|0,A=0,L=0,l=y(0),oe=0;do{if(q=n[(n[jo>>2]|0)+(oe<<2)>>2]|0,(n[q+36>>2]|0)==1)Qy(q),s[q+985>>0]=1,s[q+984>>0]=0;else{Df(q),R&&Sh(q,pt(q,js)|0,Te,Vn,Nr);do if((n[q+24>>2]|0)!=1)if((q|0)==(Ye|0)){n[Lt>>2]=n[2278],h[Gr>>2]=y(0);break}else{cP(o,q,Nr,d,_o,Nr,_o,m,js,M);break}else L|0&&(n[L+960>>2]=q),n[q+960>>2]=0,L=q,A=A|0?A:q;while(!1);Hs=y(h[q+504>>2]),l=y(l+y(Hs+y(En(q,Mr,Nr))))}oe=oe+1|0}while((oe|0)!=(go|0));for(Mo=l>Te,Ec=Du&((fr|0)==2&Mo)?1:fr,jn=(Ic|0)==1,il=jn&(R^1),Gh=(Ec|0)==1,qh=(Ec|0)==2,dc=976+(Mr<<2)|0,Wh=(Ic|2|0)==2,Kh=jn&(Du^1),Nf=1040+(Ar<<2)|0,Of=1040+(Mr<<2)|0,Vh=976+(Ar<<2)|0,Yh=(Ic|0)!=1,Mo=Du&((fr|0)!=0&Mo),Lo=o+976|0,jn=jn^1,l=Te,Hr=0,Uo=0,Hs=y(0),bu=y(0);;){e:do if(Hr>>>0<go>>>0)for(Gr=n[jo>>2]|0,oe=0,Ve=y(0),He=y(0),nt=y(0),Te=y(0),q=0,L=0,Ye=Hr;;){if(Lt=n[Gr+(Ye<<2)>>2]|0,(n[Lt+36>>2]|0)!=1&&(n[Lt+940>>2]=Uo,(n[Lt+24>>2]|0)!=1)){if(Xe=y(En(Lt,Mr,Nr)),ln=n[dc>>2]|0,u=y(Xr(Lt+380+(ln<<3)|0,Ho)),ft=y(h[Lt+504>>2]),u=y(fd(u,ft)),u=y(ri(y(Xr(Lt+364+(ln<<3)|0,Ho)),u)),Du&(oe|0)!=0&y(Xe+y(He+u))>l){m=oe,Xe=Ve,fr=Ye;break e}Xe=y(Xe+u),u=y(He+Xe),Xe=y(Ve+Xe),J1(Lt)|0&&(nt=y(nt+y(zA(Lt))),Te=y(Te-y(ft*y(xh(Lt))))),L|0&&(n[L+960>>2]=Lt),n[Lt+960>>2]=0,oe=oe+1|0,L=Lt,q=q|0?q:Lt}else Xe=Ve,u=He;if(Ye=Ye+1|0,Ye>>>0<go>>>0)Ve=Xe,He=u;else{m=oe,fr=Ye;break}}else m=0,Xe=y(0),nt=y(0),Te=y(0),q=0,fr=Hr;while(!1);ln=nt>y(0)&nt<y(1),$t=ln?y(1):nt,ln=Te>y(0)&Te<y(1),Ve=ln?y(1):Te;do if(Gh)ln=51;else if(Xe<Lf&((Mt(Lf)|0)^1))l=Lf,ln=51;else if(Xe>Mf&((Mt(Mf)|0)^1))l=Mf,ln=51;else if(s[(n[Lo>>2]|0)+3>>0]|0)ln=51;else{if($t!=y(0)&&y(zA(o))!=y(0)){ln=53;break}l=Xe,ln=53}while(!1);if((ln|0)==51&&(ln=0,Mt(l)|0?ln=53:(Rr=y(l-Xe),cr=l)),(ln|0)==53&&(ln=0,Xe<y(0)?(Rr=y(-Xe),cr=l):(Rr=y(0),cr=l)),!il&&(ap=(q|0)==0,!ap)){oe=n[dc>>2]|0,Ye=Rr<y(0),ft=y(Rr/Ve),Lt=Rr>y(0),He=y(Rr/$t),nt=y(0),Xe=y(0),l=y(0),L=q;do u=y(Xr(L+380+(oe<<3)|0,Ho)),Te=y(Xr(L+364+(oe<<3)|0,Ho)),Te=y(fd(u,y(ri(Te,y(h[L+504>>2]))))),Ye?(u=y(Te*y(xh(L))),u!=y(-0)&&(zt=y(Te-y(ft*u)),lp=y(Wn(L,Mr,zt,cr,Nr)),zt!=lp)&&(nt=y(nt-y(lp-Te)),l=y(l+u))):Lt&&(Uf=y(zA(L)),Uf!=y(0))&&(zt=y(Te+y(He*Uf)),cp=y(Wn(L,Mr,zt,cr,Nr)),zt!=cp)&&(nt=y(nt-y(cp-Te)),Xe=y(Xe-Uf)),L=n[L+960>>2]|0;while(L|0);if(l=y(Ve+l),Te=y(Rr+nt),ap)l=y(0);else{ft=y($t+Xe),Ye=n[dc>>2]|0,Lt=Te<y(0),Gr=l==y(0),He=y(Te/l),oe=Te>y(0),ft=y(Te/ft),l=y(0);do{zt=y(Xr(q+380+(Ye<<3)|0,Ho)),nt=y(Xr(q+364+(Ye<<3)|0,Ho)),nt=y(fd(zt,y(ri(nt,y(h[q+504>>2]))))),Lt?(zt=y(nt*y(xh(q))),Te=y(-zt),zt!=y(-0)?(zt=y(He*Te),Te=y(Wn(q,Mr,y(nt+(Gr?Te:zt)),cr,Nr))):Te=nt):oe&&(up=y(zA(q)),up!=y(0))?Te=y(Wn(q,Mr,y(nt+y(ft*up)),cr,Nr)):Te=nt,l=y(l-y(Te-nt)),Xe=y(En(q,Mr,Nr)),u=y(En(q,Ar,Nr)),Te=y(Te+Xe),h[Gl>>2]=Te,n[yc>>2]=1,nt=y(h[q+396>>2]);e:do if(Mt(nt)|0){L=Mt(Vn)|0;do if(!L){if(Mo|(uo(q,Ar,Vn)|0|jn)||(as(o,q)|0)!=4||(n[(Ol(q,Ar)|0)+4>>2]|0)==3||(n[(Ll(q,Ar)|0)+4>>2]|0)==3)break;h[Ao>>2]=Vn,n[Ca>>2]=1;break e}while(!1);if(uo(q,Ar,Vn)|0){L=n[q+992+(n[Vh>>2]<<2)>>2]|0,zt=y(u+y(Xr(L,Vn))),h[Ao>>2]=zt,L=Yh&(n[L+4>>2]|0)==2,n[Ca>>2]=((Mt(zt)|0|L)^1)&1;break}else{h[Ao>>2]=Vn,n[Ca>>2]=L?0:2;break}}else zt=y(Te-Xe),$t=y(zt/nt),zt=y(nt*zt),n[Ca>>2]=1,h[Ao>>2]=y(u+(fi?$t:zt));while(!1);Eu(q,Mr,cr,Nr,yc,Gl),Eu(q,Ar,Vn,Nr,Ca,Ao);do if(!(uo(q,Ar,Vn)|0)&&(as(o,q)|0)==4){if((n[(Ol(q,Ar)|0)+4>>2]|0)==3){L=0;break}L=(n[(Ll(q,Ar)|0)+4>>2]|0)!=3}else L=0;while(!1);zt=y(h[Gl>>2]),$t=y(h[Ao>>2]),mp=n[yc>>2]|0,vi=n[Ca>>2]|0,Nl(q,fi?zt:$t,fi?$t:zt,js,fi?mp:vi,fi?vi:mp,Nr,_o,R&(L^1),3488,M)|0,s[mc>>0]=s[mc>>0]|s[q+508>>0],q=n[q+960>>2]|0}while(q|0)}}else l=y(0);if(l=y(Rr+l),vi=l<y(0)&1,s[mc>>0]=vi|c[mc>>0],qh&l>y(0)?(L=n[dc>>2]|0,n[o+364+(L<<3)+4>>2]|0&&(po=y(Xr(o+364+(L<<3)|0,Ho)),po>=y(0))?Te=y(ri(y(0),y(po-y(cr-l)))):Te=y(0)):Te=l,Lt=Hr>>>0<fr>>>0,Lt){Ye=n[jo>>2]|0,oe=Hr,L=0;do q=n[Ye+(oe<<2)>>2]|0,n[q+24>>2]|0||(L=((n[(Ol(q,Mr)|0)+4>>2]|0)==3&1)+L|0,L=L+((n[(Ll(q,Mr)|0)+4>>2]|0)==3&1)|0),oe=oe+1|0;while((oe|0)!=(fr|0));L?(Xe=y(0),u=y(0)):ln=101}else ln=101;e:do if((ln|0)==101)switch(ln=0,Jh|0){case 1:{L=0,Xe=y(Te*y(.5)),u=y(0);break e}case 2:{L=0,Xe=Te,u=y(0);break e}case 3:{if(m>>>0<=1){L=0,Xe=y(0),u=y(0);break e}u=y((m+-1|0)>>>0),L=0,Xe=y(0),u=y(y(ri(Te,y(0)))/u);break e}case 5:{u=y(Te/y((m+1|0)>>>0)),L=0,Xe=u;break e}case 4:{u=y(Te/y(m>>>0)),L=0,Xe=y(u*y(.5));break e}default:{L=0,Xe=y(0),u=y(0);break e}}while(!1);if(l=y(zh+Xe),Lt){nt=y(Te/y(L|0)),oe=n[jo>>2]|0,q=Hr,Te=y(0);do{L=n[oe+(q<<2)>>2]|0;e:do if((n[L+36>>2]|0)!=1){switch(n[L+24>>2]|0){case 1:{if(ya(L,Mr)|0){if(!R)break e;zt=y(ZA(L,Mr,cr)),zt=y(zt+y(vr(o,Mr))),zt=y(zt+y(J(L,Mr,Nr))),h[L+400+(n[Of>>2]<<2)>>2]=zt;break e}break}case 0:if(vi=(n[(Ol(L,Mr)|0)+4>>2]|0)==3,zt=y(nt+l),l=vi?zt:l,R&&(vi=L+400+(n[Of>>2]<<2)|0,h[vi>>2]=y(l+y(h[vi>>2]))),vi=(n[(Ll(L,Mr)|0)+4>>2]|0)==3,zt=y(nt+l),l=vi?zt:l,il){zt=y(u+y(En(L,Mr,Nr))),Te=Vn,l=y(l+y(zt+y(h[L+504>>2])));break e}else{l=y(l+y(u+y(XA(L,Mr,Nr)))),Te=y(ri(Te,y(XA(L,Ar,Nr))));break e}default:}R&&(zt=y(Xe+y(vr(o,Mr))),vi=L+400+(n[Of>>2]<<2)|0,h[vi>>2]=y(zt+y(h[vi>>2])))}while(!1);q=q+1|0}while((q|0)!=(fr|0))}else Te=y(0);if(u=y(Zh+l),Wh?Xe=y(y(Wn(o,Ar,y(ho+Te),ku,B))-ho):Xe=Vn,nt=y(y(Wn(o,Ar,y(ho+(Kh?Vn:Te)),ku,B))-ho),Lt&R){q=Hr;do{oe=n[(n[jo>>2]|0)+(q<<2)>>2]|0;do if((n[oe+36>>2]|0)!=1){if((n[oe+24>>2]|0)==1){if(ya(oe,Ar)|0){if(zt=y(ZA(oe,Ar,Vn)),zt=y(zt+y(vr(o,Ar))),zt=y(zt+y(J(oe,Ar,Nr))),L=n[Nf>>2]|0,h[oe+400+(L<<2)>>2]=zt,!(Mt(zt)|0))break}else L=n[Nf>>2]|0;zt=y(vr(o,Ar)),h[oe+400+(L<<2)>>2]=y(zt+y(J(oe,Ar,Nr)));break}L=as(o,oe)|0;do if((L|0)==4){if((n[(Ol(oe,Ar)|0)+4>>2]|0)==3){ln=139;break}if((n[(Ll(oe,Ar)|0)+4>>2]|0)==3){ln=139;break}if(uo(oe,Ar,Vn)|0){l=Le;break}mp=n[oe+908+(n[dc>>2]<<2)>>2]|0,n[Ao>>2]=mp,l=y(h[oe+396>>2]),vi=Mt(l)|0,Te=(n[S>>2]=mp,y(h[S>>2])),vi?l=nt:(Rr=y(En(oe,Ar,Nr)),zt=y(Te/l),l=y(l*Te),l=y(Rr+(fi?zt:l))),h[Gl>>2]=l,h[Ao>>2]=y(y(En(oe,Mr,Nr))+Te),n[Ca>>2]=1,n[yc>>2]=1,Eu(oe,Mr,cr,Nr,Ca,Ao),Eu(oe,Ar,Vn,Nr,yc,Gl),l=y(h[Ao>>2]),Rr=y(h[Gl>>2]),zt=fi?l:Rr,l=fi?Rr:l,vi=((Mt(zt)|0)^1)&1,Nl(oe,zt,l,js,vi,((Mt(l)|0)^1)&1,Nr,_o,1,3493,M)|0,l=Le}else ln=139;while(!1);e:do if((ln|0)==139){ln=0,l=y(Xe-y(XA(oe,Ar,Nr)));do if((n[(Ol(oe,Ar)|0)+4>>2]|0)==3){if((n[(Ll(oe,Ar)|0)+4>>2]|0)!=3)break;l=y(Le+y(ri(y(0),y(l*y(.5)))));break e}while(!1);if((n[(Ll(oe,Ar)|0)+4>>2]|0)==3){l=Le;break}if((n[(Ol(oe,Ar)|0)+4>>2]|0)==3){l=y(Le+y(ri(y(0),l)));break}switch(L|0){case 1:{l=Le;break e}case 2:{l=y(Le+y(l*y(.5)));break e}default:{l=y(Le+l);break e}}}while(!1);zt=y(Hs+l),vi=oe+400+(n[Nf>>2]<<2)|0,h[vi>>2]=y(zt+y(h[vi>>2]))}while(!1);q=q+1|0}while((q|0)!=(fr|0))}if(Hs=y(Hs+nt),bu=y(ri(bu,u)),m=Uo+1|0,fr>>>0>=go>>>0)break;l=cr,Hr=fr,Uo=m}do if(R){if(L=m>>>0>1,!L&&!(DL(o)|0))break;if(!(Mt(Vn)|0)){l=y(Vn-Hs);e:do switch(n[o+12>>2]|0){case 3:{Le=y(Le+l),He=y(0);break}case 2:{Le=y(Le+y(l*y(.5))),He=y(0);break}case 4:{Vn>Hs?He=y(l/y(m>>>0)):He=y(0);break}case 7:if(Vn>Hs){Le=y(Le+y(l/y(m<<1>>>0))),He=y(l/y(m>>>0)),He=L?He:y(0);break e}else{Le=y(Le+y(l*y(.5))),He=y(0);break e}case 6:{He=y(l/y(Uo>>>0)),He=Vn>Hs&L?He:y(0);break}default:He=y(0)}while(!1);if(m|0)for(Lt=1040+(Ar<<2)|0,Gr=976+(Ar<<2)|0,Ye=0,q=0;;){e:do if(q>>>0<go>>>0)for(Te=y(0),nt=y(0),l=y(0),oe=q;;){L=n[(n[jo>>2]|0)+(oe<<2)>>2]|0;do if((n[L+36>>2]|0)!=1&&!(n[L+24>>2]|0)){if((n[L+940>>2]|0)!=(Ye|0))break e;if(bL(L,Ar)|0&&(zt=y(h[L+908+(n[Gr>>2]<<2)>>2]),l=y(ri(l,y(zt+y(En(L,Ar,Nr)))))),(as(o,L)|0)!=5)break;po=y(qg(L)),po=y(po+y(J(L,0,Nr))),zt=y(h[L+912>>2]),zt=y(y(zt+y(En(L,0,Nr)))-po),po=y(ri(nt,po)),zt=y(ri(Te,zt)),Te=zt,nt=po,l=y(ri(l,y(po+zt)))}while(!1);if(L=oe+1|0,L>>>0<go>>>0)oe=L;else{oe=L;break}}else nt=y(0),l=y(0),oe=q;while(!1);if(ft=y(He+l),u=Le,Le=y(Le+ft),q>>>0<oe>>>0){Xe=y(u+nt),L=q;do{q=n[(n[jo>>2]|0)+(L<<2)>>2]|0;e:do if((n[q+36>>2]|0)!=1&&!(n[q+24>>2]|0))switch(as(o,q)|0){case 1:{zt=y(u+y(J(q,Ar,Nr))),h[q+400+(n[Lt>>2]<<2)>>2]=zt;break e}case 3:{zt=y(y(Le-y(re(q,Ar,Nr)))-y(h[q+908+(n[Gr>>2]<<2)>>2])),h[q+400+(n[Lt>>2]<<2)>>2]=zt;break e}case 2:{zt=y(u+y(y(ft-y(h[q+908+(n[Gr>>2]<<2)>>2]))*y(.5))),h[q+400+(n[Lt>>2]<<2)>>2]=zt;break e}case 4:{if(zt=y(u+y(J(q,Ar,Nr))),h[q+400+(n[Lt>>2]<<2)>>2]=zt,uo(q,Ar,Vn)|0||(fi?(Te=y(h[q+908>>2]),l=y(Te+y(En(q,Mr,Nr))),nt=ft):(nt=y(h[q+912>>2]),nt=y(nt+y(En(q,Ar,Nr))),l=ft,Te=y(h[q+908>>2])),yn(l,Te)|0&&yn(nt,y(h[q+912>>2]))|0))break e;Nl(q,l,nt,js,1,1,Nr,_o,1,3501,M)|0;break e}case 5:{h[q+404>>2]=y(y(Xe-y(qg(q)))+y(ZA(q,0,Vn)));break e}default:break e}while(!1);L=L+1|0}while((L|0)!=(oe|0))}if(Ye=Ye+1|0,(Ye|0)==(m|0))break;q=oe}}}while(!1);if(h[o+908>>2]=y(Wn(o,2,Pu,B,B)),h[o+912>>2]=y(Wn(o,0,fp,k,B)),Ec|0&&(Ap=n[o+32>>2]|0,pp=(Ec|0)==2,!(pp&(Ap|0)!=2))?pp&(Ap|0)==2&&(l=y(xu+cr),l=y(ri(y(fd(l,y(Wg(o,Mr,bu,Ho)))),xu)),ln=198):(l=y(Wn(o,Mr,bu,Ho,B)),ln=198),(ln|0)==198&&(h[o+908+(n[976+(Mr<<2)>>2]<<2)>>2]=l),Ic|0&&(gp=n[o+32>>2]|0,dp=(Ic|0)==2,!(dp&(gp|0)!=2))?dp&(gp|0)==2&&(l=y(ho+Vn),l=y(ri(y(fd(l,y(Wg(o,Ar,y(ho+Hs),ku)))),ho)),ln=204):(l=y(Wn(o,Ar,y(ho+Hs),ku,B)),ln=204),(ln|0)==204&&(h[o+908+(n[976+(Ar<<2)>>2]<<2)>>2]=l),R){if((n[hp>>2]|0)==2){q=976+(Ar<<2)|0,oe=1040+(Ar<<2)|0,L=0;do Ye=Bs(o,L)|0,n[Ye+24>>2]|0||(mp=n[q>>2]|0,zt=y(h[o+908+(mp<<2)>>2]),vi=Ye+400+(n[oe>>2]<<2)|0,zt=y(zt-y(h[vi>>2])),h[vi>>2]=y(zt-y(h[Ye+908+(mp<<2)>>2]))),L=L+1|0;while((L|0)!=(go|0))}if(A|0){L=fi?Ec:d;do PL(o,A,Nr,L,_o,js,M),A=n[A+960>>2]|0;while(A|0)}if(L=(Mr|2|0)==3,q=(Ar|2|0)==3,L|q){A=0;do oe=n[(n[jo>>2]|0)+(A<<2)>>2]|0,(n[oe+36>>2]|0)!=1&&(L&&z1(o,oe,Mr),q&&z1(o,oe,Ar)),A=A+1|0;while((A|0)!=(go|0))}}}while(!1);I=Cc}function vh(o,l){o=o|0,l=y(l);var u=0;Ya(o,l>=y(0),3147),u=l==y(0),h[o+4>>2]=u?y(0):l}function YA(o,l,u,A){o=o|0,l=y(l),u=y(u),A=A|0;var d=$e,m=$e,B=0,k=0,R=0;n[2278]=(n[2278]|0)+1,Df(o),uo(o,2,l)|0?(d=y(Xr(n[o+992>>2]|0,l)),R=1,d=y(d+y(En(o,2,l)))):(d=y(Xr(o+380|0,l)),d>=y(0)?R=2:(R=((Mt(l)|0)^1)&1,d=l)),uo(o,0,u)|0?(m=y(Xr(n[o+996>>2]|0,u)),k=1,m=y(m+y(En(o,0,l)))):(m=y(Xr(o+388|0,u)),m>=y(0)?k=2:(k=((Mt(u)|0)^1)&1,m=u)),B=o+976|0,Nl(o,d,m,A,R,k,l,u,1,3189,n[B>>2]|0)|0&&(Sh(o,n[o+496>>2]|0,l,u,l),KA(o,y(h[(n[B>>2]|0)+4>>2]),y(0),y(0)),s[11696]|0)&&Hg(o,7)}function Df(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;k=I,I=I+32|0,B=k+24|0,m=k+16|0,A=k+8|0,d=k,u=0;do l=o+380+(u<<3)|0,n[o+380+(u<<3)+4>>2]|0&&(R=l,M=n[R+4>>2]|0,L=A,n[L>>2]=n[R>>2],n[L+4>>2]=M,L=o+364+(u<<3)|0,M=n[L+4>>2]|0,R=d,n[R>>2]=n[L>>2],n[R+4>>2]=M,n[m>>2]=n[A>>2],n[m+4>>2]=n[A+4>>2],n[B>>2]=n[d>>2],n[B+4>>2]=n[d+4>>2],Bf(m,B)|0)||(l=o+348+(u<<3)|0),n[o+992+(u<<2)>>2]=l,u=u+1|0;while((u|0)!=2);I=k}function uo(o,l,u){o=o|0,l=l|0,u=y(u);var A=0;switch(o=n[o+992+(n[976+(l<<2)>>2]<<2)>>2]|0,n[o+4>>2]|0){case 0:case 3:{o=0;break}case 1:{y(h[o>>2])<y(0)?o=0:A=5;break}case 2:{y(h[o>>2])<y(0)?o=0:o=(Mt(u)|0)^1;break}default:A=5}return(A|0)==5&&(o=1),o|0}function Xr(o,l){switch(o=o|0,l=y(l),n[o+4>>2]|0){case 2:{l=y(y(y(h[o>>2])*l)/y(100));break}case 1:{l=y(h[o>>2]);break}default:l=y(ae)}return y(l)}function Sh(o,l,u,A,d){o=o|0,l=l|0,u=y(u),A=y(A),d=y(d);var m=0,B=$e;l=n[o+944>>2]|0?l:1,m=dr(n[o+4>>2]|0,l)|0,l=ky(m,l)|0,u=y(uP(o,m,u)),A=y(uP(o,l,A)),B=y(u+y(J(o,m,d))),h[o+400+(n[1040+(m<<2)>>2]<<2)>>2]=B,u=y(u+y(re(o,m,d))),h[o+400+(n[1e3+(m<<2)>>2]<<2)>>2]=u,u=y(A+y(J(o,l,d))),h[o+400+(n[1040+(l<<2)>>2]<<2)>>2]=u,d=y(A+y(re(o,l,d))),h[o+400+(n[1e3+(l<<2)>>2]<<2)>>2]=d}function KA(o,l,u,A){o=o|0,l=y(l),u=y(u),A=y(A);var d=0,m=0,B=$e,k=$e,R=0,M=0,L=$e,q=0,oe=$e,Ye=$e,Le=$e,Te=$e;if(l!=y(0)&&(d=o+400|0,Te=y(h[d>>2]),m=o+404|0,Le=y(h[m>>2]),q=o+416|0,Ye=y(h[q>>2]),M=o+420|0,B=y(h[M>>2]),oe=y(Te+u),L=y(Le+A),A=y(oe+Ye),k=y(L+B),R=(n[o+988>>2]|0)==1,h[d>>2]=y(os(Te,l,0,R)),h[m>>2]=y(os(Le,l,0,R)),u=y(KM(y(Ye*l),y(1))),yn(u,y(0))|0?m=0:m=(yn(u,y(1))|0)^1,u=y(KM(y(B*l),y(1))),yn(u,y(0))|0?d=0:d=(yn(u,y(1))|0)^1,Te=y(os(A,l,R&m,R&(m^1))),h[q>>2]=y(Te-y(os(oe,l,0,R))),Te=y(os(k,l,R&d,R&(d^1))),h[M>>2]=y(Te-y(os(L,l,0,R))),m=(n[o+952>>2]|0)-(n[o+948>>2]|0)>>2,m|0)){d=0;do KA(Bs(o,d)|0,l,oe,L),d=d+1|0;while((d|0)!=(m|0))}}function Py(o,l,u,A,d){switch(o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,u|0){case 5:case 0:{o=LZ(n[489]|0,A,d)|0;break}default:o=pHe(A,d)|0}return o|0}function Gg(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;d=I,I=I+16|0,m=d,n[m>>2]=A,Dh(o,0,l,u,m),I=d}function Dh(o,l,u,A,d){if(o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,o=o|0?o:956,iX[n[o+8>>2]&1](o,l,u,A,d)|0,(u|0)==5)Nt();else return}function hc(o,l,u){o=o|0,l=l|0,u=u|0,s[o+l>>0]=u&1}function xy(o,l){o=o|0,l=l|0;var u=0,A=0;n[o>>2]=0,n[o+4>>2]=0,n[o+8>>2]=0,u=l+4|0,A=(n[u>>2]|0)-(n[l>>2]|0)>>2,A|0&&(bh(o,A),kt(o,n[l>>2]|0,n[u>>2]|0,A))}function bh(o,l){o=o|0,l=l|0;var u=0;if((N(o)|0)>>>0<l>>>0&&an(o),l>>>0>1073741823)Nt();else{u=Jt(l<<2)|0,n[o+4>>2]=u,n[o>>2]=u,n[o+8>>2]=u+(l<<2);return}}function kt(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,A=o+4|0,o=u-l|0,(o|0)>0&&(Qr(n[A>>2]|0,l|0,o|0)|0,n[A>>2]=(n[A>>2]|0)+(o>>>2<<2))}function N(o){return o=o|0,1073741823}function J(o,l,u){return o=o|0,l=l|0,u=y(u),ge(l)|0&&n[o+96>>2]|0?o=o+92|0:o=Rn(o+60|0,n[1040+(l<<2)>>2]|0,992)|0,y(Ke(o,u))}function re(o,l,u){return o=o|0,l=l|0,u=y(u),ge(l)|0&&n[o+104>>2]|0?o=o+100|0:o=Rn(o+60|0,n[1e3+(l<<2)>>2]|0,992)|0,y(Ke(o,u))}function ge(o){return o=o|0,(o|1|0)==3|0}function Ke(o,l){return o=o|0,l=y(l),(n[o+4>>2]|0)==3?l=y(0):l=y(Xr(o,l)),y(l)}function pt(o,l){return o=o|0,l=l|0,o=n[o>>2]|0,(o|0?o:(l|0)>1?l:1)|0}function dr(o,l){o=o|0,l=l|0;var u=0;e:do if((l|0)==2){switch(o|0){case 2:{o=3;break e}case 3:break;default:{u=4;break e}}o=2}else u=4;while(!1);return o|0}function vr(o,l){o=o|0,l=l|0;var u=$e;return ge(l)|0&&n[o+312>>2]|0&&(u=y(h[o+308>>2]),u>=y(0))||(u=y(ri(y(h[(Rn(o+276|0,n[1040+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(u)}function _n(o,l){o=o|0,l=l|0;var u=$e;return ge(l)|0&&n[o+320>>2]|0&&(u=y(h[o+316>>2]),u>=y(0))||(u=y(ri(y(h[(Rn(o+276|0,n[1e3+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(u)}function yi(o,l,u){o=o|0,l=l|0,u=y(u);var A=$e;return ge(l)|0&&n[o+240>>2]|0&&(A=y(Xr(o+236|0,u)),A>=y(0))||(A=y(ri(y(Xr(Rn(o+204|0,n[1040+(l<<2)>>2]|0,992)|0,u)),y(0)))),y(A)}function vs(o,l,u){o=o|0,l=l|0,u=y(u);var A=$e;return ge(l)|0&&n[o+248>>2]|0&&(A=y(Xr(o+244|0,u)),A>=y(0))||(A=y(ri(y(Xr(Rn(o+204|0,n[1e3+(l<<2)>>2]|0,992)|0,u)),y(0)))),y(A)}function JA(o,l,u,A,d,m,B){o=o|0,l=y(l),u=y(u),A=A|0,d=d|0,m=y(m),B=y(B);var k=$e,R=$e,M=$e,L=$e,q=$e,oe=$e,Ye=0,Le=0,Te=0;Te=I,I=I+16|0,Ye=Te,Le=o+964|0,Bi(o,(n[Le>>2]|0)!=0,3519),k=y($a(o,2,l)),R=y($a(o,0,l)),M=y(En(o,2,l)),L=y(En(o,0,l)),Mt(l)|0?q=l:q=y(ri(y(0),y(y(l-M)-k))),Mt(u)|0?oe=u:oe=y(ri(y(0),y(y(u-L)-R))),(A|0)==1&(d|0)==1?(h[o+908>>2]=y(Wn(o,2,y(l-M),m,m)),l=y(Wn(o,0,y(u-L),B,m))):(sX[n[Le>>2]&1](Ye,o,q,A,oe,d),q=y(k+y(h[Ye>>2])),oe=y(l-M),h[o+908>>2]=y(Wn(o,2,(A|2|0)==2?q:oe,m,m)),oe=y(R+y(h[Ye+4>>2])),l=y(u-L),l=y(Wn(o,0,(d|2|0)==2?oe:l,B,m))),h[o+912>>2]=l,I=Te}function lP(o,l,u,A,d,m,B){o=o|0,l=y(l),u=y(u),A=A|0,d=d|0,m=y(m),B=y(B);var k=$e,R=$e,M=$e,L=$e;M=y($a(o,2,m)),k=y($a(o,0,m)),L=y(En(o,2,m)),R=y(En(o,0,m)),l=y(l-L),h[o+908>>2]=y(Wn(o,2,(A|2|0)==2?M:l,m,m)),u=y(u-R),h[o+912>>2]=y(Wn(o,0,(d|2|0)==2?k:u,B,m))}function Y1(o,l,u,A,d,m,B){o=o|0,l=y(l),u=y(u),A=A|0,d=d|0,m=y(m),B=y(B);var k=0,R=$e,M=$e;return k=(A|0)==2,!(l<=y(0)&k)&&!(u<=y(0)&(d|0)==2)&&!((A|0)==1&(d|0)==1)?o=0:(R=y(En(o,0,m)),M=y(En(o,2,m)),k=l<y(0)&k|(Mt(l)|0),l=y(l-M),h[o+908>>2]=y(Wn(o,2,k?y(0):l,m,m)),l=y(u-R),k=u<y(0)&(d|0)==2|(Mt(u)|0),h[o+912>>2]=y(Wn(o,0,k?y(0):l,B,m)),o=1),o|0}function ky(o,l){return o=o|0,l=l|0,Vg(o)|0?o=dr(2,l)|0:o=0,o|0}function Ph(o,l,u){return o=o|0,l=l|0,u=y(u),u=y(yi(o,l,u)),y(u+y(vr(o,l)))}function K1(o,l,u){return o=o|0,l=l|0,u=y(u),u=y(vs(o,l,u)),y(u+y(_n(o,l)))}function $a(o,l,u){o=o|0,l=l|0,u=y(u);var A=$e;return A=y(Ph(o,l,u)),y(A+y(K1(o,l,u)))}function J1(o){return o=o|0,n[o+24>>2]|0?o=0:y(zA(o))!=y(0)?o=1:o=y(xh(o))!=y(0),o|0}function zA(o){o=o|0;var l=$e;if(n[o+944>>2]|0){if(l=y(h[o+44>>2]),Mt(l)|0)return l=y(h[o+40>>2]),o=l>y(0)&((Mt(l)|0)^1),y(o?l:y(0))}else l=y(0);return y(l)}function xh(o){o=o|0;var l=$e,u=0,A=$e;do if(n[o+944>>2]|0){if(l=y(h[o+48>>2]),Mt(l)|0){if(u=s[(n[o+976>>2]|0)+2>>0]|0,!(u<<24>>24)&&(A=y(h[o+40>>2]),A<y(0)&((Mt(A)|0)^1))){l=y(-A);break}l=u<<24>>24?y(1):y(0)}}else l=y(0);while(!1);return y(l)}function Qy(o){o=o|0;var l=0,u=0;if(nE(o+400|0,0,540)|0,s[o+985>>0]=1,ee(o),u=Mi(o)|0,u|0){l=o+948|0,o=0;do Qy(n[(n[l>>2]|0)+(o<<2)>>2]|0),o=o+1|0;while((o|0)!=(u|0))}}function cP(o,l,u,A,d,m,B,k,R,M){o=o|0,l=l|0,u=y(u),A=A|0,d=y(d),m=y(m),B=y(B),k=k|0,R=R|0,M=M|0;var L=0,q=$e,oe=0,Ye=0,Le=$e,Te=$e,nt=0,Xe=$e,ft=0,He=$e,Ve=0,Lt=0,Gr=0,fr=0,$t=0,Rr=0,Hr=0,cr=0,jn=0,Lo=0;jn=I,I=I+16|0,Gr=jn+12|0,fr=jn+8|0,$t=jn+4|0,Rr=jn,cr=dr(n[o+4>>2]|0,R)|0,Ve=ge(cr)|0,q=y(Xr(xL(l)|0,Ve?m:B)),Lt=uo(l,2,m)|0,Hr=uo(l,0,B)|0;do if(!(Mt(q)|0)&&!(Mt(Ve?u:d)|0)){if(L=l+504|0,!(Mt(y(h[L>>2]))|0)&&(!(Z1(n[l+976>>2]|0,0)|0)||(n[l+500>>2]|0)==(n[2278]|0)))break;h[L>>2]=y(ri(q,y($a(l,cr,m))))}else oe=7;while(!1);do if((oe|0)==7){if(ft=Ve^1,!(ft|Lt^1)){B=y(Xr(n[l+992>>2]|0,m)),h[l+504>>2]=y(ri(B,y($a(l,2,m))));break}if(!(Ve|Hr^1)){B=y(Xr(n[l+996>>2]|0,B)),h[l+504>>2]=y(ri(B,y($a(l,0,m))));break}h[Gr>>2]=y(ae),h[fr>>2]=y(ae),n[$t>>2]=0,n[Rr>>2]=0,Xe=y(En(l,2,m)),He=y(En(l,0,m)),Lt?(Le=y(Xe+y(Xr(n[l+992>>2]|0,m))),h[Gr>>2]=Le,n[$t>>2]=1,Ye=1):(Ye=0,Le=y(ae)),Hr?(q=y(He+y(Xr(n[l+996>>2]|0,B))),h[fr>>2]=q,n[Rr>>2]=1,L=1):(L=0,q=y(ae)),oe=n[o+32>>2]|0,Ve&(oe|0)==2?oe=2:Mt(Le)|0&&!(Mt(u)|0)&&(h[Gr>>2]=u,n[$t>>2]=2,Ye=2,Le=u),!((oe|0)==2&ft)&&Mt(q)|0&&!(Mt(d)|0)&&(h[fr>>2]=d,n[Rr>>2]=2,L=2,q=d),Te=y(h[l+396>>2]),nt=Mt(Te)|0;do if(nt)oe=Ye;else{if((Ye|0)==1&ft){h[fr>>2]=y(y(Le-Xe)/Te),n[Rr>>2]=1,L=1,oe=1;break}Ve&(L|0)==1?(h[Gr>>2]=y(Te*y(q-He)),n[$t>>2]=1,L=1,oe=1):oe=Ye}while(!1);Lo=Mt(u)|0,Ye=(as(o,l)|0)!=4,!(Ve|Lt|((A|0)!=1|Lo)|(Ye|(oe|0)==1))&&(h[Gr>>2]=u,n[$t>>2]=1,!nt)&&(h[fr>>2]=y(y(u-Xe)/Te),n[Rr>>2]=1,L=1),!(Hr|ft|((k|0)!=1|(Mt(d)|0))|(Ye|(L|0)==1))&&(h[fr>>2]=d,n[Rr>>2]=1,!nt)&&(h[Gr>>2]=y(Te*y(d-He)),n[$t>>2]=1),Eu(l,2,m,m,$t,Gr),Eu(l,0,B,m,Rr,fr),u=y(h[Gr>>2]),d=y(h[fr>>2]),Nl(l,u,d,R,n[$t>>2]|0,n[Rr>>2]|0,m,B,0,3565,M)|0,B=y(h[l+908+(n[976+(cr<<2)>>2]<<2)>>2]),h[l+504>>2]=y(ri(B,y($a(l,cr,m))))}while(!1);n[l+500>>2]=n[2278],I=jn}function Wn(o,l,u,A,d){return o=o|0,l=l|0,u=y(u),A=y(A),d=y(d),A=y(Wg(o,l,u,A)),y(ri(A,y($a(o,l,d))))}function as(o,l){return o=o|0,l=l|0,l=l+20|0,l=n[(n[l>>2]|0?l:o+16|0)>>2]|0,(l|0)==5&&Vg(n[o+4>>2]|0)|0&&(l=1),l|0}function Ol(o,l){return o=o|0,l=l|0,ge(l)|0&&n[o+96>>2]|0?l=4:l=n[1040+(l<<2)>>2]|0,o+60+(l<<3)|0}function Ll(o,l){return o=o|0,l=l|0,ge(l)|0&&n[o+104>>2]|0?l=5:l=n[1e3+(l<<2)>>2]|0,o+60+(l<<3)|0}function Eu(o,l,u,A,d,m){switch(o=o|0,l=l|0,u=y(u),A=y(A),d=d|0,m=m|0,u=y(Xr(o+380+(n[976+(l<<2)>>2]<<3)|0,u)),u=y(u+y(En(o,l,A))),n[d>>2]|0){case 2:case 1:{d=Mt(u)|0,A=y(h[m>>2]),h[m>>2]=d|A<u?A:u;break}case 0:{Mt(u)|0||(n[d>>2]=2,h[m>>2]=u);break}default:}}function ya(o,l){return o=o|0,l=l|0,o=o+132|0,ge(l)|0&&n[(Rn(o,4,948)|0)+4>>2]|0?o=1:o=(n[(Rn(o,n[1040+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,o|0}function ZA(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0;return o=o+132|0,ge(l)|0&&(A=Rn(o,4,948)|0,(n[A+4>>2]|0)!=0)?d=4:(A=Rn(o,n[1040+(l<<2)>>2]|0,948)|0,n[A+4>>2]|0?d=4:u=y(0)),(d|0)==4&&(u=y(Xr(A,u))),y(u)}function XA(o,l,u){o=o|0,l=l|0,u=y(u);var A=$e;return A=y(h[o+908+(n[976+(l<<2)>>2]<<2)>>2]),A=y(A+y(J(o,l,u))),y(A+y(re(o,l,u)))}function DL(o){o=o|0;var l=0,u=0,A=0;e:do if(Vg(n[o+4>>2]|0)|0)l=0;else if((n[o+16>>2]|0)!=5)if(u=Mi(o)|0,!u)l=0;else for(l=0;;){if(A=Bs(o,l)|0,!(n[A+24>>2]|0)&&(n[A+20>>2]|0)==5){l=1;break e}if(l=l+1|0,l>>>0>=u>>>0){l=0;break}}else l=1;while(!1);return l|0}function bL(o,l){o=o|0,l=l|0;var u=$e;return u=y(h[o+908+(n[976+(l<<2)>>2]<<2)>>2]),u>=y(0)&((Mt(u)|0)^1)|0}function qg(o){o=o|0;var l=$e,u=0,A=0,d=0,m=0,B=0,k=0,R=$e;if(u=n[o+968>>2]|0,u)R=y(h[o+908>>2]),l=y(h[o+912>>2]),l=y(eX[u&0](o,R,l)),Bi(o,(Mt(l)|0)^1,3573);else{m=Mi(o)|0;do if(m|0){for(u=0,d=0;;){if(A=Bs(o,d)|0,n[A+940>>2]|0){B=8;break}if((n[A+24>>2]|0)!=1)if(k=(as(o,A)|0)==5,k){u=A;break}else u=u|0?u:A;if(d=d+1|0,d>>>0>=m>>>0){B=8;break}}if((B|0)==8&&!u)break;return l=y(qg(u)),y(l+y(h[u+404>>2]))}while(!1);l=y(h[o+912>>2])}return y(l)}function Wg(o,l,u,A){o=o|0,l=l|0,u=y(u),A=y(A);var d=$e,m=0;return Vg(l)|0?(l=1,m=3):ge(l)|0?(l=0,m=3):(A=y(ae),d=y(ae)),(m|0)==3&&(d=y(Xr(o+364+(l<<3)|0,A)),A=y(Xr(o+380+(l<<3)|0,A))),m=A<u&(A>=y(0)&((Mt(A)|0)^1)),u=m?A:u,m=d>=y(0)&((Mt(d)|0)^1)&u<d,y(m?d:u)}function PL(o,l,u,A,d,m,B){o=o|0,l=l|0,u=y(u),A=A|0,d=y(d),m=m|0,B=B|0;var k=$e,R=$e,M=0,L=0,q=$e,oe=$e,Ye=$e,Le=0,Te=0,nt=0,Xe=0,ft=$e,He=0;nt=dr(n[o+4>>2]|0,m)|0,Le=ky(nt,m)|0,Te=ge(nt)|0,q=y(En(l,2,u)),oe=y(En(l,0,u)),uo(l,2,u)|0?k=y(q+y(Xr(n[l+992>>2]|0,u))):ya(l,2)|0&&Ry(l,2)|0?(k=y(h[o+908>>2]),R=y(vr(o,2)),R=y(k-y(R+y(_n(o,2)))),k=y(ZA(l,2,u)),k=y(Wn(l,2,y(R-y(k+y(kh(l,2,u)))),u,u))):k=y(ae),uo(l,0,d)|0?R=y(oe+y(Xr(n[l+996>>2]|0,d))):ya(l,0)|0&&Ry(l,0)|0?(R=y(h[o+912>>2]),ft=y(vr(o,0)),ft=y(R-y(ft+y(_n(o,0)))),R=y(ZA(l,0,d)),R=y(Wn(l,0,y(ft-y(R+y(kh(l,0,d)))),d,u))):R=y(ae),M=Mt(k)|0,L=Mt(R)|0;do if(M^L&&(Ye=y(h[l+396>>2]),!(Mt(Ye)|0)))if(M){k=y(q+y(y(R-oe)*Ye));break}else{ft=y(oe+y(y(k-q)/Ye)),R=L?ft:R;break}while(!1);L=Mt(k)|0,M=Mt(R)|0,L|M&&(He=(L^1)&1,A=u>y(0)&((A|0)!=0&L),k=Te?k:A?u:k,Nl(l,k,R,m,Te?He:A?2:He,L&(M^1)&1,k,R,0,3623,B)|0,k=y(h[l+908>>2]),k=y(k+y(En(l,2,u))),R=y(h[l+912>>2]),R=y(R+y(En(l,0,u)))),Nl(l,k,R,m,1,1,k,R,1,3635,B)|0,Ry(l,nt)|0&&!(ya(l,nt)|0)?(He=n[976+(nt<<2)>>2]|0,ft=y(h[o+908+(He<<2)>>2]),ft=y(ft-y(h[l+908+(He<<2)>>2])),ft=y(ft-y(_n(o,nt))),ft=y(ft-y(re(l,nt,u))),ft=y(ft-y(kh(l,nt,Te?u:d))),h[l+400+(n[1040+(nt<<2)>>2]<<2)>>2]=ft):Xe=21;do if((Xe|0)==21){if(!(ya(l,nt)|0)&&(n[o+8>>2]|0)==1){He=n[976+(nt<<2)>>2]|0,ft=y(h[o+908+(He<<2)>>2]),ft=y(y(ft-y(h[l+908+(He<<2)>>2]))*y(.5)),h[l+400+(n[1040+(nt<<2)>>2]<<2)>>2]=ft;break}!(ya(l,nt)|0)&&(n[o+8>>2]|0)==2&&(He=n[976+(nt<<2)>>2]|0,ft=y(h[o+908+(He<<2)>>2]),ft=y(ft-y(h[l+908+(He<<2)>>2])),h[l+400+(n[1040+(nt<<2)>>2]<<2)>>2]=ft)}while(!1);Ry(l,Le)|0&&!(ya(l,Le)|0)?(He=n[976+(Le<<2)>>2]|0,ft=y(h[o+908+(He<<2)>>2]),ft=y(ft-y(h[l+908+(He<<2)>>2])),ft=y(ft-y(_n(o,Le))),ft=y(ft-y(re(l,Le,u))),ft=y(ft-y(kh(l,Le,Te?d:u))),h[l+400+(n[1040+(Le<<2)>>2]<<2)>>2]=ft):Xe=30;do if((Xe|0)==30&&!(ya(l,Le)|0)){if((as(o,l)|0)==2){He=n[976+(Le<<2)>>2]|0,ft=y(h[o+908+(He<<2)>>2]),ft=y(y(ft-y(h[l+908+(He<<2)>>2]))*y(.5)),h[l+400+(n[1040+(Le<<2)>>2]<<2)>>2]=ft;break}He=(as(o,l)|0)==3,He^(n[o+28>>2]|0)==2&&(He=n[976+(Le<<2)>>2]|0,ft=y(h[o+908+(He<<2)>>2]),ft=y(ft-y(h[l+908+(He<<2)>>2])),h[l+400+(n[1040+(Le<<2)>>2]<<2)>>2]=ft)}while(!1)}function z1(o,l,u){o=o|0,l=l|0,u=u|0;var A=$e,d=0;d=n[976+(u<<2)>>2]|0,A=y(h[l+908+(d<<2)>>2]),A=y(y(h[o+908+(d<<2)>>2])-A),A=y(A-y(h[l+400+(n[1040+(u<<2)>>2]<<2)>>2])),h[l+400+(n[1e3+(u<<2)>>2]<<2)>>2]=A}function Vg(o){return o=o|0,(o|1|0)==1|0}function xL(o){o=o|0;var l=$e;switch(n[o+56>>2]|0){case 0:case 3:{l=y(h[o+40>>2]),l>y(0)&((Mt(l)|0)^1)?o=s[(n[o+976>>2]|0)+2>>0]|0?1056:992:o=1056;break}default:o=o+52|0}return o|0}function Z1(o,l){return o=o|0,l=l|0,(s[o+l>>0]|0)!=0|0}function Ry(o,l){return o=o|0,l=l|0,o=o+132|0,ge(l)|0&&n[(Rn(o,5,948)|0)+4>>2]|0?o=1:o=(n[(Rn(o,n[1e3+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,o|0}function kh(o,l,u){o=o|0,l=l|0,u=y(u);var A=0,d=0;return o=o+132|0,ge(l)|0&&(A=Rn(o,5,948)|0,(n[A+4>>2]|0)!=0)?d=4:(A=Rn(o,n[1e3+(l<<2)>>2]|0,948)|0,n[A+4>>2]|0?d=4:u=y(0)),(d|0)==4&&(u=y(Xr(A,u))),y(u)}function uP(o,l,u){return o=o|0,l=l|0,u=y(u),ya(o,l)|0?u=y(ZA(o,l,u)):u=y(-y(kh(o,l,u))),y(u)}function fP(o){return o=y(o),h[S>>2]=o,n[S>>2]|0|0}function Ty(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>1073741823)Nt();else{d=Jt(l<<2)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<2)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<2)}function AP(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function Fy(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-4-l|0)>>>2)<<2)),o=n[o>>2]|0,o|0&&It(o)}function pP(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;if(B=o+4|0,k=n[B>>2]|0,d=k-A|0,m=d>>2,o=l+(m<<2)|0,o>>>0<u>>>0){A=k;do n[A>>2]=n[o>>2],o=o+4|0,A=(n[B>>2]|0)+4|0,n[B>>2]=A;while(o>>>0<u>>>0)}m|0&&BB(k+(0-m<<2)|0,l|0,d|0)|0}function hP(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0;return k=l+4|0,R=n[k>>2]|0,d=n[o>>2]|0,B=u,m=B-d|0,A=R+(0-(m>>2)<<2)|0,n[k>>2]=A,(m|0)>0&&Qr(A|0,d|0,m|0)|0,d=o+4|0,m=l+8|0,A=(n[d>>2]|0)-B|0,(A|0)>0&&(Qr(n[m>>2]|0,u|0,A|0)|0,n[m>>2]=(n[m>>2]|0)+(A>>>2<<2)),B=n[o>>2]|0,n[o>>2]=n[k>>2],n[k>>2]=B,B=n[d>>2]|0,n[d>>2]=n[m>>2],n[m>>2]=B,B=o+8|0,u=l+12|0,o=n[B>>2]|0,n[B>>2]=n[u>>2],n[u>>2]=o,n[l>>2]=n[k>>2],R|0}function X1(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;if(B=n[l>>2]|0,m=n[u>>2]|0,(B|0)!=(m|0)){d=o+8|0,u=((m+-4-B|0)>>>2)+1|0,o=B,A=n[d>>2]|0;do n[A>>2]=n[o>>2],A=(n[d>>2]|0)+4|0,n[d>>2]=A,o=o+4|0;while((o|0)!=(m|0));n[l>>2]=B+(u<<2)}}function $1(){ha()}function gP(){var o=0;return o=Jt(4)|0,eB(o),o|0}function eB(o){o=o|0,n[o>>2]=pc()|0}function dP(o){o=o|0,o|0&&(Yg(o),It(o))}function Yg(o){o=o|0,ot(n[o>>2]|0)}function kL(o,l,u){o=o|0,l=l|0,u=u|0,hc(n[o>>2]|0,l,u)}function Ny(o,l){o=o|0,l=y(l),vh(n[o>>2]|0,l)}function Oy(o,l){return o=o|0,l=l|0,Z1(n[o>>2]|0,l)|0}function Ly(){var o=0;return o=Jt(8)|0,Kg(o,0),o|0}function Kg(o,l){o=o|0,l=l|0,l?l=ga(n[l>>2]|0)|0:l=is()|0,n[o>>2]=l,n[o+4>>2]=0,Fn(l,o)}function My(o){o=o|0;var l=0;return l=Jt(8)|0,Kg(l,o),l|0}function Jg(o){o=o|0,o|0&&(Uy(o),It(o))}function Uy(o){o=o|0;var l=0;fc(n[o>>2]|0),l=o+4|0,o=n[l>>2]|0,n[l>>2]=0,o|0&&(bf(o),It(o))}function bf(o){o=o|0,Pf(o)}function Pf(o){o=o|0,o=n[o>>2]|0,o|0&&ja(o|0)}function tB(o){return o=o|0,Ja(o)|0}function rB(o){o=o|0;var l=0,u=0;u=o+4|0,l=n[u>>2]|0,n[u>>2]=0,l|0&&(bf(l),It(l)),Ac(n[o>>2]|0)}function _y(o,l){o=o|0,l=l|0,pn(n[o>>2]|0,n[l>>2]|0)}function QL(o,l){o=o|0,l=l|0,Ih(n[o>>2]|0,l)}function RL(o,l,u){o=o|0,l=l|0,u=+u,vy(n[o>>2]|0,l,y(u))}function Hy(o,l,u){o=o|0,l=l|0,u=+u,Sy(n[o>>2]|0,l,y(u))}function nB(o,l){o=o|0,l=l|0,mh(n[o>>2]|0,l)}function iB(o,l){o=o|0,l=l|0,ko(n[o>>2]|0,l)}function xr(o,l){o=o|0,l=l|0,Eh(n[o>>2]|0,l)}function fo(o,l){o=o|0,l=l|0,Iy(n[o>>2]|0,l)}function Zi(o,l){o=o|0,l=l|0,Tg(n[o>>2]|0,l)}function Ms(o,l){o=o|0,l=l|0,xo(n[o>>2]|0,l)}function $A(o,l,u){o=o|0,l=l|0,u=+u,jA(n[o>>2]|0,l,y(u))}function sB(o,l,u){o=o|0,l=l|0,u=+u,W(n[o>>2]|0,l,y(u))}function Ss(o,l){o=o|0,l=l|0,GA(n[o>>2]|0,l)}function jy(o,l){o=o|0,l=l|0,wy(n[o>>2]|0,l)}function Qh(o,l){o=o|0,l=l|0,Qo(n[o>>2]|0,l)}function zg(o,l){o=o|0,l=+l,Ch(n[o>>2]|0,y(l))}function Rh(o,l){o=o|0,l=+l,Tl(n[o>>2]|0,y(l))}function oB(o,l){o=o|0,l=+l,By(n[o>>2]|0,y(l))}function aB(o,l){o=o|0,l=+l,Ng(n[o>>2]|0,y(l))}function lB(o,l){o=o|0,l=+l,Rl(n[o>>2]|0,y(l))}function cB(o,l){o=o|0,l=+l,Og(n[o>>2]|0,y(l))}function xf(o,l){o=o|0,l=+l,V1(n[o>>2]|0,y(l))}function sr(o){o=o|0,wh(n[o>>2]|0)}function Gy(o,l){o=o|0,l=+l,zi(n[o>>2]|0,y(l))}function uB(o,l){o=o|0,l=+l,If(n[o>>2]|0,y(l))}function gc(o){o=o|0,za(n[o>>2]|0)}function kf(o,l){o=o|0,l=+l,hu(n[o>>2]|0,y(l))}function Zg(o,l){o=o|0,l=+l,Cf(n[o>>2]|0,y(l))}function Xg(o,l){o=o|0,l=+l,mi(n[o>>2]|0,y(l))}function fB(o,l){o=o|0,l=+l,qA(n[o>>2]|0,y(l))}function AB(o,l){o=o|0,l=+l,da(n[o>>2]|0,y(l))}function Iu(o,l){o=o|0,l=+l,Xa(n[o>>2]|0,y(l))}function $g(o,l){o=o|0,l=+l,Bh(n[o>>2]|0,y(l))}function pB(o,l){o=o|0,l=+l,Ug(n[o>>2]|0,y(l))}function qy(o,l){o=o|0,l=+l,WA(n[o>>2]|0,y(l))}function Cu(o,l,u){o=o|0,l=l|0,u=+u,pu(n[o>>2]|0,l,y(u))}function Wy(o,l,u){o=o|0,l=l|0,u=+u,Ro(n[o>>2]|0,l,y(u))}function ed(o,l,u){o=o|0,l=l|0,u=+u,Ef(n[o>>2]|0,l,y(u))}function td(o){return o=o|0,Rg(n[o>>2]|0)|0}function No(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;A=I,I=I+16|0,d=A,HA(d,n[l>>2]|0,u),Ds(o,d),I=A}function Ds(o,l){o=o|0,l=l|0,Ml(o,n[l+4>>2]|0,+y(h[l>>2]))}function Ml(o,l,u){o=o|0,l=l|0,u=+u,n[o>>2]=l,E[o+8>>3]=u}function Vy(o){return o=o|0,W1(n[o>>2]|0)|0}function Ea(o){return o=o|0,yh(n[o>>2]|0)|0}function mP(o){return o=o|0,Au(n[o>>2]|0)|0}function Th(o){return o=o|0,q1(n[o>>2]|0)|0}function hB(o){return o=o|0,Fg(n[o>>2]|0)|0}function TL(o){return o=o|0,Cy(n[o>>2]|0)|0}function yP(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;A=I,I=I+16|0,d=A,xt(d,n[l>>2]|0,u),Ds(o,d),I=A}function EP(o){return o=o|0,yf(n[o>>2]|0)|0}function Yy(o){return o=o|0,Ql(n[o>>2]|0)|0}function gB(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,_A(A,n[l>>2]|0),Ds(o,A),I=u}function Fh(o){return o=o|0,+ +y(ci(n[o>>2]|0))}function IP(o){return o=o|0,+ +y(qi(n[o>>2]|0))}function CP(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,ur(A,n[l>>2]|0),Ds(o,A),I=u}function rd(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,Lg(A,n[l>>2]|0),Ds(o,A),I=u}function FL(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,wt(A,n[l>>2]|0),Ds(o,A),I=u}function NL(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,Za(A,n[l>>2]|0),Ds(o,A),I=u}function wP(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,Mg(A,n[l>>2]|0),Ds(o,A),I=u}function BP(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,by(A,n[l>>2]|0),Ds(o,A),I=u}function ep(o){return o=o|0,+ +y(_g(n[o>>2]|0))}function OL(o,l){return o=o|0,l=l|0,+ +y(Dy(n[o>>2]|0,l))}function LL(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;A=I,I=I+16|0,d=A,yt(d,n[l>>2]|0,u),Ds(o,d),I=A}function wu(o,l,u){o=o|0,l=l|0,u=u|0,lr(n[o>>2]|0,n[l>>2]|0,u)}function ML(o,l){o=o|0,l=l|0,mf(n[o>>2]|0,n[l>>2]|0)}function vP(o){return o=o|0,Mi(n[o>>2]|0)|0}function UL(o){return o=o|0,o=Et(n[o>>2]|0)|0,o?o=tB(o)|0:o=0,o|0}function SP(o,l){return o=o|0,l=l|0,o=Bs(n[o>>2]|0,l)|0,o?o=tB(o)|0:o=0,o|0}function Qf(o,l){o=o|0,l=l|0;var u=0,A=0;A=Jt(4)|0,DP(A,l),u=o+4|0,l=n[u>>2]|0,n[u>>2]=A,l|0&&(bf(l),It(l)),St(n[o>>2]|0,1)}function DP(o,l){o=o|0,l=l|0,qL(o,l)}function _L(o,l,u,A,d,m){o=o|0,l=l|0,u=y(u),A=A|0,d=y(d),m=m|0;var B=0,k=0;B=I,I=I+16|0,k=B,bP(k,Ja(l)|0,+u,A,+d,m),h[o>>2]=y(+E[k>>3]),h[o+4>>2]=y(+E[k+8>>3]),I=B}function bP(o,l,u,A,d,m){o=o|0,l=l|0,u=+u,A=A|0,d=+d,m=m|0;var B=0,k=0,R=0,M=0,L=0;B=I,I=I+32|0,L=B+8|0,M=B+20|0,R=B,k=B+16|0,E[L>>3]=u,n[M>>2]=A,E[R>>3]=d,n[k>>2]=m,Ky(o,n[l+4>>2]|0,L,M,R,k),I=B}function Ky(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0;var B=0,k=0;B=I,I=I+16|0,k=B,_l(k),l=Us(l)|0,PP(o,l,+E[u>>3],n[A>>2]|0,+E[d>>3],n[m>>2]|0),Hl(k),I=B}function Us(o){return o=o|0,n[o>>2]|0}function PP(o,l,u,A,d,m){o=o|0,l=l|0,u=+u,A=A|0,d=+d,m=m|0;var B=0;B=Ia(dB()|0)|0,u=+el(u),A=Jy(A)|0,d=+el(d),HL(o,Zn(0,B|0,l|0,+u,A|0,+d,Jy(m)|0)|0)}function dB(){var o=0;return s[7608]|0||(yB(9120),o=7608,n[o>>2]=1,n[o+4>>2]=0),9120}function Ia(o){return o=o|0,n[o+8>>2]|0}function el(o){return o=+o,+ +Rf(o)}function Jy(o){return o=o|0,nd(o)|0}function HL(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;d=I,I=I+32|0,u=d,A=l,A&1?(tl(u,0),Ue(A|0,u|0)|0,mB(o,u),jL(u)):(n[o>>2]=n[l>>2],n[o+4>>2]=n[l+4>>2],n[o+8>>2]=n[l+8>>2],n[o+12>>2]=n[l+12>>2]),I=d}function tl(o,l){o=o|0,l=l|0,Bu(o,l),n[o+8>>2]=0,s[o+24>>0]=0}function mB(o,l){o=o|0,l=l|0,l=l+8|0,n[o>>2]=n[l>>2],n[o+4>>2]=n[l+4>>2],n[o+8>>2]=n[l+8>>2],n[o+12>>2]=n[l+12>>2]}function jL(o){o=o|0,s[o+24>>0]=0}function Bu(o,l){o=o|0,l=l|0,n[o>>2]=l}function nd(o){return o=o|0,o|0}function Rf(o){return o=+o,+o}function yB(o){o=o|0,Oo(o,EB()|0,4)}function EB(){return 1064}function Oo(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u,n[o+8>>2]=Gi(l|0,u+1|0)|0}function qL(o,l){o=o|0,l=l|0,l=n[l>>2]|0,n[o>>2]=l,su(l|0)}function xP(o){o=o|0;var l=0,u=0;u=o+4|0,l=n[u>>2]|0,n[u>>2]=0,l|0&&(bf(l),It(l)),St(n[o>>2]|0,0)}function kP(o){o=o|0,bt(n[o>>2]|0)}function zy(o){return o=o|0,tr(n[o>>2]|0)|0}function WL(o,l,u,A){o=o|0,l=+l,u=+u,A=A|0,YA(n[o>>2]|0,y(l),y(u),A)}function VL(o){return o=o|0,+ +y(gu(n[o>>2]|0))}function v(o){return o=o|0,+ +y(wf(n[o>>2]|0))}function D(o){return o=o|0,+ +y(du(n[o>>2]|0))}function Q(o){return o=o|0,+ +y(Os(n[o>>2]|0))}function H(o){return o=o|0,+ +y(mu(n[o>>2]|0))}function V(o){return o=o|0,+ +y(qn(n[o>>2]|0))}function ne(o,l){o=o|0,l=l|0,E[o>>3]=+y(gu(n[l>>2]|0)),E[o+8>>3]=+y(wf(n[l>>2]|0)),E[o+16>>3]=+y(du(n[l>>2]|0)),E[o+24>>3]=+y(Os(n[l>>2]|0)),E[o+32>>3]=+y(mu(n[l>>2]|0)),E[o+40>>3]=+y(qn(n[l>>2]|0))}function ve(o,l){return o=o|0,l=l|0,+ +y(ss(n[o>>2]|0,l))}function _e(o,l){return o=o|0,l=l|0,+ +y(Pi(n[o>>2]|0,l))}function ht(o,l){return o=o|0,l=l|0,+ +y(VA(n[o>>2]|0,l))}function Wt(){return Tn()|0}function Sr(){Lr(),Xt(),Xn(),Ei(),rl(),rt()}function Lr(){$Me(11713,4938,1)}function Xt(){yMe(10448)}function Xn(){$Le(10408)}function Ei(){wLe(10324)}function rl(){kNe(10096)}function rt(){We(9132)}function We(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0,nt=0,Xe=0,ft=0,He=0,Ve=0,Lt=0,Gr=0,fr=0,$t=0,Rr=0,Hr=0,cr=0,jn=0,Lo=0,Mo=0,Uo=0,il=0,Gh=0,qh=0,dc=0,Wh=0,Nf=0,Of=0,Vh=0,Yh=0,Kh=0,ln=0,mc=0,Jh=0,Du=0,zh=0,Zh=0,Lf=0,Mf=0,bu=0,Ao=0,Gl=0,Ca=0,yc=0,ap=0,lp=0,Uf=0,cp=0,up=0,po=0,Hs=0,Ec=0,Vn=0,fp=0,_o=0,Pu=0,Ho=0,xu=0,Ap=0,pp=0,ku=0,ho=0,Ic=0,hp=0,gp=0,dp=0,Nr=0,fi=0,js=0,jo=0,go=0,Mr=0,Ar=0,Cc=0;l=I,I=I+672|0,u=l+656|0,Cc=l+648|0,Ar=l+640|0,Mr=l+632|0,go=l+624|0,jo=l+616|0,js=l+608|0,fi=l+600|0,Nr=l+592|0,dp=l+584|0,gp=l+576|0,hp=l+568|0,Ic=l+560|0,ho=l+552|0,ku=l+544|0,pp=l+536|0,Ap=l+528|0,xu=l+520|0,Ho=l+512|0,Pu=l+504|0,_o=l+496|0,fp=l+488|0,Vn=l+480|0,Ec=l+472|0,Hs=l+464|0,po=l+456|0,up=l+448|0,cp=l+440|0,Uf=l+432|0,lp=l+424|0,ap=l+416|0,yc=l+408|0,Ca=l+400|0,Gl=l+392|0,Ao=l+384|0,bu=l+376|0,Mf=l+368|0,Lf=l+360|0,Zh=l+352|0,zh=l+344|0,Du=l+336|0,Jh=l+328|0,mc=l+320|0,ln=l+312|0,Kh=l+304|0,Yh=l+296|0,Vh=l+288|0,Of=l+280|0,Nf=l+272|0,Wh=l+264|0,dc=l+256|0,qh=l+248|0,Gh=l+240|0,il=l+232|0,Uo=l+224|0,Mo=l+216|0,Lo=l+208|0,jn=l+200|0,cr=l+192|0,Hr=l+184|0,Rr=l+176|0,$t=l+168|0,fr=l+160|0,Gr=l+152|0,Lt=l+144|0,Ve=l+136|0,He=l+128|0,ft=l+120|0,Xe=l+112|0,nt=l+104|0,Te=l+96|0,Le=l+88|0,Ye=l+80|0,oe=l+72|0,q=l+64|0,L=l+56|0,M=l+48|0,R=l+40|0,k=l+32|0,B=l+24|0,m=l+16|0,d=l+8|0,A=l,dt(o,3646),Zt(o,3651,2)|0,Dr(o,3665,2)|0,ti(o,3682,18)|0,n[Cc>>2]=19,n[Cc+4>>2]=0,n[u>>2]=n[Cc>>2],n[u+4>>2]=n[Cc+4>>2],kr(o,3690,u)|0,n[Ar>>2]=1,n[Ar+4>>2]=0,n[u>>2]=n[Ar>>2],n[u+4>>2]=n[Ar+4>>2],Nn(o,3696,u)|0,n[Mr>>2]=2,n[Mr+4>>2]=0,n[u>>2]=n[Mr>>2],n[u+4>>2]=n[Mr+4>>2],Hn(o,3706,u)|0,n[go>>2]=1,n[go+4>>2]=0,n[u>>2]=n[go>>2],n[u+4>>2]=n[go+4>>2],zr(o,3722,u)|0,n[jo>>2]=2,n[jo+4>>2]=0,n[u>>2]=n[jo>>2],n[u+4>>2]=n[jo+4>>2],zr(o,3734,u)|0,n[js>>2]=3,n[js+4>>2]=0,n[u>>2]=n[js>>2],n[u+4>>2]=n[js+4>>2],Hn(o,3753,u)|0,n[fi>>2]=4,n[fi+4>>2]=0,n[u>>2]=n[fi>>2],n[u+4>>2]=n[fi+4>>2],Hn(o,3769,u)|0,n[Nr>>2]=5,n[Nr+4>>2]=0,n[u>>2]=n[Nr>>2],n[u+4>>2]=n[Nr+4>>2],Hn(o,3783,u)|0,n[dp>>2]=6,n[dp+4>>2]=0,n[u>>2]=n[dp>>2],n[u+4>>2]=n[dp+4>>2],Hn(o,3796,u)|0,n[gp>>2]=7,n[gp+4>>2]=0,n[u>>2]=n[gp>>2],n[u+4>>2]=n[gp+4>>2],Hn(o,3813,u)|0,n[hp>>2]=8,n[hp+4>>2]=0,n[u>>2]=n[hp>>2],n[u+4>>2]=n[hp+4>>2],Hn(o,3825,u)|0,n[Ic>>2]=3,n[Ic+4>>2]=0,n[u>>2]=n[Ic>>2],n[u+4>>2]=n[Ic+4>>2],zr(o,3843,u)|0,n[ho>>2]=4,n[ho+4>>2]=0,n[u>>2]=n[ho>>2],n[u+4>>2]=n[ho+4>>2],zr(o,3853,u)|0,n[ku>>2]=9,n[ku+4>>2]=0,n[u>>2]=n[ku>>2],n[u+4>>2]=n[ku+4>>2],Hn(o,3870,u)|0,n[pp>>2]=10,n[pp+4>>2]=0,n[u>>2]=n[pp>>2],n[u+4>>2]=n[pp+4>>2],Hn(o,3884,u)|0,n[Ap>>2]=11,n[Ap+4>>2]=0,n[u>>2]=n[Ap>>2],n[u+4>>2]=n[Ap+4>>2],Hn(o,3896,u)|0,n[xu>>2]=1,n[xu+4>>2]=0,n[u>>2]=n[xu>>2],n[u+4>>2]=n[xu+4>>2],ui(o,3907,u)|0,n[Ho>>2]=2,n[Ho+4>>2]=0,n[u>>2]=n[Ho>>2],n[u+4>>2]=n[Ho+4>>2],ui(o,3915,u)|0,n[Pu>>2]=3,n[Pu+4>>2]=0,n[u>>2]=n[Pu>>2],n[u+4>>2]=n[Pu+4>>2],ui(o,3928,u)|0,n[_o>>2]=4,n[_o+4>>2]=0,n[u>>2]=n[_o>>2],n[u+4>>2]=n[_o+4>>2],ui(o,3948,u)|0,n[fp>>2]=5,n[fp+4>>2]=0,n[u>>2]=n[fp>>2],n[u+4>>2]=n[fp+4>>2],ui(o,3960,u)|0,n[Vn>>2]=6,n[Vn+4>>2]=0,n[u>>2]=n[Vn>>2],n[u+4>>2]=n[Vn+4>>2],ui(o,3974,u)|0,n[Ec>>2]=7,n[Ec+4>>2]=0,n[u>>2]=n[Ec>>2],n[u+4>>2]=n[Ec+4>>2],ui(o,3983,u)|0,n[Hs>>2]=20,n[Hs+4>>2]=0,n[u>>2]=n[Hs>>2],n[u+4>>2]=n[Hs+4>>2],kr(o,3999,u)|0,n[po>>2]=8,n[po+4>>2]=0,n[u>>2]=n[po>>2],n[u+4>>2]=n[po+4>>2],ui(o,4012,u)|0,n[up>>2]=9,n[up+4>>2]=0,n[u>>2]=n[up>>2],n[u+4>>2]=n[up+4>>2],ui(o,4022,u)|0,n[cp>>2]=21,n[cp+4>>2]=0,n[u>>2]=n[cp>>2],n[u+4>>2]=n[cp+4>>2],kr(o,4039,u)|0,n[Uf>>2]=10,n[Uf+4>>2]=0,n[u>>2]=n[Uf>>2],n[u+4>>2]=n[Uf+4>>2],ui(o,4053,u)|0,n[lp>>2]=11,n[lp+4>>2]=0,n[u>>2]=n[lp>>2],n[u+4>>2]=n[lp+4>>2],ui(o,4065,u)|0,n[ap>>2]=12,n[ap+4>>2]=0,n[u>>2]=n[ap>>2],n[u+4>>2]=n[ap+4>>2],ui(o,4084,u)|0,n[yc>>2]=13,n[yc+4>>2]=0,n[u>>2]=n[yc>>2],n[u+4>>2]=n[yc+4>>2],ui(o,4097,u)|0,n[Ca>>2]=14,n[Ca+4>>2]=0,n[u>>2]=n[Ca>>2],n[u+4>>2]=n[Ca+4>>2],ui(o,4117,u)|0,n[Gl>>2]=15,n[Gl+4>>2]=0,n[u>>2]=n[Gl>>2],n[u+4>>2]=n[Gl+4>>2],ui(o,4129,u)|0,n[Ao>>2]=16,n[Ao+4>>2]=0,n[u>>2]=n[Ao>>2],n[u+4>>2]=n[Ao+4>>2],ui(o,4148,u)|0,n[bu>>2]=17,n[bu+4>>2]=0,n[u>>2]=n[bu>>2],n[u+4>>2]=n[bu+4>>2],ui(o,4161,u)|0,n[Mf>>2]=18,n[Mf+4>>2]=0,n[u>>2]=n[Mf>>2],n[u+4>>2]=n[Mf+4>>2],ui(o,4181,u)|0,n[Lf>>2]=5,n[Lf+4>>2]=0,n[u>>2]=n[Lf>>2],n[u+4>>2]=n[Lf+4>>2],zr(o,4196,u)|0,n[Zh>>2]=6,n[Zh+4>>2]=0,n[u>>2]=n[Zh>>2],n[u+4>>2]=n[Zh+4>>2],zr(o,4206,u)|0,n[zh>>2]=7,n[zh+4>>2]=0,n[u>>2]=n[zh>>2],n[u+4>>2]=n[zh+4>>2],zr(o,4217,u)|0,n[Du>>2]=3,n[Du+4>>2]=0,n[u>>2]=n[Du>>2],n[u+4>>2]=n[Du+4>>2],vu(o,4235,u)|0,n[Jh>>2]=1,n[Jh+4>>2]=0,n[u>>2]=n[Jh>>2],n[u+4>>2]=n[Jh+4>>2],YL(o,4251,u)|0,n[mc>>2]=4,n[mc+4>>2]=0,n[u>>2]=n[mc>>2],n[u+4>>2]=n[mc+4>>2],vu(o,4263,u)|0,n[ln>>2]=5,n[ln+4>>2]=0,n[u>>2]=n[ln>>2],n[u+4>>2]=n[ln+4>>2],vu(o,4279,u)|0,n[Kh>>2]=6,n[Kh+4>>2]=0,n[u>>2]=n[Kh>>2],n[u+4>>2]=n[Kh+4>>2],vu(o,4293,u)|0,n[Yh>>2]=7,n[Yh+4>>2]=0,n[u>>2]=n[Yh>>2],n[u+4>>2]=n[Yh+4>>2],vu(o,4306,u)|0,n[Vh>>2]=8,n[Vh+4>>2]=0,n[u>>2]=n[Vh>>2],n[u+4>>2]=n[Vh+4>>2],vu(o,4323,u)|0,n[Of>>2]=9,n[Of+4>>2]=0,n[u>>2]=n[Of>>2],n[u+4>>2]=n[Of+4>>2],vu(o,4335,u)|0,n[Nf>>2]=2,n[Nf+4>>2]=0,n[u>>2]=n[Nf>>2],n[u+4>>2]=n[Nf+4>>2],YL(o,4353,u)|0,n[Wh>>2]=12,n[Wh+4>>2]=0,n[u>>2]=n[Wh>>2],n[u+4>>2]=n[Wh+4>>2],id(o,4363,u)|0,n[dc>>2]=1,n[dc+4>>2]=0,n[u>>2]=n[dc>>2],n[u+4>>2]=n[dc+4>>2],tp(o,4376,u)|0,n[qh>>2]=2,n[qh+4>>2]=0,n[u>>2]=n[qh>>2],n[u+4>>2]=n[qh+4>>2],tp(o,4388,u)|0,n[Gh>>2]=13,n[Gh+4>>2]=0,n[u>>2]=n[Gh>>2],n[u+4>>2]=n[Gh+4>>2],id(o,4402,u)|0,n[il>>2]=14,n[il+4>>2]=0,n[u>>2]=n[il>>2],n[u+4>>2]=n[il+4>>2],id(o,4411,u)|0,n[Uo>>2]=15,n[Uo+4>>2]=0,n[u>>2]=n[Uo>>2],n[u+4>>2]=n[Uo+4>>2],id(o,4421,u)|0,n[Mo>>2]=16,n[Mo+4>>2]=0,n[u>>2]=n[Mo>>2],n[u+4>>2]=n[Mo+4>>2],id(o,4433,u)|0,n[Lo>>2]=17,n[Lo+4>>2]=0,n[u>>2]=n[Lo>>2],n[u+4>>2]=n[Lo+4>>2],id(o,4446,u)|0,n[jn>>2]=18,n[jn+4>>2]=0,n[u>>2]=n[jn>>2],n[u+4>>2]=n[jn+4>>2],id(o,4458,u)|0,n[cr>>2]=3,n[cr+4>>2]=0,n[u>>2]=n[cr>>2],n[u+4>>2]=n[cr+4>>2],tp(o,4471,u)|0,n[Hr>>2]=1,n[Hr+4>>2]=0,n[u>>2]=n[Hr>>2],n[u+4>>2]=n[Hr+4>>2],QP(o,4486,u)|0,n[Rr>>2]=10,n[Rr+4>>2]=0,n[u>>2]=n[Rr>>2],n[u+4>>2]=n[Rr+4>>2],vu(o,4496,u)|0,n[$t>>2]=11,n[$t+4>>2]=0,n[u>>2]=n[$t>>2],n[u+4>>2]=n[$t+4>>2],vu(o,4508,u)|0,n[fr>>2]=3,n[fr+4>>2]=0,n[u>>2]=n[fr>>2],n[u+4>>2]=n[fr+4>>2],YL(o,4519,u)|0,n[Gr>>2]=4,n[Gr+4>>2]=0,n[u>>2]=n[Gr>>2],n[u+4>>2]=n[Gr+4>>2],aPe(o,4530,u)|0,n[Lt>>2]=19,n[Lt+4>>2]=0,n[u>>2]=n[Lt>>2],n[u+4>>2]=n[Lt+4>>2],lPe(o,4542,u)|0,n[Ve>>2]=12,n[Ve+4>>2]=0,n[u>>2]=n[Ve>>2],n[u+4>>2]=n[Ve+4>>2],cPe(o,4554,u)|0,n[He>>2]=13,n[He+4>>2]=0,n[u>>2]=n[He>>2],n[u+4>>2]=n[He+4>>2],uPe(o,4568,u)|0,n[ft>>2]=2,n[ft+4>>2]=0,n[u>>2]=n[ft>>2],n[u+4>>2]=n[ft+4>>2],fPe(o,4578,u)|0,n[Xe>>2]=20,n[Xe+4>>2]=0,n[u>>2]=n[Xe>>2],n[u+4>>2]=n[Xe+4>>2],APe(o,4587,u)|0,n[nt>>2]=22,n[nt+4>>2]=0,n[u>>2]=n[nt>>2],n[u+4>>2]=n[nt+4>>2],kr(o,4602,u)|0,n[Te>>2]=23,n[Te+4>>2]=0,n[u>>2]=n[Te>>2],n[u+4>>2]=n[Te+4>>2],kr(o,4619,u)|0,n[Le>>2]=14,n[Le+4>>2]=0,n[u>>2]=n[Le>>2],n[u+4>>2]=n[Le+4>>2],pPe(o,4629,u)|0,n[Ye>>2]=1,n[Ye+4>>2]=0,n[u>>2]=n[Ye>>2],n[u+4>>2]=n[Ye+4>>2],hPe(o,4637,u)|0,n[oe>>2]=4,n[oe+4>>2]=0,n[u>>2]=n[oe>>2],n[u+4>>2]=n[oe+4>>2],tp(o,4653,u)|0,n[q>>2]=5,n[q+4>>2]=0,n[u>>2]=n[q>>2],n[u+4>>2]=n[q+4>>2],tp(o,4669,u)|0,n[L>>2]=6,n[L+4>>2]=0,n[u>>2]=n[L>>2],n[u+4>>2]=n[L+4>>2],tp(o,4686,u)|0,n[M>>2]=7,n[M+4>>2]=0,n[u>>2]=n[M>>2],n[u+4>>2]=n[M+4>>2],tp(o,4701,u)|0,n[R>>2]=8,n[R+4>>2]=0,n[u>>2]=n[R>>2],n[u+4>>2]=n[R+4>>2],tp(o,4719,u)|0,n[k>>2]=9,n[k+4>>2]=0,n[u>>2]=n[k>>2],n[u+4>>2]=n[k+4>>2],tp(o,4736,u)|0,n[B>>2]=21,n[B+4>>2]=0,n[u>>2]=n[B>>2],n[u+4>>2]=n[B+4>>2],gPe(o,4754,u)|0,n[m>>2]=2,n[m+4>>2]=0,n[u>>2]=n[m>>2],n[u+4>>2]=n[m+4>>2],QP(o,4772,u)|0,n[d>>2]=3,n[d+4>>2]=0,n[u>>2]=n[d>>2],n[u+4>>2]=n[d+4>>2],QP(o,4790,u)|0,n[A>>2]=4,n[A+4>>2]=0,n[u>>2]=n[A>>2],n[u+4>>2]=n[A+4>>2],QP(o,4808,u)|0,I=l}function dt(o,l){o=o|0,l=l|0;var u=0;u=CNe()|0,n[o>>2]=u,wNe(u,l),_h(n[o>>2]|0)}function Zt(o,l,u){return o=o|0,l=l|0,u=u|0,aNe(o,Sn(l)|0,u,0),o|0}function Dr(o,l,u){return o=o|0,l=l|0,u=u|0,WFe(o,Sn(l)|0,u,0),o|0}function ti(o,l,u){return o=o|0,l=l|0,u=u|0,QFe(o,Sn(l)|0,u,0),o|0}function kr(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],gFe(o,l,d),I=A,o|0}function Nn(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],zTe(o,l,d),I=A,o|0}function Hn(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],FTe(o,l,d),I=A,o|0}function zr(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],yTe(o,l,d),I=A,o|0}function ui(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],rTe(o,l,d),I=A,o|0}function vu(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],_Re(o,l,d),I=A,o|0}function YL(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vRe(o,l,d),I=A,o|0}function id(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],zQe(o,l,d),I=A,o|0}function tp(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],FQe(o,l,d),I=A,o|0}function QP(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],yQe(o,l,d),I=A,o|0}function aPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],rQe(o,l,d),I=A,o|0}function lPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],_ke(o,l,d),I=A,o|0}function cPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Ske(o,l,d),I=A,o|0}function uPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],uke(o,l,d),I=A,o|0}function fPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Yxe(o,l,d),I=A,o|0}function APe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],kxe(o,l,d),I=A,o|0}function pPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],hxe(o,l,d),I=A,o|0}function hPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],zPe(o,l,d),I=A,o|0}function gPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],dPe(o,l,d),I=A,o|0}function dPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],mPe(o,u,d,1),I=A}function Sn(o){return o=o|0,o|0}function mPe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=KL()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=yPe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,EPe(m,A)|0,A),I=d}function KL(){var o=0,l=0;if(s[7616]|0||(FJ(9136),gr(24,9136,U|0)|0,l=7616,n[l>>2]=1,n[l+4>>2]=0),!(_r(9136)|0)){o=9136,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));FJ(9136)}return 9136}function yPe(o){return o=o|0,0}function EPe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=KL()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],TJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(wPe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Dn(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0;var B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0;B=I,I=I+32|0,oe=B+24|0,q=B+20|0,R=B+16|0,L=B+12|0,M=B+8|0,k=B+4|0,Ye=B,n[q>>2]=l,n[R>>2]=u,n[L>>2]=A,n[M>>2]=d,n[k>>2]=m,m=o+28|0,n[Ye>>2]=n[m>>2],n[oe>>2]=n[Ye>>2],IPe(o+24|0,oe,q,L,M,R,k)|0,n[m>>2]=n[n[m>>2]>>2],I=B}function IPe(o,l,u,A,d,m,B){return o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,B=B|0,o=CPe(l)|0,l=Jt(24)|0,RJ(l+4|0,n[u>>2]|0,n[A>>2]|0,n[d>>2]|0,n[m>>2]|0,n[B>>2]|0),n[l>>2]=n[o>>2],n[o>>2]=l,l|0}function CPe(o){return o=o|0,n[o>>2]|0}function RJ(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,n[o>>2]=l,n[o+4>>2]=u,n[o+8>>2]=A,n[o+12>>2]=d,n[o+16>>2]=m}function yr(o,l){return o=o|0,l=l|0,l|o|0}function TJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function wPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=BPe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,vPe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],TJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,SPe(o,k),DPe(k),I=M;return}}function BPe(o){return o=o|0,357913941}function vPe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function SPe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function DPe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function FJ(o){o=o|0,xPe(o)}function bPe(o){o=o|0,PPe(o+24|0)}function _r(o){return o=o|0,n[o>>2]|0}function PPe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function xPe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,3,l,kPe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function tn(){return 9228}function kPe(){return 1140}function QPe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;return u=I,I=I+16|0,A=u+8|0,d=u,m=RPe(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],l=TPe(l,A)|0,I=u,l|0}function rn(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,n[o>>2]=l,n[o+4>>2]=u,n[o+8>>2]=A,n[o+12>>2]=d,n[o+16>>2]=m}function RPe(o){return o=o|0,(n[(KL()|0)+24>>2]|0)+(o*12|0)|0}function TPe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;return d=I,I=I+48|0,A=d,u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),op[u&31](A,o),A=FPe(A)|0,I=d,A|0}function FPe(o){o=o|0;var l=0,u=0,A=0,d=0;return d=I,I=I+32|0,l=d+12|0,u=d,A=JL(NJ()|0)|0,A?(zL(l,A),ZL(u,l),NPe(o,u),o=XL(l)|0):o=OPe(o)|0,I=d,o|0}function NJ(){var o=0;return s[7632]|0||(VPe(9184),gr(25,9184,U|0)|0,o=7632,n[o>>2]=1,n[o+4>>2]=0),9184}function JL(o){return o=o|0,n[o+36>>2]|0}function zL(o,l){o=o|0,l=l|0,n[o>>2]=l,n[o+4>>2]=o,n[o+8>>2]=0}function ZL(o,l){o=o|0,l=l|0,n[o>>2]=n[l>>2],n[o+4>>2]=n[l+4>>2],n[o+8>>2]=0}function NPe(o,l){o=o|0,l=l|0,_Pe(l,o,o+8|0,o+16|0,o+24|0,o+32|0,o+40|0)|0}function XL(o){return o=o|0,n[(n[o+4>>2]|0)+8>>2]|0}function OPe(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0,R=0;R=I,I=I+16|0,u=R+4|0,A=R,d=Ul(8)|0,m=d,B=Jt(48)|0,k=B,l=k+48|0;do n[k>>2]=n[o>>2],k=k+4|0,o=o+4|0;while((k|0)<(l|0));return l=m+4|0,n[l>>2]=B,k=Jt(8)|0,B=n[l>>2]|0,n[A>>2]=0,n[u>>2]=n[A>>2],OJ(k,B,u),n[d>>2]=k,I=R,m|0}function OJ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,u=Jt(16)|0,n[u+4>>2]=0,n[u+8>>2]=0,n[u>>2]=1092,n[u+12>>2]=l,n[o+4>>2]=u}function LPe(o){o=o|0,rE(o),It(o)}function MPe(o){o=o|0,o=n[o+12>>2]|0,o|0&&It(o)}function UPe(o){o=o|0,It(o)}function _Pe(o,l,u,A,d,m,B){return o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,B=B|0,m=HPe(n[o>>2]|0,l,u,A,d,m,B)|0,B=o+4|0,n[(n[B>>2]|0)+8>>2]=m,n[(n[B>>2]|0)+8>>2]|0}function HPe(o,l,u,A,d,m,B){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,B=B|0;var k=0,R=0;return k=I,I=I+16|0,R=k,_l(R),o=Us(o)|0,B=jPe(o,+E[l>>3],+E[u>>3],+E[A>>3],+E[d>>3],+E[m>>3],+E[B>>3])|0,Hl(R),I=k,B|0}function jPe(o,l,u,A,d,m,B){o=o|0,l=+l,u=+u,A=+A,d=+d,m=+m,B=+B;var k=0;return k=Ia(GPe()|0)|0,l=+el(l),u=+el(u),A=+el(A),d=+el(d),m=+el(m),lo(0,k|0,o|0,+l,+u,+A,+d,+m,+ +el(B))|0}function GPe(){var o=0;return s[7624]|0||(qPe(9172),o=7624,n[o>>2]=1,n[o+4>>2]=0),9172}function qPe(o){o=o|0,Oo(o,WPe()|0,6)}function WPe(){return 1112}function VPe(o){o=o|0,Nh(o)}function YPe(o){o=o|0,LJ(o+24|0),MJ(o+16|0)}function LJ(o){o=o|0,JPe(o)}function MJ(o){o=o|0,KPe(o)}function KPe(o){o=o|0;var l=0,u=0;if(l=n[o>>2]|0,l|0)do u=l,l=n[l>>2]|0,It(u);while(l|0);n[o>>2]=0}function JPe(o){o=o|0;var l=0,u=0;if(l=n[o>>2]|0,l|0)do u=l,l=n[l>>2]|0,It(u);while(l|0);n[o>>2]=0}function Nh(o){o=o|0;var l=0;n[o+16>>2]=0,n[o+20>>2]=0,l=o+24|0,n[l>>2]=0,n[o+28>>2]=l,n[o+36>>2]=0,s[o+40>>0]=0,s[o+41>>0]=0}function zPe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ZPe(o,u,d,0),I=A}function ZPe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=$L()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=XPe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,$Pe(m,A)|0,A),I=d}function $L(){var o=0,l=0;if(s[7640]|0||(_J(9232),gr(26,9232,U|0)|0,l=7640,n[l>>2]=1,n[l+4>>2]=0),!(_r(9232)|0)){o=9232,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));_J(9232)}return 9232}function XPe(o){return o=o|0,0}function $Pe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=$L()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],UJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(exe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function UJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function exe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=txe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,rxe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],UJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,nxe(o,k),ixe(k),I=M;return}}function txe(o){return o=o|0,357913941}function rxe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function nxe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function ixe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function _J(o){o=o|0,axe(o)}function sxe(o){o=o|0,oxe(o+24|0)}function oxe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function axe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,1,l,lxe()|0,3),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function lxe(){return 1144}function cxe(o,l,u,A,d){o=o|0,l=l|0,u=+u,A=+A,d=d|0;var m=0,B=0,k=0,R=0;m=I,I=I+16|0,B=m+8|0,k=m,R=uxe(o)|0,o=n[R+4>>2]|0,n[k>>2]=n[R>>2],n[k+4>>2]=o,n[B>>2]=n[k>>2],n[B+4>>2]=n[k+4>>2],fxe(l,B,u,A,d),I=m}function uxe(o){return o=o|0,(n[($L()|0)+24>>2]|0)+(o*12|0)|0}function fxe(o,l,u,A,d){o=o|0,l=l|0,u=+u,A=+A,d=d|0;var m=0,B=0,k=0,R=0,M=0;M=I,I=I+16|0,B=M+2|0,k=M+1|0,R=M,m=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(m=n[(n[o>>2]|0)+m>>2]|0),Tf(B,u),u=+Ff(B,u),Tf(k,A),A=+Ff(k,A),rp(R,d),R=np(R,d)|0,tX[m&1](o,u,A,R),I=M}function Tf(o,l){o=o|0,l=+l}function Ff(o,l){return o=o|0,l=+l,+ +pxe(l)}function rp(o,l){o=o|0,l=l|0}function np(o,l){return o=o|0,l=l|0,Axe(l)|0}function Axe(o){return o=o|0,o|0}function pxe(o){return o=+o,+o}function hxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],gxe(o,u,d,1),I=A}function gxe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=eM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=dxe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,mxe(m,A)|0,A),I=d}function eM(){var o=0,l=0;if(s[7648]|0||(jJ(9268),gr(27,9268,U|0)|0,l=7648,n[l>>2]=1,n[l+4>>2]=0),!(_r(9268)|0)){o=9268,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));jJ(9268)}return 9268}function dxe(o){return o=o|0,0}function mxe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=eM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],HJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(yxe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function HJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function yxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=Exe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,Ixe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],HJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,Cxe(o,k),wxe(k),I=M;return}}function Exe(o){return o=o|0,357913941}function Ixe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function Cxe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function wxe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function jJ(o){o=o|0,Sxe(o)}function Bxe(o){o=o|0,vxe(o+24|0)}function vxe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function Sxe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,4,l,Dxe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function Dxe(){return 1160}function bxe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;return u=I,I=I+16|0,A=u+8|0,d=u,m=Pxe(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],l=xxe(l,A)|0,I=u,l|0}function Pxe(o){return o=o|0,(n[(eM()|0)+24>>2]|0)+(o*12|0)|0}function xxe(o,l){o=o|0,l=l|0;var u=0;return u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),GJ(pd[u&31](o)|0)|0}function GJ(o){return o=o|0,o&1|0}function kxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Qxe(o,u,d,0),I=A}function Qxe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=tM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=Rxe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,Txe(m,A)|0,A),I=d}function tM(){var o=0,l=0;if(s[7656]|0||(WJ(9304),gr(28,9304,U|0)|0,l=7656,n[l>>2]=1,n[l+4>>2]=0),!(_r(9304)|0)){o=9304,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));WJ(9304)}return 9304}function Rxe(o){return o=o|0,0}function Txe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=tM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],qJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(Fxe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function qJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function Fxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=Nxe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,Oxe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],qJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,Lxe(o,k),Mxe(k),I=M;return}}function Nxe(o){return o=o|0,357913941}function Oxe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function Lxe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function Mxe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function WJ(o){o=o|0,Hxe(o)}function Uxe(o){o=o|0,_xe(o+24|0)}function _xe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function Hxe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,5,l,jxe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function jxe(){return 1164}function Gxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,d=A+8|0,m=A,B=qxe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Wxe(l,d,u),I=A}function qxe(o){return o=o|0,(n[(tM()|0)+24>>2]|0)+(o*12|0)|0}function Wxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),Oh(d,u),u=Lh(d,u)|0,op[A&31](o,u),Mh(d),I=m}function Oh(o,l){o=o|0,l=l|0,Vxe(o,l)}function Lh(o,l){return o=o|0,l=l|0,o|0}function Mh(o){o=o|0,bf(o)}function Vxe(o,l){o=o|0,l=l|0,rM(o,l)}function rM(o,l){o=o|0,l=l|0,n[o>>2]=l}function Yxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Kxe(o,u,d,0),I=A}function Kxe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=nM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=Jxe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,zxe(m,A)|0,A),I=d}function nM(){var o=0,l=0;if(s[7664]|0||(YJ(9340),gr(29,9340,U|0)|0,l=7664,n[l>>2]=1,n[l+4>>2]=0),!(_r(9340)|0)){o=9340,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));YJ(9340)}return 9340}function Jxe(o){return o=o|0,0}function zxe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=nM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],VJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(Zxe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function VJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function Zxe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=Xxe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,$xe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],VJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,eke(o,k),tke(k),I=M;return}}function Xxe(o){return o=o|0,357913941}function $xe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function eke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function tke(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function YJ(o){o=o|0,ike(o)}function rke(o){o=o|0,nke(o+24|0)}function nke(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function ike(o){o=o|0;var l=0;l=tn()|0,rn(o,2,4,l,ske()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function ske(){return 1180}function oke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=ake(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],u=lke(l,d,u)|0,I=A,u|0}function ake(o){return o=o|0,(n[(nM()|0)+24>>2]|0)+(o*12|0)|0}function lke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;return m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),sd(d,u),d=od(d,u)|0,d=RP($M[A&15](o,d)|0)|0,I=m,d|0}function sd(o,l){o=o|0,l=l|0}function od(o,l){return o=o|0,l=l|0,cke(l)|0}function RP(o){return o=o|0,o|0}function cke(o){return o=o|0,o|0}function uke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],fke(o,u,d,0),I=A}function fke(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=iM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=Ake(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,pke(m,A)|0,A),I=d}function iM(){var o=0,l=0;if(s[7672]|0||(JJ(9376),gr(30,9376,U|0)|0,l=7672,n[l>>2]=1,n[l+4>>2]=0),!(_r(9376)|0)){o=9376,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));JJ(9376)}return 9376}function Ake(o){return o=o|0,0}function pke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=iM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],KJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(hke(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function KJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function hke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=gke(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,dke(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],KJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,mke(o,k),yke(k),I=M;return}}function gke(o){return o=o|0,357913941}function dke(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function mke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function yke(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function JJ(o){o=o|0,Cke(o)}function Eke(o){o=o|0,Ike(o+24|0)}function Ike(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function Cke(o){o=o|0;var l=0;l=tn()|0,rn(o,2,5,l,zJ()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function zJ(){return 1196}function wke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;return u=I,I=I+16|0,A=u+8|0,d=u,m=Bke(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],l=vke(l,A)|0,I=u,l|0}function Bke(o){return o=o|0,(n[(iM()|0)+24>>2]|0)+(o*12|0)|0}function vke(o,l){o=o|0,l=l|0;var u=0;return u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),RP(pd[u&31](o)|0)|0}function Ske(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Dke(o,u,d,1),I=A}function Dke(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=sM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=bke(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,Pke(m,A)|0,A),I=d}function sM(){var o=0,l=0;if(s[7680]|0||(XJ(9412),gr(31,9412,U|0)|0,l=7680,n[l>>2]=1,n[l+4>>2]=0),!(_r(9412)|0)){o=9412,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));XJ(9412)}return 9412}function bke(o){return o=o|0,0}function Pke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=sM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],ZJ(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(xke(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function ZJ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function xke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=kke(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,Qke(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],ZJ(m,A,u),n[R>>2]=(n[R>>2]|0)+12,Rke(o,k),Tke(k),I=M;return}}function kke(o){return o=o|0,357913941}function Qke(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function Rke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function Tke(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function XJ(o){o=o|0,Oke(o)}function Fke(o){o=o|0,Nke(o+24|0)}function Nke(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function Oke(o){o=o|0;var l=0;l=tn()|0,rn(o,2,6,l,$J()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function $J(){return 1200}function Lke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;return u=I,I=I+16|0,A=u+8|0,d=u,m=Mke(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],l=Uke(l,A)|0,I=u,l|0}function Mke(o){return o=o|0,(n[(sM()|0)+24>>2]|0)+(o*12|0)|0}function Uke(o,l){o=o|0,l=l|0;var u=0;return u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),TP(pd[u&31](o)|0)|0}function TP(o){return o=o|0,o|0}function _ke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Hke(o,u,d,0),I=A}function Hke(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=oM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=jke(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,Gke(m,A)|0,A),I=d}function oM(){var o=0,l=0;if(s[7688]|0||(tz(9448),gr(32,9448,U|0)|0,l=7688,n[l>>2]=1,n[l+4>>2]=0),!(_r(9448)|0)){o=9448,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));tz(9448)}return 9448}function jke(o){return o=o|0,0}function Gke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=oM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],ez(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(qke(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function ez(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function qke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=Wke(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,Vke(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],ez(m,A,u),n[R>>2]=(n[R>>2]|0)+12,Yke(o,k),Kke(k),I=M;return}}function Wke(o){return o=o|0,357913941}function Vke(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function Yke(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function Kke(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function tz(o){o=o|0,Zke(o)}function Jke(o){o=o|0,zke(o+24|0)}function zke(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function Zke(o){o=o|0;var l=0;l=tn()|0,rn(o,2,6,l,rz()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function rz(){return 1204}function Xke(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,d=A+8|0,m=A,B=$ke(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],eQe(l,d,u),I=A}function $ke(o){return o=o|0,(n[(oM()|0)+24>>2]|0)+(o*12|0)|0}function eQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),aM(d,u),d=lM(d,u)|0,op[A&31](o,d),I=m}function aM(o,l){o=o|0,l=l|0}function lM(o,l){return o=o|0,l=l|0,tQe(l)|0}function tQe(o){return o=o|0,o|0}function rQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],nQe(o,u,d,0),I=A}function nQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=cM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=iQe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,sQe(m,A)|0,A),I=d}function cM(){var o=0,l=0;if(s[7696]|0||(iz(9484),gr(33,9484,U|0)|0,l=7696,n[l>>2]=1,n[l+4>>2]=0),!(_r(9484)|0)){o=9484,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));iz(9484)}return 9484}function iQe(o){return o=o|0,0}function sQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=cM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],nz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(oQe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function nz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function oQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=aQe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,lQe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],nz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,cQe(o,k),uQe(k),I=M;return}}function aQe(o){return o=o|0,357913941}function lQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function cQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function uQe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function iz(o){o=o|0,pQe(o)}function fQe(o){o=o|0,AQe(o+24|0)}function AQe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function pQe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,1,l,hQe()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function hQe(){return 1212}function gQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;d=I,I=I+16|0,m=d+8|0,B=d,k=dQe(o)|0,o=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=o,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],mQe(l,m,u,A),I=d}function dQe(o){return o=o|0,(n[(cM()|0)+24>>2]|0)+(o*12|0)|0}function mQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;k=I,I=I+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(d=n[(n[o>>2]|0)+d>>2]|0),aM(m,u),m=lM(m,u)|0,sd(B,A),B=od(B,A)|0,DB[d&15](o,m,B),I=k}function yQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],EQe(o,u,d,1),I=A}function EQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=uM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=IQe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,CQe(m,A)|0,A),I=d}function uM(){var o=0,l=0;if(s[7704]|0||(oz(9520),gr(34,9520,U|0)|0,l=7704,n[l>>2]=1,n[l+4>>2]=0),!(_r(9520)|0)){o=9520,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));oz(9520)}return 9520}function IQe(o){return o=o|0,0}function CQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=uM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],sz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(wQe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function sz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function wQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=BQe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,vQe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],sz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,SQe(o,k),DQe(k),I=M;return}}function BQe(o){return o=o|0,357913941}function vQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function SQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function DQe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function oz(o){o=o|0,xQe(o)}function bQe(o){o=o|0,PQe(o+24|0)}function PQe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function xQe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,1,l,kQe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function kQe(){return 1224}function QQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;return d=I,I=I+16|0,m=d+8|0,B=d,k=RQe(o)|0,o=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=o,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],A=+TQe(l,m,u),I=d,+A}function RQe(o){return o=o|0,(n[(uM()|0)+24>>2]|0)+(o*12|0)|0}function TQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),rp(d,u),d=np(d,u)|0,B=+Rf(+nX[A&7](o,d)),I=m,+B}function FQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],NQe(o,u,d,1),I=A}function NQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=fM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=OQe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,LQe(m,A)|0,A),I=d}function fM(){var o=0,l=0;if(s[7712]|0||(lz(9556),gr(35,9556,U|0)|0,l=7712,n[l>>2]=1,n[l+4>>2]=0),!(_r(9556)|0)){o=9556,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));lz(9556)}return 9556}function OQe(o){return o=o|0,0}function LQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=fM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],az(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(MQe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function az(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function MQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=UQe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,_Qe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],az(m,A,u),n[R>>2]=(n[R>>2]|0)+12,HQe(o,k),jQe(k),I=M;return}}function UQe(o){return o=o|0,357913941}function _Qe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function HQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function jQe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function lz(o){o=o|0,WQe(o)}function GQe(o){o=o|0,qQe(o+24|0)}function qQe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function WQe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,5,l,VQe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function VQe(){return 1232}function YQe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=KQe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],u=+JQe(l,d),I=A,+u}function KQe(o){return o=o|0,(n[(fM()|0)+24>>2]|0)+(o*12|0)|0}function JQe(o,l){o=o|0,l=l|0;var u=0;return u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),+ +Rf(+rX[u&15](o))}function zQe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ZQe(o,u,d,1),I=A}function ZQe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=AM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=XQe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,$Qe(m,A)|0,A),I=d}function AM(){var o=0,l=0;if(s[7720]|0||(uz(9592),gr(36,9592,U|0)|0,l=7720,n[l>>2]=1,n[l+4>>2]=0),!(_r(9592)|0)){o=9592,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));uz(9592)}return 9592}function XQe(o){return o=o|0,0}function $Qe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=AM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],cz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(eRe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function cz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function eRe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=tRe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,rRe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],cz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,nRe(o,k),iRe(k),I=M;return}}function tRe(o){return o=o|0,357913941}function rRe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function nRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function iRe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function uz(o){o=o|0,aRe(o)}function sRe(o){o=o|0,oRe(o+24|0)}function oRe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function aRe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,7,l,lRe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function lRe(){return 1276}function cRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;return u=I,I=I+16|0,A=u+8|0,d=u,m=uRe(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],l=fRe(l,A)|0,I=u,l|0}function uRe(o){return o=o|0,(n[(AM()|0)+24>>2]|0)+(o*12|0)|0}function fRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;return d=I,I=I+16|0,A=d,u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),op[u&31](A,o),A=fz(A)|0,I=d,A|0}function fz(o){o=o|0;var l=0,u=0,A=0,d=0;return d=I,I=I+32|0,l=d+12|0,u=d,A=JL(Az()|0)|0,A?(zL(l,A),ZL(u,l),ARe(o,u),o=XL(l)|0):o=pRe(o)|0,I=d,o|0}function Az(){var o=0;return s[7736]|0||(BRe(9640),gr(25,9640,U|0)|0,o=7736,n[o>>2]=1,n[o+4>>2]=0),9640}function ARe(o,l){o=o|0,l=l|0,mRe(l,o,o+8|0)|0}function pRe(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0;return u=I,I=I+16|0,d=u+4|0,B=u,A=Ul(8)|0,l=A,k=Jt(16)|0,n[k>>2]=n[o>>2],n[k+4>>2]=n[o+4>>2],n[k+8>>2]=n[o+8>>2],n[k+12>>2]=n[o+12>>2],m=l+4|0,n[m>>2]=k,o=Jt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],pM(o,m,d),n[A>>2]=o,I=u,l|0}function pM(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,u=Jt(16)|0,n[u+4>>2]=0,n[u+8>>2]=0,n[u>>2]=1244,n[u+12>>2]=l,n[o+4>>2]=u}function hRe(o){o=o|0,rE(o),It(o)}function gRe(o){o=o|0,o=n[o+12>>2]|0,o|0&&It(o)}function dRe(o){o=o|0,It(o)}function mRe(o,l,u){return o=o|0,l=l|0,u=u|0,l=yRe(n[o>>2]|0,l,u)|0,u=o+4|0,n[(n[u>>2]|0)+8>>2]=l,n[(n[u>>2]|0)+8>>2]|0}function yRe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;return A=I,I=I+16|0,d=A,_l(d),o=Us(o)|0,u=ERe(o,n[l>>2]|0,+E[u>>3])|0,Hl(d),I=A,u|0}function ERe(o,l,u){o=o|0,l=l|0,u=+u;var A=0;return A=Ia(IRe()|0)|0,l=Jy(l)|0,iu(0,A|0,o|0,l|0,+ +el(u))|0}function IRe(){var o=0;return s[7728]|0||(CRe(9628),o=7728,n[o>>2]=1,n[o+4>>2]=0),9628}function CRe(o){o=o|0,Oo(o,wRe()|0,2)}function wRe(){return 1264}function BRe(o){o=o|0,Nh(o)}function vRe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],SRe(o,u,d,1),I=A}function SRe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=hM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=DRe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,bRe(m,A)|0,A),I=d}function hM(){var o=0,l=0;if(s[7744]|0||(hz(9684),gr(37,9684,U|0)|0,l=7744,n[l>>2]=1,n[l+4>>2]=0),!(_r(9684)|0)){o=9684,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));hz(9684)}return 9684}function DRe(o){return o=o|0,0}function bRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=hM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],pz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(PRe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function pz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function PRe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=xRe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,kRe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],pz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,QRe(o,k),RRe(k),I=M;return}}function xRe(o){return o=o|0,357913941}function kRe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function QRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function RRe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function hz(o){o=o|0,NRe(o)}function TRe(o){o=o|0,FRe(o+24|0)}function FRe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function NRe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,5,l,ORe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function ORe(){return 1280}function LRe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=MRe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],u=URe(l,d,u)|0,I=A,u|0}function MRe(o){return o=o|0,(n[(hM()|0)+24>>2]|0)+(o*12|0)|0}function URe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return B=I,I=I+32|0,d=B,m=B+16|0,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),rp(m,u),m=np(m,u)|0,DB[A&15](d,o,m),m=fz(d)|0,I=B,m|0}function _Re(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],HRe(o,u,d,1),I=A}function HRe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=gM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=jRe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,GRe(m,A)|0,A),I=d}function gM(){var o=0,l=0;if(s[7752]|0||(dz(9720),gr(38,9720,U|0)|0,l=7752,n[l>>2]=1,n[l+4>>2]=0),!(_r(9720)|0)){o=9720,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));dz(9720)}return 9720}function jRe(o){return o=o|0,0}function GRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=gM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],gz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(qRe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function gz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function qRe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=WRe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,VRe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],gz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,YRe(o,k),KRe(k),I=M;return}}function WRe(o){return o=o|0,357913941}function VRe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function YRe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function KRe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function dz(o){o=o|0,ZRe(o)}function JRe(o){o=o|0,zRe(o+24|0)}function zRe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function ZRe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,8,l,XRe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function XRe(){return 1288}function $Re(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;return u=I,I=I+16|0,A=u+8|0,d=u,m=eTe(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],l=tTe(l,A)|0,I=u,l|0}function eTe(o){return o=o|0,(n[(gM()|0)+24>>2]|0)+(o*12|0)|0}function tTe(o,l){o=o|0,l=l|0;var u=0;return u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),nd(pd[u&31](o)|0)|0}function rTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],nTe(o,u,d,0),I=A}function nTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=dM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=iTe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,sTe(m,A)|0,A),I=d}function dM(){var o=0,l=0;if(s[7760]|0||(yz(9756),gr(39,9756,U|0)|0,l=7760,n[l>>2]=1,n[l+4>>2]=0),!(_r(9756)|0)){o=9756,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));yz(9756)}return 9756}function iTe(o){return o=o|0,0}function sTe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=dM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],mz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(oTe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function mz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function oTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=aTe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,lTe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],mz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,cTe(o,k),uTe(k),I=M;return}}function aTe(o){return o=o|0,357913941}function lTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function cTe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function uTe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function yz(o){o=o|0,pTe(o)}function fTe(o){o=o|0,ATe(o+24|0)}function ATe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function pTe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,8,l,hTe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function hTe(){return 1292}function gTe(o,l,u){o=o|0,l=l|0,u=+u;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,d=A+8|0,m=A,B=dTe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],mTe(l,d,u),I=A}function dTe(o){return o=o|0,(n[(dM()|0)+24>>2]|0)+(o*12|0)|0}function mTe(o,l,u){o=o|0,l=l|0,u=+u;var A=0,d=0,m=0;m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),Tf(d,u),u=+Ff(d,u),$Z[A&31](o,u),I=m}function yTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ETe(o,u,d,0),I=A}function ETe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=mM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=ITe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,CTe(m,A)|0,A),I=d}function mM(){var o=0,l=0;if(s[7768]|0||(Iz(9792),gr(40,9792,U|0)|0,l=7768,n[l>>2]=1,n[l+4>>2]=0),!(_r(9792)|0)){o=9792,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));Iz(9792)}return 9792}function ITe(o){return o=o|0,0}function CTe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=mM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Ez(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(wTe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Ez(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function wTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=BTe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,vTe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Ez(m,A,u),n[R>>2]=(n[R>>2]|0)+12,STe(o,k),DTe(k),I=M;return}}function BTe(o){return o=o|0,357913941}function vTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function STe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function DTe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function Iz(o){o=o|0,xTe(o)}function bTe(o){o=o|0,PTe(o+24|0)}function PTe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function xTe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,1,l,kTe()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function kTe(){return 1300}function QTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=+A;var d=0,m=0,B=0,k=0;d=I,I=I+16|0,m=d+8|0,B=d,k=RTe(o)|0,o=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=o,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],TTe(l,m,u,A),I=d}function RTe(o){return o=o|0,(n[(mM()|0)+24>>2]|0)+(o*12|0)|0}function TTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=+A;var d=0,m=0,B=0,k=0;k=I,I=I+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(d=n[(n[o>>2]|0)+d>>2]|0),rp(m,u),m=np(m,u)|0,Tf(B,A),A=+Ff(B,A),aX[d&15](o,m,A),I=k}function FTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],NTe(o,u,d,0),I=A}function NTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=yM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=OTe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,LTe(m,A)|0,A),I=d}function yM(){var o=0,l=0;if(s[7776]|0||(wz(9828),gr(41,9828,U|0)|0,l=7776,n[l>>2]=1,n[l+4>>2]=0),!(_r(9828)|0)){o=9828,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));wz(9828)}return 9828}function OTe(o){return o=o|0,0}function LTe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=yM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Cz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(MTe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Cz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function MTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=UTe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,_Te(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Cz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,HTe(o,k),jTe(k),I=M;return}}function UTe(o){return o=o|0,357913941}function _Te(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function HTe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function jTe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function wz(o){o=o|0,WTe(o)}function GTe(o){o=o|0,qTe(o+24|0)}function qTe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function WTe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,7,l,VTe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function VTe(){return 1312}function YTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,d=A+8|0,m=A,B=KTe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],JTe(l,d,u),I=A}function KTe(o){return o=o|0,(n[(yM()|0)+24>>2]|0)+(o*12|0)|0}function JTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),rp(d,u),d=np(d,u)|0,op[A&31](o,d),I=m}function zTe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ZTe(o,u,d,0),I=A}function ZTe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=EM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=XTe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,$Te(m,A)|0,A),I=d}function EM(){var o=0,l=0;if(s[7784]|0||(vz(9864),gr(42,9864,U|0)|0,l=7784,n[l>>2]=1,n[l+4>>2]=0),!(_r(9864)|0)){o=9864,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));vz(9864)}return 9864}function XTe(o){return o=o|0,0}function $Te(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=EM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Bz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(eFe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Bz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function eFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=tFe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,rFe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Bz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,nFe(o,k),iFe(k),I=M;return}}function tFe(o){return o=o|0,357913941}function rFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function nFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function iFe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function vz(o){o=o|0,aFe(o)}function sFe(o){o=o|0,oFe(o+24|0)}function oFe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function aFe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,8,l,lFe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function lFe(){return 1320}function cFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,d=A+8|0,m=A,B=uFe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],fFe(l,d,u),I=A}function uFe(o){return o=o|0,(n[(EM()|0)+24>>2]|0)+(o*12|0)|0}function fFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),AFe(d,u),d=pFe(d,u)|0,op[A&31](o,d),I=m}function AFe(o,l){o=o|0,l=l|0}function pFe(o,l){return o=o|0,l=l|0,hFe(l)|0}function hFe(o){return o=o|0,o|0}function gFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],dFe(o,u,d,0),I=A}function dFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=IM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=mFe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,yFe(m,A)|0,A),I=d}function IM(){var o=0,l=0;if(s[7792]|0||(Dz(9900),gr(43,9900,U|0)|0,l=7792,n[l>>2]=1,n[l+4>>2]=0),!(_r(9900)|0)){o=9900,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));Dz(9900)}return 9900}function mFe(o){return o=o|0,0}function yFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=IM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Sz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(EFe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Sz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function EFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=IFe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,CFe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Sz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,wFe(o,k),BFe(k),I=M;return}}function IFe(o){return o=o|0,357913941}function CFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function wFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function BFe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function Dz(o){o=o|0,DFe(o)}function vFe(o){o=o|0,SFe(o+24|0)}function SFe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function DFe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,22,l,bFe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function bFe(){return 1344}function PFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0;u=I,I=I+16|0,A=u+8|0,d=u,m=xFe(o)|0,o=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=o,n[A>>2]=n[d>>2],n[A+4>>2]=n[d+4>>2],kFe(l,A),I=u}function xFe(o){return o=o|0,(n[(IM()|0)+24>>2]|0)+(o*12|0)|0}function kFe(o,l){o=o|0,l=l|0;var u=0;u=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(u=n[(n[o>>2]|0)+u>>2]|0),sp[u&127](o)}function QFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=CM()|0,o=RFe(u)|0,Dn(m,l,d,o,TFe(u,A)|0,A)}function CM(){var o=0,l=0;if(s[7800]|0||(Pz(9936),gr(44,9936,U|0)|0,l=7800,n[l>>2]=1,n[l+4>>2]=0),!(_r(9936)|0)){o=9936,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));Pz(9936)}return 9936}function RFe(o){return o=o|0,o|0}function TFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=CM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(bz(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(FFe(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function bz(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function FFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=NFe(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,OFe(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,bz(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,LFe(o,d),MFe(d),I=k;return}}function NFe(o){return o=o|0,536870911}function OFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function LFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function MFe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function Pz(o){o=o|0,HFe(o)}function UFe(o){o=o|0,_Fe(o+24|0)}function _Fe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function HFe(o){o=o|0;var l=0;l=tn()|0,rn(o,1,23,l,rz()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function jFe(o,l){o=o|0,l=l|0,qFe(n[(GFe(o)|0)>>2]|0,l)}function GFe(o){return o=o|0,(n[(CM()|0)+24>>2]|0)+(o<<3)|0}function qFe(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,aM(A,l),l=lM(A,l)|0,sp[o&127](l),I=u}function WFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=wM()|0,o=VFe(u)|0,Dn(m,l,d,o,YFe(u,A)|0,A)}function wM(){var o=0,l=0;if(s[7808]|0||(kz(9972),gr(45,9972,U|0)|0,l=7808,n[l>>2]=1,n[l+4>>2]=0),!(_r(9972)|0)){o=9972,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));kz(9972)}return 9972}function VFe(o){return o=o|0,o|0}function YFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=wM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(xz(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(KFe(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function xz(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function KFe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=JFe(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,zFe(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,xz(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,ZFe(o,d),XFe(d),I=k;return}}function JFe(o){return o=o|0,536870911}function zFe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function ZFe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function XFe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function kz(o){o=o|0,tNe(o)}function $Fe(o){o=o|0,eNe(o+24|0)}function eNe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function tNe(o){o=o|0;var l=0;l=tn()|0,rn(o,1,9,l,rNe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function rNe(){return 1348}function nNe(o,l){return o=o|0,l=l|0,sNe(n[(iNe(o)|0)>>2]|0,l)|0}function iNe(o){return o=o|0,(n[(wM()|0)+24>>2]|0)+(o<<3)|0}function sNe(o,l){o=o|0,l=l|0;var u=0,A=0;return u=I,I=I+16|0,A=u,Qz(A,l),l=Rz(A,l)|0,l=RP(pd[o&31](l)|0)|0,I=u,l|0}function Qz(o,l){o=o|0,l=l|0}function Rz(o,l){return o=o|0,l=l|0,oNe(l)|0}function oNe(o){return o=o|0,o|0}function aNe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=BM()|0,o=lNe(u)|0,Dn(m,l,d,o,cNe(u,A)|0,A)}function BM(){var o=0,l=0;if(s[7816]|0||(Fz(10008),gr(46,10008,U|0)|0,l=7816,n[l>>2]=1,n[l+4>>2]=0),!(_r(10008)|0)){o=10008,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));Fz(10008)}return 10008}function lNe(o){return o=o|0,o|0}function cNe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=BM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(Tz(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(uNe(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function Tz(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function uNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=fNe(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,ANe(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,Tz(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,pNe(o,d),hNe(d),I=k;return}}function fNe(o){return o=o|0,536870911}function ANe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function pNe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function hNe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function Fz(o){o=o|0,mNe(o)}function gNe(o){o=o|0,dNe(o+24|0)}function dNe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function mNe(o){o=o|0;var l=0;l=tn()|0,rn(o,1,15,l,zJ()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function yNe(o){return o=o|0,INe(n[(ENe(o)|0)>>2]|0)|0}function ENe(o){return o=o|0,(n[(BM()|0)+24>>2]|0)+(o<<3)|0}function INe(o){return o=o|0,RP(YP[o&7]()|0)|0}function CNe(){var o=0;return s[7832]|0||(xNe(10052),gr(25,10052,U|0)|0,o=7832,n[o>>2]=1,n[o+4>>2]=0),10052}function wNe(o,l){o=o|0,l=l|0,n[o>>2]=BNe()|0,n[o+4>>2]=vNe()|0,n[o+12>>2]=l,n[o+8>>2]=SNe()|0,n[o+32>>2]=2}function BNe(){return 11709}function vNe(){return 1188}function SNe(){return FP()|0}function DNe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(bNe(u),It(u)):l|0&&(Uy(l),It(l))}function Uh(o,l){return o=o|0,l=l|0,l&o|0}function bNe(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function FP(){var o=0;return s[7824]|0||(n[2511]=PNe()|0,n[2512]=0,o=7824,n[o>>2]=1,n[o+4>>2]=0),10044}function PNe(){return 0}function xNe(o){o=o|0,Nh(o)}function kNe(o){o=o|0;var l=0,u=0,A=0,d=0,m=0;l=I,I=I+32|0,u=l+24|0,m=l+16|0,d=l+8|0,A=l,QNe(o,4827),RNe(o,4834,3)|0,TNe(o,3682,47)|0,n[m>>2]=9,n[m+4>>2]=0,n[u>>2]=n[m>>2],n[u+4>>2]=n[m+4>>2],FNe(o,4841,u)|0,n[d>>2]=1,n[d+4>>2]=0,n[u>>2]=n[d>>2],n[u+4>>2]=n[d+4>>2],NNe(o,4871,u)|0,n[A>>2]=10,n[A+4>>2]=0,n[u>>2]=n[A>>2],n[u+4>>2]=n[A+4>>2],ONe(o,4891,u)|0,I=l}function QNe(o,l){o=o|0,l=l|0;var u=0;u=hLe()|0,n[o>>2]=u,gLe(u,l),_h(n[o>>2]|0)}function RNe(o,l,u){return o=o|0,l=l|0,u=u|0,XOe(o,Sn(l)|0,u,0),o|0}function TNe(o,l,u){return o=o|0,l=l|0,u=u|0,LOe(o,Sn(l)|0,u,0),o|0}function FNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],yOe(o,l,d),I=A,o|0}function NNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],$Ne(o,l,d),I=A,o|0}function ONe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=n[u+4>>2]|0,n[m>>2]=n[u>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],LNe(o,l,d),I=A,o|0}function LNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],MNe(o,u,d,1),I=A}function MNe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=vM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=UNe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,_Ne(m,A)|0,A),I=d}function vM(){var o=0,l=0;if(s[7840]|0||(Oz(10100),gr(48,10100,U|0)|0,l=7840,n[l>>2]=1,n[l+4>>2]=0),!(_r(10100)|0)){o=10100,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));Oz(10100)}return 10100}function UNe(o){return o=o|0,0}function _Ne(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=vM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Nz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(HNe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Nz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function HNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=jNe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,GNe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Nz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,qNe(o,k),WNe(k),I=M;return}}function jNe(o){return o=o|0,357913941}function GNe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function qNe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function WNe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function Oz(o){o=o|0,KNe(o)}function VNe(o){o=o|0,YNe(o+24|0)}function YNe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function KNe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,6,l,JNe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function JNe(){return 1364}function zNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;return A=I,I=I+16|0,d=A+8|0,m=A,B=ZNe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],u=XNe(l,d,u)|0,I=A,u|0}function ZNe(o){return o=o|0,(n[(vM()|0)+24>>2]|0)+(o*12|0)|0}function XNe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;return m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),rp(d,u),d=np(d,u)|0,d=GJ($M[A&15](o,d)|0)|0,I=m,d|0}function $Ne(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],eOe(o,u,d,0),I=A}function eOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=SM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=tOe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,rOe(m,A)|0,A),I=d}function SM(){var o=0,l=0;if(s[7848]|0||(Mz(10136),gr(49,10136,U|0)|0,l=7848,n[l>>2]=1,n[l+4>>2]=0),!(_r(10136)|0)){o=10136,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));Mz(10136)}return 10136}function tOe(o){return o=o|0,0}function rOe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=SM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Lz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(nOe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Lz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function nOe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=iOe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,sOe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Lz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,oOe(o,k),aOe(k),I=M;return}}function iOe(o){return o=o|0,357913941}function sOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function oOe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function aOe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function Mz(o){o=o|0,uOe(o)}function lOe(o){o=o|0,cOe(o+24|0)}function cOe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function uOe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,9,l,fOe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function fOe(){return 1372}function AOe(o,l,u){o=o|0,l=l|0,u=+u;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,d=A+8|0,m=A,B=pOe(o)|0,o=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=o,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],hOe(l,d,u),I=A}function pOe(o){return o=o|0,(n[(SM()|0)+24>>2]|0)+(o*12|0)|0}function hOe(o,l,u){o=o|0,l=l|0,u=+u;var A=0,d=0,m=0,B=$e;m=I,I=I+16|0,d=m,A=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(A=n[(n[o>>2]|0)+A>>2]|0),gOe(d,u),B=y(dOe(d,u)),XZ[A&1](o,B),I=m}function gOe(o,l){o=o|0,l=+l}function dOe(o,l){return o=o|0,l=+l,y(mOe(l))}function mOe(o){return o=+o,y(o)}function yOe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,d=A+8|0,m=A,k=n[u>>2]|0,B=n[u+4>>2]|0,u=Sn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],EOe(o,u,d,0),I=A}function EOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0,R=0,M=0,L=0;d=I,I=I+32|0,m=d+16|0,L=d+8|0,k=d,M=n[u>>2]|0,R=n[u+4>>2]|0,B=n[o>>2]|0,o=DM()|0,n[L>>2]=M,n[L+4>>2]=R,n[m>>2]=n[L>>2],n[m+4>>2]=n[L+4>>2],u=IOe(m)|0,n[k>>2]=M,n[k+4>>2]=R,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],Dn(B,l,o,u,COe(m,A)|0,A),I=d}function DM(){var o=0,l=0;if(s[7856]|0||(_z(10172),gr(50,10172,U|0)|0,l=7856,n[l>>2]=1,n[l+4>>2]=0),!(_r(10172)|0)){o=10172,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));_z(10172)}return 10172}function IOe(o){return o=o|0,0}function COe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0;return L=I,I=I+32|0,d=L+24|0,B=L+16|0,k=L,R=L+8|0,m=n[o>>2]|0,A=n[o+4>>2]|0,n[k>>2]=m,n[k+4>>2]=A,q=DM()|0,M=q+24|0,o=yr(l,4)|0,n[R>>2]=o,l=q+28|0,u=n[l>>2]|0,u>>>0<(n[q+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=A,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],Uz(u,d,o),o=(n[l>>2]|0)+12|0,n[l>>2]=o):(wOe(M,k,R),o=n[l>>2]|0),I=L,((o-(n[M>>2]|0)|0)/12|0)+-1|0}function Uz(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=n[l+4>>2]|0,n[o>>2]=n[l>>2],n[o+4>>2]=A,n[o+8>>2]=u}function wOe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;if(M=I,I=I+48|0,A=M+32|0,B=M+24|0,k=M,R=o+4|0,d=(((n[R>>2]|0)-(n[o>>2]|0)|0)/12|0)+1|0,m=BOe(o)|0,m>>>0<d>>>0)an(o);else{L=n[o>>2]|0,oe=((n[o+8>>2]|0)-L|0)/12|0,q=oe<<1,vOe(k,oe>>>0<m>>>1>>>0?q>>>0<d>>>0?d:q:m,((n[R>>2]|0)-L|0)/12|0,o+8|0),R=k+8|0,m=n[R>>2]|0,d=n[l+4>>2]|0,u=n[u>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[A>>2]=n[B>>2],n[A+4>>2]=n[B+4>>2],Uz(m,A,u),n[R>>2]=(n[R>>2]|0)+12,SOe(o,k),DOe(k),I=M;return}}function BOe(o){return o=o|0,357913941}function vOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>357913941)Nt();else{d=Jt(l*12|0)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u*12|0)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l*12|0)}function SOe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function DOe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~(((A+-12-l|0)>>>0)/12|0)*12|0)),o=n[o>>2]|0,o|0&&It(o)}function _z(o){o=o|0,xOe(o)}function bOe(o){o=o|0,POe(o+24|0)}function POe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~(((l+-12-A|0)>>>0)/12|0)*12|0)),It(u))}function xOe(o){o=o|0;var l=0;l=tn()|0,rn(o,2,3,l,kOe()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function kOe(){return 1380}function QOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;d=I,I=I+16|0,m=d+8|0,B=d,k=ROe(o)|0,o=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=o,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],TOe(l,m,u,A),I=d}function ROe(o){return o=o|0,(n[(DM()|0)+24>>2]|0)+(o*12|0)|0}function TOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;k=I,I=I+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,o=o+(l>>1)|0,l&1&&(d=n[(n[o>>2]|0)+d>>2]|0),rp(m,u),m=np(m,u)|0,FOe(B,A),B=NOe(B,A)|0,DB[d&15](o,m,B),I=k}function FOe(o,l){o=o|0,l=l|0}function NOe(o,l){return o=o|0,l=l|0,OOe(l)|0}function OOe(o){return o=o|0,(o|0)!=0|0}function LOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=bM()|0,o=MOe(u)|0,Dn(m,l,d,o,UOe(u,A)|0,A)}function bM(){var o=0,l=0;if(s[7864]|0||(jz(10208),gr(51,10208,U|0)|0,l=7864,n[l>>2]=1,n[l+4>>2]=0),!(_r(10208)|0)){o=10208,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));jz(10208)}return 10208}function MOe(o){return o=o|0,o|0}function UOe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=bM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(Hz(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(_Oe(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function Hz(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function _Oe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=HOe(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,jOe(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,Hz(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,GOe(o,d),qOe(d),I=k;return}}function HOe(o){return o=o|0,536870911}function jOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function GOe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function qOe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function jz(o){o=o|0,YOe(o)}function WOe(o){o=o|0,VOe(o+24|0)}function VOe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function YOe(o){o=o|0;var l=0;l=tn()|0,rn(o,1,24,l,KOe()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function KOe(){return 1392}function JOe(o,l){o=o|0,l=l|0,ZOe(n[(zOe(o)|0)>>2]|0,l)}function zOe(o){return o=o|0,(n[(bM()|0)+24>>2]|0)+(o<<3)|0}function ZOe(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,Qz(A,l),l=Rz(A,l)|0,sp[o&127](l),I=u}function XOe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=PM()|0,o=$Oe(u)|0,Dn(m,l,d,o,eLe(u,A)|0,A)}function PM(){var o=0,l=0;if(s[7872]|0||(qz(10244),gr(52,10244,U|0)|0,l=7872,n[l>>2]=1,n[l+4>>2]=0),!(_r(10244)|0)){o=10244,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));qz(10244)}return 10244}function $Oe(o){return o=o|0,o|0}function eLe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=PM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(Gz(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(tLe(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function Gz(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function tLe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=rLe(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,nLe(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,Gz(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,iLe(o,d),sLe(d),I=k;return}}function rLe(o){return o=o|0,536870911}function nLe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function iLe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function sLe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function qz(o){o=o|0,lLe(o)}function oLe(o){o=o|0,aLe(o+24|0)}function aLe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function lLe(o){o=o|0;var l=0;l=tn()|0,rn(o,1,16,l,cLe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function cLe(){return 1400}function uLe(o){return o=o|0,ALe(n[(fLe(o)|0)>>2]|0)|0}function fLe(o){return o=o|0,(n[(PM()|0)+24>>2]|0)+(o<<3)|0}function ALe(o){return o=o|0,pLe(YP[o&7]()|0)|0}function pLe(o){return o=o|0,o|0}function hLe(){var o=0;return s[7880]|0||(CLe(10280),gr(25,10280,U|0)|0,o=7880,n[o>>2]=1,n[o+4>>2]=0),10280}function gLe(o,l){o=o|0,l=l|0,n[o>>2]=dLe()|0,n[o+4>>2]=mLe()|0,n[o+12>>2]=l,n[o+8>>2]=yLe()|0,n[o+32>>2]=4}function dLe(){return 11711}function mLe(){return 1356}function yLe(){return FP()|0}function ELe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(ILe(u),It(u)):l|0&&(Yg(l),It(l))}function ILe(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function CLe(o){o=o|0,Nh(o)}function wLe(o){o=o|0,BLe(o,4920),vLe(o)|0,SLe(o)|0}function BLe(o,l){o=o|0,l=l|0;var u=0;u=Az()|0,n[o>>2]=u,VLe(u,l),_h(n[o>>2]|0)}function vLe(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,OLe()|0),o|0}function SLe(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,DLe()|0),o|0}function DLe(){var o=0;return s[7888]|0||(Wz(10328),gr(53,10328,U|0)|0,o=7888,n[o>>2]=1,n[o+4>>2]=0),_r(10328)|0||Wz(10328),10328}function ad(o,l){o=o|0,l=l|0,Dn(o,0,l,0,0,0)}function Wz(o){o=o|0,xLe(o),ld(o,10)}function bLe(o){o=o|0,PLe(o+24|0)}function PLe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function xLe(o){o=o|0;var l=0;l=tn()|0,rn(o,5,1,l,TLe()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function kLe(o,l,u){o=o|0,l=l|0,u=+u,QLe(o,l,u)}function ld(o,l){o=o|0,l=l|0,n[o+20>>2]=l}function QLe(o,l,u){o=o|0,l=l|0,u=+u;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+16|0,m=A+8|0,k=A+13|0,d=A,B=A+12|0,rp(k,l),n[m>>2]=np(k,l)|0,Tf(B,u),E[d>>3]=+Ff(B,u),RLe(o,m,d),I=A}function RLe(o,l,u){o=o|0,l=l|0,u=u|0,Ml(o+8|0,n[l>>2]|0,+E[u>>3]),s[o+24>>0]=1}function TLe(){return 1404}function FLe(o,l){return o=o|0,l=+l,NLe(o,l)|0}function NLe(o,l){o=o|0,l=+l;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return A=I,I=I+16|0,m=A+4|0,B=A+8|0,k=A,d=Ul(8)|0,u=d,R=Jt(16)|0,rp(m,o),o=np(m,o)|0,Tf(B,l),Ml(R,o,+Ff(B,l)),B=u+4|0,n[B>>2]=R,o=Jt(8)|0,B=n[B>>2]|0,n[k>>2]=0,n[m>>2]=n[k>>2],pM(o,B,m),n[d>>2]=o,I=A,u|0}function OLe(){var o=0;return s[7896]|0||(Vz(10364),gr(54,10364,U|0)|0,o=7896,n[o>>2]=1,n[o+4>>2]=0),_r(10364)|0||Vz(10364),10364}function Vz(o){o=o|0,ULe(o),ld(o,55)}function LLe(o){o=o|0,MLe(o+24|0)}function MLe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function ULe(o){o=o|0;var l=0;l=tn()|0,rn(o,5,4,l,GLe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function _Le(o){o=o|0,HLe(o)}function HLe(o){o=o|0,jLe(o)}function jLe(o){o=o|0,Yz(o+8|0),s[o+24>>0]=1}function Yz(o){o=o|0,n[o>>2]=0,E[o+8>>3]=0}function GLe(){return 1424}function qLe(){return WLe()|0}function WLe(){var o=0,l=0,u=0,A=0,d=0,m=0,B=0;return l=I,I=I+16|0,d=l+4|0,B=l,u=Ul(8)|0,o=u,A=Jt(16)|0,Yz(A),m=o+4|0,n[m>>2]=A,A=Jt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],pM(A,m,d),n[u>>2]=A,I=l,o|0}function VLe(o,l){o=o|0,l=l|0,n[o>>2]=YLe()|0,n[o+4>>2]=KLe()|0,n[o+12>>2]=l,n[o+8>>2]=JLe()|0,n[o+32>>2]=5}function YLe(){return 11710}function KLe(){return 1416}function JLe(){return NP()|0}function zLe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(ZLe(u),It(u)):l|0&&It(l)}function ZLe(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function NP(){var o=0;return s[7904]|0||(n[2600]=XLe()|0,n[2601]=0,o=7904,n[o>>2]=1,n[o+4>>2]=0),10400}function XLe(){return n[357]|0}function $Le(o){o=o|0,eMe(o,4926),tMe(o)|0}function eMe(o,l){o=o|0,l=l|0;var u=0;u=NJ()|0,n[o>>2]=u,AMe(u,l),_h(n[o>>2]|0)}function tMe(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,rMe()|0),o|0}function rMe(){var o=0;return s[7912]|0||(Kz(10412),gr(56,10412,U|0)|0,o=7912,n[o>>2]=1,n[o+4>>2]=0),_r(10412)|0||Kz(10412),10412}function Kz(o){o=o|0,sMe(o),ld(o,57)}function nMe(o){o=o|0,iMe(o+24|0)}function iMe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function sMe(o){o=o|0;var l=0;l=tn()|0,rn(o,5,5,l,cMe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function oMe(o){o=o|0,aMe(o)}function aMe(o){o=o|0,lMe(o)}function lMe(o){o=o|0;var l=0,u=0;l=o+8|0,u=l+48|0;do n[l>>2]=0,l=l+4|0;while((l|0)<(u|0));s[o+56>>0]=1}function cMe(){return 1432}function uMe(){return fMe()|0}function fMe(){var o=0,l=0,u=0,A=0,d=0,m=0,B=0,k=0;B=I,I=I+16|0,o=B+4|0,l=B,u=Ul(8)|0,A=u,d=Jt(48)|0,m=d,k=m+48|0;do n[m>>2]=0,m=m+4|0;while((m|0)<(k|0));return m=A+4|0,n[m>>2]=d,k=Jt(8)|0,m=n[m>>2]|0,n[l>>2]=0,n[o>>2]=n[l>>2],OJ(k,m,o),n[u>>2]=k,I=B,A|0}function AMe(o,l){o=o|0,l=l|0,n[o>>2]=pMe()|0,n[o+4>>2]=hMe()|0,n[o+12>>2]=l,n[o+8>>2]=gMe()|0,n[o+32>>2]=6}function pMe(){return 11704}function hMe(){return 1436}function gMe(){return NP()|0}function dMe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(mMe(u),It(u)):l|0&&It(l)}function mMe(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function yMe(o){o=o|0,EMe(o,4933),IMe(o)|0,CMe(o)|0}function EMe(o,l){o=o|0,l=l|0;var u=0;u=WMe()|0,n[o>>2]=u,VMe(u,l),_h(n[o>>2]|0)}function IMe(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,NMe()|0),o|0}function CMe(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,wMe()|0),o|0}function wMe(){var o=0;return s[7920]|0||(Jz(10452),gr(58,10452,U|0)|0,o=7920,n[o>>2]=1,n[o+4>>2]=0),_r(10452)|0||Jz(10452),10452}function Jz(o){o=o|0,SMe(o),ld(o,1)}function BMe(o){o=o|0,vMe(o+24|0)}function vMe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function SMe(o){o=o|0;var l=0;l=tn()|0,rn(o,5,1,l,xMe()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function DMe(o,l,u){o=o|0,l=+l,u=+u,bMe(o,l,u)}function bMe(o,l,u){o=o|0,l=+l,u=+u;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+32|0,m=A+8|0,k=A+17|0,d=A,B=A+16|0,Tf(k,l),E[m>>3]=+Ff(k,l),Tf(B,u),E[d>>3]=+Ff(B,u),PMe(o,m,d),I=A}function PMe(o,l,u){o=o|0,l=l|0,u=u|0,zz(o+8|0,+E[l>>3],+E[u>>3]),s[o+24>>0]=1}function zz(o,l,u){o=o|0,l=+l,u=+u,E[o>>3]=l,E[o+8>>3]=u}function xMe(){return 1472}function kMe(o,l){return o=+o,l=+l,QMe(o,l)|0}function QMe(o,l){o=+o,l=+l;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return A=I,I=I+16|0,B=A+4|0,k=A+8|0,R=A,d=Ul(8)|0,u=d,m=Jt(16)|0,Tf(B,o),o=+Ff(B,o),Tf(k,l),zz(m,o,+Ff(k,l)),k=u+4|0,n[k>>2]=m,m=Jt(8)|0,k=n[k>>2]|0,n[R>>2]=0,n[B>>2]=n[R>>2],Zz(m,k,B),n[d>>2]=m,I=A,u|0}function Zz(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,u=Jt(16)|0,n[u+4>>2]=0,n[u+8>>2]=0,n[u>>2]=1452,n[u+12>>2]=l,n[o+4>>2]=u}function RMe(o){o=o|0,rE(o),It(o)}function TMe(o){o=o|0,o=n[o+12>>2]|0,o|0&&It(o)}function FMe(o){o=o|0,It(o)}function NMe(){var o=0;return s[7928]|0||(Xz(10488),gr(59,10488,U|0)|0,o=7928,n[o>>2]=1,n[o+4>>2]=0),_r(10488)|0||Xz(10488),10488}function Xz(o){o=o|0,MMe(o),ld(o,60)}function OMe(o){o=o|0,LMe(o+24|0)}function LMe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function MMe(o){o=o|0;var l=0;l=tn()|0,rn(o,5,6,l,jMe()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function UMe(o){o=o|0,_Me(o)}function _Me(o){o=o|0,HMe(o)}function HMe(o){o=o|0,$z(o+8|0),s[o+24>>0]=1}function $z(o){o=o|0,n[o>>2]=0,n[o+4>>2]=0,n[o+8>>2]=0,n[o+12>>2]=0}function jMe(){return 1492}function GMe(){return qMe()|0}function qMe(){var o=0,l=0,u=0,A=0,d=0,m=0,B=0;return l=I,I=I+16|0,d=l+4|0,B=l,u=Ul(8)|0,o=u,A=Jt(16)|0,$z(A),m=o+4|0,n[m>>2]=A,A=Jt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],Zz(A,m,d),n[u>>2]=A,I=l,o|0}function WMe(){var o=0;return s[7936]|0||(XMe(10524),gr(25,10524,U|0)|0,o=7936,n[o>>2]=1,n[o+4>>2]=0),10524}function VMe(o,l){o=o|0,l=l|0,n[o>>2]=YMe()|0,n[o+4>>2]=KMe()|0,n[o+12>>2]=l,n[o+8>>2]=JMe()|0,n[o+32>>2]=7}function YMe(){return 11700}function KMe(){return 1484}function JMe(){return NP()|0}function zMe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(ZMe(u),It(u)):l|0&&It(l)}function ZMe(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function XMe(o){o=o|0,Nh(o)}function $Me(o,l,u){o=o|0,l=l|0,u=u|0,o=Sn(l)|0,l=eUe(u)|0,u=tUe(u,0)|0,QUe(o,l,u,xM()|0,0)}function eUe(o){return o=o|0,o|0}function tUe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=xM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(tZ(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(lUe(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function xM(){var o=0,l=0;if(s[7944]|0||(eZ(10568),gr(61,10568,U|0)|0,l=7944,n[l>>2]=1,n[l+4>>2]=0),!(_r(10568)|0)){o=10568,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));eZ(10568)}return 10568}function eZ(o){o=o|0,iUe(o)}function rUe(o){o=o|0,nUe(o+24|0)}function nUe(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function iUe(o){o=o|0;var l=0;l=tn()|0,rn(o,1,17,l,$J()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function sUe(o){return o=o|0,aUe(n[(oUe(o)|0)>>2]|0)|0}function oUe(o){return o=o|0,(n[(xM()|0)+24>>2]|0)+(o<<3)|0}function aUe(o){return o=o|0,TP(YP[o&7]()|0)|0}function tZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function lUe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=cUe(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,uUe(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,tZ(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,fUe(o,d),AUe(d),I=k;return}}function cUe(o){return o=o|0,536870911}function uUe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function fUe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function AUe(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function pUe(){hUe()}function hUe(){gUe(10604)}function gUe(o){o=o|0,dUe(o,4955)}function dUe(o,l){o=o|0,l=l|0;var u=0;u=mUe()|0,n[o>>2]=u,yUe(u,l),_h(n[o>>2]|0)}function mUe(){var o=0;return s[7952]|0||(bUe(10612),gr(25,10612,U|0)|0,o=7952,n[o>>2]=1,n[o+4>>2]=0),10612}function yUe(o,l){o=o|0,l=l|0,n[o>>2]=wUe()|0,n[o+4>>2]=BUe()|0,n[o+12>>2]=l,n[o+8>>2]=vUe()|0,n[o+32>>2]=8}function _h(o){o=o|0;var l=0,u=0;l=I,I=I+16|0,u=l,Zy()|0,n[u>>2]=o,EUe(10608,u),I=l}function Zy(){return s[11714]|0||(n[2652]=0,gr(62,10608,U|0)|0,s[11714]=1),10608}function EUe(o,l){o=o|0,l=l|0;var u=0;u=Jt(8)|0,n[u+4>>2]=n[l>>2],n[u>>2]=n[o>>2],n[o>>2]=u}function IUe(o){o=o|0,CUe(o)}function CUe(o){o=o|0;var l=0,u=0;if(l=n[o>>2]|0,l|0)do u=l,l=n[l>>2]|0,It(u);while(l|0);n[o>>2]=0}function wUe(){return 11715}function BUe(){return 1496}function vUe(){return FP()|0}function SUe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(DUe(u),It(u)):l|0&&It(l)}function DUe(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function bUe(o){o=o|0,Nh(o)}function PUe(o,l){o=o|0,l=l|0;var u=0,A=0;Zy()|0,u=n[2652]|0;e:do if(u|0){for(;A=n[u+4>>2]|0,!(A|0&&!(OZ(kM(A)|0,o)|0));)if(u=n[u>>2]|0,!u)break e;xUe(A,l)}while(!1)}function kM(o){return o=o|0,n[o+12>>2]|0}function xUe(o,l){o=o|0,l=l|0;var u=0;o=o+36|0,u=n[o>>2]|0,u|0&&(bf(u),It(u)),u=Jt(4)|0,DP(u,l),n[o>>2]=u}function QM(){return s[11716]|0||(n[2664]=0,gr(63,10656,U|0)|0,s[11716]=1),10656}function rZ(){var o=0;return s[11717]|0?o=n[2665]|0:(kUe(),n[2665]=1504,s[11717]=1,o=1504),o|0}function kUe(){s[11740]|0||(s[11718]=yr(yr(8,0)|0,0)|0,s[11719]=yr(yr(0,0)|0,0)|0,s[11720]=yr(yr(0,16)|0,0)|0,s[11721]=yr(yr(8,0)|0,0)|0,s[11722]=yr(yr(0,0)|0,0)|0,s[11723]=yr(yr(8,0)|0,0)|0,s[11724]=yr(yr(0,0)|0,0)|0,s[11725]=yr(yr(8,0)|0,0)|0,s[11726]=yr(yr(0,0)|0,0)|0,s[11727]=yr(yr(8,0)|0,0)|0,s[11728]=yr(yr(0,0)|0,0)|0,s[11729]=yr(yr(0,0)|0,32)|0,s[11730]=yr(yr(0,0)|0,32)|0,s[11740]=1)}function nZ(){return 1572}function QUe(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0,M=0,L=0;m=I,I=I+32|0,L=m+16|0,M=m+12|0,R=m+8|0,k=m+4|0,B=m,n[L>>2]=o,n[M>>2]=l,n[R>>2]=u,n[k>>2]=A,n[B>>2]=d,QM()|0,RUe(10656,L,M,R,k,B),I=m}function RUe(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0;var B=0;B=Jt(24)|0,RJ(B+4|0,n[l>>2]|0,n[u>>2]|0,n[A>>2]|0,n[d>>2]|0,n[m>>2]|0),n[B>>2]=n[o>>2],n[o>>2]=B}function iZ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0,nt=0,Xe=0,ft=0;if(ft=I,I=I+32|0,Le=ft+20|0,Te=ft+8|0,nt=ft+4|0,Xe=ft,l=n[l>>2]|0,l|0){Ye=Le+4|0,R=Le+8|0,M=Te+4|0,L=Te+8|0,q=Te+8|0,oe=Le+8|0;do{if(B=l+4|0,k=RM(B)|0,k|0){if(d=IB(k)|0,n[Le>>2]=0,n[Ye>>2]=0,n[R>>2]=0,A=(CB(k)|0)+1|0,TUe(Le,A),A|0)for(;A=A+-1|0,Su(Te,n[d>>2]|0),m=n[Ye>>2]|0,m>>>0<(n[oe>>2]|0)>>>0?(n[m>>2]=n[Te>>2],n[Ye>>2]=(n[Ye>>2]|0)+4):TM(Le,Te),A;)d=d+4|0;A=wB(k)|0,n[Te>>2]=0,n[M>>2]=0,n[L>>2]=0;e:do if(n[A>>2]|0)for(d=0,m=0;;){if((d|0)==(m|0)?FUe(Te,A):(n[d>>2]=n[A>>2],n[M>>2]=(n[M>>2]|0)+4),A=A+4|0,!(n[A>>2]|0))break e;d=n[M>>2]|0,m=n[q>>2]|0}while(!1);n[nt>>2]=OP(B)|0,n[Xe>>2]=_r(k)|0,NUe(u,o,nt,Xe,Le,Te),FM(Te),ip(Le)}l=n[l>>2]|0}while(l|0)}I=ft}function RM(o){return o=o|0,n[o+12>>2]|0}function IB(o){return o=o|0,n[o+12>>2]|0}function CB(o){return o=o|0,n[o+16>>2]|0}function TUe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;d=I,I=I+32|0,u=d,A=n[o>>2]|0,(n[o+8>>2]|0)-A>>2>>>0<l>>>0&&(AZ(u,l,(n[o+4>>2]|0)-A>>2,o+8|0),pZ(o,u),hZ(u)),I=d}function TM(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0;if(B=I,I=I+32|0,u=B,A=o+4|0,d=((n[A>>2]|0)-(n[o>>2]|0)>>2)+1|0,m=fZ(o)|0,m>>>0<d>>>0)an(o);else{k=n[o>>2]|0,M=(n[o+8>>2]|0)-k|0,R=M>>1,AZ(u,M>>2>>>0<m>>>1>>>0?R>>>0<d>>>0?d:R:m,(n[A>>2]|0)-k>>2,o+8|0),m=u+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,pZ(o,u),hZ(u),I=B;return}}function wB(o){return o=o|0,n[o+8>>2]|0}function FUe(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0;if(B=I,I=I+32|0,u=B,A=o+4|0,d=((n[A>>2]|0)-(n[o>>2]|0)>>2)+1|0,m=uZ(o)|0,m>>>0<d>>>0)an(o);else{k=n[o>>2]|0,M=(n[o+8>>2]|0)-k|0,R=M>>1,e_e(u,M>>2>>>0<m>>>1>>>0?R>>>0<d>>>0?d:R:m,(n[A>>2]|0)-k>>2,o+8|0),m=u+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,t_e(o,u),r_e(u),I=B;return}}function OP(o){return o=o|0,n[o>>2]|0}function NUe(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,OUe(o,l,u,A,d,m)}function FM(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-4-A|0)>>>2)<<2)),It(u))}function ip(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-4-A|0)>>>2)<<2)),It(u))}function OUe(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0;var B=0,k=0,R=0,M=0,L=0,q=0;B=I,I=I+48|0,L=B+40|0,k=B+32|0,q=B+24|0,R=B+12|0,M=B,_l(k),o=Us(o)|0,n[q>>2]=n[l>>2],u=n[u>>2]|0,A=n[A>>2]|0,NM(R,d),LUe(M,m),n[L>>2]=n[q>>2],MUe(o,L,u,A,R,M),FM(M),ip(R),Hl(k),I=B}function NM(o,l){o=o|0,l=l|0;var u=0,A=0;n[o>>2]=0,n[o+4>>2]=0,n[o+8>>2]=0,u=l+4|0,A=(n[u>>2]|0)-(n[l>>2]|0)>>2,A|0&&(XUe(o,A),$Ue(o,n[l>>2]|0,n[u>>2]|0,A))}function LUe(o,l){o=o|0,l=l|0;var u=0,A=0;n[o>>2]=0,n[o+4>>2]=0,n[o+8>>2]=0,u=l+4|0,A=(n[u>>2]|0)-(n[l>>2]|0)>>2,A|0&&(zUe(o,A),ZUe(o,n[l>>2]|0,n[u>>2]|0,A))}function MUe(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0;var B=0,k=0,R=0,M=0,L=0,q=0;B=I,I=I+32|0,L=B+28|0,q=B+24|0,k=B+12|0,R=B,M=Ia(UUe()|0)|0,n[q>>2]=n[l>>2],n[L>>2]=n[q>>2],l=cd(L)|0,u=sZ(u)|0,A=OM(A)|0,n[k>>2]=n[d>>2],L=d+4|0,n[k+4>>2]=n[L>>2],q=d+8|0,n[k+8>>2]=n[q>>2],n[q>>2]=0,n[L>>2]=0,n[d>>2]=0,d=LM(k)|0,n[R>>2]=n[m>>2],L=m+4|0,n[R+4>>2]=n[L>>2],q=m+8|0,n[R+8>>2]=n[q>>2],n[q>>2]=0,n[L>>2]=0,n[m>>2]=0,ou(0,M|0,o|0,l|0,u|0,A|0,d|0,_Ue(R)|0)|0,FM(R),ip(k),I=B}function UUe(){var o=0;return s[7968]|0||(KUe(10708),o=7968,n[o>>2]=1,n[o+4>>2]=0),10708}function cd(o){return o=o|0,aZ(o)|0}function sZ(o){return o=o|0,oZ(o)|0}function OM(o){return o=o|0,TP(o)|0}function LM(o){return o=o|0,jUe(o)|0}function _Ue(o){return o=o|0,HUe(o)|0}function HUe(o){o=o|0;var l=0,u=0,A=0;if(A=(n[o+4>>2]|0)-(n[o>>2]|0)|0,u=A>>2,A=Ul(A+4|0)|0,n[A>>2]=u,u|0){l=0;do n[A+4+(l<<2)>>2]=oZ(n[(n[o>>2]|0)+(l<<2)>>2]|0)|0,l=l+1|0;while((l|0)!=(u|0))}return A|0}function oZ(o){return o=o|0,o|0}function jUe(o){o=o|0;var l=0,u=0,A=0;if(A=(n[o+4>>2]|0)-(n[o>>2]|0)|0,u=A>>2,A=Ul(A+4|0)|0,n[A>>2]=u,u|0){l=0;do n[A+4+(l<<2)>>2]=aZ((n[o>>2]|0)+(l<<2)|0)|0,l=l+1|0;while((l|0)!=(u|0))}return A|0}function aZ(o){o=o|0;var l=0,u=0,A=0,d=0;return d=I,I=I+32|0,l=d+12|0,u=d,A=JL(lZ()|0)|0,A?(zL(l,A),ZL(u,l),v8e(o,u),o=XL(l)|0):o=GUe(o)|0,I=d,o|0}function lZ(){var o=0;return s[7960]|0||(YUe(10664),gr(25,10664,U|0)|0,o=7960,n[o>>2]=1,n[o+4>>2]=0),10664}function GUe(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0;return u=I,I=I+16|0,d=u+4|0,B=u,A=Ul(8)|0,l=A,k=Jt(4)|0,n[k>>2]=n[o>>2],m=l+4|0,n[m>>2]=k,o=Jt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],cZ(o,m,d),n[A>>2]=o,I=u,l|0}function cZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,u=Jt(16)|0,n[u+4>>2]=0,n[u+8>>2]=0,n[u>>2]=1656,n[u+12>>2]=l,n[o+4>>2]=u}function qUe(o){o=o|0,rE(o),It(o)}function WUe(o){o=o|0,o=n[o+12>>2]|0,o|0&&It(o)}function VUe(o){o=o|0,It(o)}function YUe(o){o=o|0,Nh(o)}function KUe(o){o=o|0,Oo(o,JUe()|0,5)}function JUe(){return 1676}function zUe(o,l){o=o|0,l=l|0;var u=0;if((uZ(o)|0)>>>0<l>>>0&&an(o),l>>>0>1073741823)Nt();else{u=Jt(l<<2)|0,n[o+4>>2]=u,n[o>>2]=u,n[o+8>>2]=u+(l<<2);return}}function ZUe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,A=o+4|0,o=u-l|0,(o|0)>0&&(Qr(n[A>>2]|0,l|0,o|0)|0,n[A>>2]=(n[A>>2]|0)+(o>>>2<<2))}function uZ(o){return o=o|0,1073741823}function XUe(o,l){o=o|0,l=l|0;var u=0;if((fZ(o)|0)>>>0<l>>>0&&an(o),l>>>0>1073741823)Nt();else{u=Jt(l<<2)|0,n[o+4>>2]=u,n[o>>2]=u,n[o+8>>2]=u+(l<<2);return}}function $Ue(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,A=o+4|0,o=u-l|0,(o|0)>0&&(Qr(n[A>>2]|0,l|0,o|0)|0,n[A>>2]=(n[A>>2]|0)+(o>>>2<<2))}function fZ(o){return o=o|0,1073741823}function e_e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>1073741823)Nt();else{d=Jt(l<<2)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<2)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<2)}function t_e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function r_e(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-4-l|0)>>>2)<<2)),o=n[o>>2]|0,o|0&&It(o)}function AZ(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>1073741823)Nt();else{d=Jt(l<<2)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<2)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<2)}function pZ(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function hZ(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-4-l|0)>>>2)<<2)),o=n[o>>2]|0,o|0&&It(o)}function n_e(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0;if(Te=I,I=I+32|0,L=Te+20|0,q=Te+12|0,M=Te+16|0,oe=Te+4|0,Ye=Te,Le=Te+8|0,k=rZ()|0,m=n[k>>2]|0,B=n[m>>2]|0,B|0)for(R=n[k+8>>2]|0,k=n[k+4>>2]|0;Su(L,B),i_e(o,L,k,R),m=m+4|0,B=n[m>>2]|0,B;)R=R+1|0,k=k+1|0;if(m=nZ()|0,B=n[m>>2]|0,B|0)do Su(L,B),n[q>>2]=n[m+4>>2],s_e(l,L,q),m=m+8|0,B=n[m>>2]|0;while(B|0);if(m=n[(Zy()|0)>>2]|0,m|0)do l=n[m+4>>2]|0,Su(L,n[(Xy(l)|0)>>2]|0),n[q>>2]=kM(l)|0,o_e(u,L,q),m=n[m>>2]|0;while(m|0);if(Su(M,0),m=QM()|0,n[L>>2]=n[M>>2],iZ(L,m,d),m=n[(Zy()|0)>>2]|0,m|0){o=L+4|0,l=L+8|0,u=L+8|0;do{if(R=n[m+4>>2]|0,Su(q,n[(Xy(R)|0)>>2]|0),a_e(oe,gZ(R)|0),B=n[oe>>2]|0,B|0){n[L>>2]=0,n[o>>2]=0,n[l>>2]=0;do Su(Ye,n[(Xy(n[B+4>>2]|0)|0)>>2]|0),k=n[o>>2]|0,k>>>0<(n[u>>2]|0)>>>0?(n[k>>2]=n[Ye>>2],n[o>>2]=(n[o>>2]|0)+4):TM(L,Ye),B=n[B>>2]|0;while(B|0);l_e(A,q,L),ip(L)}n[Le>>2]=n[q>>2],M=dZ(R)|0,n[L>>2]=n[Le>>2],iZ(L,M,d),MJ(oe),m=n[m>>2]|0}while(m|0)}I=Te}function i_e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,I_e(o,l,u,A)}function s_e(o,l,u){o=o|0,l=l|0,u=u|0,E_e(o,l,u)}function Xy(o){return o=o|0,o|0}function o_e(o,l,u){o=o|0,l=l|0,u=u|0,g_e(o,l,u)}function gZ(o){return o=o|0,o+16|0}function a_e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;if(m=I,I=I+16|0,d=m+8|0,u=m,n[o>>2]=0,A=n[l>>2]|0,n[d>>2]=A,n[u>>2]=o,u=h_e(u)|0,A|0){if(A=Jt(12)|0,B=(mZ(d)|0)+4|0,o=n[B+4>>2]|0,l=A+4|0,n[l>>2]=n[B>>2],n[l+4>>2]=o,l=n[n[d>>2]>>2]|0,n[d>>2]=l,!l)o=A;else for(l=A;o=Jt(12)|0,R=(mZ(d)|0)+4|0,k=n[R+4>>2]|0,B=o+4|0,n[B>>2]=n[R>>2],n[B+4>>2]=k,n[l>>2]=o,B=n[n[d>>2]>>2]|0,n[d>>2]=B,B;)l=o;n[o>>2]=n[u>>2],n[u>>2]=A}I=m}function l_e(o,l,u){o=o|0,l=l|0,u=u|0,c_e(o,l,u)}function dZ(o){return o=o|0,o+24|0}function c_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+32|0,B=A+24|0,d=A+16|0,k=A+12|0,m=A,_l(d),o=Us(o)|0,n[k>>2]=n[l>>2],NM(m,u),n[B>>2]=n[k>>2],u_e(o,B,m),ip(m),Hl(d),I=A}function u_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=I,I=I+32|0,B=A+16|0,k=A+12|0,d=A,m=Ia(f_e()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=cd(B)|0,n[d>>2]=n[u>>2],B=u+4|0,n[d+4>>2]=n[B>>2],k=u+8|0,n[d+8>>2]=n[k>>2],n[k>>2]=0,n[B>>2]=0,n[u>>2]=0,Ns(0,m|0,o|0,l|0,LM(d)|0)|0,ip(d),I=A}function f_e(){var o=0;return s[7976]|0||(A_e(10720),o=7976,n[o>>2]=1,n[o+4>>2]=0),10720}function A_e(o){o=o|0,Oo(o,p_e()|0,2)}function p_e(){return 1732}function h_e(o){return o=o|0,n[o>>2]|0}function mZ(o){return o=o|0,n[o>>2]|0}function g_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+32|0,m=A+16|0,d=A+8|0,B=A,_l(d),o=Us(o)|0,n[B>>2]=n[l>>2],u=n[u>>2]|0,n[m>>2]=n[B>>2],yZ(o,m,u),Hl(d),I=A}function yZ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+16|0,m=A+4|0,B=A,d=Ia(d_e()|0)|0,n[B>>2]=n[l>>2],n[m>>2]=n[B>>2],l=cd(m)|0,Ns(0,d|0,o|0,l|0,sZ(u)|0)|0,I=A}function d_e(){var o=0;return s[7984]|0||(m_e(10732),o=7984,n[o>>2]=1,n[o+4>>2]=0),10732}function m_e(o){o=o|0,Oo(o,y_e()|0,2)}function y_e(){return 1744}function E_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;A=I,I=I+32|0,m=A+16|0,d=A+8|0,B=A,_l(d),o=Us(o)|0,n[B>>2]=n[l>>2],u=n[u>>2]|0,n[m>>2]=n[B>>2],yZ(o,m,u),Hl(d),I=A}function I_e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;d=I,I=I+32|0,B=d+16|0,m=d+8|0,k=d,_l(m),o=Us(o)|0,n[k>>2]=n[l>>2],u=s[u>>0]|0,A=s[A>>0]|0,n[B>>2]=n[k>>2],C_e(o,B,u,A),Hl(m),I=d}function C_e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;d=I,I=I+16|0,B=d+4|0,k=d,m=Ia(w_e()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=cd(B)|0,u=$y(u)|0,Li(0,m|0,o|0,l|0,u|0,$y(A)|0)|0,I=d}function w_e(){var o=0;return s[7992]|0||(v_e(10744),o=7992,n[o>>2]=1,n[o+4>>2]=0),10744}function $y(o){return o=o|0,B_e(o)|0}function B_e(o){return o=o|0,o&255|0}function v_e(o){o=o|0,Oo(o,S_e()|0,3)}function S_e(){return 1756}function D_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;switch(oe=I,I=I+32|0,k=oe+8|0,R=oe+4|0,M=oe+20|0,L=oe,rM(o,0),A=B8e(l)|0,n[k>>2]=0,q=k+4|0,n[q>>2]=0,n[k+8>>2]=0,A<<24>>24){case 0:{s[M>>0]=0,b_e(R,u,M),LP(o,R)|0,Pf(R);break}case 8:{q=GM(l)|0,s[M>>0]=8,Su(L,n[q+4>>2]|0),P_e(R,u,M,L,q+8|0),LP(o,R)|0,Pf(R);break}case 9:{if(m=GM(l)|0,l=n[m+4>>2]|0,l|0)for(B=k+8|0,d=m+12|0;l=l+-1|0,Su(R,n[d>>2]|0),A=n[q>>2]|0,A>>>0<(n[B>>2]|0)>>>0?(n[A>>2]=n[R>>2],n[q>>2]=(n[q>>2]|0)+4):TM(k,R),l;)d=d+4|0;s[M>>0]=9,Su(L,n[m+8>>2]|0),x_e(R,u,M,L,k),LP(o,R)|0,Pf(R);break}default:q=GM(l)|0,s[M>>0]=A,Su(L,n[q+4>>2]|0),k_e(R,u,M,L),LP(o,R)|0,Pf(R)}ip(k),I=oe}function b_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;A=I,I=I+16|0,d=A,_l(d),l=Us(l)|0,G_e(o,l,s[u>>0]|0),Hl(d),I=A}function LP(o,l){o=o|0,l=l|0;var u=0;return u=n[o>>2]|0,u|0&&ja(u|0),n[o>>2]=n[l>>2],n[l>>2]=0,o|0}function P_e(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0;m=I,I=I+32|0,k=m+16|0,B=m+8|0,R=m,_l(B),l=Us(l)|0,u=s[u>>0]|0,n[R>>2]=n[A>>2],d=n[d>>2]|0,n[k>>2]=n[R>>2],U_e(o,l,u,k,d),Hl(B),I=m}function x_e(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0,M=0;m=I,I=I+32|0,R=m+24|0,B=m+16|0,M=m+12|0,k=m,_l(B),l=Us(l)|0,u=s[u>>0]|0,n[M>>2]=n[A>>2],NM(k,d),n[R>>2]=n[M>>2],N_e(o,l,u,R,k),ip(k),Hl(B),I=m}function k_e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;d=I,I=I+32|0,B=d+16|0,m=d+8|0,k=d,_l(m),l=Us(l)|0,u=s[u>>0]|0,n[k>>2]=n[A>>2],n[B>>2]=n[k>>2],Q_e(o,l,u,B),Hl(m),I=d}function Q_e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0,B=0,k=0;d=I,I=I+16|0,m=d+4|0,k=d,B=Ia(R_e()|0)|0,u=$y(u)|0,n[k>>2]=n[A>>2],n[m>>2]=n[k>>2],MP(o,Ns(0,B|0,l|0,u|0,cd(m)|0)|0),I=d}function R_e(){var o=0;return s[8e3]|0||(T_e(10756),o=8e3,n[o>>2]=1,n[o+4>>2]=0),10756}function MP(o,l){o=o|0,l=l|0,rM(o,l)}function T_e(o){o=o|0,Oo(o,F_e()|0,2)}function F_e(){return 1772}function N_e(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0,M=0;m=I,I=I+32|0,R=m+16|0,M=m+12|0,B=m,k=Ia(O_e()|0)|0,u=$y(u)|0,n[M>>2]=n[A>>2],n[R>>2]=n[M>>2],A=cd(R)|0,n[B>>2]=n[d>>2],R=d+4|0,n[B+4>>2]=n[R>>2],M=d+8|0,n[B+8>>2]=n[M>>2],n[M>>2]=0,n[R>>2]=0,n[d>>2]=0,MP(o,Li(0,k|0,l|0,u|0,A|0,LM(B)|0)|0),ip(B),I=m}function O_e(){var o=0;return s[8008]|0||(L_e(10768),o=8008,n[o>>2]=1,n[o+4>>2]=0),10768}function L_e(o){o=o|0,Oo(o,M_e()|0,3)}function M_e(){return 1784}function U_e(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0;m=I,I=I+16|0,k=m+4|0,R=m,B=Ia(__e()|0)|0,u=$y(u)|0,n[R>>2]=n[A>>2],n[k>>2]=n[R>>2],A=cd(k)|0,MP(o,Li(0,B|0,l|0,u|0,A|0,OM(d)|0)|0),I=m}function __e(){var o=0;return s[8016]|0||(H_e(10780),o=8016,n[o>>2]=1,n[o+4>>2]=0),10780}function H_e(o){o=o|0,Oo(o,j_e()|0,3)}function j_e(){return 1800}function G_e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;A=Ia(q_e()|0)|0,MP(o,mn(0,A|0,l|0,$y(u)|0)|0)}function q_e(){var o=0;return s[8024]|0||(W_e(10792),o=8024,n[o>>2]=1,n[o+4>>2]=0),10792}function W_e(o){o=o|0,Oo(o,V_e()|0,1)}function V_e(){return 1816}function Y_e(){K_e(),J_e(),z_e()}function K_e(){n[2702]=VZ(65536)|0}function J_e(){d4e(10856)}function z_e(){Z_e(10816)}function Z_e(o){o=o|0,X_e(o,5044),$_e(o)|0}function X_e(o,l){o=o|0,l=l|0;var u=0;u=lZ()|0,n[o>>2]=u,u4e(u,l),_h(n[o>>2]|0)}function $_e(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,e4e()|0),o|0}function e4e(){var o=0;return s[8032]|0||(EZ(10820),gr(64,10820,U|0)|0,o=8032,n[o>>2]=1,n[o+4>>2]=0),_r(10820)|0||EZ(10820),10820}function EZ(o){o=o|0,n4e(o),ld(o,25)}function t4e(o){o=o|0,r4e(o+24|0)}function r4e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function n4e(o){o=o|0;var l=0;l=tn()|0,rn(o,5,18,l,a4e()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function i4e(o,l){o=o|0,l=l|0,s4e(o,l)}function s4e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;u=I,I=I+16|0,A=u,d=u+4|0,sd(d,l),n[A>>2]=od(d,l)|0,o4e(o,A),I=u}function o4e(o,l){o=o|0,l=l|0,IZ(o+4|0,n[l>>2]|0),s[o+8>>0]=1}function IZ(o,l){o=o|0,l=l|0,n[o>>2]=l}function a4e(){return 1824}function l4e(o){return o=o|0,c4e(o)|0}function c4e(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0;return u=I,I=I+16|0,d=u+4|0,B=u,A=Ul(8)|0,l=A,k=Jt(4)|0,sd(d,o),IZ(k,od(d,o)|0),m=l+4|0,n[m>>2]=k,o=Jt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],cZ(o,m,d),n[A>>2]=o,I=u,l|0}function Ul(o){o=o|0;var l=0,u=0;return o=o+7&-8,o>>>0<=32768&&(l=n[2701]|0,o>>>0<=(65536-l|0)>>>0)?(u=(n[2702]|0)+l|0,n[2701]=l+o,o=u):(o=VZ(o+8|0)|0,n[o>>2]=n[2703],n[2703]=o,o=o+8|0),o|0}function u4e(o,l){o=o|0,l=l|0,n[o>>2]=f4e()|0,n[o+4>>2]=A4e()|0,n[o+12>>2]=l,n[o+8>>2]=p4e()|0,n[o+32>>2]=9}function f4e(){return 11744}function A4e(){return 1832}function p4e(){return NP()|0}function h4e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(g4e(u),It(u)):l|0&&It(l)}function g4e(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function d4e(o){o=o|0,m4e(o,5052),y4e(o)|0,E4e(o,5058,26)|0,I4e(o,5069,1)|0,C4e(o,5077,10)|0,w4e(o,5087,19)|0,B4e(o,5094,27)|0}function m4e(o,l){o=o|0,l=l|0;var u=0;u=g8e()|0,n[o>>2]=u,d8e(u,l),_h(n[o>>2]|0)}function y4e(o){o=o|0;var l=0;return l=n[o>>2]|0,ad(l,t8e()|0),o|0}function E4e(o,l,u){return o=o|0,l=l|0,u=u|0,L3e(o,Sn(l)|0,u,0),o|0}function I4e(o,l,u){return o=o|0,l=l|0,u=u|0,w3e(o,Sn(l)|0,u,0),o|0}function C4e(o,l,u){return o=o|0,l=l|0,u=u|0,e3e(o,Sn(l)|0,u,0),o|0}function w4e(o,l,u){return o=o|0,l=l|0,u=u|0,U4e(o,Sn(l)|0,u,0),o|0}function CZ(o,l){o=o|0,l=l|0;var u=0,A=0;e:for(;;){for(u=n[2703]|0;;){if((u|0)==(l|0))break e;if(A=n[u>>2]|0,n[2703]=A,!u)u=A;else break}It(u)}n[2701]=o}function B4e(o,l,u){return o=o|0,l=l|0,u=u|0,v4e(o,Sn(l)|0,u,0),o|0}function v4e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=MM()|0,o=S4e(u)|0,Dn(m,l,d,o,D4e(u,A)|0,A)}function MM(){var o=0,l=0;if(s[8040]|0||(BZ(10860),gr(65,10860,U|0)|0,l=8040,n[l>>2]=1,n[l+4>>2]=0),!(_r(10860)|0)){o=10860,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));BZ(10860)}return 10860}function S4e(o){return o=o|0,o|0}function D4e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=MM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(wZ(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(b4e(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function wZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function b4e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=P4e(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,x4e(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,wZ(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,k4e(o,d),Q4e(d),I=k;return}}function P4e(o){return o=o|0,536870911}function x4e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function k4e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function Q4e(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function BZ(o){o=o|0,F4e(o)}function R4e(o){o=o|0,T4e(o+24|0)}function T4e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function F4e(o){o=o|0;var l=0;l=tn()|0,rn(o,1,11,l,N4e()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function N4e(){return 1840}function O4e(o,l,u){o=o|0,l=l|0,u=u|0,M4e(n[(L4e(o)|0)>>2]|0,l,u)}function L4e(o){return o=o|0,(n[(MM()|0)+24>>2]|0)+(o<<3)|0}function M4e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;A=I,I=I+16|0,m=A+1|0,d=A,sd(m,l),l=od(m,l)|0,sd(d,u),u=od(d,u)|0,op[o&31](l,u),I=A}function U4e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=UM()|0,o=_4e(u)|0,Dn(m,l,d,o,H4e(u,A)|0,A)}function UM(){var o=0,l=0;if(s[8048]|0||(SZ(10896),gr(66,10896,U|0)|0,l=8048,n[l>>2]=1,n[l+4>>2]=0),!(_r(10896)|0)){o=10896,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));SZ(10896)}return 10896}function _4e(o){return o=o|0,o|0}function H4e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=UM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(vZ(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(j4e(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function vZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function j4e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=G4e(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,q4e(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,vZ(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,W4e(o,d),V4e(d),I=k;return}}function G4e(o){return o=o|0,536870911}function q4e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function W4e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function V4e(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function SZ(o){o=o|0,J4e(o)}function Y4e(o){o=o|0,K4e(o+24|0)}function K4e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function J4e(o){o=o|0;var l=0;l=tn()|0,rn(o,1,11,l,z4e()|0,1),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function z4e(){return 1852}function Z4e(o,l){return o=o|0,l=l|0,$4e(n[(X4e(o)|0)>>2]|0,l)|0}function X4e(o){return o=o|0,(n[(UM()|0)+24>>2]|0)+(o<<3)|0}function $4e(o,l){o=o|0,l=l|0;var u=0,A=0;return u=I,I=I+16|0,A=u,sd(A,l),l=od(A,l)|0,l=TP(pd[o&31](l)|0)|0,I=u,l|0}function e3e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=_M()|0,o=t3e(u)|0,Dn(m,l,d,o,r3e(u,A)|0,A)}function _M(){var o=0,l=0;if(s[8056]|0||(bZ(10932),gr(67,10932,U|0)|0,l=8056,n[l>>2]=1,n[l+4>>2]=0),!(_r(10932)|0)){o=10932,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));bZ(10932)}return 10932}function t3e(o){return o=o|0,o|0}function r3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=_M()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(DZ(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(n3e(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function DZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function n3e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=i3e(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,s3e(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,DZ(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,o3e(o,d),a3e(d),I=k;return}}function i3e(o){return o=o|0,536870911}function s3e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function o3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function a3e(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function bZ(o){o=o|0,u3e(o)}function l3e(o){o=o|0,c3e(o+24|0)}function c3e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function u3e(o){o=o|0;var l=0;l=tn()|0,rn(o,1,7,l,f3e()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function f3e(){return 1860}function A3e(o,l,u){return o=o|0,l=l|0,u=u|0,h3e(n[(p3e(o)|0)>>2]|0,l,u)|0}function p3e(o){return o=o|0,(n[(_M()|0)+24>>2]|0)+(o<<3)|0}function h3e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0;return A=I,I=I+32|0,B=A+12|0,m=A+8|0,k=A,R=A+16|0,d=A+4|0,g3e(R,l),d3e(k,R,l),Oh(d,u),u=Lh(d,u)|0,n[B>>2]=n[k>>2],DB[o&15](m,B,u),u=m3e(m)|0,Pf(m),Mh(d),I=A,u|0}function g3e(o,l){o=o|0,l=l|0}function d3e(o,l,u){o=o|0,l=l|0,u=u|0,y3e(o,u)}function m3e(o){return o=o|0,Us(o)|0}function y3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0;d=I,I=I+16|0,u=d,A=l,A&1?(E3e(u,0),Ue(A|0,u|0)|0,I3e(o,u),C3e(u)):n[o>>2]=n[l>>2],I=d}function E3e(o,l){o=o|0,l=l|0,Bu(o,l),n[o+4>>2]=0,s[o+8>>0]=0}function I3e(o,l){o=o|0,l=l|0,n[o>>2]=n[l+4>>2]}function C3e(o){o=o|0,s[o+8>>0]=0}function w3e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=HM()|0,o=B3e(u)|0,Dn(m,l,d,o,v3e(u,A)|0,A)}function HM(){var o=0,l=0;if(s[8064]|0||(xZ(10968),gr(68,10968,U|0)|0,l=8064,n[l>>2]=1,n[l+4>>2]=0),!(_r(10968)|0)){o=10968,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));xZ(10968)}return 10968}function B3e(o){return o=o|0,o|0}function v3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=HM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(PZ(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(S3e(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function PZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function S3e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=D3e(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,b3e(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,PZ(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,P3e(o,d),x3e(d),I=k;return}}function D3e(o){return o=o|0,536870911}function b3e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function P3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function x3e(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function xZ(o){o=o|0,R3e(o)}function k3e(o){o=o|0,Q3e(o+24|0)}function Q3e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function R3e(o){o=o|0;var l=0;l=tn()|0,rn(o,1,1,l,T3e()|0,5),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function T3e(){return 1872}function F3e(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,O3e(n[(N3e(o)|0)>>2]|0,l,u,A,d,m)}function N3e(o){return o=o|0,(n[(HM()|0)+24>>2]|0)+(o<<3)|0}function O3e(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0;var B=0,k=0,R=0,M=0,L=0,q=0;B=I,I=I+32|0,k=B+16|0,R=B+12|0,M=B+8|0,L=B+4|0,q=B,Oh(k,l),l=Lh(k,l)|0,Oh(R,u),u=Lh(R,u)|0,Oh(M,A),A=Lh(M,A)|0,Oh(L,d),d=Lh(L,d)|0,Oh(q,m),m=Lh(q,m)|0,ZZ[o&1](l,u,A,d,m),Mh(q),Mh(L),Mh(M),Mh(R),Mh(k),I=B}function L3e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;m=n[o>>2]|0,d=jM()|0,o=M3e(u)|0,Dn(m,l,d,o,U3e(u,A)|0,A)}function jM(){var o=0,l=0;if(s[8072]|0||(QZ(11004),gr(69,11004,U|0)|0,l=8072,n[l>>2]=1,n[l+4>>2]=0),!(_r(11004)|0)){o=11004,l=o+36|0;do n[o>>2]=0,o=o+4|0;while((o|0)<(l|0));QZ(11004)}return 11004}function M3e(o){return o=o|0,o|0}function U3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0,k=0,R=0;return k=I,I=I+16|0,d=k,m=k+4|0,n[d>>2]=o,R=jM()|0,B=R+24|0,l=yr(l,4)|0,n[m>>2]=l,u=R+28|0,A=n[u>>2]|0,A>>>0<(n[R+32>>2]|0)>>>0?(kZ(A,o,l),l=(n[u>>2]|0)+8|0,n[u>>2]=l):(_3e(B,d,m),l=n[u>>2]|0),I=k,(l-(n[B>>2]|0)>>3)+-1|0}function kZ(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,n[o+4>>2]=u}function _3e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0;if(k=I,I=I+32|0,d=k,m=o+4|0,B=((n[m>>2]|0)-(n[o>>2]|0)>>3)+1|0,A=H3e(o)|0,A>>>0<B>>>0)an(o);else{R=n[o>>2]|0,L=(n[o+8>>2]|0)-R|0,M=L>>2,j3e(d,L>>3>>>0<A>>>1>>>0?M>>>0<B>>>0?B:M:A,(n[m>>2]|0)-R>>3,o+8|0),B=d+8|0,kZ(n[B>>2]|0,n[l>>2]|0,n[u>>2]|0),n[B>>2]=(n[B>>2]|0)+8,G3e(o,d),q3e(d),I=k;return}}function H3e(o){return o=o|0,536870911}function j3e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0;n[o+12>>2]=0,n[o+16>>2]=A;do if(l)if(l>>>0>536870911)Nt();else{d=Jt(l<<3)|0;break}else d=0;while(!1);n[o>>2]=d,A=d+(u<<3)|0,n[o+8>>2]=A,n[o+4>>2]=A,n[o+12>>2]=d+(l<<3)}function G3e(o,l){o=o|0,l=l|0;var u=0,A=0,d=0,m=0,B=0;A=n[o>>2]|0,B=o+4|0,m=l+4|0,d=(n[B>>2]|0)-A|0,u=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=u,(d|0)>0?(Qr(u|0,A|0,d|0)|0,A=m,u=n[m>>2]|0):A=m,m=n[o>>2]|0,n[o>>2]=u,n[A>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=o+8|0,B=l+12|0,o=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=o,n[l>>2]=n[A>>2]}function q3e(o){o=o|0;var l=0,u=0,A=0;l=n[o+4>>2]|0,u=o+8|0,A=n[u>>2]|0,(A|0)!=(l|0)&&(n[u>>2]=A+(~((A+-8-l|0)>>>3)<<3)),o=n[o>>2]|0,o|0&&It(o)}function QZ(o){o=o|0,Y3e(o)}function W3e(o){o=o|0,V3e(o+24|0)}function V3e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function Y3e(o){o=o|0;var l=0;l=tn()|0,rn(o,1,12,l,K3e()|0,2),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function K3e(){return 1896}function J3e(o,l,u){o=o|0,l=l|0,u=u|0,Z3e(n[(z3e(o)|0)>>2]|0,l,u)}function z3e(o){return o=o|0,(n[(jM()|0)+24>>2]|0)+(o<<3)|0}function Z3e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;A=I,I=I+16|0,m=A+4|0,d=A,X3e(m,l),l=$3e(m,l)|0,Oh(d,u),u=Lh(d,u)|0,op[o&31](l,u),Mh(d),I=A}function X3e(o,l){o=o|0,l=l|0}function $3e(o,l){return o=o|0,l=l|0,e8e(l)|0}function e8e(o){return o=o|0,o|0}function t8e(){var o=0;return s[8080]|0||(RZ(11040),gr(70,11040,U|0)|0,o=8080,n[o>>2]=1,n[o+4>>2]=0),_r(11040)|0||RZ(11040),11040}function RZ(o){o=o|0,i8e(o),ld(o,71)}function r8e(o){o=o|0,n8e(o+24|0)}function n8e(o){o=o|0;var l=0,u=0,A=0;u=n[o>>2]|0,A=u,u|0&&(o=o+4|0,l=n[o>>2]|0,(l|0)!=(u|0)&&(n[o>>2]=l+(~((l+-8-A|0)>>>3)<<3)),It(u))}function i8e(o){o=o|0;var l=0;l=tn()|0,rn(o,5,7,l,l8e()|0,0),n[o+24>>2]=0,n[o+28>>2]=0,n[o+32>>2]=0}function s8e(o){o=o|0,o8e(o)}function o8e(o){o=o|0,a8e(o)}function a8e(o){o=o|0,s[o+8>>0]=1}function l8e(){return 1936}function c8e(){return u8e()|0}function u8e(){var o=0,l=0,u=0,A=0,d=0,m=0,B=0;return l=I,I=I+16|0,d=l+4|0,B=l,u=Ul(8)|0,o=u,m=o+4|0,n[m>>2]=Jt(1)|0,A=Jt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],f8e(A,m,d),n[u>>2]=A,I=l,o|0}function f8e(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]=l,u=Jt(16)|0,n[u+4>>2]=0,n[u+8>>2]=0,n[u>>2]=1916,n[u+12>>2]=l,n[o+4>>2]=u}function A8e(o){o=o|0,rE(o),It(o)}function p8e(o){o=o|0,o=n[o+12>>2]|0,o|0&&It(o)}function h8e(o){o=o|0,It(o)}function g8e(){var o=0;return s[8088]|0||(w8e(11076),gr(25,11076,U|0)|0,o=8088,n[o>>2]=1,n[o+4>>2]=0),11076}function d8e(o,l){o=o|0,l=l|0,n[o>>2]=m8e()|0,n[o+4>>2]=y8e()|0,n[o+12>>2]=l,n[o+8>>2]=E8e()|0,n[o+32>>2]=10}function m8e(){return 11745}function y8e(){return 1940}function E8e(){return FP()|0}function I8e(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,(Uh(A,896)|0)==512?u|0&&(C8e(u),It(u)):l|0&&It(l)}function C8e(o){o=o|0,o=n[o+4>>2]|0,o|0&&Hh(o)}function w8e(o){o=o|0,Nh(o)}function Su(o,l){o=o|0,l=l|0,n[o>>2]=l}function GM(o){return o=o|0,n[o>>2]|0}function B8e(o){return o=o|0,s[n[o>>2]>>0]|0}function v8e(o,l){o=o|0,l=l|0;var u=0,A=0;u=I,I=I+16|0,A=u,n[A>>2]=n[o>>2],S8e(l,A)|0,I=u}function S8e(o,l){o=o|0,l=l|0;var u=0;return u=D8e(n[o>>2]|0,l)|0,l=o+4|0,n[(n[l>>2]|0)+8>>2]=u,n[(n[l>>2]|0)+8>>2]|0}function D8e(o,l){o=o|0,l=l|0;var u=0,A=0;return u=I,I=I+16|0,A=u,_l(A),o=Us(o)|0,l=b8e(o,n[l>>2]|0)|0,Hl(A),I=u,l|0}function _l(o){o=o|0,n[o>>2]=n[2701],n[o+4>>2]=n[2703]}function b8e(o,l){o=o|0,l=l|0;var u=0;return u=Ia(P8e()|0)|0,mn(0,u|0,o|0,OM(l)|0)|0}function Hl(o){o=o|0,CZ(n[o>>2]|0,n[o+4>>2]|0)}function P8e(){var o=0;return s[8096]|0||(x8e(11120),o=8096,n[o>>2]=1,n[o+4>>2]=0),11120}function x8e(o){o=o|0,Oo(o,k8e()|0,1)}function k8e(){return 1948}function Q8e(){R8e()}function R8e(){var o=0,l=0,u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0;if(Le=I,I=I+16|0,L=Le+4|0,q=Le,ua(65536,10804,n[2702]|0,10812),u=rZ()|0,l=n[u>>2]|0,o=n[l>>2]|0,o|0)for(A=n[u+8>>2]|0,u=n[u+4>>2]|0;gf(o|0,c[u>>0]|0|0,s[A>>0]|0),l=l+4|0,o=n[l>>2]|0,o;)A=A+1|0,u=u+1|0;if(o=nZ()|0,l=n[o>>2]|0,l|0)do OA(l|0,n[o+4>>2]|0),o=o+8|0,l=n[o>>2]|0;while(l|0);OA(T8e()|0,5167),M=Zy()|0,o=n[M>>2]|0;e:do if(o|0){do F8e(n[o+4>>2]|0),o=n[o>>2]|0;while(o|0);if(o=n[M>>2]|0,o|0){R=M;do{for(;d=o,o=n[o>>2]|0,d=n[d+4>>2]|0,!!(N8e(d)|0);)if(n[q>>2]=R,n[L>>2]=n[q>>2],O8e(M,L)|0,!o)break e;if(L8e(d),R=n[R>>2]|0,l=TZ(d)|0,m=Oi()|0,B=I,I=I+((1*(l<<2)|0)+15&-16)|0,k=I,I=I+((1*(l<<2)|0)+15&-16)|0,l=n[(gZ(d)|0)>>2]|0,l|0)for(u=B,A=k;n[u>>2]=n[(Xy(n[l+4>>2]|0)|0)>>2],n[A>>2]=n[l+8>>2],l=n[l>>2]|0,l;)u=u+4|0,A=A+4|0;Te=Xy(d)|0,l=M8e(d)|0,u=TZ(d)|0,A=U8e(d)|0,ac(Te|0,l|0,B|0,k|0,u|0,A|0,kM(d)|0),NA(m|0)}while(o|0)}}while(!1);if(o=n[(QM()|0)>>2]|0,o|0)do Te=o+4|0,M=RM(Te)|0,d=wB(M)|0,m=IB(M)|0,B=(CB(M)|0)+1|0,k=UP(M)|0,R=FZ(Te)|0,M=_r(M)|0,L=OP(Te)|0,q=qM(Te)|0,lu(0,d|0,m|0,B|0,k|0,R|0,M|0,L|0,q|0,WM(Te)|0),o=n[o>>2]|0;while(o|0);o=n[(Zy()|0)>>2]|0;e:do if(o|0){t:for(;;){if(l=n[o+4>>2]|0,l|0&&(oe=n[(Xy(l)|0)>>2]|0,Ye=n[(dZ(l)|0)>>2]|0,Ye|0)){u=Ye;do{l=u+4|0,A=RM(l)|0;r:do if(A|0)switch(_r(A)|0){case 0:break t;case 4:case 3:case 2:{k=wB(A)|0,R=IB(A)|0,M=(CB(A)|0)+1|0,L=UP(A)|0,q=_r(A)|0,Te=OP(l)|0,lu(oe|0,k|0,R|0,M|0,L|0,0,q|0,Te|0,qM(l)|0,WM(l)|0);break r}case 1:{B=wB(A)|0,k=IB(A)|0,R=(CB(A)|0)+1|0,M=UP(A)|0,L=FZ(l)|0,q=_r(A)|0,Te=OP(l)|0,lu(oe|0,B|0,k|0,R|0,M|0,L|0,q|0,Te|0,qM(l)|0,WM(l)|0);break r}case 5:{M=wB(A)|0,L=IB(A)|0,q=(CB(A)|0)+1|0,Te=UP(A)|0,lu(oe|0,M|0,L|0,q|0,Te|0,_8e(A)|0,_r(A)|0,0,0,0);break r}default:break r}while(!1);u=n[u>>2]|0}while(u|0)}if(o=n[o>>2]|0,!o)break e}Nt()}while(!1);we(),I=Le}function T8e(){return 11703}function F8e(o){o=o|0,s[o+40>>0]=0}function N8e(o){return o=o|0,(s[o+40>>0]|0)!=0|0}function O8e(o,l){return o=o|0,l=l|0,l=H8e(l)|0,o=n[l>>2]|0,n[l>>2]=n[o>>2],It(o),n[l>>2]|0}function L8e(o){o=o|0,s[o+40>>0]=1}function TZ(o){return o=o|0,n[o+20>>2]|0}function M8e(o){return o=o|0,n[o+8>>2]|0}function U8e(o){return o=o|0,n[o+32>>2]|0}function UP(o){return o=o|0,n[o+4>>2]|0}function FZ(o){return o=o|0,n[o+4>>2]|0}function qM(o){return o=o|0,n[o+8>>2]|0}function WM(o){return o=o|0,n[o+16>>2]|0}function _8e(o){return o=o|0,n[o+20>>2]|0}function H8e(o){return o=o|0,n[o>>2]|0}function _P(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0,nt=0,Xe=0,ft=0,He=0,Ve=0,Lt=0;Lt=I,I=I+16|0,oe=Lt;do if(o>>>0<245){if(M=o>>>0<11?16:o+11&-8,o=M>>>3,q=n[2783]|0,u=q>>>o,u&3|0)return l=(u&1^1)+o|0,o=11172+(l<<1<<2)|0,u=o+8|0,A=n[u>>2]|0,d=A+8|0,m=n[d>>2]|0,(o|0)==(m|0)?n[2783]=q&~(1<<l):(n[m+12>>2]=o,n[u>>2]=m),Ve=l<<3,n[A+4>>2]=Ve|3,Ve=A+Ve+4|0,n[Ve>>2]=n[Ve>>2]|1,Ve=d,I=Lt,Ve|0;if(L=n[2785]|0,M>>>0>L>>>0){if(u|0)return l=2<<o,l=u<<o&(l|0-l),l=(l&0-l)+-1|0,B=l>>>12&16,l=l>>>B,u=l>>>5&8,l=l>>>u,d=l>>>2&4,l=l>>>d,o=l>>>1&2,l=l>>>o,A=l>>>1&1,A=(u|B|d|o|A)+(l>>>A)|0,l=11172+(A<<1<<2)|0,o=l+8|0,d=n[o>>2]|0,B=d+8|0,u=n[B>>2]|0,(l|0)==(u|0)?(o=q&~(1<<A),n[2783]=o):(n[u+12>>2]=l,n[o>>2]=u,o=q),m=(A<<3)-M|0,n[d+4>>2]=M|3,A=d+M|0,n[A+4>>2]=m|1,n[A+m>>2]=m,L|0&&(d=n[2788]|0,l=L>>>3,u=11172+(l<<1<<2)|0,l=1<<l,o&l?(o=u+8|0,l=n[o>>2]|0):(n[2783]=o|l,l=u,o=u+8|0),n[o>>2]=d,n[l+12>>2]=d,n[d+8>>2]=l,n[d+12>>2]=u),n[2785]=m,n[2788]=A,Ve=B,I=Lt,Ve|0;if(k=n[2784]|0,k){if(u=(k&0-k)+-1|0,B=u>>>12&16,u=u>>>B,m=u>>>5&8,u=u>>>m,R=u>>>2&4,u=u>>>R,A=u>>>1&2,u=u>>>A,o=u>>>1&1,o=n[11436+((m|B|R|A|o)+(u>>>o)<<2)>>2]|0,u=(n[o+4>>2]&-8)-M|0,A=n[o+16+(((n[o+16>>2]|0)==0&1)<<2)>>2]|0,!A)R=o,m=u;else{do B=(n[A+4>>2]&-8)-M|0,R=B>>>0<u>>>0,u=R?B:u,o=R?A:o,A=n[A+16+(((n[A+16>>2]|0)==0&1)<<2)>>2]|0;while(A|0);R=o,m=u}if(B=R+M|0,R>>>0<B>>>0){d=n[R+24>>2]|0,l=n[R+12>>2]|0;do if((l|0)==(R|0)){if(o=R+20|0,l=n[o>>2]|0,!l&&(o=R+16|0,l=n[o>>2]|0,!l)){u=0;break}for(;;){if(u=l+20|0,A=n[u>>2]|0,A|0){l=A,o=u;continue}if(u=l+16|0,A=n[u>>2]|0,A)l=A,o=u;else break}n[o>>2]=0,u=l}else u=n[R+8>>2]|0,n[u+12>>2]=l,n[l+8>>2]=u,u=l;while(!1);do if(d|0){if(l=n[R+28>>2]|0,o=11436+(l<<2)|0,(R|0)==(n[o>>2]|0)){if(n[o>>2]=u,!u){n[2784]=k&~(1<<l);break}}else if(n[d+16+(((n[d+16>>2]|0)!=(R|0)&1)<<2)>>2]=u,!u)break;n[u+24>>2]=d,l=n[R+16>>2]|0,l|0&&(n[u+16>>2]=l,n[l+24>>2]=u),l=n[R+20>>2]|0,l|0&&(n[u+20>>2]=l,n[l+24>>2]=u)}while(!1);return m>>>0<16?(Ve=m+M|0,n[R+4>>2]=Ve|3,Ve=R+Ve+4|0,n[Ve>>2]=n[Ve>>2]|1):(n[R+4>>2]=M|3,n[B+4>>2]=m|1,n[B+m>>2]=m,L|0&&(A=n[2788]|0,l=L>>>3,u=11172+(l<<1<<2)|0,l=1<<l,q&l?(o=u+8|0,l=n[o>>2]|0):(n[2783]=q|l,l=u,o=u+8|0),n[o>>2]=A,n[l+12>>2]=A,n[A+8>>2]=l,n[A+12>>2]=u),n[2785]=m,n[2788]=B),Ve=R+8|0,I=Lt,Ve|0}else q=M}else q=M}else q=M}else if(o>>>0<=4294967231)if(o=o+11|0,M=o&-8,R=n[2784]|0,R){A=0-M|0,o=o>>>8,o?M>>>0>16777215?k=31:(q=(o+1048320|0)>>>16&8,He=o<<q,L=(He+520192|0)>>>16&4,He=He<<L,k=(He+245760|0)>>>16&2,k=14-(L|q|k)+(He<<k>>>15)|0,k=M>>>(k+7|0)&1|k<<1):k=0,u=n[11436+(k<<2)>>2]|0;e:do if(!u)u=0,o=0,He=57;else for(o=0,B=M<<((k|0)==31?0:25-(k>>>1)|0),m=0;;){if(d=(n[u+4>>2]&-8)-M|0,d>>>0<A>>>0)if(d)o=u,A=d;else{o=u,A=0,d=u,He=61;break e}if(d=n[u+20>>2]|0,u=n[u+16+(B>>>31<<2)>>2]|0,m=(d|0)==0|(d|0)==(u|0)?m:d,d=(u|0)==0,d){u=m,He=57;break}else B=B<<((d^1)&1)}while(!1);if((He|0)==57){if((u|0)==0&(o|0)==0){if(o=2<<k,o=R&(o|0-o),!o){q=M;break}q=(o&0-o)+-1|0,B=q>>>12&16,q=q>>>B,m=q>>>5&8,q=q>>>m,k=q>>>2&4,q=q>>>k,L=q>>>1&2,q=q>>>L,u=q>>>1&1,o=0,u=n[11436+((m|B|k|L|u)+(q>>>u)<<2)>>2]|0}u?(d=u,He=61):(k=o,B=A)}if((He|0)==61)for(;;)if(He=0,u=(n[d+4>>2]&-8)-M|0,q=u>>>0<A>>>0,u=q?u:A,o=q?d:o,d=n[d+16+(((n[d+16>>2]|0)==0&1)<<2)>>2]|0,d)A=u,He=61;else{k=o,B=u;break}if(k|0&&B>>>0<((n[2785]|0)-M|0)>>>0){if(m=k+M|0,k>>>0>=m>>>0)return Ve=0,I=Lt,Ve|0;d=n[k+24>>2]|0,l=n[k+12>>2]|0;do if((l|0)==(k|0)){if(o=k+20|0,l=n[o>>2]|0,!l&&(o=k+16|0,l=n[o>>2]|0,!l)){l=0;break}for(;;){if(u=l+20|0,A=n[u>>2]|0,A|0){l=A,o=u;continue}if(u=l+16|0,A=n[u>>2]|0,A)l=A,o=u;else break}n[o>>2]=0}else Ve=n[k+8>>2]|0,n[Ve+12>>2]=l,n[l+8>>2]=Ve;while(!1);do if(d){if(o=n[k+28>>2]|0,u=11436+(o<<2)|0,(k|0)==(n[u>>2]|0)){if(n[u>>2]=l,!l){A=R&~(1<<o),n[2784]=A;break}}else if(n[d+16+(((n[d+16>>2]|0)!=(k|0)&1)<<2)>>2]=l,!l){A=R;break}n[l+24>>2]=d,o=n[k+16>>2]|0,o|0&&(n[l+16>>2]=o,n[o+24>>2]=l),o=n[k+20>>2]|0,o&&(n[l+20>>2]=o,n[o+24>>2]=l),A=R}else A=R;while(!1);do if(B>>>0>=16){if(n[k+4>>2]=M|3,n[m+4>>2]=B|1,n[m+B>>2]=B,l=B>>>3,B>>>0<256){u=11172+(l<<1<<2)|0,o=n[2783]|0,l=1<<l,o&l?(o=u+8|0,l=n[o>>2]|0):(n[2783]=o|l,l=u,o=u+8|0),n[o>>2]=m,n[l+12>>2]=m,n[m+8>>2]=l,n[m+12>>2]=u;break}if(l=B>>>8,l?B>>>0>16777215?l=31:(He=(l+1048320|0)>>>16&8,Ve=l<<He,ft=(Ve+520192|0)>>>16&4,Ve=Ve<<ft,l=(Ve+245760|0)>>>16&2,l=14-(ft|He|l)+(Ve<<l>>>15)|0,l=B>>>(l+7|0)&1|l<<1):l=0,u=11436+(l<<2)|0,n[m+28>>2]=l,o=m+16|0,n[o+4>>2]=0,n[o>>2]=0,o=1<<l,!(A&o)){n[2784]=A|o,n[u>>2]=m,n[m+24>>2]=u,n[m+12>>2]=m,n[m+8>>2]=m;break}for(o=B<<((l|0)==31?0:25-(l>>>1)|0),u=n[u>>2]|0;;){if((n[u+4>>2]&-8|0)==(B|0)){He=97;break}if(A=u+16+(o>>>31<<2)|0,l=n[A>>2]|0,l)o=o<<1,u=l;else{He=96;break}}if((He|0)==96){n[A>>2]=m,n[m+24>>2]=u,n[m+12>>2]=m,n[m+8>>2]=m;break}else if((He|0)==97){He=u+8|0,Ve=n[He>>2]|0,n[Ve+12>>2]=m,n[He>>2]=m,n[m+8>>2]=Ve,n[m+12>>2]=u,n[m+24>>2]=0;break}}else Ve=B+M|0,n[k+4>>2]=Ve|3,Ve=k+Ve+4|0,n[Ve>>2]=n[Ve>>2]|1;while(!1);return Ve=k+8|0,I=Lt,Ve|0}else q=M}else q=M;else q=-1;while(!1);if(u=n[2785]|0,u>>>0>=q>>>0)return l=u-q|0,o=n[2788]|0,l>>>0>15?(Ve=o+q|0,n[2788]=Ve,n[2785]=l,n[Ve+4>>2]=l|1,n[Ve+l>>2]=l,n[o+4>>2]=q|3):(n[2785]=0,n[2788]=0,n[o+4>>2]=u|3,Ve=o+u+4|0,n[Ve>>2]=n[Ve>>2]|1),Ve=o+8|0,I=Lt,Ve|0;if(B=n[2786]|0,B>>>0>q>>>0)return ft=B-q|0,n[2786]=ft,Ve=n[2789]|0,He=Ve+q|0,n[2789]=He,n[He+4>>2]=ft|1,n[Ve+4>>2]=q|3,Ve=Ve+8|0,I=Lt,Ve|0;if(n[2901]|0?o=n[2903]|0:(n[2903]=4096,n[2902]=4096,n[2904]=-1,n[2905]=-1,n[2906]=0,n[2894]=0,o=oe&-16^1431655768,n[oe>>2]=o,n[2901]=o,o=4096),k=q+48|0,R=q+47|0,m=o+R|0,d=0-o|0,M=m&d,M>>>0<=q>>>0||(o=n[2893]|0,o|0&&(L=n[2891]|0,oe=L+M|0,oe>>>0<=L>>>0|oe>>>0>o>>>0)))return Ve=0,I=Lt,Ve|0;e:do if(n[2894]&4)l=0,He=133;else{u=n[2789]|0;t:do if(u){for(A=11580;o=n[A>>2]|0,!(o>>>0<=u>>>0&&(Te=A+4|0,(o+(n[Te>>2]|0)|0)>>>0>u>>>0));)if(o=n[A+8>>2]|0,o)A=o;else{He=118;break t}if(l=m-B&d,l>>>0<2147483647)if(o=jh(l|0)|0,(o|0)==((n[A>>2]|0)+(n[Te>>2]|0)|0)){if((o|0)!=-1){B=l,m=o,He=135;break e}}else A=o,He=126;else l=0}else He=118;while(!1);do if((He|0)==118)if(u=jh(0)|0,(u|0)!=-1&&(l=u,Ye=n[2902]|0,Le=Ye+-1|0,l=(Le&l|0?(Le+l&0-Ye)-l|0:0)+M|0,Ye=n[2891]|0,Le=l+Ye|0,l>>>0>q>>>0&l>>>0<2147483647)){if(Te=n[2893]|0,Te|0&&Le>>>0<=Ye>>>0|Le>>>0>Te>>>0){l=0;break}if(o=jh(l|0)|0,(o|0)==(u|0)){B=l,m=u,He=135;break e}else A=o,He=126}else l=0;while(!1);do if((He|0)==126){if(u=0-l|0,!(k>>>0>l>>>0&(l>>>0<2147483647&(A|0)!=-1)))if((A|0)==-1){l=0;break}else{B=l,m=A,He=135;break e}if(o=n[2903]|0,o=R-l+o&0-o,o>>>0>=2147483647){B=l,m=A,He=135;break e}if((jh(o|0)|0)==-1){jh(u|0)|0,l=0;break}else{B=o+l|0,m=A,He=135;break e}}while(!1);n[2894]=n[2894]|4,He=133}while(!1);if((He|0)==133&&M>>>0<2147483647&&(ft=jh(M|0)|0,Te=jh(0)|0,nt=Te-ft|0,Xe=nt>>>0>(q+40|0)>>>0,!((ft|0)==-1|Xe^1|ft>>>0<Te>>>0&((ft|0)!=-1&(Te|0)!=-1)^1))&&(B=Xe?nt:l,m=ft,He=135),(He|0)==135){l=(n[2891]|0)+B|0,n[2891]=l,l>>>0>(n[2892]|0)>>>0&&(n[2892]=l),R=n[2789]|0;do if(R){for(l=11580;;){if(o=n[l>>2]|0,u=l+4|0,A=n[u>>2]|0,(m|0)==(o+A|0)){He=145;break}if(d=n[l+8>>2]|0,d)l=d;else break}if((He|0)==145&&!(n[l+12>>2]&8|0)&&R>>>0<m>>>0&R>>>0>=o>>>0){n[u>>2]=A+B,Ve=R+8|0,Ve=Ve&7|0?0-Ve&7:0,He=R+Ve|0,Ve=(n[2786]|0)+(B-Ve)|0,n[2789]=He,n[2786]=Ve,n[He+4>>2]=Ve|1,n[He+Ve+4>>2]=40,n[2790]=n[2905];break}for(m>>>0<(n[2787]|0)>>>0&&(n[2787]=m),u=m+B|0,l=11580;;){if((n[l>>2]|0)==(u|0)){He=153;break}if(o=n[l+8>>2]|0,o)l=o;else break}if((He|0)==153&&!(n[l+12>>2]&8|0)){n[l>>2]=m,L=l+4|0,n[L>>2]=(n[L>>2]|0)+B,L=m+8|0,L=m+(L&7|0?0-L&7:0)|0,l=u+8|0,l=u+(l&7|0?0-l&7:0)|0,M=L+q|0,k=l-L-q|0,n[L+4>>2]=q|3;do if((l|0)!=(R|0)){if((l|0)==(n[2788]|0)){Ve=(n[2785]|0)+k|0,n[2785]=Ve,n[2788]=M,n[M+4>>2]=Ve|1,n[M+Ve>>2]=Ve;break}if(o=n[l+4>>2]|0,(o&3|0)==1){B=o&-8,A=o>>>3;e:do if(o>>>0<256)if(o=n[l+8>>2]|0,u=n[l+12>>2]|0,(u|0)==(o|0)){n[2783]=n[2783]&~(1<<A);break}else{n[o+12>>2]=u,n[u+8>>2]=o;break}else{m=n[l+24>>2]|0,o=n[l+12>>2]|0;do if((o|0)==(l|0)){if(A=l+16|0,u=A+4|0,o=n[u>>2]|0,!o)if(o=n[A>>2]|0,o)u=A;else{o=0;break}for(;;){if(A=o+20|0,d=n[A>>2]|0,d|0){o=d,u=A;continue}if(A=o+16|0,d=n[A>>2]|0,d)o=d,u=A;else break}n[u>>2]=0}else Ve=n[l+8>>2]|0,n[Ve+12>>2]=o,n[o+8>>2]=Ve;while(!1);if(!m)break;u=n[l+28>>2]|0,A=11436+(u<<2)|0;do if((l|0)!=(n[A>>2]|0)){if(n[m+16+(((n[m+16>>2]|0)!=(l|0)&1)<<2)>>2]=o,!o)break e}else{if(n[A>>2]=o,o|0)break;n[2784]=n[2784]&~(1<<u);break e}while(!1);if(n[o+24>>2]=m,u=l+16|0,A=n[u>>2]|0,A|0&&(n[o+16>>2]=A,n[A+24>>2]=o),u=n[u+4>>2]|0,!u)break;n[o+20>>2]=u,n[u+24>>2]=o}while(!1);l=l+B|0,d=B+k|0}else d=k;if(l=l+4|0,n[l>>2]=n[l>>2]&-2,n[M+4>>2]=d|1,n[M+d>>2]=d,l=d>>>3,d>>>0<256){u=11172+(l<<1<<2)|0,o=n[2783]|0,l=1<<l,o&l?(o=u+8|0,l=n[o>>2]|0):(n[2783]=o|l,l=u,o=u+8|0),n[o>>2]=M,n[l+12>>2]=M,n[M+8>>2]=l,n[M+12>>2]=u;break}l=d>>>8;do if(!l)l=0;else{if(d>>>0>16777215){l=31;break}He=(l+1048320|0)>>>16&8,Ve=l<<He,ft=(Ve+520192|0)>>>16&4,Ve=Ve<<ft,l=(Ve+245760|0)>>>16&2,l=14-(ft|He|l)+(Ve<<l>>>15)|0,l=d>>>(l+7|0)&1|l<<1}while(!1);if(A=11436+(l<<2)|0,n[M+28>>2]=l,o=M+16|0,n[o+4>>2]=0,n[o>>2]=0,o=n[2784]|0,u=1<<l,!(o&u)){n[2784]=o|u,n[A>>2]=M,n[M+24>>2]=A,n[M+12>>2]=M,n[M+8>>2]=M;break}for(o=d<<((l|0)==31?0:25-(l>>>1)|0),u=n[A>>2]|0;;){if((n[u+4>>2]&-8|0)==(d|0)){He=194;break}if(A=u+16+(o>>>31<<2)|0,l=n[A>>2]|0,l)o=o<<1,u=l;else{He=193;break}}if((He|0)==193){n[A>>2]=M,n[M+24>>2]=u,n[M+12>>2]=M,n[M+8>>2]=M;break}else if((He|0)==194){He=u+8|0,Ve=n[He>>2]|0,n[Ve+12>>2]=M,n[He>>2]=M,n[M+8>>2]=Ve,n[M+12>>2]=u,n[M+24>>2]=0;break}}else Ve=(n[2786]|0)+k|0,n[2786]=Ve,n[2789]=M,n[M+4>>2]=Ve|1;while(!1);return Ve=L+8|0,I=Lt,Ve|0}for(l=11580;o=n[l>>2]|0,!(o>>>0<=R>>>0&&(Ve=o+(n[l+4>>2]|0)|0,Ve>>>0>R>>>0));)l=n[l+8>>2]|0;d=Ve+-47|0,o=d+8|0,o=d+(o&7|0?0-o&7:0)|0,d=R+16|0,o=o>>>0<d>>>0?R:o,l=o+8|0,u=m+8|0,u=u&7|0?0-u&7:0,He=m+u|0,u=B+-40-u|0,n[2789]=He,n[2786]=u,n[He+4>>2]=u|1,n[He+u+4>>2]=40,n[2790]=n[2905],u=o+4|0,n[u>>2]=27,n[l>>2]=n[2895],n[l+4>>2]=n[2896],n[l+8>>2]=n[2897],n[l+12>>2]=n[2898],n[2895]=m,n[2896]=B,n[2898]=0,n[2897]=l,l=o+24|0;do He=l,l=l+4|0,n[l>>2]=7;while((He+8|0)>>>0<Ve>>>0);if((o|0)!=(R|0)){if(m=o-R|0,n[u>>2]=n[u>>2]&-2,n[R+4>>2]=m|1,n[o>>2]=m,l=m>>>3,m>>>0<256){u=11172+(l<<1<<2)|0,o=n[2783]|0,l=1<<l,o&l?(o=u+8|0,l=n[o>>2]|0):(n[2783]=o|l,l=u,o=u+8|0),n[o>>2]=R,n[l+12>>2]=R,n[R+8>>2]=l,n[R+12>>2]=u;break}if(l=m>>>8,l?m>>>0>16777215?u=31:(He=(l+1048320|0)>>>16&8,Ve=l<<He,ft=(Ve+520192|0)>>>16&4,Ve=Ve<<ft,u=(Ve+245760|0)>>>16&2,u=14-(ft|He|u)+(Ve<<u>>>15)|0,u=m>>>(u+7|0)&1|u<<1):u=0,A=11436+(u<<2)|0,n[R+28>>2]=u,n[R+20>>2]=0,n[d>>2]=0,l=n[2784]|0,o=1<<u,!(l&o)){n[2784]=l|o,n[A>>2]=R,n[R+24>>2]=A,n[R+12>>2]=R,n[R+8>>2]=R;break}for(o=m<<((u|0)==31?0:25-(u>>>1)|0),u=n[A>>2]|0;;){if((n[u+4>>2]&-8|0)==(m|0)){He=216;break}if(A=u+16+(o>>>31<<2)|0,l=n[A>>2]|0,l)o=o<<1,u=l;else{He=215;break}}if((He|0)==215){n[A>>2]=R,n[R+24>>2]=u,n[R+12>>2]=R,n[R+8>>2]=R;break}else if((He|0)==216){He=u+8|0,Ve=n[He>>2]|0,n[Ve+12>>2]=R,n[He>>2]=R,n[R+8>>2]=Ve,n[R+12>>2]=u,n[R+24>>2]=0;break}}}else{Ve=n[2787]|0,(Ve|0)==0|m>>>0<Ve>>>0&&(n[2787]=m),n[2895]=m,n[2896]=B,n[2898]=0,n[2792]=n[2901],n[2791]=-1,l=0;do Ve=11172+(l<<1<<2)|0,n[Ve+12>>2]=Ve,n[Ve+8>>2]=Ve,l=l+1|0;while((l|0)!=32);Ve=m+8|0,Ve=Ve&7|0?0-Ve&7:0,He=m+Ve|0,Ve=B+-40-Ve|0,n[2789]=He,n[2786]=Ve,n[He+4>>2]=Ve|1,n[He+Ve+4>>2]=40,n[2790]=n[2905]}while(!1);if(l=n[2786]|0,l>>>0>q>>>0)return ft=l-q|0,n[2786]=ft,Ve=n[2789]|0,He=Ve+q|0,n[2789]=He,n[He+4>>2]=ft|1,n[Ve+4>>2]=q|3,Ve=Ve+8|0,I=Lt,Ve|0}return n[(eE()|0)>>2]=12,Ve=0,I=Lt,Ve|0}function HP(o){o=o|0;var l=0,u=0,A=0,d=0,m=0,B=0,k=0,R=0;if(o){u=o+-8|0,d=n[2787]|0,o=n[o+-4>>2]|0,l=o&-8,R=u+l|0;do if(o&1)k=u,B=u;else{if(A=n[u>>2]|0,!(o&3)||(B=u+(0-A)|0,m=A+l|0,B>>>0<d>>>0))return;if((B|0)==(n[2788]|0)){if(o=R+4|0,l=n[o>>2]|0,(l&3|0)!=3){k=B,l=m;break}n[2785]=m,n[o>>2]=l&-2,n[B+4>>2]=m|1,n[B+m>>2]=m;return}if(u=A>>>3,A>>>0<256)if(o=n[B+8>>2]|0,l=n[B+12>>2]|0,(l|0)==(o|0)){n[2783]=n[2783]&~(1<<u),k=B,l=m;break}else{n[o+12>>2]=l,n[l+8>>2]=o,k=B,l=m;break}d=n[B+24>>2]|0,o=n[B+12>>2]|0;do if((o|0)==(B|0)){if(u=B+16|0,l=u+4|0,o=n[l>>2]|0,!o)if(o=n[u>>2]|0,o)l=u;else{o=0;break}for(;;){if(u=o+20|0,A=n[u>>2]|0,A|0){o=A,l=u;continue}if(u=o+16|0,A=n[u>>2]|0,A)o=A,l=u;else break}n[l>>2]=0}else k=n[B+8>>2]|0,n[k+12>>2]=o,n[o+8>>2]=k;while(!1);if(d){if(l=n[B+28>>2]|0,u=11436+(l<<2)|0,(B|0)==(n[u>>2]|0)){if(n[u>>2]=o,!o){n[2784]=n[2784]&~(1<<l),k=B,l=m;break}}else if(n[d+16+(((n[d+16>>2]|0)!=(B|0)&1)<<2)>>2]=o,!o){k=B,l=m;break}n[o+24>>2]=d,l=B+16|0,u=n[l>>2]|0,u|0&&(n[o+16>>2]=u,n[u+24>>2]=o),l=n[l+4>>2]|0,l?(n[o+20>>2]=l,n[l+24>>2]=o,k=B,l=m):(k=B,l=m)}else k=B,l=m}while(!1);if(!(B>>>0>=R>>>0)&&(o=R+4|0,A=n[o>>2]|0,!!(A&1))){if(A&2)n[o>>2]=A&-2,n[k+4>>2]=l|1,n[B+l>>2]=l,d=l;else{if(o=n[2788]|0,(R|0)==(n[2789]|0)){if(R=(n[2786]|0)+l|0,n[2786]=R,n[2789]=k,n[k+4>>2]=R|1,(k|0)!=(o|0))return;n[2788]=0,n[2785]=0;return}if((R|0)==(o|0)){R=(n[2785]|0)+l|0,n[2785]=R,n[2788]=B,n[k+4>>2]=R|1,n[B+R>>2]=R;return}d=(A&-8)+l|0,u=A>>>3;do if(A>>>0<256)if(l=n[R+8>>2]|0,o=n[R+12>>2]|0,(o|0)==(l|0)){n[2783]=n[2783]&~(1<<u);break}else{n[l+12>>2]=o,n[o+8>>2]=l;break}else{m=n[R+24>>2]|0,o=n[R+12>>2]|0;do if((o|0)==(R|0)){if(u=R+16|0,l=u+4|0,o=n[l>>2]|0,!o)if(o=n[u>>2]|0,o)l=u;else{u=0;break}for(;;){if(u=o+20|0,A=n[u>>2]|0,A|0){o=A,l=u;continue}if(u=o+16|0,A=n[u>>2]|0,A)o=A,l=u;else break}n[l>>2]=0,u=o}else u=n[R+8>>2]|0,n[u+12>>2]=o,n[o+8>>2]=u,u=o;while(!1);if(m|0){if(o=n[R+28>>2]|0,l=11436+(o<<2)|0,(R|0)==(n[l>>2]|0)){if(n[l>>2]=u,!u){n[2784]=n[2784]&~(1<<o);break}}else if(n[m+16+(((n[m+16>>2]|0)!=(R|0)&1)<<2)>>2]=u,!u)break;n[u+24>>2]=m,o=R+16|0,l=n[o>>2]|0,l|0&&(n[u+16>>2]=l,n[l+24>>2]=u),o=n[o+4>>2]|0,o|0&&(n[u+20>>2]=o,n[o+24>>2]=u)}}while(!1);if(n[k+4>>2]=d|1,n[B+d>>2]=d,(k|0)==(n[2788]|0)){n[2785]=d;return}}if(o=d>>>3,d>>>0<256){u=11172+(o<<1<<2)|0,l=n[2783]|0,o=1<<o,l&o?(l=u+8|0,o=n[l>>2]|0):(n[2783]=l|o,o=u,l=u+8|0),n[l>>2]=k,n[o+12>>2]=k,n[k+8>>2]=o,n[k+12>>2]=u;return}o=d>>>8,o?d>>>0>16777215?o=31:(B=(o+1048320|0)>>>16&8,R=o<<B,m=(R+520192|0)>>>16&4,R=R<<m,o=(R+245760|0)>>>16&2,o=14-(m|B|o)+(R<<o>>>15)|0,o=d>>>(o+7|0)&1|o<<1):o=0,A=11436+(o<<2)|0,n[k+28>>2]=o,n[k+20>>2]=0,n[k+16>>2]=0,l=n[2784]|0,u=1<<o;do if(l&u){for(l=d<<((o|0)==31?0:25-(o>>>1)|0),u=n[A>>2]|0;;){if((n[u+4>>2]&-8|0)==(d|0)){o=73;break}if(A=u+16+(l>>>31<<2)|0,o=n[A>>2]|0,o)l=l<<1,u=o;else{o=72;break}}if((o|0)==72){n[A>>2]=k,n[k+24>>2]=u,n[k+12>>2]=k,n[k+8>>2]=k;break}else if((o|0)==73){B=u+8|0,R=n[B>>2]|0,n[R+12>>2]=k,n[B>>2]=k,n[k+8>>2]=R,n[k+12>>2]=u,n[k+24>>2]=0;break}}else n[2784]=l|u,n[A>>2]=k,n[k+24>>2]=A,n[k+12>>2]=k,n[k+8>>2]=k;while(!1);if(R=(n[2791]|0)+-1|0,n[2791]=R,!R)o=11588;else return;for(;o=n[o>>2]|0,o;)o=o+8|0;n[2791]=-1}}}function j8e(){return 11628}function G8e(o){o=o|0;var l=0,u=0;return l=I,I=I+16|0,u=l,n[u>>2]=V8e(n[o+60>>2]|0)|0,o=jP(uu(6,u|0)|0)|0,I=l,o|0}function NZ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0;q=I,I=I+48|0,M=q+16|0,m=q,d=q+32|0,k=o+28|0,A=n[k>>2]|0,n[d>>2]=A,R=o+20|0,A=(n[R>>2]|0)-A|0,n[d+4>>2]=A,n[d+8>>2]=l,n[d+12>>2]=u,A=A+u|0,B=o+60|0,n[m>>2]=n[B>>2],n[m+4>>2]=d,n[m+8>>2]=2,m=jP(qa(146,m|0)|0)|0;e:do if((A|0)!=(m|0)){for(l=2;!((m|0)<0);)if(A=A-m|0,Ye=n[d+4>>2]|0,oe=m>>>0>Ye>>>0,d=oe?d+8|0:d,l=(oe<<31>>31)+l|0,Ye=m-(oe?Ye:0)|0,n[d>>2]=(n[d>>2]|0)+Ye,oe=d+4|0,n[oe>>2]=(n[oe>>2]|0)-Ye,n[M>>2]=n[B>>2],n[M+4>>2]=d,n[M+8>>2]=l,m=jP(qa(146,M|0)|0)|0,(A|0)==(m|0)){L=3;break e}n[o+16>>2]=0,n[k>>2]=0,n[R>>2]=0,n[o>>2]=n[o>>2]|32,(l|0)==2?u=0:u=u-(n[d+4>>2]|0)|0}else L=3;while(!1);return(L|0)==3&&(Ye=n[o+44>>2]|0,n[o+16>>2]=Ye+(n[o+48>>2]|0),n[k>>2]=Ye,n[R>>2]=Ye),I=q,u|0}function q8e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;return d=I,I=I+32|0,m=d,A=d+20|0,n[m>>2]=n[o+60>>2],n[m+4>>2]=0,n[m+8>>2]=l,n[m+12>>2]=A,n[m+16>>2]=u,(jP(Ga(140,m|0)|0)|0)<0?(n[A>>2]=-1,o=-1):o=n[A>>2]|0,I=d,o|0}function jP(o){return o=o|0,o>>>0>4294963200&&(n[(eE()|0)>>2]=0-o,o=-1),o|0}function eE(){return(W8e()|0)+64|0}function W8e(){return VM()|0}function VM(){return 2084}function V8e(o){return o=o|0,o|0}function Y8e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;return d=I,I=I+32|0,A=d,n[o+36>>2]=1,!(n[o>>2]&64|0)&&(n[A>>2]=n[o+60>>2],n[A+4>>2]=21523,n[A+8>>2]=d+16,co(54,A|0)|0)&&(s[o+75>>0]=-1),A=NZ(o,l,u)|0,I=d,A|0}function OZ(o,l){o=o|0,l=l|0;var u=0,A=0;if(u=s[o>>0]|0,A=s[l>>0]|0,!(u<<24>>24)||u<<24>>24!=A<<24>>24)o=A;else{do o=o+1|0,l=l+1|0,u=s[o>>0]|0,A=s[l>>0]|0;while(!(!(u<<24>>24)||u<<24>>24!=A<<24>>24));o=A}return(u&255)-(o&255)|0}function K8e(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0;e:do if(!u)o=0;else{for(;A=s[o>>0]|0,d=s[l>>0]|0,A<<24>>24==d<<24>>24;)if(u=u+-1|0,u)o=o+1|0,l=l+1|0;else{o=0;break e}o=(A&255)-(d&255)|0}while(!1);return o|0}function LZ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0;Te=I,I=I+224|0,L=Te+120|0,q=Te+80|0,Ye=Te,Le=Te+136|0,A=q,d=A+40|0;do n[A>>2]=0,A=A+4|0;while((A|0)<(d|0));return n[L>>2]=n[u>>2],(YM(0,l,L,Ye,q)|0)<0?u=-1:((n[o+76>>2]|0)>-1?oe=J8e(o)|0:oe=0,u=n[o>>2]|0,M=u&32,(s[o+74>>0]|0)<1&&(n[o>>2]=u&-33),A=o+48|0,n[A>>2]|0?u=YM(o,l,L,Ye,q)|0:(d=o+44|0,m=n[d>>2]|0,n[d>>2]=Le,B=o+28|0,n[B>>2]=Le,k=o+20|0,n[k>>2]=Le,n[A>>2]=80,R=o+16|0,n[R>>2]=Le+80,u=YM(o,l,L,Ye,q)|0,m&&(VP[n[o+36>>2]&7](o,0,0)|0,u=n[k>>2]|0?u:-1,n[d>>2]=m,n[A>>2]=0,n[R>>2]=0,n[B>>2]=0,n[k>>2]=0)),A=n[o>>2]|0,n[o>>2]=A|M,oe|0&&z8e(o),u=A&32|0?-1:u),I=Te,u|0}function YM(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0,nt=0,Xe=0,ft=0,He=0,Ve=0,Lt=0,Gr=0,fr=0,$t=0,Rr=0,Hr=0,cr=0;cr=I,I=I+64|0,fr=cr+16|0,$t=cr,Lt=cr+24|0,Rr=cr+8|0,Hr=cr+20|0,n[fr>>2]=l,ft=(o|0)!=0,He=Lt+40|0,Ve=He,Lt=Lt+39|0,Gr=Rr+4|0,B=0,m=0,L=0;e:for(;;){do if((m|0)>-1)if((B|0)>(2147483647-m|0)){n[(eE()|0)>>2]=75,m=-1;break}else{m=B+m|0;break}while(!1);if(B=s[l>>0]|0,B<<24>>24)k=l;else{Xe=87;break}t:for(;;){switch(B<<24>>24){case 37:{B=k,Xe=9;break t}case 0:{B=k;break t}default:}nt=k+1|0,n[fr>>2]=nt,B=s[nt>>0]|0,k=nt}t:do if((Xe|0)==9)for(;;){if(Xe=0,(s[k+1>>0]|0)!=37)break t;if(B=B+1|0,k=k+2|0,n[fr>>2]=k,(s[k>>0]|0)==37)Xe=9;else break}while(!1);if(B=B-l|0,ft&&bs(o,l,B),B|0){l=k;continue}R=k+1|0,B=(s[R>>0]|0)+-48|0,B>>>0<10?(nt=(s[k+2>>0]|0)==36,Te=nt?B:-1,L=nt?1:L,R=nt?k+3|0:R):Te=-1,n[fr>>2]=R,B=s[R>>0]|0,k=(B<<24>>24)+-32|0;t:do if(k>>>0<32)for(M=0,q=B;;){if(B=1<<k,!(B&75913)){B=q;break t}if(M=B|M,R=R+1|0,n[fr>>2]=R,B=s[R>>0]|0,k=(B<<24>>24)+-32|0,k>>>0>=32)break;q=B}else M=0;while(!1);if(B<<24>>24==42){if(k=R+1|0,B=(s[k>>0]|0)+-48|0,B>>>0<10&&(s[R+2>>0]|0)==36)n[d+(B<<2)>>2]=10,B=n[A+((s[k>>0]|0)+-48<<3)>>2]|0,L=1,R=R+3|0;else{if(L|0){m=-1;break}ft?(L=(n[u>>2]|0)+3&-4,B=n[L>>2]|0,n[u>>2]=L+4,L=0,R=k):(B=0,L=0,R=k)}n[fr>>2]=R,nt=(B|0)<0,B=nt?0-B|0:B,M=nt?M|8192:M}else{if(B=MZ(fr)|0,(B|0)<0){m=-1;break}R=n[fr>>2]|0}do if((s[R>>0]|0)==46){if((s[R+1>>0]|0)!=42){n[fr>>2]=R+1,k=MZ(fr)|0,R=n[fr>>2]|0;break}if(q=R+2|0,k=(s[q>>0]|0)+-48|0,k>>>0<10&&(s[R+3>>0]|0)==36){n[d+(k<<2)>>2]=10,k=n[A+((s[q>>0]|0)+-48<<3)>>2]|0,R=R+4|0,n[fr>>2]=R;break}if(L|0){m=-1;break e}ft?(nt=(n[u>>2]|0)+3&-4,k=n[nt>>2]|0,n[u>>2]=nt+4):k=0,n[fr>>2]=q,R=q}else k=-1;while(!1);for(Le=0;;){if(((s[R>>0]|0)+-65|0)>>>0>57){m=-1;break e}if(nt=R+1|0,n[fr>>2]=nt,q=s[(s[R>>0]|0)+-65+(5178+(Le*58|0))>>0]|0,oe=q&255,(oe+-1|0)>>>0<8)Le=oe,R=nt;else break}if(!(q<<24>>24)){m=-1;break}Ye=(Te|0)>-1;do if(q<<24>>24==19)if(Ye){m=-1;break e}else Xe=49;else{if(Ye){n[d+(Te<<2)>>2]=oe,Ye=A+(Te<<3)|0,Te=n[Ye+4>>2]|0,Xe=$t,n[Xe>>2]=n[Ye>>2],n[Xe+4>>2]=Te,Xe=49;break}if(!ft){m=0;break e}UZ($t,oe,u)}while(!1);if((Xe|0)==49&&(Xe=0,!ft)){B=0,l=nt;continue}R=s[R>>0]|0,R=(Le|0)!=0&(R&15|0)==3?R&-33:R,Ye=M&-65537,Te=M&8192|0?Ye:M;t:do switch(R|0){case 110:switch((Le&255)<<24>>24){case 0:{n[n[$t>>2]>>2]=m,B=0,l=nt;continue e}case 1:{n[n[$t>>2]>>2]=m,B=0,l=nt;continue e}case 2:{B=n[$t>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=nt;continue e}case 3:{a[n[$t>>2]>>1]=m,B=0,l=nt;continue e}case 4:{s[n[$t>>2]>>0]=m,B=0,l=nt;continue e}case 6:{n[n[$t>>2]>>2]=m,B=0,l=nt;continue e}case 7:{B=n[$t>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=nt;continue e}default:{B=0,l=nt;continue e}}case 112:{R=120,k=k>>>0>8?k:8,l=Te|8,Xe=61;break}case 88:case 120:{l=Te,Xe=61;break}case 111:{R=$t,l=n[R>>2]|0,R=n[R+4>>2]|0,oe=X8e(l,R,He)|0,Ye=Ve-oe|0,M=0,q=5642,k=(Te&8|0)==0|(k|0)>(Ye|0)?k:Ye+1|0,Ye=Te,Xe=67;break}case 105:case 100:if(R=$t,l=n[R>>2]|0,R=n[R+4>>2]|0,(R|0)<0){l=GP(0,0,l|0,R|0)|0,R=Be,M=$t,n[M>>2]=l,n[M+4>>2]=R,M=1,q=5642,Xe=66;break t}else{M=(Te&2049|0)!=0&1,q=Te&2048|0?5643:Te&1|0?5644:5642,Xe=66;break t}case 117:{R=$t,M=0,q=5642,l=n[R>>2]|0,R=n[R+4>>2]|0,Xe=66;break}case 99:{s[Lt>>0]=n[$t>>2],l=Lt,M=0,q=5642,oe=He,R=1,k=Ye;break}case 109:{R=$8e(n[(eE()|0)>>2]|0)|0,Xe=71;break}case 115:{R=n[$t>>2]|0,R=R|0?R:5652,Xe=71;break}case 67:{n[Rr>>2]=n[$t>>2],n[Gr>>2]=0,n[$t>>2]=Rr,oe=-1,R=Rr,Xe=75;break}case 83:{l=n[$t>>2]|0,k?(oe=k,R=l,Xe=75):(_s(o,32,B,0,Te),l=0,Xe=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{B=tHe(o,+E[$t>>3],B,k,Te,R)|0,l=nt;continue e}default:M=0,q=5642,oe=He,R=k,k=Te}while(!1);t:do if((Xe|0)==61)Te=$t,Le=n[Te>>2]|0,Te=n[Te+4>>2]|0,oe=Z8e(Le,Te,He,R&32)|0,q=(l&8|0)==0|(Le|0)==0&(Te|0)==0,M=q?0:2,q=q?5642:5642+(R>>4)|0,Ye=l,l=Le,R=Te,Xe=67;else if((Xe|0)==66)oe=tE(l,R,He)|0,Ye=Te,Xe=67;else if((Xe|0)==71)Xe=0,Te=eHe(R,0,k)|0,Le=(Te|0)==0,l=R,M=0,q=5642,oe=Le?R+k|0:Te,R=Le?k:Te-R|0,k=Ye;else if((Xe|0)==75){for(Xe=0,q=R,l=0,k=0;M=n[q>>2]|0,!(!M||(k=_Z(Hr,M)|0,(k|0)<0|k>>>0>(oe-l|0)>>>0));)if(l=k+l|0,oe>>>0>l>>>0)q=q+4|0;else break;if((k|0)<0){m=-1;break e}if(_s(o,32,B,l,Te),!l)l=0,Xe=84;else for(M=0;;){if(k=n[R>>2]|0,!k){Xe=84;break t}if(k=_Z(Hr,k)|0,M=k+M|0,(M|0)>(l|0)){Xe=84;break t}if(bs(o,Hr,k),M>>>0>=l>>>0){Xe=84;break}else R=R+4|0}}while(!1);if((Xe|0)==67)Xe=0,R=(l|0)!=0|(R|0)!=0,Te=(k|0)!=0|R,R=((R^1)&1)+(Ve-oe)|0,l=Te?oe:He,oe=He,R=Te?(k|0)>(R|0)?k:R:k,k=(k|0)>-1?Ye&-65537:Ye;else if((Xe|0)==84){Xe=0,_s(o,32,B,l,Te^8192),B=(B|0)>(l|0)?B:l,l=nt;continue}Le=oe-l|0,Ye=(R|0)<(Le|0)?Le:R,Te=Ye+M|0,B=(B|0)<(Te|0)?Te:B,_s(o,32,B,Te,k),bs(o,q,M),_s(o,48,B,Te,k^65536),_s(o,48,Ye,Le,0),bs(o,l,Le),_s(o,32,B,Te,k^8192),l=nt}e:do if((Xe|0)==87&&!o)if(!L)m=0;else{for(m=1;l=n[d+(m<<2)>>2]|0,!!l;)if(UZ(A+(m<<3)|0,l,u),m=m+1|0,(m|0)>=10){m=1;break e}for(;;){if(n[d+(m<<2)>>2]|0){m=-1;break e}if(m=m+1|0,(m|0)>=10){m=1;break}}}while(!1);return I=cr,m|0}function J8e(o){return o=o|0,0}function z8e(o){o=o|0}function bs(o,l,u){o=o|0,l=l|0,u=u|0,n[o>>2]&32||uHe(l,u,o)|0}function MZ(o){o=o|0;var l=0,u=0,A=0;if(u=n[o>>2]|0,A=(s[u>>0]|0)+-48|0,A>>>0<10){l=0;do l=A+(l*10|0)|0,u=u+1|0,n[o>>2]=u,A=(s[u>>0]|0)+-48|0;while(A>>>0<10)}else l=0;return l|0}function UZ(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;e:do if(l>>>0<=20)do switch(l|0){case 9:{A=(n[u>>2]|0)+3&-4,l=n[A>>2]|0,n[u>>2]=A+4,n[o>>2]=l;break e}case 10:{A=(n[u>>2]|0)+3&-4,l=n[A>>2]|0,n[u>>2]=A+4,A=o,n[A>>2]=l,n[A+4>>2]=((l|0)<0)<<31>>31;break e}case 11:{A=(n[u>>2]|0)+3&-4,l=n[A>>2]|0,n[u>>2]=A+4,A=o,n[A>>2]=l,n[A+4>>2]=0;break e}case 12:{A=(n[u>>2]|0)+7&-8,l=A,d=n[l>>2]|0,l=n[l+4>>2]|0,n[u>>2]=A+8,A=o,n[A>>2]=d,n[A+4>>2]=l;break e}case 13:{d=(n[u>>2]|0)+3&-4,A=n[d>>2]|0,n[u>>2]=d+4,A=(A&65535)<<16>>16,d=o,n[d>>2]=A,n[d+4>>2]=((A|0)<0)<<31>>31;break e}case 14:{d=(n[u>>2]|0)+3&-4,A=n[d>>2]|0,n[u>>2]=d+4,d=o,n[d>>2]=A&65535,n[d+4>>2]=0;break e}case 15:{d=(n[u>>2]|0)+3&-4,A=n[d>>2]|0,n[u>>2]=d+4,A=(A&255)<<24>>24,d=o,n[d>>2]=A,n[d+4>>2]=((A|0)<0)<<31>>31;break e}case 16:{d=(n[u>>2]|0)+3&-4,A=n[d>>2]|0,n[u>>2]=d+4,d=o,n[d>>2]=A&255,n[d+4>>2]=0;break e}case 17:{d=(n[u>>2]|0)+7&-8,m=+E[d>>3],n[u>>2]=d+8,E[o>>3]=m;break e}case 18:{d=(n[u>>2]|0)+7&-8,m=+E[d>>3],n[u>>2]=d+8,E[o>>3]=m;break e}default:break e}while(!1);while(!1)}function Z8e(o,l,u,A){if(o=o|0,l=l|0,u=u|0,A=A|0,!((o|0)==0&(l|0)==0))do u=u+-1|0,s[u>>0]=c[5694+(o&15)>>0]|0|A,o=qP(o|0,l|0,4)|0,l=Be;while(!((o|0)==0&(l|0)==0));return u|0}function X8e(o,l,u){if(o=o|0,l=l|0,u=u|0,!((o|0)==0&(l|0)==0))do u=u+-1|0,s[u>>0]=o&7|48,o=qP(o|0,l|0,3)|0,l=Be;while(!((o|0)==0&(l|0)==0));return u|0}function tE(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;if(l>>>0>0|(l|0)==0&o>>>0>4294967295){for(;A=ZM(o|0,l|0,10,0)|0,u=u+-1|0,s[u>>0]=A&255|48,A=o,o=zM(o|0,l|0,10,0)|0,l>>>0>9|(l|0)==9&A>>>0>4294967295;)l=Be;l=o}else l=o;if(l)for(;u=u+-1|0,s[u>>0]=(l>>>0)%10|0|48,!(l>>>0<10);)l=(l>>>0)/10|0;return u|0}function $8e(o){return o=o|0,oHe(o,n[(sHe()|0)+188>>2]|0)|0}function eHe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;m=l&255,A=(u|0)!=0;e:do if(A&(o&3|0)!=0)for(d=l&255;;){if((s[o>>0]|0)==d<<24>>24){B=6;break e}if(o=o+1|0,u=u+-1|0,A=(u|0)!=0,!(A&(o&3|0)!=0)){B=5;break}}else B=5;while(!1);(B|0)==5&&(A?B=6:u=0);e:do if((B|0)==6&&(d=l&255,(s[o>>0]|0)!=d<<24>>24)){A=Me(m,16843009)|0;t:do if(u>>>0>3){for(;m=n[o>>2]^A,!((m&-2139062144^-2139062144)&m+-16843009|0);)if(o=o+4|0,u=u+-4|0,u>>>0<=3){B=11;break t}}else B=11;while(!1);if((B|0)==11&&!u){u=0;break}for(;;){if((s[o>>0]|0)==d<<24>>24)break e;if(o=o+1|0,u=u+-1|0,!u){u=0;break}}}while(!1);return(u|0?o:0)|0}function _s(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0;if(B=I,I=I+256|0,m=B,(u|0)>(A|0)&(d&73728|0)==0){if(d=u-A|0,nE(m|0,l|0,(d>>>0<256?d:256)|0)|0,d>>>0>255){l=u-A|0;do bs(o,m,256),d=d+-256|0;while(d>>>0>255);d=l&255}bs(o,m,d)}I=B}function _Z(o,l){return o=o|0,l=l|0,o?o=nHe(o,l,0)|0:o=0,o|0}function tHe(o,l,u,A,d,m){o=o|0,l=+l,u=u|0,A=A|0,d=d|0,m=m|0;var B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0,Te=0,nt=0,Xe=0,ft=0,He=0,Ve=0,Lt=0,Gr=0,fr=0,$t=0,Rr=0,Hr=0,cr=0,jn=0;jn=I,I=I+560|0,R=jn+8|0,nt=jn,cr=jn+524|0,Hr=cr,M=jn+512|0,n[nt>>2]=0,Rr=M+12|0,HZ(l)|0,(Be|0)<0?(l=-l,fr=1,Gr=5659):(fr=(d&2049|0)!=0&1,Gr=d&2048|0?5662:d&1|0?5665:5660),HZ(l)|0,$t=Be&2146435072;do if($t>>>0<2146435072|($t|0)==2146435072&!1){if(Ye=+rHe(l,nt)*2,B=Ye!=0,B&&(n[nt>>2]=(n[nt>>2]|0)+-1),ft=m|32,(ft|0)==97){Le=m&32,oe=Le|0?Gr+9|0:Gr,q=fr|2,B=12-A|0;do if(A>>>0>11|(B|0)==0)l=Ye;else{l=8;do B=B+-1|0,l=l*16;while(B|0);if((s[oe>>0]|0)==45){l=-(l+(-Ye-l));break}else{l=Ye+l-l;break}}while(!1);k=n[nt>>2]|0,B=(k|0)<0?0-k|0:k,B=tE(B,((B|0)<0)<<31>>31,Rr)|0,(B|0)==(Rr|0)&&(B=M+11|0,s[B>>0]=48),s[B+-1>>0]=(k>>31&2)+43,L=B+-2|0,s[L>>0]=m+15,M=(A|0)<1,R=(d&8|0)==0,B=cr;do $t=~~l,k=B+1|0,s[B>>0]=c[5694+$t>>0]|Le,l=(l-+($t|0))*16,(k-Hr|0)==1&&!(R&(M&l==0))?(s[k>>0]=46,B=B+2|0):B=k;while(l!=0);$t=B-Hr|0,Hr=Rr-L|0,Rr=(A|0)!=0&($t+-2|0)<(A|0)?A+2|0:$t,B=Hr+q+Rr|0,_s(o,32,u,B,d),bs(o,oe,q),_s(o,48,u,B,d^65536),bs(o,cr,$t),_s(o,48,Rr-$t|0,0,0),bs(o,L,Hr),_s(o,32,u,B,d^8192);break}k=(A|0)<0?6:A,B?(B=(n[nt>>2]|0)+-28|0,n[nt>>2]=B,l=Ye*268435456):(l=Ye,B=n[nt>>2]|0),$t=(B|0)<0?R:R+288|0,R=$t;do Ve=~~l>>>0,n[R>>2]=Ve,R=R+4|0,l=(l-+(Ve>>>0))*1e9;while(l!=0);if((B|0)>0)for(M=$t,q=R;;){if(L=(B|0)<29?B:29,B=q+-4|0,B>>>0>=M>>>0){R=0;do He=YZ(n[B>>2]|0,0,L|0)|0,He=JM(He|0,Be|0,R|0,0)|0,Ve=Be,Xe=ZM(He|0,Ve|0,1e9,0)|0,n[B>>2]=Xe,R=zM(He|0,Ve|0,1e9,0)|0,B=B+-4|0;while(B>>>0>=M>>>0);R&&(M=M+-4|0,n[M>>2]=R)}for(R=q;!(R>>>0<=M>>>0);)if(B=R+-4|0,!(n[B>>2]|0))R=B;else break;if(B=(n[nt>>2]|0)-L|0,n[nt>>2]=B,(B|0)>0)q=R;else break}else M=$t;if((B|0)<0){A=((k+25|0)/9|0)+1|0,Te=(ft|0)==102;do{if(Le=0-B|0,Le=(Le|0)<9?Le:9,M>>>0<R>>>0){L=(1<<Le)+-1|0,q=1e9>>>Le,oe=0,B=M;do Ve=n[B>>2]|0,n[B>>2]=(Ve>>>Le)+oe,oe=Me(Ve&L,q)|0,B=B+4|0;while(B>>>0<R>>>0);B=n[M>>2]|0?M:M+4|0,oe?(n[R>>2]=oe,M=B,B=R+4|0):(M=B,B=R)}else M=n[M>>2]|0?M:M+4|0,B=R;R=Te?$t:M,R=(B-R>>2|0)>(A|0)?R+(A<<2)|0:B,B=(n[nt>>2]|0)+Le|0,n[nt>>2]=B}while((B|0)<0);B=M,A=R}else B=M,A=R;if(Ve=$t,B>>>0<A>>>0){if(R=(Ve-B>>2)*9|0,L=n[B>>2]|0,L>>>0>=10){M=10;do M=M*10|0,R=R+1|0;while(L>>>0>=M>>>0)}}else R=0;if(Te=(ft|0)==103,Xe=(k|0)!=0,M=k-((ft|0)!=102?R:0)+((Xe&Te)<<31>>31)|0,(M|0)<(((A-Ve>>2)*9|0)+-9|0)){if(M=M+9216|0,Le=$t+4+(((M|0)/9|0)+-1024<<2)|0,M=((M|0)%9|0)+1|0,(M|0)<9){L=10;do L=L*10|0,M=M+1|0;while((M|0)!=9)}else L=10;if(q=n[Le>>2]|0,oe=(q>>>0)%(L>>>0)|0,M=(Le+4|0)==(A|0),M&(oe|0)==0)M=Le;else if(Ye=((q>>>0)/(L>>>0)|0)&1|0?9007199254740994:9007199254740992,He=(L|0)/2|0,l=oe>>>0<He>>>0?.5:M&(oe|0)==(He|0)?1:1.5,fr&&(He=(s[Gr>>0]|0)==45,l=He?-l:l,Ye=He?-Ye:Ye),M=q-oe|0,n[Le>>2]=M,Ye+l!=Ye){if(He=M+L|0,n[Le>>2]=He,He>>>0>999999999)for(R=Le;M=R+-4|0,n[R>>2]=0,M>>>0<B>>>0&&(B=B+-4|0,n[B>>2]=0),He=(n[M>>2]|0)+1|0,n[M>>2]=He,He>>>0>999999999;)R=M;else M=Le;if(R=(Ve-B>>2)*9|0,q=n[B>>2]|0,q>>>0>=10){L=10;do L=L*10|0,R=R+1|0;while(q>>>0>=L>>>0)}}else M=Le;M=M+4|0,M=A>>>0>M>>>0?M:A,He=B}else M=A,He=B;for(ft=M;;){if(ft>>>0<=He>>>0){nt=0;break}if(B=ft+-4|0,!(n[B>>2]|0))ft=B;else{nt=1;break}}A=0-R|0;do if(Te)if(B=((Xe^1)&1)+k|0,(B|0)>(R|0)&(R|0)>-5?(L=m+-1|0,k=B+-1-R|0):(L=m+-2|0,k=B+-1|0),B=d&8,B)Le=B;else{if(nt&&(Lt=n[ft+-4>>2]|0,(Lt|0)!=0))if((Lt>>>0)%10|0)M=0;else{M=0,B=10;do B=B*10|0,M=M+1|0;while(!((Lt>>>0)%(B>>>0)|0|0))}else M=9;if(B=((ft-Ve>>2)*9|0)+-9|0,(L|32|0)==102){Le=B-M|0,Le=(Le|0)>0?Le:0,k=(k|0)<(Le|0)?k:Le,Le=0;break}else{Le=B+R-M|0,Le=(Le|0)>0?Le:0,k=(k|0)<(Le|0)?k:Le,Le=0;break}}else L=m,Le=d&8;while(!1);if(Te=k|Le,q=(Te|0)!=0&1,oe=(L|32|0)==102,oe)Xe=0,B=(R|0)>0?R:0;else{if(B=(R|0)<0?A:R,B=tE(B,((B|0)<0)<<31>>31,Rr)|0,M=Rr,(M-B|0)<2)do B=B+-1|0,s[B>>0]=48;while((M-B|0)<2);s[B+-1>>0]=(R>>31&2)+43,B=B+-2|0,s[B>>0]=L,Xe=B,B=M-B|0}if(B=fr+1+k+q+B|0,_s(o,32,u,B,d),bs(o,Gr,fr),_s(o,48,u,B,d^65536),oe){L=He>>>0>$t>>>0?$t:He,Le=cr+9|0,q=Le,oe=cr+8|0,M=L;do{if(R=tE(n[M>>2]|0,0,Le)|0,(M|0)==(L|0))(R|0)==(Le|0)&&(s[oe>>0]=48,R=oe);else if(R>>>0>cr>>>0){nE(cr|0,48,R-Hr|0)|0;do R=R+-1|0;while(R>>>0>cr>>>0)}bs(o,R,q-R|0),M=M+4|0}while(M>>>0<=$t>>>0);if(Te|0&&bs(o,5710,1),M>>>0<ft>>>0&(k|0)>0)for(;;){if(R=tE(n[M>>2]|0,0,Le)|0,R>>>0>cr>>>0){nE(cr|0,48,R-Hr|0)|0;do R=R+-1|0;while(R>>>0>cr>>>0)}if(bs(o,R,(k|0)<9?k:9),M=M+4|0,R=k+-9|0,M>>>0<ft>>>0&(k|0)>9)k=R;else{k=R;break}}_s(o,48,k+9|0,9,0)}else{if(Te=nt?ft:He+4|0,(k|0)>-1){nt=cr+9|0,Le=(Le|0)==0,A=nt,q=0-Hr|0,oe=cr+8|0,L=He;do{R=tE(n[L>>2]|0,0,nt)|0,(R|0)==(nt|0)&&(s[oe>>0]=48,R=oe);do if((L|0)==(He|0)){if(M=R+1|0,bs(o,R,1),Le&(k|0)<1){R=M;break}bs(o,5710,1),R=M}else{if(R>>>0<=cr>>>0)break;nE(cr|0,48,R+q|0)|0;do R=R+-1|0;while(R>>>0>cr>>>0)}while(!1);Hr=A-R|0,bs(o,R,(k|0)>(Hr|0)?Hr:k),k=k-Hr|0,L=L+4|0}while(L>>>0<Te>>>0&(k|0)>-1)}_s(o,48,k+18|0,18,0),bs(o,Xe,Rr-Xe|0)}_s(o,32,u,B,d^8192)}else cr=(m&32|0)!=0,B=fr+3|0,_s(o,32,u,B,d&-65537),bs(o,Gr,fr),bs(o,l!=l|!1?cr?5686:5690:cr?5678:5682,3),_s(o,32,u,B,d^8192);while(!1);return I=jn,((B|0)<(u|0)?u:B)|0}function HZ(o){o=+o;var l=0;return E[S>>3]=o,l=n[S>>2]|0,Be=n[S+4>>2]|0,l|0}function rHe(o,l){return o=+o,l=l|0,+ +jZ(o,l)}function jZ(o,l){o=+o,l=l|0;var u=0,A=0,d=0;switch(E[S>>3]=o,u=n[S>>2]|0,A=n[S+4>>2]|0,d=qP(u|0,A|0,52)|0,d&2047){case 0:{o!=0?(o=+jZ(o*18446744073709552e3,l),u=(n[l>>2]|0)+-64|0):u=0,n[l>>2]=u;break}case 2047:break;default:n[l>>2]=(d&2047)+-1022,n[S>>2]=u,n[S+4>>2]=A&-2146435073|1071644672,o=+E[S>>3]}return+o}function nHe(o,l,u){o=o|0,l=l|0,u=u|0;do if(o){if(l>>>0<128){s[o>>0]=l,o=1;break}if(!(n[n[(iHe()|0)+188>>2]>>2]|0))if((l&-128|0)==57216){s[o>>0]=l,o=1;break}else{n[(eE()|0)>>2]=84,o=-1;break}if(l>>>0<2048){s[o>>0]=l>>>6|192,s[o+1>>0]=l&63|128,o=2;break}if(l>>>0<55296|(l&-8192|0)==57344){s[o>>0]=l>>>12|224,s[o+1>>0]=l>>>6&63|128,s[o+2>>0]=l&63|128,o=3;break}if((l+-65536|0)>>>0<1048576){s[o>>0]=l>>>18|240,s[o+1>>0]=l>>>12&63|128,s[o+2>>0]=l>>>6&63|128,s[o+3>>0]=l&63|128,o=4;break}else{n[(eE()|0)>>2]=84,o=-1;break}}else o=1;while(!1);return o|0}function iHe(){return VM()|0}function sHe(){return VM()|0}function oHe(o,l){o=o|0,l=l|0;var u=0,A=0;for(A=0;;){if((c[5712+A>>0]|0)==(o|0)){o=2;break}if(u=A+1|0,(u|0)==87){u=5800,A=87,o=5;break}else A=u}if((o|0)==2&&(A?(u=5800,o=5):u=5800),(o|0)==5)for(;;){do o=u,u=u+1|0;while(s[o>>0]|0);if(A=A+-1|0,A)o=5;else break}return aHe(u,n[l+20>>2]|0)|0}function aHe(o,l){return o=o|0,l=l|0,lHe(o,l)|0}function lHe(o,l){return o=o|0,l=l|0,l?l=cHe(n[l>>2]|0,n[l+4>>2]|0,o)|0:l=0,(l|0?l:o)|0}function cHe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0;oe=(n[o>>2]|0)+1794895138|0,m=ud(n[o+8>>2]|0,oe)|0,A=ud(n[o+12>>2]|0,oe)|0,d=ud(n[o+16>>2]|0,oe)|0;e:do if(m>>>0<l>>>2>>>0&&(q=l-(m<<2)|0,A>>>0<q>>>0&d>>>0<q>>>0)&&!((d|A)&3|0)){for(q=A>>>2,L=d>>>2,M=0;;){if(k=m>>>1,R=M+k|0,B=R<<1,d=B+q|0,A=ud(n[o+(d<<2)>>2]|0,oe)|0,d=ud(n[o+(d+1<<2)>>2]|0,oe)|0,!(d>>>0<l>>>0&A>>>0<(l-d|0)>>>0)){A=0;break e}if(s[o+(d+A)>>0]|0){A=0;break e}if(A=OZ(u,o+d|0)|0,!A)break;if(A=(A|0)<0,(m|0)==1){A=0;break e}else M=A?M:R,m=A?k:m-k|0}A=B+L|0,d=ud(n[o+(A<<2)>>2]|0,oe)|0,A=ud(n[o+(A+1<<2)>>2]|0,oe)|0,A>>>0<l>>>0&d>>>0<(l-A|0)>>>0?A=s[o+(A+d)>>0]|0?0:o+A|0:A=0}else A=0;while(!1);return A|0}function ud(o,l){o=o|0,l=l|0;var u=0;return u=zZ(o|0)|0,(l|0?u:o)|0}function uHe(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0,k=0;A=u+16|0,d=n[A>>2]|0,d?m=5:fHe(u)|0?A=0:(d=n[A>>2]|0,m=5);e:do if((m|0)==5){if(k=u+20|0,B=n[k>>2]|0,A=B,(d-B|0)>>>0<l>>>0){A=VP[n[u+36>>2]&7](u,o,l)|0;break}t:do if((s[u+75>>0]|0)>-1){for(B=l;;){if(!B){m=0,d=o;break t}if(d=B+-1|0,(s[o+d>>0]|0)==10)break;B=d}if(A=VP[n[u+36>>2]&7](u,o,B)|0,A>>>0<B>>>0)break e;m=B,d=o+B|0,l=l-B|0,A=n[k>>2]|0}else m=0,d=o;while(!1);Qr(A|0,d|0,l|0)|0,n[k>>2]=(n[k>>2]|0)+l,A=m+l|0}while(!1);return A|0}function fHe(o){o=o|0;var l=0,u=0;return l=o+74|0,u=s[l>>0]|0,s[l>>0]=u+255|u,l=n[o>>2]|0,l&8?(n[o>>2]=l|32,o=-1):(n[o+8>>2]=0,n[o+4>>2]=0,u=n[o+44>>2]|0,n[o+28>>2]=u,n[o+20>>2]=u,n[o+16>>2]=u+(n[o+48>>2]|0),o=0),o|0}function ri(o,l){o=y(o),l=y(l);var u=0,A=0;u=GZ(o)|0;do if((u&2147483647)>>>0<=2139095040){if(A=GZ(l)|0,(A&2147483647)>>>0<=2139095040)if((A^u|0)<0){o=(u|0)<0?l:o;break}else{o=o<l?l:o;break}}else o=l;while(!1);return y(o)}function GZ(o){return o=y(o),h[S>>2]=o,n[S>>2]|0|0}function fd(o,l){o=y(o),l=y(l);var u=0,A=0;u=qZ(o)|0;do if((u&2147483647)>>>0<=2139095040){if(A=qZ(l)|0,(A&2147483647)>>>0<=2139095040)if((A^u|0)<0){o=(u|0)<0?o:l;break}else{o=o<l?o:l;break}}else o=l;while(!1);return y(o)}function qZ(o){return o=y(o),h[S>>2]=o,n[S>>2]|0|0}function KM(o,l){o=y(o),l=y(l);var u=0,A=0,d=0,m=0,B=0,k=0,R=0,M=0;m=(h[S>>2]=o,n[S>>2]|0),k=(h[S>>2]=l,n[S>>2]|0),u=m>>>23&255,B=k>>>23&255,R=m&-2147483648,d=k<<1;e:do if(d|0&&!((u|0)==255|((AHe(l)|0)&2147483647)>>>0>2139095040)){if(A=m<<1,A>>>0<=d>>>0)return l=y(o*y(0)),y((A|0)==(d|0)?l:o);if(u)A=m&8388607|8388608;else{if(u=m<<9,(u|0)>-1){A=u,u=0;do u=u+-1|0,A=A<<1;while((A|0)>-1)}else u=0;A=m<<1-u}if(B)k=k&8388607|8388608;else{if(m=k<<9,(m|0)>-1){d=0;do d=d+-1|0,m=m<<1;while((m|0)>-1)}else d=0;B=d,k=k<<1-d}d=A-k|0,m=(d|0)>-1;t:do if((u|0)>(B|0)){for(;;){if(m)if(d)A=d;else break;if(A=A<<1,u=u+-1|0,d=A-k|0,m=(d|0)>-1,(u|0)<=(B|0))break t}l=y(o*y(0));break e}while(!1);if(m)if(d)A=d;else{l=y(o*y(0));break}if(A>>>0<8388608)do A=A<<1,u=u+-1|0;while(A>>>0<8388608);(u|0)>0?u=A+-8388608|u<<23:u=A>>>(1-u|0),l=(n[S>>2]=u|R,y(h[S>>2]))}else M=3;while(!1);return(M|0)==3&&(l=y(o*l),l=y(l/l)),y(l)}function AHe(o){return o=y(o),h[S>>2]=o,n[S>>2]|0|0}function pHe(o,l){return o=o|0,l=l|0,LZ(n[582]|0,o,l)|0}function an(o){o=o|0,Nt()}function rE(o){o=o|0}function hHe(o,l){return o=o|0,l=l|0,0}function gHe(o){return o=o|0,(WZ(o+4|0)|0)==-1?(sp[n[(n[o>>2]|0)+8>>2]&127](o),o=1):o=0,o|0}function WZ(o){o=o|0;var l=0;return l=n[o>>2]|0,n[o>>2]=l+-1,l+-1|0}function Hh(o){o=o|0,gHe(o)|0&&dHe(o)}function dHe(o){o=o|0;var l=0;l=o+8|0,n[l>>2]|0&&(WZ(l)|0)!=-1||sp[n[(n[o>>2]|0)+16>>2]&127](o)}function Jt(o){o=o|0;var l=0;for(l=o|0?o:1;o=_P(l)|0,!(o|0);){if(o=yHe()|0,!o){o=0;break}oX[o&0]()}return o|0}function VZ(o){return o=o|0,Jt(o)|0}function It(o){o=o|0,HP(o)}function mHe(o){o=o|0,(s[o+11>>0]|0)<0&&It(n[o>>2]|0)}function yHe(){var o=0;return o=n[2923]|0,n[2923]=o+0,o|0}function EHe(){}function GP(o,l,u,A){return o=o|0,l=l|0,u=u|0,A=A|0,A=l-A-(u>>>0>o>>>0|0)>>>0,Be=A,o-u>>>0|0|0}function JM(o,l,u,A){return o=o|0,l=l|0,u=u|0,A=A|0,u=o+u>>>0,Be=l+A+(u>>>0<o>>>0|0)>>>0,u|0|0}function nE(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0,B=0;if(m=o+u|0,l=l&255,(u|0)>=67){for(;o&3;)s[o>>0]=l,o=o+1|0;for(A=m&-4|0,d=A-64|0,B=l|l<<8|l<<16|l<<24;(o|0)<=(d|0);)n[o>>2]=B,n[o+4>>2]=B,n[o+8>>2]=B,n[o+12>>2]=B,n[o+16>>2]=B,n[o+20>>2]=B,n[o+24>>2]=B,n[o+28>>2]=B,n[o+32>>2]=B,n[o+36>>2]=B,n[o+40>>2]=B,n[o+44>>2]=B,n[o+48>>2]=B,n[o+52>>2]=B,n[o+56>>2]=B,n[o+60>>2]=B,o=o+64|0;for(;(o|0)<(A|0);)n[o>>2]=B,o=o+4|0}for(;(o|0)<(m|0);)s[o>>0]=l,o=o+1|0;return m-u|0}function YZ(o,l,u){return o=o|0,l=l|0,u=u|0,(u|0)<32?(Be=l<<u|(o&(1<<u)-1<<32-u)>>>32-u,o<<u):(Be=o<<u-32,0)}function qP(o,l,u){return o=o|0,l=l|0,u=u|0,(u|0)<32?(Be=l>>>u,o>>>u|(l&(1<<u)-1)<<32-u):(Be=0,l>>>u-32|0)}function Qr(o,l,u){o=o|0,l=l|0,u=u|0;var A=0,d=0,m=0;if((u|0)>=8192)return LA(o|0,l|0,u|0)|0;if(m=o|0,d=o+u|0,(o&3)==(l&3)){for(;o&3;){if(!u)return m|0;s[o>>0]=s[l>>0]|0,o=o+1|0,l=l+1|0,u=u-1|0}for(u=d&-4|0,A=u-64|0;(o|0)<=(A|0);)n[o>>2]=n[l>>2],n[o+4>>2]=n[l+4>>2],n[o+8>>2]=n[l+8>>2],n[o+12>>2]=n[l+12>>2],n[o+16>>2]=n[l+16>>2],n[o+20>>2]=n[l+20>>2],n[o+24>>2]=n[l+24>>2],n[o+28>>2]=n[l+28>>2],n[o+32>>2]=n[l+32>>2],n[o+36>>2]=n[l+36>>2],n[o+40>>2]=n[l+40>>2],n[o+44>>2]=n[l+44>>2],n[o+48>>2]=n[l+48>>2],n[o+52>>2]=n[l+52>>2],n[o+56>>2]=n[l+56>>2],n[o+60>>2]=n[l+60>>2],o=o+64|0,l=l+64|0;for(;(o|0)<(u|0);)n[o>>2]=n[l>>2],o=o+4|0,l=l+4|0}else for(u=d-4|0;(o|0)<(u|0);)s[o>>0]=s[l>>0]|0,s[o+1>>0]=s[l+1>>0]|0,s[o+2>>0]=s[l+2>>0]|0,s[o+3>>0]=s[l+3>>0]|0,o=o+4|0,l=l+4|0;for(;(o|0)<(d|0);)s[o>>0]=s[l>>0]|0,o=o+1|0,l=l+1|0;return m|0}function KZ(o){o=o|0;var l=0;return l=s[O+(o&255)>>0]|0,(l|0)<8?l|0:(l=s[O+(o>>8&255)>>0]|0,(l|0)<8?l+8|0:(l=s[O+(o>>16&255)>>0]|0,(l|0)<8?l+16|0:(s[O+(o>>>24)>>0]|0)+24|0))}function JZ(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0;var m=0,B=0,k=0,R=0,M=0,L=0,q=0,oe=0,Ye=0,Le=0;if(L=o,R=l,M=R,B=u,oe=A,k=oe,!M)return m=(d|0)!=0,k?m?(n[d>>2]=o|0,n[d+4>>2]=l&0,oe=0,d=0,Be=oe,d|0):(oe=0,d=0,Be=oe,d|0):(m&&(n[d>>2]=(L>>>0)%(B>>>0),n[d+4>>2]=0),oe=0,d=(L>>>0)/(B>>>0)>>>0,Be=oe,d|0);m=(k|0)==0;do if(B){if(!m){if(m=(b(k|0)|0)-(b(M|0)|0)|0,m>>>0<=31){q=m+1|0,k=31-m|0,l=m-31>>31,B=q,o=L>>>(q>>>0)&l|M<<k,l=M>>>(q>>>0)&l,m=0,k=L<<k;break}return d?(n[d>>2]=o|0,n[d+4>>2]=R|l&0,oe=0,d=0,Be=oe,d|0):(oe=0,d=0,Be=oe,d|0)}if(m=B-1|0,m&B|0){k=(b(B|0)|0)+33-(b(M|0)|0)|0,Le=64-k|0,q=32-k|0,R=q>>31,Ye=k-32|0,l=Ye>>31,B=k,o=q-1>>31&M>>>(Ye>>>0)|(M<<q|L>>>(k>>>0))&l,l=l&M>>>(k>>>0),m=L<<Le&R,k=(M<<Le|L>>>(Ye>>>0))&R|L<<q&k-33>>31;break}return d|0&&(n[d>>2]=m&L,n[d+4>>2]=0),(B|0)==1?(Ye=R|l&0,Le=o|0|0,Be=Ye,Le|0):(Le=KZ(B|0)|0,Ye=M>>>(Le>>>0)|0,Le=M<<32-Le|L>>>(Le>>>0)|0,Be=Ye,Le|0)}else{if(m)return d|0&&(n[d>>2]=(M>>>0)%(B>>>0),n[d+4>>2]=0),Ye=0,Le=(M>>>0)/(B>>>0)>>>0,Be=Ye,Le|0;if(!L)return d|0&&(n[d>>2]=0,n[d+4>>2]=(M>>>0)%(k>>>0)),Ye=0,Le=(M>>>0)/(k>>>0)>>>0,Be=Ye,Le|0;if(m=k-1|0,!(m&k))return d|0&&(n[d>>2]=o|0,n[d+4>>2]=m&M|l&0),Ye=0,Le=M>>>((KZ(k|0)|0)>>>0),Be=Ye,Le|0;if(m=(b(k|0)|0)-(b(M|0)|0)|0,m>>>0<=30){l=m+1|0,k=31-m|0,B=l,o=M<<k|L>>>(l>>>0),l=M>>>(l>>>0),m=0,k=L<<k;break}return d?(n[d>>2]=o|0,n[d+4>>2]=R|l&0,Ye=0,Le=0,Be=Ye,Le|0):(Ye=0,Le=0,Be=Ye,Le|0)}while(!1);if(!B)M=k,R=0,k=0;else{q=u|0|0,L=oe|A&0,M=JM(q|0,L|0,-1,-1)|0,u=Be,R=k,k=0;do A=R,R=m>>>31|R<<1,m=k|m<<1,A=o<<1|A>>>31|0,oe=o>>>31|l<<1|0,GP(M|0,u|0,A|0,oe|0)|0,Le=Be,Ye=Le>>31|((Le|0)<0?-1:0)<<1,k=Ye&1,o=GP(A|0,oe|0,Ye&q|0,(((Le|0)<0?-1:0)>>31|((Le|0)<0?-1:0)<<1)&L|0)|0,l=Be,B=B-1|0;while(B|0);M=R,R=0}return B=0,d|0&&(n[d>>2]=o,n[d+4>>2]=l),Ye=(m|0)>>>31|(M|B)<<1|(B<<1|m>>>31)&0|R,Le=(m<<1|0)&-2|k,Be=Ye,Le|0}function zM(o,l,u,A){return o=o|0,l=l|0,u=u|0,A=A|0,JZ(o,l,u,A,0)|0}function jh(o){o=o|0;var l=0,u=0;return u=o+15&-16|0,l=n[C>>2]|0,o=l+u|0,(u|0)>0&(o|0)<(l|0)|(o|0)<0?(se()|0,cu(12),-1):(n[C>>2]=o,(o|0)>($()|0)&&!(Z()|0)?(n[C>>2]=l,cu(12),-1):l|0)}function BB(o,l,u){o=o|0,l=l|0,u=u|0;var A=0;if((l|0)<(o|0)&(o|0)<(l+u|0)){for(A=o,l=l+u|0,o=o+u|0;(u|0)>0;)o=o-1|0,l=l-1|0,u=u-1|0,s[o>>0]=s[l>>0]|0;o=A}else Qr(o,l,u)|0;return o|0}function ZM(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0;var d=0,m=0;return m=I,I=I+16|0,d=m|0,JZ(o,l,u,A,d)|0,I=m,Be=n[d+4>>2]|0,n[d>>2]|0|0}function zZ(o){return o=o|0,(o&255)<<24|(o>>8&255)<<16|(o>>16&255)<<8|o>>>24|0}function IHe(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,ZZ[o&1](l|0,u|0,A|0,d|0,m|0)}function CHe(o,l,u){o=o|0,l=l|0,u=y(u),XZ[o&1](l|0,y(u))}function wHe(o,l,u){o=o|0,l=l|0,u=+u,$Z[o&31](l|0,+u)}function BHe(o,l,u,A){return o=o|0,l=l|0,u=y(u),A=y(A),y(eX[o&0](l|0,y(u),y(A)))}function vHe(o,l){o=o|0,l=l|0,sp[o&127](l|0)}function SHe(o,l,u){o=o|0,l=l|0,u=u|0,op[o&31](l|0,u|0)}function DHe(o,l){return o=o|0,l=l|0,pd[o&31](l|0)|0}function bHe(o,l,u,A,d){o=o|0,l=l|0,u=+u,A=+A,d=d|0,tX[o&1](l|0,+u,+A,d|0)}function PHe(o,l,u,A){o=o|0,l=l|0,u=+u,A=+A,lje[o&1](l|0,+u,+A)}function xHe(o,l,u,A){return o=o|0,l=l|0,u=u|0,A=A|0,VP[o&7](l|0,u|0,A|0)|0}function kHe(o,l,u,A){return o=o|0,l=l|0,u=u|0,A=A|0,+cje[o&1](l|0,u|0,A|0)}function QHe(o,l){return o=o|0,l=l|0,+rX[o&15](l|0)}function RHe(o,l,u){return o=o|0,l=l|0,u=+u,uje[o&1](l|0,+u)|0}function THe(o,l,u){return o=o|0,l=l|0,u=u|0,$M[o&15](l|0,u|0)|0}function FHe(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=+A,d=+d,m=m|0,fje[o&1](l|0,u|0,+A,+d,m|0)}function NHe(o,l,u,A,d,m,B){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,B=B|0,Aje[o&1](l|0,u|0,A|0,d|0,m|0,B|0)}function OHe(o,l,u){return o=o|0,l=l|0,u=u|0,+nX[o&7](l|0,u|0)}function LHe(o){return o=o|0,YP[o&7]()|0}function MHe(o,l,u,A,d,m){return o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,iX[o&1](l|0,u|0,A|0,d|0,m|0)|0}function UHe(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=+d,pje[o&1](l|0,u|0,A|0,+d)}function _He(o,l,u,A,d,m,B){o=o|0,l=l|0,u=u|0,A=y(A),d=d|0,m=y(m),B=B|0,sX[o&1](l|0,u|0,y(A),d|0,y(m),B|0)}function HHe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,DB[o&15](l|0,u|0,A|0)}function jHe(o){o=o|0,oX[o&0]()}function GHe(o,l,u,A){o=o|0,l=l|0,u=u|0,A=+A,aX[o&15](l|0,u|0,+A)}function qHe(o,l,u){return o=o|0,l=+l,u=+u,hje[o&1](+l,+u)|0}function WHe(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,eU[o&15](l|0,u|0,A|0,d|0)}function VHe(o,l,u,A,d){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,F(0)}function YHe(o,l){o=o|0,l=y(l),F(1)}function nl(o,l){o=o|0,l=+l,F(2)}function KHe(o,l,u){return o=o|0,l=y(l),u=y(u),F(3),$e}function wr(o){o=o|0,F(4)}function vB(o,l){o=o|0,l=l|0,F(5)}function jl(o){return o=o|0,F(6),0}function JHe(o,l,u,A){o=o|0,l=+l,u=+u,A=A|0,F(7)}function zHe(o,l,u){o=o|0,l=+l,u=+u,F(8)}function ZHe(o,l,u){return o=o|0,l=l|0,u=u|0,F(9),0}function XHe(o,l,u){return o=o|0,l=l|0,u=u|0,F(10),0}function Ad(o){return o=o|0,F(11),0}function $He(o,l){return o=o|0,l=+l,F(12),0}function SB(o,l){return o=o|0,l=l|0,F(13),0}function eje(o,l,u,A,d){o=o|0,l=l|0,u=+u,A=+A,d=d|0,F(14)}function tje(o,l,u,A,d,m){o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,m=m|0,F(15)}function XM(o,l){return o=o|0,l=l|0,F(16),0}function rje(){return F(17),0}function nje(o,l,u,A,d){return o=o|0,l=l|0,u=u|0,A=A|0,d=d|0,F(18),0}function ije(o,l,u,A){o=o|0,l=l|0,u=u|0,A=+A,F(19)}function sje(o,l,u,A,d,m){o=o|0,l=l|0,u=y(u),A=A|0,d=y(d),m=m|0,F(20)}function WP(o,l,u){o=o|0,l=l|0,u=u|0,F(21)}function oje(){F(22)}function iE(o,l,u){o=o|0,l=l|0,u=+u,F(23)}function aje(o,l){return o=+o,l=+l,F(24),0}function sE(o,l,u,A){o=o|0,l=l|0,u=u|0,A=A|0,F(25)}var ZZ=[VHe,n_e],XZ=[YHe,Ny],$Z=[nl,zg,Rh,oB,aB,lB,cB,xf,Gy,uB,kf,Zg,Xg,fB,AB,Iu,$g,pB,qy,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl],eX=[KHe],sp=[wr,rE,LPe,MPe,UPe,hRe,gRe,dRe,RMe,TMe,FMe,qUe,WUe,VUe,A8e,p8e,h8e,xl,Jg,rB,sr,gc,xP,kP,bPe,YPe,sxe,Bxe,Uxe,rke,Eke,Fke,Jke,fQe,bQe,GQe,sRe,TRe,JRe,fTe,bTe,GTe,sFe,vFe,UFe,$Fe,gNe,dP,VNe,lOe,bOe,WOe,oLe,bLe,LLe,_Le,nMe,oMe,BMe,OMe,UMe,rUe,IUe,LJ,t4e,R4e,Y4e,l3e,k3e,W3e,r8e,s8e,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr,wr],op=[vB,_y,QL,nB,iB,xr,fo,Zi,Ms,Ss,jy,Qh,gB,CP,rd,FL,NL,wP,BP,ML,Qf,ne,PFe,jFe,JOe,i4e,PUe,CZ,vB,vB,vB,vB],pd=[jl,G8e,My,td,Vy,Ea,mP,Th,hB,TL,EP,Yy,vP,UL,zy,yNe,uLe,sUe,l4e,Ul,jl,jl,jl,jl,jl,jl,jl,jl,jl,jl,jl,jl],tX=[JHe,WL],lje=[zHe,DMe],VP=[ZHe,NZ,q8e,Y8e,oke,LRe,zNe,A3e],cje=[XHe,QQe],rX=[Ad,Fh,IP,ep,VL,v,D,Q,H,V,Ad,Ad,Ad,Ad,Ad,Ad],uje=[$He,FLe],$M=[SB,hHe,SP,QPe,bxe,wke,Lke,cRe,$Re,nNe,Oy,Z4e,SB,SB,SB,SB],fje=[eje,cxe],Aje=[tje,F3e],nX=[XM,OL,ve,_e,ht,YQe,XM,XM],YP=[rje,Wt,Ly,gP,qLe,uMe,GMe,c8e],iX=[nje,Py],pje=[ije,QTe],sX=[sje,_L],DB=[WP,No,yP,LL,wu,Gxe,Xke,YTe,cFe,kL,D_e,O4e,J3e,WP,WP,WP],oX=[oje],aX=[iE,RL,Hy,$A,sB,Cu,Wy,ed,gTe,AOe,kLe,iE,iE,iE,iE,iE],hje=[aje,kMe],eU=[sE,gQe,DNe,QOe,ELe,zLe,dMe,zMe,SUe,h4e,I8e,sE,sE,sE,sE,sE];return{_llvm_bswap_i32:zZ,dynCall_idd:qHe,dynCall_i:LHe,_i64Subtract:GP,___udivdi3:zM,dynCall_vif:CHe,setThrew:pa,dynCall_viii:HHe,_bitshift64Lshr:qP,_bitshift64Shl:YZ,dynCall_vi:vHe,dynCall_viiddi:FHe,dynCall_diii:kHe,dynCall_iii:THe,_memset:nE,_sbrk:jh,_memcpy:Qr,__GLOBAL__sub_I_Yoga_cpp:$1,dynCall_vii:SHe,___uremdi3:ZM,dynCall_vid:wHe,stackAlloc:Va,_nbind_init:Q8e,getTempRet0:UA,dynCall_di:QHe,dynCall_iid:RHe,setTempRet0:MA,_i64Add:JM,dynCall_fiff:BHe,dynCall_iiii:xHe,_emscripten_get_global_libc:j8e,dynCall_viid:GHe,dynCall_viiid:UHe,dynCall_viififi:_He,dynCall_ii:DHe,__GLOBAL__sub_I_Binding_cc:Y_e,dynCall_viiii:WHe,dynCall_iiiiii:MHe,stackSave:df,dynCall_viiiii:IHe,__GLOBAL__sub_I_nbind_cc:Sr,dynCall_vidd:PHe,_free:HP,runPostSets:EHe,dynCall_viiiiii:NHe,establishStackSpace:vn,_memmove:BB,stackRestore:cc,_malloc:_P,__GLOBAL__sub_I_common_cc:pUe,dynCall_viddi:bHe,dynCall_dii:OHe,dynCall_v:jHe}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(e){this.name=\"ExitStatus\",this.message=\"Program terminated with exit(\"+e+\")\",this.status=e}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function e(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=e)},Module.callMain=Module.callMain=function e(t){t=t||[],ensureInitRuntime();var r=t.length+1;function s(){for(var p=0;p<3;p++)a.push(0)}var a=[allocate(intArrayFromString(Module.thisProgram),\"i8\",ALLOC_NORMAL)];s();for(var n=0;n<r-1;n=n+1)a.push(allocate(intArrayFromString(t[n]),\"i8\",ALLOC_NORMAL)),s();a.push(0),a=allocate(a,\"i32\",ALLOC_NORMAL);try{var c=Module._main(r,a,0);exit(c,!0)}catch(p){if(p instanceof ExitStatus)return;if(p==\"SimulateInfiniteLoop\"){Module.noExitRuntime=!0;return}else{var f=p;p&&typeof p==\"object\"&&p.stack&&(f=[p,p.stack]),Module.printErr(\"exception thrown: \"+f),Module.quit(1,p)}}finally{calledMain=!0}};function run(e){if(e=e||Module.arguments,preloadStartTime===null&&(preloadStartTime=Date.now()),runDependencies>0||(preRun(),runDependencies>0)||Module.calledRun)return;function t(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(e),postRun()))}Module.setStatus?(Module.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){Module.setStatus(\"\")},1),t()},1)):t()}Module.run=Module.run=run;function exit(e,t){t&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=e,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(e)),ENVIRONMENT_IS_NODE&&process.exit(e),Module.quit(e,new ExitStatus(e)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(e){Module.onAbort&&Module.onAbort(e),e!==void 0?(Module.print(e),Module.printErr(e),e=JSON.stringify(e)):e=\"\",ABORT=!0,EXITSTATUS=1;var t=`\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,r=\"abort(\"+e+\") at \"+stackTrace()+t;throw abortDecorators&&abortDecorators.forEach(function(s){r=s(r,e)}),r}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit==\"function\"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var Lm=G((RYt,IIe)=>{\"use strict\";var Hut=yIe(),jut=EIe(),A9=!1,p9=null;jut({},function(e,t){if(!A9){if(A9=!0,e)throw e;p9=t}});if(!A9)throw new Error(\"Failed to load the yoga module - it needed to be loaded synchronously, but didn't\");IIe.exports=Hut(p9.bind,p9.lib)});var g9=G((TYt,h9)=>{\"use strict\";var CIe=e=>Number.isNaN(e)?!1:e>=4352&&(e<=4447||e===9001||e===9002||11904<=e&&e<=12871&&e!==12351||12880<=e&&e<=19903||19968<=e&&e<=42182||43360<=e&&e<=43388||44032<=e&&e<=55203||63744<=e&&e<=64255||65040<=e&&e<=65049||65072<=e&&e<=65131||65281<=e&&e<=65376||65504<=e&&e<=65510||110592<=e&&e<=110593||127488<=e&&e<=127569||131072<=e&&e<=262141);h9.exports=CIe;h9.exports.default=CIe});var BIe=G((FYt,wIe)=>{\"use strict\";wIe.exports=function(){return/\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62(?:\\uDB40\\uDC65\\uDB40\\uDC6E\\uDB40\\uDC67|\\uDB40\\uDC73\\uDB40\\uDC63\\uDB40\\uDC74|\\uDB40\\uDC77\\uDB40\\uDC6C\\uDB40\\uDC73)\\uDB40\\uDC7F|\\uD83D\\uDC68(?:\\uD83C\\uDFFC\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C\\uDFFB|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFF\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFE])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFE\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFD])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFD\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFC])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\u200D(?:\\u2764\\uFE0F\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83D\\uDC68|(?:\\uD83D[\\uDC68\\uDC69])\\u200D(?:\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67]))|\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67])|(?:\\uD83D[\\uDC68\\uDC69])\\u200D(?:\\uD83D[\\uDC66\\uDC67])|[\\u2695\\u2696\\u2708]\\uFE0F|\\uD83D[\\uDC66\\uDC67]|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|(?:\\uD83C\\uDFFB\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFF\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFE\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFD\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFC\\u200D[\\u2695\\u2696\\u2708])\\uFE0F|\\uD83C\\uDFFB\\u200D(?:\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C[\\uDFFB-\\uDFFF])|(?:\\uD83E\\uDDD1\\uD83C\\uDFFB\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFC\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)\\uD83C\\uDFFB|\\uD83E\\uDDD1(?:\\uD83C\\uDFFF\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1(?:\\uD83C[\\uDFFB-\\uDFFF])|\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1)|(?:\\uD83E\\uDDD1\\uD83C\\uDFFE\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFF\\u200D\\uD83E\\uDD1D\\u200D(?:\\uD83D[\\uDC68\\uDC69]))(?:\\uD83C[\\uDFFB-\\uDFFE])|(?:\\uD83E\\uDDD1\\uD83C\\uDFFC\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFD\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)(?:\\uD83C[\\uDFFB\\uDFFC])|\\uD83D\\uDC69(?:\\uD83C\\uDFFE\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFC\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFB\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFC-\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFD\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\u200D(?:\\u2764\\uFE0F\\u200D(?:\\uD83D\\uDC8B\\u200D(?:\\uD83D[\\uDC68\\uDC69])|\\uD83D[\\uDC68\\uDC69])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFF\\u200D(?:\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD]))|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D(?:\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67]))|(?:\\uD83E\\uDDD1\\uD83C\\uDFFD\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFE\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)(?:\\uD83C[\\uDFFB-\\uDFFD])|\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D(?:\\uD83D[\\uDC66\\uDC67])|(?:\\uD83D\\uDC41\\uFE0F\\u200D\\uD83D\\uDDE8|\\uD83D\\uDC69(?:\\uD83C\\uDFFF\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFE\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFC\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFB\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFD\\u200D[\\u2695\\u2696\\u2708]|\\u200D[\\u2695\\u2696\\u2708])|(?:(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)\\uFE0F|\\uD83D\\uDC6F|\\uD83E[\\uDD3C\\uDDDE\\uDDDF])\\u200D[\\u2640\\u2642]|(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)(?:\\uD83C[\\uDFFB-\\uDFFF])\\u200D[\\u2640\\u2642]|(?:\\uD83C[\\uDFC3\\uDFC4\\uDFCA]|\\uD83D[\\uDC6E\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4-\\uDEB6]|\\uD83E[\\uDD26\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD-\\uDDCF\\uDDD6-\\uDDDD])(?:(?:\\uD83C[\\uDFFB-\\uDFFF])\\u200D[\\u2640\\u2642]|\\u200D[\\u2640\\u2642])|\\uD83C\\uDFF4\\u200D\\u2620)\\uFE0F|\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67])|\\uD83C\\uDFF3\\uFE0F\\u200D\\uD83C\\uDF08|\\uD83D\\uDC15\\u200D\\uD83E\\uDDBA|\\uD83D\\uDC69\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83C\\uDDFD\\uD83C\\uDDF0|\\uD83C\\uDDF4\\uD83C\\uDDF2|\\uD83C\\uDDF6\\uD83C\\uDDE6|[#\\*0-9]\\uFE0F\\u20E3|\\uD83C\\uDDE7(?:\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEF\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9\\uDDFB\\uDDFC\\uDDFE\\uDDFF])|\\uD83C\\uDDF9(?:\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDED\\uDDEF-\\uDDF4\\uDDF7\\uDDF9\\uDDFB\\uDDFC\\uDDFF])|\\uD83C\\uDDEA(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDED\\uDDF7-\\uDDFA])|\\uD83E\\uDDD1(?:\\uD83C[\\uDFFB-\\uDFFF])|\\uD83C\\uDDF7(?:\\uD83C[\\uDDEA\\uDDF4\\uDDF8\\uDDFA\\uDDFC])|\\uD83D\\uDC69(?:\\uD83C[\\uDFFB-\\uDFFF])|\\uD83C\\uDDF2(?:\\uD83C[\\uDDE6\\uDDE8-\\uDDED\\uDDF0-\\uDDFF])|\\uD83C\\uDDE6(?:\\uD83C[\\uDDE8-\\uDDEC\\uDDEE\\uDDF1\\uDDF2\\uDDF4\\uDDF6-\\uDDFA\\uDDFC\\uDDFD\\uDDFF])|\\uD83C\\uDDF0(?:\\uD83C[\\uDDEA\\uDDEC-\\uDDEE\\uDDF2\\uDDF3\\uDDF5\\uDDF7\\uDDFC\\uDDFE\\uDDFF])|\\uD83C\\uDDED(?:\\uD83C[\\uDDF0\\uDDF2\\uDDF3\\uDDF7\\uDDF9\\uDDFA])|\\uD83C\\uDDE9(?:\\uD83C[\\uDDEA\\uDDEC\\uDDEF\\uDDF0\\uDDF2\\uDDF4\\uDDFF])|\\uD83C\\uDDFE(?:\\uD83C[\\uDDEA\\uDDF9])|\\uD83C\\uDDEC(?:\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEE\\uDDF1-\\uDDF3\\uDDF5-\\uDDFA\\uDDFC\\uDDFE])|\\uD83C\\uDDF8(?:\\uD83C[\\uDDE6-\\uDDEA\\uDDEC-\\uDDF4\\uDDF7-\\uDDF9\\uDDFB\\uDDFD-\\uDDFF])|\\uD83C\\uDDEB(?:\\uD83C[\\uDDEE-\\uDDF0\\uDDF2\\uDDF4\\uDDF7])|\\uD83C\\uDDF5(?:\\uD83C[\\uDDE6\\uDDEA-\\uDDED\\uDDF0-\\uDDF3\\uDDF7-\\uDDF9\\uDDFC\\uDDFE])|\\uD83C\\uDDFB(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDEE\\uDDF3\\uDDFA])|\\uD83C\\uDDF3(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA-\\uDDEC\\uDDEE\\uDDF1\\uDDF4\\uDDF5\\uDDF7\\uDDFA\\uDDFF])|\\uD83C\\uDDE8(?:\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDEE\\uDDF0-\\uDDF5\\uDDF7\\uDDFA-\\uDDFF])|\\uD83C\\uDDF1(?:\\uD83C[\\uDDE6-\\uDDE8\\uDDEE\\uDDF0\\uDDF7-\\uDDFB\\uDDFE])|\\uD83C\\uDDFF(?:\\uD83C[\\uDDE6\\uDDF2\\uDDFC])|\\uD83C\\uDDFC(?:\\uD83C[\\uDDEB\\uDDF8])|\\uD83C\\uDDFA(?:\\uD83C[\\uDDE6\\uDDEC\\uDDF2\\uDDF3\\uDDF8\\uDDFE\\uDDFF])|\\uD83C\\uDDEE(?:\\uD83C[\\uDDE8-\\uDDEA\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9])|\\uD83C\\uDDEF(?:\\uD83C[\\uDDEA\\uDDF2\\uDDF4\\uDDF5])|(?:\\uD83C[\\uDFC3\\uDFC4\\uDFCA]|\\uD83D[\\uDC6E\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4-\\uDEB6]|\\uD83E[\\uDD26\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD-\\uDDCF\\uDDD6-\\uDDDD])(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:[\\u261D\\u270A-\\u270D]|\\uD83C[\\uDF85\\uDFC2\\uDFC7]|\\uD83D[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66\\uDC67\\uDC6B-\\uDC6D\\uDC70\\uDC72\\uDC74-\\uDC76\\uDC78\\uDC7C\\uDC83\\uDC85\\uDCAA\\uDD74\\uDD7A\\uDD90\\uDD95\\uDD96\\uDE4C\\uDE4F\\uDEC0\\uDECC]|\\uD83E[\\uDD0F\\uDD18-\\uDD1C\\uDD1E\\uDD1F\\uDD30-\\uDD36\\uDDB5\\uDDB6\\uDDBB\\uDDD2-\\uDDD5])(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:[\\u231A\\u231B\\u23E9-\\u23EC\\u23F0\\u23F3\\u25FD\\u25FE\\u2614\\u2615\\u2648-\\u2653\\u267F\\u2693\\u26A1\\u26AA\\u26AB\\u26BD\\u26BE\\u26C4\\u26C5\\u26CE\\u26D4\\u26EA\\u26F2\\u26F3\\u26F5\\u26FA\\u26FD\\u2705\\u270A\\u270B\\u2728\\u274C\\u274E\\u2753-\\u2755\\u2757\\u2795-\\u2797\\u27B0\\u27BF\\u2B1B\\u2B1C\\u2B50\\u2B55]|\\uD83C[\\uDC04\\uDCCF\\uDD8E\\uDD91-\\uDD9A\\uDDE6-\\uDDFF\\uDE01\\uDE1A\\uDE2F\\uDE32-\\uDE36\\uDE38-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF20\\uDF2D-\\uDF35\\uDF37-\\uDF7C\\uDF7E-\\uDF93\\uDFA0-\\uDFCA\\uDFCF-\\uDFD3\\uDFE0-\\uDFF0\\uDFF4\\uDFF8-\\uDFFF]|\\uD83D[\\uDC00-\\uDC3E\\uDC40\\uDC42-\\uDCFC\\uDCFF-\\uDD3D\\uDD4B-\\uDD4E\\uDD50-\\uDD67\\uDD7A\\uDD95\\uDD96\\uDDA4\\uDDFB-\\uDE4F\\uDE80-\\uDEC5\\uDECC\\uDED0-\\uDED2\\uDED5\\uDEEB\\uDEEC\\uDEF4-\\uDEFA\\uDFE0-\\uDFEB]|\\uD83E[\\uDD0D-\\uDD3A\\uDD3C-\\uDD45\\uDD47-\\uDD71\\uDD73-\\uDD76\\uDD7A-\\uDDA2\\uDDA5-\\uDDAA\\uDDAE-\\uDDCA\\uDDCD-\\uDDFF\\uDE70-\\uDE73\\uDE78-\\uDE7A\\uDE80-\\uDE82\\uDE90-\\uDE95])|(?:[#\\*0-9\\xA9\\xAE\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9\\u21AA\\u231A\\u231B\\u2328\\u23CF\\u23E9-\\u23F3\\u23F8-\\u23FA\\u24C2\\u25AA\\u25AB\\u25B6\\u25C0\\u25FB-\\u25FE\\u2600-\\u2604\\u260E\\u2611\\u2614\\u2615\\u2618\\u261D\\u2620\\u2622\\u2623\\u2626\\u262A\\u262E\\u262F\\u2638-\\u263A\\u2640\\u2642\\u2648-\\u2653\\u265F\\u2660\\u2663\\u2665\\u2666\\u2668\\u267B\\u267E\\u267F\\u2692-\\u2697\\u2699\\u269B\\u269C\\u26A0\\u26A1\\u26AA\\u26AB\\u26B0\\u26B1\\u26BD\\u26BE\\u26C4\\u26C5\\u26C8\\u26CE\\u26CF\\u26D1\\u26D3\\u26D4\\u26E9\\u26EA\\u26F0-\\u26F5\\u26F7-\\u26FA\\u26FD\\u2702\\u2705\\u2708-\\u270D\\u270F\\u2712\\u2714\\u2716\\u271D\\u2721\\u2728\\u2733\\u2734\\u2744\\u2747\\u274C\\u274E\\u2753-\\u2755\\u2757\\u2763\\u2764\\u2795-\\u2797\\u27A1\\u27B0\\u27BF\\u2934\\u2935\\u2B05-\\u2B07\\u2B1B\\u2B1C\\u2B50\\u2B55\\u3030\\u303D\\u3297\\u3299]|\\uD83C[\\uDC04\\uDCCF\\uDD70\\uDD71\\uDD7E\\uDD7F\\uDD8E\\uDD91-\\uDD9A\\uDDE6-\\uDDFF\\uDE01\\uDE02\\uDE1A\\uDE2F\\uDE32-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF21\\uDF24-\\uDF93\\uDF96\\uDF97\\uDF99-\\uDF9B\\uDF9E-\\uDFF0\\uDFF3-\\uDFF5\\uDFF7-\\uDFFF]|\\uD83D[\\uDC00-\\uDCFD\\uDCFF-\\uDD3D\\uDD49-\\uDD4E\\uDD50-\\uDD67\\uDD6F\\uDD70\\uDD73-\\uDD7A\\uDD87\\uDD8A-\\uDD8D\\uDD90\\uDD95\\uDD96\\uDDA4\\uDDA5\\uDDA8\\uDDB1\\uDDB2\\uDDBC\\uDDC2-\\uDDC4\\uDDD1-\\uDDD3\\uDDDC-\\uDDDE\\uDDE1\\uDDE3\\uDDE8\\uDDEF\\uDDF3\\uDDFA-\\uDE4F\\uDE80-\\uDEC5\\uDECB-\\uDED2\\uDED5\\uDEE0-\\uDEE5\\uDEE9\\uDEEB\\uDEEC\\uDEF0\\uDEF3-\\uDEFA\\uDFE0-\\uDFEB]|\\uD83E[\\uDD0D-\\uDD3A\\uDD3C-\\uDD45\\uDD47-\\uDD71\\uDD73-\\uDD76\\uDD7A-\\uDDA2\\uDDA5-\\uDDAA\\uDDAE-\\uDDCA\\uDDCD-\\uDDFF\\uDE70-\\uDE73\\uDE78-\\uDE7A\\uDE80-\\uDE82\\uDE90-\\uDE95])\\uFE0F|(?:[\\u261D\\u26F9\\u270A-\\u270D]|\\uD83C[\\uDF85\\uDFC2-\\uDFC4\\uDFC7\\uDFCA-\\uDFCC]|\\uD83D[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66-\\uDC78\\uDC7C\\uDC81-\\uDC83\\uDC85-\\uDC87\\uDC8F\\uDC91\\uDCAA\\uDD74\\uDD75\\uDD7A\\uDD90\\uDD95\\uDD96\\uDE45-\\uDE47\\uDE4B-\\uDE4F\\uDEA3\\uDEB4-\\uDEB6\\uDEC0\\uDECC]|\\uD83E[\\uDD0F\\uDD18-\\uDD1F\\uDD26\\uDD30-\\uDD39\\uDD3C-\\uDD3E\\uDDB5\\uDDB6\\uDDB8\\uDDB9\\uDDBB\\uDDCD-\\uDDCF\\uDDD1-\\uDDDD])/g}});var GS=G((NYt,d9)=>{\"use strict\";var Gut=gk(),qut=g9(),Wut=BIe(),vIe=e=>{if(typeof e!=\"string\"||e.length===0||(e=Gut(e),e.length===0))return 0;e=e.replace(Wut(),\"  \");let t=0;for(let r=0;r<e.length;r++){let s=e.codePointAt(r);s<=31||s>=127&&s<=159||s>=768&&s<=879||(s>65535&&r++,t+=qut(s)?2:1)}return t};d9.exports=vIe;d9.exports.default=vIe});var y9=G((OYt,m9)=>{\"use strict\";var Vut=GS(),SIe=e=>{let t=0;for(let r of e.split(`\n`))t=Math.max(t,Vut(r));return t};m9.exports=SIe;m9.exports.default=SIe});var DIe=G(qS=>{\"use strict\";var Yut=qS&&qS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(qS,\"__esModule\",{value:!0});var Kut=Yut(y9()),E9={};qS.default=e=>{if(e.length===0)return{width:0,height:0};if(E9[e])return E9[e];let t=Kut.default(e),r=e.split(`\n`).length;return E9[e]={width:t,height:r},{width:t,height:r}}});var bIe=G(WS=>{\"use strict\";var Jut=WS&&WS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(WS,\"__esModule\",{value:!0});var xn=Jut(Lm()),zut=(e,t)=>{\"position\"in t&&e.setPositionType(t.position===\"absolute\"?xn.default.POSITION_TYPE_ABSOLUTE:xn.default.POSITION_TYPE_RELATIVE)},Zut=(e,t)=>{\"marginLeft\"in t&&e.setMargin(xn.default.EDGE_START,t.marginLeft||0),\"marginRight\"in t&&e.setMargin(xn.default.EDGE_END,t.marginRight||0),\"marginTop\"in t&&e.setMargin(xn.default.EDGE_TOP,t.marginTop||0),\"marginBottom\"in t&&e.setMargin(xn.default.EDGE_BOTTOM,t.marginBottom||0)},Xut=(e,t)=>{\"paddingLeft\"in t&&e.setPadding(xn.default.EDGE_LEFT,t.paddingLeft||0),\"paddingRight\"in t&&e.setPadding(xn.default.EDGE_RIGHT,t.paddingRight||0),\"paddingTop\"in t&&e.setPadding(xn.default.EDGE_TOP,t.paddingTop||0),\"paddingBottom\"in t&&e.setPadding(xn.default.EDGE_BOTTOM,t.paddingBottom||0)},$ut=(e,t)=>{var r;\"flexGrow\"in t&&e.setFlexGrow((r=t.flexGrow)!==null&&r!==void 0?r:0),\"flexShrink\"in t&&e.setFlexShrink(typeof t.flexShrink==\"number\"?t.flexShrink:1),\"flexDirection\"in t&&(t.flexDirection===\"row\"&&e.setFlexDirection(xn.default.FLEX_DIRECTION_ROW),t.flexDirection===\"row-reverse\"&&e.setFlexDirection(xn.default.FLEX_DIRECTION_ROW_REVERSE),t.flexDirection===\"column\"&&e.setFlexDirection(xn.default.FLEX_DIRECTION_COLUMN),t.flexDirection===\"column-reverse\"&&e.setFlexDirection(xn.default.FLEX_DIRECTION_COLUMN_REVERSE)),\"flexBasis\"in t&&(typeof t.flexBasis==\"number\"?e.setFlexBasis(t.flexBasis):typeof t.flexBasis==\"string\"?e.setFlexBasisPercent(Number.parseInt(t.flexBasis,10)):e.setFlexBasis(NaN)),\"alignItems\"in t&&((t.alignItems===\"stretch\"||!t.alignItems)&&e.setAlignItems(xn.default.ALIGN_STRETCH),t.alignItems===\"flex-start\"&&e.setAlignItems(xn.default.ALIGN_FLEX_START),t.alignItems===\"center\"&&e.setAlignItems(xn.default.ALIGN_CENTER),t.alignItems===\"flex-end\"&&e.setAlignItems(xn.default.ALIGN_FLEX_END)),\"alignSelf\"in t&&((t.alignSelf===\"auto\"||!t.alignSelf)&&e.setAlignSelf(xn.default.ALIGN_AUTO),t.alignSelf===\"flex-start\"&&e.setAlignSelf(xn.default.ALIGN_FLEX_START),t.alignSelf===\"center\"&&e.setAlignSelf(xn.default.ALIGN_CENTER),t.alignSelf===\"flex-end\"&&e.setAlignSelf(xn.default.ALIGN_FLEX_END)),\"justifyContent\"in t&&((t.justifyContent===\"flex-start\"||!t.justifyContent)&&e.setJustifyContent(xn.default.JUSTIFY_FLEX_START),t.justifyContent===\"center\"&&e.setJustifyContent(xn.default.JUSTIFY_CENTER),t.justifyContent===\"flex-end\"&&e.setJustifyContent(xn.default.JUSTIFY_FLEX_END),t.justifyContent===\"space-between\"&&e.setJustifyContent(xn.default.JUSTIFY_SPACE_BETWEEN),t.justifyContent===\"space-around\"&&e.setJustifyContent(xn.default.JUSTIFY_SPACE_AROUND))},eft=(e,t)=>{var r,s;\"width\"in t&&(typeof t.width==\"number\"?e.setWidth(t.width):typeof t.width==\"string\"?e.setWidthPercent(Number.parseInt(t.width,10)):e.setWidthAuto()),\"height\"in t&&(typeof t.height==\"number\"?e.setHeight(t.height):typeof t.height==\"string\"?e.setHeightPercent(Number.parseInt(t.height,10)):e.setHeightAuto()),\"minWidth\"in t&&(typeof t.minWidth==\"string\"?e.setMinWidthPercent(Number.parseInt(t.minWidth,10)):e.setMinWidth((r=t.minWidth)!==null&&r!==void 0?r:0)),\"minHeight\"in t&&(typeof t.minHeight==\"string\"?e.setMinHeightPercent(Number.parseInt(t.minHeight,10)):e.setMinHeight((s=t.minHeight)!==null&&s!==void 0?s:0))},tft=(e,t)=>{\"display\"in t&&e.setDisplay(t.display===\"flex\"?xn.default.DISPLAY_FLEX:xn.default.DISPLAY_NONE)},rft=(e,t)=>{if(\"borderStyle\"in t){let r=typeof t.borderStyle==\"string\"?1:0;e.setBorder(xn.default.EDGE_TOP,r),e.setBorder(xn.default.EDGE_BOTTOM,r),e.setBorder(xn.default.EDGE_LEFT,r),e.setBorder(xn.default.EDGE_RIGHT,r)}};WS.default=(e,t={})=>{zut(e,t),Zut(e,t),Xut(e,t),$ut(e,t),eft(e,t),tft(e,t),rft(e,t)}});var kIe=G((UYt,xIe)=>{\"use strict\";var VS=GS(),nft=gk(),ift=ik(),C9=new Set([\"\\x1B\",\"\\x9B\"]),sft=39,PIe=e=>`${C9.values().next().value}[${e}m`,oft=e=>e.split(\" \").map(t=>VS(t)),I9=(e,t,r)=>{let s=[...t],a=!1,n=VS(nft(e[e.length-1]));for(let[c,f]of s.entries()){let p=VS(f);if(n+p<=r?e[e.length-1]+=f:(e.push(f),n=0),C9.has(f))a=!0;else if(a&&f===\"m\"){a=!1;continue}a||(n+=p,n===r&&c<s.length-1&&(e.push(\"\"),n=0))}!n&&e[e.length-1].length>0&&e.length>1&&(e[e.length-2]+=e.pop())},aft=e=>{let t=e.split(\" \"),r=t.length;for(;r>0&&!(VS(t[r-1])>0);)r--;return r===t.length?e:t.slice(0,r).join(\" \")+t.slice(r).join(\"\")},lft=(e,t,r={})=>{if(r.trim!==!1&&e.trim()===\"\")return\"\";let s=\"\",a=\"\",n,c=oft(e),f=[\"\"];for(let[p,h]of e.split(\" \").entries()){r.trim!==!1&&(f[f.length-1]=f[f.length-1].trimLeft());let E=VS(f[f.length-1]);if(p!==0&&(E>=t&&(r.wordWrap===!1||r.trim===!1)&&(f.push(\"\"),E=0),(E>0||r.trim===!1)&&(f[f.length-1]+=\" \",E++)),r.hard&&c[p]>t){let C=t-E,S=1+Math.floor((c[p]-C-1)/t);Math.floor((c[p]-1)/t)<S&&f.push(\"\"),I9(f,h,t);continue}if(E+c[p]>t&&E>0&&c[p]>0){if(r.wordWrap===!1&&E<t){I9(f,h,t);continue}f.push(\"\")}if(E+c[p]>t&&r.wordWrap===!1){I9(f,h,t);continue}f[f.length-1]+=h}r.trim!==!1&&(f=f.map(aft)),s=f.join(`\n`);for(let[p,h]of[...s].entries()){if(a+=h,C9.has(h)){let C=parseFloat(/\\d[^m]*/.exec(s.slice(p,p+4)));n=C===sft?null:C}let E=ift.codes.get(Number(n));n&&E&&(s[p+1]===`\n`?a+=PIe(E):h===`\n`&&(a+=PIe(n)))}return a};xIe.exports=(e,t,r)=>String(e).normalize().replace(/\\r\\n/g,`\n`).split(`\n`).map(s=>lft(s,t,r)).join(`\n`)});var TIe=G((_Yt,RIe)=>{\"use strict\";var QIe=\"[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]\",cft=e=>e&&e.exact?new RegExp(`^${QIe}$`):new RegExp(QIe,\"g\");RIe.exports=cft});var w9=G((HYt,LIe)=>{\"use strict\";var uft=g9(),fft=TIe(),FIe=ik(),OIe=[\"\\x1B\",\"\\x9B\"],EF=e=>`${OIe[0]}[${e}m`,NIe=(e,t,r)=>{let s=[];e=[...e];for(let a of e){let n=a;a.match(\";\")&&(a=a.split(\";\")[0][0]+\"0\");let c=FIe.codes.get(parseInt(a,10));if(c){let f=e.indexOf(c.toString());f>=0?e.splice(f,1):s.push(EF(t?c:n))}else if(t){s.push(EF(0));break}else s.push(EF(n))}if(t&&(s=s.filter((a,n)=>s.indexOf(a)===n),r!==void 0)){let a=EF(FIe.codes.get(parseInt(r,10)));s=s.reduce((n,c)=>c===a?[c,...n]:[...n,c],[])}return s.join(\"\")};LIe.exports=(e,t,r)=>{let s=[...e.normalize()],a=[];r=typeof r==\"number\"?r:s.length;let n=!1,c,f=0,p=\"\";for(let[h,E]of s.entries()){let C=!1;if(OIe.includes(E)){let S=/\\d[^m]*/.exec(e.slice(h,h+18));c=S&&S.length>0?S[0]:void 0,f<r&&(n=!0,c!==void 0&&a.push(c))}else n&&E===\"m\"&&(n=!1,C=!0);if(!n&&!C&&++f,!fft({exact:!0}).test(E)&&uft(E.codePointAt())&&++f,f>t&&f<=r)p+=E;else if(f===t&&!n&&c!==void 0)p=NIe(a);else if(f>=r){p+=NIe(a,!0,c);break}}return p}});var UIe=G((jYt,MIe)=>{\"use strict\";var Z0=w9(),Aft=GS();function IF(e,t,r){if(e.charAt(t)===\" \")return t;for(let s=1;s<=3;s++)if(r){if(e.charAt(t+s)===\" \")return t+s}else if(e.charAt(t-s)===\" \")return t-s;return t}MIe.exports=(e,t,r)=>{r={position:\"end\",preferTruncationOnSpace:!1,...r};let{position:s,space:a,preferTruncationOnSpace:n}=r,c=\"\\u2026\",f=1;if(typeof e!=\"string\")throw new TypeError(`Expected \\`input\\` to be a string, got ${typeof e}`);if(typeof t!=\"number\")throw new TypeError(`Expected \\`columns\\` to be a number, got ${typeof t}`);if(t<1)return\"\";if(t===1)return c;let p=Aft(e);if(p<=t)return e;if(s===\"start\"){if(n){let h=IF(e,p-t+1,!0);return c+Z0(e,h,p).trim()}return a===!0&&(c+=\" \",f=2),c+Z0(e,p-t+f,p)}if(s===\"middle\"){a===!0&&(c=\" \"+c+\" \",f=3);let h=Math.floor(t/2);if(n){let E=IF(e,h),C=IF(e,p-(t-h)+1,!0);return Z0(e,0,E)+c+Z0(e,C,p).trim()}return Z0(e,0,h)+c+Z0(e,p-(t-h)+f,p)}if(s===\"end\"){if(n){let h=IF(e,t-1);return Z0(e,0,h)+c}return a===!0&&(c=\" \"+c,f=2),Z0(e,0,t-f)+c}throw new Error(`Expected \\`options.position\\` to be either \\`start\\`, \\`middle\\` or \\`end\\`, got ${s}`)}});var v9=G(YS=>{\"use strict\";var _Ie=YS&&YS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(YS,\"__esModule\",{value:!0});var pft=_Ie(kIe()),hft=_Ie(UIe()),B9={};YS.default=(e,t,r)=>{let s=e+String(t)+String(r);if(B9[s])return B9[s];let a=e;if(r===\"wrap\"&&(a=pft.default(e,t,{trim:!1,hard:!0})),r.startsWith(\"truncate\")){let n=\"end\";r===\"truncate-middle\"&&(n=\"middle\"),r===\"truncate-start\"&&(n=\"start\"),a=hft.default(e,t,{position:n})}return B9[s]=a,a}});var D9=G(S9=>{\"use strict\";Object.defineProperty(S9,\"__esModule\",{value:!0});var HIe=e=>{let t=\"\";if(e.childNodes.length>0)for(let r of e.childNodes){let s=\"\";r.nodeName===\"#text\"?s=r.nodeValue:((r.nodeName===\"ink-text\"||r.nodeName===\"ink-virtual-text\")&&(s=HIe(r)),s.length>0&&typeof r.internal_transform==\"function\"&&(s=r.internal_transform(s))),t+=s}return t};S9.default=HIe});var b9=G(bi=>{\"use strict\";var KS=bi&&bi.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(bi,\"__esModule\",{value:!0});bi.setTextNodeValue=bi.createTextNode=bi.setStyle=bi.setAttribute=bi.removeChildNode=bi.insertBeforeNode=bi.appendChildNode=bi.createNode=bi.TEXT_NAME=void 0;var gft=KS(Lm()),jIe=KS(DIe()),dft=KS(bIe()),mft=KS(v9()),yft=KS(D9());bi.TEXT_NAME=\"#text\";bi.createNode=e=>{var t;let r={nodeName:e,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:e===\"ink-virtual-text\"?void 0:gft.default.Node.create()};return e===\"ink-text\"&&((t=r.yogaNode)===null||t===void 0||t.setMeasureFunc(Eft.bind(null,r))),r};bi.appendChildNode=(e,t)=>{var r;t.parentNode&&bi.removeChildNode(t.parentNode,t),t.parentNode=e,e.childNodes.push(t),t.yogaNode&&((r=e.yogaNode)===null||r===void 0||r.insertChild(t.yogaNode,e.yogaNode.getChildCount())),(e.nodeName===\"ink-text\"||e.nodeName===\"ink-virtual-text\")&&CF(e)};bi.insertBeforeNode=(e,t,r)=>{var s,a;t.parentNode&&bi.removeChildNode(t.parentNode,t),t.parentNode=e;let n=e.childNodes.indexOf(r);if(n>=0){e.childNodes.splice(n,0,t),t.yogaNode&&((s=e.yogaNode)===null||s===void 0||s.insertChild(t.yogaNode,n));return}e.childNodes.push(t),t.yogaNode&&((a=e.yogaNode)===null||a===void 0||a.insertChild(t.yogaNode,e.yogaNode.getChildCount())),(e.nodeName===\"ink-text\"||e.nodeName===\"ink-virtual-text\")&&CF(e)};bi.removeChildNode=(e,t)=>{var r,s;t.yogaNode&&((s=(r=t.parentNode)===null||r===void 0?void 0:r.yogaNode)===null||s===void 0||s.removeChild(t.yogaNode)),t.parentNode=null;let a=e.childNodes.indexOf(t);a>=0&&e.childNodes.splice(a,1),(e.nodeName===\"ink-text\"||e.nodeName===\"ink-virtual-text\")&&CF(e)};bi.setAttribute=(e,t,r)=>{e.attributes[t]=r};bi.setStyle=(e,t)=>{e.style=t,e.yogaNode&&dft.default(e.yogaNode,t)};bi.createTextNode=e=>{let t={nodeName:\"#text\",nodeValue:e,yogaNode:void 0,parentNode:null,style:{}};return bi.setTextNodeValue(t,e),t};var Eft=function(e,t){var r,s;let a=e.nodeName===\"#text\"?e.nodeValue:yft.default(e),n=jIe.default(a);if(n.width<=t||n.width>=1&&t>0&&t<1)return n;let c=(s=(r=e.style)===null||r===void 0?void 0:r.textWrap)!==null&&s!==void 0?s:\"wrap\",f=mft.default(a,t,c);return jIe.default(f)},GIe=e=>{var t;if(!(!e||!e.parentNode))return(t=e.yogaNode)!==null&&t!==void 0?t:GIe(e.parentNode)},CF=e=>{let t=GIe(e);t?.markDirty()};bi.setTextNodeValue=(e,t)=>{typeof t!=\"string\"&&(t=String(t)),e.nodeValue=t,CF(e)}});var KIe=G(JS=>{\"use strict\";var YIe=JS&&JS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(JS,\"__esModule\",{value:!0});var qIe=c9(),Ift=YIe(AIe()),WIe=YIe(Lm()),ia=b9(),VIe=e=>{e?.unsetMeasureFunc(),e?.freeRecursive()};JS.default=Ift.default({schedulePassiveEffects:qIe.unstable_scheduleCallback,cancelPassiveEffects:qIe.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>null,preparePortalMount:()=>null,clearContainer:()=>!1,shouldDeprioritizeSubtree:()=>!1,resetAfterCommit:e=>{if(e.isStaticDirty){e.isStaticDirty=!1,typeof e.onImmediateRender==\"function\"&&e.onImmediateRender();return}typeof e.onRender==\"function\"&&e.onRender()},getChildHostContext:(e,t)=>{let r=e.isInsideText,s=t===\"ink-text\"||t===\"ink-virtual-text\";return r===s?e:{isInsideText:s}},shouldSetTextContent:()=>!1,createInstance:(e,t,r,s)=>{if(s.isInsideText&&e===\"ink-box\")throw new Error(\"<Box> can\\u2019t be nested inside <Text> component\");let a=e===\"ink-text\"&&s.isInsideText?\"ink-virtual-text\":e,n=ia.createNode(a);for(let[c,f]of Object.entries(t))c!==\"children\"&&(c===\"style\"?ia.setStyle(n,f):c===\"internal_transform\"?n.internal_transform=f:c===\"internal_static\"?n.internal_static=!0:ia.setAttribute(n,c,f));return n},createTextInstance:(e,t,r)=>{if(!r.isInsideText)throw new Error(`Text string \"${e}\" must be rendered inside <Text> component`);return ia.createTextNode(e)},resetTextContent:()=>{},hideTextInstance:e=>{ia.setTextNodeValue(e,\"\")},unhideTextInstance:(e,t)=>{ia.setTextNodeValue(e,t)},getPublicInstance:e=>e,hideInstance:e=>{var t;(t=e.yogaNode)===null||t===void 0||t.setDisplay(WIe.default.DISPLAY_NONE)},unhideInstance:e=>{var t;(t=e.yogaNode)===null||t===void 0||t.setDisplay(WIe.default.DISPLAY_FLEX)},appendInitialChild:ia.appendChildNode,appendChild:ia.appendChildNode,insertBefore:ia.insertBeforeNode,finalizeInitialChildren:(e,t,r,s)=>(e.internal_static&&(s.isStaticDirty=!0,s.staticNode=e),!1),supportsMutation:!0,appendChildToContainer:ia.appendChildNode,insertInContainerBefore:ia.insertBeforeNode,removeChildFromContainer:(e,t)=>{ia.removeChildNode(e,t),VIe(t.yogaNode)},prepareUpdate:(e,t,r,s,a)=>{e.internal_static&&(a.isStaticDirty=!0);let n={},c=Object.keys(s);for(let f of c)if(s[f]!==r[f]){if(f===\"style\"&&typeof s.style==\"object\"&&typeof r.style==\"object\"){let h=s.style,E=r.style,C=Object.keys(h);for(let S of C){if(S===\"borderStyle\"||S===\"borderColor\"){if(typeof n.style!=\"object\"){let x={};n.style=x}n.style.borderStyle=h.borderStyle,n.style.borderColor=h.borderColor}if(h[S]!==E[S]){if(typeof n.style!=\"object\"){let x={};n.style=x}n.style[S]=h[S]}}continue}n[f]=s[f]}return n},commitUpdate:(e,t)=>{for(let[r,s]of Object.entries(t))r!==\"children\"&&(r===\"style\"?ia.setStyle(e,s):r===\"internal_transform\"?e.internal_transform=s:r===\"internal_static\"?e.internal_static=!0:ia.setAttribute(e,r,s))},commitTextUpdate:(e,t,r)=>{ia.setTextNodeValue(e,r)},removeChild:(e,t)=>{ia.removeChildNode(e,t),VIe(t.yogaNode)}})});var zIe=G((YYt,JIe)=>{\"use strict\";JIe.exports=(e,t=1,r)=>{if(r={indent:\" \",includeEmptyLines:!1,...r},typeof e!=\"string\")throw new TypeError(`Expected \\`input\\` to be a \\`string\\`, got \\`${typeof e}\\``);if(typeof t!=\"number\")throw new TypeError(`Expected \\`count\\` to be a \\`number\\`, got \\`${typeof t}\\``);if(typeof r.indent!=\"string\")throw new TypeError(`Expected \\`options.indent\\` to be a \\`string\\`, got \\`${typeof r.indent}\\``);if(t===0)return e;let s=r.includeEmptyLines?/^/gm:/^(?!\\s*$)/gm;return e.replace(s,r.indent.repeat(t))}});var ZIe=G(zS=>{\"use strict\";var Cft=zS&&zS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(zS,\"__esModule\",{value:!0});var wF=Cft(Lm());zS.default=e=>e.getComputedWidth()-e.getComputedPadding(wF.default.EDGE_LEFT)-e.getComputedPadding(wF.default.EDGE_RIGHT)-e.getComputedBorder(wF.default.EDGE_LEFT)-e.getComputedBorder(wF.default.EDGE_RIGHT)});var XIe=G((JYt,wft)=>{wft.exports={single:{topLeft:\"\\u250C\",topRight:\"\\u2510\",bottomRight:\"\\u2518\",bottomLeft:\"\\u2514\",vertical:\"\\u2502\",horizontal:\"\\u2500\"},double:{topLeft:\"\\u2554\",topRight:\"\\u2557\",bottomRight:\"\\u255D\",bottomLeft:\"\\u255A\",vertical:\"\\u2551\",horizontal:\"\\u2550\"},round:{topLeft:\"\\u256D\",topRight:\"\\u256E\",bottomRight:\"\\u256F\",bottomLeft:\"\\u2570\",vertical:\"\\u2502\",horizontal:\"\\u2500\"},bold:{topLeft:\"\\u250F\",topRight:\"\\u2513\",bottomRight:\"\\u251B\",bottomLeft:\"\\u2517\",vertical:\"\\u2503\",horizontal:\"\\u2501\"},singleDouble:{topLeft:\"\\u2553\",topRight:\"\\u2556\",bottomRight:\"\\u255C\",bottomLeft:\"\\u2559\",vertical:\"\\u2551\",horizontal:\"\\u2500\"},doubleSingle:{topLeft:\"\\u2552\",topRight:\"\\u2555\",bottomRight:\"\\u255B\",bottomLeft:\"\\u2558\",vertical:\"\\u2502\",horizontal:\"\\u2550\"},classic:{topLeft:\"+\",topRight:\"+\",bottomRight:\"+\",bottomLeft:\"+\",vertical:\"|\",horizontal:\"-\"}}});var eCe=G((zYt,P9)=>{\"use strict\";var $Ie=XIe();P9.exports=$Ie;P9.exports.default=$Ie});var x9=G(XS=>{\"use strict\";var Bft=XS&&XS.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(XS,\"__esModule\",{value:!0});var ZS=Bft(NE()),vft=/^(rgb|hsl|hsv|hwb)\\(\\s?(\\d+),\\s?(\\d+),\\s?(\\d+)\\s?\\)$/,Sft=/^(ansi|ansi256)\\(\\s?(\\d+)\\s?\\)$/,BF=(e,t)=>t===\"foreground\"?e:\"bg\"+e[0].toUpperCase()+e.slice(1);XS.default=(e,t,r)=>{if(!t)return e;if(t in ZS.default){let a=BF(t,r);return ZS.default[a](e)}if(t.startsWith(\"#\")){let a=BF(\"hex\",r);return ZS.default[a](t)(e)}if(t.startsWith(\"ansi\")){let a=Sft.exec(t);if(!a)return e;let n=BF(a[1],r),c=Number(a[2]);return ZS.default[n](c)(e)}if(t.startsWith(\"rgb\")||t.startsWith(\"hsl\")||t.startsWith(\"hsv\")||t.startsWith(\"hwb\")){let a=vft.exec(t);if(!a)return e;let n=BF(a[1],r),c=Number(a[2]),f=Number(a[3]),p=Number(a[4]);return ZS.default[n](c,f,p)(e)}return e}});var rCe=G($S=>{\"use strict\";var tCe=$S&&$S.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty($S,\"__esModule\",{value:!0});var Dft=tCe(eCe()),k9=tCe(x9());$S.default=(e,t,r,s)=>{if(typeof r.style.borderStyle==\"string\"){let a=r.yogaNode.getComputedWidth(),n=r.yogaNode.getComputedHeight(),c=r.style.borderColor,f=Dft.default[r.style.borderStyle],p=k9.default(f.topLeft+f.horizontal.repeat(a-2)+f.topRight,c,\"foreground\"),h=(k9.default(f.vertical,c,\"foreground\")+`\n`).repeat(n-2),E=k9.default(f.bottomLeft+f.horizontal.repeat(a-2)+f.bottomRight,c,\"foreground\");s.write(e,t,p,{transformers:[]}),s.write(e,t+1,h,{transformers:[]}),s.write(e+a-1,t+1,h,{transformers:[]}),s.write(e,t+n-1,E,{transformers:[]})}}});var iCe=G(eD=>{\"use strict\";var Mm=eD&&eD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(eD,\"__esModule\",{value:!0});var bft=Mm(Lm()),Pft=Mm(y9()),xft=Mm(zIe()),kft=Mm(v9()),Qft=Mm(ZIe()),Rft=Mm(D9()),Tft=Mm(rCe()),Fft=(e,t)=>{var r;let s=(r=e.childNodes[0])===null||r===void 0?void 0:r.yogaNode;if(s){let a=s.getComputedLeft(),n=s.getComputedTop();t=`\n`.repeat(n)+xft.default(t,a)}return t},nCe=(e,t,r)=>{var s;let{offsetX:a=0,offsetY:n=0,transformers:c=[],skipStaticElements:f}=r;if(f&&e.internal_static)return;let{yogaNode:p}=e;if(p){if(p.getDisplay()===bft.default.DISPLAY_NONE)return;let h=a+p.getComputedLeft(),E=n+p.getComputedTop(),C=c;if(typeof e.internal_transform==\"function\"&&(C=[e.internal_transform,...c]),e.nodeName===\"ink-text\"){let S=Rft.default(e);if(S.length>0){let x=Pft.default(S),I=Qft.default(p);if(x>I){let T=(s=e.style.textWrap)!==null&&s!==void 0?s:\"wrap\";S=kft.default(S,I,T)}S=Fft(e,S),t.write(h,E,S,{transformers:C})}return}if(e.nodeName===\"ink-box\"&&Tft.default(h,E,e,t),e.nodeName===\"ink-root\"||e.nodeName===\"ink-box\")for(let S of e.childNodes)nCe(S,t,{offsetX:h,offsetY:E,transformers:C,skipStaticElements:f})}};eD.default=nCe});var aCe=G(tD=>{\"use strict\";var oCe=tD&&tD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(tD,\"__esModule\",{value:!0});var sCe=oCe(w9()),Nft=oCe(GS()),Q9=class{constructor(t){this.writes=[];let{width:r,height:s}=t;this.width=r,this.height=s}write(t,r,s,a){let{transformers:n}=a;s&&this.writes.push({x:t,y:r,text:s,transformers:n})}get(){let t=[];for(let s=0;s<this.height;s++)t.push(\" \".repeat(this.width));for(let s of this.writes){let{x:a,y:n,text:c,transformers:f}=s,p=c.split(`\n`),h=0;for(let E of p){let C=t[n+h];if(!C)continue;let S=Nft.default(E);for(let x of f)E=x(E);t[n+h]=sCe.default(C,0,a)+E+sCe.default(C,a+S),h++}}return{output:t.map(s=>s.trimRight()).join(`\n`),height:t.length}}};tD.default=Q9});var uCe=G(rD=>{\"use strict\";var R9=rD&&rD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(rD,\"__esModule\",{value:!0});var Oft=R9(Lm()),lCe=R9(iCe()),cCe=R9(aCe());rD.default=(e,t)=>{var r;if(e.yogaNode.setWidth(t),e.yogaNode){e.yogaNode.calculateLayout(void 0,void 0,Oft.default.DIRECTION_LTR);let s=new cCe.default({width:e.yogaNode.getComputedWidth(),height:e.yogaNode.getComputedHeight()});lCe.default(e,s,{skipStaticElements:!0});let a;!((r=e.staticNode)===null||r===void 0)&&r.yogaNode&&(a=new cCe.default({width:e.staticNode.yogaNode.getComputedWidth(),height:e.staticNode.yogaNode.getComputedHeight()}),lCe.default(e.staticNode,a,{skipStaticElements:!1}));let{output:n,height:c}=s.get();return{output:n,outputHeight:c,staticOutput:a?`${a.get().output}\n`:\"\"}}return{output:\"\",outputHeight:0,staticOutput:\"\"}}});var hCe=G((r7t,pCe)=>{\"use strict\";var fCe=Ie(\"stream\"),ACe=[\"assert\",\"count\",\"countReset\",\"debug\",\"dir\",\"dirxml\",\"error\",\"group\",\"groupCollapsed\",\"groupEnd\",\"info\",\"log\",\"table\",\"time\",\"timeEnd\",\"timeLog\",\"trace\",\"warn\"],T9={},Lft=e=>{let t=new fCe.PassThrough,r=new fCe.PassThrough;t.write=a=>e(\"stdout\",a),r.write=a=>e(\"stderr\",a);let s=new console.Console(t,r);for(let a of ACe)T9[a]=console[a],console[a]=s[a];return()=>{for(let a of ACe)console[a]=T9[a];T9={}}};pCe.exports=Lft});var N9=G(F9=>{\"use strict\";Object.defineProperty(F9,\"__esModule\",{value:!0});F9.default=new WeakMap});var L9=G(O9=>{\"use strict\";Object.defineProperty(O9,\"__esModule\",{value:!0});var Mft=gn(),gCe=Mft.createContext({exit:()=>{}});gCe.displayName=\"InternalAppContext\";O9.default=gCe});var U9=G(M9=>{\"use strict\";Object.defineProperty(M9,\"__esModule\",{value:!0});var Uft=gn(),dCe=Uft.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});dCe.displayName=\"InternalStdinContext\";M9.default=dCe});var H9=G(_9=>{\"use strict\";Object.defineProperty(_9,\"__esModule\",{value:!0});var _ft=gn(),mCe=_ft.createContext({stdout:void 0,write:()=>{}});mCe.displayName=\"InternalStdoutContext\";_9.default=mCe});var G9=G(j9=>{\"use strict\";Object.defineProperty(j9,\"__esModule\",{value:!0});var Hft=gn(),yCe=Hft.createContext({stderr:void 0,write:()=>{}});yCe.displayName=\"InternalStderrContext\";j9.default=yCe});var vF=G(q9=>{\"use strict\";Object.defineProperty(q9,\"__esModule\",{value:!0});var jft=gn(),ECe=jft.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{},focus:()=>{}});ECe.displayName=\"InternalFocusContext\";q9.default=ECe});var CCe=G((c7t,ICe)=>{\"use strict\";var Gft=/[|\\\\{}()[\\]^$+*?.-]/g;ICe.exports=e=>{if(typeof e!=\"string\")throw new TypeError(\"Expected a string\");return e.replace(Gft,\"\\\\$&\")}});var SCe=G((u7t,vCe)=>{\"use strict\";var qft=CCe(),Wft=typeof process==\"object\"&&process&&typeof process.cwd==\"function\"?process.cwd():\".\",BCe=[].concat(Ie(\"module\").builtinModules,\"bootstrap_node\",\"node\").map(e=>new RegExp(`(?:\\\\((?:node:)?${e}(?:\\\\.js)?:\\\\d+:\\\\d+\\\\)$|^\\\\s*at (?:node:)?${e}(?:\\\\.js)?:\\\\d+:\\\\d+$)`));BCe.push(/\\((?:node:)?internal\\/[^:]+:\\d+:\\d+\\)$/,/\\s*at (?:node:)?internal\\/[^:]+:\\d+:\\d+$/,/\\/\\.node-spawn-wrap-\\w+-\\w+\\/node:\\d+:\\d+\\)?$/);var W9=class e{constructor(t){t={ignoredPackages:[],...t},\"internals\"in t||(t.internals=e.nodeInternals()),\"cwd\"in t||(t.cwd=Wft),this._cwd=t.cwd.replace(/\\\\/g,\"/\"),this._internals=[].concat(t.internals,Vft(t.ignoredPackages)),this._wrapCallSite=t.wrapCallSite||!1}static nodeInternals(){return[...BCe]}clean(t,r=0){r=\" \".repeat(r),Array.isArray(t)||(t=t.split(`\n`)),!/^\\s*at /.test(t[0])&&/^\\s*at /.test(t[1])&&(t=t.slice(1));let s=!1,a=null,n=[];return t.forEach(c=>{if(c=c.replace(/\\\\/g,\"/\"),this._internals.some(p=>p.test(c)))return;let f=/^\\s*at /.test(c);s?c=c.trimEnd().replace(/^(\\s+)at /,\"$1\"):(c=c.trim(),f&&(c=c.slice(3))),c=c.replace(`${this._cwd}/`,\"\"),c&&(f?(a&&(n.push(a),a=null),n.push(c)):(s=!0,a=c))}),n.map(c=>`${r}${c}\n`).join(\"\")}captureString(t,r=this.captureString){typeof t==\"function\"&&(r=t,t=1/0);let{stackTraceLimit:s}=Error;t&&(Error.stackTraceLimit=t);let a={};Error.captureStackTrace(a,r);let{stack:n}=a;return Error.stackTraceLimit=s,this.clean(n)}capture(t,r=this.capture){typeof t==\"function\"&&(r=t,t=1/0);let{prepareStackTrace:s,stackTraceLimit:a}=Error;Error.prepareStackTrace=(f,p)=>this._wrapCallSite?p.map(this._wrapCallSite):p,t&&(Error.stackTraceLimit=t);let n={};Error.captureStackTrace(n,r);let{stack:c}=n;return Object.assign(Error,{prepareStackTrace:s,stackTraceLimit:a}),c}at(t=this.at){let[r]=this.capture(1,t);if(!r)return{};let s={line:r.getLineNumber(),column:r.getColumnNumber()};wCe(s,r.getFileName(),this._cwd),r.isConstructor()&&(s.constructor=!0),r.isEval()&&(s.evalOrigin=r.getEvalOrigin()),r.isNative()&&(s.native=!0);let a;try{a=r.getTypeName()}catch{}a&&a!==\"Object\"&&a!==\"[object Object]\"&&(s.type=a);let n=r.getFunctionName();n&&(s.function=n);let c=r.getMethodName();return c&&n!==c&&(s.method=c),s}parseLine(t){let r=t&&t.match(Yft);if(!r)return null;let s=r[1]===\"new\",a=r[2],n=r[3],c=r[4],f=Number(r[5]),p=Number(r[6]),h=r[7],E=r[8],C=r[9],S=r[10]===\"native\",x=r[11]===\")\",I,T={};if(E&&(T.line=Number(E)),C&&(T.column=Number(C)),x&&h){let O=0;for(let U=h.length-1;U>0;U--)if(h.charAt(U)===\")\")O++;else if(h.charAt(U)===\"(\"&&h.charAt(U-1)===\" \"&&(O--,O===-1&&h.charAt(U-1)===\" \")){let Y=h.slice(0,U-1);h=h.slice(U+1),a+=` (${Y}`;break}}if(a){let O=a.match(Kft);O&&(a=O[1],I=O[2])}return wCe(T,h,this._cwd),s&&(T.constructor=!0),n&&(T.evalOrigin=n,T.evalLine=f,T.evalColumn=p,T.evalFile=c&&c.replace(/\\\\/g,\"/\")),S&&(T.native=!0),a&&(T.function=a),I&&a!==I&&(T.method=I),T}};function wCe(e,t,r){t&&(t=t.replace(/\\\\/g,\"/\"),t.startsWith(`${r}/`)&&(t=t.slice(r.length+1)),e.file=t)}function Vft(e){if(e.length===0)return[];let t=e.map(r=>qft(r));return new RegExp(`[/\\\\\\\\]node_modules[/\\\\\\\\](?:${t.join(\"|\")})[/\\\\\\\\][^:]+:\\\\d+:\\\\d+`)}var Yft=new RegExp(\"^(?:\\\\s*at )?(?:(new) )?(?:(.*?) \\\\()?(?:eval at ([^ ]+) \\\\((.+?):(\\\\d+):(\\\\d+)\\\\), )?(?:(.+?):(\\\\d+):(\\\\d+)|(native))(\\\\)?)$\"),Kft=/^(.*?) \\[as (.*?)\\]$/;vCe.exports=W9});var bCe=G((f7t,DCe)=>{\"use strict\";DCe.exports=(e,t)=>e.replace(/^\\t+/gm,r=>\" \".repeat(r.length*(t||2)))});var xCe=G((A7t,PCe)=>{\"use strict\";var Jft=bCe(),zft=(e,t)=>{let r=[],s=e-t,a=e+t;for(let n=s;n<=a;n++)r.push(n);return r};PCe.exports=(e,t,r)=>{if(typeof e!=\"string\")throw new TypeError(\"Source code is missing.\");if(!t||t<1)throw new TypeError(\"Line number must start from `1`.\");if(e=Jft(e).split(/\\r?\\n/),!(t>e.length))return r={around:3,...r},zft(t,r.around).filter(s=>e[s-1]!==void 0).map(s=>({line:s,value:e[s-1]}))}});var SF=G(sf=>{\"use strict\";var Zft=sf&&sf.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Xft=sf&&sf.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),$ft=sf&&sf.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.hasOwnProperty.call(e,r)&&Zft(t,e,r);return Xft(t,e),t},eAt=sf&&sf.__rest||function(e,t){var r={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(r[s]=e[s]);if(e!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,s=Object.getOwnPropertySymbols(e);a<s.length;a++)t.indexOf(s[a])<0&&Object.prototype.propertyIsEnumerable.call(e,s[a])&&(r[s[a]]=e[s[a]]);return r};Object.defineProperty(sf,\"__esModule\",{value:!0});var kCe=$ft(gn()),V9=kCe.forwardRef((e,t)=>{var{children:r}=e,s=eAt(e,[\"children\"]);let a=Object.assign(Object.assign({},s),{marginLeft:s.marginLeft||s.marginX||s.margin||0,marginRight:s.marginRight||s.marginX||s.margin||0,marginTop:s.marginTop||s.marginY||s.margin||0,marginBottom:s.marginBottom||s.marginY||s.margin||0,paddingLeft:s.paddingLeft||s.paddingX||s.padding||0,paddingRight:s.paddingRight||s.paddingX||s.padding||0,paddingTop:s.paddingTop||s.paddingY||s.padding||0,paddingBottom:s.paddingBottom||s.paddingY||s.padding||0});return kCe.default.createElement(\"ink-box\",{ref:t,style:a},r)});V9.displayName=\"Box\";V9.defaultProps={flexDirection:\"row\",flexGrow:0,flexShrink:1};sf.default=V9});var J9=G(nD=>{\"use strict\";var Y9=nD&&nD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(nD,\"__esModule\",{value:!0});var tAt=Y9(gn()),cw=Y9(NE()),QCe=Y9(x9()),K9=({color:e,backgroundColor:t,dimColor:r,bold:s,italic:a,underline:n,strikethrough:c,inverse:f,wrap:p,children:h})=>{if(h==null)return null;let E=C=>(r&&(C=cw.default.dim(C)),e&&(C=QCe.default(C,e,\"foreground\")),t&&(C=QCe.default(C,t,\"background\")),s&&(C=cw.default.bold(C)),a&&(C=cw.default.italic(C)),n&&(C=cw.default.underline(C)),c&&(C=cw.default.strikethrough(C)),f&&(C=cw.default.inverse(C)),C);return tAt.default.createElement(\"ink-text\",{style:{flexGrow:0,flexShrink:1,flexDirection:\"row\",textWrap:p},internal_transform:E},h)};K9.displayName=\"Text\";K9.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:\"wrap\"};nD.default=K9});var NCe=G(of=>{\"use strict\";var rAt=of&&of.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),nAt=of&&of.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),iAt=of&&of.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.hasOwnProperty.call(e,r)&&rAt(t,e,r);return nAt(t,e),t},iD=of&&of.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(of,\"__esModule\",{value:!0});var RCe=iAt(Ie(\"fs\")),Fs=iD(gn()),TCe=iD(SCe()),sAt=iD(xCe()),Zp=iD(SF()),pA=iD(J9()),FCe=new TCe.default({cwd:process.cwd(),internals:TCe.default.nodeInternals()}),oAt=({error:e})=>{let t=e.stack?e.stack.split(`\n`).slice(1):void 0,r=t?FCe.parseLine(t[0]):void 0,s,a=0;if(r?.file&&r?.line&&RCe.existsSync(r.file)){let n=RCe.readFileSync(r.file,\"utf8\");if(s=sAt.default(n,r.line),s)for(let{line:c}of s)a=Math.max(a,String(c).length)}return Fs.default.createElement(Zp.default,{flexDirection:\"column\",padding:1},Fs.default.createElement(Zp.default,null,Fs.default.createElement(pA.default,{backgroundColor:\"red\",color:\"white\"},\" \",\"ERROR\",\" \"),Fs.default.createElement(pA.default,null,\" \",e.message)),r&&Fs.default.createElement(Zp.default,{marginTop:1},Fs.default.createElement(pA.default,{dimColor:!0},r.file,\":\",r.line,\":\",r.column)),r&&s&&Fs.default.createElement(Zp.default,{marginTop:1,flexDirection:\"column\"},s.map(({line:n,value:c})=>Fs.default.createElement(Zp.default,{key:n},Fs.default.createElement(Zp.default,{width:a+1},Fs.default.createElement(pA.default,{dimColor:n!==r.line,backgroundColor:n===r.line?\"red\":void 0,color:n===r.line?\"white\":void 0},String(n).padStart(a,\" \"),\":\")),Fs.default.createElement(pA.default,{key:n,backgroundColor:n===r.line?\"red\":void 0,color:n===r.line?\"white\":void 0},\" \"+c)))),e.stack&&Fs.default.createElement(Zp.default,{marginTop:1,flexDirection:\"column\"},e.stack.split(`\n`).slice(1).map(n=>{let c=FCe.parseLine(n);return c?Fs.default.createElement(Zp.default,{key:n},Fs.default.createElement(pA.default,{dimColor:!0},\"- \"),Fs.default.createElement(pA.default,{dimColor:!0,bold:!0},c.function),Fs.default.createElement(pA.default,{dimColor:!0,color:\"gray\"},\" \",\"(\",c.file,\":\",c.line,\":\",c.column,\")\")):Fs.default.createElement(Zp.default,{key:n},Fs.default.createElement(pA.default,{dimColor:!0},\"- \"),Fs.default.createElement(pA.default,{dimColor:!0,bold:!0},n))})))};of.default=oAt});var LCe=G(af=>{\"use strict\";var aAt=af&&af.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),lAt=af&&af.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),cAt=af&&af.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.hasOwnProperty.call(e,r)&&aAt(t,e,r);return lAt(t,e),t},_m=af&&af.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(af,\"__esModule\",{value:!0});var Um=cAt(gn()),OCe=_m(Zq()),uAt=_m(L9()),fAt=_m(U9()),AAt=_m(H9()),pAt=_m(G9()),hAt=_m(vF()),gAt=_m(NCe()),dAt=\"\t\",mAt=\"\\x1B[Z\",yAt=\"\\x1B\",DF=class extends Um.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=t=>{let{stdin:r}=this.props;if(!this.isRawModeSupported())throw r===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default.\nRead about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink.\nRead about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(r.setEncoding(\"utf8\"),t){this.rawModeEnabledCount===0&&(r.addListener(\"data\",this.handleInput),r.resume(),r.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(r.setRawMode(!1),r.removeListener(\"data\",this.handleInput),r.pause())},this.handleInput=t=>{t===\"\u0003\"&&this.props.exitOnCtrlC&&this.handleExit(),t===yAt&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(t===dAt&&this.focusNext(),t===mAt&&this.focusPrevious())},this.handleExit=t=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(t)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focus=t=>{this.setState(r=>r.focusables.some(a=>a?.id===t)?{activeFocusId:t}:r)},this.focusNext=()=>{this.setState(t=>{var r;let s=(r=t.focusables[0])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findNextFocusable(t)||s}})},this.focusPrevious=()=>{this.setState(t=>{var r;let s=(r=t.focusables[t.focusables.length-1])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findPreviousFocusable(t)||s}})},this.addFocusable=(t,{autoFocus:r})=>{this.setState(s=>{let a=s.activeFocusId;return!a&&r&&(a=t),{activeFocusId:a,focusables:[...s.focusables,{id:t,isActive:!0}]}})},this.removeFocusable=t=>{this.setState(r=>({activeFocusId:r.activeFocusId===t?void 0:r.activeFocusId,focusables:r.focusables.filter(s=>s.id!==t)}))},this.activateFocusable=t=>{this.setState(r=>({focusables:r.focusables.map(s=>s.id!==t?s:{id:t,isActive:!0})}))},this.deactivateFocusable=t=>{this.setState(r=>({activeFocusId:r.activeFocusId===t?void 0:r.activeFocusId,focusables:r.focusables.map(s=>s.id!==t?s:{id:t,isActive:!1})}))},this.findNextFocusable=t=>{var r;let s=t.focusables.findIndex(a=>a.id===t.activeFocusId);for(let a=s+1;a<t.focusables.length;a++)if(!((r=t.focusables[a])===null||r===void 0)&&r.isActive)return t.focusables[a].id},this.findPreviousFocusable=t=>{var r;let s=t.focusables.findIndex(a=>a.id===t.activeFocusId);for(let a=s-1;a>=0;a--)if(!((r=t.focusables[a])===null||r===void 0)&&r.isActive)return t.focusables[a].id}}static getDerivedStateFromError(t){return{error:t}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return Um.default.createElement(uAt.default.Provider,{value:{exit:this.handleExit}},Um.default.createElement(fAt.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},Um.default.createElement(AAt.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},Um.default.createElement(pAt.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},Um.default.createElement(hAt.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious,focus:this.focus}},this.state.error?Um.default.createElement(gAt.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){OCe.default.hide(this.props.stdout)}componentWillUnmount(){OCe.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(t){this.handleExit(t)}};af.default=DF;DF.displayName=\"InternalApp\"});var _Ce=G(lf=>{\"use strict\";var EAt=lf&&lf.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),IAt=lf&&lf.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),CAt=lf&&lf.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.hasOwnProperty.call(e,r)&&EAt(t,e,r);return IAt(t,e),t},cf=lf&&lf.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(lf,\"__esModule\",{value:!0});var wAt=cf(gn()),MCe=REe(),BAt=cf(KEe()),vAt=cf(Vq()),SAt=cf(eIe()),DAt=cf(rIe()),z9=cf(KIe()),bAt=cf(uCe()),PAt=cf(zq()),xAt=cf(hCe()),kAt=CAt(b9()),QAt=cf(N9()),RAt=cf(LCe()),uw=process.env.CI===\"false\"?!1:SAt.default,UCe=()=>{},Z9=class{constructor(t){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:r,outputHeight:s,staticOutput:a}=bAt.default(this.rootNode,this.options.stdout.columns||80),n=a&&a!==`\n`;if(this.options.debug){n&&(this.fullStaticOutput+=a),this.options.stdout.write(this.fullStaticOutput+r);return}if(uw){n&&this.options.stdout.write(a),this.lastOutput=r;return}if(n&&(this.fullStaticOutput+=a),s>=this.options.stdout.rows){this.options.stdout.write(vAt.default.clearTerminal+this.fullStaticOutput+r),this.lastOutput=r;return}n&&(this.log.clear(),this.options.stdout.write(a),this.log(r)),!n&&r!==this.lastOutput&&this.throttledLog(r),this.lastOutput=r},DAt.default(this),this.options=t,this.rootNode=kAt.createNode(\"ink-root\"),this.rootNode.onRender=t.debug?this.onRender:MCe(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=BAt.default.create(t.stdout),this.throttledLog=t.debug?this.log:MCe(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput=\"\",this.fullStaticOutput=\"\",this.container=z9.default.createContainer(this.rootNode,0,!1,null),this.unsubscribeExit=PAt.default(this.unmount,{alwaysLast:!1}),t.patchConsole&&this.patchConsole(),uw||(t.stdout.on(\"resize\",this.onRender),this.unsubscribeResize=()=>{t.stdout.off(\"resize\",this.onRender)})}render(t){let r=wAt.default.createElement(RAt.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},t);z9.default.updateContainer(r,this.container,null,UCe)}writeToStdout(t){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(t+this.fullStaticOutput+this.lastOutput);return}if(uw){this.options.stdout.write(t);return}this.log.clear(),this.options.stdout.write(t),this.log(this.lastOutput)}}writeToStderr(t){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(t),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(uw){this.options.stderr.write(t);return}this.log.clear(),this.options.stderr.write(t),this.log(this.lastOutput)}}unmount(t){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole==\"function\"&&this.restoreConsole(),typeof this.unsubscribeResize==\"function\"&&this.unsubscribeResize(),uw?this.options.stdout.write(this.lastOutput+`\n`):this.options.debug||this.log.done(),this.isUnmounted=!0,z9.default.updateContainer(null,this.container,null,UCe),QAt.default.delete(this.options.stdout),t instanceof Error?this.rejectExitPromise(t):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((t,r)=>{this.resolveExitPromise=t,this.rejectExitPromise=r})),this.exitPromise}clear(){!uw&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=xAt.default((t,r)=>{t===\"stdout\"&&this.writeToStdout(r),t===\"stderr\"&&(r.startsWith(\"The above error occurred\")||this.writeToStderr(r))}))}};lf.default=Z9});var jCe=G(sD=>{\"use strict\";var HCe=sD&&sD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(sD,\"__esModule\",{value:!0});var TAt=HCe(_Ce()),bF=HCe(N9()),FAt=Ie(\"stream\"),NAt=(e,t)=>{let r=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},OAt(t)),s=LAt(r.stdout,()=>new TAt.default(r));return s.render(e),{rerender:s.render,unmount:()=>s.unmount(),waitUntilExit:s.waitUntilExit,cleanup:()=>bF.default.delete(r.stdout),clear:s.clear}};sD.default=NAt;var OAt=(e={})=>e instanceof FAt.Stream?{stdout:e,stdin:process.stdin}:e,LAt=(e,t)=>{let r;return bF.default.has(e)?r=bF.default.get(e):(r=t(),bF.default.set(e,r)),r}});var qCe=G(Xp=>{\"use strict\";var MAt=Xp&&Xp.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),UAt=Xp&&Xp.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),_At=Xp&&Xp.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.hasOwnProperty.call(e,r)&&MAt(t,e,r);return UAt(t,e),t};Object.defineProperty(Xp,\"__esModule\",{value:!0});var oD=_At(gn()),GCe=e=>{let{items:t,children:r,style:s}=e,[a,n]=oD.useState(0),c=oD.useMemo(()=>t.slice(a),[t,a]);oD.useLayoutEffect(()=>{n(t.length)},[t.length]);let f=c.map((h,E)=>r(h,a+E)),p=oD.useMemo(()=>Object.assign({position:\"absolute\",flexDirection:\"column\"},s),[s]);return oD.default.createElement(\"ink-box\",{internal_static:!0,style:p},f)};GCe.displayName=\"Static\";Xp.default=GCe});var VCe=G(aD=>{\"use strict\";var HAt=aD&&aD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(aD,\"__esModule\",{value:!0});var jAt=HAt(gn()),WCe=({children:e,transform:t})=>e==null?null:jAt.default.createElement(\"ink-text\",{style:{flexGrow:0,flexShrink:1,flexDirection:\"row\"},internal_transform:t},e);WCe.displayName=\"Transform\";aD.default=WCe});var KCe=G(lD=>{\"use strict\";var GAt=lD&&lD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(lD,\"__esModule\",{value:!0});var qAt=GAt(gn()),YCe=({count:e=1})=>qAt.default.createElement(\"ink-text\",null,`\n`.repeat(e));YCe.displayName=\"Newline\";lD.default=YCe});var ZCe=G(cD=>{\"use strict\";var JCe=cD&&cD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(cD,\"__esModule\",{value:!0});var WAt=JCe(gn()),VAt=JCe(SF()),zCe=()=>WAt.default.createElement(VAt.default,{flexGrow:1});zCe.displayName=\"Spacer\";cD.default=zCe});var PF=G(uD=>{\"use strict\";var YAt=uD&&uD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(uD,\"__esModule\",{value:!0});var KAt=gn(),JAt=YAt(U9()),zAt=()=>KAt.useContext(JAt.default);uD.default=zAt});var $Ce=G(fD=>{\"use strict\";var ZAt=fD&&fD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(fD,\"__esModule\",{value:!0});var XCe=gn(),XAt=ZAt(PF()),$At=(e,t={})=>{let{stdin:r,setRawMode:s,internal_exitOnCtrlC:a}=XAt.default();XCe.useEffect(()=>{if(t.isActive!==!1)return s(!0),()=>{s(!1)}},[t.isActive,s]),XCe.useEffect(()=>{if(t.isActive===!1)return;let n=c=>{let f=String(c),p={upArrow:f===\"\\x1B[A\",downArrow:f===\"\\x1B[B\",leftArrow:f===\"\\x1B[D\",rightArrow:f===\"\\x1B[C\",pageDown:f===\"\\x1B[6~\",pageUp:f===\"\\x1B[5~\",return:f===\"\\r\",escape:f===\"\\x1B\",ctrl:!1,shift:!1,tab:f===\"\t\"||f===\"\\x1B[Z\",backspace:f===\"\\b\",delete:f===\"\\x7F\"||f===\"\\x1B[3~\",meta:!1};f<=\"\u001a\"&&!p.return&&(f=String.fromCharCode(f.charCodeAt(0)+97-1),p.ctrl=!0),f.startsWith(\"\\x1B\")&&(f=f.slice(1),p.meta=!0);let h=f>=\"A\"&&f<=\"Z\",E=f>=\"\\u0410\"&&f<=\"\\u042F\";f.length===1&&(h||E)&&(p.shift=!0),p.tab&&f===\"[Z\"&&(p.shift=!0),(p.tab||p.backspace||p.delete)&&(f=\"\"),(!(f===\"c\"&&p.ctrl)||!a)&&e(f,p)};return r?.on(\"data\",n),()=>{r?.off(\"data\",n)}},[t.isActive,r,a,e])};fD.default=$At});var ewe=G(AD=>{\"use strict\";var ept=AD&&AD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(AD,\"__esModule\",{value:!0});var tpt=gn(),rpt=ept(L9()),npt=()=>tpt.useContext(rpt.default);AD.default=npt});var twe=G(pD=>{\"use strict\";var ipt=pD&&pD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(pD,\"__esModule\",{value:!0});var spt=gn(),opt=ipt(H9()),apt=()=>spt.useContext(opt.default);pD.default=apt});var rwe=G(hD=>{\"use strict\";var lpt=hD&&hD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(hD,\"__esModule\",{value:!0});var cpt=gn(),upt=lpt(G9()),fpt=()=>cpt.useContext(upt.default);hD.default=fpt});var iwe=G(dD=>{\"use strict\";var nwe=dD&&dD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(dD,\"__esModule\",{value:!0});var gD=gn(),Apt=nwe(vF()),ppt=nwe(PF()),hpt=({isActive:e=!0,autoFocus:t=!1,id:r}={})=>{let{isRawModeSupported:s,setRawMode:a}=ppt.default(),{activeId:n,add:c,remove:f,activate:p,deactivate:h,focus:E}=gD.useContext(Apt.default),C=gD.useMemo(()=>r??Math.random().toString().slice(2,7),[r]);return gD.useEffect(()=>(c(C,{autoFocus:t}),()=>{f(C)}),[C,t]),gD.useEffect(()=>{e?p(C):h(C)},[e,C]),gD.useEffect(()=>{if(!(!s||!e))return a(!0),()=>{a(!1)}},[e]),{isFocused:!!C&&n===C,focus:E}};dD.default=hpt});var swe=G(mD=>{\"use strict\";var gpt=mD&&mD.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(mD,\"__esModule\",{value:!0});var dpt=gn(),mpt=gpt(vF()),ypt=()=>{let e=dpt.useContext(mpt.default);return{enableFocus:e.enableFocus,disableFocus:e.disableFocus,focusNext:e.focusNext,focusPrevious:e.focusPrevious,focus:e.focus}};mD.default=ypt});var owe=G(X9=>{\"use strict\";Object.defineProperty(X9,\"__esModule\",{value:!0});X9.default=e=>{var t,r,s,a;return{width:(r=(t=e.yogaNode)===null||t===void 0?void 0:t.getComputedWidth())!==null&&r!==void 0?r:0,height:(a=(s=e.yogaNode)===null||s===void 0?void 0:s.getComputedHeight())!==null&&a!==void 0?a:0}}});var Gc=G(wo=>{\"use strict\";Object.defineProperty(wo,\"__esModule\",{value:!0});var Ept=jCe();Object.defineProperty(wo,\"render\",{enumerable:!0,get:function(){return Ept.default}});var Ipt=SF();Object.defineProperty(wo,\"Box\",{enumerable:!0,get:function(){return Ipt.default}});var Cpt=J9();Object.defineProperty(wo,\"Text\",{enumerable:!0,get:function(){return Cpt.default}});var wpt=qCe();Object.defineProperty(wo,\"Static\",{enumerable:!0,get:function(){return wpt.default}});var Bpt=VCe();Object.defineProperty(wo,\"Transform\",{enumerable:!0,get:function(){return Bpt.default}});var vpt=KCe();Object.defineProperty(wo,\"Newline\",{enumerable:!0,get:function(){return vpt.default}});var Spt=ZCe();Object.defineProperty(wo,\"Spacer\",{enumerable:!0,get:function(){return Spt.default}});var Dpt=$Ce();Object.defineProperty(wo,\"useInput\",{enumerable:!0,get:function(){return Dpt.default}});var bpt=ewe();Object.defineProperty(wo,\"useApp\",{enumerable:!0,get:function(){return bpt.default}});var Ppt=PF();Object.defineProperty(wo,\"useStdin\",{enumerable:!0,get:function(){return Ppt.default}});var xpt=twe();Object.defineProperty(wo,\"useStdout\",{enumerable:!0,get:function(){return xpt.default}});var kpt=rwe();Object.defineProperty(wo,\"useStderr\",{enumerable:!0,get:function(){return kpt.default}});var Qpt=iwe();Object.defineProperty(wo,\"useFocus\",{enumerable:!0,get:function(){return Qpt.default}});var Rpt=swe();Object.defineProperty(wo,\"useFocusManager\",{enumerable:!0,get:function(){return Rpt.default}});var Tpt=owe();Object.defineProperty(wo,\"measureElement\",{enumerable:!0,get:function(){return Tpt.default}})});var eW={};Yt(eW,{Gem:()=>$9});var awe,Hm,$9,xF=Ze(()=>{awe=et(Gc()),Hm=et(gn()),$9=(0,Hm.memo)(({active:e})=>{let t=(0,Hm.useMemo)(()=>e?\"\\u25C9\":\"\\u25EF\",[e]),r=(0,Hm.useMemo)(()=>e?\"green\":\"yellow\",[e]);return Hm.default.createElement(awe.Text,{color:r},t)})});var tW={};Yt(tW,{useKeypress:()=>jm});function jm({active:e},t,r){let{stdin:s}=(0,lwe.useStdin)(),a=(0,kF.useCallback)((n,c)=>t(n,c),r);(0,kF.useEffect)(()=>{if(!(!e||!s))return s.on(\"keypress\",a),()=>{s.off(\"keypress\",a)}},[e,a,s])}var lwe,kF,fw=Ze(()=>{lwe=et(Gc()),kF=et(gn())});var uwe={};Yt(uwe,{FocusRequest:()=>cwe,useFocusRequest:()=>rW});var cwe,rW,nW=Ze(()=>{fw();cwe=(r=>(r.BEFORE=\"before\",r.AFTER=\"after\",r))(cwe||{}),rW=function({active:e},t,r){jm({active:e},(s,a)=>{a.name===\"tab\"&&(a.shift?t(\"before\"):t(\"after\"))},r)}});var fwe={};Yt(fwe,{useListInput:()=>yD});var yD,QF=Ze(()=>{fw();yD=function(e,t,{active:r,minus:s,plus:a,set:n,loop:c=!0}){jm({active:r},(f,p)=>{let h=t.indexOf(e);switch(p.name){case s:{let E=h-1;if(c){n(t[(t.length+E)%t.length]);return}if(E<0)return;n(t[E])}break;case a:{let E=h+1;if(c){n(t[E%t.length]);return}if(E>=t.length)return;n(t[E])}break}},[t,e,a,n,c])}});var RF={};Yt(RF,{ScrollableItems:()=>Fpt});var X0,wl,Fpt,TF=Ze(()=>{X0=et(Gc()),wl=et(gn());nW();QF();Fpt=({active:e=!0,children:t=[],radius:r=10,size:s=1,loop:a=!0,onFocusRequest:n,willReachEnd:c})=>{let f=O=>{if(O.key===null)throw new Error(\"Expected all children to have a key\");return O.key},p=wl.default.Children.map(t,O=>f(O)),h=p[0],[E,C]=(0,wl.useState)(h),S=p.indexOf(E);(0,wl.useEffect)(()=>{p.includes(E)||C(h)},[t]),(0,wl.useEffect)(()=>{c&&S>=p.length-2&&c()},[S]),rW({active:e&&!!n},O=>{n?.(O)},[n]),yD(E,p,{active:e,minus:\"up\",plus:\"down\",set:C,loop:a});let x=S-r,I=S+r;I>p.length&&(x-=I-p.length,I=p.length),x<0&&(I+=-x,x=0),I>=p.length&&(I=p.length-1);let T=[];for(let O=x;O<=I;++O){let U=p[O],Y=e&&U===E;T.push(wl.default.createElement(X0.Box,{key:U,height:s},wl.default.createElement(X0.Box,{marginLeft:1,marginRight:1},wl.default.createElement(X0.Text,null,Y?wl.default.createElement(X0.Text,{color:\"cyan\",bold:!0},\">\"):\" \")),wl.default.createElement(X0.Box,null,wl.default.cloneElement(t[O],{active:Y}))))}return wl.default.createElement(X0.Box,{flexDirection:\"column\",width:\"100%\"},T)}});var Awe,$p,pwe,FF,hwe,iW=Ze(()=>{Awe=et(Gc()),$p=et(gn()),pwe=Ie(\"readline\"),FF=$p.default.createContext(null),hwe=({children:e})=>{let{stdin:t,setRawMode:r}=(0,Awe.useStdin)();(0,$p.useEffect)(()=>{r&&r(!0),t&&(0,pwe.emitKeypressEvents)(t)},[t,r]);let[s,a]=(0,$p.useState)(new Map),n=(0,$p.useMemo)(()=>({getAll:()=>s,get:c=>s.get(c),set:(c,f)=>a(p=>new Map([...p,[c,f]])),setAll:c=>a(f=>new Map([...f,...c]))}),[s,a]);return $p.default.createElement(FF.Provider,{value:n,children:e})}});var sW={};Yt(sW,{useMinistore:()=>Npt,useMinistoreSetAll:()=>Opt});function Npt(e,t){let r=(0,ED.useContext)(FF);if(r===null)throw new Error(\"Expected this hook to run with a ministore context attached\");if(typeof e>\"u\")return r.getAll();let s=(0,ED.useCallback)(n=>{r.set(e,n)},[e,r.set]),a=r.get(e);return typeof a>\"u\"&&(a=t),[a,s]}function Opt(){let e=(0,ED.useContext)(FF);if(e===null)throw new Error(\"Expected this hook to run with a ministore context attached\");return e.setAll}var ED,oW=Ze(()=>{ED=et(gn());iW()});var OF={};Yt(OF,{renderForm:()=>Lpt});async function Lpt(e,t,{stdin:r,stdout:s,stderr:a}){let n,c=p=>{let{exit:h}=(0,NF.useApp)();jm({active:!0},(E,C)=>{C.name===\"return\"&&(n=p,h())},[h,p])},{waitUntilExit:f}=(0,NF.render)(aW.default.createElement(hwe,null,aW.default.createElement(e,{...t,useSubmit:c})),{stdin:r,stdout:s,stderr:a});return await f(),n}var NF,aW,LF=Ze(()=>{NF=et(Gc()),aW=et(gn());iW();fw()});var ywe=G(ID=>{\"use strict\";Object.defineProperty(ID,\"__esModule\",{value:!0});ID.UncontrolledTextInput=void 0;var dwe=gn(),lW=gn(),gwe=Gc(),Gm=NE(),mwe=({value:e,placeholder:t=\"\",focus:r=!0,mask:s,highlightPastedText:a=!1,showCursor:n=!0,onChange:c,onSubmit:f})=>{let[{cursorOffset:p,cursorWidth:h},E]=lW.useState({cursorOffset:(e||\"\").length,cursorWidth:0});lW.useEffect(()=>{E(T=>{if(!r||!n)return T;let O=e||\"\";return T.cursorOffset>O.length-1?{cursorOffset:O.length,cursorWidth:0}:T})},[e,r,n]);let C=a?h:0,S=s?s.repeat(e.length):e,x=S,I=t?Gm.grey(t):void 0;if(n&&r){I=t.length>0?Gm.inverse(t[0])+Gm.grey(t.slice(1)):Gm.inverse(\" \"),x=S.length>0?\"\":Gm.inverse(\" \");let T=0;for(let O of S)T>=p-C&&T<=p?x+=Gm.inverse(O):x+=O,T++;S.length>0&&p===S.length&&(x+=Gm.inverse(\" \"))}return gwe.useInput((T,O)=>{if(O.upArrow||O.downArrow||O.ctrl&&T===\"c\"||O.tab||O.shift&&O.tab)return;if(O.return){f&&f(e);return}let U=p,Y=e,te=0;O.leftArrow?n&&U--:O.rightArrow?n&&U++:O.backspace||O.delete?p>0&&(Y=e.slice(0,p-1)+e.slice(p,e.length),U--):(Y=e.slice(0,p)+T+e.slice(p,e.length),U+=T.length,T.length>1&&(te=T.length)),p<0&&(U=0),p>e.length&&(U=e.length),E({cursorOffset:U,cursorWidth:te}),Y!==e&&c(Y)},{isActive:r}),dwe.createElement(gwe.Text,null,t?S.length>0?x:I:x)};ID.default=mwe;ID.UncontrolledTextInput=({initialValue:e=\"\",...t})=>{let[r,s]=lW.useState(e);return dwe.createElement(mwe,Object.assign({},t,{value:r,onChange:s}))}});var Cwe={};Yt(Cwe,{Pad:()=>cW});var Ewe,Iwe,cW,uW=Ze(()=>{Ewe=et(Gc()),Iwe=et(gn()),cW=({length:e,active:t})=>{if(e===0)return null;let r=e>1?` ${\"-\".repeat(e-1)}`:\" \";return Iwe.default.createElement(Ewe.Text,{dimColor:!t},r)}});var wwe={};Yt(wwe,{ItemOptions:()=>Mpt});var wD,$0,Mpt,Bwe=Ze(()=>{wD=et(Gc()),$0=et(gn());QF();xF();uW();Mpt=function({active:e,skewer:t,options:r,value:s,onChange:a,sizes:n=[]}){let c=r.filter(({label:p})=>!!p).map(({value:p})=>p),f=r.findIndex(p=>p.value===s&&p.label!=\"\");return yD(s,c,{active:e,minus:\"left\",plus:\"right\",set:a}),$0.default.createElement($0.default.Fragment,null,r.map(({label:p},h)=>{let E=h===f,C=n[h]-1||0,S=p.replace(/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,\"\"),x=Math.max(0,C-S.length-2);return p?$0.default.createElement(wD.Box,{key:p,width:C,marginLeft:1},$0.default.createElement(wD.Text,{wrap:\"truncate\"},$0.default.createElement($9,{active:E}),\" \",p),t?$0.default.createElement(cW,{active:e,length:x}):null):$0.default.createElement(wD.Box,{key:`spacer-${h}`,width:C,marginLeft:1})}))}});var Mwe=G((dJt,Lwe)=>{var CW;Lwe.exports=()=>(typeof CW>\"u\"&&(CW=Ie(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),CW)});var s1e=G((HJt,i1e)=>{var kW=Symbol(\"arg flag\"),qc=class e extends Error{constructor(t,r){super(t),this.name=\"ArgError\",this.code=r,Object.setPrototypeOf(this,e.prototype)}};function UD(e,{argv:t=process.argv.slice(2),permissive:r=!1,stopAtPositional:s=!1}={}){if(!e)throw new qc(\"argument specification object is required\",\"ARG_CONFIG_NO_SPEC\");let a={_:[]},n={},c={};for(let f of Object.keys(e)){if(!f)throw new qc(\"argument key cannot be an empty string\",\"ARG_CONFIG_EMPTY_KEY\");if(f[0]!==\"-\")throw new qc(`argument key must start with '-' but found: '${f}'`,\"ARG_CONFIG_NONOPT_KEY\");if(f.length===1)throw new qc(`argument key must have a name; singular '-' keys are not allowed: ${f}`,\"ARG_CONFIG_NONAME_KEY\");if(typeof e[f]==\"string\"){n[f]=e[f];continue}let p=e[f],h=!1;if(Array.isArray(p)&&p.length===1&&typeof p[0]==\"function\"){let[E]=p;p=(C,S,x=[])=>(x.push(E(C,S,x[x.length-1])),x),h=E===Boolean||E[kW]===!0}else if(typeof p==\"function\")h=p===Boolean||p[kW]===!0;else throw new qc(`type missing or not a function or valid array type: ${f}`,\"ARG_CONFIG_VAD_TYPE\");if(f[1]!==\"-\"&&f.length>2)throw new qc(`short argument keys (with a single hyphen) must have only one character: ${f}`,\"ARG_CONFIG_SHORTOPT_TOOLONG\");c[f]=[p,h]}for(let f=0,p=t.length;f<p;f++){let h=t[f];if(s&&a._.length>0){a._=a._.concat(t.slice(f));break}if(h===\"--\"){a._=a._.concat(t.slice(f+1));break}if(h.length>1&&h[0]===\"-\"){let E=h[1]===\"-\"||h.length===2?[h]:h.slice(1).split(\"\").map(C=>`-${C}`);for(let C=0;C<E.length;C++){let S=E[C],[x,I]=S[1]===\"-\"?S.split(/=(.*)/,2):[S,void 0],T=x;for(;T in n;)T=n[T];if(!(T in c))if(r){a._.push(S);continue}else throw new qc(`unknown or unexpected option: ${x}`,\"ARG_UNKNOWN_OPTION\");let[O,U]=c[T];if(!U&&C+1<E.length)throw new qc(`option requires argument (but was followed by another short argument): ${x}`,\"ARG_MISSING_REQUIRED_SHORTARG\");if(U)a[T]=O(!0,T,a[T]);else if(I===void 0){if(t.length<f+2||t[f+1].length>1&&t[f+1][0]===\"-\"&&!(t[f+1].match(/^-?\\d*(\\.(?=\\d))?\\d*$/)&&(O===Number||typeof BigInt<\"u\"&&O===BigInt))){let Y=x===T?\"\":` (alias for ${T})`;throw new qc(`option requires argument: ${x}${Y}`,\"ARG_MISSING_REQUIRED_LONGARG\")}a[T]=O(t[f+1],T,a[T]),++f}else a[T]=O(I,T,a[T])}}else a._.push(h)}return a}UD.flag=e=>(e[kW]=!0,e);UD.COUNT=UD.flag((e,t,r)=>(r||0)+1);UD.ArgError=qc;i1e.exports=UD});var p1e=G((mzt,A1e)=>{var FW;A1e.exports=()=>(typeof FW>\"u\"&&(FW=Ie(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),FW)});var y1e=G((_W,HW)=>{(function(e){_W&&typeof _W==\"object\"&&typeof HW<\"u\"?HW.exports=e():typeof define==\"function\"&&define.amd?define([],e):typeof window<\"u\"?window.isWindows=e():typeof global<\"u\"?global.isWindows=e():typeof self<\"u\"?self.isWindows=e():this.isWindows=e()})(function(){\"use strict\";return function(){return process&&(process.platform===\"win32\"||/^(msys|cygwin)$/.test(process.env.OSTYPE))}})});var w1e=G((gZt,C1e)=>{\"use strict\";jW.ifExists=Uht;var yw=Ie(\"util\"),Wc=Ie(\"path\"),E1e=y1e(),Oht=/^#!\\s*(?:\\/usr\\/bin\\/env)?\\s*([^ \\t]+)(.*)$/,Lht={createPwshFile:!0,createCmdFile:E1e(),fs:Ie(\"fs\")},Mht=new Map([[\".js\",\"node\"],[\".cjs\",\"node\"],[\".mjs\",\"node\"],[\".cmd\",\"cmd\"],[\".bat\",\"cmd\"],[\".ps1\",\"pwsh\"],[\".sh\",\"sh\"]]);function I1e(e){let t={...Lht,...e},r=t.fs;return t.fs_={chmod:r.chmod?yw.promisify(r.chmod):async()=>{},mkdir:yw.promisify(r.mkdir),readFile:yw.promisify(r.readFile),stat:yw.promisify(r.stat),unlink:yw.promisify(r.unlink),writeFile:yw.promisify(r.writeFile)},t}async function jW(e,t,r){let s=I1e(r);await s.fs_.stat(e),await Hht(e,t,s)}function Uht(e,t,r){return jW(e,t,r).catch(()=>{})}function _ht(e,t){return t.fs_.unlink(e).catch(()=>{})}async function Hht(e,t,r){let s=await Vht(e,r);return await jht(t,r),Ght(e,t,s,r)}function jht(e,t){return t.fs_.mkdir(Wc.dirname(e),{recursive:!0})}function Ght(e,t,r,s){let a=I1e(s),n=[{generator:Jht,extension:\"\"}];return a.createCmdFile&&n.push({generator:Kht,extension:\".cmd\"}),a.createPwshFile&&n.push({generator:zht,extension:\".ps1\"}),Promise.all(n.map(c=>Yht(e,t+c.extension,r,c.generator,a)))}function qht(e,t){return _ht(e,t)}function Wht(e,t){return Zht(e,t)}async function Vht(e,t){let a=(await t.fs_.readFile(e,\"utf8\")).trim().split(/\\r*\\n/)[0].match(Oht);if(!a){let n=Wc.extname(e).toLowerCase();return{program:Mht.get(n)||null,additionalArgs:\"\"}}return{program:a[1],additionalArgs:a[2]}}async function Yht(e,t,r,s,a){let n=a.preserveSymlinks?\"--preserve-symlinks\":\"\",c=[r.additionalArgs,n].filter(f=>f).join(\" \");return a=Object.assign({},a,{prog:r.program,args:c}),await qht(t,a),await a.fs_.writeFile(t,s(e,t,a),\"utf8\"),Wht(t,a)}function Kht(e,t,r){let a=Wc.relative(Wc.dirname(t),e).split(\"/\").join(\"\\\\\"),n=Wc.isAbsolute(a)?`\"${a}\"`:`\"%~dp0\\\\${a}\"`,c,f=r.prog,p=r.args||\"\",h=GW(r.nodePath).win32;f?(c=`\"%~dp0\\\\${f}.exe\"`,a=n):(f=n,p=\"\",a=\"\");let E=r.progArgs?`${r.progArgs.join(\" \")} `:\"\",C=h?`@SET NODE_PATH=${h}\\r\n`:\"\";return c?C+=`@IF EXIST ${c} (\\r\n  ${c} ${p} ${a} ${E}%*\\r\n) ELSE (\\r\n  @SETLOCAL\\r\n  @SET PATHEXT=%PATHEXT:;.JS;=;%\\r\n  ${f} ${p} ${a} ${E}%*\\r\n)\\r\n`:C+=`@${f} ${p} ${a} ${E}%*\\r\n`,C}function Jht(e,t,r){let s=Wc.relative(Wc.dirname(t),e),a=r.prog&&r.prog.split(\"\\\\\").join(\"/\"),n;s=s.split(\"\\\\\").join(\"/\");let c=Wc.isAbsolute(s)?`\"${s}\"`:`\"$basedir/${s}\"`,f=r.args||\"\",p=GW(r.nodePath).posix;a?(n=`\"$basedir/${r.prog}\"`,s=c):(a=c,f=\"\",s=\"\");let h=r.progArgs?`${r.progArgs.join(\" \")} `:\"\",E=`#!/bin/sh\nbasedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\\\\\,/,g')\")\n\ncase \\`uname\\` in\n    *CYGWIN*) basedir=\\`cygpath -w \"$basedir\"\\`;;\nesac\n\n`,C=r.nodePath?`export NODE_PATH=\"${p}\"\n`:\"\";return n?E+=`${C}if [ -x ${n} ]; then\n  exec ${n} ${f} ${s} ${h}\"$@\"\nelse\n  exec ${a} ${f} ${s} ${h}\"$@\"\nfi\n`:E+=`${C}${a} ${f} ${s} ${h}\"$@\"\nexit $?\n`,E}function zht(e,t,r){let s=Wc.relative(Wc.dirname(t),e),a=r.prog&&r.prog.split(\"\\\\\").join(\"/\"),n=a&&`\"${a}$exe\"`,c;s=s.split(\"\\\\\").join(\"/\");let f=Wc.isAbsolute(s)?`\"${s}\"`:`\"$basedir/${s}\"`,p=r.args||\"\",h=GW(r.nodePath),E=h.win32,C=h.posix;n?(c=`\"$basedir/${r.prog}$exe\"`,s=f):(n=f,p=\"\",s=\"\");let S=r.progArgs?`${r.progArgs.join(\" \")} `:\"\",x=`#!/usr/bin/env pwsh\n$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent\n\n$exe=\"\"\n${r.nodePath?`$env_node_path=$env:NODE_PATH\n$env:NODE_PATH=\"${E}\"\n`:\"\"}if ($PSVersionTable.PSVersion -lt \"6.0\" -or $IsWindows) {\n  # Fix case when both the Windows and Linux builds of Node\n  # are installed in the same directory\n  $exe=\".exe\"\n}`;return r.nodePath&&(x+=` else {\n  $env:NODE_PATH=\"${C}\"\n}`),c?x+=`\n$ret=0\nif (Test-Path ${c}) {\n  # Support pipeline input\n  if ($MyInvocation.ExpectingInput) {\n    $input | & ${c} ${p} ${s} ${S}$args\n  } else {\n    & ${c} ${p} ${s} ${S}$args\n  }\n  $ret=$LASTEXITCODE\n} else {\n  # Support pipeline input\n  if ($MyInvocation.ExpectingInput) {\n    $input | & ${n} ${p} ${s} ${S}$args\n  } else {\n    & ${n} ${p} ${s} ${S}$args\n  }\n  $ret=$LASTEXITCODE\n}\n${r.nodePath?`$env:NODE_PATH=$env_node_path\n`:\"\"}exit $ret\n`:x+=`\n# Support pipeline input\nif ($MyInvocation.ExpectingInput) {\n  $input | & ${n} ${p} ${s} ${S}$args\n} else {\n  & ${n} ${p} ${s} ${S}$args\n}\n${r.nodePath?`$env:NODE_PATH=$env_node_path\n`:\"\"}exit $LASTEXITCODE\n`,x}function Zht(e,t){return t.fs_.chmod(e,493)}function GW(e){if(!e)return{win32:\"\",posix:\"\"};let t=typeof e==\"string\"?e.split(Wc.delimiter):Array.from(e),r={};for(let s=0;s<t.length;s++){let a=t[s].split(\"/\").join(\"\\\\\"),n=E1e()?t[s].split(\"\\\\\").join(\"/\").replace(/^([^:\\\\/]*):/,(c,f)=>`/mnt/${f.toLowerCase()}`):t[s];r.win32=r.win32?`${r.win32};${a}`:a,r.posix=r.posix?`${r.posix}:${n}`:n,r[s]={win32:a,posix:n}}return r}C1e.exports=jW});var nV=G((GXt,H1e)=>{H1e.exports=Ie(\"stream\")});var W1e=G((qXt,q1e)=>{\"use strict\";function j1e(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable})),r.push.apply(r,s)}return r}function Q0t(e){for(var t=1;t<arguments.length;t++){var r=arguments[t]!=null?arguments[t]:{};t%2?j1e(Object(r),!0).forEach(function(s){R0t(e,s,r[s])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):j1e(Object(r)).forEach(function(s){Object.defineProperty(e,s,Object.getOwnPropertyDescriptor(r,s))})}return e}function R0t(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function T0t(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function G1e(e,t){for(var r=0;r<t.length;r++){var s=t[r];s.enumerable=s.enumerable||!1,s.configurable=!0,\"value\"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}function F0t(e,t,r){return t&&G1e(e.prototype,t),r&&G1e(e,r),e}var N0t=Ie(\"buffer\"),ZF=N0t.Buffer,O0t=Ie(\"util\"),iV=O0t.inspect,L0t=iV&&iV.custom||\"inspect\";function M0t(e,t,r){ZF.prototype.copy.call(e,t,r)}q1e.exports=function(){function e(){T0t(this,e),this.head=null,this.tail=null,this.length=0}return F0t(e,[{key:\"push\",value:function(r){var s={data:r,next:null};this.length>0?this.tail.next=s:this.head=s,this.tail=s,++this.length}},{key:\"unshift\",value:function(r){var s={data:r,next:this.head};this.length===0&&(this.tail=s),this.head=s,++this.length}},{key:\"shift\",value:function(){if(this.length!==0){var r=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,r}}},{key:\"clear\",value:function(){this.head=this.tail=null,this.length=0}},{key:\"join\",value:function(r){if(this.length===0)return\"\";for(var s=this.head,a=\"\"+s.data;s=s.next;)a+=r+s.data;return a}},{key:\"concat\",value:function(r){if(this.length===0)return ZF.alloc(0);for(var s=ZF.allocUnsafe(r>>>0),a=this.head,n=0;a;)M0t(a.data,s,n),n+=a.data.length,a=a.next;return s}},{key:\"consume\",value:function(r,s){var a;return r<this.head.data.length?(a=this.head.data.slice(0,r),this.head.data=this.head.data.slice(r)):r===this.head.data.length?a=this.shift():a=s?this._getString(r):this._getBuffer(r),a}},{key:\"first\",value:function(){return this.head.data}},{key:\"_getString\",value:function(r){var s=this.head,a=1,n=s.data;for(r-=n.length;s=s.next;){var c=s.data,f=r>c.length?c.length:r;if(f===c.length?n+=c:n+=c.slice(0,r),r-=f,r===0){f===c.length?(++a,s.next?this.head=s.next:this.head=this.tail=null):(this.head=s,s.data=c.slice(f));break}++a}return this.length-=a,n}},{key:\"_getBuffer\",value:function(r){var s=ZF.allocUnsafe(r),a=this.head,n=1;for(a.data.copy(s),r-=a.data.length;a=a.next;){var c=a.data,f=r>c.length?c.length:r;if(c.copy(s,s.length-r,0,f),r-=f,r===0){f===c.length?(++n,a.next?this.head=a.next:this.head=this.tail=null):(this.head=a,a.data=c.slice(f));break}++n}return this.length-=n,s}},{key:L0t,value:function(r,s){return iV(this,Q0t({},s,{depth:0,customInspect:!1}))}}]),e}()});var oV=G((WXt,Y1e)=>{\"use strict\";function U0t(e,t){var r=this,s=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return s||a?(t?t(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(sV,this,e)):process.nextTick(sV,this,e)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(n){!t&&n?r._writableState?r._writableState.errorEmitted?process.nextTick(XF,r):(r._writableState.errorEmitted=!0,process.nextTick(V1e,r,n)):process.nextTick(V1e,r,n):t?(process.nextTick(XF,r),t(n)):process.nextTick(XF,r)}),this)}function V1e(e,t){sV(e,t),XF(e)}function XF(e){e._writableState&&!e._writableState.emitClose||e._readableState&&!e._readableState.emitClose||e.emit(\"close\")}function _0t(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function sV(e,t){e.emit(\"error\",t)}function H0t(e,t){var r=e._readableState,s=e._writableState;r&&r.autoDestroy||s&&s.autoDestroy?e.destroy(t):e.emit(\"error\",t)}Y1e.exports={destroy:U0t,undestroy:_0t,errorOrDestroy:H0t}});var og=G((VXt,z1e)=>{\"use strict\";var J1e={};function Yc(e,t,r){r||(r=Error);function s(n,c,f){return typeof t==\"string\"?t:t(n,c,f)}class a extends r{constructor(c,f,p){super(s(c,f,p))}}a.prototype.name=r.name,a.prototype.code=e,J1e[e]=a}function K1e(e,t){if(Array.isArray(e)){let r=e.length;return e=e.map(s=>String(s)),r>2?`one of ${t} ${e.slice(0,r-1).join(\", \")}, or `+e[r-1]:r===2?`one of ${t} ${e[0]} or ${e[1]}`:`of ${t} ${e[0]}`}else return`of ${t} ${String(e)}`}function j0t(e,t,r){return e.substr(!r||r<0?0:+r,t.length)===t}function G0t(e,t,r){return(r===void 0||r>e.length)&&(r=e.length),e.substring(r-t.length,r)===t}function q0t(e,t,r){return typeof r!=\"number\"&&(r=0),r+t.length>e.length?!1:e.indexOf(t,r)!==-1}Yc(\"ERR_INVALID_OPT_VALUE\",function(e,t){return'The value \"'+t+'\" is invalid for option \"'+e+'\"'},TypeError);Yc(\"ERR_INVALID_ARG_TYPE\",function(e,t,r){let s;typeof t==\"string\"&&j0t(t,\"not \")?(s=\"must not be\",t=t.replace(/^not /,\"\")):s=\"must be\";let a;if(G0t(e,\" argument\"))a=`The ${e} ${s} ${K1e(t,\"type\")}`;else{let n=q0t(e,\".\")?\"property\":\"argument\";a=`The \"${e}\" ${n} ${s} ${K1e(t,\"type\")}`}return a+=`. Received type ${typeof r}`,a},TypeError);Yc(\"ERR_STREAM_PUSH_AFTER_EOF\",\"stream.push() after EOF\");Yc(\"ERR_METHOD_NOT_IMPLEMENTED\",function(e){return\"The \"+e+\" method is not implemented\"});Yc(\"ERR_STREAM_PREMATURE_CLOSE\",\"Premature close\");Yc(\"ERR_STREAM_DESTROYED\",function(e){return\"Cannot call \"+e+\" after a stream was destroyed\"});Yc(\"ERR_MULTIPLE_CALLBACK\",\"Callback called multiple times\");Yc(\"ERR_STREAM_CANNOT_PIPE\",\"Cannot pipe, not readable\");Yc(\"ERR_STREAM_WRITE_AFTER_END\",\"write after end\");Yc(\"ERR_STREAM_NULL_VALUES\",\"May not write null values to stream\",TypeError);Yc(\"ERR_UNKNOWN_ENCODING\",function(e){return\"Unknown encoding: \"+e},TypeError);Yc(\"ERR_STREAM_UNSHIFT_AFTER_END_EVENT\",\"stream.unshift() after end event\");z1e.exports.codes=J1e});var aV=G((YXt,Z1e)=>{\"use strict\";var W0t=og().codes.ERR_INVALID_OPT_VALUE;function V0t(e,t,r){return e.highWaterMark!=null?e.highWaterMark:t?e[r]:null}function Y0t(e,t,r,s){var a=V0t(t,s,r);if(a!=null){if(!(isFinite(a)&&Math.floor(a)===a)||a<0){var n=s?r:\"highWaterMark\";throw new W0t(n,a)}return Math.floor(a)}return e.objectMode?16:16*1024}Z1e.exports={getHighWaterMark:Y0t}});var X1e=G((KXt,lV)=>{typeof Object.create==\"function\"?lV.exports=function(t,r){r&&(t.super_=r,t.prototype=Object.create(r.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}))}:lV.exports=function(t,r){if(r){t.super_=r;var s=function(){};s.prototype=r.prototype,t.prototype=new s,t.prototype.constructor=t}}});var ag=G((JXt,uV)=>{try{if(cV=Ie(\"util\"),typeof cV.inherits!=\"function\")throw\"\";uV.exports=cV.inherits}catch{uV.exports=X1e()}var cV});var eBe=G((zXt,$1e)=>{$1e.exports=Ie(\"util\").deprecate});var pV=G((ZXt,oBe)=>{\"use strict\";oBe.exports=Yi;function rBe(e){var t=this;this.next=null,this.entry=null,this.finish=function(){Igt(t,e)}}var vw;Yi.WritableState=XD;var K0t={deprecate:eBe()},nBe=nV(),eN=Ie(\"buffer\").Buffer,J0t=global.Uint8Array||function(){};function z0t(e){return eN.from(e)}function Z0t(e){return eN.isBuffer(e)||e instanceof J0t}var AV=oV(),X0t=aV(),$0t=X0t.getHighWaterMark,lg=og().codes,egt=lg.ERR_INVALID_ARG_TYPE,tgt=lg.ERR_METHOD_NOT_IMPLEMENTED,rgt=lg.ERR_MULTIPLE_CALLBACK,ngt=lg.ERR_STREAM_CANNOT_PIPE,igt=lg.ERR_STREAM_DESTROYED,sgt=lg.ERR_STREAM_NULL_VALUES,ogt=lg.ERR_STREAM_WRITE_AFTER_END,agt=lg.ERR_UNKNOWN_ENCODING,Sw=AV.errorOrDestroy;ag()(Yi,nBe);function lgt(){}function XD(e,t,r){vw=vw||Jm(),e=e||{},typeof r!=\"boolean\"&&(r=t instanceof vw),this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode),this.highWaterMark=$0t(this,e,\"writableHighWaterMark\",r),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var s=e.decodeStrings===!1;this.decodeStrings=!s,this.defaultEncoding=e.defaultEncoding||\"utf8\",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(a){ggt(t,a)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=e.emitClose!==!1,this.autoDestroy=!!e.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new rBe(this)}XD.prototype.getBuffer=function(){for(var t=this.bufferedRequest,r=[];t;)r.push(t),t=t.next;return r};(function(){try{Object.defineProperty(XD.prototype,\"buffer\",{get:K0t.deprecate(function(){return this.getBuffer()},\"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.\",\"DEP0003\")})}catch{}})();var $F;typeof Symbol==\"function\"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]==\"function\"?($F=Function.prototype[Symbol.hasInstance],Object.defineProperty(Yi,Symbol.hasInstance,{value:function(t){return $F.call(this,t)?!0:this!==Yi?!1:t&&t._writableState instanceof XD}})):$F=function(t){return t instanceof this};function Yi(e){vw=vw||Jm();var t=this instanceof vw;if(!t&&!$F.call(Yi,this))return new Yi(e);this._writableState=new XD(e,this,t),this.writable=!0,e&&(typeof e.write==\"function\"&&(this._write=e.write),typeof e.writev==\"function\"&&(this._writev=e.writev),typeof e.destroy==\"function\"&&(this._destroy=e.destroy),typeof e.final==\"function\"&&(this._final=e.final)),nBe.call(this)}Yi.prototype.pipe=function(){Sw(this,new ngt)};function cgt(e,t){var r=new ogt;Sw(e,r),process.nextTick(t,r)}function ugt(e,t,r,s){var a;return r===null?a=new sgt:typeof r!=\"string\"&&!t.objectMode&&(a=new egt(\"chunk\",[\"string\",\"Buffer\"],r)),a?(Sw(e,a),process.nextTick(s,a),!1):!0}Yi.prototype.write=function(e,t,r){var s=this._writableState,a=!1,n=!s.objectMode&&Z0t(e);return n&&!eN.isBuffer(e)&&(e=z0t(e)),typeof t==\"function\"&&(r=t,t=null),n?t=\"buffer\":t||(t=s.defaultEncoding),typeof r!=\"function\"&&(r=lgt),s.ending?cgt(this,r):(n||ugt(this,s,e,r))&&(s.pendingcb++,a=Agt(this,s,n,e,t,r)),a};Yi.prototype.cork=function(){this._writableState.corked++};Yi.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,!e.writing&&!e.corked&&!e.bufferProcessing&&e.bufferedRequest&&iBe(this,e))};Yi.prototype.setDefaultEncoding=function(t){if(typeof t==\"string\"&&(t=t.toLowerCase()),!([\"hex\",\"utf8\",\"utf-8\",\"ascii\",\"binary\",\"base64\",\"ucs2\",\"ucs-2\",\"utf16le\",\"utf-16le\",\"raw\"].indexOf((t+\"\").toLowerCase())>-1))throw new agt(t);return this._writableState.defaultEncoding=t,this};Object.defineProperty(Yi.prototype,\"writableBuffer\",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});function fgt(e,t,r){return!e.objectMode&&e.decodeStrings!==!1&&typeof t==\"string\"&&(t=eN.from(t,r)),t}Object.defineProperty(Yi.prototype,\"writableHighWaterMark\",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function Agt(e,t,r,s,a,n){if(!r){var c=fgt(t,s,a);s!==c&&(r=!0,a=\"buffer\",s=c)}var f=t.objectMode?1:s.length;t.length+=f;var p=t.length<t.highWaterMark;if(p||(t.needDrain=!0),t.writing||t.corked){var h=t.lastBufferedRequest;t.lastBufferedRequest={chunk:s,encoding:a,isBuf:r,callback:n,next:null},h?h.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else fV(e,t,!1,f,s,a,n);return p}function fV(e,t,r,s,a,n,c){t.writelen=s,t.writecb=c,t.writing=!0,t.sync=!0,t.destroyed?t.onwrite(new igt(\"write\")):r?e._writev(a,t.onwrite):e._write(a,n,t.onwrite),t.sync=!1}function pgt(e,t,r,s,a){--t.pendingcb,r?(process.nextTick(a,s),process.nextTick(ZD,e,t),e._writableState.errorEmitted=!0,Sw(e,s)):(a(s),e._writableState.errorEmitted=!0,Sw(e,s),ZD(e,t))}function hgt(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}function ggt(e,t){var r=e._writableState,s=r.sync,a=r.writecb;if(typeof a!=\"function\")throw new rgt;if(hgt(r),t)pgt(e,r,s,t,a);else{var n=sBe(r)||e.destroyed;!n&&!r.corked&&!r.bufferProcessing&&r.bufferedRequest&&iBe(e,r),s?process.nextTick(tBe,e,r,n,a):tBe(e,r,n,a)}}function tBe(e,t,r,s){r||dgt(e,t),t.pendingcb--,s(),ZD(e,t)}function dgt(e,t){t.length===0&&t.needDrain&&(t.needDrain=!1,e.emit(\"drain\"))}function iBe(e,t){t.bufferProcessing=!0;var r=t.bufferedRequest;if(e._writev&&r&&r.next){var s=t.bufferedRequestCount,a=new Array(s),n=t.corkedRequestsFree;n.entry=r;for(var c=0,f=!0;r;)a[c]=r,r.isBuf||(f=!1),r=r.next,c+=1;a.allBuffers=f,fV(e,t,!0,t.length,a,\"\",n.finish),t.pendingcb++,t.lastBufferedRequest=null,n.next?(t.corkedRequestsFree=n.next,n.next=null):t.corkedRequestsFree=new rBe(t),t.bufferedRequestCount=0}else{for(;r;){var p=r.chunk,h=r.encoding,E=r.callback,C=t.objectMode?1:p.length;if(fV(e,t,!1,C,p,h,E),r=r.next,t.bufferedRequestCount--,t.writing)break}r===null&&(t.lastBufferedRequest=null)}t.bufferedRequest=r,t.bufferProcessing=!1}Yi.prototype._write=function(e,t,r){r(new tgt(\"_write()\"))};Yi.prototype._writev=null;Yi.prototype.end=function(e,t,r){var s=this._writableState;return typeof e==\"function\"?(r=e,e=null,t=null):typeof t==\"function\"&&(r=t,t=null),e!=null&&this.write(e,t),s.corked&&(s.corked=1,this.uncork()),s.ending||Egt(this,s,r),this};Object.defineProperty(Yi.prototype,\"writableLength\",{enumerable:!1,get:function(){return this._writableState.length}});function sBe(e){return e.ending&&e.length===0&&e.bufferedRequest===null&&!e.finished&&!e.writing}function mgt(e,t){e._final(function(r){t.pendingcb--,r&&Sw(e,r),t.prefinished=!0,e.emit(\"prefinish\"),ZD(e,t)})}function ygt(e,t){!t.prefinished&&!t.finalCalled&&(typeof e._final==\"function\"&&!t.destroyed?(t.pendingcb++,t.finalCalled=!0,process.nextTick(mgt,e,t)):(t.prefinished=!0,e.emit(\"prefinish\")))}function ZD(e,t){var r=sBe(t);if(r&&(ygt(e,t),t.pendingcb===0&&(t.finished=!0,e.emit(\"finish\"),t.autoDestroy))){var s=e._readableState;(!s||s.autoDestroy&&s.endEmitted)&&e.destroy()}return r}function Egt(e,t,r){t.ending=!0,ZD(e,t),r&&(t.finished?process.nextTick(r):e.once(\"finish\",r)),t.ended=!0,e.writable=!1}function Igt(e,t,r){var s=e.entry;for(e.entry=null;s;){var a=s.callback;t.pendingcb--,a(r),s=s.next}t.corkedRequestsFree.next=e}Object.defineProperty(Yi.prototype,\"destroyed\",{enumerable:!1,get:function(){return this._writableState===void 0?!1:this._writableState.destroyed},set:function(t){this._writableState&&(this._writableState.destroyed=t)}});Yi.prototype.destroy=AV.destroy;Yi.prototype._undestroy=AV.undestroy;Yi.prototype._destroy=function(e,t){t(e)}});var Jm=G((XXt,lBe)=>{\"use strict\";var Cgt=Object.keys||function(e){var t=[];for(var r in e)t.push(r);return t};lBe.exports=mA;var aBe=dV(),gV=pV();ag()(mA,aBe);for(hV=Cgt(gV.prototype),tN=0;tN<hV.length;tN++)rN=hV[tN],mA.prototype[rN]||(mA.prototype[rN]=gV.prototype[rN]);var hV,rN,tN;function mA(e){if(!(this instanceof mA))return new mA(e);aBe.call(this,e),gV.call(this,e),this.allowHalfOpen=!0,e&&(e.readable===!1&&(this.readable=!1),e.writable===!1&&(this.writable=!1),e.allowHalfOpen===!1&&(this.allowHalfOpen=!1,this.once(\"end\",wgt)))}Object.defineProperty(mA.prototype,\"writableHighWaterMark\",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});Object.defineProperty(mA.prototype,\"writableBuffer\",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});Object.defineProperty(mA.prototype,\"writableLength\",{enumerable:!1,get:function(){return this._writableState.length}});function wgt(){this._writableState.ended||process.nextTick(Bgt,this)}function Bgt(e){e.end()}Object.defineProperty(mA.prototype,\"destroyed\",{enumerable:!1,get:function(){return this._readableState===void 0||this._writableState===void 0?!1:this._readableState.destroyed&&this._writableState.destroyed},set:function(t){this._readableState===void 0||this._writableState===void 0||(this._readableState.destroyed=t,this._writableState.destroyed=t)}})});var fBe=G((mV,uBe)=>{var nN=Ie(\"buffer\"),sh=nN.Buffer;function cBe(e,t){for(var r in e)t[r]=e[r]}sh.from&&sh.alloc&&sh.allocUnsafe&&sh.allocUnsafeSlow?uBe.exports=nN:(cBe(nN,mV),mV.Buffer=Dw);function Dw(e,t,r){return sh(e,t,r)}cBe(sh,Dw);Dw.from=function(e,t,r){if(typeof e==\"number\")throw new TypeError(\"Argument must not be a number\");return sh(e,t,r)};Dw.alloc=function(e,t,r){if(typeof e!=\"number\")throw new TypeError(\"Argument must be a number\");var s=sh(e);return t!==void 0?typeof r==\"string\"?s.fill(t,r):s.fill(t):s.fill(0),s};Dw.allocUnsafe=function(e){if(typeof e!=\"number\")throw new TypeError(\"Argument must be a number\");return sh(e)};Dw.allocUnsafeSlow=function(e){if(typeof e!=\"number\")throw new TypeError(\"Argument must be a number\");return nN.SlowBuffer(e)}});var IV=G(pBe=>{\"use strict\";var EV=fBe().Buffer,ABe=EV.isEncoding||function(e){switch(e=\"\"+e,e&&e.toLowerCase()){case\"hex\":case\"utf8\":case\"utf-8\":case\"ascii\":case\"binary\":case\"base64\":case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":case\"raw\":return!0;default:return!1}};function vgt(e){if(!e)return\"utf8\";for(var t;;)switch(e){case\"utf8\":case\"utf-8\":return\"utf8\";case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return\"utf16le\";case\"latin1\":case\"binary\":return\"latin1\";case\"base64\":case\"ascii\":case\"hex\":return e;default:if(t)return;e=(\"\"+e).toLowerCase(),t=!0}}function Sgt(e){var t=vgt(e);if(typeof t!=\"string\"&&(EV.isEncoding===ABe||!ABe(e)))throw new Error(\"Unknown encoding: \"+e);return t||e}pBe.StringDecoder=$D;function $D(e){this.encoding=Sgt(e);var t;switch(this.encoding){case\"utf16le\":this.text=Qgt,this.end=Rgt,t=4;break;case\"utf8\":this.fillLast=Pgt,t=4;break;case\"base64\":this.text=Tgt,this.end=Fgt,t=3;break;default:this.write=Ngt,this.end=Ogt;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=EV.allocUnsafe(t)}$D.prototype.write=function(e){if(e.length===0)return\"\";var t,r;if(this.lastNeed){if(t=this.fillLast(e),t===void 0)return\"\";r=this.lastNeed,this.lastNeed=0}else r=0;return r<e.length?t?t+this.text(e,r):this.text(e,r):t||\"\"};$D.prototype.end=kgt;$D.prototype.text=xgt;$D.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length};function yV(e){return e<=127?0:e>>5===6?2:e>>4===14?3:e>>3===30?4:e>>6===2?-1:-2}function Dgt(e,t,r){var s=t.length-1;if(s<r)return 0;var a=yV(t[s]);return a>=0?(a>0&&(e.lastNeed=a-1),a):--s<r||a===-2?0:(a=yV(t[s]),a>=0?(a>0&&(e.lastNeed=a-2),a):--s<r||a===-2?0:(a=yV(t[s]),a>=0?(a>0&&(a===2?a=0:e.lastNeed=a-3),a):0))}function bgt(e,t,r){if((t[0]&192)!==128)return e.lastNeed=0,\"\\uFFFD\";if(e.lastNeed>1&&t.length>1){if((t[1]&192)!==128)return e.lastNeed=1,\"\\uFFFD\";if(e.lastNeed>2&&t.length>2&&(t[2]&192)!==128)return e.lastNeed=2,\"\\uFFFD\"}}function Pgt(e){var t=this.lastTotal-this.lastNeed,r=bgt(this,e,t);if(r!==void 0)return r;if(this.lastNeed<=e.length)return e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length}function xgt(e,t){var r=Dgt(this,e,t);if(!this.lastNeed)return e.toString(\"utf8\",t);this.lastTotal=r;var s=e.length-(r-this.lastNeed);return e.copy(this.lastChar,0,s),e.toString(\"utf8\",t,s)}function kgt(e){var t=e&&e.length?this.write(e):\"\";return this.lastNeed?t+\"\\uFFFD\":t}function Qgt(e,t){if((e.length-t)%2===0){var r=e.toString(\"utf16le\",t);if(r){var s=r.charCodeAt(r.length-1);if(s>=55296&&s<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString(\"utf16le\",t,e.length-1)}function Rgt(e){var t=e&&e.length?this.write(e):\"\";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return t+this.lastChar.toString(\"utf16le\",0,r)}return t}function Tgt(e,t){var r=(e.length-t)%3;return r===0?e.toString(\"base64\",t):(this.lastNeed=3-r,this.lastTotal=3,r===1?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString(\"base64\",t,e.length-r))}function Fgt(e){var t=e&&e.length?this.write(e):\"\";return this.lastNeed?t+this.lastChar.toString(\"base64\",0,3-this.lastNeed):t}function Ngt(e){return e.toString(this.encoding)}function Ogt(e){return e&&e.length?this.write(e):\"\"}});var iN=G((e$t,dBe)=>{\"use strict\";var hBe=og().codes.ERR_STREAM_PREMATURE_CLOSE;function Lgt(e){var t=!1;return function(){if(!t){t=!0;for(var r=arguments.length,s=new Array(r),a=0;a<r;a++)s[a]=arguments[a];e.apply(this,s)}}}function Mgt(){}function Ugt(e){return e.setHeader&&typeof e.abort==\"function\"}function gBe(e,t,r){if(typeof t==\"function\")return gBe(e,null,t);t||(t={}),r=Lgt(r||Mgt);var s=t.readable||t.readable!==!1&&e.readable,a=t.writable||t.writable!==!1&&e.writable,n=function(){e.writable||f()},c=e._writableState&&e._writableState.finished,f=function(){a=!1,c=!0,s||r.call(e)},p=e._readableState&&e._readableState.endEmitted,h=function(){s=!1,p=!0,a||r.call(e)},E=function(I){r.call(e,I)},C=function(){var I;if(s&&!p)return(!e._readableState||!e._readableState.ended)&&(I=new hBe),r.call(e,I);if(a&&!c)return(!e._writableState||!e._writableState.ended)&&(I=new hBe),r.call(e,I)},S=function(){e.req.on(\"finish\",f)};return Ugt(e)?(e.on(\"complete\",f),e.on(\"abort\",C),e.req?S():e.on(\"request\",S)):a&&!e._writableState&&(e.on(\"end\",n),e.on(\"close\",n)),e.on(\"end\",h),e.on(\"finish\",f),t.error!==!1&&e.on(\"error\",E),e.on(\"close\",C),function(){e.removeListener(\"complete\",f),e.removeListener(\"abort\",C),e.removeListener(\"request\",S),e.req&&e.req.removeListener(\"finish\",f),e.removeListener(\"end\",n),e.removeListener(\"close\",n),e.removeListener(\"finish\",f),e.removeListener(\"end\",h),e.removeListener(\"error\",E),e.removeListener(\"close\",C)}}dBe.exports=gBe});var yBe=G((t$t,mBe)=>{\"use strict\";var sN;function cg(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var _gt=iN(),ug=Symbol(\"lastResolve\"),zm=Symbol(\"lastReject\"),eb=Symbol(\"error\"),oN=Symbol(\"ended\"),Zm=Symbol(\"lastPromise\"),CV=Symbol(\"handlePromise\"),Xm=Symbol(\"stream\");function fg(e,t){return{value:e,done:t}}function Hgt(e){var t=e[ug];if(t!==null){var r=e[Xm].read();r!==null&&(e[Zm]=null,e[ug]=null,e[zm]=null,t(fg(r,!1)))}}function jgt(e){process.nextTick(Hgt,e)}function Ggt(e,t){return function(r,s){e.then(function(){if(t[oN]){r(fg(void 0,!0));return}t[CV](r,s)},s)}}var qgt=Object.getPrototypeOf(function(){}),Wgt=Object.setPrototypeOf((sN={get stream(){return this[Xm]},next:function(){var t=this,r=this[eb];if(r!==null)return Promise.reject(r);if(this[oN])return Promise.resolve(fg(void 0,!0));if(this[Xm].destroyed)return new Promise(function(c,f){process.nextTick(function(){t[eb]?f(t[eb]):c(fg(void 0,!0))})});var s=this[Zm],a;if(s)a=new Promise(Ggt(s,this));else{var n=this[Xm].read();if(n!==null)return Promise.resolve(fg(n,!1));a=new Promise(this[CV])}return this[Zm]=a,a}},cg(sN,Symbol.asyncIterator,function(){return this}),cg(sN,\"return\",function(){var t=this;return new Promise(function(r,s){t[Xm].destroy(null,function(a){if(a){s(a);return}r(fg(void 0,!0))})})}),sN),qgt),Vgt=function(t){var r,s=Object.create(Wgt,(r={},cg(r,Xm,{value:t,writable:!0}),cg(r,ug,{value:null,writable:!0}),cg(r,zm,{value:null,writable:!0}),cg(r,eb,{value:null,writable:!0}),cg(r,oN,{value:t._readableState.endEmitted,writable:!0}),cg(r,CV,{value:function(n,c){var f=s[Xm].read();f?(s[Zm]=null,s[ug]=null,s[zm]=null,n(fg(f,!1))):(s[ug]=n,s[zm]=c)},writable:!0}),r));return s[Zm]=null,_gt(t,function(a){if(a&&a.code!==\"ERR_STREAM_PREMATURE_CLOSE\"){var n=s[zm];n!==null&&(s[Zm]=null,s[ug]=null,s[zm]=null,n(a)),s[eb]=a;return}var c=s[ug];c!==null&&(s[Zm]=null,s[ug]=null,s[zm]=null,c(fg(void 0,!0))),s[oN]=!0}),t.on(\"readable\",jgt.bind(null,s)),s};mBe.exports=Vgt});var wBe=G((r$t,CBe)=>{\"use strict\";function EBe(e,t,r,s,a,n,c){try{var f=e[n](c),p=f.value}catch(h){r(h);return}f.done?t(p):Promise.resolve(p).then(s,a)}function Ygt(e){return function(){var t=this,r=arguments;return new Promise(function(s,a){var n=e.apply(t,r);function c(p){EBe(n,s,a,c,f,\"next\",p)}function f(p){EBe(n,s,a,c,f,\"throw\",p)}c(void 0)})}}function IBe(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable})),r.push.apply(r,s)}return r}function Kgt(e){for(var t=1;t<arguments.length;t++){var r=arguments[t]!=null?arguments[t]:{};t%2?IBe(Object(r),!0).forEach(function(s){Jgt(e,s,r[s])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):IBe(Object(r)).forEach(function(s){Object.defineProperty(e,s,Object.getOwnPropertyDescriptor(r,s))})}return e}function Jgt(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var zgt=og().codes.ERR_INVALID_ARG_TYPE;function Zgt(e,t,r){var s;if(t&&typeof t.next==\"function\")s=t;else if(t&&t[Symbol.asyncIterator])s=t[Symbol.asyncIterator]();else if(t&&t[Symbol.iterator])s=t[Symbol.iterator]();else throw new zgt(\"iterable\",[\"Iterable\"],t);var a=new e(Kgt({objectMode:!0},r)),n=!1;a._read=function(){n||(n=!0,c())};function c(){return f.apply(this,arguments)}function f(){return f=Ygt(function*(){try{var p=yield s.next(),h=p.value,E=p.done;E?a.push(null):a.push(yield h)?c():n=!1}catch(C){a.destroy(C)}}),f.apply(this,arguments)}return a}CBe.exports=Zgt});var dV=G((i$t,RBe)=>{\"use strict\";RBe.exports=kn;var bw;kn.ReadableState=DBe;var n$t=Ie(\"events\").EventEmitter,SBe=function(t,r){return t.listeners(r).length},rb=nV(),aN=Ie(\"buffer\").Buffer,Xgt=global.Uint8Array||function(){};function $gt(e){return aN.from(e)}function edt(e){return aN.isBuffer(e)||e instanceof Xgt}var wV=Ie(\"util\"),un;wV&&wV.debuglog?un=wV.debuglog(\"stream\"):un=function(){};var tdt=W1e(),xV=oV(),rdt=aV(),ndt=rdt.getHighWaterMark,lN=og().codes,idt=lN.ERR_INVALID_ARG_TYPE,sdt=lN.ERR_STREAM_PUSH_AFTER_EOF,odt=lN.ERR_METHOD_NOT_IMPLEMENTED,adt=lN.ERR_STREAM_UNSHIFT_AFTER_END_EVENT,Pw,BV,vV;ag()(kn,rb);var tb=xV.errorOrDestroy,SV=[\"error\",\"close\",\"destroy\",\"pause\",\"resume\"];function ldt(e,t,r){if(typeof e.prependListener==\"function\")return e.prependListener(t,r);!e._events||!e._events[t]?e.on(t,r):Array.isArray(e._events[t])?e._events[t].unshift(r):e._events[t]=[r,e._events[t]]}function DBe(e,t,r){bw=bw||Jm(),e=e||{},typeof r!=\"boolean\"&&(r=t instanceof bw),this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode),this.highWaterMark=ndt(this,e,\"readableHighWaterMark\",r),this.buffer=new tdt,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=e.emitClose!==!1,this.autoDestroy=!!e.autoDestroy,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||\"utf8\",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(Pw||(Pw=IV().StringDecoder),this.decoder=new Pw(e.encoding),this.encoding=e.encoding)}function kn(e){if(bw=bw||Jm(),!(this instanceof kn))return new kn(e);var t=this instanceof bw;this._readableState=new DBe(e,this,t),this.readable=!0,e&&(typeof e.read==\"function\"&&(this._read=e.read),typeof e.destroy==\"function\"&&(this._destroy=e.destroy)),rb.call(this)}Object.defineProperty(kn.prototype,\"destroyed\",{enumerable:!1,get:function(){return this._readableState===void 0?!1:this._readableState.destroyed},set:function(t){this._readableState&&(this._readableState.destroyed=t)}});kn.prototype.destroy=xV.destroy;kn.prototype._undestroy=xV.undestroy;kn.prototype._destroy=function(e,t){t(e)};kn.prototype.push=function(e,t){var r=this._readableState,s;return r.objectMode?s=!0:typeof e==\"string\"&&(t=t||r.defaultEncoding,t!==r.encoding&&(e=aN.from(e,t),t=\"\"),s=!0),bBe(this,e,t,!1,s)};kn.prototype.unshift=function(e){return bBe(this,e,null,!0,!1)};function bBe(e,t,r,s,a){un(\"readableAddChunk\",t);var n=e._readableState;if(t===null)n.reading=!1,fdt(e,n);else{var c;if(a||(c=cdt(n,t)),c)tb(e,c);else if(n.objectMode||t&&t.length>0)if(typeof t!=\"string\"&&!n.objectMode&&Object.getPrototypeOf(t)!==aN.prototype&&(t=$gt(t)),s)n.endEmitted?tb(e,new adt):DV(e,n,t,!0);else if(n.ended)tb(e,new sdt);else{if(n.destroyed)return!1;n.reading=!1,n.decoder&&!r?(t=n.decoder.write(t),n.objectMode||t.length!==0?DV(e,n,t,!1):PV(e,n)):DV(e,n,t,!1)}else s||(n.reading=!1,PV(e,n))}return!n.ended&&(n.length<n.highWaterMark||n.length===0)}function DV(e,t,r,s){t.flowing&&t.length===0&&!t.sync?(t.awaitDrain=0,e.emit(\"data\",r)):(t.length+=t.objectMode?1:r.length,s?t.buffer.unshift(r):t.buffer.push(r),t.needReadable&&cN(e)),PV(e,t)}function cdt(e,t){var r;return!edt(t)&&typeof t!=\"string\"&&t!==void 0&&!e.objectMode&&(r=new idt(\"chunk\",[\"string\",\"Buffer\",\"Uint8Array\"],t)),r}kn.prototype.isPaused=function(){return this._readableState.flowing===!1};kn.prototype.setEncoding=function(e){Pw||(Pw=IV().StringDecoder);var t=new Pw(e);this._readableState.decoder=t,this._readableState.encoding=this._readableState.decoder.encoding;for(var r=this._readableState.buffer.head,s=\"\";r!==null;)s+=t.write(r.data),r=r.next;return this._readableState.buffer.clear(),s!==\"\"&&this._readableState.buffer.push(s),this._readableState.length=s.length,this};var BBe=1073741824;function udt(e){return e>=BBe?e=BBe:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}function vBe(e,t){return e<=0||t.length===0&&t.ended?0:t.objectMode?1:e!==e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=udt(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}kn.prototype.read=function(e){un(\"read\",e),e=parseInt(e,10);var t=this._readableState,r=e;if(e!==0&&(t.emittedReadable=!1),e===0&&t.needReadable&&((t.highWaterMark!==0?t.length>=t.highWaterMark:t.length>0)||t.ended))return un(\"read: emitReadable\",t.length,t.ended),t.length===0&&t.ended?bV(this):cN(this),null;if(e=vBe(e,t),e===0&&t.ended)return t.length===0&&bV(this),null;var s=t.needReadable;un(\"need readable\",s),(t.length===0||t.length-e<t.highWaterMark)&&(s=!0,un(\"length less than watermark\",s)),t.ended||t.reading?(s=!1,un(\"reading or ended\",s)):s&&(un(\"do read\"),t.reading=!0,t.sync=!0,t.length===0&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=vBe(r,t)));var a;return e>0?a=kBe(e,t):a=null,a===null?(t.needReadable=t.length<=t.highWaterMark,e=0):(t.length-=e,t.awaitDrain=0),t.length===0&&(t.ended||(t.needReadable=!0),r!==e&&t.ended&&bV(this)),a!==null&&this.emit(\"data\",a),a};function fdt(e,t){if(un(\"onEofChunk\"),!t.ended){if(t.decoder){var r=t.decoder.end();r&&r.length&&(t.buffer.push(r),t.length+=t.objectMode?1:r.length)}t.ended=!0,t.sync?cN(e):(t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,PBe(e)))}}function cN(e){var t=e._readableState;un(\"emitReadable\",t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(un(\"emitReadable\",t.flowing),t.emittedReadable=!0,process.nextTick(PBe,e))}function PBe(e){var t=e._readableState;un(\"emitReadable_\",t.destroyed,t.length,t.ended),!t.destroyed&&(t.length||t.ended)&&(e.emit(\"readable\"),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,kV(e)}function PV(e,t){t.readingMore||(t.readingMore=!0,process.nextTick(Adt,e,t))}function Adt(e,t){for(;!t.reading&&!t.ended&&(t.length<t.highWaterMark||t.flowing&&t.length===0);){var r=t.length;if(un(\"maybeReadMore read 0\"),e.read(0),r===t.length)break}t.readingMore=!1}kn.prototype._read=function(e){tb(this,new odt(\"_read()\"))};kn.prototype.pipe=function(e,t){var r=this,s=this._readableState;switch(s.pipesCount){case 0:s.pipes=e;break;case 1:s.pipes=[s.pipes,e];break;default:s.pipes.push(e);break}s.pipesCount+=1,un(\"pipe count=%d opts=%j\",s.pipesCount,t);var a=(!t||t.end!==!1)&&e!==process.stdout&&e!==process.stderr,n=a?f:T;s.endEmitted?process.nextTick(n):r.once(\"end\",n),e.on(\"unpipe\",c);function c(O,U){un(\"onunpipe\"),O===r&&U&&U.hasUnpiped===!1&&(U.hasUnpiped=!0,E())}function f(){un(\"onend\"),e.end()}var p=pdt(r);e.on(\"drain\",p);var h=!1;function E(){un(\"cleanup\"),e.removeListener(\"close\",x),e.removeListener(\"finish\",I),e.removeListener(\"drain\",p),e.removeListener(\"error\",S),e.removeListener(\"unpipe\",c),r.removeListener(\"end\",f),r.removeListener(\"end\",T),r.removeListener(\"data\",C),h=!0,s.awaitDrain&&(!e._writableState||e._writableState.needDrain)&&p()}r.on(\"data\",C);function C(O){un(\"ondata\");var U=e.write(O);un(\"dest.write\",U),U===!1&&((s.pipesCount===1&&s.pipes===e||s.pipesCount>1&&QBe(s.pipes,e)!==-1)&&!h&&(un(\"false write response, pause\",s.awaitDrain),s.awaitDrain++),r.pause())}function S(O){un(\"onerror\",O),T(),e.removeListener(\"error\",S),SBe(e,\"error\")===0&&tb(e,O)}ldt(e,\"error\",S);function x(){e.removeListener(\"finish\",I),T()}e.once(\"close\",x);function I(){un(\"onfinish\"),e.removeListener(\"close\",x),T()}e.once(\"finish\",I);function T(){un(\"unpipe\"),r.unpipe(e)}return e.emit(\"pipe\",r),s.flowing||(un(\"pipe resume\"),r.resume()),e};function pdt(e){return function(){var r=e._readableState;un(\"pipeOnDrain\",r.awaitDrain),r.awaitDrain&&r.awaitDrain--,r.awaitDrain===0&&SBe(e,\"data\")&&(r.flowing=!0,kV(e))}}kn.prototype.unpipe=function(e){var t=this._readableState,r={hasUnpiped:!1};if(t.pipesCount===0)return this;if(t.pipesCount===1)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit(\"unpipe\",this,r),this);if(!e){var s=t.pipes,a=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var n=0;n<a;n++)s[n].emit(\"unpipe\",this,{hasUnpiped:!1});return this}var c=QBe(t.pipes,e);return c===-1?this:(t.pipes.splice(c,1),t.pipesCount-=1,t.pipesCount===1&&(t.pipes=t.pipes[0]),e.emit(\"unpipe\",this,r),this)};kn.prototype.on=function(e,t){var r=rb.prototype.on.call(this,e,t),s=this._readableState;return e===\"data\"?(s.readableListening=this.listenerCount(\"readable\")>0,s.flowing!==!1&&this.resume()):e===\"readable\"&&!s.endEmitted&&!s.readableListening&&(s.readableListening=s.needReadable=!0,s.flowing=!1,s.emittedReadable=!1,un(\"on readable\",s.length,s.reading),s.length?cN(this):s.reading||process.nextTick(hdt,this)),r};kn.prototype.addListener=kn.prototype.on;kn.prototype.removeListener=function(e,t){var r=rb.prototype.removeListener.call(this,e,t);return e===\"readable\"&&process.nextTick(xBe,this),r};kn.prototype.removeAllListeners=function(e){var t=rb.prototype.removeAllListeners.apply(this,arguments);return(e===\"readable\"||e===void 0)&&process.nextTick(xBe,this),t};function xBe(e){var t=e._readableState;t.readableListening=e.listenerCount(\"readable\")>0,t.resumeScheduled&&!t.paused?t.flowing=!0:e.listenerCount(\"data\")>0&&e.resume()}function hdt(e){un(\"readable nexttick read 0\"),e.read(0)}kn.prototype.resume=function(){var e=this._readableState;return e.flowing||(un(\"resume\"),e.flowing=!e.readableListening,gdt(this,e)),e.paused=!1,this};function gdt(e,t){t.resumeScheduled||(t.resumeScheduled=!0,process.nextTick(ddt,e,t))}function ddt(e,t){un(\"resume\",t.reading),t.reading||e.read(0),t.resumeScheduled=!1,e.emit(\"resume\"),kV(e),t.flowing&&!t.reading&&e.read(0)}kn.prototype.pause=function(){return un(\"call pause flowing=%j\",this._readableState.flowing),this._readableState.flowing!==!1&&(un(\"pause\"),this._readableState.flowing=!1,this.emit(\"pause\")),this._readableState.paused=!0,this};function kV(e){var t=e._readableState;for(un(\"flow\",t.flowing);t.flowing&&e.read()!==null;);}kn.prototype.wrap=function(e){var t=this,r=this._readableState,s=!1;e.on(\"end\",function(){if(un(\"wrapped end\"),r.decoder&&!r.ended){var c=r.decoder.end();c&&c.length&&t.push(c)}t.push(null)}),e.on(\"data\",function(c){if(un(\"wrapped data\"),r.decoder&&(c=r.decoder.write(c)),!(r.objectMode&&c==null)&&!(!r.objectMode&&(!c||!c.length))){var f=t.push(c);f||(s=!0,e.pause())}});for(var a in e)this[a]===void 0&&typeof e[a]==\"function\"&&(this[a]=function(f){return function(){return e[f].apply(e,arguments)}}(a));for(var n=0;n<SV.length;n++)e.on(SV[n],this.emit.bind(this,SV[n]));return this._read=function(c){un(\"wrapped _read\",c),s&&(s=!1,e.resume())},this};typeof Symbol==\"function\"&&(kn.prototype[Symbol.asyncIterator]=function(){return BV===void 0&&(BV=yBe()),BV(this)});Object.defineProperty(kn.prototype,\"readableHighWaterMark\",{enumerable:!1,get:function(){return this._readableState.highWaterMark}});Object.defineProperty(kn.prototype,\"readableBuffer\",{enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}});Object.defineProperty(kn.prototype,\"readableFlowing\",{enumerable:!1,get:function(){return this._readableState.flowing},set:function(t){this._readableState&&(this._readableState.flowing=t)}});kn._fromList=kBe;Object.defineProperty(kn.prototype,\"readableLength\",{enumerable:!1,get:function(){return this._readableState.length}});function kBe(e,t){if(t.length===0)return null;var r;return t.objectMode?r=t.buffer.shift():!e||e>=t.length?(t.decoder?r=t.buffer.join(\"\"):t.buffer.length===1?r=t.buffer.first():r=t.buffer.concat(t.length),t.buffer.clear()):r=t.buffer.consume(e,t.decoder),r}function bV(e){var t=e._readableState;un(\"endReadable\",t.endEmitted),t.endEmitted||(t.ended=!0,process.nextTick(mdt,t,e))}function mdt(e,t){if(un(\"endReadableNT\",e.endEmitted,e.length),!e.endEmitted&&e.length===0&&(e.endEmitted=!0,t.readable=!1,t.emit(\"end\"),e.autoDestroy)){var r=t._writableState;(!r||r.autoDestroy&&r.finished)&&t.destroy()}}typeof Symbol==\"function\"&&(kn.from=function(e,t){return vV===void 0&&(vV=wBe()),vV(kn,e,t)});function QBe(e,t){for(var r=0,s=e.length;r<s;r++)if(e[r]===t)return r;return-1}});var QV=G((s$t,FBe)=>{\"use strict\";FBe.exports=oh;var uN=og().codes,ydt=uN.ERR_METHOD_NOT_IMPLEMENTED,Edt=uN.ERR_MULTIPLE_CALLBACK,Idt=uN.ERR_TRANSFORM_ALREADY_TRANSFORMING,Cdt=uN.ERR_TRANSFORM_WITH_LENGTH_0,fN=Jm();ag()(oh,fN);function wdt(e,t){var r=this._transformState;r.transforming=!1;var s=r.writecb;if(s===null)return this.emit(\"error\",new Edt);r.writechunk=null,r.writecb=null,t!=null&&this.push(t),s(e);var a=this._readableState;a.reading=!1,(a.needReadable||a.length<a.highWaterMark)&&this._read(a.highWaterMark)}function oh(e){if(!(this instanceof oh))return new oh(e);fN.call(this,e),this._transformState={afterTransform:wdt.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&(typeof e.transform==\"function\"&&(this._transform=e.transform),typeof e.flush==\"function\"&&(this._flush=e.flush)),this.on(\"prefinish\",Bdt)}function Bdt(){var e=this;typeof this._flush==\"function\"&&!this._readableState.destroyed?this._flush(function(t,r){TBe(e,t,r)}):TBe(this,null,null)}oh.prototype.push=function(e,t){return this._transformState.needTransform=!1,fN.prototype.push.call(this,e,t)};oh.prototype._transform=function(e,t,r){r(new ydt(\"_transform()\"))};oh.prototype._write=function(e,t,r){var s=this._transformState;if(s.writecb=r,s.writechunk=e,s.writeencoding=t,!s.transforming){var a=this._readableState;(s.needTransform||a.needReadable||a.length<a.highWaterMark)&&this._read(a.highWaterMark)}};oh.prototype._read=function(e){var t=this._transformState;t.writechunk!==null&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0};oh.prototype._destroy=function(e,t){fN.prototype._destroy.call(this,e,function(r){t(r)})};function TBe(e,t,r){if(t)return e.emit(\"error\",t);if(r!=null&&e.push(r),e._writableState.length)throw new Cdt;if(e._transformState.transforming)throw new Idt;return e.push(null)}});var LBe=G((o$t,OBe)=>{\"use strict\";OBe.exports=nb;var NBe=QV();ag()(nb,NBe);function nb(e){if(!(this instanceof nb))return new nb(e);NBe.call(this,e)}nb.prototype._transform=function(e,t,r){r(null,e)}});var jBe=G((a$t,HBe)=>{\"use strict\";var RV;function vdt(e){var t=!1;return function(){t||(t=!0,e.apply(void 0,arguments))}}var _Be=og().codes,Sdt=_Be.ERR_MISSING_ARGS,Ddt=_Be.ERR_STREAM_DESTROYED;function MBe(e){if(e)throw e}function bdt(e){return e.setHeader&&typeof e.abort==\"function\"}function Pdt(e,t,r,s){s=vdt(s);var a=!1;e.on(\"close\",function(){a=!0}),RV===void 0&&(RV=iN()),RV(e,{readable:t,writable:r},function(c){if(c)return s(c);a=!0,s()});var n=!1;return function(c){if(!a&&!n){if(n=!0,bdt(e))return e.abort();if(typeof e.destroy==\"function\")return e.destroy();s(c||new Ddt(\"pipe\"))}}}function UBe(e){e()}function xdt(e,t){return e.pipe(t)}function kdt(e){return!e.length||typeof e[e.length-1]!=\"function\"?MBe:e.pop()}function Qdt(){for(var e=arguments.length,t=new Array(e),r=0;r<e;r++)t[r]=arguments[r];var s=kdt(t);if(Array.isArray(t[0])&&(t=t[0]),t.length<2)throw new Sdt(\"streams\");var a,n=t.map(function(c,f){var p=f<t.length-1,h=f>0;return Pdt(c,p,h,function(E){a||(a=E),E&&n.forEach(UBe),!p&&(n.forEach(UBe),s(a))})});return t.reduce(xdt)}HBe.exports=Qdt});var xw=G((Kc,sb)=>{var ib=Ie(\"stream\");process.env.READABLE_STREAM===\"disable\"&&ib?(sb.exports=ib.Readable,Object.assign(sb.exports,ib),sb.exports.Stream=ib):(Kc=sb.exports=dV(),Kc.Stream=ib||Kc,Kc.Readable=Kc,Kc.Writable=pV(),Kc.Duplex=Jm(),Kc.Transform=QV(),Kc.PassThrough=LBe(),Kc.finished=iN(),Kc.pipeline=jBe())});var WBe=G((l$t,qBe)=>{\"use strict\";var{Buffer:ff}=Ie(\"buffer\"),GBe=Symbol.for(\"BufferList\");function wi(e){if(!(this instanceof wi))return new wi(e);wi._init.call(this,e)}wi._init=function(t){Object.defineProperty(this,GBe,{value:!0}),this._bufs=[],this.length=0,t&&this.append(t)};wi.prototype._new=function(t){return new wi(t)};wi.prototype._offset=function(t){if(t===0)return[0,0];let r=0;for(let s=0;s<this._bufs.length;s++){let a=r+this._bufs[s].length;if(t<a||s===this._bufs.length-1)return[s,t-r];r=a}};wi.prototype._reverseOffset=function(e){let t=e[0],r=e[1];for(let s=0;s<t;s++)r+=this._bufs[s].length;return r};wi.prototype.get=function(t){if(t>this.length||t<0)return;let r=this._offset(t);return this._bufs[r[0]][r[1]]};wi.prototype.slice=function(t,r){return typeof t==\"number\"&&t<0&&(t+=this.length),typeof r==\"number\"&&r<0&&(r+=this.length),this.copy(null,0,t,r)};wi.prototype.copy=function(t,r,s,a){if((typeof s!=\"number\"||s<0)&&(s=0),(typeof a!=\"number\"||a>this.length)&&(a=this.length),s>=this.length||a<=0)return t||ff.alloc(0);let n=!!t,c=this._offset(s),f=a-s,p=f,h=n&&r||0,E=c[1];if(s===0&&a===this.length){if(!n)return this._bufs.length===1?this._bufs[0]:ff.concat(this._bufs,this.length);for(let C=0;C<this._bufs.length;C++)this._bufs[C].copy(t,h),h+=this._bufs[C].length;return t}if(p<=this._bufs[c[0]].length-E)return n?this._bufs[c[0]].copy(t,r,E,E+p):this._bufs[c[0]].slice(E,E+p);n||(t=ff.allocUnsafe(f));for(let C=c[0];C<this._bufs.length;C++){let S=this._bufs[C].length-E;if(p>S)this._bufs[C].copy(t,h,E),h+=S;else{this._bufs[C].copy(t,h,E,E+p),h+=S;break}p-=S,E&&(E=0)}return t.length>h?t.slice(0,h):t};wi.prototype.shallowSlice=function(t,r){if(t=t||0,r=typeof r!=\"number\"?this.length:r,t<0&&(t+=this.length),r<0&&(r+=this.length),t===r)return this._new();let s=this._offset(t),a=this._offset(r),n=this._bufs.slice(s[0],a[0]+1);return a[1]===0?n.pop():n[n.length-1]=n[n.length-1].slice(0,a[1]),s[1]!==0&&(n[0]=n[0].slice(s[1])),this._new(n)};wi.prototype.toString=function(t,r,s){return this.slice(r,s).toString(t)};wi.prototype.consume=function(t){if(t=Math.trunc(t),Number.isNaN(t)||t<=0)return this;for(;this._bufs.length;)if(t>=this._bufs[0].length)t-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift();else{this._bufs[0]=this._bufs[0].slice(t),this.length-=t;break}return this};wi.prototype.duplicate=function(){let t=this._new();for(let r=0;r<this._bufs.length;r++)t.append(this._bufs[r]);return t};wi.prototype.append=function(t){if(t==null)return this;if(t.buffer)this._appendBuffer(ff.from(t.buffer,t.byteOffset,t.byteLength));else if(Array.isArray(t))for(let r=0;r<t.length;r++)this.append(t[r]);else if(this._isBufferList(t))for(let r=0;r<t._bufs.length;r++)this.append(t._bufs[r]);else typeof t==\"number\"&&(t=t.toString()),this._appendBuffer(ff.from(t));return this};wi.prototype._appendBuffer=function(t){this._bufs.push(t),this.length+=t.length};wi.prototype.indexOf=function(e,t,r){if(r===void 0&&typeof t==\"string\"&&(r=t,t=void 0),typeof e==\"function\"||Array.isArray(e))throw new TypeError('The \"value\" argument must be one of type string, Buffer, BufferList, or Uint8Array.');if(typeof e==\"number\"?e=ff.from([e]):typeof e==\"string\"?e=ff.from(e,r):this._isBufferList(e)?e=e.slice():Array.isArray(e.buffer)?e=ff.from(e.buffer,e.byteOffset,e.byteLength):ff.isBuffer(e)||(e=ff.from(e)),t=Number(t||0),isNaN(t)&&(t=0),t<0&&(t=this.length+t),t<0&&(t=0),e.length===0)return t>this.length?this.length:t;let s=this._offset(t),a=s[0],n=s[1];for(;a<this._bufs.length;a++){let c=this._bufs[a];for(;n<c.length;)if(c.length-n>=e.length){let p=c.indexOf(e,n);if(p!==-1)return this._reverseOffset([a,p]);n=c.length-e.length+1}else{let p=this._reverseOffset([a,n]);if(this._match(p,e))return p;n++}n=0}return-1};wi.prototype._match=function(e,t){if(this.length-e<t.length)return!1;for(let r=0;r<t.length;r++)if(this.get(e+r)!==t[r])return!1;return!0};(function(){let e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1,readIntBE:null,readIntLE:null,readUIntBE:null,readUIntLE:null};for(let t in e)(function(r){e[r]===null?wi.prototype[r]=function(s,a){return this.slice(s,s+a)[r](0,a)}:wi.prototype[r]=function(s=0){return this.slice(s,s+e[r])[r](0)}})(t)})();wi.prototype._isBufferList=function(t){return t instanceof wi||wi.isBufferList(t)};wi.isBufferList=function(t){return t!=null&&t[GBe]};qBe.exports=wi});var VBe=G((c$t,AN)=>{\"use strict\";var TV=xw().Duplex,Rdt=ag(),ob=WBe();function oa(e){if(!(this instanceof oa))return new oa(e);if(typeof e==\"function\"){this._callback=e;let t=function(s){this._callback&&(this._callback(s),this._callback=null)}.bind(this);this.on(\"pipe\",function(s){s.on(\"error\",t)}),this.on(\"unpipe\",function(s){s.removeListener(\"error\",t)}),e=null}ob._init.call(this,e),TV.call(this)}Rdt(oa,TV);Object.assign(oa.prototype,ob.prototype);oa.prototype._new=function(t){return new oa(t)};oa.prototype._write=function(t,r,s){this._appendBuffer(t),typeof s==\"function\"&&s()};oa.prototype._read=function(t){if(!this.length)return this.push(null);t=Math.min(t,this.length),this.push(this.slice(0,t)),this.consume(t)};oa.prototype.end=function(t){TV.prototype.end.call(this,t),this._callback&&(this._callback(null,this.slice()),this._callback=null)};oa.prototype._destroy=function(t,r){this._bufs.length=0,this.length=0,r(t)};oa.prototype._isBufferList=function(t){return t instanceof oa||t instanceof ob||oa.isBufferList(t)};oa.isBufferList=ob.isBufferList;AN.exports=oa;AN.exports.BufferListStream=oa;AN.exports.BufferList=ob});var OV=G(Qw=>{var Tdt=Buffer.alloc,Fdt=\"0000000000000000000\",Ndt=\"7777777777777777777\",YBe=48,KBe=Buffer.from(\"ustar\\0\",\"binary\"),Odt=Buffer.from(\"00\",\"binary\"),Ldt=Buffer.from(\"ustar \",\"binary\"),Mdt=Buffer.from(\" \\0\",\"binary\"),Udt=parseInt(\"7777\",8),ab=257,NV=263,_dt=function(e,t,r){return typeof e!=\"number\"?r:(e=~~e,e>=t?t:e>=0||(e+=t,e>=0)?e:0)},Hdt=function(e){switch(e){case 0:return\"file\";case 1:return\"link\";case 2:return\"symlink\";case 3:return\"character-device\";case 4:return\"block-device\";case 5:return\"directory\";case 6:return\"fifo\";case 7:return\"contiguous-file\";case 72:return\"pax-header\";case 55:return\"pax-global-header\";case 27:return\"gnu-long-link-path\";case 28:case 30:return\"gnu-long-path\"}return null},jdt=function(e){switch(e){case\"file\":return 0;case\"link\":return 1;case\"symlink\":return 2;case\"character-device\":return 3;case\"block-device\":return 4;case\"directory\":return 5;case\"fifo\":return 6;case\"contiguous-file\":return 7;case\"pax-header\":return 72}return 0},JBe=function(e,t,r,s){for(;r<s;r++)if(e[r]===t)return r;return s},zBe=function(e){for(var t=256,r=0;r<148;r++)t+=e[r];for(var s=156;s<512;s++)t+=e[s];return t},Ag=function(e,t){return e=e.toString(8),e.length>t?Ndt.slice(0,t)+\" \":Fdt.slice(0,t-e.length)+e+\" \"};function Gdt(e){var t;if(e[0]===128)t=!0;else if(e[0]===255)t=!1;else return null;for(var r=[],s=e.length-1;s>0;s--){var a=e[s];t?r.push(a):r.push(255-a)}var n=0,c=r.length;for(s=0;s<c;s++)n+=r[s]*Math.pow(256,s);return t?n:-1*n}var pg=function(e,t,r){if(e=e.slice(t,t+r),t=0,e[t]&128)return Gdt(e);for(;t<e.length&&e[t]===32;)t++;for(var s=_dt(JBe(e,32,t,e.length),e.length,e.length);t<s&&e[t]===0;)t++;return s===t?0:parseInt(e.slice(t,s).toString(),8)},kw=function(e,t,r,s){return e.slice(t,JBe(e,0,t,t+r)).toString(s)},FV=function(e){var t=Buffer.byteLength(e),r=Math.floor(Math.log(t)/Math.log(10))+1;return t+r>=Math.pow(10,r)&&r++,t+r+e};Qw.decodeLongPath=function(e,t){return kw(e,0,e.length,t)};Qw.encodePax=function(e){var t=\"\";e.name&&(t+=FV(\" path=\"+e.name+`\n`)),e.linkname&&(t+=FV(\" linkpath=\"+e.linkname+`\n`));var r=e.pax;if(r)for(var s in r)t+=FV(\" \"+s+\"=\"+r[s]+`\n`);return Buffer.from(t)};Qw.decodePax=function(e){for(var t={};e.length;){for(var r=0;r<e.length&&e[r]!==32;)r++;var s=parseInt(e.slice(0,r).toString(),10);if(!s)return t;var a=e.slice(r+1,s-1).toString(),n=a.indexOf(\"=\");if(n===-1)return t;t[a.slice(0,n)]=a.slice(n+1),e=e.slice(s)}return t};Qw.encode=function(e){var t=Tdt(512),r=e.name,s=\"\";if(e.typeflag===5&&r[r.length-1]!==\"/\"&&(r+=\"/\"),Buffer.byteLength(r)!==r.length)return null;for(;Buffer.byteLength(r)>100;){var a=r.indexOf(\"/\");if(a===-1)return null;s+=s?\"/\"+r.slice(0,a):r.slice(0,a),r=r.slice(a+1)}return Buffer.byteLength(r)>100||Buffer.byteLength(s)>155||e.linkname&&Buffer.byteLength(e.linkname)>100?null:(t.write(r),t.write(Ag(e.mode&Udt,6),100),t.write(Ag(e.uid,6),108),t.write(Ag(e.gid,6),116),t.write(Ag(e.size,11),124),t.write(Ag(e.mtime.getTime()/1e3|0,11),136),t[156]=YBe+jdt(e.type),e.linkname&&t.write(e.linkname,157),KBe.copy(t,ab),Odt.copy(t,NV),e.uname&&t.write(e.uname,265),e.gname&&t.write(e.gname,297),t.write(Ag(e.devmajor||0,6),329),t.write(Ag(e.devminor||0,6),337),s&&t.write(s,345),t.write(Ag(zBe(t),6),148),t)};Qw.decode=function(e,t,r){var s=e[156]===0?0:e[156]-YBe,a=kw(e,0,100,t),n=pg(e,100,8),c=pg(e,108,8),f=pg(e,116,8),p=pg(e,124,12),h=pg(e,136,12),E=Hdt(s),C=e[157]===0?null:kw(e,157,100,t),S=kw(e,265,32),x=kw(e,297,32),I=pg(e,329,8),T=pg(e,337,8),O=zBe(e);if(O===8*32)return null;if(O!==pg(e,148,8))throw new Error(\"Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?\");if(KBe.compare(e,ab,ab+6)===0)e[345]&&(a=kw(e,345,155,t)+\"/\"+a);else if(!(Ldt.compare(e,ab,ab+6)===0&&Mdt.compare(e,NV,NV+2)===0)){if(!r)throw new Error(\"Invalid tar header: unknown format.\")}return s===0&&a&&a[a.length-1]===\"/\"&&(s=5),{name:a,mode:n,uid:c,gid:f,size:p,mtime:new Date(1e3*h),type:E,linkname:C,uname:S,gname:x,devmajor:I,devminor:T}}});var n2e=G((f$t,r2e)=>{var XBe=Ie(\"util\"),qdt=VBe(),lb=OV(),$Be=xw().Writable,e2e=xw().PassThrough,t2e=function(){},ZBe=function(e){return e&=511,e&&512-e},Wdt=function(e,t){var r=new pN(e,t);return r.end(),r},Vdt=function(e,t){return t.path&&(e.name=t.path),t.linkpath&&(e.linkname=t.linkpath),t.size&&(e.size=parseInt(t.size,10)),e.pax=t,e},pN=function(e,t){this._parent=e,this.offset=t,e2e.call(this,{autoDestroy:!1})};XBe.inherits(pN,e2e);pN.prototype.destroy=function(e){this._parent.destroy(e)};var ah=function(e){if(!(this instanceof ah))return new ah(e);$Be.call(this,e),e=e||{},this._offset=0,this._buffer=qdt(),this._missing=0,this._partial=!1,this._onparse=t2e,this._header=null,this._stream=null,this._overflow=null,this._cb=null,this._locked=!1,this._destroyed=!1,this._pax=null,this._paxGlobal=null,this._gnuLongPath=null,this._gnuLongLinkPath=null;var t=this,r=t._buffer,s=function(){t._continue()},a=function(S){if(t._locked=!1,S)return t.destroy(S);t._stream||s()},n=function(){t._stream=null;var S=ZBe(t._header.size);S?t._parse(S,c):t._parse(512,C),t._locked||s()},c=function(){t._buffer.consume(ZBe(t._header.size)),t._parse(512,C),s()},f=function(){var S=t._header.size;t._paxGlobal=lb.decodePax(r.slice(0,S)),r.consume(S),n()},p=function(){var S=t._header.size;t._pax=lb.decodePax(r.slice(0,S)),t._paxGlobal&&(t._pax=Object.assign({},t._paxGlobal,t._pax)),r.consume(S),n()},h=function(){var S=t._header.size;this._gnuLongPath=lb.decodeLongPath(r.slice(0,S),e.filenameEncoding),r.consume(S),n()},E=function(){var S=t._header.size;this._gnuLongLinkPath=lb.decodeLongPath(r.slice(0,S),e.filenameEncoding),r.consume(S),n()},C=function(){var S=t._offset,x;try{x=t._header=lb.decode(r.slice(0,512),e.filenameEncoding,e.allowUnknownFormat)}catch(I){t.emit(\"error\",I)}if(r.consume(512),!x){t._parse(512,C),s();return}if(x.type===\"gnu-long-path\"){t._parse(x.size,h),s();return}if(x.type===\"gnu-long-link-path\"){t._parse(x.size,E),s();return}if(x.type===\"pax-global-header\"){t._parse(x.size,f),s();return}if(x.type===\"pax-header\"){t._parse(x.size,p),s();return}if(t._gnuLongPath&&(x.name=t._gnuLongPath,t._gnuLongPath=null),t._gnuLongLinkPath&&(x.linkname=t._gnuLongLinkPath,t._gnuLongLinkPath=null),t._pax&&(t._header=x=Vdt(x,t._pax),t._pax=null),t._locked=!0,!x.size||x.type===\"directory\"){t._parse(512,C),t.emit(\"entry\",x,Wdt(t,S),a);return}t._stream=new pN(t,S),t.emit(\"entry\",x,t._stream,a),t._parse(x.size,n),s()};this._onheader=C,this._parse(512,C)};XBe.inherits(ah,$Be);ah.prototype.destroy=function(e){this._destroyed||(this._destroyed=!0,e&&this.emit(\"error\",e),this.emit(\"close\"),this._stream&&this._stream.emit(\"close\"))};ah.prototype._parse=function(e,t){this._destroyed||(this._offset+=e,this._missing=e,t===this._onheader&&(this._partial=!1),this._onparse=t)};ah.prototype._continue=function(){if(!this._destroyed){var e=this._cb;this._cb=t2e,this._overflow?this._write(this._overflow,void 0,e):e()}};ah.prototype._write=function(e,t,r){if(!this._destroyed){var s=this._stream,a=this._buffer,n=this._missing;if(e.length&&(this._partial=!0),e.length<n)return this._missing-=e.length,this._overflow=null,s?s.write(e,r):(a.append(e),r());this._cb=r,this._missing=0;var c=null;e.length>n&&(c=e.slice(n),e=e.slice(0,n)),s?s.end(e):a.append(e),this._overflow=c,this._onparse()}};ah.prototype._final=function(e){if(this._partial)return this.destroy(new Error(\"Unexpected end of data\"));e()};r2e.exports=ah});var s2e=G((A$t,i2e)=>{i2e.exports=Ie(\"fs\").constants||Ie(\"constants\")});var u2e=G((p$t,c2e)=>{var Rw=s2e(),o2e=Y8(),gN=ag(),Ydt=Buffer.alloc,a2e=xw().Readable,Tw=xw().Writable,Kdt=Ie(\"string_decoder\").StringDecoder,hN=OV(),Jdt=parseInt(\"755\",8),zdt=parseInt(\"644\",8),l2e=Ydt(1024),MV=function(){},LV=function(e,t){t&=511,t&&e.push(l2e.slice(0,512-t))};function Zdt(e){switch(e&Rw.S_IFMT){case Rw.S_IFBLK:return\"block-device\";case Rw.S_IFCHR:return\"character-device\";case Rw.S_IFDIR:return\"directory\";case Rw.S_IFIFO:return\"fifo\";case Rw.S_IFLNK:return\"symlink\"}return\"file\"}var dN=function(e){Tw.call(this),this.written=0,this._to=e,this._destroyed=!1};gN(dN,Tw);dN.prototype._write=function(e,t,r){if(this.written+=e.length,this._to.push(e))return r();this._to._drain=r};dN.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit(\"close\"))};var mN=function(){Tw.call(this),this.linkname=\"\",this._decoder=new Kdt(\"utf-8\"),this._destroyed=!1};gN(mN,Tw);mN.prototype._write=function(e,t,r){this.linkname+=this._decoder.write(e),r()};mN.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit(\"close\"))};var ub=function(){Tw.call(this),this._destroyed=!1};gN(ub,Tw);ub.prototype._write=function(e,t,r){r(new Error(\"No body allowed for this entry\"))};ub.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit(\"close\"))};var yA=function(e){if(!(this instanceof yA))return new yA(e);a2e.call(this,e),this._drain=MV,this._finalized=!1,this._finalizing=!1,this._destroyed=!1,this._stream=null};gN(yA,a2e);yA.prototype.entry=function(e,t,r){if(this._stream)throw new Error(\"already piping an entry\");if(!(this._finalized||this._destroyed)){typeof t==\"function\"&&(r=t,t=null),r||(r=MV);var s=this;if((!e.size||e.type===\"symlink\")&&(e.size=0),e.type||(e.type=Zdt(e.mode)),e.mode||(e.mode=e.type===\"directory\"?Jdt:zdt),e.uid||(e.uid=0),e.gid||(e.gid=0),e.mtime||(e.mtime=new Date),typeof t==\"string\"&&(t=Buffer.from(t)),Buffer.isBuffer(t)){e.size=t.length,this._encode(e);var a=this.push(t);return LV(s,e.size),a?process.nextTick(r):this._drain=r,new ub}if(e.type===\"symlink\"&&!e.linkname){var n=new mN;return o2e(n,function(f){if(f)return s.destroy(),r(f);e.linkname=n.linkname,s._encode(e),r()}),n}if(this._encode(e),e.type!==\"file\"&&e.type!==\"contiguous-file\")return process.nextTick(r),new ub;var c=new dN(this);return this._stream=c,o2e(c,function(f){if(s._stream=null,f)return s.destroy(),r(f);if(c.written!==e.size)return s.destroy(),r(new Error(\"size mismatch\"));LV(s,e.size),s._finalizing&&s.finalize(),r()}),c}};yA.prototype.finalize=function(){if(this._stream){this._finalizing=!0;return}this._finalized||(this._finalized=!0,this.push(l2e),this.push(null))};yA.prototype.destroy=function(e){this._destroyed||(this._destroyed=!0,e&&this.emit(\"error\",e),this.emit(\"close\"),this._stream&&this._stream.destroy&&this._stream.destroy())};yA.prototype._encode=function(e){if(!e.pax){var t=hN.encode(e);if(t){this.push(t);return}}this._encodePax(e)};yA.prototype._encodePax=function(e){var t=hN.encodePax({name:e.name,linkname:e.linkname,pax:e.pax}),r={name:\"PaxHeader\",mode:e.mode,uid:e.uid,gid:e.gid,size:t.length,mtime:e.mtime,type:\"pax-header\",linkname:e.linkname&&\"PaxHeader\",uname:e.uname,gname:e.gname,devmajor:e.devmajor,devminor:e.devminor};this.push(hN.encode(r)),this.push(t),LV(this,t.length),r.size=e.size,r.type=e.type,this.push(hN.encode(r))};yA.prototype._read=function(e){var t=this._drain;this._drain=MV,t()};c2e.exports=yA});var f2e=G(UV=>{UV.extract=n2e();UV.pack=u2e()});var v2e=G(Ma=>{\"use strict\";var umt=Ma&&Ma.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ma,\"__esModule\",{value:!0});Ma.Minipass=Ma.isWritable=Ma.isReadable=Ma.isStream=void 0;var E2e=typeof process==\"object\"&&process?process:{stdout:null,stderr:null},ZV=Ie(\"node:events\"),B2e=umt(Ie(\"node:stream\")),fmt=Ie(\"node:string_decoder\"),Amt=e=>!!e&&typeof e==\"object\"&&(e instanceof DN||e instanceof B2e.default||(0,Ma.isReadable)(e)||(0,Ma.isWritable)(e));Ma.isStream=Amt;var pmt=e=>!!e&&typeof e==\"object\"&&e instanceof ZV.EventEmitter&&typeof e.pipe==\"function\"&&e.pipe!==B2e.default.Writable.prototype.pipe;Ma.isReadable=pmt;var hmt=e=>!!e&&typeof e==\"object\"&&e instanceof ZV.EventEmitter&&typeof e.write==\"function\"&&typeof e.end==\"function\";Ma.isWritable=hmt;var lh=Symbol(\"EOF\"),ch=Symbol(\"maybeEmitEnd\"),hg=Symbol(\"emittedEnd\"),IN=Symbol(\"emittingEnd\"),fb=Symbol(\"emittedError\"),CN=Symbol(\"closed\"),I2e=Symbol(\"read\"),wN=Symbol(\"flush\"),C2e=Symbol(\"flushChunk\"),Af=Symbol(\"encoding\"),Nw=Symbol(\"decoder\"),to=Symbol(\"flowing\"),Ab=Symbol(\"paused\"),Ow=Symbol(\"resume\"),ro=Symbol(\"buffer\"),La=Symbol(\"pipes\"),no=Symbol(\"bufferLength\"),WV=Symbol(\"bufferPush\"),BN=Symbol(\"bufferShift\"),aa=Symbol(\"objectMode\"),rs=Symbol(\"destroyed\"),VV=Symbol(\"error\"),YV=Symbol(\"emitData\"),w2e=Symbol(\"emitEnd\"),KV=Symbol(\"emitEnd2\"),IA=Symbol(\"async\"),JV=Symbol(\"abort\"),vN=Symbol(\"aborted\"),pb=Symbol(\"signal\"),$m=Symbol(\"dataListeners\"),nc=Symbol(\"discarded\"),hb=e=>Promise.resolve().then(e),gmt=e=>e(),dmt=e=>e===\"end\"||e===\"finish\"||e===\"prefinish\",mmt=e=>e instanceof ArrayBuffer||!!e&&typeof e==\"object\"&&e.constructor&&e.constructor.name===\"ArrayBuffer\"&&e.byteLength>=0,ymt=e=>!Buffer.isBuffer(e)&&ArrayBuffer.isView(e),SN=class{src;dest;opts;ondrain;constructor(t,r,s){this.src=t,this.dest=r,this.opts=s,this.ondrain=()=>t[Ow](),this.dest.on(\"drain\",this.ondrain)}unpipe(){this.dest.removeListener(\"drain\",this.ondrain)}proxyErrors(t){}end(){this.unpipe(),this.opts.end&&this.dest.end()}},zV=class extends SN{unpipe(){this.src.removeListener(\"error\",this.proxyErrors),super.unpipe()}constructor(t,r,s){super(t,r,s),this.proxyErrors=a=>r.emit(\"error\",a),t.on(\"error\",this.proxyErrors)}},Emt=e=>!!e.objectMode,Imt=e=>!e.objectMode&&!!e.encoding&&e.encoding!==\"buffer\",DN=class extends ZV.EventEmitter{[to]=!1;[Ab]=!1;[La]=[];[ro]=[];[aa];[Af];[IA];[Nw];[lh]=!1;[hg]=!1;[IN]=!1;[CN]=!1;[fb]=null;[no]=0;[rs]=!1;[pb];[vN]=!1;[$m]=0;[nc]=!1;writable=!0;readable=!0;constructor(...t){let r=t[0]||{};if(super(),r.objectMode&&typeof r.encoding==\"string\")throw new TypeError(\"Encoding and objectMode may not be used together\");Emt(r)?(this[aa]=!0,this[Af]=null):Imt(r)?(this[Af]=r.encoding,this[aa]=!1):(this[aa]=!1,this[Af]=null),this[IA]=!!r.async,this[Nw]=this[Af]?new fmt.StringDecoder(this[Af]):null,r&&r.debugExposeBuffer===!0&&Object.defineProperty(this,\"buffer\",{get:()=>this[ro]}),r&&r.debugExposePipes===!0&&Object.defineProperty(this,\"pipes\",{get:()=>this[La]});let{signal:s}=r;s&&(this[pb]=s,s.aborted?this[JV]():s.addEventListener(\"abort\",()=>this[JV]()))}get bufferLength(){return this[no]}get encoding(){return this[Af]}set encoding(t){throw new Error(\"Encoding must be set at instantiation time\")}setEncoding(t){throw new Error(\"Encoding must be set at instantiation time\")}get objectMode(){return this[aa]}set objectMode(t){throw new Error(\"objectMode must be set at instantiation time\")}get async(){return this[IA]}set async(t){this[IA]=this[IA]||!!t}[JV](){this[vN]=!0,this.emit(\"abort\",this[pb]?.reason),this.destroy(this[pb]?.reason)}get aborted(){return this[vN]}set aborted(t){}write(t,r,s){if(this[vN])return!1;if(this[lh])throw new Error(\"write after end\");if(this[rs])return this.emit(\"error\",Object.assign(new Error(\"Cannot call write after a stream was destroyed\"),{code:\"ERR_STREAM_DESTROYED\"})),!0;typeof r==\"function\"&&(s=r,r=\"utf8\"),r||(r=\"utf8\");let a=this[IA]?hb:gmt;if(!this[aa]&&!Buffer.isBuffer(t)){if(ymt(t))t=Buffer.from(t.buffer,t.byteOffset,t.byteLength);else if(mmt(t))t=Buffer.from(t);else if(typeof t!=\"string\")throw new Error(\"Non-contiguous data written to non-objectMode stream\")}return this[aa]?(this[to]&&this[no]!==0&&this[wN](!0),this[to]?this.emit(\"data\",t):this[WV](t),this[no]!==0&&this.emit(\"readable\"),s&&a(s),this[to]):t.length?(typeof t==\"string\"&&!(r===this[Af]&&!this[Nw]?.lastNeed)&&(t=Buffer.from(t,r)),Buffer.isBuffer(t)&&this[Af]&&(t=this[Nw].write(t)),this[to]&&this[no]!==0&&this[wN](!0),this[to]?this.emit(\"data\",t):this[WV](t),this[no]!==0&&this.emit(\"readable\"),s&&a(s),this[to]):(this[no]!==0&&this.emit(\"readable\"),s&&a(s),this[to])}read(t){if(this[rs])return null;if(this[nc]=!1,this[no]===0||t===0||t&&t>this[no])return this[ch](),null;this[aa]&&(t=null),this[ro].length>1&&!this[aa]&&(this[ro]=[this[Af]?this[ro].join(\"\"):Buffer.concat(this[ro],this[no])]);let r=this[I2e](t||null,this[ro][0]);return this[ch](),r}[I2e](t,r){if(this[aa])this[BN]();else{let s=r;t===s.length||t===null?this[BN]():typeof s==\"string\"?(this[ro][0]=s.slice(t),r=s.slice(0,t),this[no]-=t):(this[ro][0]=s.subarray(t),r=s.subarray(0,t),this[no]-=t)}return this.emit(\"data\",r),!this[ro].length&&!this[lh]&&this.emit(\"drain\"),r}end(t,r,s){return typeof t==\"function\"&&(s=t,t=void 0),typeof r==\"function\"&&(s=r,r=\"utf8\"),t!==void 0&&this.write(t,r),s&&this.once(\"end\",s),this[lh]=!0,this.writable=!1,(this[to]||!this[Ab])&&this[ch](),this}[Ow](){this[rs]||(!this[$m]&&!this[La].length&&(this[nc]=!0),this[Ab]=!1,this[to]=!0,this.emit(\"resume\"),this[ro].length?this[wN]():this[lh]?this[ch]():this.emit(\"drain\"))}resume(){return this[Ow]()}pause(){this[to]=!1,this[Ab]=!0,this[nc]=!1}get destroyed(){return this[rs]}get flowing(){return this[to]}get paused(){return this[Ab]}[WV](t){this[aa]?this[no]+=1:this[no]+=t.length,this[ro].push(t)}[BN](){return this[aa]?this[no]-=1:this[no]-=this[ro][0].length,this[ro].shift()}[wN](t=!1){do;while(this[C2e](this[BN]())&&this[ro].length);!t&&!this[ro].length&&!this[lh]&&this.emit(\"drain\")}[C2e](t){return this.emit(\"data\",t),this[to]}pipe(t,r){if(this[rs])return t;this[nc]=!1;let s=this[hg];return r=r||{},t===E2e.stdout||t===E2e.stderr?r.end=!1:r.end=r.end!==!1,r.proxyErrors=!!r.proxyErrors,s?r.end&&t.end():(this[La].push(r.proxyErrors?new zV(this,t,r):new SN(this,t,r)),this[IA]?hb(()=>this[Ow]()):this[Ow]()),t}unpipe(t){let r=this[La].find(s=>s.dest===t);r&&(this[La].length===1?(this[to]&&this[$m]===0&&(this[to]=!1),this[La]=[]):this[La].splice(this[La].indexOf(r),1),r.unpipe())}addListener(t,r){return this.on(t,r)}on(t,r){let s=super.on(t,r);if(t===\"data\")this[nc]=!1,this[$m]++,!this[La].length&&!this[to]&&this[Ow]();else if(t===\"readable\"&&this[no]!==0)super.emit(\"readable\");else if(dmt(t)&&this[hg])super.emit(t),this.removeAllListeners(t);else if(t===\"error\"&&this[fb]){let a=r;this[IA]?hb(()=>a.call(this,this[fb])):a.call(this,this[fb])}return s}removeListener(t,r){return this.off(t,r)}off(t,r){let s=super.off(t,r);return t===\"data\"&&(this[$m]=this.listeners(\"data\").length,this[$m]===0&&!this[nc]&&!this[La].length&&(this[to]=!1)),s}removeAllListeners(t){let r=super.removeAllListeners(t);return(t===\"data\"||t===void 0)&&(this[$m]=0,!this[nc]&&!this[La].length&&(this[to]=!1)),r}get emittedEnd(){return this[hg]}[ch](){!this[IN]&&!this[hg]&&!this[rs]&&this[ro].length===0&&this[lh]&&(this[IN]=!0,this.emit(\"end\"),this.emit(\"prefinish\"),this.emit(\"finish\"),this[CN]&&this.emit(\"close\"),this[IN]=!1)}emit(t,...r){let s=r[0];if(t!==\"error\"&&t!==\"close\"&&t!==rs&&this[rs])return!1;if(t===\"data\")return!this[aa]&&!s?!1:this[IA]?(hb(()=>this[YV](s)),!0):this[YV](s);if(t===\"end\")return this[w2e]();if(t===\"close\"){if(this[CN]=!0,!this[hg]&&!this[rs])return!1;let n=super.emit(\"close\");return this.removeAllListeners(\"close\"),n}else if(t===\"error\"){this[fb]=s,super.emit(VV,s);let n=!this[pb]||this.listeners(\"error\").length?super.emit(\"error\",s):!1;return this[ch](),n}else if(t===\"resume\"){let n=super.emit(\"resume\");return this[ch](),n}else if(t===\"finish\"||t===\"prefinish\"){let n=super.emit(t);return this.removeAllListeners(t),n}let a=super.emit(t,...r);return this[ch](),a}[YV](t){for(let s of this[La])s.dest.write(t)===!1&&this.pause();let r=this[nc]?!1:super.emit(\"data\",t);return this[ch](),r}[w2e](){return this[hg]?!1:(this[hg]=!0,this.readable=!1,this[IA]?(hb(()=>this[KV]()),!0):this[KV]())}[KV](){if(this[Nw]){let r=this[Nw].end();if(r){for(let s of this[La])s.dest.write(r);this[nc]||super.emit(\"data\",r)}}for(let r of this[La])r.end();let t=super.emit(\"end\");return this.removeAllListeners(\"end\"),t}async collect(){let t=Object.assign([],{dataLength:0});this[aa]||(t.dataLength=0);let r=this.promise();return this.on(\"data\",s=>{t.push(s),this[aa]||(t.dataLength+=s.length)}),await r,t}async concat(){if(this[aa])throw new Error(\"cannot concat in objectMode\");let t=await this.collect();return this[Af]?t.join(\"\"):Buffer.concat(t,t.dataLength)}async promise(){return new Promise((t,r)=>{this.on(rs,()=>r(new Error(\"stream destroyed\"))),this.on(\"error\",s=>r(s)),this.on(\"end\",()=>t())})}[Symbol.asyncIterator](){this[nc]=!1;let t=!1,r=async()=>(this.pause(),t=!0,{value:void 0,done:!0});return{next:()=>{if(t)return r();let a=this.read();if(a!==null)return Promise.resolve({done:!1,value:a});if(this[lh])return r();let n,c,f=C=>{this.off(\"data\",p),this.off(\"end\",h),this.off(rs,E),r(),c(C)},p=C=>{this.off(\"error\",f),this.off(\"end\",h),this.off(rs,E),this.pause(),n({value:C,done:!!this[lh]})},h=()=>{this.off(\"error\",f),this.off(\"data\",p),this.off(rs,E),r(),n({done:!0,value:void 0})},E=()=>f(new Error(\"stream destroyed\"));return new Promise((C,S)=>{c=S,n=C,this.once(rs,E),this.once(\"error\",f),this.once(\"end\",h),this.once(\"data\",p)})},throw:r,return:r,[Symbol.asyncIterator](){return this}}}[Symbol.iterator](){this[nc]=!1;let t=!1,r=()=>(this.pause(),this.off(VV,r),this.off(rs,r),this.off(\"end\",r),t=!0,{done:!0,value:void 0}),s=()=>{if(t)return r();let a=this.read();return a===null?r():{done:!1,value:a}};return this.once(\"end\",r),this.once(VV,r),this.once(rs,r),{next:s,throw:r,return:r,[Symbol.iterator](){return this}}}destroy(t){if(this[rs])return t?this.emit(\"error\",t):this.emit(rs),this;this[rs]=!0,this[nc]=!0,this[ro].length=0,this[no]=0;let r=this;return typeof r.close==\"function\"&&!this[CN]&&r.close(),t?this.emit(\"error\",t):this.emit(rs),this}static get isStream(){return Ma.isStream}};Ma.Minipass=DN});var b2e=G((F$t,CA)=>{\"use strict\";var db=Ie(\"crypto\"),{Minipass:Cmt}=v2e(),$V=[\"sha512\",\"sha384\",\"sha256\"],tY=[\"sha512\"],wmt=/^[a-z0-9+/]+(?:=?=?)$/i,Bmt=/^([a-z0-9]+)-([^?]+)([?\\S*]*)$/,vmt=/^([a-z0-9]+)-([A-Za-z0-9+/=]{44,88})(\\?[\\x21-\\x7E]*)?$/,Smt=/^[\\x21-\\x7E]+$/,mb=e=>e?.length?`?${e.join(\"?\")}`:\"\",eY=class extends Cmt{#e;#t;#s;constructor(t){super(),this.size=0,this.opts=t,this.#r(),t?.algorithms?this.algorithms=[...t.algorithms]:this.algorithms=[...tY],this.algorithm!==null&&!this.algorithms.includes(this.algorithm)&&this.algorithms.push(this.algorithm),this.hashes=this.algorithms.map(db.createHash)}#r(){this.sri=this.opts?.integrity?ic(this.opts?.integrity,this.opts):null,this.expectedSize=this.opts?.size,this.sri?this.sri.isHash?(this.goodSri=!0,this.algorithm=this.sri.algorithm):(this.goodSri=!this.sri.isEmpty(),this.algorithm=this.sri.pickAlgorithm(this.opts)):this.algorithm=null,this.digests=this.goodSri?this.sri[this.algorithm]:null,this.optString=mb(this.opts?.options)}on(t,r){return t===\"size\"&&this.#t?r(this.#t):t===\"integrity\"&&this.#e?r(this.#e):t===\"verified\"&&this.#s?r(this.#s):super.on(t,r)}emit(t,r){return t===\"end\"&&this.#i(),super.emit(t,r)}write(t){return this.size+=t.length,this.hashes.forEach(r=>r.update(t)),super.write(t)}#i(){this.goodSri||this.#r();let t=ic(this.hashes.map((s,a)=>`${this.algorithms[a]}-${s.digest(\"base64\")}${this.optString}`).join(\" \"),this.opts),r=this.goodSri&&t.match(this.sri,this.opts);if(typeof this.expectedSize==\"number\"&&this.size!==this.expectedSize){let s=new Error(`stream size mismatch when checking ${this.sri}.\n  Wanted: ${this.expectedSize}\n  Found: ${this.size}`);s.code=\"EBADSIZE\",s.found=this.size,s.expected=this.expectedSize,s.sri=this.sri,this.emit(\"error\",s)}else if(this.sri&&!r){let s=new Error(`${this.sri} integrity checksum failed when using ${this.algorithm}: wanted ${this.digests} but got ${t}. (${this.size} bytes)`);s.code=\"EINTEGRITY\",s.found=t,s.expected=this.digests,s.algorithm=this.algorithm,s.sri=this.sri,this.emit(\"error\",s)}else this.#t=this.size,this.emit(\"size\",this.size),this.#e=t,this.emit(\"integrity\",t),r&&(this.#s=r,this.emit(\"verified\",r))}},uh=class{get isHash(){return!0}constructor(t,r){let s=r?.strict;this.source=t.trim(),this.digest=\"\",this.algorithm=\"\",this.options=[];let a=this.source.match(s?vmt:Bmt);if(!a||s&&!$V.includes(a[1]))return;this.algorithm=a[1],this.digest=a[2];let n=a[3];n&&(this.options=n.slice(1).split(\"?\"))}hexDigest(){return this.digest&&Buffer.from(this.digest,\"base64\").toString(\"hex\")}toJSON(){return this.toString()}match(t,r){let s=ic(t,r);if(!s)return!1;if(s.isIntegrity){let a=s.pickAlgorithm(r,[this.algorithm]);if(!a)return!1;let n=s[a].find(c=>c.digest===this.digest);return n||!1}return s.digest===this.digest?s:!1}toString(t){return t?.strict&&!($V.includes(this.algorithm)&&this.digest.match(wmt)&&this.options.every(r=>r.match(Smt)))?\"\":`${this.algorithm}-${this.digest}${mb(this.options)}`}};function S2e(e,t,r,s){let a=e!==\"\",n=!1,c=\"\",f=s.length-1;for(let h=0;h<f;h++){let E=uh.prototype.toString.call(s[h],r);E&&(n=!0,c+=E,c+=t)}let p=uh.prototype.toString.call(s[f],r);return p&&(n=!0,c+=p),a&&n?e+t+c:e+c}var ey=class{get isIntegrity(){return!0}toJSON(){return this.toString()}isEmpty(){return Object.keys(this).length===0}toString(t){let r=t?.sep||\" \",s=\"\";if(t?.strict){r=r.replace(/\\S+/g,\" \");for(let a of $V)this[a]&&(s=S2e(s,r,t,this[a]))}else for(let a of Object.keys(this))s=S2e(s,r,t,this[a]);return s}concat(t,r){let s=typeof t==\"string\"?t:gb(t,r);return ic(`${this.toString(r)} ${s}`,r)}hexDigest(){return ic(this,{single:!0}).hexDigest()}merge(t,r){let s=ic(t,r);for(let a in s)if(this[a]){if(!this[a].find(n=>s[a].find(c=>n.digest===c.digest)))throw new Error(\"hashes do not match, cannot update integrity\")}else this[a]=s[a]}match(t,r){let s=ic(t,r);if(!s)return!1;let a=s.pickAlgorithm(r,Object.keys(this));return!!a&&this[a]&&s[a]&&this[a].find(n=>s[a].find(c=>n.digest===c.digest))||!1}pickAlgorithm(t,r){let s=t?.pickAlgorithm||Tmt,a=Object.keys(this).filter(n=>r?.length?r.includes(n):!0);return a.length?a.reduce((n,c)=>s(n,c)||n):null}};CA.exports.parse=ic;function ic(e,t){if(!e)return null;if(typeof e==\"string\")return XV(e,t);if(e.algorithm&&e.digest){let r=new ey;return r[e.algorithm]=[e],XV(gb(r,t),t)}else return XV(gb(e,t),t)}function XV(e,t){if(t?.single)return new uh(e,t);let r=e.trim().split(/\\s+/).reduce((s,a)=>{let n=new uh(a,t);if(n.algorithm&&n.digest){let c=n.algorithm;s[c]||(s[c]=[]),s[c].push(n)}return s},new ey);return r.isEmpty()?null:r}CA.exports.stringify=gb;function gb(e,t){return e.algorithm&&e.digest?uh.prototype.toString.call(e,t):typeof e==\"string\"?gb(ic(e,t),t):ey.prototype.toString.call(e,t)}CA.exports.fromHex=Dmt;function Dmt(e,t,r){let s=mb(r?.options);return ic(`${t}-${Buffer.from(e,\"hex\").toString(\"base64\")}${s}`,r)}CA.exports.fromData=bmt;function bmt(e,t){let r=t?.algorithms||[...tY],s=mb(t?.options);return r.reduce((a,n)=>{let c=db.createHash(n).update(e).digest(\"base64\"),f=new uh(`${n}-${c}${s}`,t);if(f.algorithm&&f.digest){let p=f.algorithm;a[p]||(a[p]=[]),a[p].push(f)}return a},new ey)}CA.exports.fromStream=Pmt;function Pmt(e,t){let r=rY(t);return new Promise((s,a)=>{e.pipe(r),e.on(\"error\",a),r.on(\"error\",a);let n;r.on(\"integrity\",c=>{n=c}),r.on(\"end\",()=>s(n)),r.resume()})}CA.exports.checkData=xmt;function xmt(e,t,r){if(t=ic(t,r),!t||!Object.keys(t).length){if(r?.error)throw Object.assign(new Error(\"No valid integrity hashes to check against\"),{code:\"EINTEGRITY\"});return!1}let s=t.pickAlgorithm(r),a=db.createHash(s).update(e).digest(\"base64\"),n=ic({algorithm:s,digest:a}),c=n.match(t,r);if(r=r||{},c||!r.error)return c;if(typeof r.size==\"number\"&&e.length!==r.size){let f=new Error(`data size mismatch when checking ${t}.\n  Wanted: ${r.size}\n  Found: ${e.length}`);throw f.code=\"EBADSIZE\",f.found=e.length,f.expected=r.size,f.sri=t,f}else{let f=new Error(`Integrity checksum failed when using ${s}: Wanted ${t}, but got ${n}. (${e.length} bytes)`);throw f.code=\"EINTEGRITY\",f.found=n,f.expected=t,f.algorithm=s,f.sri=t,f}}CA.exports.checkStream=kmt;function kmt(e,t,r){if(r=r||Object.create(null),r.integrity=t,t=ic(t,r),!t||!Object.keys(t).length)return Promise.reject(Object.assign(new Error(\"No valid integrity hashes to check against\"),{code:\"EINTEGRITY\"}));let s=rY(r);return new Promise((a,n)=>{e.pipe(s),e.on(\"error\",n),s.on(\"error\",n);let c;s.on(\"verified\",f=>{c=f}),s.on(\"end\",()=>a(c)),s.resume()})}CA.exports.integrityStream=rY;function rY(e=Object.create(null)){return new eY(e)}CA.exports.create=Qmt;function Qmt(e){let t=e?.algorithms||[...tY],r=mb(e?.options),s=t.map(db.createHash);return{update:function(a,n){return s.forEach(c=>c.update(a,n)),this},digest:function(){return t.reduce((n,c)=>{let f=s.shift().digest(\"base64\"),p=new uh(`${c}-${f}${r}`,e);if(p.algorithm&&p.digest){let h=p.algorithm;n[h]||(n[h]=[]),n[h].push(p)}return n},new ey)}}}var Rmt=db.getHashes(),D2e=[\"md5\",\"whirlpool\",\"sha1\",\"sha224\",\"sha256\",\"sha384\",\"sha512\",\"sha3\",\"sha3-256\",\"sha3-384\",\"sha3-512\",\"sha3_256\",\"sha3_384\",\"sha3_512\"].filter(e=>Rmt.includes(e));function Tmt(e,t){return D2e.indexOf(e.toLowerCase())>=D2e.indexOf(t.toLowerCase())?e:t}});var nY=G(gg=>{\"use strict\";Object.defineProperty(gg,\"__esModule\",{value:!0});gg.Signature=gg.Envelope=void 0;gg.Envelope={fromJSON(e){return{payload:bN(e.payload)?Buffer.from(P2e(e.payload)):Buffer.alloc(0),payloadType:bN(e.payloadType)?globalThis.String(e.payloadType):\"\",signatures:globalThis.Array.isArray(e?.signatures)?e.signatures.map(t=>gg.Signature.fromJSON(t)):[]}},toJSON(e){let t={};return e.payload.length!==0&&(t.payload=x2e(e.payload)),e.payloadType!==\"\"&&(t.payloadType=e.payloadType),e.signatures?.length&&(t.signatures=e.signatures.map(r=>gg.Signature.toJSON(r))),t}};gg.Signature={fromJSON(e){return{sig:bN(e.sig)?Buffer.from(P2e(e.sig)):Buffer.alloc(0),keyid:bN(e.keyid)?globalThis.String(e.keyid):\"\"}},toJSON(e){let t={};return e.sig.length!==0&&(t.sig=x2e(e.sig)),e.keyid!==\"\"&&(t.keyid=e.keyid),t}};function P2e(e){return Uint8Array.from(globalThis.Buffer.from(e,\"base64\"))}function x2e(e){return globalThis.Buffer.from(e).toString(\"base64\")}function bN(e){return e!=null}});var Q2e=G(PN=>{\"use strict\";Object.defineProperty(PN,\"__esModule\",{value:!0});PN.Timestamp=void 0;PN.Timestamp={fromJSON(e){return{seconds:k2e(e.seconds)?globalThis.String(e.seconds):\"0\",nanos:k2e(e.nanos)?globalThis.Number(e.nanos):0}},toJSON(e){let t={};return e.seconds!==\"0\"&&(t.seconds=e.seconds),e.nanos!==0&&(t.nanos=Math.round(e.nanos)),t}};function k2e(e){return e!=null}});var Lw=G(Ur=>{\"use strict\";Object.defineProperty(Ur,\"__esModule\",{value:!0});Ur.TimeRange=Ur.X509CertificateChain=Ur.SubjectAlternativeName=Ur.X509Certificate=Ur.DistinguishedName=Ur.ObjectIdentifierValuePair=Ur.ObjectIdentifier=Ur.PublicKeyIdentifier=Ur.PublicKey=Ur.RFC3161SignedTimestamp=Ur.LogId=Ur.MessageSignature=Ur.HashOutput=Ur.SubjectAlternativeNameType=Ur.PublicKeyDetails=Ur.HashAlgorithm=void 0;Ur.hashAlgorithmFromJSON=T2e;Ur.hashAlgorithmToJSON=F2e;Ur.publicKeyDetailsFromJSON=N2e;Ur.publicKeyDetailsToJSON=O2e;Ur.subjectAlternativeNameTypeFromJSON=L2e;Ur.subjectAlternativeNameTypeToJSON=M2e;var Fmt=Q2e(),vl;(function(e){e[e.HASH_ALGORITHM_UNSPECIFIED=0]=\"HASH_ALGORITHM_UNSPECIFIED\",e[e.SHA2_256=1]=\"SHA2_256\",e[e.SHA2_384=2]=\"SHA2_384\",e[e.SHA2_512=3]=\"SHA2_512\",e[e.SHA3_256=4]=\"SHA3_256\",e[e.SHA3_384=5]=\"SHA3_384\"})(vl||(Ur.HashAlgorithm=vl={}));function T2e(e){switch(e){case 0:case\"HASH_ALGORITHM_UNSPECIFIED\":return vl.HASH_ALGORITHM_UNSPECIFIED;case 1:case\"SHA2_256\":return vl.SHA2_256;case 2:case\"SHA2_384\":return vl.SHA2_384;case 3:case\"SHA2_512\":return vl.SHA2_512;case 4:case\"SHA3_256\":return vl.SHA3_256;case 5:case\"SHA3_384\":return vl.SHA3_384;default:throw new globalThis.Error(\"Unrecognized enum value \"+e+\" for enum HashAlgorithm\")}}function F2e(e){switch(e){case vl.HASH_ALGORITHM_UNSPECIFIED:return\"HASH_ALGORITHM_UNSPECIFIED\";case vl.SHA2_256:return\"SHA2_256\";case vl.SHA2_384:return\"SHA2_384\";case vl.SHA2_512:return\"SHA2_512\";case vl.SHA3_256:return\"SHA3_256\";case vl.SHA3_384:return\"SHA3_384\";default:throw new globalThis.Error(\"Unrecognized enum value \"+e+\" for enum HashAlgorithm\")}}var sn;(function(e){e[e.PUBLIC_KEY_DETAILS_UNSPECIFIED=0]=\"PUBLIC_KEY_DETAILS_UNSPECIFIED\",e[e.PKCS1_RSA_PKCS1V5=1]=\"PKCS1_RSA_PKCS1V5\",e[e.PKCS1_RSA_PSS=2]=\"PKCS1_RSA_PSS\",e[e.PKIX_RSA_PKCS1V5=3]=\"PKIX_RSA_PKCS1V5\",e[e.PKIX_RSA_PSS=4]=\"PKIX_RSA_PSS\",e[e.PKIX_RSA_PKCS1V15_2048_SHA256=9]=\"PKIX_RSA_PKCS1V15_2048_SHA256\",e[e.PKIX_RSA_PKCS1V15_3072_SHA256=10]=\"PKIX_RSA_PKCS1V15_3072_SHA256\",e[e.PKIX_RSA_PKCS1V15_4096_SHA256=11]=\"PKIX_RSA_PKCS1V15_4096_SHA256\",e[e.PKIX_RSA_PSS_2048_SHA256=16]=\"PKIX_RSA_PSS_2048_SHA256\",e[e.PKIX_RSA_PSS_3072_SHA256=17]=\"PKIX_RSA_PSS_3072_SHA256\",e[e.PKIX_RSA_PSS_4096_SHA256=18]=\"PKIX_RSA_PSS_4096_SHA256\",e[e.PKIX_ECDSA_P256_HMAC_SHA_256=6]=\"PKIX_ECDSA_P256_HMAC_SHA_256\",e[e.PKIX_ECDSA_P256_SHA_256=5]=\"PKIX_ECDSA_P256_SHA_256\",e[e.PKIX_ECDSA_P384_SHA_384=12]=\"PKIX_ECDSA_P384_SHA_384\",e[e.PKIX_ECDSA_P521_SHA_512=13]=\"PKIX_ECDSA_P521_SHA_512\",e[e.PKIX_ED25519=7]=\"PKIX_ED25519\",e[e.PKIX_ED25519_PH=8]=\"PKIX_ED25519_PH\",e[e.LMS_SHA256=14]=\"LMS_SHA256\",e[e.LMOTS_SHA256=15]=\"LMOTS_SHA256\"})(sn||(Ur.PublicKeyDetails=sn={}));function N2e(e){switch(e){case 0:case\"PUBLIC_KEY_DETAILS_UNSPECIFIED\":return sn.PUBLIC_KEY_DETAILS_UNSPECIFIED;case 1:case\"PKCS1_RSA_PKCS1V5\":return sn.PKCS1_RSA_PKCS1V5;case 2:case\"PKCS1_RSA_PSS\":return sn.PKCS1_RSA_PSS;case 3:case\"PKIX_RSA_PKCS1V5\":return sn.PKIX_RSA_PKCS1V5;case 4:case\"PKIX_RSA_PSS\":return sn.PKIX_RSA_PSS;case 9:case\"PKIX_RSA_PKCS1V15_2048_SHA256\":return sn.PKIX_RSA_PKCS1V15_2048_SHA256;case 10:case\"PKIX_RSA_PKCS1V15_3072_SHA256\":return sn.PKIX_RSA_PKCS1V15_3072_SHA256;case 11:case\"PKIX_RSA_PKCS1V15_4096_SHA256\":return sn.PKIX_RSA_PKCS1V15_4096_SHA256;case 16:case\"PKIX_RSA_PSS_2048_SHA256\":return sn.PKIX_RSA_PSS_2048_SHA256;case 17:case\"PKIX_RSA_PSS_3072_SHA256\":return sn.PKIX_RSA_PSS_3072_SHA256;case 18:case\"PKIX_RSA_PSS_4096_SHA256\":return sn.PKIX_RSA_PSS_4096_SHA256;case 6:case\"PKIX_ECDSA_P256_HMAC_SHA_256\":return sn.PKIX_ECDSA_P256_HMAC_SHA_256;case 5:case\"PKIX_ECDSA_P256_SHA_256\":return sn.PKIX_ECDSA_P256_SHA_256;case 12:case\"PKIX_ECDSA_P384_SHA_384\":return sn.PKIX_ECDSA_P384_SHA_384;case 13:case\"PKIX_ECDSA_P521_SHA_512\":return sn.PKIX_ECDSA_P521_SHA_512;case 7:case\"PKIX_ED25519\":return sn.PKIX_ED25519;case 8:case\"PKIX_ED25519_PH\":return sn.PKIX_ED25519_PH;case 14:case\"LMS_SHA256\":return sn.LMS_SHA256;case 15:case\"LMOTS_SHA256\":return sn.LMOTS_SHA256;default:throw new globalThis.Error(\"Unrecognized enum value \"+e+\" for enum PublicKeyDetails\")}}function O2e(e){switch(e){case sn.PUBLIC_KEY_DETAILS_UNSPECIFIED:return\"PUBLIC_KEY_DETAILS_UNSPECIFIED\";case sn.PKCS1_RSA_PKCS1V5:return\"PKCS1_RSA_PKCS1V5\";case sn.PKCS1_RSA_PSS:return\"PKCS1_RSA_PSS\";case sn.PKIX_RSA_PKCS1V5:return\"PKIX_RSA_PKCS1V5\";case sn.PKIX_RSA_PSS:return\"PKIX_RSA_PSS\";case sn.PKIX_RSA_PKCS1V15_2048_SHA256:return\"PKIX_RSA_PKCS1V15_2048_SHA256\";case sn.PKIX_RSA_PKCS1V15_3072_SHA256:return\"PKIX_RSA_PKCS1V15_3072_SHA256\";case sn.PKIX_RSA_PKCS1V15_4096_SHA256:return\"PKIX_RSA_PKCS1V15_4096_SHA256\";case sn.PKIX_RSA_PSS_2048_SHA256:return\"PKIX_RSA_PSS_2048_SHA256\";case sn.PKIX_RSA_PSS_3072_SHA256:return\"PKIX_RSA_PSS_3072_SHA256\";case sn.PKIX_RSA_PSS_4096_SHA256:return\"PKIX_RSA_PSS_4096_SHA256\";case sn.PKIX_ECDSA_P256_HMAC_SHA_256:return\"PKIX_ECDSA_P256_HMAC_SHA_256\";case sn.PKIX_ECDSA_P256_SHA_256:return\"PKIX_ECDSA_P256_SHA_256\";case sn.PKIX_ECDSA_P384_SHA_384:return\"PKIX_ECDSA_P384_SHA_384\";case sn.PKIX_ECDSA_P521_SHA_512:return\"PKIX_ECDSA_P521_SHA_512\";case sn.PKIX_ED25519:return\"PKIX_ED25519\";case sn.PKIX_ED25519_PH:return\"PKIX_ED25519_PH\";case sn.LMS_SHA256:return\"LMS_SHA256\";case sn.LMOTS_SHA256:return\"LMOTS_SHA256\";default:throw new globalThis.Error(\"Unrecognized enum value \"+e+\" for enum PublicKeyDetails\")}}var wA;(function(e){e[e.SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED=0]=\"SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED\",e[e.EMAIL=1]=\"EMAIL\",e[e.URI=2]=\"URI\",e[e.OTHER_NAME=3]=\"OTHER_NAME\"})(wA||(Ur.SubjectAlternativeNameType=wA={}));function L2e(e){switch(e){case 0:case\"SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED\":return wA.SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED;case 1:case\"EMAIL\":return wA.EMAIL;case 2:case\"URI\":return wA.URI;case 3:case\"OTHER_NAME\":return wA.OTHER_NAME;default:throw new globalThis.Error(\"Unrecognized enum value \"+e+\" for enum SubjectAlternativeNameType\")}}function M2e(e){switch(e){case wA.SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED:return\"SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED\";case wA.EMAIL:return\"EMAIL\";case wA.URI:return\"URI\";case wA.OTHER_NAME:return\"OTHER_NAME\";default:throw new globalThis.Error(\"Unrecognized enum value \"+e+\" for enum SubjectAlternativeNameType\")}}Ur.HashOutput={fromJSON(e){return{algorithm:Es(e.algorithm)?T2e(e.algorithm):0,digest:Es(e.digest)?Buffer.from(ty(e.digest)):Buffer.alloc(0)}},toJSON(e){let t={};return e.algorithm!==0&&(t.algorithm=F2e(e.algorithm)),e.digest.length!==0&&(t.digest=ry(e.digest)),t}};Ur.MessageSignature={fromJSON(e){return{messageDigest:Es(e.messageDigest)?Ur.HashOutput.fromJSON(e.messageDigest):void 0,signature:Es(e.signature)?Buffer.from(ty(e.signature)):Buffer.alloc(0)}},toJSON(e){let t={};return e.messageDigest!==void 0&&(t.messageDigest=Ur.HashOutput.toJSON(e.messageDigest)),e.signature.length!==0&&(t.signature=ry(e.signature)),t}};Ur.LogId={fromJSON(e){return{keyId:Es(e.keyId)?Buffer.from(ty(e.keyId)):Buffer.alloc(0)}},toJSON(e){let t={};return e.keyId.length!==0&&(t.keyId=ry(e.keyId)),t}};Ur.RFC3161SignedTimestamp={fromJSON(e){return{signedTimestamp:Es(e.signedTimestamp)?Buffer.from(ty(e.signedTimestamp)):Buffer.alloc(0)}},toJSON(e){let t={};return e.signedTimestamp.length!==0&&(t.signedTimestamp=ry(e.signedTimestamp)),t}};Ur.PublicKey={fromJSON(e){return{rawBytes:Es(e.rawBytes)?Buffer.from(ty(e.rawBytes)):void 0,keyDetails:Es(e.keyDetails)?N2e(e.keyDetails):0,validFor:Es(e.validFor)?Ur.TimeRange.fromJSON(e.validFor):void 0}},toJSON(e){let t={};return e.rawBytes!==void 0&&(t.rawBytes=ry(e.rawBytes)),e.keyDetails!==0&&(t.keyDetails=O2e(e.keyDetails)),e.validFor!==void 0&&(t.validFor=Ur.TimeRange.toJSON(e.validFor)),t}};Ur.PublicKeyIdentifier={fromJSON(e){return{hint:Es(e.hint)?globalThis.String(e.hint):\"\"}},toJSON(e){let t={};return e.hint!==\"\"&&(t.hint=e.hint),t}};Ur.ObjectIdentifier={fromJSON(e){return{id:globalThis.Array.isArray(e?.id)?e.id.map(t=>globalThis.Number(t)):[]}},toJSON(e){let t={};return e.id?.length&&(t.id=e.id.map(r=>Math.round(r))),t}};Ur.ObjectIdentifierValuePair={fromJSON(e){return{oid:Es(e.oid)?Ur.ObjectIdentifier.fromJSON(e.oid):void 0,value:Es(e.value)?Buffer.from(ty(e.value)):Buffer.alloc(0)}},toJSON(e){let t={};return e.oid!==void 0&&(t.oid=Ur.ObjectIdentifier.toJSON(e.oid)),e.value.length!==0&&(t.value=ry(e.value)),t}};Ur.DistinguishedName={fromJSON(e){return{organization:Es(e.organization)?globalThis.String(e.organization):\"\",commonName:Es(e.commonName)?globalThis.String(e.commonName):\"\"}},toJSON(e){let t={};return e.organization!==\"\"&&(t.organization=e.organization),e.commonName!==\"\"&&(t.commonName=e.commonName),t}};Ur.X509Certificate={fromJSON(e){return{rawBytes:Es(e.rawBytes)?Buffer.from(ty(e.rawBytes)):Buffer.alloc(0)}},toJSON(e){let t={};return e.rawBytes.length!==0&&(t.rawBytes=ry(e.rawBytes)),t}};Ur.SubjectAlternativeName={fromJSON(e){return{type:Es(e.type)?L2e(e.type):0,identity:Es(e.regexp)?{$case:\"regexp\",regexp:globalThis.String(e.regexp)}:Es(e.value)?{$case:\"value\",value:globalThis.String(e.value)}:void 0}},toJSON(e){let t={};return e.type!==0&&(t.type=M2e(e.type)),e.identity?.$case===\"regexp\"?t.regexp=e.identity.regexp:e.identity?.$case===\"value\"&&(t.value=e.identity.value),t}};Ur.X509CertificateChain={fromJSON(e){return{certificates:globalThis.Array.isArray(e?.certificates)?e.certificates.map(t=>Ur.X509Certificate.fromJSON(t)):[]}},toJSON(e){let t={};return e.certificates?.length&&(t.certificates=e.certificates.map(r=>Ur.X509Certificate.toJSON(r))),t}};Ur.TimeRange={fromJSON(e){return{start:Es(e.start)?R2e(e.start):void 0,end:Es(e.end)?R2e(e.end):void 0}},toJSON(e){let t={};return e.start!==void 0&&(t.start=e.start.toISOString()),e.end!==void 0&&(t.end=e.end.toISOString()),t}};function ty(e){return Uint8Array.from(globalThis.Buffer.from(e,\"base64\"))}function ry(e){return globalThis.Buffer.from(e).toString(\"base64\")}function Nmt(e){let t=(globalThis.Number(e.seconds)||0)*1e3;return t+=(e.nanos||0)/1e6,new globalThis.Date(t)}function R2e(e){return e instanceof globalThis.Date?e:typeof e==\"string\"?new globalThis.Date(e):Nmt(Fmt.Timestamp.fromJSON(e))}function Es(e){return e!=null}});var iY=G(Is=>{\"use strict\";Object.defineProperty(Is,\"__esModule\",{value:!0});Is.TransparencyLogEntry=Is.InclusionPromise=Is.InclusionProof=Is.Checkpoint=Is.KindVersion=void 0;var U2e=Lw();Is.KindVersion={fromJSON(e){return{kind:Ua(e.kind)?globalThis.String(e.kind):\"\",version:Ua(e.version)?globalThis.String(e.version):\"\"}},toJSON(e){let t={};return e.kind!==\"\"&&(t.kind=e.kind),e.version!==\"\"&&(t.version=e.version),t}};Is.Checkpoint={fromJSON(e){return{envelope:Ua(e.envelope)?globalThis.String(e.envelope):\"\"}},toJSON(e){let t={};return e.envelope!==\"\"&&(t.envelope=e.envelope),t}};Is.InclusionProof={fromJSON(e){return{logIndex:Ua(e.logIndex)?globalThis.String(e.logIndex):\"0\",rootHash:Ua(e.rootHash)?Buffer.from(xN(e.rootHash)):Buffer.alloc(0),treeSize:Ua(e.treeSize)?globalThis.String(e.treeSize):\"0\",hashes:globalThis.Array.isArray(e?.hashes)?e.hashes.map(t=>Buffer.from(xN(t))):[],checkpoint:Ua(e.checkpoint)?Is.Checkpoint.fromJSON(e.checkpoint):void 0}},toJSON(e){let t={};return e.logIndex!==\"0\"&&(t.logIndex=e.logIndex),e.rootHash.length!==0&&(t.rootHash=kN(e.rootHash)),e.treeSize!==\"0\"&&(t.treeSize=e.treeSize),e.hashes?.length&&(t.hashes=e.hashes.map(r=>kN(r))),e.checkpoint!==void 0&&(t.checkpoint=Is.Checkpoint.toJSON(e.checkpoint)),t}};Is.InclusionPromise={fromJSON(e){return{signedEntryTimestamp:Ua(e.signedEntryTimestamp)?Buffer.from(xN(e.signedEntryTimestamp)):Buffer.alloc(0)}},toJSON(e){let t={};return e.signedEntryTimestamp.length!==0&&(t.signedEntryTimestamp=kN(e.signedEntryTimestamp)),t}};Is.TransparencyLogEntry={fromJSON(e){return{logIndex:Ua(e.logIndex)?globalThis.String(e.logIndex):\"0\",logId:Ua(e.logId)?U2e.LogId.fromJSON(e.logId):void 0,kindVersion:Ua(e.kindVersion)?Is.KindVersion.fromJSON(e.kindVersion):void 0,integratedTime:Ua(e.integratedTime)?globalThis.String(e.integratedTime):\"0\",inclusionPromise:Ua(e.inclusionPromise)?Is.InclusionPromise.fromJSON(e.inclusionPromise):void 0,inclusionProof:Ua(e.inclusionProof)?Is.InclusionProof.fromJSON(e.inclusionProof):void 0,canonicalizedBody:Ua(e.canonicalizedBody)?Buffer.from(xN(e.canonicalizedBody)):Buffer.alloc(0)}},toJSON(e){let t={};return e.logIndex!==\"0\"&&(t.logIndex=e.logIndex),e.logId!==void 0&&(t.logId=U2e.LogId.toJSON(e.logId)),e.kindVersion!==void 0&&(t.kindVersion=Is.KindVersion.toJSON(e.kindVersion)),e.integratedTime!==\"0\"&&(t.integratedTime=e.integratedTime),e.inclusionPromise!==void 0&&(t.inclusionPromise=Is.InclusionPromise.toJSON(e.inclusionPromise)),e.inclusionProof!==void 0&&(t.inclusionProof=Is.InclusionProof.toJSON(e.inclusionProof)),e.canonicalizedBody.length!==0&&(t.canonicalizedBody=kN(e.canonicalizedBody)),t}};function xN(e){return Uint8Array.from(globalThis.Buffer.from(e,\"base64\"))}function kN(e){return globalThis.Buffer.from(e).toString(\"base64\")}function Ua(e){return e!=null}});var sY=G(Jc=>{\"use strict\";Object.defineProperty(Jc,\"__esModule\",{value:!0});Jc.Bundle=Jc.VerificationMaterial=Jc.TimestampVerificationData=void 0;var _2e=nY(),BA=Lw(),H2e=iY();Jc.TimestampVerificationData={fromJSON(e){return{rfc3161Timestamps:globalThis.Array.isArray(e?.rfc3161Timestamps)?e.rfc3161Timestamps.map(t=>BA.RFC3161SignedTimestamp.fromJSON(t)):[]}},toJSON(e){let t={};return e.rfc3161Timestamps?.length&&(t.rfc3161Timestamps=e.rfc3161Timestamps.map(r=>BA.RFC3161SignedTimestamp.toJSON(r))),t}};Jc.VerificationMaterial={fromJSON(e){return{content:dg(e.publicKey)?{$case:\"publicKey\",publicKey:BA.PublicKeyIdentifier.fromJSON(e.publicKey)}:dg(e.x509CertificateChain)?{$case:\"x509CertificateChain\",x509CertificateChain:BA.X509CertificateChain.fromJSON(e.x509CertificateChain)}:dg(e.certificate)?{$case:\"certificate\",certificate:BA.X509Certificate.fromJSON(e.certificate)}:void 0,tlogEntries:globalThis.Array.isArray(e?.tlogEntries)?e.tlogEntries.map(t=>H2e.TransparencyLogEntry.fromJSON(t)):[],timestampVerificationData:dg(e.timestampVerificationData)?Jc.TimestampVerificationData.fromJSON(e.timestampVerificationData):void 0}},toJSON(e){let t={};return e.content?.$case===\"publicKey\"?t.publicKey=BA.PublicKeyIdentifier.toJSON(e.content.publicKey):e.content?.$case===\"x509CertificateChain\"?t.x509CertificateChain=BA.X509CertificateChain.toJSON(e.content.x509CertificateChain):e.content?.$case===\"certificate\"&&(t.certificate=BA.X509Certificate.toJSON(e.content.certificate)),e.tlogEntries?.length&&(t.tlogEntries=e.tlogEntries.map(r=>H2e.TransparencyLogEntry.toJSON(r))),e.timestampVerificationData!==void 0&&(t.timestampVerificationData=Jc.TimestampVerificationData.toJSON(e.timestampVerificationData)),t}};Jc.Bundle={fromJSON(e){return{mediaType:dg(e.mediaType)?globalThis.String(e.mediaType):\"\",verificationMaterial:dg(e.verificationMaterial)?Jc.VerificationMaterial.fromJSON(e.verificationMaterial):void 0,content:dg(e.messageSignature)?{$case:\"messageSignature\",messageSignature:BA.MessageSignature.fromJSON(e.messageSignature)}:dg(e.dsseEnvelope)?{$case:\"dsseEnvelope\",dsseEnvelope:_2e.Envelope.fromJSON(e.dsseEnvelope)}:void 0}},toJSON(e){let t={};return e.mediaType!==\"\"&&(t.mediaType=e.mediaType),e.verificationMaterial!==void 0&&(t.verificationMaterial=Jc.VerificationMaterial.toJSON(e.verificationMaterial)),e.content?.$case===\"messageSignature\"?t.messageSignature=BA.MessageSignature.toJSON(e.content.messageSignature):e.content?.$case===\"dsseEnvelope\"&&(t.dsseEnvelope=_2e.Envelope.toJSON(e.content.dsseEnvelope)),t}};function dg(e){return e!=null}});var oY=G(Ti=>{\"use strict\";Object.defineProperty(Ti,\"__esModule\",{value:!0});Ti.ClientTrustConfig=Ti.SigningConfig=Ti.TrustedRoot=Ti.CertificateAuthority=Ti.TransparencyLogInstance=void 0;var Sl=Lw();Ti.TransparencyLogInstance={fromJSON(e){return{baseUrl:la(e.baseUrl)?globalThis.String(e.baseUrl):\"\",hashAlgorithm:la(e.hashAlgorithm)?(0,Sl.hashAlgorithmFromJSON)(e.hashAlgorithm):0,publicKey:la(e.publicKey)?Sl.PublicKey.fromJSON(e.publicKey):void 0,logId:la(e.logId)?Sl.LogId.fromJSON(e.logId):void 0,checkpointKeyId:la(e.checkpointKeyId)?Sl.LogId.fromJSON(e.checkpointKeyId):void 0}},toJSON(e){let t={};return e.baseUrl!==\"\"&&(t.baseUrl=e.baseUrl),e.hashAlgorithm!==0&&(t.hashAlgorithm=(0,Sl.hashAlgorithmToJSON)(e.hashAlgorithm)),e.publicKey!==void 0&&(t.publicKey=Sl.PublicKey.toJSON(e.publicKey)),e.logId!==void 0&&(t.logId=Sl.LogId.toJSON(e.logId)),e.checkpointKeyId!==void 0&&(t.checkpointKeyId=Sl.LogId.toJSON(e.checkpointKeyId)),t}};Ti.CertificateAuthority={fromJSON(e){return{subject:la(e.subject)?Sl.DistinguishedName.fromJSON(e.subject):void 0,uri:la(e.uri)?globalThis.String(e.uri):\"\",certChain:la(e.certChain)?Sl.X509CertificateChain.fromJSON(e.certChain):void 0,validFor:la(e.validFor)?Sl.TimeRange.fromJSON(e.validFor):void 0}},toJSON(e){let t={};return e.subject!==void 0&&(t.subject=Sl.DistinguishedName.toJSON(e.subject)),e.uri!==\"\"&&(t.uri=e.uri),e.certChain!==void 0&&(t.certChain=Sl.X509CertificateChain.toJSON(e.certChain)),e.validFor!==void 0&&(t.validFor=Sl.TimeRange.toJSON(e.validFor)),t}};Ti.TrustedRoot={fromJSON(e){return{mediaType:la(e.mediaType)?globalThis.String(e.mediaType):\"\",tlogs:globalThis.Array.isArray(e?.tlogs)?e.tlogs.map(t=>Ti.TransparencyLogInstance.fromJSON(t)):[],certificateAuthorities:globalThis.Array.isArray(e?.certificateAuthorities)?e.certificateAuthorities.map(t=>Ti.CertificateAuthority.fromJSON(t)):[],ctlogs:globalThis.Array.isArray(e?.ctlogs)?e.ctlogs.map(t=>Ti.TransparencyLogInstance.fromJSON(t)):[],timestampAuthorities:globalThis.Array.isArray(e?.timestampAuthorities)?e.timestampAuthorities.map(t=>Ti.CertificateAuthority.fromJSON(t)):[]}},toJSON(e){let t={};return e.mediaType!==\"\"&&(t.mediaType=e.mediaType),e.tlogs?.length&&(t.tlogs=e.tlogs.map(r=>Ti.TransparencyLogInstance.toJSON(r))),e.certificateAuthorities?.length&&(t.certificateAuthorities=e.certificateAuthorities.map(r=>Ti.CertificateAuthority.toJSON(r))),e.ctlogs?.length&&(t.ctlogs=e.ctlogs.map(r=>Ti.TransparencyLogInstance.toJSON(r))),e.timestampAuthorities?.length&&(t.timestampAuthorities=e.timestampAuthorities.map(r=>Ti.CertificateAuthority.toJSON(r))),t}};Ti.SigningConfig={fromJSON(e){return{mediaType:la(e.mediaType)?globalThis.String(e.mediaType):\"\",caUrl:la(e.caUrl)?globalThis.String(e.caUrl):\"\",oidcUrl:la(e.oidcUrl)?globalThis.String(e.oidcUrl):\"\",tlogUrls:globalThis.Array.isArray(e?.tlogUrls)?e.tlogUrls.map(t=>globalThis.String(t)):[],tsaUrls:globalThis.Array.isArray(e?.tsaUrls)?e.tsaUrls.map(t=>globalThis.String(t)):[]}},toJSON(e){let t={};return e.mediaType!==\"\"&&(t.mediaType=e.mediaType),e.caUrl!==\"\"&&(t.caUrl=e.caUrl),e.oidcUrl!==\"\"&&(t.oidcUrl=e.oidcUrl),e.tlogUrls?.length&&(t.tlogUrls=e.tlogUrls),e.tsaUrls?.length&&(t.tsaUrls=e.tsaUrls),t}};Ti.ClientTrustConfig={fromJSON(e){return{mediaType:la(e.mediaType)?globalThis.String(e.mediaType):\"\",trustedRoot:la(e.trustedRoot)?Ti.TrustedRoot.fromJSON(e.trustedRoot):void 0,signingConfig:la(e.signingConfig)?Ti.SigningConfig.fromJSON(e.signingConfig):void 0}},toJSON(e){let t={};return e.mediaType!==\"\"&&(t.mediaType=e.mediaType),e.trustedRoot!==void 0&&(t.trustedRoot=Ti.TrustedRoot.toJSON(e.trustedRoot)),e.signingConfig!==void 0&&(t.signingConfig=Ti.SigningConfig.toJSON(e.signingConfig)),t}};function la(e){return e!=null}});var q2e=G(Yr=>{\"use strict\";Object.defineProperty(Yr,\"__esModule\",{value:!0});Yr.Input=Yr.Artifact=Yr.ArtifactVerificationOptions_ObserverTimestampOptions=Yr.ArtifactVerificationOptions_TlogIntegratedTimestampOptions=Yr.ArtifactVerificationOptions_TimestampAuthorityOptions=Yr.ArtifactVerificationOptions_CtlogOptions=Yr.ArtifactVerificationOptions_TlogOptions=Yr.ArtifactVerificationOptions=Yr.PublicKeyIdentities=Yr.CertificateIdentities=Yr.CertificateIdentity=void 0;var j2e=sY(),mg=Lw(),G2e=oY();Yr.CertificateIdentity={fromJSON(e){return{issuer:di(e.issuer)?globalThis.String(e.issuer):\"\",san:di(e.san)?mg.SubjectAlternativeName.fromJSON(e.san):void 0,oids:globalThis.Array.isArray(e?.oids)?e.oids.map(t=>mg.ObjectIdentifierValuePair.fromJSON(t)):[]}},toJSON(e){let t={};return e.issuer!==\"\"&&(t.issuer=e.issuer),e.san!==void 0&&(t.san=mg.SubjectAlternativeName.toJSON(e.san)),e.oids?.length&&(t.oids=e.oids.map(r=>mg.ObjectIdentifierValuePair.toJSON(r))),t}};Yr.CertificateIdentities={fromJSON(e){return{identities:globalThis.Array.isArray(e?.identities)?e.identities.map(t=>Yr.CertificateIdentity.fromJSON(t)):[]}},toJSON(e){let t={};return e.identities?.length&&(t.identities=e.identities.map(r=>Yr.CertificateIdentity.toJSON(r))),t}};Yr.PublicKeyIdentities={fromJSON(e){return{publicKeys:globalThis.Array.isArray(e?.publicKeys)?e.publicKeys.map(t=>mg.PublicKey.fromJSON(t)):[]}},toJSON(e){let t={};return e.publicKeys?.length&&(t.publicKeys=e.publicKeys.map(r=>mg.PublicKey.toJSON(r))),t}};Yr.ArtifactVerificationOptions={fromJSON(e){return{signers:di(e.certificateIdentities)?{$case:\"certificateIdentities\",certificateIdentities:Yr.CertificateIdentities.fromJSON(e.certificateIdentities)}:di(e.publicKeys)?{$case:\"publicKeys\",publicKeys:Yr.PublicKeyIdentities.fromJSON(e.publicKeys)}:void 0,tlogOptions:di(e.tlogOptions)?Yr.ArtifactVerificationOptions_TlogOptions.fromJSON(e.tlogOptions):void 0,ctlogOptions:di(e.ctlogOptions)?Yr.ArtifactVerificationOptions_CtlogOptions.fromJSON(e.ctlogOptions):void 0,tsaOptions:di(e.tsaOptions)?Yr.ArtifactVerificationOptions_TimestampAuthorityOptions.fromJSON(e.tsaOptions):void 0,integratedTsOptions:di(e.integratedTsOptions)?Yr.ArtifactVerificationOptions_TlogIntegratedTimestampOptions.fromJSON(e.integratedTsOptions):void 0,observerOptions:di(e.observerOptions)?Yr.ArtifactVerificationOptions_ObserverTimestampOptions.fromJSON(e.observerOptions):void 0}},toJSON(e){let t={};return e.signers?.$case===\"certificateIdentities\"?t.certificateIdentities=Yr.CertificateIdentities.toJSON(e.signers.certificateIdentities):e.signers?.$case===\"publicKeys\"&&(t.publicKeys=Yr.PublicKeyIdentities.toJSON(e.signers.publicKeys)),e.tlogOptions!==void 0&&(t.tlogOptions=Yr.ArtifactVerificationOptions_TlogOptions.toJSON(e.tlogOptions)),e.ctlogOptions!==void 0&&(t.ctlogOptions=Yr.ArtifactVerificationOptions_CtlogOptions.toJSON(e.ctlogOptions)),e.tsaOptions!==void 0&&(t.tsaOptions=Yr.ArtifactVerificationOptions_TimestampAuthorityOptions.toJSON(e.tsaOptions)),e.integratedTsOptions!==void 0&&(t.integratedTsOptions=Yr.ArtifactVerificationOptions_TlogIntegratedTimestampOptions.toJSON(e.integratedTsOptions)),e.observerOptions!==void 0&&(t.observerOptions=Yr.ArtifactVerificationOptions_ObserverTimestampOptions.toJSON(e.observerOptions)),t}};Yr.ArtifactVerificationOptions_TlogOptions={fromJSON(e){return{threshold:di(e.threshold)?globalThis.Number(e.threshold):0,performOnlineVerification:di(e.performOnlineVerification)?globalThis.Boolean(e.performOnlineVerification):!1,disable:di(e.disable)?globalThis.Boolean(e.disable):!1}},toJSON(e){let t={};return e.threshold!==0&&(t.threshold=Math.round(e.threshold)),e.performOnlineVerification!==!1&&(t.performOnlineVerification=e.performOnlineVerification),e.disable!==!1&&(t.disable=e.disable),t}};Yr.ArtifactVerificationOptions_CtlogOptions={fromJSON(e){return{threshold:di(e.threshold)?globalThis.Number(e.threshold):0,disable:di(e.disable)?globalThis.Boolean(e.disable):!1}},toJSON(e){let t={};return e.threshold!==0&&(t.threshold=Math.round(e.threshold)),e.disable!==!1&&(t.disable=e.disable),t}};Yr.ArtifactVerificationOptions_TimestampAuthorityOptions={fromJSON(e){return{threshold:di(e.threshold)?globalThis.Number(e.threshold):0,disable:di(e.disable)?globalThis.Boolean(e.disable):!1}},toJSON(e){let t={};return e.threshold!==0&&(t.threshold=Math.round(e.threshold)),e.disable!==!1&&(t.disable=e.disable),t}};Yr.ArtifactVerificationOptions_TlogIntegratedTimestampOptions={fromJSON(e){return{threshold:di(e.threshold)?globalThis.Number(e.threshold):0,disable:di(e.disable)?globalThis.Boolean(e.disable):!1}},toJSON(e){let t={};return e.threshold!==0&&(t.threshold=Math.round(e.threshold)),e.disable!==!1&&(t.disable=e.disable),t}};Yr.ArtifactVerificationOptions_ObserverTimestampOptions={fromJSON(e){return{threshold:di(e.threshold)?globalThis.Number(e.threshold):0,disable:di(e.disable)?globalThis.Boolean(e.disable):!1}},toJSON(e){let t={};return e.threshold!==0&&(t.threshold=Math.round(e.threshold)),e.disable!==!1&&(t.disable=e.disable),t}};Yr.Artifact={fromJSON(e){return{data:di(e.artifactUri)?{$case:\"artifactUri\",artifactUri:globalThis.String(e.artifactUri)}:di(e.artifact)?{$case:\"artifact\",artifact:Buffer.from(Omt(e.artifact))}:di(e.artifactDigest)?{$case:\"artifactDigest\",artifactDigest:mg.HashOutput.fromJSON(e.artifactDigest)}:void 0}},toJSON(e){let t={};return e.data?.$case===\"artifactUri\"?t.artifactUri=e.data.artifactUri:e.data?.$case===\"artifact\"?t.artifact=Lmt(e.data.artifact):e.data?.$case===\"artifactDigest\"&&(t.artifactDigest=mg.HashOutput.toJSON(e.data.artifactDigest)),t}};Yr.Input={fromJSON(e){return{artifactTrustRoot:di(e.artifactTrustRoot)?G2e.TrustedRoot.fromJSON(e.artifactTrustRoot):void 0,artifactVerificationOptions:di(e.artifactVerificationOptions)?Yr.ArtifactVerificationOptions.fromJSON(e.artifactVerificationOptions):void 0,bundle:di(e.bundle)?j2e.Bundle.fromJSON(e.bundle):void 0,artifact:di(e.artifact)?Yr.Artifact.fromJSON(e.artifact):void 0}},toJSON(e){let t={};return e.artifactTrustRoot!==void 0&&(t.artifactTrustRoot=G2e.TrustedRoot.toJSON(e.artifactTrustRoot)),e.artifactVerificationOptions!==void 0&&(t.artifactVerificationOptions=Yr.ArtifactVerificationOptions.toJSON(e.artifactVerificationOptions)),e.bundle!==void 0&&(t.bundle=j2e.Bundle.toJSON(e.bundle)),e.artifact!==void 0&&(t.artifact=Yr.Artifact.toJSON(e.artifact)),t}};function Omt(e){return Uint8Array.from(globalThis.Buffer.from(e,\"base64\"))}function Lmt(e){return globalThis.Buffer.from(e).toString(\"base64\")}function di(e){return e!=null}});var yb=G(zc=>{\"use strict\";var Mmt=zc&&zc.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Mw=zc&&zc.__exportStar||function(e,t){for(var r in e)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(t,r)&&Mmt(t,e,r)};Object.defineProperty(zc,\"__esModule\",{value:!0});Mw(nY(),zc);Mw(sY(),zc);Mw(Lw(),zc);Mw(iY(),zc);Mw(oY(),zc);Mw(q2e(),zc)});var QN=G(Dl=>{\"use strict\";Object.defineProperty(Dl,\"__esModule\",{value:!0});Dl.BUNDLE_V03_MEDIA_TYPE=Dl.BUNDLE_V03_LEGACY_MEDIA_TYPE=Dl.BUNDLE_V02_MEDIA_TYPE=Dl.BUNDLE_V01_MEDIA_TYPE=void 0;Dl.isBundleWithCertificateChain=Umt;Dl.isBundleWithPublicKey=_mt;Dl.isBundleWithMessageSignature=Hmt;Dl.isBundleWithDsseEnvelope=jmt;Dl.BUNDLE_V01_MEDIA_TYPE=\"application/vnd.dev.sigstore.bundle+json;version=0.1\";Dl.BUNDLE_V02_MEDIA_TYPE=\"application/vnd.dev.sigstore.bundle+json;version=0.2\";Dl.BUNDLE_V03_LEGACY_MEDIA_TYPE=\"application/vnd.dev.sigstore.bundle+json;version=0.3\";Dl.BUNDLE_V03_MEDIA_TYPE=\"application/vnd.dev.sigstore.bundle.v0.3+json\";function Umt(e){return e.verificationMaterial.content.$case===\"x509CertificateChain\"}function _mt(e){return e.verificationMaterial.content.$case===\"publicKey\"}function Hmt(e){return e.content.$case===\"messageSignature\"}function jmt(e){return e.content.$case===\"dsseEnvelope\"}});var V2e=G(TN=>{\"use strict\";Object.defineProperty(TN,\"__esModule\",{value:!0});TN.toMessageSignatureBundle=qmt;TN.toDSSEBundle=Wmt;var Gmt=yb(),RN=QN();function qmt(e){return{mediaType:e.certificateChain?RN.BUNDLE_V02_MEDIA_TYPE:RN.BUNDLE_V03_MEDIA_TYPE,content:{$case:\"messageSignature\",messageSignature:{messageDigest:{algorithm:Gmt.HashAlgorithm.SHA2_256,digest:e.digest},signature:e.signature}},verificationMaterial:W2e(e)}}function Wmt(e){return{mediaType:e.certificateChain?RN.BUNDLE_V02_MEDIA_TYPE:RN.BUNDLE_V03_MEDIA_TYPE,content:{$case:\"dsseEnvelope\",dsseEnvelope:Vmt(e)},verificationMaterial:W2e(e)}}function Vmt(e){return{payloadType:e.artifactType,payload:e.artifact,signatures:[Ymt(e)]}}function Ymt(e){return{keyid:e.keyHint||\"\",sig:e.signature}}function W2e(e){return{content:Kmt(e),tlogEntries:[],timestampVerificationData:{rfc3161Timestamps:[]}}}function Kmt(e){return e.certificate?e.certificateChain?{$case:\"x509CertificateChain\",x509CertificateChain:{certificates:[{rawBytes:e.certificate}]}}:{$case:\"certificate\",certificate:{rawBytes:e.certificate}}:{$case:\"publicKey\",publicKey:{hint:e.keyHint||\"\"}}}});var lY=G(FN=>{\"use strict\";Object.defineProperty(FN,\"__esModule\",{value:!0});FN.ValidationError=void 0;var aY=class extends Error{constructor(t,r){super(t),this.fields=r}};FN.ValidationError=aY});var cY=G(ny=>{\"use strict\";Object.defineProperty(ny,\"__esModule\",{value:!0});ny.assertBundle=Jmt;ny.assertBundleV01=Y2e;ny.isBundleV01=zmt;ny.assertBundleV02=Zmt;ny.assertBundleLatest=Xmt;var NN=lY();function Jmt(e){let t=ON(e);if(t.length>0)throw new NN.ValidationError(\"invalid bundle\",t)}function Y2e(e){let t=[];if(t.push(...ON(e)),t.push(...$mt(e)),t.length>0)throw new NN.ValidationError(\"invalid v0.1 bundle\",t)}function zmt(e){try{return Y2e(e),!0}catch{return!1}}function Zmt(e){let t=[];if(t.push(...ON(e)),t.push(...K2e(e)),t.length>0)throw new NN.ValidationError(\"invalid v0.2 bundle\",t)}function Xmt(e){let t=[];if(t.push(...ON(e)),t.push(...K2e(e)),t.push(...eyt(e)),t.length>0)throw new NN.ValidationError(\"invalid bundle\",t)}function ON(e){let t=[];if((e.mediaType===void 0||!e.mediaType.match(/^application\\/vnd\\.dev\\.sigstore\\.bundle\\+json;version=\\d\\.\\d/)&&!e.mediaType.match(/^application\\/vnd\\.dev\\.sigstore\\.bundle\\.v\\d\\.\\d\\+json/))&&t.push(\"mediaType\"),e.content===void 0)t.push(\"content\");else switch(e.content.$case){case\"messageSignature\":e.content.messageSignature.messageDigest===void 0?t.push(\"content.messageSignature.messageDigest\"):e.content.messageSignature.messageDigest.digest.length===0&&t.push(\"content.messageSignature.messageDigest.digest\"),e.content.messageSignature.signature.length===0&&t.push(\"content.messageSignature.signature\");break;case\"dsseEnvelope\":e.content.dsseEnvelope.payload.length===0&&t.push(\"content.dsseEnvelope.payload\"),e.content.dsseEnvelope.signatures.length!==1?t.push(\"content.dsseEnvelope.signatures\"):e.content.dsseEnvelope.signatures[0].sig.length===0&&t.push(\"content.dsseEnvelope.signatures[0].sig\");break}if(e.verificationMaterial===void 0)t.push(\"verificationMaterial\");else{if(e.verificationMaterial.content===void 0)t.push(\"verificationMaterial.content\");else switch(e.verificationMaterial.content.$case){case\"x509CertificateChain\":e.verificationMaterial.content.x509CertificateChain.certificates.length===0&&t.push(\"verificationMaterial.content.x509CertificateChain.certificates\"),e.verificationMaterial.content.x509CertificateChain.certificates.forEach((r,s)=>{r.rawBytes.length===0&&t.push(`verificationMaterial.content.x509CertificateChain.certificates[${s}].rawBytes`)});break;case\"certificate\":e.verificationMaterial.content.certificate.rawBytes.length===0&&t.push(\"verificationMaterial.content.certificate.rawBytes\");break}e.verificationMaterial.tlogEntries===void 0?t.push(\"verificationMaterial.tlogEntries\"):e.verificationMaterial.tlogEntries.length>0&&e.verificationMaterial.tlogEntries.forEach((r,s)=>{r.logId===void 0&&t.push(`verificationMaterial.tlogEntries[${s}].logId`),r.kindVersion===void 0&&t.push(`verificationMaterial.tlogEntries[${s}].kindVersion`)})}return t}function $mt(e){let t=[];return e.verificationMaterial&&e.verificationMaterial.tlogEntries?.length>0&&e.verificationMaterial.tlogEntries.forEach((r,s)=>{r.inclusionPromise===void 0&&t.push(`verificationMaterial.tlogEntries[${s}].inclusionPromise`)}),t}function K2e(e){let t=[];return e.verificationMaterial&&e.verificationMaterial.tlogEntries?.length>0&&e.verificationMaterial.tlogEntries.forEach((r,s)=>{r.inclusionProof===void 0?t.push(`verificationMaterial.tlogEntries[${s}].inclusionProof`):r.inclusionProof.checkpoint===void 0&&t.push(`verificationMaterial.tlogEntries[${s}].inclusionProof.checkpoint`)}),t}function eyt(e){let t=[];return e.verificationMaterial?.content?.$case===\"x509CertificateChain\"&&t.push(\"verificationMaterial.content.$case\"),t}});var z2e=G(vA=>{\"use strict\";Object.defineProperty(vA,\"__esModule\",{value:!0});vA.envelopeToJSON=vA.envelopeFromJSON=vA.bundleToJSON=vA.bundleFromJSON=void 0;var LN=yb(),J2e=QN(),uY=cY(),tyt=e=>{let t=LN.Bundle.fromJSON(e);switch(t.mediaType){case J2e.BUNDLE_V01_MEDIA_TYPE:(0,uY.assertBundleV01)(t);break;case J2e.BUNDLE_V02_MEDIA_TYPE:(0,uY.assertBundleV02)(t);break;default:(0,uY.assertBundleLatest)(t);break}return t};vA.bundleFromJSON=tyt;var ryt=e=>LN.Bundle.toJSON(e);vA.bundleToJSON=ryt;var nyt=e=>LN.Envelope.fromJSON(e);vA.envelopeFromJSON=nyt;var iyt=e=>LN.Envelope.toJSON(e);vA.envelopeToJSON=iyt});var Ib=G(Zr=>{\"use strict\";Object.defineProperty(Zr,\"__esModule\",{value:!0});Zr.isBundleV01=Zr.assertBundleV02=Zr.assertBundleV01=Zr.assertBundleLatest=Zr.assertBundle=Zr.envelopeToJSON=Zr.envelopeFromJSON=Zr.bundleToJSON=Zr.bundleFromJSON=Zr.ValidationError=Zr.isBundleWithPublicKey=Zr.isBundleWithMessageSignature=Zr.isBundleWithDsseEnvelope=Zr.isBundleWithCertificateChain=Zr.BUNDLE_V03_MEDIA_TYPE=Zr.BUNDLE_V03_LEGACY_MEDIA_TYPE=Zr.BUNDLE_V02_MEDIA_TYPE=Zr.BUNDLE_V01_MEDIA_TYPE=Zr.toMessageSignatureBundle=Zr.toDSSEBundle=void 0;var Z2e=V2e();Object.defineProperty(Zr,\"toDSSEBundle\",{enumerable:!0,get:function(){return Z2e.toDSSEBundle}});Object.defineProperty(Zr,\"toMessageSignatureBundle\",{enumerable:!0,get:function(){return Z2e.toMessageSignatureBundle}});var yg=QN();Object.defineProperty(Zr,\"BUNDLE_V01_MEDIA_TYPE\",{enumerable:!0,get:function(){return yg.BUNDLE_V01_MEDIA_TYPE}});Object.defineProperty(Zr,\"BUNDLE_V02_MEDIA_TYPE\",{enumerable:!0,get:function(){return yg.BUNDLE_V02_MEDIA_TYPE}});Object.defineProperty(Zr,\"BUNDLE_V03_LEGACY_MEDIA_TYPE\",{enumerable:!0,get:function(){return yg.BUNDLE_V03_LEGACY_MEDIA_TYPE}});Object.defineProperty(Zr,\"BUNDLE_V03_MEDIA_TYPE\",{enumerable:!0,get:function(){return yg.BUNDLE_V03_MEDIA_TYPE}});Object.defineProperty(Zr,\"isBundleWithCertificateChain\",{enumerable:!0,get:function(){return yg.isBundleWithCertificateChain}});Object.defineProperty(Zr,\"isBundleWithDsseEnvelope\",{enumerable:!0,get:function(){return yg.isBundleWithDsseEnvelope}});Object.defineProperty(Zr,\"isBundleWithMessageSignature\",{enumerable:!0,get:function(){return yg.isBundleWithMessageSignature}});Object.defineProperty(Zr,\"isBundleWithPublicKey\",{enumerable:!0,get:function(){return yg.isBundleWithPublicKey}});var syt=lY();Object.defineProperty(Zr,\"ValidationError\",{enumerable:!0,get:function(){return syt.ValidationError}});var MN=z2e();Object.defineProperty(Zr,\"bundleFromJSON\",{enumerable:!0,get:function(){return MN.bundleFromJSON}});Object.defineProperty(Zr,\"bundleToJSON\",{enumerable:!0,get:function(){return MN.bundleToJSON}});Object.defineProperty(Zr,\"envelopeFromJSON\",{enumerable:!0,get:function(){return MN.envelopeFromJSON}});Object.defineProperty(Zr,\"envelopeToJSON\",{enumerable:!0,get:function(){return MN.envelopeToJSON}});var Eb=cY();Object.defineProperty(Zr,\"assertBundle\",{enumerable:!0,get:function(){return Eb.assertBundle}});Object.defineProperty(Zr,\"assertBundleLatest\",{enumerable:!0,get:function(){return Eb.assertBundleLatest}});Object.defineProperty(Zr,\"assertBundleV01\",{enumerable:!0,get:function(){return Eb.assertBundleV01}});Object.defineProperty(Zr,\"assertBundleV02\",{enumerable:!0,get:function(){return Eb.assertBundleV02}});Object.defineProperty(Zr,\"isBundleV01\",{enumerable:!0,get:function(){return Eb.isBundleV01}})});var Cb=G(_N=>{\"use strict\";Object.defineProperty(_N,\"__esModule\",{value:!0});_N.ByteStream=void 0;var fY=class extends Error{},UN=class e{constructor(t){this.start=0,t?(this.buf=t,this.view=Buffer.from(t)):(this.buf=new ArrayBuffer(0),this.view=Buffer.from(this.buf))}get buffer(){return this.view.subarray(0,this.start)}get length(){return this.view.byteLength}get position(){return this.start}seek(t){this.start=t}slice(t,r){let s=t+r;if(s>this.length)throw new fY(\"request past end of buffer\");return this.view.subarray(t,s)}appendChar(t){this.ensureCapacity(1),this.view[this.start]=t,this.start+=1}appendUint16(t){this.ensureCapacity(2);let r=new Uint16Array([t]),s=new Uint8Array(r.buffer);this.view[this.start]=s[1],this.view[this.start+1]=s[0],this.start+=2}appendUint24(t){this.ensureCapacity(3);let r=new Uint32Array([t]),s=new Uint8Array(r.buffer);this.view[this.start]=s[2],this.view[this.start+1]=s[1],this.view[this.start+2]=s[0],this.start+=3}appendView(t){this.ensureCapacity(t.length),this.view.set(t,this.start),this.start+=t.length}getBlock(t){if(t<=0)return Buffer.alloc(0);if(this.start+t>this.view.length)throw new Error(\"request past end of buffer\");let r=this.view.subarray(this.start,this.start+t);return this.start+=t,r}getUint8(){return this.getBlock(1)[0]}getUint16(){let t=this.getBlock(2);return t[0]<<8|t[1]}ensureCapacity(t){if(this.start+t>this.view.byteLength){let r=e.BLOCK_SIZE+(t>e.BLOCK_SIZE?t:0);this.realloc(this.view.byteLength+r)}}realloc(t){let r=new ArrayBuffer(t),s=Buffer.from(r);s.set(this.view),this.buf=r,this.view=s}};_N.ByteStream=UN;UN.BLOCK_SIZE=1024});var HN=G(Uw=>{\"use strict\";Object.defineProperty(Uw,\"__esModule\",{value:!0});Uw.ASN1TypeError=Uw.ASN1ParseError=void 0;var AY=class extends Error{};Uw.ASN1ParseError=AY;var pY=class extends Error{};Uw.ASN1TypeError=pY});var $2e=G(jN=>{\"use strict\";Object.defineProperty(jN,\"__esModule\",{value:!0});jN.decodeLength=oyt;jN.encodeLength=ayt;var X2e=HN();function oyt(e){let t=e.getUint8();if(!(t&128))return t;let r=t&127;if(r>6)throw new X2e.ASN1ParseError(\"length exceeds 6 byte limit\");let s=0;for(let a=0;a<r;a++)s=s*256+e.getUint8();if(s===0)throw new X2e.ASN1ParseError(\"indefinite length encoding not supported\");return s}function ayt(e){if(e<128)return Buffer.from([e]);let t=BigInt(e),r=[];for(;t>0n;)r.unshift(Number(t&255n)),t=t>>8n;return Buffer.from([128|r.length,...r])}});var tve=G(Eg=>{\"use strict\";Object.defineProperty(Eg,\"__esModule\",{value:!0});Eg.parseInteger=uyt;Eg.parseStringASCII=eve;Eg.parseTime=fyt;Eg.parseOID=Ayt;Eg.parseBoolean=pyt;Eg.parseBitString=hyt;var lyt=/^(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\.\\d{3})?Z$/,cyt=/^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\.\\d{3})?Z$/;function uyt(e){let t=0,r=e.length,s=e[t],a=s>127,n=a?255:0;for(;s==n&&++t<r;)s=e[t];if(r-t===0)return BigInt(a?-1:0);s=a?s-256:s;let f=BigInt(s);for(let p=t+1;p<r;++p)f=f*BigInt(256)+BigInt(e[p]);return f}function eve(e){return e.toString(\"ascii\")}function fyt(e,t){let r=eve(e),s=t?lyt.exec(r):cyt.exec(r);if(!s)throw new Error(\"invalid time\");if(t){let a=Number(s[1]);a+=a>=50?1900:2e3,s[1]=a.toString()}return new Date(`${s[1]}-${s[2]}-${s[3]}T${s[4]}:${s[5]}:${s[6]}Z`)}function Ayt(e){let t=0,r=e.length,s=e[t++],a=Math.floor(s/40),n=s%40,c=`${a}.${n}`,f=0;for(;t<r;++t)s=e[t],f=(f<<7)+(s&127),s&128||(c+=`.${f}`,f=0);return c}function pyt(e){return e[0]!==0}function hyt(e){let t=e[0],r=1,s=e.length,a=[];for(let n=r;n<s;++n){let c=e[n],f=n===s-1?t:0;for(let p=7;p>=f;--p)a.push(c>>p&1)}return a}});var nve=G(GN=>{\"use strict\";Object.defineProperty(GN,\"__esModule\",{value:!0});GN.ASN1Tag=void 0;var rve=HN(),iy={BOOLEAN:1,INTEGER:2,BIT_STRING:3,OCTET_STRING:4,OBJECT_IDENTIFIER:6,SEQUENCE:16,SET:17,PRINTABLE_STRING:19,UTC_TIME:23,GENERALIZED_TIME:24},hY={UNIVERSAL:0,APPLICATION:1,CONTEXT_SPECIFIC:2,PRIVATE:3},gY=class{constructor(t){if(this.number=t&31,this.constructed=(t&32)===32,this.class=t>>6,this.number===31)throw new rve.ASN1ParseError(\"long form tags not supported\");if(this.class===hY.UNIVERSAL&&this.number===0)throw new rve.ASN1ParseError(\"unsupported tag 0x00\")}isUniversal(){return this.class===hY.UNIVERSAL}isContextSpecific(t){let r=this.class===hY.CONTEXT_SPECIFIC;return t!==void 0?r&&this.number===t:r}isBoolean(){return this.isUniversal()&&this.number===iy.BOOLEAN}isInteger(){return this.isUniversal()&&this.number===iy.INTEGER}isBitString(){return this.isUniversal()&&this.number===iy.BIT_STRING}isOctetString(){return this.isUniversal()&&this.number===iy.OCTET_STRING}isOID(){return this.isUniversal()&&this.number===iy.OBJECT_IDENTIFIER}isUTCTime(){return this.isUniversal()&&this.number===iy.UTC_TIME}isGeneralizedTime(){return this.isUniversal()&&this.number===iy.GENERALIZED_TIME}toDER(){return this.number|(this.constructed?32:0)|this.class<<6}};GN.ASN1Tag=gY});var ave=G(WN=>{\"use strict\";Object.defineProperty(WN,\"__esModule\",{value:!0});WN.ASN1Obj=void 0;var dY=Cb(),sy=HN(),sve=$2e(),_w=tve(),gyt=nve(),qN=class{constructor(t,r,s){this.tag=t,this.value=r,this.subs=s}static parseBuffer(t){return ove(new dY.ByteStream(t))}toDER(){let t=new dY.ByteStream;if(this.subs.length>0)for(let a of this.subs)t.appendView(a.toDER());else t.appendView(this.value);let r=t.buffer,s=new dY.ByteStream;return s.appendChar(this.tag.toDER()),s.appendView((0,sve.encodeLength)(r.length)),s.appendView(r),s.buffer}toBoolean(){if(!this.tag.isBoolean())throw new sy.ASN1TypeError(\"not a boolean\");return(0,_w.parseBoolean)(this.value)}toInteger(){if(!this.tag.isInteger())throw new sy.ASN1TypeError(\"not an integer\");return(0,_w.parseInteger)(this.value)}toOID(){if(!this.tag.isOID())throw new sy.ASN1TypeError(\"not an OID\");return(0,_w.parseOID)(this.value)}toDate(){switch(!0){case this.tag.isUTCTime():return(0,_w.parseTime)(this.value,!0);case this.tag.isGeneralizedTime():return(0,_w.parseTime)(this.value,!1);default:throw new sy.ASN1TypeError(\"not a date\")}}toBitString(){if(!this.tag.isBitString())throw new sy.ASN1TypeError(\"not a bit string\");return(0,_w.parseBitString)(this.value)}};WN.ASN1Obj=qN;function ove(e){let t=new gyt.ASN1Tag(e.getUint8()),r=(0,sve.decodeLength)(e),s=e.slice(e.position,r),a=e.position,n=[];if(t.constructed)n=ive(e,r);else if(t.isOctetString())try{n=ive(e,r)}catch{}return n.length===0&&e.seek(a+r),new qN(t,s,n)}function ive(e,t){let r=e.position+t;if(r>e.length)throw new sy.ASN1ParseError(\"invalid length\");let s=[];for(;e.position<r;)s.push(ove(e));if(e.position!==r)throw new sy.ASN1ParseError(\"invalid length\");return s}});var YN=G(VN=>{\"use strict\";Object.defineProperty(VN,\"__esModule\",{value:!0});VN.ASN1Obj=void 0;var dyt=ave();Object.defineProperty(VN,\"ASN1Obj\",{enumerable:!0,get:function(){return dyt.ASN1Obj}})});var Hw=G(Ig=>{\"use strict\";var myt=Ig&&Ig.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ig,\"__esModule\",{value:!0});Ig.createPublicKey=yyt;Ig.digest=Eyt;Ig.verify=Iyt;Ig.bufferEqual=Cyt;var wb=myt(Ie(\"crypto\"));function yyt(e,t=\"spki\"){return typeof e==\"string\"?wb.default.createPublicKey(e):wb.default.createPublicKey({key:e,format:\"der\",type:t})}function Eyt(e,...t){let r=wb.default.createHash(e);for(let s of t)r.update(s);return r.digest()}function Iyt(e,t,r,s){try{return wb.default.verify(s,e,t,r)}catch{return!1}}function Cyt(e,t){try{return wb.default.timingSafeEqual(e,t)}catch{return!1}}});var lve=G(mY=>{\"use strict\";Object.defineProperty(mY,\"__esModule\",{value:!0});mY.preAuthEncoding=Byt;var wyt=\"DSSEv1\";function Byt(e,t){let r=[wyt,e.length,e,t.length,\"\"].join(\" \");return Buffer.concat([Buffer.from(r,\"ascii\"),t])}});var fve=G(KN=>{\"use strict\";Object.defineProperty(KN,\"__esModule\",{value:!0});KN.base64Encode=vyt;KN.base64Decode=Syt;var cve=\"base64\",uve=\"utf-8\";function vyt(e){return Buffer.from(e,uve).toString(cve)}function Syt(e){return Buffer.from(e,cve).toString(uve)}});var Ave=G(EY=>{\"use strict\";Object.defineProperty(EY,\"__esModule\",{value:!0});EY.canonicalize=yY;function yY(e){let t=\"\";if(e===null||typeof e!=\"object\"||e.toJSON!=null)t+=JSON.stringify(e);else if(Array.isArray(e)){t+=\"[\";let r=!0;e.forEach(s=>{r||(t+=\",\"),r=!1,t+=yY(s)}),t+=\"]\"}else{t+=\"{\";let r=!0;Object.keys(e).sort().forEach(s=>{r||(t+=\",\"),r=!1,t+=JSON.stringify(s),t+=\":\",t+=yY(e[s])}),t+=\"}\"}return t}});var IY=G(JN=>{\"use strict\";Object.defineProperty(JN,\"__esModule\",{value:!0});JN.toDER=Pyt;JN.fromDER=xyt;var Dyt=/-----BEGIN (.*)-----/,byt=/-----END (.*)-----/;function Pyt(e){let t=\"\";return e.split(`\n`).forEach(r=>{r.match(Dyt)||r.match(byt)||(t+=r)}),Buffer.from(t,\"base64\")}function xyt(e,t=\"CERTIFICATE\"){let s=e.toString(\"base64\").match(/.{1,64}/g)||\"\";return[`-----BEGIN ${t}-----`,...s,`-----END ${t}-----`].join(`\n`).concat(`\n`)}});var zN=G(jw=>{\"use strict\";Object.defineProperty(jw,\"__esModule\",{value:!0});jw.SHA2_HASH_ALGOS=jw.ECDSA_SIGNATURE_ALGOS=void 0;jw.ECDSA_SIGNATURE_ALGOS={\"1.2.840.10045.4.3.1\":\"sha224\",\"1.2.840.10045.4.3.2\":\"sha256\",\"1.2.840.10045.4.3.3\":\"sha384\",\"1.2.840.10045.4.3.4\":\"sha512\"};jw.SHA2_HASH_ALGOS={\"2.16.840.1.101.3.4.2.1\":\"sha256\",\"2.16.840.1.101.3.4.2.2\":\"sha384\",\"2.16.840.1.101.3.4.2.3\":\"sha512\"}});var wY=G(ZN=>{\"use strict\";Object.defineProperty(ZN,\"__esModule\",{value:!0});ZN.RFC3161TimestampVerificationError=void 0;var CY=class extends Error{};ZN.RFC3161TimestampVerificationError=CY});var hve=G(SA=>{\"use strict\";var kyt=SA&&SA.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Qyt=SA&&SA.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Ryt=SA&&SA.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&kyt(t,e,r);return Qyt(t,e),t};Object.defineProperty(SA,\"__esModule\",{value:!0});SA.TSTInfo=void 0;var pve=Ryt(Hw()),Tyt=zN(),Fyt=wY(),BY=class{constructor(t){this.root=t}get version(){return this.root.subs[0].toInteger()}get genTime(){return this.root.subs[4].toDate()}get messageImprintHashAlgorithm(){let t=this.messageImprintObj.subs[0].subs[0].toOID();return Tyt.SHA2_HASH_ALGOS[t]}get messageImprintHashedMessage(){return this.messageImprintObj.subs[1].value}get raw(){return this.root.toDER()}verify(t){let r=pve.digest(this.messageImprintHashAlgorithm,t);if(!pve.bufferEqual(r,this.messageImprintHashedMessage))throw new Fyt.RFC3161TimestampVerificationError(\"message imprint does not match artifact\")}get messageImprintObj(){return this.root.subs[2]}};SA.TSTInfo=BY});var dve=G(DA=>{\"use strict\";var Nyt=DA&&DA.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Oyt=DA&&DA.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Lyt=DA&&DA.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&Nyt(t,e,r);return Oyt(t,e),t};Object.defineProperty(DA,\"__esModule\",{value:!0});DA.RFC3161Timestamp=void 0;var Myt=YN(),vY=Lyt(Hw()),gve=zN(),Bb=wY(),Uyt=hve(),_yt=\"1.2.840.113549.1.7.2\",Hyt=\"1.2.840.113549.1.9.16.1.4\",jyt=\"1.2.840.113549.1.9.4\",SY=class e{constructor(t){this.root=t}static parse(t){let r=Myt.ASN1Obj.parseBuffer(t);return new e(r)}get status(){return this.pkiStatusInfoObj.subs[0].toInteger()}get contentType(){return this.contentTypeObj.toOID()}get eContentType(){return this.eContentTypeObj.toOID()}get signingTime(){return this.tstInfo.genTime}get signerIssuer(){return this.signerSidObj.subs[0].value}get signerSerialNumber(){return this.signerSidObj.subs[1].value}get signerDigestAlgorithm(){let t=this.signerDigestAlgorithmObj.subs[0].toOID();return gve.SHA2_HASH_ALGOS[t]}get signatureAlgorithm(){let t=this.signatureAlgorithmObj.subs[0].toOID();return gve.ECDSA_SIGNATURE_ALGOS[t]}get signatureValue(){return this.signatureValueObj.value}get tstInfo(){return new Uyt.TSTInfo(this.eContentObj.subs[0].subs[0])}verify(t,r){if(!this.timeStampTokenObj)throw new Bb.RFC3161TimestampVerificationError(\"timeStampToken is missing\");if(this.contentType!==_yt)throw new Bb.RFC3161TimestampVerificationError(`incorrect content type: ${this.contentType}`);if(this.eContentType!==Hyt)throw new Bb.RFC3161TimestampVerificationError(`incorrect encapsulated content type: ${this.eContentType}`);this.tstInfo.verify(t),this.verifyMessageDigest(),this.verifySignature(r)}verifyMessageDigest(){let t=vY.digest(this.signerDigestAlgorithm,this.tstInfo.raw),r=this.messageDigestAttributeObj.subs[1].subs[0].value;if(!vY.bufferEqual(t,r))throw new Bb.RFC3161TimestampVerificationError(\"signed data does not match tstInfo\")}verifySignature(t){let r=this.signedAttrsObj.toDER();if(r[0]=49,!vY.verify(r,t,this.signatureValue,this.signatureAlgorithm))throw new Bb.RFC3161TimestampVerificationError(\"signature verification failed\")}get pkiStatusInfoObj(){return this.root.subs[0]}get timeStampTokenObj(){return this.root.subs[1]}get contentTypeObj(){return this.timeStampTokenObj.subs[0]}get signedDataObj(){return this.timeStampTokenObj.subs.find(r=>r.tag.isContextSpecific(0)).subs[0]}get encapContentInfoObj(){return this.signedDataObj.subs[2]}get signerInfosObj(){let t=this.signedDataObj;return t.subs[t.subs.length-1]}get signerInfoObj(){return this.signerInfosObj.subs[0]}get eContentTypeObj(){return this.encapContentInfoObj.subs[0]}get eContentObj(){return this.encapContentInfoObj.subs[1]}get signedAttrsObj(){return this.signerInfoObj.subs.find(r=>r.tag.isContextSpecific(0))}get messageDigestAttributeObj(){return this.signedAttrsObj.subs.find(r=>r.subs[0].tag.isOID()&&r.subs[0].toOID()===jyt)}get signerSidObj(){return this.signerInfoObj.subs[1]}get signerDigestAlgorithmObj(){return this.signerInfoObj.subs[2]}get signatureAlgorithmObj(){return this.signerInfoObj.subs[4]}get signatureValueObj(){return this.signerInfoObj.subs[5]}};DA.RFC3161Timestamp=SY});var mve=G(XN=>{\"use strict\";Object.defineProperty(XN,\"__esModule\",{value:!0});XN.RFC3161Timestamp=void 0;var Gyt=dve();Object.defineProperty(XN,\"RFC3161Timestamp\",{enumerable:!0,get:function(){return Gyt.RFC3161Timestamp}})});var Eve=G(bA=>{\"use strict\";var qyt=bA&&bA.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Wyt=bA&&bA.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Vyt=bA&&bA.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&qyt(t,e,r);return Wyt(t,e),t};Object.defineProperty(bA,\"__esModule\",{value:!0});bA.SignedCertificateTimestamp=void 0;var Yyt=Vyt(Hw()),yve=Cb(),DY=class e{constructor(t){this.version=t.version,this.logID=t.logID,this.timestamp=t.timestamp,this.extensions=t.extensions,this.hashAlgorithm=t.hashAlgorithm,this.signatureAlgorithm=t.signatureAlgorithm,this.signature=t.signature}get datetime(){return new Date(Number(this.timestamp.readBigInt64BE()))}get algorithm(){switch(this.hashAlgorithm){case 0:return\"none\";case 1:return\"md5\";case 2:return\"sha1\";case 3:return\"sha224\";case 4:return\"sha256\";case 5:return\"sha384\";case 6:return\"sha512\";default:return\"unknown\"}}verify(t,r){let s=new yve.ByteStream;return s.appendChar(this.version),s.appendChar(0),s.appendView(this.timestamp),s.appendUint16(1),s.appendView(t),s.appendUint16(this.extensions.byteLength),this.extensions.byteLength>0&&s.appendView(this.extensions),Yyt.verify(s.buffer,r,this.signature,this.algorithm)}static parse(t){let r=new yve.ByteStream(t),s=r.getUint8(),a=r.getBlock(32),n=r.getBlock(8),c=r.getUint16(),f=r.getBlock(c),p=r.getUint8(),h=r.getUint8(),E=r.getUint16(),C=r.getBlock(E);if(r.position!==t.length)throw new Error(\"SCT buffer length mismatch\");return new e({version:s,logID:a,timestamp:n,extensions:f,hashAlgorithm:p,signatureAlgorithm:h,signature:C})}};bA.SignedCertificateTimestamp=DY});var TY=G(ca=>{\"use strict\";Object.defineProperty(ca,\"__esModule\",{value:!0});ca.X509SCTExtension=ca.X509SubjectKeyIDExtension=ca.X509AuthorityKeyIDExtension=ca.X509SubjectAlternativeNameExtension=ca.X509KeyUsageExtension=ca.X509BasicConstraintsExtension=ca.X509Extension=void 0;var Kyt=Cb(),Jyt=Eve(),fh=class{constructor(t){this.root=t}get oid(){return this.root.subs[0].toOID()}get critical(){return this.root.subs.length===3?this.root.subs[1].toBoolean():!1}get value(){return this.extnValueObj.value}get valueObj(){return this.extnValueObj}get extnValueObj(){return this.root.subs[this.root.subs.length-1]}};ca.X509Extension=fh;var bY=class extends fh{get isCA(){return this.sequence.subs[0]?.toBoolean()??!1}get pathLenConstraint(){return this.sequence.subs.length>1?this.sequence.subs[1].toInteger():void 0}get sequence(){return this.extnValueObj.subs[0]}};ca.X509BasicConstraintsExtension=bY;var PY=class extends fh{get digitalSignature(){return this.bitString[0]===1}get keyCertSign(){return this.bitString[5]===1}get crlSign(){return this.bitString[6]===1}get bitString(){return this.extnValueObj.subs[0].toBitString()}};ca.X509KeyUsageExtension=PY;var xY=class extends fh{get rfc822Name(){return this.findGeneralName(1)?.value.toString(\"ascii\")}get uri(){return this.findGeneralName(6)?.value.toString(\"ascii\")}otherName(t){let r=this.findGeneralName(0);return r===void 0||r.subs[0].toOID()!==t?void 0:r.subs[1].subs[0].value.toString(\"ascii\")}findGeneralName(t){return this.generalNames.find(r=>r.tag.isContextSpecific(t))}get generalNames(){return this.extnValueObj.subs[0].subs}};ca.X509SubjectAlternativeNameExtension=xY;var kY=class extends fh{get keyIdentifier(){return this.findSequenceMember(0)?.value}findSequenceMember(t){return this.sequence.subs.find(r=>r.tag.isContextSpecific(t))}get sequence(){return this.extnValueObj.subs[0]}};ca.X509AuthorityKeyIDExtension=kY;var QY=class extends fh{get keyIdentifier(){return this.extnValueObj.subs[0].value}};ca.X509SubjectKeyIDExtension=QY;var RY=class extends fh{constructor(t){super(t)}get signedCertificateTimestamps(){let t=this.extnValueObj.subs[0].value,r=new Kyt.ByteStream(t),s=r.getUint16()+2,a=[];for(;r.position<s;){let n=r.getUint16(),c=r.getBlock(n);a.push(Jyt.SignedCertificateTimestamp.parse(c))}if(r.position!==s)throw new Error(\"SCT list length does not match actual length\");return a}};ca.X509SCTExtension=RY});var wve=G(sc=>{\"use strict\";var zyt=sc&&sc.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),Zyt=sc&&sc.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Cve=sc&&sc.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&zyt(t,e,r);return Zyt(t,e),t};Object.defineProperty(sc,\"__esModule\",{value:!0});sc.X509Certificate=sc.EXTENSION_OID_SCT=void 0;var Xyt=YN(),Ive=Cve(Hw()),$yt=zN(),eEt=Cve(IY()),oy=TY(),tEt=\"2.5.29.14\",rEt=\"2.5.29.15\",nEt=\"2.5.29.17\",iEt=\"2.5.29.19\",sEt=\"2.5.29.35\";sc.EXTENSION_OID_SCT=\"1.3.6.1.4.1.11129.2.4.2\";var FY=class e{constructor(t){this.root=t}static parse(t){let r=typeof t==\"string\"?eEt.toDER(t):t,s=Xyt.ASN1Obj.parseBuffer(r);return new e(s)}get tbsCertificate(){return this.tbsCertificateObj}get version(){return`v${(this.versionObj.subs[0].toInteger()+BigInt(1)).toString()}`}get serialNumber(){return this.serialNumberObj.value}get notBefore(){return this.validityObj.subs[0].toDate()}get notAfter(){return this.validityObj.subs[1].toDate()}get issuer(){return this.issuerObj.value}get subject(){return this.subjectObj.value}get publicKey(){return this.subjectPublicKeyInfoObj.toDER()}get signatureAlgorithm(){let t=this.signatureAlgorithmObj.subs[0].toOID();return $yt.ECDSA_SIGNATURE_ALGOS[t]}get signatureValue(){return this.signatureValueObj.value.subarray(1)}get subjectAltName(){let t=this.extSubjectAltName;return t?.uri||t?.rfc822Name}get extensions(){return this.extensionsObj?.subs[0]?.subs||[]}get extKeyUsage(){let t=this.findExtension(rEt);return t?new oy.X509KeyUsageExtension(t):void 0}get extBasicConstraints(){let t=this.findExtension(iEt);return t?new oy.X509BasicConstraintsExtension(t):void 0}get extSubjectAltName(){let t=this.findExtension(nEt);return t?new oy.X509SubjectAlternativeNameExtension(t):void 0}get extAuthorityKeyID(){let t=this.findExtension(sEt);return t?new oy.X509AuthorityKeyIDExtension(t):void 0}get extSubjectKeyID(){let t=this.findExtension(tEt);return t?new oy.X509SubjectKeyIDExtension(t):void 0}get extSCT(){let t=this.findExtension(sc.EXTENSION_OID_SCT);return t?new oy.X509SCTExtension(t):void 0}get isCA(){let t=this.extBasicConstraints?.isCA||!1;return this.extKeyUsage?t&&this.extKeyUsage.keyCertSign:t}extension(t){let r=this.findExtension(t);return r?new oy.X509Extension(r):void 0}verify(t){let r=t?.publicKey||this.publicKey,s=Ive.createPublicKey(r);return Ive.verify(this.tbsCertificate.toDER(),s,this.signatureValue,this.signatureAlgorithm)}validForDate(t){return this.notBefore<=t&&t<=this.notAfter}equals(t){return this.root.toDER().equals(t.root.toDER())}clone(){let t=this.root.toDER(),r=Buffer.alloc(t.length);return t.copy(r),e.parse(r)}findExtension(t){return this.extensions.find(r=>r.subs[0].toOID()===t)}get tbsCertificateObj(){return this.root.subs[0]}get signatureAlgorithmObj(){return this.root.subs[1]}get signatureValueObj(){return this.root.subs[2]}get versionObj(){return this.tbsCertificateObj.subs[0]}get serialNumberObj(){return this.tbsCertificateObj.subs[1]}get issuerObj(){return this.tbsCertificateObj.subs[3]}get validityObj(){return this.tbsCertificateObj.subs[4]}get subjectObj(){return this.tbsCertificateObj.subs[5]}get subjectPublicKeyInfoObj(){return this.tbsCertificateObj.subs[6]}get extensionsObj(){return this.tbsCertificateObj.subs.find(t=>t.tag.isContextSpecific(3))}};sc.X509Certificate=FY});var vve=G(Cg=>{\"use strict\";Object.defineProperty(Cg,\"__esModule\",{value:!0});Cg.X509SCTExtension=Cg.X509Certificate=Cg.EXTENSION_OID_SCT=void 0;var Bve=wve();Object.defineProperty(Cg,\"EXTENSION_OID_SCT\",{enumerable:!0,get:function(){return Bve.EXTENSION_OID_SCT}});Object.defineProperty(Cg,\"X509Certificate\",{enumerable:!0,get:function(){return Bve.X509Certificate}});var oEt=TY();Object.defineProperty(Cg,\"X509SCTExtension\",{enumerable:!0,get:function(){return oEt.X509SCTExtension}})});var bl=G(zn=>{\"use strict\";var aEt=zn&&zn.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),lEt=zn&&zn.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),vb=zn&&zn.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&aEt(t,e,r);return lEt(t,e),t};Object.defineProperty(zn,\"__esModule\",{value:!0});zn.X509SCTExtension=zn.X509Certificate=zn.EXTENSION_OID_SCT=zn.ByteStream=zn.RFC3161Timestamp=zn.pem=zn.json=zn.encoding=zn.dsse=zn.crypto=zn.ASN1Obj=void 0;var cEt=YN();Object.defineProperty(zn,\"ASN1Obj\",{enumerable:!0,get:function(){return cEt.ASN1Obj}});zn.crypto=vb(Hw());zn.dsse=vb(lve());zn.encoding=vb(fve());zn.json=vb(Ave());zn.pem=vb(IY());var uEt=mve();Object.defineProperty(zn,\"RFC3161Timestamp\",{enumerable:!0,get:function(){return uEt.RFC3161Timestamp}});var fEt=Cb();Object.defineProperty(zn,\"ByteStream\",{enumerable:!0,get:function(){return fEt.ByteStream}});var NY=vve();Object.defineProperty(zn,\"EXTENSION_OID_SCT\",{enumerable:!0,get:function(){return NY.EXTENSION_OID_SCT}});Object.defineProperty(zn,\"X509Certificate\",{enumerable:!0,get:function(){return NY.X509Certificate}});Object.defineProperty(zn,\"X509SCTExtension\",{enumerable:!0,get:function(){return NY.X509SCTExtension}})});var Sve=G(OY=>{\"use strict\";Object.defineProperty(OY,\"__esModule\",{value:!0});OY.extractJWTSubject=pEt;var AEt=bl();function pEt(e){let t=e.split(\".\",3),r=JSON.parse(AEt.encoding.base64Decode(t[1]));switch(r.iss){case\"https://accounts.google.com\":case\"https://oauth2.sigstore.dev/auth\":return r.email;default:return r.sub}}});var Dve=G((yer,hEt)=>{hEt.exports={name:\"@sigstore/sign\",version:\"3.1.0\",description:\"Sigstore signing library\",main:\"dist/index.js\",types:\"dist/index.d.ts\",scripts:{clean:\"shx rm -rf dist *.tsbuildinfo\",build:\"tsc --build\",test:\"jest\"},files:[\"dist\"],author:\"bdehamer@github.com\",license:\"Apache-2.0\",repository:{type:\"git\",url:\"git+https://github.com/sigstore/sigstore-js.git\"},bugs:{url:\"https://github.com/sigstore/sigstore-js/issues\"},homepage:\"https://github.com/sigstore/sigstore-js/tree/main/packages/sign#readme\",publishConfig:{provenance:!0},devDependencies:{\"@sigstore/jest\":\"^0.0.0\",\"@sigstore/mock\":\"^0.10.0\",\"@sigstore/rekor-types\":\"^3.0.0\",\"@types/make-fetch-happen\":\"^10.0.4\",\"@types/promise-retry\":\"^1.1.6\"},dependencies:{\"@sigstore/bundle\":\"^3.1.0\",\"@sigstore/core\":\"^2.0.0\",\"@sigstore/protobuf-specs\":\"^0.4.0\",\"make-fetch-happen\":\"^14.0.2\",\"proc-log\":\"^5.0.0\",\"promise-retry\":\"^2.0.1\"},engines:{node:\"^18.17.0 || >=20.5.0\"}}});var Pve=G(Gw=>{\"use strict\";var gEt=Gw&&Gw.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Gw,\"__esModule\",{value:!0});Gw.getUserAgent=void 0;var bve=gEt(Ie(\"os\")),dEt=()=>{let e=Dve().version,t=process.version,r=bve.default.platform(),s=bve.default.arch();return`sigstore-js/${e} (Node ${t}) (${r}/${s})`};Gw.getUserAgent=dEt});var wg=G(Ki=>{\"use strict\";var mEt=Ki&&Ki.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),yEt=Ki&&Ki.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),xve=Ki&&Ki.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(r){var s=[];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(s[s.length]=a);return s},e(t)};return function(t){if(t&&t.__esModule)return t;var r={};if(t!=null)for(var s=e(t),a=0;a<s.length;a++)s[a]!==\"default\"&&mEt(r,t,s[a]);return yEt(r,t),r}}();Object.defineProperty(Ki,\"__esModule\",{value:!0});Ki.ua=Ki.oidc=Ki.pem=Ki.json=Ki.encoding=Ki.dsse=Ki.crypto=void 0;var Sb=bl();Object.defineProperty(Ki,\"crypto\",{enumerable:!0,get:function(){return Sb.crypto}});Object.defineProperty(Ki,\"dsse\",{enumerable:!0,get:function(){return Sb.dsse}});Object.defineProperty(Ki,\"encoding\",{enumerable:!0,get:function(){return Sb.encoding}});Object.defineProperty(Ki,\"json\",{enumerable:!0,get:function(){return Sb.json}});Object.defineProperty(Ki,\"pem\",{enumerable:!0,get:function(){return Sb.pem}});Ki.oidc=xve(Sve());Ki.ua=xve(Pve())});var MY=G($N=>{\"use strict\";Object.defineProperty($N,\"__esModule\",{value:!0});$N.BaseBundleBuilder=void 0;var LY=class{constructor(t){this.signer=t.signer,this.witnesses=t.witnesses}async create(t){let r=await this.prepare(t).then(f=>this.signer.sign(f)),s=await this.package(t,r),a=await Promise.all(this.witnesses.map(f=>f.testify(s.content,EEt(r.key)))),n=[],c=[];return a.forEach(({tlogEntries:f,rfc3161Timestamps:p})=>{n.push(...f??[]),c.push(...p??[])}),s.verificationMaterial.tlogEntries=n,s.verificationMaterial.timestampVerificationData={rfc3161Timestamps:c},s}async prepare(t){return t.data}};$N.BaseBundleBuilder=LY;function EEt(e){switch(e.$case){case\"publicKey\":return e.publicKey;case\"x509Certificate\":return e.certificate}}});var _Y=G(PA=>{\"use strict\";var IEt=PA&&PA.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),CEt=PA&&PA.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),wEt=PA&&PA.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(r){var s=[];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(s[s.length]=a);return s},e(t)};return function(t){if(t&&t.__esModule)return t;var r={};if(t!=null)for(var s=e(t),a=0;a<s.length;a++)s[a]!==\"default\"&&IEt(r,t,s[a]);return CEt(r,t),r}}();Object.defineProperty(PA,\"__esModule\",{value:!0});PA.toMessageSignatureBundle=BEt;PA.toDSSEBundle=vEt;var kve=wEt(Ib()),UY=wg();function BEt(e,t){let r=UY.crypto.digest(\"sha256\",e.data);return kve.toMessageSignatureBundle({digest:r,signature:t.signature,certificate:t.key.$case===\"x509Certificate\"?UY.pem.toDER(t.key.certificate):void 0,keyHint:t.key.$case===\"publicKey\"?t.key.hint:void 0,certificateChain:!0})}function vEt(e,t,r){return kve.toDSSEBundle({artifact:e.data,artifactType:e.type,signature:t.signature,certificate:t.key.$case===\"x509Certificate\"?UY.pem.toDER(t.key.certificate):void 0,keyHint:t.key.$case===\"publicKey\"?t.key.hint:void 0,certificateChain:r})}});var Rve=G(eO=>{\"use strict\";Object.defineProperty(eO,\"__esModule\",{value:!0});eO.DSSEBundleBuilder=void 0;var SEt=wg(),DEt=MY(),bEt=_Y(),HY=class extends DEt.BaseBundleBuilder{constructor(t){super(t),this.certificateChain=t.certificateChain??!1}async prepare(t){let r=Qve(t);return SEt.dsse.preAuthEncoding(r.type,r.data)}async package(t,r){return(0,bEt.toDSSEBundle)(Qve(t),r,this.certificateChain)}};eO.DSSEBundleBuilder=HY;function Qve(e){return{...e,type:e.type??\"\"}}});var Tve=G(tO=>{\"use strict\";Object.defineProperty(tO,\"__esModule\",{value:!0});tO.MessageSignatureBundleBuilder=void 0;var PEt=MY(),xEt=_Y(),jY=class extends PEt.BaseBundleBuilder{constructor(t){super(t)}async package(t,r){return(0,xEt.toMessageSignatureBundle)(t,r)}};tO.MessageSignatureBundleBuilder=jY});var Fve=G(qw=>{\"use strict\";Object.defineProperty(qw,\"__esModule\",{value:!0});qw.MessageSignatureBundleBuilder=qw.DSSEBundleBuilder=void 0;var kEt=Rve();Object.defineProperty(qw,\"DSSEBundleBuilder\",{enumerable:!0,get:function(){return kEt.DSSEBundleBuilder}});var QEt=Tve();Object.defineProperty(qw,\"MessageSignatureBundleBuilder\",{enumerable:!0,get:function(){return QEt.MessageSignatureBundleBuilder}})});var nO=G(rO=>{\"use strict\";Object.defineProperty(rO,\"__esModule\",{value:!0});rO.HTTPError=void 0;var GY=class extends Error{constructor({status:t,message:r,location:s}){super(`(${t}) ${r}`),this.statusCode=t,this.location=s}};rO.HTTPError=GY});var Ww=G(Db=>{\"use strict\";Object.defineProperty(Db,\"__esModule\",{value:!0});Db.InternalError=void 0;Db.internalError=TEt;var REt=nO(),iO=class extends Error{constructor({code:t,message:r,cause:s}){super(r),this.name=this.constructor.name,this.cause=s,this.code=t}};Db.InternalError=iO;function TEt(e,t,r){throw e instanceof REt.HTTPError&&(r+=` - ${e.message}`),new iO({code:t,message:r,cause:e})}});var sO=G((Per,Nve)=>{Nve.exports=fetch});var Ove=G(Vw=>{\"use strict\";var FEt=Vw&&Vw.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Vw,\"__esModule\",{value:!0});Vw.CIContextProvider=void 0;var NEt=FEt(sO()),OEt=[LEt,MEt],qY=class{constructor(t=\"sigstore\"){this.audience=t}async getToken(){return Promise.any(OEt.map(t=>t(this.audience))).catch(()=>Promise.reject(\"CI: no tokens available\"))}};Vw.CIContextProvider=qY;async function LEt(e){if(!process.env.ACTIONS_ID_TOKEN_REQUEST_URL||!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN)return Promise.reject(\"no token available\");let t=new URL(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);return t.searchParams.append(\"audience\",e),(await(0,NEt.default)(t.href,{retry:2,headers:{Accept:\"application/json\",Authorization:`Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`}})).json().then(s=>s.value)}async function MEt(){return process.env.SIGSTORE_ID_TOKEN?process.env.SIGSTORE_ID_TOKEN:Promise.reject(\"no token available\")}});var Lve=G(oO=>{\"use strict\";Object.defineProperty(oO,\"__esModule\",{value:!0});oO.CIContextProvider=void 0;var UEt=Ove();Object.defineProperty(oO,\"CIContextProvider\",{enumerable:!0,get:function(){return UEt.CIContextProvider}})});var Uve=G((Qer,Mve)=>{var _Et=Symbol(\"proc-log.meta\");Mve.exports={META:_Et,output:{LEVELS:[\"standard\",\"error\",\"buffer\",\"flush\"],KEYS:{standard:\"standard\",error:\"error\",buffer:\"buffer\",flush:\"flush\"},standard:function(...e){return process.emit(\"output\",\"standard\",...e)},error:function(...e){return process.emit(\"output\",\"error\",...e)},buffer:function(...e){return process.emit(\"output\",\"buffer\",...e)},flush:function(...e){return process.emit(\"output\",\"flush\",...e)}},log:{LEVELS:[\"notice\",\"error\",\"warn\",\"info\",\"verbose\",\"http\",\"silly\",\"timing\",\"pause\",\"resume\"],KEYS:{notice:\"notice\",error:\"error\",warn:\"warn\",info:\"info\",verbose:\"verbose\",http:\"http\",silly:\"silly\",timing:\"timing\",pause:\"pause\",resume:\"resume\"},error:function(...e){return process.emit(\"log\",\"error\",...e)},notice:function(...e){return process.emit(\"log\",\"notice\",...e)},warn:function(...e){return process.emit(\"log\",\"warn\",...e)},info:function(...e){return process.emit(\"log\",\"info\",...e)},verbose:function(...e){return process.emit(\"log\",\"verbose\",...e)},http:function(...e){return process.emit(\"log\",\"http\",...e)},silly:function(...e){return process.emit(\"log\",\"silly\",...e)},timing:function(...e){return process.emit(\"log\",\"timing\",...e)},pause:function(){return process.emit(\"log\",\"pause\")},resume:function(){return process.emit(\"log\",\"resume\")}},time:{LEVELS:[\"start\",\"end\"],KEYS:{start:\"start\",end:\"end\"},start:function(e,t){process.emit(\"time\",\"start\",e);function r(){return process.emit(\"time\",\"end\",e)}if(typeof t==\"function\"){let s=t();return s&&s.finally?s.finally(r):(r(),s)}return r},end:function(e){return process.emit(\"time\",\"end\",e)}},input:{LEVELS:[\"start\",\"end\",\"read\"],KEYS:{start:\"start\",end:\"end\",read:\"read\"},start:function(e){process.emit(\"input\",\"start\");function t(){return process.emit(\"input\",\"end\")}if(typeof e==\"function\"){let r=e();return r&&r.finally?r.finally(t):(t(),r)}return t},end:function(){return process.emit(\"input\",\"end\")},read:function(...e){let t,r,s=new Promise((a,n)=>{t=a,r=n});return process.emit(\"input\",\"read\",t,r,...e),s}}}});var jve=G((Rer,Hve)=>{\"use strict\";function _ve(e,t){for(let r in t)Object.defineProperty(e,r,{value:t[r],enumerable:!0,configurable:!0});return e}function HEt(e,t,r){if(!e||typeof e==\"string\")throw new TypeError(\"Please pass an Error to err-code\");r||(r={}),typeof t==\"object\"&&(r=t,t=void 0),t!=null&&(r.code=t);try{return _ve(e,r)}catch{r.message=e.message,r.stack=e.stack;let a=function(){};return a.prototype=Object.create(Object.getPrototypeOf(e)),_ve(new a,r)}}Hve.exports=HEt});var qve=G((Ter,Gve)=>{function Zc(e,t){typeof t==\"boolean\"&&(t={forever:t}),this._originalTimeouts=JSON.parse(JSON.stringify(e)),this._timeouts=e,this._options=t||{},this._maxRetryTime=t&&t.maxRetryTime||1/0,this._fn=null,this._errors=[],this._attempts=1,this._operationTimeout=null,this._operationTimeoutCb=null,this._timeout=null,this._operationStart=null,this._options.forever&&(this._cachedTimeouts=this._timeouts.slice(0))}Gve.exports=Zc;Zc.prototype.reset=function(){this._attempts=1,this._timeouts=this._originalTimeouts};Zc.prototype.stop=function(){this._timeout&&clearTimeout(this._timeout),this._timeouts=[],this._cachedTimeouts=null};Zc.prototype.retry=function(e){if(this._timeout&&clearTimeout(this._timeout),!e)return!1;var t=new Date().getTime();if(e&&t-this._operationStart>=this._maxRetryTime)return this._errors.unshift(new Error(\"RetryOperation timeout occurred\")),!1;this._errors.push(e);var r=this._timeouts.shift();if(r===void 0)if(this._cachedTimeouts)this._errors.splice(this._errors.length-1,this._errors.length),this._timeouts=this._cachedTimeouts.slice(0),r=this._timeouts.shift();else return!1;var s=this,a=setTimeout(function(){s._attempts++,s._operationTimeoutCb&&(s._timeout=setTimeout(function(){s._operationTimeoutCb(s._attempts)},s._operationTimeout),s._options.unref&&s._timeout.unref()),s._fn(s._attempts)},r);return this._options.unref&&a.unref(),!0};Zc.prototype.attempt=function(e,t){this._fn=e,t&&(t.timeout&&(this._operationTimeout=t.timeout),t.cb&&(this._operationTimeoutCb=t.cb));var r=this;this._operationTimeoutCb&&(this._timeout=setTimeout(function(){r._operationTimeoutCb()},r._operationTimeout)),this._operationStart=new Date().getTime(),this._fn(this._attempts)};Zc.prototype.try=function(e){console.log(\"Using RetryOperation.try() is deprecated\"),this.attempt(e)};Zc.prototype.start=function(e){console.log(\"Using RetryOperation.start() is deprecated\"),this.attempt(e)};Zc.prototype.start=Zc.prototype.try;Zc.prototype.errors=function(){return this._errors};Zc.prototype.attempts=function(){return this._attempts};Zc.prototype.mainError=function(){if(this._errors.length===0)return null;for(var e={},t=null,r=0,s=0;s<this._errors.length;s++){var a=this._errors[s],n=a.message,c=(e[n]||0)+1;e[n]=c,c>=r&&(t=a,r=c)}return t}});var Wve=G(ay=>{var jEt=qve();ay.operation=function(e){var t=ay.timeouts(e);return new jEt(t,{forever:e&&e.forever,unref:e&&e.unref,maxRetryTime:e&&e.maxRetryTime})};ay.timeouts=function(e){if(e instanceof Array)return[].concat(e);var t={retries:10,factor:2,minTimeout:1*1e3,maxTimeout:1/0,randomize:!1};for(var r in e)t[r]=e[r];if(t.minTimeout>t.maxTimeout)throw new Error(\"minTimeout is greater than maxTimeout\");for(var s=[],a=0;a<t.retries;a++)s.push(this.createTimeout(a,t));return e&&e.forever&&!s.length&&s.push(this.createTimeout(a,t)),s.sort(function(n,c){return n-c}),s};ay.createTimeout=function(e,t){var r=t.randomize?Math.random()+1:1,s=Math.round(r*t.minTimeout*Math.pow(t.factor,e));return s=Math.min(s,t.maxTimeout),s};ay.wrap=function(e,t,r){if(t instanceof Array&&(r=t,t=null),!r){r=[];for(var s in e)typeof e[s]==\"function\"&&r.push(s)}for(var a=0;a<r.length;a++){var n=r[a],c=e[n];e[n]=function(p){var h=ay.operation(t),E=Array.prototype.slice.call(arguments,1),C=E.pop();E.push(function(S){h.retry(S)||(S&&(arguments[0]=h.mainError()),C.apply(this,arguments))}),h.attempt(function(){p.apply(e,E)})}.bind(e,c),e[n].options=t}}});var Yve=G((Ner,Vve)=>{Vve.exports=Wve()});var zve=G((Oer,Jve)=>{\"use strict\";var GEt=jve(),qEt=Yve(),WEt=Object.prototype.hasOwnProperty;function Kve(e){return e&&e.code===\"EPROMISERETRY\"&&WEt.call(e,\"retried\")}function VEt(e,t){var r,s;return typeof e==\"object\"&&typeof t==\"function\"&&(r=t,t=e,e=r),s=qEt.operation(t),new Promise(function(a,n){s.attempt(function(c){Promise.resolve().then(function(){return e(function(f){throw Kve(f)&&(f=f.retried),GEt(new Error(\"Retrying\"),\"EPROMISERETRY\",{retried:f})},c)}).then(a,function(f){Kve(f)&&(f=f.retried,s.retry(f||new Error))||n(f)})})})}Jve.exports=VEt});var aO=G(bb=>{\"use strict\";var Xve=bb&&bb.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(bb,\"__esModule\",{value:!0});bb.fetchWithRetry=iIt;var YEt=Ie(\"http2\"),KEt=Xve(sO()),Zve=Uve(),JEt=Xve(zve()),zEt=wg(),ZEt=nO(),{HTTP2_HEADER_LOCATION:XEt,HTTP2_HEADER_CONTENT_TYPE:$Et,HTTP2_HEADER_USER_AGENT:eIt,HTTP_STATUS_INTERNAL_SERVER_ERROR:tIt,HTTP_STATUS_TOO_MANY_REQUESTS:rIt,HTTP_STATUS_REQUEST_TIMEOUT:nIt}=YEt.constants;async function iIt(e,t){return(0,JEt.default)(async(r,s)=>{let a=t.method||\"POST\",n={[eIt]:zEt.ua.getUserAgent(),...t.headers},c=await(0,KEt.default)(e,{method:a,headers:n,body:t.body,timeout:t.timeout,retry:!1}).catch(f=>(Zve.log.http(\"fetch\",`${a} ${e} attempt ${s} failed with ${f}`),r(f)));if(c.ok)return c;{let f=await sIt(c);if(Zve.log.http(\"fetch\",`${a} ${e} attempt ${s} failed with ${c.status}`),oIt(c.status))return r(f);throw f}},aIt(t.retry))}var sIt=async e=>{let t=e.statusText,r=e.headers.get(XEt)||void 0;if(e.headers.get($Et)?.includes(\"application/json\"))try{t=(await e.json()).message||t}catch{}return new ZEt.HTTPError({status:e.status,message:t,location:r})},oIt=e=>[nIt,rIt].includes(e)||e>=tIt,aIt=e=>typeof e==\"boolean\"?{retries:e?1:0}:typeof e==\"number\"?{retries:e}:{retries:0,...e}});var $ve=G(lO=>{\"use strict\";Object.defineProperty(lO,\"__esModule\",{value:!0});lO.Fulcio=void 0;var lIt=aO(),WY=class{constructor(t){this.options=t}async createSigningCertificate(t){let{baseURL:r,retry:s,timeout:a}=this.options,n=`${r}/api/v2/signingCert`;return(await(0,lIt.fetchWithRetry)(n,{headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify(t),timeout:a,retry:s})).json()}};lO.Fulcio=WY});var eSe=G(cO=>{\"use strict\";Object.defineProperty(cO,\"__esModule\",{value:!0});cO.CAClient=void 0;var cIt=Ww(),uIt=$ve(),VY=class{constructor(t){this.fulcio=new uIt.Fulcio({baseURL:t.fulcioBaseURL,retry:t.retry,timeout:t.timeout})}async createSigningCertificate(t,r,s){let a=fIt(t,r,s);try{let n=await this.fulcio.createSigningCertificate(a);return(n.signedCertificateEmbeddedSct?n.signedCertificateEmbeddedSct:n.signedCertificateDetachedSct).chain.certificates}catch(n){(0,cIt.internalError)(n,\"CA_CREATE_SIGNING_CERTIFICATE_ERROR\",\"error creating signing certificate\")}}};cO.CAClient=VY;function fIt(e,t,r){return{credentials:{oidcIdentityToken:e},publicKeyRequest:{publicKey:{algorithm:\"ECDSA\",content:t},proofOfPossession:r.toString(\"base64\")}}}});var rSe=G(Yw=>{\"use strict\";var AIt=Yw&&Yw.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Yw,\"__esModule\",{value:!0});Yw.EphemeralSigner=void 0;var tSe=AIt(Ie(\"crypto\")),pIt=\"ec\",hIt=\"P-256\",YY=class{constructor(){this.keypair=tSe.default.generateKeyPairSync(pIt,{namedCurve:hIt})}async sign(t){let r=tSe.default.sign(null,t,this.keypair.privateKey),s=this.keypair.publicKey.export({format:\"pem\",type:\"spki\"}).toString(\"ascii\");return{signature:r,key:{$case:\"publicKey\",publicKey:s}}}};Yw.EphemeralSigner=YY});var nSe=G(ly=>{\"use strict\";Object.defineProperty(ly,\"__esModule\",{value:!0});ly.FulcioSigner=ly.DEFAULT_FULCIO_URL=void 0;var KY=Ww(),gIt=wg(),dIt=eSe(),mIt=rSe();ly.DEFAULT_FULCIO_URL=\"https://fulcio.sigstore.dev\";var JY=class{constructor(t){this.ca=new dIt.CAClient({...t,fulcioBaseURL:t.fulcioBaseURL||ly.DEFAULT_FULCIO_URL}),this.identityProvider=t.identityProvider,this.keyHolder=t.keyHolder||new mIt.EphemeralSigner}async sign(t){let r=await this.getIdentityToken(),s;try{s=gIt.oidc.extractJWTSubject(r)}catch(f){throw new KY.InternalError({code:\"IDENTITY_TOKEN_PARSE_ERROR\",message:`invalid identity token: ${r}`,cause:f})}let a=await this.keyHolder.sign(Buffer.from(s));if(a.key.$case!==\"publicKey\")throw new KY.InternalError({code:\"CA_CREATE_SIGNING_CERTIFICATE_ERROR\",message:\"unexpected format for signing key\"});let n=await this.ca.createSigningCertificate(r,a.key.publicKey,a.signature);return{signature:(await this.keyHolder.sign(t)).signature,key:{$case:\"x509Certificate\",certificate:n[0]}}}async getIdentityToken(){try{return await this.identityProvider.getToken()}catch(t){throw new KY.InternalError({code:\"IDENTITY_TOKEN_READ_ERROR\",message:\"error retrieving identity token\",cause:t})}}};ly.FulcioSigner=JY});var sSe=G(Kw=>{\"use strict\";Object.defineProperty(Kw,\"__esModule\",{value:!0});Kw.FulcioSigner=Kw.DEFAULT_FULCIO_URL=void 0;var iSe=nSe();Object.defineProperty(Kw,\"DEFAULT_FULCIO_URL\",{enumerable:!0,get:function(){return iSe.DEFAULT_FULCIO_URL}});Object.defineProperty(Kw,\"FulcioSigner\",{enumerable:!0,get:function(){return iSe.FulcioSigner}})});var lSe=G(uO=>{\"use strict\";Object.defineProperty(uO,\"__esModule\",{value:!0});uO.Rekor=void 0;var oSe=aO(),zY=class{constructor(t){this.options=t}async createEntry(t){let{baseURL:r,timeout:s,retry:a}=this.options,n=`${r}/api/v1/log/entries`,f=await(await(0,oSe.fetchWithRetry)(n,{headers:{\"Content-Type\":\"application/json\",Accept:\"application/json\"},body:JSON.stringify(t),timeout:s,retry:a})).json();return aSe(f)}async getEntry(t){let{baseURL:r,timeout:s,retry:a}=this.options,n=`${r}/api/v1/log/entries/${t}`,f=await(await(0,oSe.fetchWithRetry)(n,{method:\"GET\",headers:{Accept:\"application/json\"},timeout:s,retry:a})).json();return aSe(f)}};uO.Rekor=zY;function aSe(e){let t=Object.entries(e);if(t.length!=1)throw new Error(\"Received multiple entries in Rekor response\");let[r,s]=t[0];return{...s,uuid:r}}});var uSe=G(fO=>{\"use strict\";Object.defineProperty(fO,\"__esModule\",{value:!0});fO.TLogClient=void 0;var cSe=Ww(),yIt=nO(),EIt=lSe(),ZY=class{constructor(t){this.fetchOnConflict=t.fetchOnConflict??!1,this.rekor=new EIt.Rekor({baseURL:t.rekorBaseURL,retry:t.retry,timeout:t.timeout})}async createEntry(t){let r;try{r=await this.rekor.createEntry(t)}catch(s){if(IIt(s)&&this.fetchOnConflict){let a=s.location.split(\"/\").pop()||\"\";try{r=await this.rekor.getEntry(a)}catch(n){(0,cSe.internalError)(n,\"TLOG_FETCH_ENTRY_ERROR\",\"error fetching tlog entry\")}}else(0,cSe.internalError)(s,\"TLOG_CREATE_ENTRY_ERROR\",\"error creating tlog entry\")}return r}};fO.TLogClient=ZY;function IIt(e){return e instanceof yIt.HTTPError&&e.statusCode===409&&e.location!==void 0}});var fSe=G(XY=>{\"use strict\";Object.defineProperty(XY,\"__esModule\",{value:!0});XY.toProposedEntry=wIt;var CIt=Ib(),Bg=wg(),Pb=\"sha256\";function wIt(e,t,r=\"dsse\"){switch(e.$case){case\"dsseEnvelope\":return r===\"intoto\"?SIt(e.dsseEnvelope,t):vIt(e.dsseEnvelope,t);case\"messageSignature\":return BIt(e.messageSignature,t)}}function BIt(e,t){let r=e.messageDigest.digest.toString(\"hex\"),s=e.signature.toString(\"base64\"),a=Bg.encoding.base64Encode(t);return{apiVersion:\"0.0.1\",kind:\"hashedrekord\",spec:{data:{hash:{algorithm:Pb,value:r}},signature:{content:s,publicKey:{content:a}}}}}function vIt(e,t){let r=JSON.stringify((0,CIt.envelopeToJSON)(e)),s=Bg.encoding.base64Encode(t);return{apiVersion:\"0.0.1\",kind:\"dsse\",spec:{proposedContent:{envelope:r,verifiers:[s]}}}}function SIt(e,t){let r=Bg.crypto.digest(Pb,e.payload).toString(\"hex\"),s=DIt(e,t),a=Bg.encoding.base64Encode(e.payload.toString(\"base64\")),n=Bg.encoding.base64Encode(e.signatures[0].sig.toString(\"base64\")),c=e.signatures[0].keyid,f=Bg.encoding.base64Encode(t),p={payloadType:e.payloadType,payload:a,signatures:[{sig:n,publicKey:f}]};return c.length>0&&(p.signatures[0].keyid=c),{apiVersion:\"0.0.2\",kind:\"intoto\",spec:{content:{envelope:p,hash:{algorithm:Pb,value:s},payloadHash:{algorithm:Pb,value:r}}}}}function DIt(e,t){let r={payloadType:e.payloadType,payload:e.payload.toString(\"base64\"),signatures:[{sig:e.signatures[0].sig.toString(\"base64\"),publicKey:t}]};return e.signatures[0].keyid.length>0&&(r.signatures[0].keyid=e.signatures[0].keyid),Bg.crypto.digest(Pb,Bg.json.canonicalize(r)).toString(\"hex\")}});var ASe=G(cy=>{\"use strict\";Object.defineProperty(cy,\"__esModule\",{value:!0});cy.RekorWitness=cy.DEFAULT_REKOR_URL=void 0;var bIt=wg(),PIt=uSe(),xIt=fSe();cy.DEFAULT_REKOR_URL=\"https://rekor.sigstore.dev\";var $Y=class{constructor(t){this.entryType=t.entryType,this.tlog=new PIt.TLogClient({...t,rekorBaseURL:t.rekorBaseURL||cy.DEFAULT_REKOR_URL})}async testify(t,r){let s=(0,xIt.toProposedEntry)(t,r,this.entryType),a=await this.tlog.createEntry(s);return kIt(a)}};cy.RekorWitness=$Y;function kIt(e){let t=Buffer.from(e.logID,\"hex\"),r=bIt.encoding.base64Decode(e.body),s=JSON.parse(r),a=e?.verification?.signedEntryTimestamp?QIt(e.verification.signedEntryTimestamp):void 0,n=e?.verification?.inclusionProof?RIt(e.verification.inclusionProof):void 0;return{tlogEntries:[{logIndex:e.logIndex.toString(),logId:{keyId:t},integratedTime:e.integratedTime.toString(),kindVersion:{kind:s.kind,version:s.apiVersion},inclusionPromise:a,inclusionProof:n,canonicalizedBody:Buffer.from(e.body,\"base64\")}]}}function QIt(e){return{signedEntryTimestamp:Buffer.from(e,\"base64\")}}function RIt(e){return{logIndex:e.logIndex.toString(),treeSize:e.treeSize.toString(),rootHash:Buffer.from(e.rootHash,\"hex\"),hashes:e.hashes.map(t=>Buffer.from(t,\"hex\")),checkpoint:{envelope:e.checkpoint}}}});var pSe=G(AO=>{\"use strict\";Object.defineProperty(AO,\"__esModule\",{value:!0});AO.TimestampAuthority=void 0;var TIt=aO(),e7=class{constructor(t){this.options=t}async createTimestamp(t){let{baseURL:r,timeout:s,retry:a}=this.options,n=`${r}/api/v1/timestamp`;return(await(0,TIt.fetchWithRetry)(n,{headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify(t),timeout:s,retry:a})).buffer()}};AO.TimestampAuthority=e7});var gSe=G(pO=>{\"use strict\";Object.defineProperty(pO,\"__esModule\",{value:!0});pO.TSAClient=void 0;var FIt=Ww(),NIt=pSe(),OIt=wg(),hSe=\"sha256\",t7=class{constructor(t){this.tsa=new NIt.TimestampAuthority({baseURL:t.tsaBaseURL,retry:t.retry,timeout:t.timeout})}async createTimestamp(t){let r={artifactHash:OIt.crypto.digest(hSe,t).toString(\"base64\"),hashAlgorithm:hSe};try{return await this.tsa.createTimestamp(r)}catch(s){(0,FIt.internalError)(s,\"TSA_CREATE_TIMESTAMP_ERROR\",\"error creating timestamp\")}}};pO.TSAClient=t7});var dSe=G(hO=>{\"use strict\";Object.defineProperty(hO,\"__esModule\",{value:!0});hO.TSAWitness=void 0;var LIt=gSe(),r7=class{constructor(t){this.tsa=new LIt.TSAClient({tsaBaseURL:t.tsaBaseURL,retry:t.retry,timeout:t.timeout})}async testify(t){let r=MIt(t);return{rfc3161Timestamps:[{signedTimestamp:await this.tsa.createTimestamp(r)}]}}};hO.TSAWitness=r7;function MIt(e){switch(e.$case){case\"dsseEnvelope\":return e.dsseEnvelope.signatures[0].sig;case\"messageSignature\":return e.messageSignature.signature}}});var ySe=G(vg=>{\"use strict\";Object.defineProperty(vg,\"__esModule\",{value:!0});vg.TSAWitness=vg.RekorWitness=vg.DEFAULT_REKOR_URL=void 0;var mSe=ASe();Object.defineProperty(vg,\"DEFAULT_REKOR_URL\",{enumerable:!0,get:function(){return mSe.DEFAULT_REKOR_URL}});Object.defineProperty(vg,\"RekorWitness\",{enumerable:!0,get:function(){return mSe.RekorWitness}});var UIt=dSe();Object.defineProperty(vg,\"TSAWitness\",{enumerable:!0,get:function(){return UIt.TSAWitness}})});var i7=G(Cs=>{\"use strict\";Object.defineProperty(Cs,\"__esModule\",{value:!0});Cs.TSAWitness=Cs.RekorWitness=Cs.DEFAULT_REKOR_URL=Cs.FulcioSigner=Cs.DEFAULT_FULCIO_URL=Cs.CIContextProvider=Cs.InternalError=Cs.MessageSignatureBundleBuilder=Cs.DSSEBundleBuilder=void 0;var ESe=Fve();Object.defineProperty(Cs,\"DSSEBundleBuilder\",{enumerable:!0,get:function(){return ESe.DSSEBundleBuilder}});Object.defineProperty(Cs,\"MessageSignatureBundleBuilder\",{enumerable:!0,get:function(){return ESe.MessageSignatureBundleBuilder}});var _It=Ww();Object.defineProperty(Cs,\"InternalError\",{enumerable:!0,get:function(){return _It.InternalError}});var HIt=Lve();Object.defineProperty(Cs,\"CIContextProvider\",{enumerable:!0,get:function(){return HIt.CIContextProvider}});var ISe=sSe();Object.defineProperty(Cs,\"DEFAULT_FULCIO_URL\",{enumerable:!0,get:function(){return ISe.DEFAULT_FULCIO_URL}});Object.defineProperty(Cs,\"FulcioSigner\",{enumerable:!0,get:function(){return ISe.FulcioSigner}});var n7=ySe();Object.defineProperty(Cs,\"DEFAULT_REKOR_URL\",{enumerable:!0,get:function(){return n7.DEFAULT_REKOR_URL}});Object.defineProperty(Cs,\"RekorWitness\",{enumerable:!0,get:function(){return n7.RekorWitness}});Object.defineProperty(Cs,\"TSAWitness\",{enumerable:!0,get:function(){return n7.TSAWitness}})});var wSe=G(xb=>{\"use strict\";var CSe=xb&&xb.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(xb,\"__esModule\",{value:!0});xb.appDataPath=GIt;var jIt=CSe(Ie(\"os\")),Jw=CSe(Ie(\"path\"));function GIt(e){let t=jIt.default.homedir();switch(process.platform){case\"darwin\":{let r=Jw.default.join(t,\"Library\",\"Application Support\");return Jw.default.join(r,e)}case\"win32\":{let r=process.env.LOCALAPPDATA||Jw.default.join(t,\"AppData\",\"Local\");return Jw.default.join(r,e,\"Data\")}default:{let r=process.env.XDG_DATA_HOME||Jw.default.join(t,\".local\",\"share\");return Jw.default.join(r,e)}}}});var xA=G(Pl=>{\"use strict\";Object.defineProperty(Pl,\"__esModule\",{value:!0});Pl.UnsupportedAlgorithmError=Pl.CryptoError=Pl.LengthOrHashMismatchError=Pl.UnsignedMetadataError=Pl.RepositoryError=Pl.ValueError=void 0;var s7=class extends Error{};Pl.ValueError=s7;var kb=class extends Error{};Pl.RepositoryError=kb;var o7=class extends kb{};Pl.UnsignedMetadataError=o7;var a7=class extends kb{};Pl.LengthOrHashMismatchError=a7;var gO=class extends Error{};Pl.CryptoError=gO;var l7=class extends gO{};Pl.UnsupportedAlgorithmError=l7});var vSe=G(Sg=>{\"use strict\";Object.defineProperty(Sg,\"__esModule\",{value:!0});Sg.isDefined=qIt;Sg.isObject=BSe;Sg.isStringArray=WIt;Sg.isObjectArray=VIt;Sg.isStringRecord=YIt;Sg.isObjectRecord=KIt;function qIt(e){return e!==void 0}function BSe(e){return typeof e==\"object\"&&e!==null}function WIt(e){return Array.isArray(e)&&e.every(t=>typeof t==\"string\")}function VIt(e){return Array.isArray(e)&&e.every(BSe)}function YIt(e){return typeof e==\"object\"&&e!==null&&Object.keys(e).every(t=>typeof t==\"string\")&&Object.values(e).every(t=>typeof t==\"string\")}function KIt(e){return typeof e==\"object\"&&e!==null&&Object.keys(e).every(t=>typeof t==\"string\")&&Object.values(e).every(t=>typeof t==\"object\"&&t!==null)}});var u7=G((ttr,bSe)=>{var SSe=\",\",JIt=\":\",zIt=\"[\",ZIt=\"]\",XIt=\"{\",$It=\"}\";function c7(e){let t=[];if(typeof e==\"string\")t.push(DSe(e));else if(typeof e==\"boolean\")t.push(JSON.stringify(e));else if(Number.isInteger(e))t.push(JSON.stringify(e));else if(e===null)t.push(JSON.stringify(e));else if(Array.isArray(e)){t.push(zIt);let r=!0;e.forEach(s=>{r||t.push(SSe),r=!1,t.push(c7(s))}),t.push(ZIt)}else if(typeof e==\"object\"){t.push(XIt);let r=!0;Object.keys(e).sort().forEach(s=>{r||t.push(SSe),r=!1,t.push(DSe(s)),t.push(JIt),t.push(c7(e[s]))}),t.push($It)}else throw new TypeError(\"cannot encode \"+e.toString());return t.join(\"\")}function DSe(e){return'\"'+e.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"')+'\"'}bSe.exports={canonicalize:c7}});var PSe=G(zw=>{\"use strict\";var eCt=zw&&zw.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(zw,\"__esModule\",{value:!0});zw.verifySignature=void 0;var tCt=u7(),rCt=eCt(Ie(\"crypto\")),nCt=(e,t,r)=>{let s=Buffer.from((0,tCt.canonicalize)(e));return rCt.default.verify(void 0,s,t,Buffer.from(r,\"hex\"))};zw.verifySignature=nCt});var pf=G(Xc=>{\"use strict\";var iCt=Xc&&Xc.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),sCt=Xc&&Xc.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),xSe=Xc&&Xc.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&iCt(t,e,r);return sCt(t,e),t};Object.defineProperty(Xc,\"__esModule\",{value:!0});Xc.crypto=Xc.guard=void 0;Xc.guard=xSe(vSe());Xc.crypto=xSe(PSe())});var uy=G(Ah=>{\"use strict\";var oCt=Ah&&Ah.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ah,\"__esModule\",{value:!0});Ah.Signed=Ah.MetadataKind=void 0;Ah.isMetadataKind=lCt;var aCt=oCt(Ie(\"util\")),Qb=xA(),f7=pf(),kSe=[\"1\",\"0\",\"31\"],A7;(function(e){e.Root=\"root\",e.Timestamp=\"timestamp\",e.Snapshot=\"snapshot\",e.Targets=\"targets\"})(A7||(Ah.MetadataKind=A7={}));function lCt(e){return typeof e==\"string\"&&Object.values(A7).includes(e)}var p7=class e{constructor(t){this.specVersion=t.specVersion||kSe.join(\".\");let r=this.specVersion.split(\".\");if(!(r.length===2||r.length===3)||!r.every(s=>cCt(s)))throw new Qb.ValueError(\"Failed to parse specVersion\");if(r[0]!=kSe[0])throw new Qb.ValueError(\"Unsupported specVersion\");this.expires=t.expires,this.version=t.version,this.unrecognizedFields=t.unrecognizedFields||{}}equals(t){return t instanceof e?this.specVersion===t.specVersion&&this.expires===t.expires&&this.version===t.version&&aCt.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields):!1}isExpired(t){return t||(t=new Date),t>=new Date(this.expires)}static commonFieldsFromJSON(t){let{spec_version:r,expires:s,version:a,...n}=t;if(f7.guard.isDefined(r)){if(typeof r!=\"string\")throw new TypeError(\"spec_version must be a string\")}else throw new Qb.ValueError(\"spec_version is not defined\");if(f7.guard.isDefined(s)){if(typeof s!=\"string\")throw new TypeError(\"expires must be a string\")}else throw new Qb.ValueError(\"expires is not defined\");if(f7.guard.isDefined(a)){if(typeof a!=\"number\")throw new TypeError(\"version must be a number\")}else throw new Qb.ValueError(\"version is not defined\");return{specVersion:r,expires:s,version:a,unrecognizedFields:n}}};Ah.Signed=p7;function cCt(e){return!isNaN(Number(e))}});var Rb=G(bg=>{\"use strict\";var QSe=bg&&bg.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(bg,\"__esModule\",{value:!0});bg.TargetFile=bg.MetaFile=void 0;var RSe=QSe(Ie(\"crypto\")),mO=QSe(Ie(\"util\")),Dg=xA(),dO=pf(),h7=class e{constructor(t){if(t.version<=0)throw new Dg.ValueError(\"Metafile version must be at least 1\");t.length!==void 0&&TSe(t.length),this.version=t.version,this.length=t.length,this.hashes=t.hashes,this.unrecognizedFields=t.unrecognizedFields||{}}equals(t){return t instanceof e?this.version===t.version&&this.length===t.length&&mO.default.isDeepStrictEqual(this.hashes,t.hashes)&&mO.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields):!1}verify(t){if(this.length!==void 0&&t.length!==this.length)throw new Dg.LengthOrHashMismatchError(`Expected length ${this.length} but got ${t.length}`);this.hashes&&Object.entries(this.hashes).forEach(([r,s])=>{let a;try{a=RSe.default.createHash(r)}catch{throw new Dg.LengthOrHashMismatchError(`Hash algorithm ${r} not supported`)}let n=a.update(t).digest(\"hex\");if(n!==s)throw new Dg.LengthOrHashMismatchError(`Expected hash ${s} but got ${n}`)})}toJSON(){let t={version:this.version,...this.unrecognizedFields};return this.length!==void 0&&(t.length=this.length),this.hashes&&(t.hashes=this.hashes),t}static fromJSON(t){let{version:r,length:s,hashes:a,...n}=t;if(typeof r!=\"number\")throw new TypeError(\"version must be a number\");if(dO.guard.isDefined(s)&&typeof s!=\"number\")throw new TypeError(\"length must be a number\");if(dO.guard.isDefined(a)&&!dO.guard.isStringRecord(a))throw new TypeError(\"hashes must be string keys and values\");return new e({version:r,length:s,hashes:a,unrecognizedFields:n})}};bg.MetaFile=h7;var g7=class e{constructor(t){TSe(t.length),this.length=t.length,this.path=t.path,this.hashes=t.hashes,this.unrecognizedFields=t.unrecognizedFields||{}}get custom(){let t=this.unrecognizedFields.custom;return!t||Array.isArray(t)||typeof t!=\"object\"?{}:t}equals(t){return t instanceof e?this.length===t.length&&this.path===t.path&&mO.default.isDeepStrictEqual(this.hashes,t.hashes)&&mO.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields):!1}async verify(t){let r=0,s=Object.keys(this.hashes).reduce((a,n)=>{try{a[n]=RSe.default.createHash(n)}catch{throw new Dg.LengthOrHashMismatchError(`Hash algorithm ${n} not supported`)}return a},{});for await(let a of t)r+=a.length,Object.values(s).forEach(n=>{n.update(a)});if(r!==this.length)throw new Dg.LengthOrHashMismatchError(`Expected length ${this.length} but got ${r}`);Object.entries(s).forEach(([a,n])=>{let c=this.hashes[a],f=n.digest(\"hex\");if(f!==c)throw new Dg.LengthOrHashMismatchError(`Expected hash ${c} but got ${f}`)})}toJSON(){return{length:this.length,hashes:this.hashes,...this.unrecognizedFields}}static fromJSON(t,r){let{length:s,hashes:a,...n}=r;if(typeof s!=\"number\")throw new TypeError(\"length must be a number\");if(!dO.guard.isStringRecord(a))throw new TypeError(\"hashes must have string keys and values\");return new e({length:s,path:t,hashes:a,unrecognizedFields:n})}};bg.TargetFile=g7;function TSe(e){if(e<0)throw new Dg.ValueError(\"Length must be at least 0\")}});var FSe=G(d7=>{\"use strict\";Object.defineProperty(d7,\"__esModule\",{value:!0});d7.encodeOIDString=fCt;var uCt=6;function fCt(e){let t=e.split(\".\"),r=parseInt(t[0],10)*40+parseInt(t[1],10),s=[];t.slice(2).forEach(n=>{let c=ACt(parseInt(n,10));s.push(...c)});let a=Buffer.from([r,...s]);return Buffer.from([uCt,a.length,...a])}function ACt(e){let t=[],r=0;for(;e>0;)t.unshift(e&127|r),e>>=7,r=128;return t}});var MSe=G(Fb=>{\"use strict\";var pCt=Fb&&Fb.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Fb,\"__esModule\",{value:!0});Fb.getPublicKey=mCt;var Zw=pCt(Ie(\"crypto\")),Tb=xA(),m7=FSe(),yO=48,NSe=3,OSe=0,hCt=\"1.3.101.112\",gCt=\"1.2.840.10045.2.1\",dCt=\"1.2.840.10045.3.1.7\",y7=\"-----BEGIN PUBLIC KEY-----\";function mCt(e){switch(e.keyType){case\"rsa\":return yCt(e);case\"ed25519\":return ECt(e);case\"ecdsa\":case\"ecdsa-sha2-nistp256\":case\"ecdsa-sha2-nistp384\":return ICt(e);default:throw new Tb.UnsupportedAlgorithmError(`Unsupported key type: ${e.keyType}`)}}function yCt(e){if(!e.keyVal.startsWith(y7))throw new Tb.CryptoError(\"Invalid key format\");let t=Zw.default.createPublicKey(e.keyVal);switch(e.scheme){case\"rsassa-pss-sha256\":return{key:t,padding:Zw.default.constants.RSA_PKCS1_PSS_PADDING};default:throw new Tb.UnsupportedAlgorithmError(`Unsupported RSA scheme: ${e.scheme}`)}}function ECt(e){let t;if(e.keyVal.startsWith(y7))t=Zw.default.createPublicKey(e.keyVal);else{if(!LSe(e.keyVal))throw new Tb.CryptoError(\"Invalid key format\");t=Zw.default.createPublicKey({key:CCt.hexToDER(e.keyVal),format:\"der\",type:\"spki\"})}return{key:t}}function ICt(e){let t;if(e.keyVal.startsWith(y7))t=Zw.default.createPublicKey(e.keyVal);else{if(!LSe(e.keyVal))throw new Tb.CryptoError(\"Invalid key format\");t=Zw.default.createPublicKey({key:wCt.hexToDER(e.keyVal),format:\"der\",type:\"spki\"})}return{key:t}}var CCt={hexToDER:e=>{let t=Buffer.from(e,\"hex\"),r=(0,m7.encodeOIDString)(hCt),s=Buffer.concat([Buffer.concat([Buffer.from([yO]),Buffer.from([r.length]),r]),Buffer.concat([Buffer.from([NSe]),Buffer.from([t.length+1]),Buffer.from([OSe]),t])]);return Buffer.concat([Buffer.from([yO]),Buffer.from([s.length]),s])}},wCt={hexToDER:e=>{let t=Buffer.from(e,\"hex\"),r=Buffer.concat([Buffer.from([NSe]),Buffer.from([t.length+1]),Buffer.from([OSe]),t]),s=Buffer.concat([(0,m7.encodeOIDString)(gCt),(0,m7.encodeOIDString)(dCt)]),a=Buffer.concat([Buffer.from([yO]),Buffer.from([s.length]),s]);return Buffer.concat([Buffer.from([yO]),Buffer.from([a.length+r.length]),a,r])}},LSe=e=>/^[0-9a-fA-F]+$/.test(e)});var EO=G(Xw=>{\"use strict\";var BCt=Xw&&Xw.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Xw,\"__esModule\",{value:!0});Xw.Key=void 0;var USe=BCt(Ie(\"util\")),Nb=xA(),_Se=pf(),vCt=MSe(),E7=class e{constructor(t){let{keyID:r,keyType:s,scheme:a,keyVal:n,unrecognizedFields:c}=t;this.keyID=r,this.keyType=s,this.scheme=a,this.keyVal=n,this.unrecognizedFields=c||{}}verifySignature(t){let r=t.signatures[this.keyID];if(!r)throw new Nb.UnsignedMetadataError(\"no signature for key found in metadata\");if(!this.keyVal.public)throw new Nb.UnsignedMetadataError(\"no public key found\");let s=(0,vCt.getPublicKey)({keyType:this.keyType,scheme:this.scheme,keyVal:this.keyVal.public}),a=t.signed.toJSON();try{if(!_Se.crypto.verifySignature(a,s,r.sig))throw new Nb.UnsignedMetadataError(`failed to verify ${this.keyID} signature`)}catch(n){throw n instanceof Nb.UnsignedMetadataError?n:new Nb.UnsignedMetadataError(`failed to verify ${this.keyID} signature`)}}equals(t){return t instanceof e?this.keyID===t.keyID&&this.keyType===t.keyType&&this.scheme===t.scheme&&USe.default.isDeepStrictEqual(this.keyVal,t.keyVal)&&USe.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields):!1}toJSON(){return{keytype:this.keyType,scheme:this.scheme,keyval:this.keyVal,...this.unrecognizedFields}}static fromJSON(t,r){let{keytype:s,scheme:a,keyval:n,...c}=r;if(typeof s!=\"string\")throw new TypeError(\"keytype must be a string\");if(typeof a!=\"string\")throw new TypeError(\"scheme must be a string\");if(!_Se.guard.isStringRecord(n))throw new TypeError(\"keyval must be a string record\");return new e({keyID:t,keyType:s,scheme:a,keyVal:n,unrecognizedFields:c})}};Xw.Key=E7});var WSe=G((ctr,qSe)=>{\"use strict\";qSe.exports=jSe;function jSe(e,t,r){e instanceof RegExp&&(e=HSe(e,r)),t instanceof RegExp&&(t=HSe(t,r));var s=GSe(e,t,r);return s&&{start:s[0],end:s[1],pre:r.slice(0,s[0]),body:r.slice(s[0]+e.length,s[1]),post:r.slice(s[1]+t.length)}}function HSe(e,t){var r=t.match(e);return r?r[0]:null}jSe.range=GSe;function GSe(e,t,r){var s,a,n,c,f,p=r.indexOf(e),h=r.indexOf(t,p+1),E=p;if(p>=0&&h>0){for(s=[],n=r.length;E>=0&&!f;)E==p?(s.push(E),p=r.indexOf(e,E+1)):s.length==1?f=[s.pop(),h]:(a=s.pop(),a<n&&(n=a,c=h),h=r.indexOf(t,E+1)),E=p<h&&p>=0?p:h;s.length&&(f=[n,c])}return f}});var $Se=G((utr,XSe)=>{var VSe=WSe();XSe.exports=bCt;var YSe=\"\\0SLASH\"+Math.random()+\"\\0\",KSe=\"\\0OPEN\"+Math.random()+\"\\0\",C7=\"\\0CLOSE\"+Math.random()+\"\\0\",JSe=\"\\0COMMA\"+Math.random()+\"\\0\",zSe=\"\\0PERIOD\"+Math.random()+\"\\0\";function I7(e){return parseInt(e,10)==e?parseInt(e,10):e.charCodeAt(0)}function SCt(e){return e.split(\"\\\\\\\\\").join(YSe).split(\"\\\\{\").join(KSe).split(\"\\\\}\").join(C7).split(\"\\\\,\").join(JSe).split(\"\\\\.\").join(zSe)}function DCt(e){return e.split(YSe).join(\"\\\\\").split(KSe).join(\"{\").split(C7).join(\"}\").split(JSe).join(\",\").split(zSe).join(\".\")}function ZSe(e){if(!e)return[\"\"];var t=[],r=VSe(\"{\",\"}\",e);if(!r)return e.split(\",\");var s=r.pre,a=r.body,n=r.post,c=s.split(\",\");c[c.length-1]+=\"{\"+a+\"}\";var f=ZSe(n);return n.length&&(c[c.length-1]+=f.shift(),c.push.apply(c,f)),t.push.apply(t,c),t}function bCt(e){return e?(e.substr(0,2)===\"{}\"&&(e=\"\\\\{\\\\}\"+e.substr(2)),Ob(SCt(e),!0).map(DCt)):[]}function PCt(e){return\"{\"+e+\"}\"}function xCt(e){return/^-?0\\d/.test(e)}function kCt(e,t){return e<=t}function QCt(e,t){return e>=t}function Ob(e,t){var r=[],s=VSe(\"{\",\"}\",e);if(!s)return[e];var a=s.pre,n=s.post.length?Ob(s.post,!1):[\"\"];if(/\\$$/.test(s.pre))for(var c=0;c<n.length;c++){var f=a+\"{\"+s.body+\"}\"+n[c];r.push(f)}else{var p=/^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(s.body),h=/^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(s.body),E=p||h,C=s.body.indexOf(\",\")>=0;if(!E&&!C)return s.post.match(/,.*\\}/)?(e=s.pre+\"{\"+s.body+C7+s.post,Ob(e)):[e];var S;if(E)S=s.body.split(/\\.\\./);else if(S=ZSe(s.body),S.length===1&&(S=Ob(S[0],!1).map(PCt),S.length===1))return n.map(function(Ee){return s.pre+S[0]+Ee});var x;if(E){var I=I7(S[0]),T=I7(S[1]),O=Math.max(S[0].length,S[1].length),U=S.length==3?Math.abs(I7(S[2])):1,Y=kCt,te=T<I;te&&(U*=-1,Y=QCt);var ie=S.some(xCt);x=[];for(var ue=I;Y(ue,T);ue+=U){var ae;if(h)ae=String.fromCharCode(ue),ae===\"\\\\\"&&(ae=\"\");else if(ae=String(ue),ie){var de=O-ae.length;if(de>0){var Ae=new Array(de+1).join(\"0\");ue<0?ae=\"-\"+Ae+ae.slice(1):ae=Ae+ae}}x.push(ae)}}else{x=[];for(var Ce=0;Ce<S.length;Ce++)x.push.apply(x,Ob(S[Ce],!1))}for(var Ce=0;Ce<x.length;Ce++)for(var c=0;c<n.length;c++){var f=a+x[Ce]+n[c];(!t||E||f)&&r.push(f)}}return r}});var eDe=G(IO=>{\"use strict\";Object.defineProperty(IO,\"__esModule\",{value:!0});IO.assertValidPattern=void 0;var RCt=1024*64,TCt=e=>{if(typeof e!=\"string\")throw new TypeError(\"invalid pattern\");if(e.length>RCt)throw new TypeError(\"pattern is too long\")};IO.assertValidPattern=TCt});var rDe=G(CO=>{\"use strict\";Object.defineProperty(CO,\"__esModule\",{value:!0});CO.parseClass=void 0;var FCt={\"[:alnum:]\":[\"\\\\p{L}\\\\p{Nl}\\\\p{Nd}\",!0],\"[:alpha:]\":[\"\\\\p{L}\\\\p{Nl}\",!0],\"[:ascii:]\":[\"\\\\x00-\\\\x7f\",!1],\"[:blank:]\":[\"\\\\p{Zs}\\\\t\",!0],\"[:cntrl:]\":[\"\\\\p{Cc}\",!0],\"[:digit:]\":[\"\\\\p{Nd}\",!0],\"[:graph:]\":[\"\\\\p{Z}\\\\p{C}\",!0,!0],\"[:lower:]\":[\"\\\\p{Ll}\",!0],\"[:print:]\":[\"\\\\p{C}\",!0],\"[:punct:]\":[\"\\\\p{P}\",!0],\"[:space:]\":[\"\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f\",!0],\"[:upper:]\":[\"\\\\p{Lu}\",!0],\"[:word:]\":[\"\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}\",!0],\"[:xdigit:]\":[\"A-Fa-f0-9\",!1]},Lb=e=>e.replace(/[[\\]\\\\-]/g,\"\\\\$&\"),NCt=e=>e.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g,\"\\\\$&\"),tDe=e=>e.join(\"\"),OCt=(e,t)=>{let r=t;if(e.charAt(r)!==\"[\")throw new Error(\"not in a brace expression\");let s=[],a=[],n=r+1,c=!1,f=!1,p=!1,h=!1,E=r,C=\"\";e:for(;n<e.length;){let T=e.charAt(n);if((T===\"!\"||T===\"^\")&&n===r+1){h=!0,n++;continue}if(T===\"]\"&&c&&!p){E=n+1;break}if(c=!0,T===\"\\\\\"&&!p){p=!0,n++;continue}if(T===\"[\"&&!p){for(let[O,[U,Y,te]]of Object.entries(FCt))if(e.startsWith(O,n)){if(C)return[\"$.\",!1,e.length-r,!0];n+=O.length,te?a.push(U):s.push(U),f=f||Y;continue e}}if(p=!1,C){T>C?s.push(Lb(C)+\"-\"+Lb(T)):T===C&&s.push(Lb(T)),C=\"\",n++;continue}if(e.startsWith(\"-]\",n+1)){s.push(Lb(T+\"-\")),n+=2;continue}if(e.startsWith(\"-\",n+1)){C=T,n+=2;continue}s.push(Lb(T)),n++}if(E<n)return[\"\",!1,0,!1];if(!s.length&&!a.length)return[\"$.\",!1,e.length-r,!0];if(a.length===0&&s.length===1&&/^\\\\?.$/.test(s[0])&&!h){let T=s[0].length===2?s[0].slice(-1):s[0];return[NCt(T),!1,E-r,!1]}let S=\"[\"+(h?\"^\":\"\")+tDe(s)+\"]\",x=\"[\"+(h?\"\":\"^\")+tDe(a)+\"]\";return[s.length&&a.length?\"(\"+S+\"|\"+x+\")\":s.length?S:x,f,E-r,!0]};CO.parseClass=OCt});var BO=G(wO=>{\"use strict\";Object.defineProperty(wO,\"__esModule\",{value:!0});wO.unescape=void 0;var LCt=(e,{windowsPathsNoEscape:t=!1}={})=>t?e.replace(/\\[([^\\/\\\\])\\]/g,\"$1\"):e.replace(/((?!\\\\).|^)\\[([^\\/\\\\])\\]/g,\"$1$2\").replace(/\\\\([^\\/])/g,\"$1\");wO.unescape=LCt});var v7=G(DO=>{\"use strict\";Object.defineProperty(DO,\"__esModule\",{value:!0});DO.AST=void 0;var MCt=rDe(),vO=BO(),UCt=new Set([\"!\",\"?\",\"+\",\"*\",\"@\"]),nDe=e=>UCt.has(e),_Ct=\"(?!(?:^|/)\\\\.\\\\.?(?:$|/))\",SO=\"(?!\\\\.)\",HCt=new Set([\"[\",\".\"]),jCt=new Set([\"..\",\".\"]),GCt=new Set(\"().*{}+?[]^$\\\\!\"),qCt=e=>e.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g,\"\\\\$&\"),B7=\"[^/]\",iDe=B7+\"*?\",sDe=B7+\"+?\",w7=class e{type;#e;#t;#s=!1;#r=[];#i;#n;#o;#l=!1;#a;#c;#f=!1;constructor(t,r,s={}){this.type=t,t&&(this.#t=!0),this.#i=r,this.#e=this.#i?this.#i.#e:this,this.#a=this.#e===this?s:this.#e.#a,this.#o=this.#e===this?[]:this.#e.#o,t===\"!\"&&!this.#e.#l&&this.#o.push(this),this.#n=this.#i?this.#i.#r.length:0}get hasMagic(){if(this.#t!==void 0)return this.#t;for(let t of this.#r)if(typeof t!=\"string\"&&(t.type||t.hasMagic))return this.#t=!0;return this.#t}toString(){return this.#c!==void 0?this.#c:this.type?this.#c=this.type+\"(\"+this.#r.map(t=>String(t)).join(\"|\")+\")\":this.#c=this.#r.map(t=>String(t)).join(\"\")}#p(){if(this!==this.#e)throw new Error(\"should only call on root\");if(this.#l)return this;this.toString(),this.#l=!0;let t;for(;t=this.#o.pop();){if(t.type!==\"!\")continue;let r=t,s=r.#i;for(;s;){for(let a=r.#n+1;!s.type&&a<s.#r.length;a++)for(let n of t.#r){if(typeof n==\"string\")throw new Error(\"string part in extglob AST??\");n.copyIn(s.#r[a])}r=s,s=r.#i}}return this}push(...t){for(let r of t)if(r!==\"\"){if(typeof r!=\"string\"&&!(r instanceof e&&r.#i===this))throw new Error(\"invalid part: \"+r);this.#r.push(r)}}toJSON(){let t=this.type===null?this.#r.slice().map(r=>typeof r==\"string\"?r:r.toJSON()):[this.type,...this.#r.map(r=>r.toJSON())];return this.isStart()&&!this.type&&t.unshift([]),this.isEnd()&&(this===this.#e||this.#e.#l&&this.#i?.type===\"!\")&&t.push({}),t}isStart(){if(this.#e===this)return!0;if(!this.#i?.isStart())return!1;if(this.#n===0)return!0;let t=this.#i;for(let r=0;r<this.#n;r++){let s=t.#r[r];if(!(s instanceof e&&s.type===\"!\"))return!1}return!0}isEnd(){if(this.#e===this||this.#i?.type===\"!\")return!0;if(!this.#i?.isEnd())return!1;if(!this.type)return this.#i?.isEnd();let t=this.#i?this.#i.#r.length:0;return this.#n===t-1}copyIn(t){typeof t==\"string\"?this.push(t):this.push(t.clone(this))}clone(t){let r=new e(this.type,t);for(let s of this.#r)r.copyIn(s);return r}static#u(t,r,s,a){let n=!1,c=!1,f=-1,p=!1;if(r.type===null){let x=s,I=\"\";for(;x<t.length;){let T=t.charAt(x++);if(n||T===\"\\\\\"){n=!n,I+=T;continue}if(c){x===f+1?(T===\"^\"||T===\"!\")&&(p=!0):T===\"]\"&&!(x===f+2&&p)&&(c=!1),I+=T;continue}else if(T===\"[\"){c=!0,f=x,p=!1,I+=T;continue}if(!a.noext&&nDe(T)&&t.charAt(x)===\"(\"){r.push(I),I=\"\";let O=new e(T,r);x=e.#u(t,O,x,a),r.push(O);continue}I+=T}return r.push(I),x}let h=s+1,E=new e(null,r),C=[],S=\"\";for(;h<t.length;){let x=t.charAt(h++);if(n||x===\"\\\\\"){n=!n,S+=x;continue}if(c){h===f+1?(x===\"^\"||x===\"!\")&&(p=!0):x===\"]\"&&!(h===f+2&&p)&&(c=!1),S+=x;continue}else if(x===\"[\"){c=!0,f=h,p=!1,S+=x;continue}if(nDe(x)&&t.charAt(h)===\"(\"){E.push(S),S=\"\";let I=new e(x,E);E.push(I),h=e.#u(t,I,h,a);continue}if(x===\"|\"){E.push(S),S=\"\",C.push(E),E=new e(null,r);continue}if(x===\")\")return S===\"\"&&r.#r.length===0&&(r.#f=!0),E.push(S),S=\"\",r.push(...C,E),h;S+=x}return r.type=null,r.#t=void 0,r.#r=[t.substring(s-1)],h}static fromGlob(t,r={}){let s=new e(null,void 0,r);return e.#u(t,s,0,r),s}toMMPattern(){if(this!==this.#e)return this.#e.toMMPattern();let t=this.toString(),[r,s,a,n]=this.toRegExpSource();if(!(a||this.#t||this.#a.nocase&&!this.#a.nocaseMagicOnly&&t.toUpperCase()!==t.toLowerCase()))return s;let f=(this.#a.nocase?\"i\":\"\")+(n?\"u\":\"\");return Object.assign(new RegExp(`^${r}$`,f),{_src:r,_glob:t})}get options(){return this.#a}toRegExpSource(t){let r=t??!!this.#a.dot;if(this.#e===this&&this.#p(),!this.type){let p=this.isStart()&&this.isEnd(),h=this.#r.map(x=>{let[I,T,O,U]=typeof x==\"string\"?e.#h(x,this.#t,p):x.toRegExpSource(t);return this.#t=this.#t||O,this.#s=this.#s||U,I}).join(\"\"),E=\"\";if(this.isStart()&&typeof this.#r[0]==\"string\"&&!(this.#r.length===1&&jCt.has(this.#r[0]))){let I=HCt,T=r&&I.has(h.charAt(0))||h.startsWith(\"\\\\.\")&&I.has(h.charAt(2))||h.startsWith(\"\\\\.\\\\.\")&&I.has(h.charAt(4)),O=!r&&!t&&I.has(h.charAt(0));E=T?_Ct:O?SO:\"\"}let C=\"\";return this.isEnd()&&this.#e.#l&&this.#i?.type===\"!\"&&(C=\"(?:$|\\\\/)\"),[E+h+C,(0,vO.unescape)(h),this.#t=!!this.#t,this.#s]}let s=this.type===\"*\"||this.type===\"+\",a=this.type===\"!\"?\"(?:(?!(?:\":\"(?:\",n=this.#A(r);if(this.isStart()&&this.isEnd()&&!n&&this.type!==\"!\"){let p=this.toString();return this.#r=[p],this.type=null,this.#t=void 0,[p,(0,vO.unescape)(this.toString()),!1,!1]}let c=!s||t||r||!SO?\"\":this.#A(!0);c===n&&(c=\"\"),c&&(n=`(?:${n})(?:${c})*?`);let f=\"\";if(this.type===\"!\"&&this.#f)f=(this.isStart()&&!r?SO:\"\")+sDe;else{let p=this.type===\"!\"?\"))\"+(this.isStart()&&!r&&!t?SO:\"\")+iDe+\")\":this.type===\"@\"?\")\":this.type===\"?\"?\")?\":this.type===\"+\"&&c?\")\":this.type===\"*\"&&c?\")?\":`)${this.type}`;f=a+n+p}return[f,(0,vO.unescape)(n),this.#t=!!this.#t,this.#s]}#A(t){return this.#r.map(r=>{if(typeof r==\"string\")throw new Error(\"string type in extglob ast??\");let[s,a,n,c]=r.toRegExpSource(t);return this.#s=this.#s||c,s}).filter(r=>!(this.isStart()&&this.isEnd())||!!r).join(\"|\")}static#h(t,r,s=!1){let a=!1,n=\"\",c=!1;for(let f=0;f<t.length;f++){let p=t.charAt(f);if(a){a=!1,n+=(GCt.has(p)?\"\\\\\":\"\")+p;continue}if(p===\"\\\\\"){f===t.length-1?n+=\"\\\\\\\\\":a=!0;continue}if(p===\"[\"){let[h,E,C,S]=(0,MCt.parseClass)(t,f);if(C){n+=h,c=c||E,f+=C-1,r=r||S;continue}}if(p===\"*\"){s&&t===\"*\"?n+=sDe:n+=iDe,r=!0;continue}if(p===\"?\"){n+=B7,r=!0;continue}n+=qCt(p)}return[n,(0,vO.unescape)(t),!!r,c]}};DO.AST=w7});var S7=G(bO=>{\"use strict\";Object.defineProperty(bO,\"__esModule\",{value:!0});bO.escape=void 0;var WCt=(e,{windowsPathsNoEscape:t=!1}={})=>t?e.replace(/[?*()[\\]]/g,\"[$&]\"):e.replace(/[?*()[\\]\\\\]/g,\"\\\\$&\");bO.escape=WCt});var ADe=G(pr=>{\"use strict\";var VCt=pr&&pr.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(pr,\"__esModule\",{value:!0});pr.unescape=pr.escape=pr.AST=pr.Minimatch=pr.match=pr.makeRe=pr.braceExpand=pr.defaults=pr.filter=pr.GLOBSTAR=pr.sep=pr.minimatch=void 0;var YCt=VCt($Se()),PO=eDe(),lDe=v7(),KCt=S7(),JCt=BO(),zCt=(e,t,r={})=>((0,PO.assertValidPattern)(t),!r.nocomment&&t.charAt(0)===\"#\"?!1:new fy(t,r).match(e));pr.minimatch=zCt;var ZCt=/^\\*+([^+@!?\\*\\[\\(]*)$/,XCt=e=>t=>!t.startsWith(\".\")&&t.endsWith(e),$Ct=e=>t=>t.endsWith(e),ewt=e=>(e=e.toLowerCase(),t=>!t.startsWith(\".\")&&t.toLowerCase().endsWith(e)),twt=e=>(e=e.toLowerCase(),t=>t.toLowerCase().endsWith(e)),rwt=/^\\*+\\.\\*+$/,nwt=e=>!e.startsWith(\".\")&&e.includes(\".\"),iwt=e=>e!==\".\"&&e!==\"..\"&&e.includes(\".\"),swt=/^\\.\\*+$/,owt=e=>e!==\".\"&&e!==\"..\"&&e.startsWith(\".\"),awt=/^\\*+$/,lwt=e=>e.length!==0&&!e.startsWith(\".\"),cwt=e=>e.length!==0&&e!==\".\"&&e!==\"..\",uwt=/^\\?+([^+@!?\\*\\[\\(]*)?$/,fwt=([e,t=\"\"])=>{let r=cDe([e]);return t?(t=t.toLowerCase(),s=>r(s)&&s.toLowerCase().endsWith(t)):r},Awt=([e,t=\"\"])=>{let r=uDe([e]);return t?(t=t.toLowerCase(),s=>r(s)&&s.toLowerCase().endsWith(t)):r},pwt=([e,t=\"\"])=>{let r=uDe([e]);return t?s=>r(s)&&s.endsWith(t):r},hwt=([e,t=\"\"])=>{let r=cDe([e]);return t?s=>r(s)&&s.endsWith(t):r},cDe=([e])=>{let t=e.length;return r=>r.length===t&&!r.startsWith(\".\")},uDe=([e])=>{let t=e.length;return r=>r.length===t&&r!==\".\"&&r!==\"..\"},fDe=typeof process==\"object\"&&process?typeof process.env==\"object\"&&process.env&&process.env.__MINIMATCH_TESTING_PLATFORM__||process.platform:\"posix\",oDe={win32:{sep:\"\\\\\"},posix:{sep:\"/\"}};pr.sep=fDe===\"win32\"?oDe.win32.sep:oDe.posix.sep;pr.minimatch.sep=pr.sep;pr.GLOBSTAR=Symbol(\"globstar **\");pr.minimatch.GLOBSTAR=pr.GLOBSTAR;var gwt=\"[^/]\",dwt=gwt+\"*?\",mwt=\"(?:(?!(?:\\\\/|^)(?:\\\\.{1,2})($|\\\\/)).)*?\",ywt=\"(?:(?!(?:\\\\/|^)\\\\.).)*?\",Ewt=(e,t={})=>r=>(0,pr.minimatch)(r,e,t);pr.filter=Ewt;pr.minimatch.filter=pr.filter;var $c=(e,t={})=>Object.assign({},e,t),Iwt=e=>{if(!e||typeof e!=\"object\"||!Object.keys(e).length)return pr.minimatch;let t=pr.minimatch;return Object.assign((s,a,n={})=>t(s,a,$c(e,n)),{Minimatch:class extends t.Minimatch{constructor(a,n={}){super(a,$c(e,n))}static defaults(a){return t.defaults($c(e,a)).Minimatch}},AST:class extends t.AST{constructor(a,n,c={}){super(a,n,$c(e,c))}static fromGlob(a,n={}){return t.AST.fromGlob(a,$c(e,n))}},unescape:(s,a={})=>t.unescape(s,$c(e,a)),escape:(s,a={})=>t.escape(s,$c(e,a)),filter:(s,a={})=>t.filter(s,$c(e,a)),defaults:s=>t.defaults($c(e,s)),makeRe:(s,a={})=>t.makeRe(s,$c(e,a)),braceExpand:(s,a={})=>t.braceExpand(s,$c(e,a)),match:(s,a,n={})=>t.match(s,a,$c(e,n)),sep:t.sep,GLOBSTAR:pr.GLOBSTAR})};pr.defaults=Iwt;pr.minimatch.defaults=pr.defaults;var Cwt=(e,t={})=>((0,PO.assertValidPattern)(e),t.nobrace||!/\\{(?:(?!\\{).)*\\}/.test(e)?[e]:(0,YCt.default)(e));pr.braceExpand=Cwt;pr.minimatch.braceExpand=pr.braceExpand;var wwt=(e,t={})=>new fy(e,t).makeRe();pr.makeRe=wwt;pr.minimatch.makeRe=pr.makeRe;var Bwt=(e,t,r={})=>{let s=new fy(t,r);return e=e.filter(a=>s.match(a)),s.options.nonull&&!e.length&&e.push(t),e};pr.match=Bwt;pr.minimatch.match=pr.match;var aDe=/[?*]|[+@!]\\(.*?\\)|\\[|\\]/,vwt=e=>e.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g,\"\\\\$&\"),fy=class{options;set;pattern;windowsPathsNoEscape;nonegate;negate;comment;empty;preserveMultipleSlashes;partial;globSet;globParts;nocase;isWindows;platform;windowsNoMagicRoot;regexp;constructor(t,r={}){(0,PO.assertValidPattern)(t),r=r||{},this.options=r,this.pattern=t,this.platform=r.platform||fDe,this.isWindows=this.platform===\"win32\",this.windowsPathsNoEscape=!!r.windowsPathsNoEscape||r.allowWindowsEscape===!1,this.windowsPathsNoEscape&&(this.pattern=this.pattern.replace(/\\\\/g,\"/\")),this.preserveMultipleSlashes=!!r.preserveMultipleSlashes,this.regexp=null,this.negate=!1,this.nonegate=!!r.nonegate,this.comment=!1,this.empty=!1,this.partial=!!r.partial,this.nocase=!!this.options.nocase,this.windowsNoMagicRoot=r.windowsNoMagicRoot!==void 0?r.windowsNoMagicRoot:!!(this.isWindows&&this.nocase),this.globSet=[],this.globParts=[],this.set=[],this.make()}hasMagic(){if(this.options.magicalBraces&&this.set.length>1)return!0;for(let t of this.set)for(let r of t)if(typeof r!=\"string\")return!0;return!1}debug(...t){}make(){let t=this.pattern,r=this.options;if(!r.nocomment&&t.charAt(0)===\"#\"){this.comment=!0;return}if(!t){this.empty=!0;return}this.parseNegate(),this.globSet=[...new Set(this.braceExpand())],r.debug&&(this.debug=(...n)=>console.error(...n)),this.debug(this.pattern,this.globSet);let s=this.globSet.map(n=>this.slashSplit(n));this.globParts=this.preprocess(s),this.debug(this.pattern,this.globParts);let a=this.globParts.map((n,c,f)=>{if(this.isWindows&&this.windowsNoMagicRoot){let p=n[0]===\"\"&&n[1]===\"\"&&(n[2]===\"?\"||!aDe.test(n[2]))&&!aDe.test(n[3]),h=/^[a-z]:/i.test(n[0]);if(p)return[...n.slice(0,4),...n.slice(4).map(E=>this.parse(E))];if(h)return[n[0],...n.slice(1).map(E=>this.parse(E))]}return n.map(p=>this.parse(p))});if(this.debug(this.pattern,a),this.set=a.filter(n=>n.indexOf(!1)===-1),this.isWindows)for(let n=0;n<this.set.length;n++){let c=this.set[n];c[0]===\"\"&&c[1]===\"\"&&this.globParts[n][2]===\"?\"&&typeof c[3]==\"string\"&&/^[a-z]:$/i.test(c[3])&&(c[2]=\"?\")}this.debug(this.pattern,this.set)}preprocess(t){if(this.options.noglobstar)for(let s=0;s<t.length;s++)for(let a=0;a<t[s].length;a++)t[s][a]===\"**\"&&(t[s][a]=\"*\");let{optimizationLevel:r=1}=this.options;return r>=2?(t=this.firstPhasePreProcess(t),t=this.secondPhasePreProcess(t)):r>=1?t=this.levelOneOptimize(t):t=this.adjascentGlobstarOptimize(t),t}adjascentGlobstarOptimize(t){return t.map(r=>{let s=-1;for(;(s=r.indexOf(\"**\",s+1))!==-1;){let a=s;for(;r[a+1]===\"**\";)a++;a!==s&&r.splice(s,a-s)}return r})}levelOneOptimize(t){return t.map(r=>(r=r.reduce((s,a)=>{let n=s[s.length-1];return a===\"**\"&&n===\"**\"?s:a===\"..\"&&n&&n!==\"..\"&&n!==\".\"&&n!==\"**\"?(s.pop(),s):(s.push(a),s)},[]),r.length===0?[\"\"]:r))}levelTwoFileOptimize(t){Array.isArray(t)||(t=this.slashSplit(t));let r=!1;do{if(r=!1,!this.preserveMultipleSlashes){for(let a=1;a<t.length-1;a++){let n=t[a];a===1&&n===\"\"&&t[0]===\"\"||(n===\".\"||n===\"\")&&(r=!0,t.splice(a,1),a--)}t[0]===\".\"&&t.length===2&&(t[1]===\".\"||t[1]===\"\")&&(r=!0,t.pop())}let s=0;for(;(s=t.indexOf(\"..\",s+1))!==-1;){let a=t[s-1];a&&a!==\".\"&&a!==\"..\"&&a!==\"**\"&&(r=!0,t.splice(s-1,2),s-=2)}}while(r);return t.length===0?[\"\"]:t}firstPhasePreProcess(t){let r=!1;do{r=!1;for(let s of t){let a=-1;for(;(a=s.indexOf(\"**\",a+1))!==-1;){let c=a;for(;s[c+1]===\"**\";)c++;c>a&&s.splice(a+1,c-a);let f=s[a+1],p=s[a+2],h=s[a+3];if(f!==\"..\"||!p||p===\".\"||p===\"..\"||!h||h===\".\"||h===\"..\")continue;r=!0,s.splice(a,1);let E=s.slice(0);E[a]=\"**\",t.push(E),a--}if(!this.preserveMultipleSlashes){for(let c=1;c<s.length-1;c++){let f=s[c];c===1&&f===\"\"&&s[0]===\"\"||(f===\".\"||f===\"\")&&(r=!0,s.splice(c,1),c--)}s[0]===\".\"&&s.length===2&&(s[1]===\".\"||s[1]===\"\")&&(r=!0,s.pop())}let n=0;for(;(n=s.indexOf(\"..\",n+1))!==-1;){let c=s[n-1];if(c&&c!==\".\"&&c!==\"..\"&&c!==\"**\"){r=!0;let p=n===1&&s[n+1]===\"**\"?[\".\"]:[];s.splice(n-1,2,...p),s.length===0&&s.push(\"\"),n-=2}}}}while(r);return t}secondPhasePreProcess(t){for(let r=0;r<t.length-1;r++)for(let s=r+1;s<t.length;s++){let a=this.partsMatch(t[r],t[s],!this.preserveMultipleSlashes);if(a){t[r]=[],t[s]=a;break}}return t.filter(r=>r.length)}partsMatch(t,r,s=!1){let a=0,n=0,c=[],f=\"\";for(;a<t.length&&n<r.length;)if(t[a]===r[n])c.push(f===\"b\"?r[n]:t[a]),a++,n++;else if(s&&t[a]===\"**\"&&r[n]===t[a+1])c.push(t[a]),a++;else if(s&&r[n]===\"**\"&&t[a]===r[n+1])c.push(r[n]),n++;else if(t[a]===\"*\"&&r[n]&&(this.options.dot||!r[n].startsWith(\".\"))&&r[n]!==\"**\"){if(f===\"b\")return!1;f=\"a\",c.push(t[a]),a++,n++}else if(r[n]===\"*\"&&t[a]&&(this.options.dot||!t[a].startsWith(\".\"))&&t[a]!==\"**\"){if(f===\"a\")return!1;f=\"b\",c.push(r[n]),a++,n++}else return!1;return t.length===r.length&&c}parseNegate(){if(this.nonegate)return;let t=this.pattern,r=!1,s=0;for(let a=0;a<t.length&&t.charAt(a)===\"!\";a++)r=!r,s++;s&&(this.pattern=t.slice(s)),this.negate=r}matchOne(t,r,s=!1){let a=this.options;if(this.isWindows){let T=typeof t[0]==\"string\"&&/^[a-z]:$/i.test(t[0]),O=!T&&t[0]===\"\"&&t[1]===\"\"&&t[2]===\"?\"&&/^[a-z]:$/i.test(t[3]),U=typeof r[0]==\"string\"&&/^[a-z]:$/i.test(r[0]),Y=!U&&r[0]===\"\"&&r[1]===\"\"&&r[2]===\"?\"&&typeof r[3]==\"string\"&&/^[a-z]:$/i.test(r[3]),te=O?3:T?0:void 0,ie=Y?3:U?0:void 0;if(typeof te==\"number\"&&typeof ie==\"number\"){let[ue,ae]=[t[te],r[ie]];ue.toLowerCase()===ae.toLowerCase()&&(r[ie]=ue,ie>te?r=r.slice(ie):te>ie&&(t=t.slice(te)))}}let{optimizationLevel:n=1}=this.options;n>=2&&(t=this.levelTwoFileOptimize(t)),this.debug(\"matchOne\",this,{file:t,pattern:r}),this.debug(\"matchOne\",t.length,r.length);for(var c=0,f=0,p=t.length,h=r.length;c<p&&f<h;c++,f++){this.debug(\"matchOne loop\");var E=r[f],C=t[c];if(this.debug(r,E,C),E===!1)return!1;if(E===pr.GLOBSTAR){this.debug(\"GLOBSTAR\",[r,E,C]);var S=c,x=f+1;if(x===h){for(this.debug(\"** at the end\");c<p;c++)if(t[c]===\".\"||t[c]===\"..\"||!a.dot&&t[c].charAt(0)===\".\")return!1;return!0}for(;S<p;){var I=t[S];if(this.debug(`\nglobstar while`,t,S,r,x,I),this.matchOne(t.slice(S),r.slice(x),s))return this.debug(\"globstar found match!\",S,p,I),!0;if(I===\".\"||I===\"..\"||!a.dot&&I.charAt(0)===\".\"){this.debug(\"dot detected!\",t,S,r,x);break}this.debug(\"globstar swallow a segment, and continue\"),S++}return!!(s&&(this.debug(`\n>>> no match, partial?`,t,S,r,x),S===p))}let T;if(typeof E==\"string\"?(T=C===E,this.debug(\"string match\",E,C,T)):(T=E.test(C),this.debug(\"pattern match\",E,C,T)),!T)return!1}if(c===p&&f===h)return!0;if(c===p)return s;if(f===h)return c===p-1&&t[c]===\"\";throw new Error(\"wtf?\")}braceExpand(){return(0,pr.braceExpand)(this.pattern,this.options)}parse(t){(0,PO.assertValidPattern)(t);let r=this.options;if(t===\"**\")return pr.GLOBSTAR;if(t===\"\")return\"\";let s,a=null;(s=t.match(awt))?a=r.dot?cwt:lwt:(s=t.match(ZCt))?a=(r.nocase?r.dot?twt:ewt:r.dot?$Ct:XCt)(s[1]):(s=t.match(uwt))?a=(r.nocase?r.dot?Awt:fwt:r.dot?pwt:hwt)(s):(s=t.match(rwt))?a=r.dot?iwt:nwt:(s=t.match(swt))&&(a=owt);let n=lDe.AST.fromGlob(t,this.options).toMMPattern();return a&&typeof n==\"object\"&&Reflect.defineProperty(n,\"test\",{value:a}),n}makeRe(){if(this.regexp||this.regexp===!1)return this.regexp;let t=this.set;if(!t.length)return this.regexp=!1,this.regexp;let r=this.options,s=r.noglobstar?dwt:r.dot?mwt:ywt,a=new Set(r.nocase?[\"i\"]:[]),n=t.map(p=>{let h=p.map(E=>{if(E instanceof RegExp)for(let C of E.flags.split(\"\"))a.add(C);return typeof E==\"string\"?vwt(E):E===pr.GLOBSTAR?pr.GLOBSTAR:E._src});return h.forEach((E,C)=>{let S=h[C+1],x=h[C-1];E!==pr.GLOBSTAR||x===pr.GLOBSTAR||(x===void 0?S!==void 0&&S!==pr.GLOBSTAR?h[C+1]=\"(?:\\\\/|\"+s+\"\\\\/)?\"+S:h[C]=s:S===void 0?h[C-1]=x+\"(?:\\\\/|\"+s+\")?\":S!==pr.GLOBSTAR&&(h[C-1]=x+\"(?:\\\\/|\\\\/\"+s+\"\\\\/)\"+S,h[C+1]=pr.GLOBSTAR))}),h.filter(E=>E!==pr.GLOBSTAR).join(\"/\")}).join(\"|\"),[c,f]=t.length>1?[\"(?:\",\")\"]:[\"\",\"\"];n=\"^\"+c+n+f+\"$\",this.negate&&(n=\"^(?!\"+n+\").+$\");try{this.regexp=new RegExp(n,[...a].join(\"\"))}catch{this.regexp=!1}return this.regexp}slashSplit(t){return this.preserveMultipleSlashes?t.split(\"/\"):this.isWindows&&/^\\/\\/[^\\/]+/.test(t)?[\"\",...t.split(/\\/+/)]:t.split(/\\/+/)}match(t,r=this.partial){if(this.debug(\"match\",t,this.pattern),this.comment)return!1;if(this.empty)return t===\"\";if(t===\"/\"&&r)return!0;let s=this.options;this.isWindows&&(t=t.split(\"\\\\\").join(\"/\"));let a=this.slashSplit(t);this.debug(this.pattern,\"split\",a);let n=this.set;this.debug(this.pattern,\"set\",n);let c=a[a.length-1];if(!c)for(let f=a.length-2;!c&&f>=0;f--)c=a[f];for(let f=0;f<n.length;f++){let p=n[f],h=a;if(s.matchBase&&p.length===1&&(h=[c]),this.matchOne(h,p,r))return s.flipNegate?!0:!this.negate}return s.flipNegate?!1:this.negate}static defaults(t){return pr.minimatch.defaults(t).Minimatch}};pr.Minimatch=fy;var Swt=v7();Object.defineProperty(pr,\"AST\",{enumerable:!0,get:function(){return Swt.AST}});var Dwt=S7();Object.defineProperty(pr,\"escape\",{enumerable:!0,get:function(){return Dwt.escape}});var bwt=BO();Object.defineProperty(pr,\"unescape\",{enumerable:!0,get:function(){return bwt.unescape}});pr.minimatch.AST=lDe.AST;pr.minimatch.Minimatch=fy;pr.minimatch.escape=KCt.escape;pr.minimatch.unescape=JCt.unescape});var P7=G(eu=>{\"use strict\";var pDe=eu&&eu.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(eu,\"__esModule\",{value:!0});eu.SuccinctRoles=eu.DelegatedRole=eu.Role=eu.TOP_LEVEL_ROLE_NAMES=void 0;var hDe=pDe(Ie(\"crypto\")),Pwt=ADe(),xO=pDe(Ie(\"util\")),kO=xA(),Ay=pf();eu.TOP_LEVEL_ROLE_NAMES=[\"root\",\"targets\",\"snapshot\",\"timestamp\"];var Mb=class e{constructor(t){let{keyIDs:r,threshold:s,unrecognizedFields:a}=t;if(xwt(r))throw new kO.ValueError(\"duplicate key IDs found\");if(s<1)throw new kO.ValueError(\"threshold must be at least 1\");this.keyIDs=r,this.threshold=s,this.unrecognizedFields=a||{}}equals(t){return t instanceof e?this.threshold===t.threshold&&xO.default.isDeepStrictEqual(this.keyIDs,t.keyIDs)&&xO.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields):!1}toJSON(){return{keyids:this.keyIDs,threshold:this.threshold,...this.unrecognizedFields}}static fromJSON(t){let{keyids:r,threshold:s,...a}=t;if(!Ay.guard.isStringArray(r))throw new TypeError(\"keyids must be an array\");if(typeof s!=\"number\")throw new TypeError(\"threshold must be a number\");return new e({keyIDs:r,threshold:s,unrecognizedFields:a})}};eu.Role=Mb;function xwt(e){return new Set(e).size!==e.length}var D7=class e extends Mb{constructor(t){super(t);let{name:r,terminating:s,paths:a,pathHashPrefixes:n}=t;if(this.name=r,this.terminating=s,t.paths&&t.pathHashPrefixes)throw new kO.ValueError(\"paths and pathHashPrefixes are mutually exclusive\");this.paths=a,this.pathHashPrefixes=n}equals(t){return t instanceof e?super.equals(t)&&this.name===t.name&&this.terminating===t.terminating&&xO.default.isDeepStrictEqual(this.paths,t.paths)&&xO.default.isDeepStrictEqual(this.pathHashPrefixes,t.pathHashPrefixes):!1}isDelegatedPath(t){if(this.paths)return this.paths.some(r=>Qwt(t,r));if(this.pathHashPrefixes){let s=hDe.default.createHash(\"sha256\").update(t).digest(\"hex\");return this.pathHashPrefixes.some(a=>s.startsWith(a))}return!1}toJSON(){let t={...super.toJSON(),name:this.name,terminating:this.terminating};return this.paths&&(t.paths=this.paths),this.pathHashPrefixes&&(t.path_hash_prefixes=this.pathHashPrefixes),t}static fromJSON(t){let{keyids:r,threshold:s,name:a,terminating:n,paths:c,path_hash_prefixes:f,...p}=t;if(!Ay.guard.isStringArray(r))throw new TypeError(\"keyids must be an array of strings\");if(typeof s!=\"number\")throw new TypeError(\"threshold must be a number\");if(typeof a!=\"string\")throw new TypeError(\"name must be a string\");if(typeof n!=\"boolean\")throw new TypeError(\"terminating must be a boolean\");if(Ay.guard.isDefined(c)&&!Ay.guard.isStringArray(c))throw new TypeError(\"paths must be an array of strings\");if(Ay.guard.isDefined(f)&&!Ay.guard.isStringArray(f))throw new TypeError(\"path_hash_prefixes must be an array of strings\");return new e({keyIDs:r,threshold:s,name:a,terminating:n,paths:c,pathHashPrefixes:f,unrecognizedFields:p})}};eu.DelegatedRole=D7;var kwt=(e,t)=>e.map((r,s)=>[r,t[s]]);function Qwt(e,t){let r=e.split(\"/\"),s=t.split(\"/\");return s.length!=r.length?!1:kwt(r,s).every(([a,n])=>(0,Pwt.minimatch)(a,n))}var b7=class e extends Mb{constructor(t){super(t);let{bitLength:r,namePrefix:s}=t;if(r<=0||r>32)throw new kO.ValueError(\"bitLength must be between 1 and 32\");this.bitLength=r,this.namePrefix=s,this.numberOfBins=Math.pow(2,r),this.suffixLen=(this.numberOfBins-1).toString(16).length}equals(t){return t instanceof e?super.equals(t)&&this.bitLength===t.bitLength&&this.namePrefix===t.namePrefix:!1}getRoleForTarget(t){let a=hDe.default.createHash(\"sha256\").update(t).digest().subarray(0,4),n=32-this.bitLength,f=(a.readUInt32BE()>>>n).toString(16).padStart(this.suffixLen,\"0\");return`${this.namePrefix}-${f}`}*getRoles(){for(let t=0;t<this.numberOfBins;t++){let r=t.toString(16).padStart(this.suffixLen,\"0\");yield`${this.namePrefix}-${r}`}}isDelegatedRole(t){let r=this.namePrefix+\"-\";if(!t.startsWith(r))return!1;let s=t.slice(r.length,t.length);if(s.length!=this.suffixLen||!s.match(/^[0-9a-fA-F]+$/))return!1;let a=parseInt(s,16);return 0<=a&&a<this.numberOfBins}toJSON(){return{...super.toJSON(),bit_length:this.bitLength,name_prefix:this.namePrefix}}static fromJSON(t){let{keyids:r,threshold:s,bit_length:a,name_prefix:n,...c}=t;if(!Ay.guard.isStringArray(r))throw new TypeError(\"keyids must be an array of strings\");if(typeof s!=\"number\")throw new TypeError(\"threshold must be a number\");if(typeof a!=\"number\")throw new TypeError(\"bit_length must be a number\");if(typeof n!=\"string\")throw new TypeError(\"name_prefix must be a string\");return new e({keyIDs:r,threshold:s,bitLength:a,namePrefix:n,unrecognizedFields:c})}};eu.SuccinctRoles=b7});var Q7=G($w=>{\"use strict\";var Rwt=$w&&$w.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty($w,\"__esModule\",{value:!0});$w.Root=void 0;var gDe=Rwt(Ie(\"util\")),x7=uy(),dDe=xA(),Twt=EO(),QO=P7(),RO=pf(),k7=class e extends x7.Signed{constructor(t){if(super(t),this.type=x7.MetadataKind.Root,this.keys=t.keys||{},this.consistentSnapshot=t.consistentSnapshot??!0,!t.roles)this.roles=QO.TOP_LEVEL_ROLE_NAMES.reduce((r,s)=>({...r,[s]:new QO.Role({keyIDs:[],threshold:1})}),{});else{let r=new Set(Object.keys(t.roles));if(!QO.TOP_LEVEL_ROLE_NAMES.every(s=>r.has(s)))throw new dDe.ValueError(\"missing top-level role\");this.roles=t.roles}}addKey(t,r){if(!this.roles[r])throw new dDe.ValueError(`role ${r} does not exist`);this.roles[r].keyIDs.includes(t.keyID)||this.roles[r].keyIDs.push(t.keyID),this.keys[t.keyID]=t}equals(t){return t instanceof e?super.equals(t)&&this.consistentSnapshot===t.consistentSnapshot&&gDe.default.isDeepStrictEqual(this.keys,t.keys)&&gDe.default.isDeepStrictEqual(this.roles,t.roles):!1}toJSON(){return{_type:this.type,spec_version:this.specVersion,version:this.version,expires:this.expires,keys:Fwt(this.keys),roles:Nwt(this.roles),consistent_snapshot:this.consistentSnapshot,...this.unrecognizedFields}}static fromJSON(t){let{unrecognizedFields:r,...s}=x7.Signed.commonFieldsFromJSON(t),{keys:a,roles:n,consistent_snapshot:c,...f}=r;if(typeof c!=\"boolean\")throw new TypeError(\"consistent_snapshot must be a boolean\");return new e({...s,keys:Owt(a),roles:Lwt(n),consistentSnapshot:c,unrecognizedFields:f})}};$w.Root=k7;function Fwt(e){return Object.entries(e).reduce((t,[r,s])=>({...t,[r]:s.toJSON()}),{})}function Nwt(e){return Object.entries(e).reduce((t,[r,s])=>({...t,[r]:s.toJSON()}),{})}function Owt(e){let t;if(RO.guard.isDefined(e)){if(!RO.guard.isObjectRecord(e))throw new TypeError(\"keys must be an object\");t=Object.entries(e).reduce((r,[s,a])=>({...r,[s]:Twt.Key.fromJSON(s,a)}),{})}return t}function Lwt(e){let t;if(RO.guard.isDefined(e)){if(!RO.guard.isObjectRecord(e))throw new TypeError(\"roles must be an object\");t=Object.entries(e).reduce((r,[s,a])=>({...r,[s]:QO.Role.fromJSON(a)}),{})}return t}});var T7=G(TO=>{\"use strict\";Object.defineProperty(TO,\"__esModule\",{value:!0});TO.Signature=void 0;var R7=class e{constructor(t){let{keyID:r,sig:s}=t;this.keyID=r,this.sig=s}toJSON(){return{keyid:this.keyID,sig:this.sig}}static fromJSON(t){let{keyid:r,sig:s}=t;if(typeof r!=\"string\")throw new TypeError(\"keyid must be a string\");if(typeof s!=\"string\")throw new TypeError(\"sig must be a string\");return new e({keyID:r,sig:s})}};TO.Signature=R7});var O7=G(e1=>{\"use strict\";var Mwt=e1&&e1.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(e1,\"__esModule\",{value:!0});e1.Snapshot=void 0;var Uwt=Mwt(Ie(\"util\")),F7=uy(),yDe=Rb(),mDe=pf(),N7=class e extends F7.Signed{constructor(t){super(t),this.type=F7.MetadataKind.Snapshot,this.meta=t.meta||{\"targets.json\":new yDe.MetaFile({version:1})}}equals(t){return t instanceof e?super.equals(t)&&Uwt.default.isDeepStrictEqual(this.meta,t.meta):!1}toJSON(){return{_type:this.type,meta:_wt(this.meta),spec_version:this.specVersion,version:this.version,expires:this.expires,...this.unrecognizedFields}}static fromJSON(t){let{unrecognizedFields:r,...s}=F7.Signed.commonFieldsFromJSON(t),{meta:a,...n}=r;return new e({...s,meta:Hwt(a),unrecognizedFields:n})}};e1.Snapshot=N7;function _wt(e){return Object.entries(e).reduce((t,[r,s])=>({...t,[r]:s.toJSON()}),{})}function Hwt(e){let t;if(mDe.guard.isDefined(e))if(mDe.guard.isObjectRecord(e))t=Object.entries(e).reduce((r,[s,a])=>({...r,[s]:yDe.MetaFile.fromJSON(a)}),{});else throw new TypeError(\"meta field is malformed\");return t}});var EDe=G(t1=>{\"use strict\";var jwt=t1&&t1.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t1,\"__esModule\",{value:!0});t1.Delegations=void 0;var FO=jwt(Ie(\"util\")),Gwt=xA(),qwt=EO(),L7=P7(),NO=pf(),M7=class e{constructor(t){if(this.keys=t.keys,this.unrecognizedFields=t.unrecognizedFields||{},t.roles&&Object.keys(t.roles).some(r=>L7.TOP_LEVEL_ROLE_NAMES.includes(r)))throw new Gwt.ValueError(\"Delegated role name conflicts with top-level role name\");this.succinctRoles=t.succinctRoles,this.roles=t.roles}equals(t){return t instanceof e?FO.default.isDeepStrictEqual(this.keys,t.keys)&&FO.default.isDeepStrictEqual(this.roles,t.roles)&&FO.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields)&&FO.default.isDeepStrictEqual(this.succinctRoles,t.succinctRoles):!1}*rolesForTarget(t){if(this.roles)for(let r of Object.values(this.roles))r.isDelegatedPath(t)&&(yield{role:r.name,terminating:r.terminating});else this.succinctRoles&&(yield{role:this.succinctRoles.getRoleForTarget(t),terminating:!0})}toJSON(){let t={keys:Wwt(this.keys),...this.unrecognizedFields};return this.roles?t.roles=Vwt(this.roles):this.succinctRoles&&(t.succinct_roles=this.succinctRoles.toJSON()),t}static fromJSON(t){let{keys:r,roles:s,succinct_roles:a,...n}=t,c;return NO.guard.isObject(a)&&(c=L7.SuccinctRoles.fromJSON(a)),new e({keys:Ywt(r),roles:Kwt(s),unrecognizedFields:n,succinctRoles:c})}};t1.Delegations=M7;function Wwt(e){return Object.entries(e).reduce((t,[r,s])=>({...t,[r]:s.toJSON()}),{})}function Vwt(e){return Object.values(e).map(t=>t.toJSON())}function Ywt(e){if(!NO.guard.isObjectRecord(e))throw new TypeError(\"keys is malformed\");return Object.entries(e).reduce((t,[r,s])=>({...t,[r]:qwt.Key.fromJSON(r,s)}),{})}function Kwt(e){let t;if(NO.guard.isDefined(e)){if(!NO.guard.isObjectArray(e))throw new TypeError(\"roles is malformed\");t=e.reduce((r,s)=>{let a=L7.DelegatedRole.fromJSON(s);return{...r,[a.name]:a}},{})}return t}});var H7=G(r1=>{\"use strict\";var Jwt=r1&&r1.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(r1,\"__esModule\",{value:!0});r1.Targets=void 0;var IDe=Jwt(Ie(\"util\")),U7=uy(),zwt=EDe(),Zwt=Rb(),OO=pf(),_7=class e extends U7.Signed{constructor(t){super(t),this.type=U7.MetadataKind.Targets,this.targets=t.targets||{},this.delegations=t.delegations}addTarget(t){this.targets[t.path]=t}equals(t){return t instanceof e?super.equals(t)&&IDe.default.isDeepStrictEqual(this.targets,t.targets)&&IDe.default.isDeepStrictEqual(this.delegations,t.delegations):!1}toJSON(){let t={_type:this.type,spec_version:this.specVersion,version:this.version,expires:this.expires,targets:Xwt(this.targets),...this.unrecognizedFields};return this.delegations&&(t.delegations=this.delegations.toJSON()),t}static fromJSON(t){let{unrecognizedFields:r,...s}=U7.Signed.commonFieldsFromJSON(t),{targets:a,delegations:n,...c}=r;return new e({...s,targets:$wt(a),delegations:e1t(n),unrecognizedFields:c})}};r1.Targets=_7;function Xwt(e){return Object.entries(e).reduce((t,[r,s])=>({...t,[r]:s.toJSON()}),{})}function $wt(e){let t;if(OO.guard.isDefined(e))if(OO.guard.isObjectRecord(e))t=Object.entries(e).reduce((r,[s,a])=>({...r,[s]:Zwt.TargetFile.fromJSON(s,a)}),{});else throw new TypeError(\"targets must be an object\");return t}function e1t(e){let t;if(OO.guard.isDefined(e))if(OO.guard.isObject(e))t=zwt.Delegations.fromJSON(e);else throw new TypeError(\"delegations must be an object\");return t}});var W7=G(LO=>{\"use strict\";Object.defineProperty(LO,\"__esModule\",{value:!0});LO.Timestamp=void 0;var j7=uy(),CDe=Rb(),G7=pf(),q7=class e extends j7.Signed{constructor(t){super(t),this.type=j7.MetadataKind.Timestamp,this.snapshotMeta=t.snapshotMeta||new CDe.MetaFile({version:1})}equals(t){return t instanceof e?super.equals(t)&&this.snapshotMeta.equals(t.snapshotMeta):!1}toJSON(){return{_type:this.type,spec_version:this.specVersion,version:this.version,expires:this.expires,meta:{\"snapshot.json\":this.snapshotMeta.toJSON()},...this.unrecognizedFields}}static fromJSON(t){let{unrecognizedFields:r,...s}=j7.Signed.commonFieldsFromJSON(t),{meta:a,...n}=r;return new e({...s,snapshotMeta:t1t(a),unrecognizedFields:n})}};LO.Timestamp=q7;function t1t(e){let t;if(G7.guard.isDefined(e)){let r=e[\"snapshot.json\"];if(!G7.guard.isDefined(r)||!G7.guard.isObject(r))throw new TypeError(\"missing snapshot.json in meta\");t=CDe.MetaFile.fromJSON(r)}return t}});var BDe=G(i1=>{\"use strict\";var r1t=i1&&i1.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(i1,\"__esModule\",{value:!0});i1.Metadata=void 0;var n1t=u7(),wDe=r1t(Ie(\"util\")),n1=uy(),Ub=xA(),i1t=Q7(),s1t=T7(),o1t=O7(),a1t=H7(),l1t=W7(),V7=pf(),Y7=class e{constructor(t,r,s){this.signed=t,this.signatures=r||{},this.unrecognizedFields=s||{}}sign(t,r=!0){let s=Buffer.from((0,n1t.canonicalize)(this.signed.toJSON())),a=t(s);r||(this.signatures={}),this.signatures[a.keyID]=a}verifyDelegate(t,r){let s,a={};switch(this.signed.type){case n1.MetadataKind.Root:a=this.signed.keys,s=this.signed.roles[t];break;case n1.MetadataKind.Targets:if(!this.signed.delegations)throw new Ub.ValueError(`No delegations found for ${t}`);a=this.signed.delegations.keys,this.signed.delegations.roles?s=this.signed.delegations.roles[t]:this.signed.delegations.succinctRoles&&this.signed.delegations.succinctRoles.isDelegatedRole(t)&&(s=this.signed.delegations.succinctRoles);break;default:throw new TypeError(\"invalid metadata type\")}if(!s)throw new Ub.ValueError(`no delegation found for ${t}`);let n=new Set;if(s.keyIDs.forEach(c=>{let f=a[c];if(f)try{f.verifySignature(r),n.add(f.keyID)}catch{}}),n.size<s.threshold)throw new Ub.UnsignedMetadataError(`${t} was signed by ${n.size}/${s.threshold} keys`)}equals(t){return t instanceof e?this.signed.equals(t.signed)&&wDe.default.isDeepStrictEqual(this.signatures,t.signatures)&&wDe.default.isDeepStrictEqual(this.unrecognizedFields,t.unrecognizedFields):!1}toJSON(){return{signatures:Object.values(this.signatures).map(r=>r.toJSON()),signed:this.signed.toJSON(),...this.unrecognizedFields}}static fromJSON(t,r){let{signed:s,signatures:a,...n}=r;if(!V7.guard.isDefined(s)||!V7.guard.isObject(s))throw new TypeError(\"signed is not defined\");if(t!==s._type)throw new Ub.ValueError(`expected '${t}', got ${s._type}`);if(!V7.guard.isObjectArray(a))throw new TypeError(\"signatures is not an array\");let c;switch(t){case n1.MetadataKind.Root:c=i1t.Root.fromJSON(s);break;case n1.MetadataKind.Timestamp:c=l1t.Timestamp.fromJSON(s);break;case n1.MetadataKind.Snapshot:c=o1t.Snapshot.fromJSON(s);break;case n1.MetadataKind.Targets:c=a1t.Targets.fromJSON(s);break;default:throw new TypeError(\"invalid metadata type\")}let f={};return a.forEach(p=>{let h=s1t.Signature.fromJSON(p);if(f[h.keyID])throw new Ub.ValueError(`multiple signatures found for keyid: ${h.keyID}`);f[h.keyID]=h}),new e(c,f,n)}};i1.Metadata=Y7});var MO=G(Fi=>{\"use strict\";Object.defineProperty(Fi,\"__esModule\",{value:!0});Fi.Timestamp=Fi.Targets=Fi.Snapshot=Fi.Signature=Fi.Root=Fi.Metadata=Fi.Key=Fi.TargetFile=Fi.MetaFile=Fi.ValueError=Fi.MetadataKind=void 0;var c1t=uy();Object.defineProperty(Fi,\"MetadataKind\",{enumerable:!0,get:function(){return c1t.MetadataKind}});var u1t=xA();Object.defineProperty(Fi,\"ValueError\",{enumerable:!0,get:function(){return u1t.ValueError}});var vDe=Rb();Object.defineProperty(Fi,\"MetaFile\",{enumerable:!0,get:function(){return vDe.MetaFile}});Object.defineProperty(Fi,\"TargetFile\",{enumerable:!0,get:function(){return vDe.TargetFile}});var f1t=EO();Object.defineProperty(Fi,\"Key\",{enumerable:!0,get:function(){return f1t.Key}});var A1t=BDe();Object.defineProperty(Fi,\"Metadata\",{enumerable:!0,get:function(){return A1t.Metadata}});var p1t=Q7();Object.defineProperty(Fi,\"Root\",{enumerable:!0,get:function(){return p1t.Root}});var h1t=T7();Object.defineProperty(Fi,\"Signature\",{enumerable:!0,get:function(){return h1t.Signature}});var g1t=O7();Object.defineProperty(Fi,\"Snapshot\",{enumerable:!0,get:function(){return g1t.Snapshot}});var d1t=H7();Object.defineProperty(Fi,\"Targets\",{enumerable:!0,get:function(){return d1t.Targets}});var m1t=W7();Object.defineProperty(Fi,\"Timestamp\",{enumerable:!0,get:function(){return m1t.Timestamp}})});var DDe=G((xtr,SDe)=>{var s1=1e3,o1=s1*60,a1=o1*60,py=a1*24,y1t=py*7,E1t=py*365.25;SDe.exports=function(e,t){t=t||{};var r=typeof e;if(r===\"string\"&&e.length>0)return I1t(e);if(r===\"number\"&&isFinite(e))return t.long?w1t(e):C1t(e);throw new Error(\"val is not a non-empty string or a valid number. val=\"+JSON.stringify(e))};function I1t(e){if(e=String(e),!(e.length>100)){var t=/^(-?(?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(t){var r=parseFloat(t[1]),s=(t[2]||\"ms\").toLowerCase();switch(s){case\"years\":case\"year\":case\"yrs\":case\"yr\":case\"y\":return r*E1t;case\"weeks\":case\"week\":case\"w\":return r*y1t;case\"days\":case\"day\":case\"d\":return r*py;case\"hours\":case\"hour\":case\"hrs\":case\"hr\":case\"h\":return r*a1;case\"minutes\":case\"minute\":case\"mins\":case\"min\":case\"m\":return r*o1;case\"seconds\":case\"second\":case\"secs\":case\"sec\":case\"s\":return r*s1;case\"milliseconds\":case\"millisecond\":case\"msecs\":case\"msec\":case\"ms\":return r;default:return}}}}function C1t(e){var t=Math.abs(e);return t>=py?Math.round(e/py)+\"d\":t>=a1?Math.round(e/a1)+\"h\":t>=o1?Math.round(e/o1)+\"m\":t>=s1?Math.round(e/s1)+\"s\":e+\"ms\"}function w1t(e){var t=Math.abs(e);return t>=py?UO(e,t,py,\"day\"):t>=a1?UO(e,t,a1,\"hour\"):t>=o1?UO(e,t,o1,\"minute\"):t>=s1?UO(e,t,s1,\"second\"):e+\" ms\"}function UO(e,t,r,s){var a=t>=r*1.5;return Math.round(e/r)+\" \"+s+(a?\"s\":\"\")}});var K7=G((ktr,bDe)=>{function B1t(e){r.debug=r,r.default=r,r.coerce=p,r.disable=c,r.enable=a,r.enabled=f,r.humanize=DDe(),r.destroy=h,Object.keys(e).forEach(E=>{r[E]=e[E]}),r.names=[],r.skips=[],r.formatters={};function t(E){let C=0;for(let S=0;S<E.length;S++)C=(C<<5)-C+E.charCodeAt(S),C|=0;return r.colors[Math.abs(C)%r.colors.length]}r.selectColor=t;function r(E){let C,S=null,x,I;function T(...O){if(!T.enabled)return;let U=T,Y=Number(new Date),te=Y-(C||Y);U.diff=te,U.prev=C,U.curr=Y,C=Y,O[0]=r.coerce(O[0]),typeof O[0]!=\"string\"&&O.unshift(\"%O\");let ie=0;O[0]=O[0].replace(/%([a-zA-Z%])/g,(ae,de)=>{if(ae===\"%%\")return\"%\";ie++;let Ae=r.formatters[de];if(typeof Ae==\"function\"){let Ce=O[ie];ae=Ae.call(U,Ce),O.splice(ie,1),ie--}return ae}),r.formatArgs.call(U,O),(U.log||r.log).apply(U,O)}return T.namespace=E,T.useColors=r.useColors(),T.color=r.selectColor(E),T.extend=s,T.destroy=r.destroy,Object.defineProperty(T,\"enabled\",{enumerable:!0,configurable:!1,get:()=>S!==null?S:(x!==r.namespaces&&(x=r.namespaces,I=r.enabled(E)),I),set:O=>{S=O}}),typeof r.init==\"function\"&&r.init(T),T}function s(E,C){let S=r(this.namespace+(typeof C>\"u\"?\":\":C)+E);return S.log=this.log,S}function a(E){r.save(E),r.namespaces=E,r.names=[],r.skips=[];let C=(typeof E==\"string\"?E:\"\").trim().replace(\" \",\",\").split(\",\").filter(Boolean);for(let S of C)S[0]===\"-\"?r.skips.push(S.slice(1)):r.names.push(S)}function n(E,C){let S=0,x=0,I=-1,T=0;for(;S<E.length;)if(x<C.length&&(C[x]===E[S]||C[x]===\"*\"))C[x]===\"*\"?(I=x,T=S,x++):(S++,x++);else if(I!==-1)x=I+1,T++,S=T;else return!1;for(;x<C.length&&C[x]===\"*\";)x++;return x===C.length}function c(){let E=[...r.names,...r.skips.map(C=>\"-\"+C)].join(\",\");return r.enable(\"\"),E}function f(E){for(let C of r.skips)if(n(E,C))return!1;for(let C of r.names)if(n(E,C))return!0;return!1}function p(E){return E instanceof Error?E.stack||E.message:E}function h(){console.warn(\"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.\")}return r.enable(r.load()),r}bDe.exports=B1t});var PDe=G((oc,_O)=>{oc.formatArgs=S1t;oc.save=D1t;oc.load=b1t;oc.useColors=v1t;oc.storage=P1t();oc.destroy=(()=>{let e=!1;return()=>{e||(e=!0,console.warn(\"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.\"))}})();oc.colors=[\"#0000CC\",\"#0000FF\",\"#0033CC\",\"#0033FF\",\"#0066CC\",\"#0066FF\",\"#0099CC\",\"#0099FF\",\"#00CC00\",\"#00CC33\",\"#00CC66\",\"#00CC99\",\"#00CCCC\",\"#00CCFF\",\"#3300CC\",\"#3300FF\",\"#3333CC\",\"#3333FF\",\"#3366CC\",\"#3366FF\",\"#3399CC\",\"#3399FF\",\"#33CC00\",\"#33CC33\",\"#33CC66\",\"#33CC99\",\"#33CCCC\",\"#33CCFF\",\"#6600CC\",\"#6600FF\",\"#6633CC\",\"#6633FF\",\"#66CC00\",\"#66CC33\",\"#9900CC\",\"#9900FF\",\"#9933CC\",\"#9933FF\",\"#99CC00\",\"#99CC33\",\"#CC0000\",\"#CC0033\",\"#CC0066\",\"#CC0099\",\"#CC00CC\",\"#CC00FF\",\"#CC3300\",\"#CC3333\",\"#CC3366\",\"#CC3399\",\"#CC33CC\",\"#CC33FF\",\"#CC6600\",\"#CC6633\",\"#CC9900\",\"#CC9933\",\"#CCCC00\",\"#CCCC33\",\"#FF0000\",\"#FF0033\",\"#FF0066\",\"#FF0099\",\"#FF00CC\",\"#FF00FF\",\"#FF3300\",\"#FF3333\",\"#FF3366\",\"#FF3399\",\"#FF33CC\",\"#FF33FF\",\"#FF6600\",\"#FF6633\",\"#FF9900\",\"#FF9933\",\"#FFCC00\",\"#FFCC33\"];function v1t(){if(typeof window<\"u\"&&window.process&&(window.process.type===\"renderer\"||window.process.__nwjs))return!0;if(typeof navigator<\"u\"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\\/(\\d+)/))return!1;let e;return typeof document<\"u\"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<\"u\"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<\"u\"&&navigator.userAgent&&(e=navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/))&&parseInt(e[1],10)>=31||typeof navigator<\"u\"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/)}function S1t(e){if(e[0]=(this.useColors?\"%c\":\"\")+this.namespace+(this.useColors?\" %c\":\" \")+e[0]+(this.useColors?\"%c \":\" \")+\"+\"+_O.exports.humanize(this.diff),!this.useColors)return;let t=\"color: \"+this.color;e.splice(1,0,t,\"color: inherit\");let r=0,s=0;e[0].replace(/%[a-zA-Z%]/g,a=>{a!==\"%%\"&&(r++,a===\"%c\"&&(s=r))}),e.splice(s,0,t)}oc.log=console.debug||console.log||(()=>{});function D1t(e){try{e?oc.storage.setItem(\"debug\",e):oc.storage.removeItem(\"debug\")}catch{}}function b1t(){let e;try{e=oc.storage.getItem(\"debug\")}catch{}return!e&&typeof process<\"u\"&&\"env\"in process&&(e=process.env.DEBUG),e}function P1t(){try{return localStorage}catch{}}_O.exports=K7()(oc);var{formatters:x1t}=_O.exports;x1t.j=function(e){try{return JSON.stringify(e)}catch(t){return\"[UnexpectedJSONParseError]: \"+t.message}}});var kDe=G((io,jO)=>{var k1t=Ie(\"tty\"),HO=Ie(\"util\");io.init=L1t;io.log=F1t;io.formatArgs=R1t;io.save=N1t;io.load=O1t;io.useColors=Q1t;io.destroy=HO.deprecate(()=>{},\"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.\");io.colors=[6,2,3,4,5,1];try{let e=Ie(\"supports-color\");e&&(e.stderr||e).level>=2&&(io.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}io.inspectOpts=Object.keys(process.env).filter(e=>/^debug_/i.test(e)).reduce((e,t)=>{let r=t.substring(6).toLowerCase().replace(/_([a-z])/g,(a,n)=>n.toUpperCase()),s=process.env[t];return/^(yes|on|true|enabled)$/i.test(s)?s=!0:/^(no|off|false|disabled)$/i.test(s)?s=!1:s===\"null\"?s=null:s=Number(s),e[r]=s,e},{});function Q1t(){return\"colors\"in io.inspectOpts?!!io.inspectOpts.colors:k1t.isatty(process.stderr.fd)}function R1t(e){let{namespace:t,useColors:r}=this;if(r){let s=this.color,a=\"\\x1B[3\"+(s<8?s:\"8;5;\"+s),n=`  ${a};1m${t} \\x1B[0m`;e[0]=n+e[0].split(`\n`).join(`\n`+n),e.push(a+\"m+\"+jO.exports.humanize(this.diff)+\"\\x1B[0m\")}else e[0]=T1t()+t+\" \"+e[0]}function T1t(){return io.inspectOpts.hideDate?\"\":new Date().toISOString()+\" \"}function F1t(...e){return process.stderr.write(HO.formatWithOptions(io.inspectOpts,...e)+`\n`)}function N1t(e){e?process.env.DEBUG=e:delete process.env.DEBUG}function O1t(){return process.env.DEBUG}function L1t(e){e.inspectOpts={};let t=Object.keys(io.inspectOpts);for(let r=0;r<t.length;r++)e.inspectOpts[t[r]]=io.inspectOpts[t[r]]}jO.exports=K7()(io);var{formatters:xDe}=jO.exports;xDe.o=function(e){return this.inspectOpts.colors=this.useColors,HO.inspect(e,this.inspectOpts).split(`\n`).map(t=>t.trim()).join(\" \")};xDe.O=function(e){return this.inspectOpts.colors=this.useColors,HO.inspect(e,this.inspectOpts)}});var z7=G((Qtr,J7)=>{typeof process>\"u\"||process.type===\"renderer\"||process.browser===!0||process.__nwjs?J7.exports=PDe():J7.exports=kDe()});var qO=G(Ji=>{\"use strict\";Object.defineProperty(Ji,\"__esModule\",{value:!0});Ji.DownloadHTTPError=Ji.DownloadLengthMismatchError=Ji.DownloadError=Ji.ExpiredMetadataError=Ji.EqualVersionError=Ji.BadVersionError=Ji.RepositoryError=Ji.PersistError=Ji.RuntimeError=Ji.ValueError=void 0;var Z7=class extends Error{};Ji.ValueError=Z7;var X7=class extends Error{};Ji.RuntimeError=X7;var $7=class extends Error{};Ji.PersistError=$7;var _b=class extends Error{};Ji.RepositoryError=_b;var GO=class extends _b{};Ji.BadVersionError=GO;var eK=class extends GO{};Ji.EqualVersionError=eK;var tK=class extends _b{};Ji.ExpiredMetadataError=tK;var Hb=class extends Error{};Ji.DownloadError=Hb;var rK=class extends Hb{};Ji.DownloadLengthMismatchError=rK;var nK=class extends Hb{constructor(t,r){super(t),this.statusCode=r}};Ji.DownloadHTTPError=nK});var RDe=G(l1=>{\"use strict\";var sK=l1&&l1.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(l1,\"__esModule\",{value:!0});l1.withTempFile=void 0;var iK=sK(Ie(\"fs/promises\")),M1t=sK(Ie(\"os\")),QDe=sK(Ie(\"path\")),U1t=async e=>_1t(async t=>e(QDe.default.join(t,\"tempfile\")));l1.withTempFile=U1t;var _1t=async e=>{let t=await iK.default.realpath(M1t.default.tmpdir()),r=await iK.default.mkdtemp(t+QDe.default.sep);try{return await e(r)}finally{await iK.default.rm(r,{force:!0,recursive:!0,maxRetries:3})}}});var aK=G(Pg=>{\"use strict\";var VO=Pg&&Pg.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Pg,\"__esModule\",{value:!0});Pg.DefaultFetcher=Pg.BaseFetcher=void 0;var H1t=VO(z7()),TDe=VO(Ie(\"fs\")),j1t=VO(sO()),G1t=VO(Ie(\"util\")),FDe=qO(),q1t=RDe(),W1t=(0,H1t.default)(\"tuf:fetch\"),WO=class{async downloadFile(t,r,s){return(0,q1t.withTempFile)(async a=>{let n=await this.fetch(t),c=0,f=TDe.default.createWriteStream(a);try{for await(let p of n){let h=Buffer.from(p);if(c+=h.length,c>r)throw new FDe.DownloadLengthMismatchError(\"Max length reached\");await V1t(f,h)}}finally{await G1t.default.promisify(f.close).bind(f)()}return s(a)})}async downloadBytes(t,r){return this.downloadFile(t,r,async s=>{let a=TDe.default.createReadStream(s),n=[];for await(let c of a)n.push(c);return Buffer.concat(n)})}};Pg.BaseFetcher=WO;var oK=class extends WO{constructor(t={}){super(),this.timeout=t.timeout,this.retry=t.retry}async fetch(t){W1t(\"GET %s\",t);let r=await(0,j1t.default)(t,{timeout:this.timeout,retry:this.retry});if(!r.ok||!r?.body)throw new FDe.DownloadHTTPError(\"Failed to download\",r.status);return r.body}};Pg.DefaultFetcher=oK;var V1t=async(e,t)=>new Promise((r,s)=>{e.write(t,a=>{a&&s(a),r(!0)})})});var NDe=G(YO=>{\"use strict\";Object.defineProperty(YO,\"__esModule\",{value:!0});YO.defaultConfig=void 0;YO.defaultConfig={maxRootRotations:256,maxDelegations:32,rootMaxLength:512e3,timestampMaxLength:16384,snapshotMaxLength:2e6,targetsMaxLength:5e6,prefixTargetsWithHash:!0,fetchTimeout:1e5,fetchRetries:void 0,fetchRetry:2}});var ODe=G(KO=>{\"use strict\";Object.defineProperty(KO,\"__esModule\",{value:!0});KO.TrustedMetadataStore=void 0;var ws=MO(),Hi=qO(),lK=class{constructor(t){this.trustedSet={},this.referenceTime=new Date,this.loadTrustedRoot(t)}get root(){if(!this.trustedSet.root)throw new ReferenceError(\"No trusted root metadata\");return this.trustedSet.root}get timestamp(){return this.trustedSet.timestamp}get snapshot(){return this.trustedSet.snapshot}get targets(){return this.trustedSet.targets}getRole(t){return this.trustedSet[t]}updateRoot(t){let r=JSON.parse(t.toString(\"utf8\")),s=ws.Metadata.fromJSON(ws.MetadataKind.Root,r);if(s.signed.type!=ws.MetadataKind.Root)throw new Hi.RepositoryError(`Expected 'root', got ${s.signed.type}`);if(this.root.verifyDelegate(ws.MetadataKind.Root,s),s.signed.version!=this.root.signed.version+1)throw new Hi.BadVersionError(`Expected version ${this.root.signed.version+1}, got ${s.signed.version}`);return s.verifyDelegate(ws.MetadataKind.Root,s),this.trustedSet.root=s,s}updateTimestamp(t){if(this.snapshot)throw new Hi.RuntimeError(\"Cannot update timestamp after snapshot\");if(this.root.signed.isExpired(this.referenceTime))throw new Hi.ExpiredMetadataError(\"Final root.json is expired\");let r=JSON.parse(t.toString(\"utf8\")),s=ws.Metadata.fromJSON(ws.MetadataKind.Timestamp,r);if(s.signed.type!=ws.MetadataKind.Timestamp)throw new Hi.RepositoryError(`Expected 'timestamp', got ${s.signed.type}`);if(this.root.verifyDelegate(ws.MetadataKind.Timestamp,s),this.timestamp){if(s.signed.version<this.timestamp.signed.version)throw new Hi.BadVersionError(`New timestamp version ${s.signed.version} is less than current version ${this.timestamp.signed.version}`);if(s.signed.version===this.timestamp.signed.version)throw new Hi.EqualVersionError(`New timestamp version ${s.signed.version} is equal to current version ${this.timestamp.signed.version}`);let a=this.timestamp.signed.snapshotMeta,n=s.signed.snapshotMeta;if(n.version<a.version)throw new Hi.BadVersionError(`New snapshot version ${n.version} is less than current version ${a.version}`)}return this.trustedSet.timestamp=s,this.checkFinalTimestamp(),s}updateSnapshot(t,r=!1){if(!this.timestamp)throw new Hi.RuntimeError(\"Cannot update snapshot before timestamp\");if(this.targets)throw new Hi.RuntimeError(\"Cannot update snapshot after targets\");this.checkFinalTimestamp();let s=this.timestamp.signed.snapshotMeta;r||s.verify(t);let a=JSON.parse(t.toString(\"utf8\")),n=ws.Metadata.fromJSON(ws.MetadataKind.Snapshot,a);if(n.signed.type!=ws.MetadataKind.Snapshot)throw new Hi.RepositoryError(`Expected 'snapshot', got ${n.signed.type}`);return this.root.verifyDelegate(ws.MetadataKind.Snapshot,n),this.snapshot&&Object.entries(this.snapshot.signed.meta).forEach(([c,f])=>{let p=n.signed.meta[c];if(!p)throw new Hi.RepositoryError(`Missing file ${c} in new snapshot`);if(p.version<f.version)throw new Hi.BadVersionError(`New version ${p.version} of ${c} is less than current version ${f.version}`)}),this.trustedSet.snapshot=n,this.checkFinalSnapsnot(),n}updateDelegatedTargets(t,r,s){if(!this.snapshot)throw new Hi.RuntimeError(\"Cannot update delegated targets before snapshot\");this.checkFinalSnapsnot();let a=this.trustedSet[s];if(!a)throw new Hi.RuntimeError(`No trusted ${s} metadata`);let n=this.snapshot.signed.meta?.[`${r}.json`];if(!n)throw new Hi.RepositoryError(`Missing ${r}.json in snapshot`);n.verify(t);let c=JSON.parse(t.toString(\"utf8\")),f=ws.Metadata.fromJSON(ws.MetadataKind.Targets,c);if(f.signed.type!=ws.MetadataKind.Targets)throw new Hi.RepositoryError(`Expected 'targets', got ${f.signed.type}`);a.verifyDelegate(r,f);let p=f.signed.version;if(p!=n.version)throw new Hi.BadVersionError(`Version ${p} of ${r} does not match snapshot version ${n.version}`);if(f.signed.isExpired(this.referenceTime))throw new Hi.ExpiredMetadataError(`${r}.json is expired`);this.trustedSet[r]=f}loadTrustedRoot(t){let r=JSON.parse(t.toString(\"utf8\")),s=ws.Metadata.fromJSON(ws.MetadataKind.Root,r);if(s.signed.type!=ws.MetadataKind.Root)throw new Hi.RepositoryError(`Expected 'root', got ${s.signed.type}`);s.verifyDelegate(ws.MetadataKind.Root,s),this.trustedSet.root=s}checkFinalTimestamp(){if(!this.timestamp)throw new ReferenceError(\"No trusted timestamp metadata\");if(this.timestamp.signed.isExpired(this.referenceTime))throw new Hi.ExpiredMetadataError(\"Final timestamp.json is expired\")}checkFinalSnapsnot(){if(!this.snapshot)throw new ReferenceError(\"No trusted snapshot metadata\");if(!this.timestamp)throw new ReferenceError(\"No trusted timestamp metadata\");if(this.snapshot.signed.isExpired(this.referenceTime))throw new Hi.ExpiredMetadataError(\"snapshot.json is expired\");let t=this.timestamp.signed.snapshotMeta;if(this.snapshot.signed.version!==t.version)throw new Hi.BadVersionError(\"Snapshot version doesn't match timestamp\")}};KO.TrustedMetadataStore=lK});var LDe=G(cK=>{\"use strict\";Object.defineProperty(cK,\"__esModule\",{value:!0});cK.join=K1t;var Y1t=Ie(\"url\");function K1t(e,t){return new Y1t.URL(J1t(e)+z1t(t)).toString()}function J1t(e){return e.endsWith(\"/\")?e:e+\"/\"}function z1t(e){return e.startsWith(\"/\")?e.slice(1):e}});var MDe=G(tu=>{\"use strict\";var Z1t=tu&&tu.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),X1t=tu&&tu.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),AK=tu&&tu.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r in e)r!==\"default\"&&Object.prototype.hasOwnProperty.call(e,r)&&Z1t(t,e,r);return X1t(t,e),t},$1t=tu&&tu.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(tu,\"__esModule\",{value:!0});tu.Updater=void 0;var kA=MO(),eBt=$1t(z7()),c1=AK(Ie(\"fs\")),JO=AK(Ie(\"path\")),tBt=NDe(),hy=qO(),rBt=aK(),nBt=ODe(),jb=AK(LDe()),uK=(0,eBt.default)(\"tuf:cache\"),fK=class{constructor(t){let{metadataDir:r,metadataBaseUrl:s,targetDir:a,targetBaseUrl:n,fetcher:c,config:f}=t;this.dir=r,this.metadataBaseUrl=s,this.targetDir=a,this.targetBaseUrl=n,this.forceCache=t.forceCache??!1;let p=this.loadLocalMetadata(kA.MetadataKind.Root);this.trustedSet=new nBt.TrustedMetadataStore(p),this.config={...tBt.defaultConfig,...f},this.fetcher=c||new rBt.DefaultFetcher({timeout:this.config.fetchTimeout,retry:this.config.fetchRetries??this.config.fetchRetry})}async refresh(){if(this.forceCache)try{await this.loadTimestamp({checkRemote:!1})}catch{await this.loadRoot(),await this.loadTimestamp()}else await this.loadRoot(),await this.loadTimestamp();await this.loadSnapshot(),await this.loadTargets(kA.MetadataKind.Targets,kA.MetadataKind.Root)}async getTargetInfo(t){return this.trustedSet.targets||await this.refresh(),this.preorderDepthFirstWalk(t)}async downloadTarget(t,r,s){let a=r||this.generateTargetPath(t);if(!s){if(!this.targetBaseUrl)throw new hy.ValueError(\"Target base URL not set\");s=this.targetBaseUrl}let n=t.path;if(this.trustedSet.root.signed.consistentSnapshot&&this.config.prefixTargetsWithHash){let p=Object.values(t.hashes),{dir:h,base:E}=JO.parse(n),C=`${p[0]}.${E}`;n=h?`${h}/${C}`:C}let f=jb.join(s,n);return await this.fetcher.downloadFile(f,t.length,async p=>{await t.verify(c1.createReadStream(p)),uK(\"WRITE %s\",a),c1.copyFileSync(p,a)}),a}async findCachedTarget(t,r){r||(r=this.generateTargetPath(t));try{if(c1.existsSync(r))return await t.verify(c1.createReadStream(r)),r}catch{return}}loadLocalMetadata(t){let r=JO.join(this.dir,`${t}.json`);return uK(\"READ %s\",r),c1.readFileSync(r)}async loadRoot(){let r=this.trustedSet.root.signed.version+1,s=r+this.config.maxRootRotations;for(let a=r;a<s;a++){let n=jb.join(this.metadataBaseUrl,`${a}.root.json`);try{let c=await this.fetcher.downloadBytes(n,this.config.rootMaxLength);this.trustedSet.updateRoot(c),this.persistMetadata(kA.MetadataKind.Root,c)}catch(c){if(c instanceof hy.DownloadHTTPError&&[403,404].includes(c.statusCode))break;throw c}}}async loadTimestamp({checkRemote:t}={checkRemote:!0}){try{let a=this.loadLocalMetadata(kA.MetadataKind.Timestamp);if(this.trustedSet.updateTimestamp(a),!t)return}catch{}let r=jb.join(this.metadataBaseUrl,\"timestamp.json\"),s=await this.fetcher.downloadBytes(r,this.config.timestampMaxLength);try{this.trustedSet.updateTimestamp(s)}catch(a){if(a instanceof hy.EqualVersionError)return;throw a}this.persistMetadata(kA.MetadataKind.Timestamp,s)}async loadSnapshot(){try{let t=this.loadLocalMetadata(kA.MetadataKind.Snapshot);this.trustedSet.updateSnapshot(t,!0)}catch{if(!this.trustedSet.timestamp)throw new ReferenceError(\"No timestamp metadata\");let r=this.trustedSet.timestamp.signed.snapshotMeta,s=r.length||this.config.snapshotMaxLength,a=this.trustedSet.root.signed.consistentSnapshot?r.version:void 0,n=jb.join(this.metadataBaseUrl,a?`${a}.snapshot.json`:\"snapshot.json\");try{let c=await this.fetcher.downloadBytes(n,s);this.trustedSet.updateSnapshot(c),this.persistMetadata(kA.MetadataKind.Snapshot,c)}catch(c){throw new hy.RuntimeError(`Unable to load snapshot metadata error ${c}`)}}}async loadTargets(t,r){if(this.trustedSet.getRole(t))return this.trustedSet.getRole(t);try{let s=this.loadLocalMetadata(t);this.trustedSet.updateDelegatedTargets(s,t,r)}catch{if(!this.trustedSet.snapshot)throw new ReferenceError(\"No snapshot metadata\");let a=this.trustedSet.snapshot.signed.meta[`${t}.json`],n=a.length||this.config.targetsMaxLength,c=this.trustedSet.root.signed.consistentSnapshot?a.version:void 0,f=encodeURIComponent(t),p=jb.join(this.metadataBaseUrl,c?`${c}.${f}.json`:`${f}.json`);try{let h=await this.fetcher.downloadBytes(p,n);this.trustedSet.updateDelegatedTargets(h,t,r),this.persistMetadata(t,h)}catch(h){throw new hy.RuntimeError(`Unable to load targets error ${h}`)}}return this.trustedSet.getRole(t)}async preorderDepthFirstWalk(t){let r=[{roleName:kA.MetadataKind.Targets,parentRoleName:kA.MetadataKind.Root}],s=new Set;for(;s.size<=this.config.maxDelegations&&r.length>0;){let{roleName:a,parentRoleName:n}=r.pop();if(s.has(a))continue;let c=(await this.loadTargets(a,n))?.signed;if(!c)continue;let f=c.targets?.[t];if(f)return f;if(s.add(a),c.delegations){let p=[],h=c.delegations.rolesForTarget(t);for(let{role:E,terminating:C}of h)if(p.push({roleName:E,parentRoleName:a}),C){r.splice(0);break}p.reverse(),r.push(...p)}}}generateTargetPath(t){if(!this.targetDir)throw new hy.ValueError(\"Target directory not set\");let r=encodeURIComponent(t.path);return JO.join(this.targetDir,r)}persistMetadata(t,r){let s=encodeURIComponent(t);try{let a=JO.join(this.dir,`${s}.json`);uK(\"WRITE %s\",a),c1.writeFileSync(a,r.toString(\"utf8\"))}catch(a){throw new hy.PersistError(`Failed to persist metadata ${s} error: ${a}`)}}};tu.Updater=fK});var UDe=G(xg=>{\"use strict\";Object.defineProperty(xg,\"__esModule\",{value:!0});xg.Updater=xg.BaseFetcher=xg.TargetFile=void 0;var iBt=MO();Object.defineProperty(xg,\"TargetFile\",{enumerable:!0,get:function(){return iBt.TargetFile}});var sBt=aK();Object.defineProperty(xg,\"BaseFetcher\",{enumerable:!0,get:function(){return sBt.BaseFetcher}});var oBt=MDe();Object.defineProperty(xg,\"Updater\",{enumerable:!0,get:function(){return oBt.Updater}})});var hK=G(zO=>{\"use strict\";Object.defineProperty(zO,\"__esModule\",{value:!0});zO.TUFError=void 0;var pK=class extends Error{constructor({code:t,message:r,cause:s}){super(r),this.code=t,this.cause=s,this.name=this.constructor.name}};zO.TUFError=pK});var _De=G(Gb=>{\"use strict\";var aBt=Gb&&Gb.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Gb,\"__esModule\",{value:!0});Gb.readTarget=cBt;var lBt=aBt(Ie(\"fs\")),ZO=hK();async function cBt(e,t){let r=await uBt(e,t);return new Promise((s,a)=>{lBt.default.readFile(r,\"utf-8\",(n,c)=>{n?a(new ZO.TUFError({code:\"TUF_READ_TARGET_ERROR\",message:`error reading target ${r}`,cause:n})):s(c)})})}async function uBt(e,t){let r;try{r=await e.getTargetInfo(t)}catch(a){throw new ZO.TUFError({code:\"TUF_REFRESH_METADATA_ERROR\",message:\"error refreshing TUF metadata\",cause:a})}if(!r)throw new ZO.TUFError({code:\"TUF_FIND_TARGET_ERROR\",message:`target ${t} not found`});let s=await e.findCachedTarget(r);if(!s)try{s=await e.downloadTarget(r)}catch(a){throw new ZO.TUFError({code:\"TUF_DOWNLOAD_TARGET_ERROR\",message:`error downloading target ${s}`,cause:a})}return s}});var HDe=G((jtr,fBt)=>{fBt.exports={\"https://tuf-repo-cdn.sigstore.dev\":{\"root.json\":\"ewogInNpZ25hdHVyZXMiOiBbCiAgewogICAia2V5aWQiOiAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyIsCiAgICJzaWciOiAiMzA0NjAyMjEwMDhhYjFmNmYxN2Q0ZjllNmQ3ZGNmMWM4ODkxMmI2YjUzY2MxMDM4ODY0NGFlMWYwOWJjMzdhMDgyY2QwNjAwM2UwMjIxMDBlMTQ1ZWY0YzdiNzgyZDRlODEwN2I1MzQzN2U2NjlkMDQ3Njg5MmNlOTk5OTAzYWUzM2QxNDQ0ODM2Njk5NmU3IgogIH0sCiAgewogICAia2V5aWQiOiAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICJzaWciOiAiMzA0NTAyMjEwMGM3NjhiMmY4NmRhOTk1NjkwMTljMTYwYTA4MWRhNTRhZTM2YzM0YzBhMzEyMGQzY2I2OWI1M2I3ZDExMzc1OGUwMjIwNGY2NzE1MThmNjE3YjIwZDQ2NTM3ZmFlNmMzYjYzYmFlODkxM2Y0ZjE5NjIxNTYxMDVjYzRmMDE5YWMzNWM2YSIKICB9LAogIHsKICAgImtleWlkIjogIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAic2lnIjogIjMwNDUwMjIxMDBiNDQzNGU2OTk1ZDM2OGQyM2U3NDc1OWFjZDBjYjkwMTNjODNhNWQzNTExZjBmOTk3ZWM1NGM0NTZhZTQzNTBhMDIyMDE1YjBlMjY1ZDE4MmQyYjYxZGM3NGUxNTVkOThiM2MzZmJlNTY0YmEwNTI4NmFhMTRjOGRmMDJjOWI3NTY1MTYiCiAgfSwKICB7CiAgICJrZXlpZCI6ICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgInNpZyI6ICIzMDQ1MDIyMTAwODJjNTg0MTFkOTg5ZWI5Zjg2MTQxMDg1N2Q0MjM4MTU5MGVjOTQyNGRiZGFhNTFlNzhlZDEzNTE1NDMxOTA0ZTAyMjAxMTgxODVkYTZhNmMyOTQ3MTMxYzE3Nzk3ZTJiYjc2MjBjZTI2ZTVmMzAxZDFjZWFjNWYyYTdlNThmOWRjZjJlIgogIH0sCiAgewogICAia2V5aWQiOiAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIsCiAgICJzaWciOiAiMzA0NjAyMjEwMGM3ODUxMzg1NGNhZTljMzJlYWE2Yjg4ZTE4OTEyZjQ4MDA2YzI3NTdhMjU4ZjkxNzMxMmNhYmE3NTk0OGViOWUwMjIxMDBkOWUxYjRjZTBhZGZlOWZkMmUyMTQ4ZDdmYTI3YTJmNDBiYTExMjJiZDY5ZGE3NjEyZDhkMTc3NmIwMTNjOTFkIgogIH0sCiAgewogICAia2V5aWQiOiAiZmRmYTgzYTA3YjVhODM1ODliODdkZWQ0MWY3N2YzOWQyMzJhZDkxZjdjY2U1Mjg2OGRhY2QwNmJhMDg5ODQ5ZiIsCiAgICJzaWciOiAiMzA0NTAyMjA1NjQ4M2EyZDVkOWVhOWNlYzZlMTFlYWRmYjMzYzQ4NGI2MTQyOThmYWNhMTVhY2YxYzQzMWIxMWVkN2Y3MzRjMDIyMTAwZDBjMWQ3MjZhZjkyYTg3ZTRlNjY0NTljYTVhZGYzOGEwNWI0NGUxZjk0MzE4NDIzZjk1NGJhZThiY2E1YmIyZSIKICB9LAogIHsKICAgImtleWlkIjogImUyZjU5YWNiOTQ4ODUxOTQwN2UxOGNiZmM5MzI5NTEwYmUwM2MwNGFjYTk5MjlkMmYwMzAxMzQzZmVjODU1MjMiLAogICAic2lnIjogIjMwNDYwMjIxMDBkMDA0ZGU4ODAyNGMzMmRjNTY1M2E5ZjQ4NDNjZmM1MjE1NDI3MDQ4YWQ5NjAwZDJjZjljOTY5ZTZlZGZmM2QyMDIyMTAwZDllYmI3OThmNWZjNjZhZjEwODk5ZGVjZTAxNGE4NjI4Y2NmM2M1NDAyY2Q0YTQyNzAyMDc0NzJmOGY2ZTcxMiIKICB9LAogIHsKICAgImtleWlkIjogIjNjMzQ0YWEwNjhmZDRjYzRlODdkYzUwYjYxMmMwMjQzMWZiYzc3MWU5NTAwMzk5MzY4M2EyYjBiZjI2MGNmMGUiLAogICAic2lnIjogIjMwNDYwMjIxMDBiN2IwOTk5NmM0NWNhMmQ0YjA1NjAzZTU2YmFlZmEyOTcxOGEwYjcxMTQ3Y2Y4YzZlNjYzNDliYWE2MTQ3N2RmMDIyMTAwYzRkYTgwYzcxN2I0ZmE3YmJhMGZkNWM3MmRhOGEwNDk5MzU4YjAxMzU4YjIzMDlmNDFkMTQ1NmVhMWU3ZTFkOSIKICB9LAogIHsKICAgImtleWlkIjogImVjODE2Njk3MzRlMDE3OTk2YzViODVmM2QwMmMzZGUxZGQ0NjM3YTE1MjAxOWZlMWFmMTI1ZDJmOTM2OGI5NWUiLAogICAic2lnIjogIjMwNDYwMjIxMDBiZTk3ODJjMzA3NDRlNDExYTgyZmE4NWI1MTM4ZDYwMWNlMTQ4YmMxOTI1OGFlYzY0ZTdlYzI0NDc4ZjM4ODEyMDIyMTAwY2FlZjYzZGNhZjFhNGI5YTUwMGQzYmQwZTNmMTY0ZWMxOGYxYjYzZDdhOTQ2MGQ5YWNhYjEwNjZkYjBmMDE2ZCIKICB9LAogIHsKICAgImtleWlkIjogIjFlMWQ2NWNlOThiMTBhZGRhZDQ3NjRmZWJmN2RkYTJkMDQzNmIzZDNhMzg5MzU3OWMwZGRkYWVhMjBlNTQ4NDkiLAogICAic2lnIjogIjMwNDUwMjIwNzQ2ZWMzZjg1MzRjZTU1NTMxZDBkMDFmZjY0OTY0ZWY0NDBkMWU3ZDJjNGMxNDI0MDliOGU5NzY5ZjFhZGE2ZjAyMjEwMGUzYjkyOWZjZDkzZWExOGZlYWEwODI1ODg3YTcyMTA0ODk4NzlhNjY3ODBjMDdhODNmNGJkNDZlMmYwOWFiM2IiCiAgfQogXSwKICJzaWduZWQiOiB7CiAgIl90eXBlIjogInJvb3QiLAogICJjb25zaXN0ZW50X3NuYXBzaG90IjogdHJ1ZSwKICAiZXhwaXJlcyI6ICIyMDI1LTAyLTE5VDA4OjA0OjMyWiIsCiAgImtleXMiOiB7CiAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFekJ6Vk9tSENQb2pNVkxTSTM2NFdpaVY4TlByRFxuNklnUnhWbGlza3ovdit5M0pFUjVtY1ZHY09ObGlEY1dNQzVKMmxmSG1qUE5QaGI0SDd4bThMemZTQT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBzYW50aWFnb3RvcnJlcyIKICAgfSwKICAgIjYxNjQzODM4MTI1YjQ0MGI0MGRiNjk0MmY1Y2I1YTMxYzBkYzA0MzY4MzE2ZWIyYWFhNThiOTU5MDRhNTgyMjIiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVpbmlrU3NBUW1Za05lSDVlWXEvQ25JekxhYWNPXG54bFNhYXdRRE93cUt5L3RDcXhxNXh4UFNKYzIxSzRXSWhzOUd5T2tLZnp1ZVkzR0lMemNNSlo0Y1d3PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGJvYmNhbGxhd2F5IgogICB9LAogICAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXk4WEtzbWhCWURJOEpjMEd3ekJ4ZUtheDBjbTVcblNUS0VVNjVIUEZ1blVuNDFzVDhwaTBGak00SWtIei9ZVW13bUxVTzBXdDdseGhqNkJrTElLNHFZQXc9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAZGxvcmVuYyIKICAgfSwKICAgIjcyNDdmMGRiYWQ4NWIxNDdlMTg2M2JhZGU3NjEyNDNjYzc4NWRjYjdhYTQxMGU3MTA1ZGQzZDJiNjFhMzZkMmMiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVXUmlHcjUraiszSjVTc0grWnRyNW5FMkgyd083XG5CVituTzNzOTNnTGNhMThxVE96SFkxb1d5QUdEeWtNU3NHVFVCU3Q5RCtBbjBLZktzRDJtZlNNNDJRPT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2ktb25saW5lLXVyaSI6ICJnY3BrbXM6Ly9wcm9qZWN0cy9zaWdzdG9yZS1yb290LXNpZ25pbmcvbG9jYXRpb25zL2dsb2JhbC9rZXlSaW5ncy9yb290L2NyeXB0b0tleXMvdGltZXN0YW1wIgogICB9LAogICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTBnaHJoOTJMdzFZcjNpZEdWNVdxQ3RNREI4Q3hcbitEOGhkQzR3MlpMTklwbFZSb1ZHTHNrWWEzZ2hlTXlPamlKOGtQaTE1YVEyLy83UCtvajdVdkpQR3c9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAam9zaHVhZ2wiCiAgIH0sCiAgICJlNzFhNTRkNTQzODM1YmE4NmFkYWQ5NDYwMzc5Yzc2NDFmYjg3MjZkMTY0ZWE3NjY4MDFhMWM1MjJhYmE3ZWEyIjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFRVhzejNTWlhGYjhqTVY0Mmo2cEpseWpialI4S1xuTjNCd29jZXhxNkxNSWI1cXNXS09RdkxOMTZOVWVmTGM0SHN3T291bVJzVlZhYWpTcFFTNmZvYmtSdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBtbm02NzgiCiAgIH0KICB9LAogICJyb2xlcyI6IHsKICAgInJvb3QiOiB7CiAgICAia2V5aWRzIjogWwogICAgICI2ZjI2MDA4OWQ1OTIzZGFmMjAxNjZjYTY1N2M1NDNhZjYxODM0NmFiOTcxODg0YTk5OTYyYjAxOTg4YmJlMGMzIiwKICAgICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICAgIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIKICAgIF0sCiAgICAidGhyZXNob2xkIjogMwogICB9LAogICAic25hcHNob3QiOiB7CiAgICAia2V5aWRzIjogWwogICAgICI3MjQ3ZjBkYmFkODViMTQ3ZTE4NjNiYWRlNzYxMjQzY2M3ODVkY2I3YWE0MTBlNzEwNWRkM2QyYjYxYTM2ZDJjIgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAxLAogICAgIngtdHVmLW9uLWNpLWV4cGlyeS1wZXJpb2QiOiAzNjUwLAogICAgIngtdHVmLW9uLWNpLXNpZ25pbmctcGVyaW9kIjogMzY1CiAgIH0sCiAgICJ0YXJnZXRzIjogewogICAgImtleWlkcyI6IFsKICAgICAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyIsCiAgICAgImU3MWE1NGQ1NDM4MzViYTg2YWRhZDk0NjAzNzljNzY0MWZiODcyNmQxNjRlYTc2NjgwMWExYzUyMmFiYTdlYTIiLAogICAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IiwKICAgICAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICAgImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDMKICAgfSwKICAgInRpbWVzdGFtcCI6IHsKICAgICJrZXlpZHMiOiBbCiAgICAgIjcyNDdmMGRiYWQ4NWIxNDdlMTg2M2JhZGU3NjEyNDNjYzc4NWRjYjdhYTQxMGU3MTA1ZGQzZDJiNjFhMzZkMmMiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDEsCiAgICAieC10dWYtb24tY2ktZXhwaXJ5LXBlcmlvZCI6IDcsCiAgICAieC10dWYtb24tY2ktc2lnbmluZy1wZXJpb2QiOiA0CiAgIH0KICB9LAogICJzcGVjX3ZlcnNpb24iOiAiMS4wIiwKICAidmVyc2lvbiI6IDEwLAogICJ4LXR1Zi1vbi1jaS1leHBpcnktcGVyaW9kIjogMTgyLAogICJ4LXR1Zi1vbi1jaS1zaWduaW5nLXBlcmlvZCI6IDMxCiB9Cn0=\",targets:{\"trusted_root.json\":\"ewogICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRldi5zaWdzdG9yZS50cnVzdGVkcm9vdCtqc29uO3ZlcnNpb249MC4xIiwKICAidGxvZ3MiOiBbCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vcmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUyRzJZKzJ0YWJkVFY1QmNHaUJJeDBhOWZBRndya0JibUxTR3RrczRMM3FYNnlZWTB6dWZCbmhDOFVyL2l5NTVHaFdQLzlBL2JZMkxoQzMwTTkrUll0dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDEtMTJUMTE6NTM6MjcuMDAwWiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAid05JOWF0UUdseitWV2ZPNkxSeWdINFFVZlkvOFc0UkZ3aVQ1aTVXUmdCMD0iCiAgICAgIH0KICAgIH0KICBdLAogICJjZXJ0aWZpY2F0ZUF1dGhvcml0aWVzIjogWwogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly9mdWxjaW8uc2lnc3RvcmUuZGV2IiwKICAgICAgImNlcnRDaGFpbiI6IHsKICAgICAgICAiY2VydGlmaWNhdGVzIjogWwogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQitEQ0NBWDZnQXdJQkFnSVROVmtEWm9DaW9mUERzeTdkZm02Z2VMYnVoekFLQmdncWhrak9QUVFEQXpBcU1SVXdFd1lEVlFRS0V3eHphV2R6ZEc5eVpTNWtaWFl4RVRBUEJnTlZCQU1UQ0hOcFozTjBiM0psTUI0WERUSXhNRE13TnpBek1qQXlPVm9YRFRNeE1ESXlNekF6TWpBeU9Wb3dLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkxTeUE3SWk1aytwTk84WkVXWTB5bGVtV0Rvd09rTmEza0wrR1pFNVo1R1dlaEw5L0E5YlJOQTNSYnJzWjVpMEpjYXN0YVJMN1NwNWZwL2pENWR4cWMvVWRUVm5sdlMxNmFuKzJZZnN3ZS9RdUxvbFJVQ3JjT0UyKzJpQTUrdHpkNk5tTUdRd0RnWURWUjBQQVFIL0JBUURBZ0VHTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFFd0hRWURWUjBPQkJZRUZNakZIUUJCbWlRcE1sRWs2dzJ1U3UxS0J0UHNNQjhHQTFVZEl3UVlNQmFBRk1qRkhRQkJtaVFwTWxFazZ3MnVTdTFLQnRQc01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01IOGxpV0pmTXVpNnZYWEJoakRnWTRNd3NsbU4vVEp4VmUvODNXckZvbXdtTmYwNTZ5MVg0OEY5YzRtM2Ezb3pYQUl4QUtqUmF5NS9hai9qc0tLR0lrbVFhdGpJOHV1cEhyLytDeEZ2YUpXbXBZcU5rTERHUlUrOW9yemg1aEkyUnJjdWFRPT0iCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMDdUMDM6MjA6MjkuMDAwWiIsCiAgICAgICAgImVuZCI6ICIyMDIyLTEyLTMxVDIzOjU5OjU5Ljk5OVoiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAic2lnc3RvcmUuZGV2IiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJzaWdzdG9yZSIKICAgICAgfSwKICAgICAgInVyaSI6ICJodHRwczovL2Z1bGNpby5zaWdzdG9yZS5kZXYiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlDR2pDQ0FhR2dBd0lCQWdJVUFMblZpVmZuVTBickphc21Sa0hybi9VbmZhUXdDZ1lJS29aSXpqMEVBd013S2pFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUkV3RHdZRFZRUURFd2h6YVdkemRHOXlaVEFlRncweU1qQTBNVE15TURBMk1UVmFGdzB6TVRFd01EVXhNelUyTlRoYU1EY3hGVEFUQmdOVkJBb1RESE5wWjNOMGIzSmxMbVJsZGpFZU1Cd0dBMVVFQXhNVmMybG5jM1J2Y21VdGFXNTBaWEp0WldScFlYUmxNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRThSVlMveXNIK05PdnVEWnlQSVp0aWxnVUY5TmxhcllwQWQ5SFAxdkJCSDFVNUNWNzdMU1M3czBaaUg0bkU3SHY3cHRTNkx2dlIvU1RrNzk4TFZnTXpMbEo0SGVJZkYzdEhTYWV4TGNZcFNBU3Ixa1MwTi9SZ0JKei85aldDaVhubzNzd2VUQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3TXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFkQmdOVkhRNEVGZ1FVMzlQcHoxWWtFWmI1cU5qcEtGV2l4aTRZWkQ4d0h3WURWUjBqQkJnd0ZvQVVXTUFlWDVGRnBXYXBlc3lRb1pNaTBDckZ4Zm93Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3UENzUUs0RFlpWllEUElhRGk1SEZLbmZ4WHg2QVNTVm1FUmZzeW5ZQmlYMlg2U0pSblpVODQvOURaZG5GdnZ4bUFqQk90NlFwQmxjNEovMER4dmtUQ3FwY2x2emlMNkJDQ1BuamRsSUIzUHUzQnhzUG15Z1VZN0lpMnpiZENkbGlpb3c9IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUI5ekNDQVh5Z0F3SUJBZ0lVQUxaTkFQRmR4SFB3amVEbG9Ed3lZQ2hBTy80d0NnWUlLb1pJemowRUF3TXdLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQWVGdzB5TVRFd01EY3hNelUyTlRsYUZ3MHpNVEV3TURVeE16VTJOVGhhTUNveEZUQVRCZ05WQkFvVERITnBaM04wYjNKbExtUmxkakVSTUE4R0ExVUVBeE1JYzJsbmMzUnZjbVV3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBVDdYZUZUNHJiM1BRR3dTNElhanRMazMvT2xucGdhbmdhQmNsWXBzWUJyNWkrNHluQjA3Y2ViM0xQME9JT1pkeGV4WDY5YzVpVnV5SlJRK0h6MDV5aStVRjN1QldBbEhwaVM1c2gwK0gyR0hFN1NYcmsxRUM1bTFUcjE5TDlnZzkyall6QmhNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUll3QjVma1VXbFpxbDZ6SkNoa3lMUUtzWEYrakFmQmdOVkhTTUVHREFXZ0JSWXdCNWZrVVdsWnFsNnpKQ2hreUxRS3NYRitqQUtCZ2dxaGtqT1BRUURBd05wQURCbUFqRUFqMW5IZVhacCsxM05XQk5hK0VEc0RQOEcxV1dnMXRDTVdQL1dIUHFwYVZvMGpoc3dlTkZaZ1NzMGVFN3dZSTRxQWpFQTJXQjlvdDk4c0lrb0YzdlpZZGQzL1Z0V0I1YjlUTk1lYTdJeC9zdEo1VGZjTExlQUJMRTRCTkpPc1E0dm5CSEoiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjItMDQtMTNUMjA6MDY6MTUuMDAwWiIKICAgICAgfQogICAgfQogIF0sCiAgImN0bG9ncyI6IFsKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi90ZXN0IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUViZndSK1JKdWRYc2NnUkJScEtYMVhGRHkzUHl1ZER4ei9TZm5SaTFmVDhla3BmQmQyTzF1b3o3anIzWjhuS3p4QTY5RVVRK2VGQ0ZJM3pldWJQV1U3dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMTRUMDA6MDA6MDAuMDAwWiIsCiAgICAgICAgICAiZW5kIjogIjIwMjItMTAtMzFUMjM6NTk6NTkuOTk5WiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAiQ0dDUzhDaFMvMmhGMGRGcko0U2NSV2NZckJZOXd6alNiZWE4SWdZMmIzST0iCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vY3RmZS5zaWdzdG9yZS5kZXYvMjAyMiIsCiAgICAgICJoYXNoQWxnb3JpdGhtIjogIlNIQTJfMjU2IiwKICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAicmF3Qnl0ZXMiOiAiTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaVBTbEZpMENtRlRmRWpDVXFGOUh1Q0VjWVhOS0FhWWFsSUptQlo4eXllelBqVHFoeHJLQnBNbmFvY1Z0TEpCSTFlTTN1WG5RelFHQUpkSjRnczlGeXc9PSIsCiAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEwLTIwVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgfQogICAgICB9LAogICAgICAibG9nSWQiOiB7CiAgICAgICAgImtleUlkIjogIjNUMHdhc2JIRVRKakdSNGNtV2MzQXFKS1hyamVQSzMvaDRweWdDOHA3bzQ9IgogICAgICB9CiAgICB9CiAgXSwKICAidGltZXN0YW1wQXV0aG9yaXRpZXMiOiBbCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAiR2l0SHViLCBJbmMuIiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJJbnRlcm5hbCBTZXJ2aWNlcyBSb290IgogICAgICB9LAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCM0RDQ0FXS2dBd0lCQWdJVWNoa05zSDM2WGEwNGIxTHFJYytxcjlEVmVjTXdDZ1lJS29aSXpqMEVBd013TWpFVk1CTUdBMVVFQ2hNTVIybDBTSFZpTENCSmJtTXVNUmt3RndZRFZRUURFeEJVVTBFZ2FXNTBaWEp0WldScFlYUmxNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVEkwTURReE16QXdNREF3TUZvd01qRVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVJrd0Z3WURWUVFERXhCVVUwRWdWR2x0WlhOMFlXMXdhVzVuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVUQ1Wk5iU3FZTWQ2cjhxcE9PRVg5aWJHblpUOUdzdVhPaHIvZjhVOUZKdWdCR0V4S1lwNDBPVUxTMGVyalpXN3hWOXhWNTJObkpmNU9lRHE0ZTVaS3FOV01GUXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUlNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVhVzFSdWRPZ1Z0MGxlcVkwV0tZYnVQcjQ3d0F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl3YlVIOUh2RDRlakNaSk9XUW5xQWxrcVVSbGx2dTlNOCtWcUxiaVJLK3pTZlpDWndzaWxqUm44TVFRUlNrWEVFNUFqRUFnK1Z4cXRvamZWZnU4RGh6emhDeDlHS0VUYkpIYjE5aVY3Mm1NS1ViREFGbXpaNmJROGI1NFpiOHRpZHk1YVdlIgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUNFRENDQVpXZ0F3SUJBZ0lVWDhaTzVRWFA3dk40ZE1RNWU5c1UzbnViOE9nd0NnWUlLb1pJemowRUF3TXdPREVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1SOHdIUVlEVlFRREV4WkpiblJsY201aGJDQlRaWEoyYVdObGN5QlNiMjkwTUI0WERUSXpNRFF4TkRBd01EQXdNRm9YRFRJNE1EUXhNakF3TURBd01Gb3dNakVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1Sa3dGd1lEVlFRREV4QlVVMEVnYVc1MFpYSnRaV1JwWVhSbE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFdk1MWS9kVFZidklKWUFOQXVzekV3Sm5RRTFsbGZ0eW55TUtJTWhoNDhIbXFiVnI1eWd5YnpzTFJMVktiQldPZFoyMWFlSnorZ1ppeXRaZXRxY3lGOVdsRVI1TkVNZjZKVjdaTm9qUXB4SHE0UkhHb0dTY2VRdi9xdlRpWnhFREtvMll3WkRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVWFXMVJ1ZE9nVnQwbGVxWTBXS1lidVByNDd3QXdId1lEVlIwakJCZ3dGb0FVOU5ZWWxvYm5BRzRjMC9xanh5SC9scS93eitRd0NnWUlLb1pJemowRUF3TURhUUF3WmdJeEFLMUIxODV5Z0NySVlGbElzM0dqc3dqbndTTUc2TFk4d29MVmRha0tEWnhWYThmOGNxTXMxRGhjeEowKzA5dzk1UUl4QU8rdEJ6Wms3dmpVSjlpSmdENFI2WldUeFFXS3FObTc0ak85OW8rbzlzdjRGSS9TWlRaVEZ5TW4wSUpFSGRObXlBPT0iCiAgICAgICAgICB9LAogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQjlEQ0NBWHFnQXdJQkFnSVVhL0pBa2RVaks0SlV3c3F0YWlSSkdXaHFMU293Q2dZSUtvWkl6ajBFQXdNd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVE16TURReE1UQXdNREF3TUZvd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRWY5akZBWHh6NGt4NjhBSFJNT2tGQmhmbERjTVR2emFYejR4L0ZDY1hqSi8xcUVLb24vcVBJR25hVVJza0R0eU5iTkRPcGVKVERERnF0NDhpTVBybnpweDZJWndxZW1mVUpONHhCRVpmemErcFl0L2l5b2QrOXRacjIwUlJXU3YvbzBVd1F6QU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFqQWRCZ05WSFE0RUZnUVU5TllZbG9ibkFHNGMwL3FqeHlIL2xxL3d6K1F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl4QUxaTFo4QmdSWHpLeExNTU45VklsTytlNGhyQm5OQmdGN3R6N0hucm93djJOZXRaRXJJQUNLRnltQmx2V0R2dE1BSXdaTytraTZzc1ExYnNabzk4TzhtRUFmMk5aN2lpQ2dERFUwVndqZWNvNnp5ZWgwekJUczkvN2dWNkFITlE1M3hEIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfSwKICAgICAgInZhbGlkRm9yIjogewogICAgICAgICJzdGFydCI6ICIyMDIzLTA0LTE0VDAwOjAwOjAwLjAwMFoiCiAgICAgIH0KICAgIH0KICBdCn0K\",\"registry.npmjs.org%2Fkeys.json\":\"ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIxOTk5LTAxLTAxVDAwOjAwOjAwLjAwMFoiLAogICAgICAgICAgICAgICAgICAgICJlbmQiOiAiMjAyNS0wMS0yOVQwMDowMDowMC4wMDBaIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAgICJrZXlJZCI6ICJTSEEyNTY6amwzYndzd3U4MFBqam9rQ2doMG8ydzVjMlU0TGhRQUU1N2dqOWN6MWt6QSIsCiAgICAgICAgICAgICJrZXlVc2FnZSI6ICJucG06YXR0ZXN0YXRpb25zIiwKICAgICAgICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUxT2xiM3pNQUZGeFhLSGlJa1FPNWNKM1lobDVpNlVQcCtJaHV0ZUJKYnVIY0E1VW9nS28wRVd0bFd3VzZLU2FLb1RORVlMN0psQ1FpVm5raEJrdFVnZz09IiwKICAgICAgICAgICAgICAgICJrZXlEZXRhaWxzIjogIlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwKICAgICAgICAgICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICAgICAgICAgICAic3RhcnQiOiAiMjAyMi0xMi0wMVQwMDowMDowMC4wMDBaIiwKICAgICAgICAgICAgICAgICAgICAiZW5kIjogIjIwMjUtMDEtMjlUMDA6MDA6MDAuMDAwWiIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OkRoUTh3UjVBUEJ2RkhMRi8rVGMrQVl2UE9kVHBjSURxT2h4c0JIUndDN1UiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVk2WWE3VysrN2FVUHp2TVRyZXpINlljeDNjK0hPS1lDY05HeWJKWlNDSnEvZmQ3UWE4dXVBS3RkSWtVUXRRaUVLRVJoQW1FNWxNTUpoUDhPa0RPYTJnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDI1LTAxLTEzVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICAgImtleUlkIjogIlNIQTI1NjpEaFE4d1I1QVBCdkZITEYvK1RjK0FZdlBPZFRwY0lEcU9oeHNCSFJ3QzdVIiwKICAgICAgICAgICAgImtleVVzYWdlIjogIm5wbTphdHRlc3RhdGlvbnMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVk2WWE3VysrN2FVUHp2TVRyZXpINlljeDNjK0hPS1lDY05HeWJKWlNDSnEvZmQ3UWE4dXVBS3RkSWtVUXRRaUVLRVJoQW1FNWxNTUpoUDhPa0RPYTJnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDI1LTAxLTEzVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICBdCn0K\"}}}});var GDe=G(u1=>{\"use strict\";var jDe=u1&&u1.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(u1,\"__esModule\",{value:!0});u1.TUFClient=void 0;var kg=jDe(Ie(\"fs\")),qb=jDe(Ie(\"path\")),ABt=UDe(),pBt=XO(),hBt=_De(),dK=\"targets\",gK=class{constructor(t){let r=new URL(t.mirrorURL),s=encodeURIComponent(r.host+r.pathname.replace(/\\/$/,\"\")),a=qb.default.join(t.cachePath,s);gBt(a),dBt({cachePath:a,mirrorURL:t.mirrorURL,tufRootPath:t.rootPath,forceInit:t.forceInit}),this.updater=mBt({mirrorURL:t.mirrorURL,cachePath:a,forceCache:t.forceCache,retry:t.retry,timeout:t.timeout})}async refresh(){return this.updater.refresh()}getTarget(t){return(0,hBt.readTarget)(this.updater,t)}};u1.TUFClient=gK;function gBt(e){let t=qb.default.join(e,dK);kg.default.existsSync(e)||kg.default.mkdirSync(e,{recursive:!0}),kg.default.existsSync(t)||kg.default.mkdirSync(t)}function dBt({cachePath:e,mirrorURL:t,tufRootPath:r,forceInit:s}){let a=qb.default.join(e,\"root.json\");if(!kg.default.existsSync(a)||s)if(r)kg.default.copyFileSync(r,a);else{let c=HDe()[t];if(!c)throw new pBt.TUFError({code:\"TUF_INIT_CACHE_ERROR\",message:`No root.json found for mirror: ${t}`});kg.default.writeFileSync(a,Buffer.from(c[\"root.json\"],\"base64\")),Object.entries(c.targets).forEach(([f,p])=>{kg.default.writeFileSync(qb.default.join(e,dK,f),Buffer.from(p,\"base64\"))})}}function mBt(e){let t={fetchTimeout:e.timeout,fetchRetry:e.retry};return new ABt.Updater({metadataBaseUrl:e.mirrorURL,targetBaseUrl:`${e.mirrorURL}/targets`,metadataDir:e.cachePath,targetDir:qb.default.join(e.cachePath,dK),forceCache:e.forceCache,config:t})}});var XO=G(ph=>{\"use strict\";Object.defineProperty(ph,\"__esModule\",{value:!0});ph.TUFError=ph.DEFAULT_MIRROR_URL=void 0;ph.getTrustedRoot=SBt;ph.initTUF=DBt;var yBt=yb(),EBt=wSe(),IBt=GDe();ph.DEFAULT_MIRROR_URL=\"https://tuf-repo-cdn.sigstore.dev\";var CBt=\"sigstore-js\",wBt={retries:2},BBt=5e3,vBt=\"trusted_root.json\";async function SBt(e={}){let r=await qDe(e).getTarget(vBt);return yBt.TrustedRoot.fromJSON(JSON.parse(r))}async function DBt(e={}){let t=qDe(e);return t.refresh().then(()=>t)}function qDe(e){return new IBt.TUFClient({cachePath:e.cachePath||(0,EBt.appDataPath)(CBt),rootPath:e.rootPath,mirrorURL:e.mirrorURL||ph.DEFAULT_MIRROR_URL,retry:e.retry??wBt,timeout:e.timeout??BBt,forceCache:e.forceCache??!1,forceInit:e.forceInit??e.force??!1})}var bBt=hK();Object.defineProperty(ph,\"TUFError\",{enumerable:!0,get:function(){return bBt.TUFError}})});var WDe=G($O=>{\"use strict\";Object.defineProperty($O,\"__esModule\",{value:!0});$O.DSSESignatureContent=void 0;var Wb=bl(),mK=class{constructor(t){this.env=t}compareDigest(t){return Wb.crypto.bufferEqual(t,Wb.crypto.digest(\"sha256\",this.env.payload))}compareSignature(t){return Wb.crypto.bufferEqual(t,this.signature)}verifySignature(t){return Wb.crypto.verify(this.preAuthEncoding,t,this.signature)}get signature(){return this.env.signatures.length>0?this.env.signatures[0].sig:Buffer.from(\"\")}get preAuthEncoding(){return Wb.dsse.preAuthEncoding(this.env.payloadType,this.env.payload)}};$O.DSSESignatureContent=mK});var VDe=G(eL=>{\"use strict\";Object.defineProperty(eL,\"__esModule\",{value:!0});eL.MessageSignatureContent=void 0;var yK=bl(),EK=class{constructor(t,r){this.signature=t.signature,this.messageDigest=t.messageDigest.digest,this.artifact=r}compareSignature(t){return yK.crypto.bufferEqual(t,this.signature)}compareDigest(t){return yK.crypto.bufferEqual(t,this.messageDigest)}verifySignature(t){return yK.crypto.verify(this.artifact,t,this.signature)}};eL.MessageSignatureContent=EK});var KDe=G(tL=>{\"use strict\";Object.defineProperty(tL,\"__esModule\",{value:!0});tL.toSignedEntity=kBt;tL.signatureContent=YDe;var IK=bl(),PBt=WDe(),xBt=VDe();function kBt(e,t){let{tlogEntries:r,timestampVerificationData:s}=e.verificationMaterial,a=[];for(let n of r)a.push({$case:\"transparency-log\",tlogEntry:n});for(let n of s?.rfc3161Timestamps??[])a.push({$case:\"timestamp-authority\",timestamp:IK.RFC3161Timestamp.parse(n.signedTimestamp)});return{signature:YDe(e,t),key:QBt(e),tlogEntries:r,timestamps:a}}function YDe(e,t){switch(e.content.$case){case\"dsseEnvelope\":return new PBt.DSSESignatureContent(e.content.dsseEnvelope);case\"messageSignature\":return new xBt.MessageSignatureContent(e.content.messageSignature,t)}}function QBt(e){switch(e.verificationMaterial.content.$case){case\"publicKey\":return{$case:\"public-key\",hint:e.verificationMaterial.content.publicKey.hint};case\"x509CertificateChain\":return{$case:\"certificate\",certificate:IK.X509Certificate.parse(e.verificationMaterial.content.x509CertificateChain.certificates[0].rawBytes)};case\"certificate\":return{$case:\"certificate\",certificate:IK.X509Certificate.parse(e.verificationMaterial.content.certificate.rawBytes)}}}});var vo=G(f1=>{\"use strict\";Object.defineProperty(f1,\"__esModule\",{value:!0});f1.PolicyError=f1.VerificationError=void 0;var rL=class extends Error{constructor({code:t,message:r,cause:s}){super(r),this.code=t,this.cause=s,this.name=this.constructor.name}},CK=class extends rL{};f1.VerificationError=CK;var wK=class extends rL{};f1.PolicyError=wK});var JDe=G(nL=>{\"use strict\";Object.defineProperty(nL,\"__esModule\",{value:!0});nL.filterCertAuthorities=RBt;nL.filterTLogAuthorities=TBt;function RBt(e,t){return e.filter(r=>r.validFor.start<=t.start&&r.validFor.end>=t.end)}function TBt(e,t){return e.filter(r=>t.logID&&!r.logID.equals(t.logID)?!1:r.validFor.start<=t.targetDate&&t.targetDate<=r.validFor.end)}});var dy=G(gy=>{\"use strict\";Object.defineProperty(gy,\"__esModule\",{value:!0});gy.filterTLogAuthorities=gy.filterCertAuthorities=void 0;gy.toTrustMaterial=NBt;var BK=bl(),Vb=yb(),FBt=vo(),vK=new Date(0),SK=new Date(864e13),XDe=JDe();Object.defineProperty(gy,\"filterCertAuthorities\",{enumerable:!0,get:function(){return XDe.filterCertAuthorities}});Object.defineProperty(gy,\"filterTLogAuthorities\",{enumerable:!0,get:function(){return XDe.filterTLogAuthorities}});function NBt(e,t){let r=typeof t==\"function\"?t:OBt(t);return{certificateAuthorities:e.certificateAuthorities.map(ZDe),timestampAuthorities:e.timestampAuthorities.map(ZDe),tlogs:e.tlogs.map(zDe),ctlogs:e.ctlogs.map(zDe),publicKey:r}}function zDe(e){let t=e.publicKey.keyDetails,r=t===Vb.PublicKeyDetails.PKCS1_RSA_PKCS1V5||t===Vb.PublicKeyDetails.PKIX_RSA_PKCS1V5||t===Vb.PublicKeyDetails.PKIX_RSA_PKCS1V15_2048_SHA256||t===Vb.PublicKeyDetails.PKIX_RSA_PKCS1V15_3072_SHA256||t===Vb.PublicKeyDetails.PKIX_RSA_PKCS1V15_4096_SHA256?\"pkcs1\":\"spki\";return{logID:e.logId.keyId,publicKey:BK.crypto.createPublicKey(e.publicKey.rawBytes,r),validFor:{start:e.publicKey.validFor?.start||vK,end:e.publicKey.validFor?.end||SK}}}function ZDe(e){return{certChain:e.certChain.certificates.map(t=>BK.X509Certificate.parse(t.rawBytes)),validFor:{start:e.validFor?.start||vK,end:e.validFor?.end||SK}}}function OBt(e){return t=>{let r=(e||{})[t];if(!r)throw new FBt.VerificationError({code:\"PUBLIC_KEY_ERROR\",message:`key not found: ${t}`});return{publicKey:BK.crypto.createPublicKey(r.rawBytes),validFor:s=>(r.validFor?.start||vK)<=s&&(r.validFor?.end||SK)>=s}}}});var DK=G(Yb=>{\"use strict\";Object.defineProperty(Yb,\"__esModule\",{value:!0});Yb.CertificateChainVerifier=void 0;Yb.verifyCertificateChain=MBt;var my=vo(),LBt=dy();function MBt(e,t){let r=(0,LBt.filterCertAuthorities)(t,{start:e.notBefore,end:e.notAfter}),s;for(let a of r)try{return new iL({trustedCerts:a.certChain,untrustedCert:e}).verify()}catch(n){s=n}throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"Failed to verify certificate chain\",cause:s})}var iL=class{constructor(t){this.untrustedCert=t.untrustedCert,this.trustedCerts=t.trustedCerts,this.localCerts=UBt([...t.trustedCerts,t.untrustedCert])}verify(){let t=this.sort();return this.checkPath(t),t}sort(){let t=this.untrustedCert,r=this.buildPaths(t);if(r=r.filter(a=>a.some(n=>this.trustedCerts.includes(n))),r.length===0)throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"no trusted certificate path found\"});let s=r.reduce((a,n)=>a.length<n.length?a:n);return[t,...s].slice(0,-1)}buildPaths(t){let r=[],s=this.findIssuer(t);if(s.length===0)throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"no valid certificate path found\"});for(let a=0;a<s.length;a++){let n=s[a];if(n.equals(t)){r.push([t]);continue}let c=this.buildPaths(n);for(let f=0;f<c.length;f++)r.push([n,...c[f]])}return r}findIssuer(t){let r=[],s;return t.subject.equals(t.issuer)&&t.verify()?[t]:(t.extAuthorityKeyID&&(s=t.extAuthorityKeyID.keyIdentifier),this.localCerts.forEach(a=>{if(s&&a.extSubjectKeyID){a.extSubjectKeyID.keyIdentifier.equals(s)&&r.push(a);return}a.subject.equals(t.issuer)&&r.push(a)}),r=r.filter(a=>{try{return t.verify(a)}catch{return!1}}),r)}checkPath(t){if(t.length<1)throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"certificate chain must contain at least one certificate\"});if(!t.slice(1).every(s=>s.isCA))throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"intermediate certificate is not a CA\"});for(let s=t.length-2;s>=0;s--)if(!t[s].issuer.equals(t[s+1].subject))throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"incorrect certificate name chaining\"});for(let s=0;s<t.length;s++){let a=t[s];if(a.extBasicConstraints?.isCA){let n=a.extBasicConstraints.pathLenConstraint;if(n!==void 0&&n<s-1)throw new my.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"path length constraint exceeded\"})}}}};Yb.CertificateChainVerifier=iL;function UBt(e){for(let t=0;t<e.length;t++)for(let r=t+1;r<e.length;r++)e[t].equals(e[r])&&(e.splice(r,1),r--);return e}});var $De=G(bK=>{\"use strict\";Object.defineProperty(bK,\"__esModule\",{value:!0});bK.verifySCTs=jBt;var sL=bl(),_Bt=vo(),HBt=dy();function jBt(e,t,r){let s,a=e.clone();for(let p=0;p<a.extensions.length;p++){let h=a.extensions[p];if(h.subs[0].toOID()===sL.EXTENSION_OID_SCT){s=new sL.X509SCTExtension(h),a.extensions.splice(p,1);break}}if(!s)return[];if(s.signedCertificateTimestamps.length===0)return[];let n=new sL.ByteStream,c=sL.crypto.digest(\"sha256\",t.publicKey);n.appendView(c);let f=a.tbsCertificate.toDER();return n.appendUint24(f.length),n.appendView(f),s.signedCertificateTimestamps.map(p=>{if(!(0,HBt.filterTLogAuthorities)(r,{logID:p.logID,targetDate:p.datetime}).some(C=>p.verify(n.buffer,C.publicKey)))throw new _Bt.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"SCT verification failed\"});return p.logID})}});var tbe=G(oL=>{\"use strict\";Object.defineProperty(oL,\"__esModule\",{value:!0});oL.verifyPublicKey=KBt;oL.verifyCertificate=JBt;var GBt=bl(),ebe=vo(),qBt=DK(),WBt=$De(),VBt=\"1.3.6.1.4.1.57264.1.1\",YBt=\"1.3.6.1.4.1.57264.1.8\";function KBt(e,t,r){let s=r.publicKey(e);return t.forEach(a=>{if(!s.validFor(a))throw new ebe.VerificationError({code:\"PUBLIC_KEY_ERROR\",message:`Public key is not valid for timestamp: ${a.toISOString()}`})}),{key:s.publicKey}}function JBt(e,t,r){let s=(0,qBt.verifyCertificateChain)(e,r.certificateAuthorities);if(!t.every(n=>s.every(c=>c.validForDate(n))))throw new ebe.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"certificate is not valid or expired at the specified date\"});return{scts:(0,WBt.verifySCTs)(s[0],s[1],r.ctlogs),signer:zBt(s[0])}}function zBt(e){let t,r=e.extension(YBt);r?t=r.valueObj.subs?.[0]?.value.toString(\"ascii\"):t=e.extension(VBt)?.value.toString(\"ascii\");let s={extensions:{issuer:t},subjectAlternativeName:e.subjectAltName};return{key:GBt.crypto.createPublicKey(e.publicKey),identity:s}}});var nbe=G(aL=>{\"use strict\";Object.defineProperty(aL,\"__esModule\",{value:!0});aL.verifySubjectAlternativeName=ZBt;aL.verifyExtensions=XBt;var rbe=vo();function ZBt(e,t){if(t===void 0||!t.match(e))throw new rbe.PolicyError({code:\"UNTRUSTED_SIGNER_ERROR\",message:`certificate identity error - expected ${e}, got ${t}`})}function XBt(e,t={}){let r;for(r in e)if(t[r]!==e[r])throw new rbe.PolicyError({code:\"UNTRUSTED_SIGNER_ERROR\",message:`invalid certificate extension - expected ${r}=${e[r]}, got ${r}=${t[r]}`})}});var ibe=G(RK=>{\"use strict\";Object.defineProperty(RK,\"__esModule\",{value:!0});RK.verifyCheckpoint=t2t;var xK=bl(),A1=vo(),$Bt=dy(),PK=`\n\n`,e2t=/\\u2014 (\\S+) (\\S+)\\n/g;function t2t(e,t){let r=(0,$Bt.filterTLogAuthorities)(t,{targetDate:new Date(Number(e.integratedTime)*1e3)}),s=e.inclusionProof,a=kK.fromString(s.checkpoint.envelope),n=QK.fromString(a.note);if(!r2t(a,r))throw new A1.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"invalid checkpoint signature\"});if(!xK.crypto.bufferEqual(n.logHash,s.rootHash))throw new A1.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"root hash mismatch\"})}function r2t(e,t){let r=Buffer.from(e.note,\"utf-8\");return e.signatures.every(s=>{let a=t.find(n=>xK.crypto.bufferEqual(n.logID.subarray(0,4),s.keyHint));return a?xK.crypto.verify(r,a.publicKey,s.signature):!1})}var kK=class e{constructor(t,r){this.note=t,this.signatures=r}static fromString(t){if(!t.includes(PK))throw new A1.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"missing checkpoint separator\"});let r=t.indexOf(PK),s=t.slice(0,r+1),n=t.slice(r+PK.length).matchAll(e2t),c=Array.from(n,f=>{let[,p,h]=f,E=Buffer.from(h,\"base64\");if(E.length<5)throw new A1.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"malformed checkpoint signature\"});return{name:p,keyHint:E.subarray(0,4),signature:E.subarray(4)}});if(c.length===0)throw new A1.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"no signatures found in checkpoint\"});return new e(s,c)}},QK=class e{constructor(t,r,s,a){this.origin=t,this.logSize=r,this.logHash=s,this.rest=a}static fromString(t){let r=t.trimEnd().split(`\n`);if(r.length<3)throw new A1.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"too few lines in checkpoint header\"});let s=r[0],a=BigInt(r[1]),n=Buffer.from(r[2],\"base64\"),c=r.slice(3);return new e(s,a,n,c)}}});var sbe=G(OK=>{\"use strict\";Object.defineProperty(OK,\"__esModule\",{value:!0});OK.verifyMerkleInclusion=s2t;var NK=bl(),TK=vo(),n2t=Buffer.from([0]),i2t=Buffer.from([1]);function s2t(e){let t=e.inclusionProof,r=BigInt(t.logIndex),s=BigInt(t.treeSize);if(r<0n||r>=s)throw new TK.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:`invalid index: ${r}`});let{inner:a,border:n}=o2t(r,s);if(t.hashes.length!==a+n)throw new TK.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"invalid hash count\"});let c=t.hashes.slice(0,a),f=t.hashes.slice(a),p=A2t(e.canonicalizedBody),h=l2t(a2t(p,c,r),f);if(!NK.crypto.bufferEqual(h,t.rootHash))throw new TK.VerificationError({code:\"TLOG_INCLUSION_PROOF_ERROR\",message:\"calculated root hash does not match inclusion proof\"})}function o2t(e,t){let r=c2t(e,t),s=u2t(e>>BigInt(r));return{inner:r,border:s}}function a2t(e,t,r){return t.reduce((s,a,n)=>r>>BigInt(n)&BigInt(1)?FK(a,s):FK(s,a),e)}function l2t(e,t){return t.reduce((r,s)=>FK(s,r),e)}function c2t(e,t){return f2t(e^t-BigInt(1))}function u2t(e){return e.toString(2).split(\"1\").length-1}function f2t(e){return e===0n?0:e.toString(2).length}function FK(e,t){return NK.crypto.digest(\"sha256\",i2t,e,t)}function A2t(e){return NK.crypto.digest(\"sha256\",n2t,e)}});var abe=G(LK=>{\"use strict\";Object.defineProperty(LK,\"__esModule\",{value:!0});LK.verifyTLogSET=g2t;var obe=bl(),p2t=vo(),h2t=dy();function g2t(e,t){if(!(0,h2t.filterTLogAuthorities)(t,{logID:e.logId.keyId,targetDate:new Date(Number(e.integratedTime)*1e3)}).some(a=>{let n=d2t(e),c=Buffer.from(obe.json.canonicalize(n),\"utf8\"),f=e.inclusionPromise.signedEntryTimestamp;return obe.crypto.verify(c,a.publicKey,f)}))throw new p2t.VerificationError({code:\"TLOG_INCLUSION_PROMISE_ERROR\",message:\"inclusion promise could not be verified\"})}function d2t(e){let{integratedTime:t,logIndex:r,logId:s,canonicalizedBody:a}=e;return{body:a.toString(\"base64\"),integratedTime:Number(t),logIndex:Number(r),logID:s.keyId.toString(\"hex\")}}});var lbe=G(_K=>{\"use strict\";Object.defineProperty(_K,\"__esModule\",{value:!0});_K.verifyRFC3161Timestamp=E2t;var MK=bl(),UK=vo(),m2t=DK(),y2t=dy();function E2t(e,t,r){let s=e.signingTime;if(r=(0,y2t.filterCertAuthorities)(r,{start:s,end:s}),r=C2t(r,{serialNumber:e.signerSerialNumber,issuer:e.signerIssuer}),!r.some(n=>{try{return I2t(e,t,n),!0}catch{return!1}}))throw new UK.VerificationError({code:\"TIMESTAMP_ERROR\",message:\"timestamp could not be verified\"})}function I2t(e,t,r){let[s,...a]=r.certChain,n=MK.crypto.createPublicKey(s.publicKey),c=e.signingTime;try{new m2t.CertificateChainVerifier({untrustedCert:s,trustedCerts:a}).verify()}catch{throw new UK.VerificationError({code:\"TIMESTAMP_ERROR\",message:\"invalid certificate chain\"})}if(!r.certChain.every(p=>p.validForDate(c)))throw new UK.VerificationError({code:\"TIMESTAMP_ERROR\",message:\"timestamp was signed with an expired certificate\"});e.verify(t,n)}function C2t(e,t){return e.filter(r=>r.certChain.length>0&&MK.crypto.bufferEqual(r.certChain[0].serialNumber,t.serialNumber)&&MK.crypto.bufferEqual(r.certChain[0].issuer,t.issuer))}});var cbe=G(lL=>{\"use strict\";Object.defineProperty(lL,\"__esModule\",{value:!0});lL.verifyTSATimestamp=b2t;lL.verifyTLogTimestamp=P2t;var w2t=vo(),B2t=ibe(),v2t=sbe(),S2t=abe(),D2t=lbe();function b2t(e,t,r){return(0,D2t.verifyRFC3161Timestamp)(e,t,r),{type:\"timestamp-authority\",logID:e.signerSerialNumber,timestamp:e.signingTime}}function P2t(e,t){let r=!1;if(x2t(e)&&((0,S2t.verifyTLogSET)(e,t),r=!0),k2t(e)&&((0,v2t.verifyMerkleInclusion)(e),(0,B2t.verifyCheckpoint)(e,t),r=!0),!r)throw new w2t.VerificationError({code:\"TLOG_MISSING_INCLUSION_ERROR\",message:\"inclusion could not be verified\"});return{type:\"transparency-log\",logID:e.logId.keyId,timestamp:new Date(Number(e.integratedTime)*1e3)}}function x2t(e){return e.inclusionPromise!==void 0}function k2t(e){return e.inclusionProof!==void 0}});var ube=G(HK=>{\"use strict\";Object.defineProperty(HK,\"__esModule\",{value:!0});HK.verifyDSSETLogBody=Q2t;var cL=vo();function Q2t(e,t){switch(e.apiVersion){case\"0.0.1\":return R2t(e,t);default:throw new cL.VerificationError({code:\"TLOG_BODY_ERROR\",message:`unsupported dsse version: ${e.apiVersion}`})}}function R2t(e,t){if(e.spec.signatures?.length!==1)throw new cL.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"signature count mismatch\"});let r=e.spec.signatures[0].signature;if(!t.compareSignature(Buffer.from(r,\"base64\")))throw new cL.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"tlog entry signature mismatch\"});let s=e.spec.payloadHash?.value||\"\";if(!t.compareDigest(Buffer.from(s,\"hex\")))throw new cL.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"DSSE payload hash mismatch\"})}});var fbe=G(GK=>{\"use strict\";Object.defineProperty(GK,\"__esModule\",{value:!0});GK.verifyHashedRekordTLogBody=T2t;var jK=vo();function T2t(e,t){switch(e.apiVersion){case\"0.0.1\":return F2t(e,t);default:throw new jK.VerificationError({code:\"TLOG_BODY_ERROR\",message:`unsupported hashedrekord version: ${e.apiVersion}`})}}function F2t(e,t){let r=e.spec.signature.content||\"\";if(!t.compareSignature(Buffer.from(r,\"base64\")))throw new jK.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"signature mismatch\"});let s=e.spec.data.hash?.value||\"\";if(!t.compareDigest(Buffer.from(s,\"hex\")))throw new jK.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"digest mismatch\"})}});var Abe=G(qK=>{\"use strict\";Object.defineProperty(qK,\"__esModule\",{value:!0});qK.verifyIntotoTLogBody=N2t;var uL=vo();function N2t(e,t){switch(e.apiVersion){case\"0.0.2\":return O2t(e,t);default:throw new uL.VerificationError({code:\"TLOG_BODY_ERROR\",message:`unsupported intoto version: ${e.apiVersion}`})}}function O2t(e,t){if(e.spec.content.envelope.signatures?.length!==1)throw new uL.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"signature count mismatch\"});let r=L2t(e.spec.content.envelope.signatures[0].sig);if(!t.compareSignature(Buffer.from(r,\"base64\")))throw new uL.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"tlog entry signature mismatch\"});let s=e.spec.content.payloadHash?.value||\"\";if(!t.compareDigest(Buffer.from(s,\"hex\")))throw new uL.VerificationError({code:\"TLOG_BODY_ERROR\",message:\"DSSE payload hash mismatch\"})}function L2t(e){return Buffer.from(e,\"base64\").toString(\"utf-8\")}});var hbe=G(WK=>{\"use strict\";Object.defineProperty(WK,\"__esModule\",{value:!0});WK.verifyTLogBody=H2t;var pbe=vo(),M2t=ube(),U2t=fbe(),_2t=Abe();function H2t(e,t){let{kind:r,version:s}=e.kindVersion,a=JSON.parse(e.canonicalizedBody.toString(\"utf8\"));if(r!==a.kind||s!==a.apiVersion)throw new pbe.VerificationError({code:\"TLOG_BODY_ERROR\",message:`kind/version mismatch - expected: ${r}/${s}, received: ${a.kind}/${a.apiVersion}`});switch(a.kind){case\"dsse\":return(0,M2t.verifyDSSETLogBody)(a,t);case\"intoto\":return(0,_2t.verifyIntotoTLogBody)(a,t);case\"hashedrekord\":return(0,U2t.verifyHashedRekordTLogBody)(a,t);default:throw new pbe.VerificationError({code:\"TLOG_BODY_ERROR\",message:`unsupported kind: ${r}`})}}});var Ebe=G(fL=>{\"use strict\";Object.defineProperty(fL,\"__esModule\",{value:!0});fL.Verifier=void 0;var j2t=Ie(\"util\"),p1=vo(),gbe=tbe(),dbe=nbe(),mbe=cbe(),G2t=hbe(),VK=class{constructor(t,r={}){this.trustMaterial=t,this.options={ctlogThreshold:r.ctlogThreshold??1,tlogThreshold:r.tlogThreshold??1,tsaThreshold:r.tsaThreshold??0}}verify(t,r){let s=this.verifyTimestamps(t),a=this.verifySigningKey(t,s);return this.verifyTLogs(t),this.verifySignature(t,a),r&&this.verifyPolicy(r,a.identity||{}),a}verifyTimestamps(t){let r=0,s=0,a=t.timestamps.map(n=>{switch(n.$case){case\"timestamp-authority\":return s++,(0,mbe.verifyTSATimestamp)(n.timestamp,t.signature.signature,this.trustMaterial.timestampAuthorities);case\"transparency-log\":return r++,(0,mbe.verifyTLogTimestamp)(n.tlogEntry,this.trustMaterial.tlogs)}});if(ybe(a))throw new p1.VerificationError({code:\"TIMESTAMP_ERROR\",message:\"duplicate timestamp\"});if(r<this.options.tlogThreshold)throw new p1.VerificationError({code:\"TIMESTAMP_ERROR\",message:`expected ${this.options.tlogThreshold} tlog timestamps, got ${r}`});if(s<this.options.tsaThreshold)throw new p1.VerificationError({code:\"TIMESTAMP_ERROR\",message:`expected ${this.options.tsaThreshold} tsa timestamps, got ${s}`});return a.map(n=>n.timestamp)}verifySigningKey({key:t},r){switch(t.$case){case\"public-key\":return(0,gbe.verifyPublicKey)(t.hint,r,this.trustMaterial);case\"certificate\":{let s=(0,gbe.verifyCertificate)(t.certificate,r,this.trustMaterial);if(ybe(s.scts))throw new p1.VerificationError({code:\"CERTIFICATE_ERROR\",message:\"duplicate SCT\"});if(s.scts.length<this.options.ctlogThreshold)throw new p1.VerificationError({code:\"CERTIFICATE_ERROR\",message:`expected ${this.options.ctlogThreshold} SCTs, got ${s.scts.length}`});return s.signer}}}verifyTLogs({signature:t,tlogEntries:r}){r.forEach(s=>(0,G2t.verifyTLogBody)(s,t))}verifySignature(t,r){if(!t.signature.verifySignature(r.key))throw new p1.VerificationError({code:\"SIGNATURE_ERROR\",message:\"signature verification failed\"})}verifyPolicy(t,r){t.subjectAlternativeName&&(0,dbe.verifySubjectAlternativeName)(t.subjectAlternativeName,r.subjectAlternativeName),t.extensions&&(0,dbe.verifyExtensions)(t.extensions,r.extensions)}};fL.Verifier=VK;function ybe(e){for(let t=0;t<e.length;t++)for(let r=t+1;r<e.length;r++)if((0,j2t.isDeepStrictEqual)(e[t],e[r]))return!0;return!1}});var AL=G(ru=>{\"use strict\";Object.defineProperty(ru,\"__esModule\",{value:!0});ru.Verifier=ru.toTrustMaterial=ru.VerificationError=ru.PolicyError=ru.toSignedEntity=void 0;var q2t=KDe();Object.defineProperty(ru,\"toSignedEntity\",{enumerable:!0,get:function(){return q2t.toSignedEntity}});var Ibe=vo();Object.defineProperty(ru,\"PolicyError\",{enumerable:!0,get:function(){return Ibe.PolicyError}});Object.defineProperty(ru,\"VerificationError\",{enumerable:!0,get:function(){return Ibe.VerificationError}});var W2t=dy();Object.defineProperty(ru,\"toTrustMaterial\",{enumerable:!0,get:function(){return W2t.toTrustMaterial}});var V2t=Ebe();Object.defineProperty(ru,\"Verifier\",{enumerable:!0,get:function(){return V2t.Verifier}})});var Cbe=G(Ha=>{\"use strict\";Object.defineProperty(Ha,\"__esModule\",{value:!0});Ha.DEFAULT_TIMEOUT=Ha.DEFAULT_RETRY=void 0;Ha.createBundleBuilder=J2t;Ha.createKeyFinder=z2t;Ha.createVerificationPolicy=Z2t;var Y2t=bl(),h1=i7(),K2t=AL();Ha.DEFAULT_RETRY={retries:2};Ha.DEFAULT_TIMEOUT=5e3;function J2t(e,t){let r={signer:X2t(t),witnesses:evt(t)};switch(e){case\"messageSignature\":return new h1.MessageSignatureBundleBuilder(r);case\"dsseEnvelope\":return new h1.DSSEBundleBuilder({...r,certificateChain:t.legacyCompatibility})}}function z2t(e){return t=>{let r=e(t);if(!r)throw new K2t.VerificationError({code:\"PUBLIC_KEY_ERROR\",message:`key not found: ${t}`});return{publicKey:Y2t.crypto.createPublicKey(r),validFor:()=>!0}}}function Z2t(e){let t={},r=e.certificateIdentityEmail||e.certificateIdentityURI;return r&&(t.subjectAlternativeName=r),e.certificateIssuer&&(t.extensions={issuer:e.certificateIssuer}),t}function X2t(e){return new h1.FulcioSigner({fulcioBaseURL:e.fulcioURL,identityProvider:e.identityProvider||$2t(e),retry:e.retry??Ha.DEFAULT_RETRY,timeout:e.timeout??Ha.DEFAULT_TIMEOUT})}function $2t(e){let t=e.identityToken;return t?{getToken:()=>Promise.resolve(t)}:new h1.CIContextProvider(\"sigstore\")}function evt(e){let t=[];return tvt(e)&&t.push(new h1.RekorWitness({rekorBaseURL:e.rekorURL,entryType:e.legacyCompatibility?\"intoto\":\"dsse\",fetchOnConflict:!1,retry:e.retry??Ha.DEFAULT_RETRY,timeout:e.timeout??Ha.DEFAULT_TIMEOUT})),rvt(e)&&t.push(new h1.TSAWitness({tsaBaseURL:e.tsaServerURL,retry:e.retry??Ha.DEFAULT_RETRY,timeout:e.timeout??Ha.DEFAULT_TIMEOUT})),t}function tvt(e){return e.tlogUpload!==!1}function rvt(e){return e.tsaServerURL!==void 0}});var vbe=G(nu=>{\"use strict\";var nvt=nu&&nu.__createBinding||(Object.create?function(e,t,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(t,r);(!a||(\"get\"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,s,a)}:function(e,t,r,s){s===void 0&&(s=r),e[s]=t[r]}),ivt=nu&&nu.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,\"default\",{enumerable:!0,value:t})}:function(e,t){e.default=t}),wbe=nu&&nu.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(r){var s=[];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(s[s.length]=a);return s},e(t)};return function(t){if(t&&t.__esModule)return t;var r={};if(t!=null)for(var s=e(t),a=0;a<s.length;a++)s[a]!==\"default\"&&nvt(r,t,s[a]);return ivt(r,t),r}}();Object.defineProperty(nu,\"__esModule\",{value:!0});nu.sign=ovt;nu.attest=avt;nu.verify=lvt;nu.createVerifier=Bbe;var KK=Ib(),svt=wbe(XO()),YK=AL(),g1=wbe(Cbe());async function ovt(e,t={}){let s=await g1.createBundleBuilder(\"messageSignature\",t).create({data:e});return(0,KK.bundleToJSON)(s)}async function avt(e,t,r={}){let a=await g1.createBundleBuilder(\"dsseEnvelope\",r).create({data:e,type:t});return(0,KK.bundleToJSON)(a)}async function lvt(e,t,r){let s;return Buffer.isBuffer(t)?s=t:r=t,Bbe(r).then(a=>a.verify(e,s))}async function Bbe(e={}){let t=await svt.getTrustedRoot({mirrorURL:e.tufMirrorURL,rootPath:e.tufRootPath,cachePath:e.tufCachePath,forceCache:e.tufForceCache,retry:e.retry??g1.DEFAULT_RETRY,timeout:e.timeout??g1.DEFAULT_TIMEOUT}),r=e.keySelector?g1.createKeyFinder(e.keySelector):void 0,s=(0,YK.toTrustMaterial)(t,r),a={ctlogThreshold:e.ctLogThreshold,tlogThreshold:e.tlogThreshold},n=new YK.Verifier(s,a),c=g1.createVerificationPolicy(e);return{verify:(f,p)=>{let h=(0,KK.bundleFromJSON)(f),E=(0,YK.toSignedEntity)(h,p);n.verify(E,c)}}}});var Dbe=G(Ni=>{\"use strict\";Object.defineProperty(Ni,\"__esModule\",{value:!0});Ni.verify=Ni.sign=Ni.createVerifier=Ni.attest=Ni.VerificationError=Ni.PolicyError=Ni.TUFError=Ni.InternalError=Ni.DEFAULT_REKOR_URL=Ni.DEFAULT_FULCIO_URL=Ni.ValidationError=void 0;var cvt=Ib();Object.defineProperty(Ni,\"ValidationError\",{enumerable:!0,get:function(){return cvt.ValidationError}});var JK=i7();Object.defineProperty(Ni,\"DEFAULT_FULCIO_URL\",{enumerable:!0,get:function(){return JK.DEFAULT_FULCIO_URL}});Object.defineProperty(Ni,\"DEFAULT_REKOR_URL\",{enumerable:!0,get:function(){return JK.DEFAULT_REKOR_URL}});Object.defineProperty(Ni,\"InternalError\",{enumerable:!0,get:function(){return JK.InternalError}});var uvt=XO();Object.defineProperty(Ni,\"TUFError\",{enumerable:!0,get:function(){return uvt.TUFError}});var Sbe=AL();Object.defineProperty(Ni,\"PolicyError\",{enumerable:!0,get:function(){return Sbe.PolicyError}});Object.defineProperty(Ni,\"VerificationError\",{enumerable:!0,get:function(){return Sbe.VerificationError}});var pL=vbe();Object.defineProperty(Ni,\"attest\",{enumerable:!0,get:function(){return pL.attest}});Object.defineProperty(Ni,\"createVerifier\",{enumerable:!0,get:function(){return pL.createVerifier}});Object.defineProperty(Ni,\"sign\",{enumerable:!0,get:function(){return pL.sign}});Object.defineProperty(Ni,\"verify\",{enumerable:!0,get:function(){return pL.verify}})});Dt();qe();Dt();var rPe=Ie(\"child_process\"),nPe=et(Rd());Vt();var qI=new Map([]);var Gv={};Yt(Gv,{BaseCommand:()=>At,WorkspaceRequiredError:()=>ar,getCli:()=>h0e,getDynamicLibs:()=>p0e,getPluginConfiguration:()=>VI,openWorkspace:()=>WI,pluginCommands:()=>qI,runExit:()=>QT});Vt();var At=class extends at{constructor(){super(...arguments);this.cwd=he.String(\"--cwd\",{hidden:!0})}validateAndExecute(){if(typeof this.cwd<\"u\")throw new st(\"The --cwd option is ambiguous when used anywhere else than the very first parameter provided in the command line, before even the command path\");return super.validateAndExecute()}};qe();Dt();Vt();var ar=class extends st{constructor(t,r){let s=K.relative(t,r),a=K.join(t,Ut.fileName);super(`This command can only be run from within a workspace of your project (${s} isn't a workspace of ${a}).`)}};qe();Dt();rA();Bc();sv();Vt();var Qit=et(pi());ul();var p0e=()=>new Map([[\"@yarnpkg/cli\",Gv],[\"@yarnpkg/core\",jv],[\"@yarnpkg/fslib\",RB],[\"@yarnpkg/libzip\",nv],[\"@yarnpkg/parsers\",_B],[\"@yarnpkg/shell\",cv],[\"clipanion\",XB],[\"semver\",Qit],[\"typanion\",Yo]]);qe();async function WI(e,t){let{project:r,workspace:s}=await Rt.find(e,t);if(!s)throw new ar(r.cwd,t);return s}qe();Dt();rA();Bc();sv();Vt();var FSt=et(pi());ul();var Q5={};Yt(Q5,{AddCommand:()=>zI,BinCommand:()=>ZI,CacheCleanCommand:()=>XI,ClipanionCommand:()=>iC,ConfigCommand:()=>rC,ConfigGetCommand:()=>$I,ConfigSetCommand:()=>eC,ConfigUnsetCommand:()=>tC,DedupeCommand:()=>nC,EntryCommand:()=>oC,ExecCommand:()=>lC,ExplainCommand:()=>fC,ExplainPeerRequirementsCommand:()=>cC,HelpCommand:()=>sC,InfoCommand:()=>AC,LinkCommand:()=>hC,NodeCommand:()=>gC,PluginCheckCommand:()=>dC,PluginImportCommand:()=>EC,PluginImportSourcesCommand:()=>IC,PluginListCommand:()=>mC,PluginRemoveCommand:()=>CC,PluginRuntimeCommand:()=>wC,RebuildCommand:()=>BC,RemoveCommand:()=>vC,RunCommand:()=>DC,RunIndexCommand:()=>SC,SetResolutionCommand:()=>bC,SetVersionCommand:()=>uC,SetVersionSourcesCommand:()=>yC,UnlinkCommand:()=>PC,UpCommand:()=>xC,VersionCommand:()=>aC,WhyCommand:()=>kC,WorkspaceCommand:()=>NC,WorkspacesListCommand:()=>FC,YarnCommand:()=>pC,dedupeUtils:()=>_T,default:()=>Wot,suggestUtils:()=>$u});var Lde=et(Rd());qe();qe();qe();Vt();var tde=et(Yv());ul();var $u={};Yt($u,{Modifier:()=>l5,Strategy:()=>MT,Target:()=>Kv,WorkspaceModifier:()=>zge,applyModifier:()=>Zst,extractDescriptorFromPath:()=>c5,extractRangeModifier:()=>Zge,fetchDescriptorFrom:()=>u5,findProjectDescriptors:()=>ede,getModifier:()=>Jv,getSuggestedDescriptors:()=>zv,makeWorkspaceDescriptor:()=>$ge,toWorkspaceModifier:()=>Xge});qe();qe();Dt();var a5=et(pi()),Jst=\"workspace:\",Kv=(s=>(s.REGULAR=\"dependencies\",s.DEVELOPMENT=\"devDependencies\",s.PEER=\"peerDependencies\",s))(Kv||{}),l5=(s=>(s.CARET=\"^\",s.TILDE=\"~\",s.EXACT=\"\",s))(l5||{}),zge=(s=>(s.CARET=\"^\",s.TILDE=\"~\",s.EXACT=\"*\",s))(zge||{}),MT=(n=>(n.KEEP=\"keep\",n.REUSE=\"reuse\",n.PROJECT=\"project\",n.LATEST=\"latest\",n.CACHE=\"cache\",n))(MT||{});function Jv(e,t){return e.exact?\"\":e.caret?\"^\":e.tilde?\"~\":t.configuration.get(\"defaultSemverRangePrefix\")}var zst=/^([\\^~]?)[0-9]+(?:\\.[0-9]+){0,2}(?:-\\S+)?$/;function Zge(e,{project:t}){let r=e.match(zst);return r?r[1]:t.configuration.get(\"defaultSemverRangePrefix\")}function Zst(e,t){let{protocol:r,source:s,params:a,selector:n}=j.parseRange(e.range);return a5.default.valid(n)&&(n=`${t}${e.range}`),j.makeDescriptor(e,j.makeRange({protocol:r,source:s,params:a,selector:n}))}function Xge(e){switch(e){case\"^\":return\"^\";case\"~\":return\"~\";case\"\":return\"*\";default:throw new Error(`Assertion failed: Unknown modifier: \"${e}\"`)}}function $ge(e,t){return j.makeDescriptor(e.anchoredDescriptor,`${Jst}${Xge(t)}`)}async function ede(e,{project:t,target:r}){let s=new Map,a=n=>{let c=s.get(n.descriptorHash);return c||s.set(n.descriptorHash,c={descriptor:n,locators:[]}),c};for(let n of t.workspaces)if(r===\"peerDependencies\"){let c=n.manifest.peerDependencies.get(e.identHash);c!==void 0&&a(c).locators.push(n.anchoredLocator)}else{let c=n.manifest.dependencies.get(e.identHash),f=n.manifest.devDependencies.get(e.identHash);r===\"devDependencies\"?f!==void 0?a(f).locators.push(n.anchoredLocator):c!==void 0&&a(c).locators.push(n.anchoredLocator):c!==void 0?a(c).locators.push(n.anchoredLocator):f!==void 0&&a(f).locators.push(n.anchoredLocator)}return s}async function c5(e,{cwd:t,workspace:r}){return await $st(async s=>{K.isAbsolute(e)||(e=K.relative(r.cwd,K.resolve(t,e)),e.match(/^\\.{0,2}\\//)||(e=`./${e}`));let{project:a}=r,n=await u5(j.makeIdent(null,\"archive\"),e,{project:r.project,cache:s,workspace:r});if(!n)throw new Error(\"Assertion failed: The descriptor should have been found\");let c=new ki,f=a.configuration.makeResolver(),p=a.configuration.makeFetcher(),h={checksums:a.storedChecksums,project:a,cache:s,fetcher:p,report:c,resolver:f},E=f.bindDescriptor(n,r.anchoredLocator,h),C=j.convertDescriptorToLocator(E),S=await p.fetch(C,h),x=await Ut.find(S.prefixPath,{baseFs:S.packageFs});if(!x.name)throw new Error(\"Target path doesn't have a name\");return j.makeDescriptor(x.name,e)})}function Xst(e){if(e.range===\"unknown\")return{type:\"resolve\",range:\"latest\"};if(Fr.validRange(e.range))return{type:\"fixed\",range:e.range};if(Up.test(e.range))return{type:\"resolve\",range:e.range};let t=e.range.match(/^(?:jsr:|npm:)(.*)/);if(!t)return{type:\"fixed\",range:e.range};let[,r]=t,s=`${j.stringifyIdent(e)}@`;return r.startsWith(s)&&(r=r.slice(s.length)),Fr.validRange(r)?{type:\"fixed\",range:e.range}:Up.test(r)?{type:\"resolve\",range:e.range}:{type:\"fixed\",range:e.range}}async function zv(e,{project:t,workspace:r,cache:s,target:a,fixed:n,modifier:c,strategies:f,maxResults:p=1/0}){if(!(p>=0))throw new Error(`Invalid maxResults (${p})`);let h=!n||e.range===\"unknown\"?Xst(e):{type:\"fixed\",range:e.range};if(h.type===\"fixed\")return{suggestions:[{descriptor:e,name:`Use ${j.prettyDescriptor(t.configuration,e)}`,reason:\"(unambiguous explicit request)\"}],rejections:[]};let E=typeof r<\"u\"&&r!==null&&r.manifest[a].get(e.identHash)||null,C=[],S=[],x=async I=>{try{await I()}catch(T){S.push(T)}};for(let I of f){if(C.length>=p)break;switch(I){case\"keep\":await x(async()=>{E&&C.push({descriptor:E,name:`Keep ${j.prettyDescriptor(t.configuration,E)}`,reason:\"(no changes)\"})});break;case\"reuse\":await x(async()=>{for(let{descriptor:T,locators:O}of(await ede(e,{project:t,target:a})).values()){if(O.length===1&&O[0].locatorHash===r.anchoredLocator.locatorHash&&f.includes(\"keep\"))continue;let U=`(originally used by ${j.prettyLocator(t.configuration,O[0])}`;U+=O.length>1?` and ${O.length-1} other${O.length>2?\"s\":\"\"})`:\")\",C.push({descriptor:T,name:`Reuse ${j.prettyDescriptor(t.configuration,T)}`,reason:U})}});break;case\"cache\":await x(async()=>{for(let T of t.storedDescriptors.values())T.identHash===e.identHash&&C.push({descriptor:T,name:`Reuse ${j.prettyDescriptor(t.configuration,T)}`,reason:\"(already used somewhere in the lockfile)\"})});break;case\"project\":await x(async()=>{if(r.manifest.name!==null&&e.identHash===r.manifest.name.identHash)return;let T=t.tryWorkspaceByIdent(e);if(T===null)return;let O=$ge(T,c);C.push({descriptor:O,name:`Attach ${j.prettyDescriptor(t.configuration,O)}`,reason:`(local workspace at ${pe.pretty(t.configuration,T.relativeCwd,pe.Type.PATH)})`})});break;case\"latest\":{let T=t.configuration.get(\"enableNetwork\"),O=t.configuration.get(\"enableOfflineMode\");await x(async()=>{if(a===\"peerDependencies\")C.push({descriptor:j.makeDescriptor(e,\"*\"),name:\"Use *\",reason:\"(catch-all peer dependency pattern)\"});else if(!T&&!O)C.push({descriptor:null,name:\"Resolve from latest\",reason:pe.pretty(t.configuration,\"(unavailable because enableNetwork is toggled off)\",\"grey\")});else{let U=await u5(e,h.range,{project:t,cache:s,workspace:r,modifier:c});U&&C.push({descriptor:U,name:`Use ${j.prettyDescriptor(t.configuration,U)}`,reason:`(resolved from ${O?\"the cache\":\"latest\"})`})}})}break}}return{suggestions:C.slice(0,p),rejections:S.slice(0,p)}}async function u5(e,t,{project:r,cache:s,workspace:a,preserveModifier:n=!0,modifier:c}){let f=r.configuration.normalizeDependency(j.makeDescriptor(e,t)),p=new ki,h=r.configuration.makeFetcher(),E=r.configuration.makeResolver(),C={project:r,fetcher:h,cache:s,checksums:r.storedChecksums,report:p,cacheOptions:{skipIntegrityCheck:!0}},S={...C,resolver:E,fetchOptions:C},x=E.bindDescriptor(f,a.anchoredLocator,S),I=await E.getCandidates(x,{},S);if(I.length===0)return null;let T=I[0],{protocol:O,source:U,params:Y,selector:te}=j.parseRange(j.convertToManifestRange(T.reference));if(O===r.configuration.get(\"defaultProtocol\")&&(O=null),a5.default.valid(te)){let ie=te;if(typeof c<\"u\")te=c+te;else if(n!==!1){let de=typeof n==\"string\"?n:f.range;te=Zge(de,{project:r})+te}let ue=j.makeDescriptor(T,j.makeRange({protocol:O,source:U,params:Y,selector:te}));(await E.getCandidates(r.configuration.normalizeDependency(ue),{},S)).length!==1&&(te=ie)}return j.makeDescriptor(T,j.makeRange({protocol:O,source:U,params:Y,selector:te}))}async function $st(e){return await le.mktempPromise(async t=>{let r=ze.create(t);return r.useWithSource(t,{enableMirror:!1,compressionLevel:0},t,{overwrite:!0}),await e(new Jr(t,{configuration:r,check:!1,immutable:!1}))})}var zI=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.fixed=he.Boolean(\"-F,--fixed\",!1,{description:\"Store dependency tags as-is instead of resolving them\"});this.exact=he.Boolean(\"-E,--exact\",!1,{description:\"Don't use any semver modifier on the resolved range\"});this.tilde=he.Boolean(\"-T,--tilde\",!1,{description:\"Use the `~` semver modifier on the resolved range\"});this.caret=he.Boolean(\"-C,--caret\",!1,{description:\"Use the `^` semver modifier on the resolved range\"});this.dev=he.Boolean(\"-D,--dev\",!1,{description:\"Add a package as a dev dependency\"});this.peer=he.Boolean(\"-P,--peer\",!1,{description:\"Add a package as a peer dependency\"});this.optional=he.Boolean(\"-O,--optional\",!1,{description:\"Add / upgrade a package to an optional regular / peer dependency\"});this.preferDev=he.Boolean(\"--prefer-dev\",!1,{description:\"Add / upgrade a package to a dev dependency\"});this.interactive=he.Boolean(\"-i,--interactive\",{description:\"Reuse the specified package from other workspaces in the project\"});this.cached=he.Boolean(\"--cached\",!1,{description:\"Reuse the highest version already used somewhere within the project\"});this.mode=he.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:ks(Na)});this.silent=he.Boolean(\"--silent\",{hidden:!0});this.packages=he.Rest()}static{this.paths=[[\"add\"]]}static{this.usage=at.Usage({description:\"add dependencies to the project\",details:\"\\n      This command adds a package to the package.json for the nearest workspace.\\n\\n      - If it didn't exist before, the package will by default be added to the regular `dependencies` field, but this behavior can be overriden thanks to the `-D,--dev` flag (which will cause the dependency to be added to the `devDependencies` field instead) and the `-P,--peer` flag (which will do the same but for `peerDependencies`).\\n\\n      - If the package was already listed in your dependencies, it will by default be upgraded whether it's part of your `dependencies` or `devDependencies` (it won't ever update `peerDependencies`, though).\\n\\n      - If set, the `--prefer-dev` flag will operate as a more flexible `-D,--dev` in that it will add the package to your `devDependencies` if it isn't already listed in either `dependencies` or `devDependencies`, but it will also happily upgrade your `dependencies` if that's what you already use (whereas `-D,--dev` would throw an exception).\\n\\n      - If set, the `-O,--optional` flag will add the package to the `optionalDependencies` field and, in combination with the `-P,--peer` flag, it will add the package as an optional peer dependency. If the package was already listed in your `dependencies`, it will be upgraded to `optionalDependencies`. If the package was already listed in your `peerDependencies`, in combination with the `-P,--peer` flag, it will be upgraded to an optional peer dependency: `\\\"peerDependenciesMeta\\\": { \\\"<package>\\\": { \\\"optional\\\": true } }`\\n\\n      - If the added package doesn't specify a range at all its `latest` tag will be resolved and the returned version will be used to generate a new semver range (using the `^` modifier by default unless otherwise configured via the `defaultSemverRangePrefix` configuration, or the `~` modifier if `-T,--tilde` is specified, or no modifier at all if `-E,--exact` is specified). Two exceptions to this rule: the first one is that if the package is a workspace then its local version will be used, and the second one is that if you use `-P,--peer` the default range will be `*` and won't be resolved at all.\\n\\n      - If the added package specifies a range (such as `^1.0.0`, `latest`, or `rc`), Yarn will add this range as-is in the resulting package.json entry (in particular, tags such as `rc` will be encoded as-is rather than being converted into a semver range).\\n\\n      If the `--cached` option is used, Yarn will preferably reuse the highest version already used somewhere within the project, even if through a transitive dependency.\\n\\n      If the `-i,--interactive` option is used (or if the `preferInteractive` settings is toggled on) the command will first try to check whether other workspaces in the project use the specified package and, if so, will offer to reuse them.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n\\n      For a compilation of all the supported protocols, please consult the dedicated page from our website: https://yarnpkg.com/protocols.\\n    \",examples:[[\"Add a regular package to the current workspace\",\"$0 add lodash\"],[\"Add a specific version for a package to the current workspace\",\"$0 add lodash@1.2.3\"],[\"Add a package from a GitHub repository (the master branch) to the current workspace using a URL\",\"$0 add lodash@https://github.com/lodash/lodash\"],[\"Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol\",\"$0 add lodash@github:lodash/lodash\"],[\"Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol (shorthand)\",\"$0 add lodash@lodash/lodash\"],[\"Add a package from a specific branch of a GitHub repository to the current workspace using the GitHub protocol (shorthand)\",\"$0 add lodash-es@lodash/lodash#es\"],[\"Add a local package (gzipped tarball format) to the current workspace\",\"$0 add local-package-name@file:../path/to/local-package-name-v0.1.2.tgz\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let c=this.fixed,f=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=f||r.get(\"preferReuse\"),h=Jv(this,s),E=[p?\"reuse\":void 0,\"project\",this.cached?\"cache\":void 0,\"latest\"].filter(Y=>typeof Y<\"u\"),C=f?1/0:1,S=Y=>{let te=j.tryParseDescriptor(Y.slice(4));return te?te.range===\"unknown\"?j.makeDescriptor(te,`jsr:${j.stringifyIdent(te)}@latest`):j.makeDescriptor(te,`jsr:${te.range}`):null},x=await Promise.all(this.packages.map(async Y=>{let te=Y.match(/^\\.{0,2}\\//)?await c5(Y,{cwd:this.context.cwd,workspace:a}):Y.startsWith(\"jsr:\")?S(Y):j.tryParseDescriptor(Y),ie=Y.match(/^(https?:|git@github)/);if(ie)throw new st(`It seems you are trying to add a package using a ${pe.pretty(r,`${ie[0]}...`,pe.Type.RANGE)} url; we now require package names to be explicitly specified.\nTry running the command again with the package name prefixed: ${pe.pretty(r,\"yarn add\",pe.Type.CODE)} ${pe.pretty(r,j.makeDescriptor(j.makeIdent(null,\"my-package\"),`${ie[0]}...`),pe.Type.DESCRIPTOR)}`);if(!te)throw new st(`The ${pe.pretty(r,Y,pe.Type.CODE)} string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name?`);let ue=eot(a,te,{dev:this.dev,peer:this.peer,preferDev:this.preferDev,optional:this.optional});return await Promise.all(ue.map(async de=>{let Ae=await zv(te,{project:s,workspace:a,cache:n,fixed:c,target:de,modifier:h,strategies:E,maxResults:C});return{request:te,suggestedDescriptors:Ae,target:de}}))})).then(Y=>Y.flat()),I=await cA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async Y=>{for(let{request:te,suggestedDescriptors:{suggestions:ie,rejections:ue}}of x)if(ie.filter(de=>de.descriptor!==null).length===0){let[de]=ue;if(typeof de>\"u\")throw new Error(\"Assertion failed: Expected an error to have been set\");s.configuration.get(\"enableNetwork\")?Y.reportError(27,`${j.prettyDescriptor(r,te)} can't be resolved to a satisfying range`):Y.reportError(27,`${j.prettyDescriptor(r,te)} can't be resolved to a satisfying range (note: network resolution has been disabled)`),Y.reportSeparator(),Y.reportExceptionOnce(de)}});if(I.hasErrors())return I.exitCode();let T=!1,O=[],U=[];for(let{suggestedDescriptors:{suggestions:Y},target:te}of x){let ie,ue=Y.filter(Ce=>Ce.descriptor!==null),ae=ue[0].descriptor,de=ue.every(Ce=>j.areDescriptorsEqual(Ce.descriptor,ae));ue.length===1||de?ie=ae:(T=!0,{answer:ie}=await(0,tde.prompt)({type:\"select\",name:\"answer\",message:\"Which range do you want to use?\",choices:Y.map(({descriptor:Ce,name:Ee,reason:g})=>Ce?{name:Ee,hint:g,descriptor:Ce}:{name:Ee,hint:g,disabled:!0}),onCancel:()=>process.exit(130),result(Ce){return this.find(Ce,\"descriptor\")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ae=a.manifest[te].get(ie.identHash);(typeof Ae>\"u\"||Ae.descriptorHash!==ie.descriptorHash)&&(a.manifest[te].set(ie.identHash,ie),this.optional&&(te===\"dependencies\"?a.manifest.ensureDependencyMeta({...ie,range:\"unknown\"}).optional=!0:te===\"peerDependencies\"&&(a.manifest.ensurePeerDependencyMeta({...ie,range:\"unknown\"}).optional=!0)),typeof Ae>\"u\"?O.push([a,te,ie,E]):U.push([a,te,Ae,ie]))}return await r.triggerMultipleHooks(Y=>Y.afterWorkspaceDependencyAddition,O),await r.triggerMultipleHooks(Y=>Y.afterWorkspaceDependencyReplacement,U),T&&this.context.stdout.write(`\n`),await s.installWithNewReport({json:this.json,stdout:this.context.stdout,quiet:this.context.quiet},{cache:n,mode:this.mode})}};function eot(e,t,{dev:r,peer:s,preferDev:a,optional:n}){let c=e.manifest.dependencies.has(t.identHash),f=e.manifest.devDependencies.has(t.identHash),p=e.manifest.peerDependencies.has(t.identHash);if((r||s)&&c)throw new st(`Package \"${j.prettyIdent(e.project.configuration,t)}\" is already listed as a regular dependency - remove the -D,-P flags or remove it from your dependencies first`);if(!r&&!s&&p)throw new st(`Package \"${j.prettyIdent(e.project.configuration,t)}\" is already listed as a peer dependency - use either of -D or -P, or remove it from your peer dependencies first`);if(n&&f)throw new st(`Package \"${j.prettyIdent(e.project.configuration,t)}\" is already listed as a dev dependency - remove the -O flag or remove it from your dev dependencies first`);if(n&&!s&&p)throw new st(`Package \"${j.prettyIdent(e.project.configuration,t)}\" is already listed as a peer dependency - remove the -O flag or add the -P flag or remove it from your peer dependencies first`);if((r||a)&&n)throw new st(`Package \"${j.prettyIdent(e.project.configuration,t)}\" cannot simultaneously be a dev dependency and an optional dependency`);let h=[];return s&&h.push(\"peerDependencies\"),(r||a)&&h.push(\"devDependencies\"),n&&h.push(\"dependencies\"),h.length>0?h:f?[\"devDependencies\"]:p?[\"peerDependencies\"]:[\"dependencies\"]}qe();qe();Vt();var ZI=class extends At{constructor(){super(...arguments);this.verbose=he.Boolean(\"-v,--verbose\",!1,{description:\"Print both the binary name and the locator of the package that provides the binary\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.name=he.String({required:!1})}static{this.paths=[[\"bin\"]]}static{this.usage=at.Usage({description:\"get the path to a binary script\",details:`\n      When used without arguments, this command will print the list of all the binaries available in the current workspace. Adding the \\`-v,--verbose\\` flag will cause the output to contain both the binary name and the locator of the package that provides the binary.\n\n      When an argument is specified, this command will just print the path to the binary on the standard output and exit. Note that the reported path may be stored within a zip archive.\n    `,examples:[[\"List all the available binaries\",\"$0 bin\"],[\"Print the path to a specific binary\",\"$0 bin eslint\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,locator:a}=await Rt.find(r,this.context.cwd);if(await s.restoreInstallState(),this.name){let f=(await Cn.getPackageAccessibleBinaries(a,{project:s})).get(this.name);if(!f)throw new st(`Couldn't find a binary named \"${this.name}\" for package \"${j.prettyLocator(r,a)}\"`);let[,p]=f;return this.context.stdout.write(`${p}\n`),0}return(await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async c=>{let f=await Cn.getPackageAccessibleBinaries(a,{project:s}),h=Array.from(f.keys()).reduce((E,C)=>Math.max(E,C.length),0);for(let[E,[C,S]]of f)c.reportJson({name:E,source:j.stringifyIdent(C),path:S});if(this.verbose)for(let[E,[C]]of f)c.reportInfo(null,`${E.padEnd(h,\" \")}   ${j.prettyLocator(r,C)}`);else for(let E of f.keys())c.reportInfo(null,E)})).exitCode()}};qe();Dt();Vt();var XI=class extends At{constructor(){super(...arguments);this.mirror=he.Boolean(\"--mirror\",!1,{description:\"Remove the global cache files instead of the local cache files\"});this.all=he.Boolean(\"--all\",!1,{description:\"Remove both the global cache files and the local cache files of the current project\"})}static{this.paths=[[\"cache\",\"clean\"],[\"cache\",\"clear\"]]}static{this.usage=at.Usage({description:\"remove the shared cache files\",details:`\n      This command will remove all the files from the cache.\n    `,examples:[[\"Remove all the local archives\",\"$0 cache clean\"],[\"Remove all the archives stored in the ~/.yarn directory\",\"$0 cache clean --mirror\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);if(!r.get(\"enableCacheClean\"))throw new st(\"Cache cleaning is currently disabled. To enable it, set `enableCacheClean: true` in your configuration file. Note: Cache cleaning is typically not required and should be avoided when using Zero-Installs.\");let s=await Jr.find(r);return(await Ot.start({configuration:r,stdout:this.context.stdout},async()=>{let n=(this.all||this.mirror)&&s.mirrorCwd!==null,c=!this.mirror;n&&(await le.removePromise(s.mirrorCwd),await r.triggerHook(f=>f.cleanGlobalArtifacts,r)),c&&await le.removePromise(s.cwd)})).exitCode()}};qe();Vt();Jl();var f5=Ie(\"util\"),$I=class extends At{constructor(){super(...arguments);this.why=he.Boolean(\"--why\",!1,{description:\"Print the explanation for why a setting has its value\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.unsafe=he.Boolean(\"--no-redacted\",!1,{description:\"Don't redact secrets (such as tokens) from the output\"});this.name=he.String()}static{this.paths=[[\"config\",\"get\"]]}static{this.usage=at.Usage({description:\"read a configuration settings\",details:`\n      This command will print a configuration setting.\n\n      Secrets (such as tokens) will be redacted from the output by default. If this behavior isn't desired, set the \\`--no-redacted\\` to get the untransformed value.\n    `,examples:[[\"Print a simple configuration setting\",\"yarn config get yarnPath\"],[\"Print a complex configuration setting\",\"yarn config get packageExtensions\"],[\"Print a nested field from the configuration\",`yarn config get 'npmScopes[\"my-company\"].npmRegistryServer'`],[\"Print a token from the configuration\",\"yarn config get npmAuthToken --no-redacted\"],[\"Print a configuration setting as JSON\",\"yarn config get packageExtensions --json\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=this.name.replace(/[.[].*$/,\"\"),a=this.name.replace(/^[^.[]*/,\"\");if(typeof r.settings.get(s)>\"u\")throw new st(`Couldn't find a configuration settings named \"${s}\"`);let c=r.getSpecial(s,{hideSecrets:!this.unsafe,getNativePaths:!0}),f=Ge.convertMapsToIndexableObjects(c),p=a?ba(f,a):f,h=await Ot.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async E=>{E.reportJson(p)});if(!this.json){if(typeof p==\"string\")return this.context.stdout.write(`${p}\n`),h.exitCode();f5.inspect.styles.name=\"cyan\",this.context.stdout.write(`${(0,f5.inspect)(p,{depth:1/0,colors:r.get(\"enableColors\"),compact:!1})}\n`)}return h.exitCode()}};qe();Vt();Jl();var A5=Ie(\"util\"),eC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Set complex configuration settings to JSON values\"});this.home=he.Boolean(\"-H,--home\",!1,{description:\"Update the home configuration instead of the project configuration\"});this.name=he.String();this.value=he.String()}static{this.paths=[[\"config\",\"set\"]]}static{this.usage=at.Usage({description:\"change a configuration settings\",details:`\n      This command will set a configuration setting.\n\n      When used without the \\`--json\\` flag, it can only set a simple configuration setting (a string, a number, or a boolean).\n\n      When used with the \\`--json\\` flag, it can set both simple and complex configuration settings, including Arrays and Objects.\n    `,examples:[[\"Set a simple configuration setting (a string, a number, or a boolean)\",\"yarn config set initScope myScope\"],[\"Set a simple configuration setting (a string, a number, or a boolean) using the `--json` flag\",'yarn config set initScope --json \\\\\"myScope\\\\\"'],[\"Set a complex configuration setting (an Array) using the `--json` flag\",`yarn config set unsafeHttpWhitelist --json '[\"*.example.com\", \"example.com\"]'`],[\"Set a complex configuration setting (an Object) using the `--json` flag\",`yarn config set packageExtensions --json '{ \"@babel/parser@*\": { \"dependencies\": { \"@babel/types\": \"*\" } } }'`],[\"Set a nested configuration setting\",'yarn config set npmScopes.company.npmRegistryServer \"https://npm.example.com\"'],[\"Set a nested configuration setting using indexed access for non-simple keys\",`yarn config set 'npmRegistries[\"//npm.example.com\"].npmAuthToken' \"ffffffff-ffff-ffff-ffff-ffffffffffff\"`]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=()=>{if(!r.projectCwd)throw new st(\"This command must be run from within a project folder\");return r.projectCwd},a=this.name.replace(/[.[].*$/,\"\"),n=this.name.replace(/^[^.[]*\\.?/,\"\");if(typeof r.settings.get(a)>\"u\")throw new st(`Couldn't find a configuration settings named \"${a}\"`);if(a===\"enableStrictSettings\")throw new st(\"This setting only affects the file it's in, and thus cannot be set from the CLI\");let f=this.json?JSON.parse(this.value):this.value;await(this.home?I=>ze.updateHomeConfiguration(I):I=>ze.updateConfiguration(s(),I))(I=>{if(n){let T=c0(I);return Vd(T,this.name,f),T}else return{...I,[a]:f}});let E=(await ze.find(this.context.cwd,this.context.plugins)).getSpecial(a,{hideSecrets:!0,getNativePaths:!0}),C=Ge.convertMapsToIndexableObjects(E),S=n?ba(C,n):C;return(await Ot.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async I=>{A5.inspect.styles.name=\"cyan\",I.reportInfo(0,`Successfully set ${this.name} to ${(0,A5.inspect)(S,{depth:1/0,colors:r.get(\"enableColors\"),compact:!1})}`)})).exitCode()}};qe();Vt();Jl();var tC=class extends At{constructor(){super(...arguments);this.home=he.Boolean(\"-H,--home\",!1,{description:\"Update the home configuration instead of the project configuration\"});this.name=he.String()}static{this.paths=[[\"config\",\"unset\"]]}static{this.usage=at.Usage({description:\"unset a configuration setting\",details:`\n      This command will unset a configuration setting.\n    `,examples:[[\"Unset a simple configuration setting\",\"yarn config unset initScope\"],[\"Unset a complex configuration setting\",\"yarn config unset packageExtensions\"],[\"Unset a nested configuration setting\",\"yarn config unset npmScopes.company.npmRegistryServer\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=()=>{if(!r.projectCwd)throw new st(\"This command must be run from within a project folder\");return r.projectCwd},a=this.name.replace(/[.[].*$/,\"\"),n=this.name.replace(/^[^.[]*\\.?/,\"\");if(typeof r.settings.get(a)>\"u\")throw new st(`Couldn't find a configuration settings named \"${a}\"`);let f=this.home?h=>ze.updateHomeConfiguration(h):h=>ze.updateConfiguration(s(),h);return(await Ot.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async h=>{let E=!1;await f(C=>{if(!d2(C,this.name))return h.reportWarning(0,`Configuration doesn't contain setting ${this.name}; there is nothing to unset`),E=!0,C;let S=n?c0(C):{...C};return u0(S,this.name),S}),E||h.reportInfo(0,`Successfully unset ${this.name}`)})).exitCode()}};qe();Dt();Vt();var UT=Ie(\"util\"),rC=class extends At{constructor(){super(...arguments);this.noDefaults=he.Boolean(\"--no-defaults\",!1,{description:\"Omit the default values from the display\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.verbose=he.Boolean(\"-v,--verbose\",{hidden:!0});this.why=he.Boolean(\"--why\",{hidden:!0});this.names=he.Rest()}static{this.paths=[[\"config\"]]}static{this.usage=at.Usage({description:\"display the current configuration\",details:`\n      This command prints the current active configuration settings.\n    `,examples:[[\"Print the active configuration settings\",\"$0 config\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins,{strict:!1}),s=await PI({configuration:r,stdout:this.context.stdout,forceError:this.json},[{option:this.verbose,message:\"The --verbose option is deprecated, the settings' descriptions are now always displayed\"},{option:this.why,message:\"The --why option is deprecated, the settings' sources are now always displayed\"}]);if(s!==null)return s;let a=this.names.length>0?[...new Set(this.names)].sort():[...r.settings.keys()].sort(),n,c=await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async f=>{if(r.invalid.size>0&&!this.json){for(let[p,h]of r.invalid)f.reportError(34,`Invalid configuration key \"${p}\" in ${h}`);f.reportSeparator()}if(this.json)for(let p of a){if(this.noDefaults&&!r.sources.has(p))continue;let h=r.settings.get(p);typeof h>\"u\"&&f.reportError(34,`No configuration key named \"${p}\"`);let E=r.getSpecial(p,{hideSecrets:!0,getNativePaths:!0}),C=r.sources.get(p)??\"<default>\",S=C&&C[0]!==\"<\"?fe.fromPortablePath(C):C;f.reportJson({key:p,effective:E,source:S,...h})}else{let p={breakLength:1/0,colors:r.get(\"enableColors\"),maxArrayLength:2},h={},E={children:h};for(let C of a){if(this.noDefaults&&!r.sources.has(C))continue;let S=r.settings.get(C),x=r.sources.get(C)??\"<default>\",I=r.getSpecial(C,{hideSecrets:!0,getNativePaths:!0}),T={Description:{label:\"Description\",value:pe.tuple(pe.Type.MARKDOWN,{text:S.description,format:this.cli.format(),paragraphs:!1})},Source:{label:\"Source\",value:pe.tuple(x[0]===\"<\"?pe.Type.CODE:pe.Type.PATH,x)}};h[C]={value:pe.tuple(pe.Type.CODE,C),children:T};let O=(U,Y)=>{for(let[te,ie]of Y)if(ie instanceof Map){let ue={};U[te]={children:ue},O(ue,ie)}else U[te]={label:te,value:pe.tuple(pe.Type.NO_HINT,(0,UT.inspect)(ie,p))}};I instanceof Map?O(T,I):T.Value={label:\"Value\",value:pe.tuple(pe.Type.NO_HINT,(0,UT.inspect)(I,p))}}a.length!==1&&(n=void 0),Rs.emitTree(E,{configuration:r,json:this.json,stdout:this.context.stdout,separators:2})}});if(!this.json&&typeof n<\"u\"){let f=a[0],p=(0,UT.inspect)(r.getSpecial(f,{hideSecrets:!0,getNativePaths:!0}),{colors:r.get(\"enableColors\")});this.context.stdout.write(`\n`),this.context.stdout.write(`${p}\n`)}return c.exitCode()}};qe();Vt();ul();var _T={};Yt(_T,{Strategy:()=>Zv,acceptedStrategies:()=>tot,dedupe:()=>p5});qe();qe();var rde=et(Jo()),Zv=(t=>(t.HIGHEST=\"highest\",t))(Zv||{}),tot=new Set(Object.values(Zv)),rot={highest:async(e,t,{resolver:r,fetcher:s,resolveOptions:a,fetchOptions:n})=>{let c=new Map;for(let[p,h]of e.storedResolutions){let E=e.storedDescriptors.get(p);if(typeof E>\"u\")throw new Error(`Assertion failed: The descriptor (${p}) should have been registered`);Ge.getSetWithDefault(c,E.identHash).add(h)}let f=new Map(Ge.mapAndFilter(e.storedDescriptors.values(),p=>j.isVirtualDescriptor(p)?Ge.mapAndFilter.skip:[p.descriptorHash,Ge.makeDeferred()]));for(let p of e.storedDescriptors.values()){let h=f.get(p.descriptorHash);if(typeof h>\"u\")throw new Error(`Assertion failed: The descriptor (${p.descriptorHash}) should have been registered`);let E=e.storedResolutions.get(p.descriptorHash);if(typeof E>\"u\")throw new Error(`Assertion failed: The resolution (${p.descriptorHash}) should have been registered`);let C=e.originalPackages.get(E);if(typeof C>\"u\")throw new Error(`Assertion failed: The package (${E}) should have been registered`);Promise.resolve().then(async()=>{let S=r.getResolutionDependencies(p,a),x=Object.fromEntries(await Ge.allSettledSafe(Object.entries(S).map(async([te,ie])=>{let ue=f.get(ie.descriptorHash);if(typeof ue>\"u\")throw new Error(`Assertion failed: The descriptor (${ie.descriptorHash}) should have been registered`);let ae=await ue.promise;if(!ae)throw new Error(\"Assertion failed: Expected the dependency to have been through the dedupe process itself\");return[te,ae.updatedPackage]})));if(t.length&&!rde.default.isMatch(j.stringifyIdent(p),t)||!r.shouldPersistResolution(C,a))return C;let I=c.get(p.identHash);if(typeof I>\"u\")throw new Error(`Assertion failed: The resolutions (${p.identHash}) should have been registered`);if(I.size===1)return C;let T=[...I].map(te=>{let ie=e.originalPackages.get(te);if(typeof ie>\"u\")throw new Error(`Assertion failed: The package (${te}) should have been registered`);return ie}),O=await r.getSatisfying(p,x,T,a),U=O.locators?.[0];if(typeof U>\"u\"||!O.sorted)return C;let Y=e.originalPackages.get(U.locatorHash);if(typeof Y>\"u\")throw new Error(`Assertion failed: The package (${U.locatorHash}) should have been registered`);return Y}).then(async S=>{let x=await e.preparePackage(S,{resolver:r,resolveOptions:a});h.resolve({descriptor:p,currentPackage:C,updatedPackage:S,resolvedPackage:x})}).catch(S=>{h.reject(S)})}return[...f.values()].map(p=>p.promise)}};async function p5(e,{strategy:t,patterns:r,cache:s,report:a}){let{configuration:n}=e,c=new ki,f=n.makeResolver(),p=n.makeFetcher(),h={cache:s,checksums:e.storedChecksums,fetcher:p,project:e,report:c,cacheOptions:{skipIntegrityCheck:!0}},E={project:e,resolver:f,report:c,fetchOptions:h};return await a.startTimerPromise(\"Deduplication step\",async()=>{let C=rot[t],S=await C(e,r,{resolver:f,resolveOptions:E,fetcher:p,fetchOptions:h}),x=yo.progressViaCounter(S.length);await a.reportProgress(x);let I=0;await Promise.all(S.map(U=>U.then(Y=>{if(Y===null||Y.currentPackage.locatorHash===Y.updatedPackage.locatorHash)return;I++;let{descriptor:te,currentPackage:ie,updatedPackage:ue}=Y;a.reportInfo(0,`${j.prettyDescriptor(n,te)} can be deduped from ${j.prettyLocator(n,ie)} to ${j.prettyLocator(n,ue)}`),a.reportJson({descriptor:j.stringifyDescriptor(te),currentResolution:j.stringifyLocator(ie),updatedResolution:j.stringifyLocator(ue)}),e.storedResolutions.set(te.descriptorHash,ue.locatorHash)}).finally(()=>x.tick())));let T;switch(I){case 0:T=\"No packages\";break;case 1:T=\"One package\";break;default:T=`${I} packages`}let O=pe.pretty(n,t,pe.Type.CODE);return a.reportInfo(0,`${T} can be deduped using the ${O} strategy`),I})}var nC=class extends At{constructor(){super(...arguments);this.strategy=he.String(\"-s,--strategy\",\"highest\",{description:\"The strategy to use when deduping dependencies\",validator:ks(Zv)});this.check=he.Boolean(\"-c,--check\",!1,{description:\"Exit with exit code 1 when duplicates are found, without persisting the dependency tree\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.mode=he.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:ks(Na)});this.patterns=he.Rest()}static{this.paths=[[\"dedupe\"]]}static{this.usage=at.Usage({description:\"deduplicate dependencies with overlapping ranges\",details:\"\\n      Duplicates are defined as descriptors with overlapping ranges being resolved and locked to different locators. They are a natural consequence of Yarn's deterministic installs, but they can sometimes pile up and unnecessarily increase the size of your project.\\n\\n      This command dedupes dependencies in the current project using different strategies (only one is implemented at the moment):\\n\\n      - `highest`: Reuses (where possible) the locators with the highest versions. This means that dependencies can only be upgraded, never downgraded. It's also guaranteed that it never takes more than a single pass to dedupe the entire dependency tree.\\n\\n      **Note:** Even though it never produces a wrong dependency tree, this command should be used with caution, as it modifies the dependency tree, which can sometimes cause problems when packages don't strictly follow semver recommendations. Because of this, it is recommended to also review the changes manually.\\n\\n      If set, the `-c,--check` flag will only report the found duplicates, without persisting the modified dependency tree. If changes are found, the command will exit with a non-zero exit code, making it suitable for CI purposes.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n\\n      This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\\n\\n      ### In-depth explanation:\\n\\n      Yarn doesn't deduplicate dependencies by default, otherwise installs wouldn't be deterministic and the lockfile would be useless. What it actually does is that it tries to not duplicate dependencies in the first place.\\n\\n      **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@*`will cause Yarn to reuse `foo@2.3.4`, even if the latest `foo` is actually `foo@2.10.14`, thus preventing unnecessary duplication.\\n\\n      Duplication happens when Yarn can't unlock dependencies that have already been locked inside the lockfile.\\n\\n      **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@2.10.14` will cause Yarn to install `foo@2.10.14` because the existing resolution doesn't satisfy the range `2.10.14`. This behavior can lead to (sometimes) unwanted duplication, since now the lockfile contains 2 separate resolutions for the 2 `foo` descriptors, even though they have overlapping ranges, which means that the lockfile can be simplified so that both descriptors resolve to `foo@2.10.14`.\\n    \",examples:[[\"Dedupe all packages\",\"$0 dedupe\"],[\"Dedupe all packages using a specific strategy\",\"$0 dedupe --strategy highest\"],[\"Dedupe a specific package\",\"$0 dedupe lodash\"],[\"Dedupe all packages with the `@babel/*` scope\",\"$0 dedupe '@babel/*'\"],[\"Check for duplicates (can be used as a CI step)\",\"$0 dedupe --check\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd),a=await Jr.find(r);await s.restoreInstallState({restoreResolutions:!1});let n=0,c=await Ot.start({configuration:r,includeFooter:!1,stdout:this.context.stdout,json:this.json},async f=>{n=await p5(s,{strategy:this.strategy,patterns:this.patterns,cache:a,report:f})});return c.hasErrors()?c.exitCode():this.check?n?1:0:await s.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:a,mode:this.mode})}};qe();Vt();var iC=class extends At{static{this.paths=[[\"--clipanion=definitions\"]]}async execute(){let{plugins:t}=await ze.find(this.context.cwd,this.context.plugins),r=[];for(let c of t){let{commands:f}=c[1];if(f){let h=va.from(f).definitions();r.push([c[0],h])}}let s=this.cli.definitions(),a=(c,f)=>c.split(\" \").slice(1).join()===f.split(\" \").slice(1).join(),n=nde()[\"@yarnpkg/builder\"].bundles.standard;for(let c of r){let f=c[1];for(let p of f)s.find(h=>a(h.path,p.path)).plugin={name:c[0],isDefault:n.includes(c[0])}}this.context.stdout.write(`${JSON.stringify(s,null,2)}\n`)}};var sC=class extends At{static{this.paths=[[\"help\"],[\"--help\"],[\"-h\"]]}async execute(){this.context.stdout.write(this.cli.usage(null))}};qe();Dt();Vt();var oC=class extends At{constructor(){super(...arguments);this.leadingArgument=he.String();this.args=he.Proxy()}async execute(){if(this.leadingArgument.match(/[\\\\/]/)&&!j.tryParseIdent(this.leadingArgument)){let r=K.resolve(this.context.cwd,fe.toPortablePath(this.leadingArgument));return await this.cli.run(this.args,{cwd:r})}else return await this.cli.run([\"run\",this.leadingArgument,...this.args])}};qe();var aC=class extends At{static{this.paths=[[\"-v\"],[\"--version\"]]}async execute(){this.context.stdout.write(`${An||\"<unknown>\"}\n`)}};qe();qe();Vt();var lC=class extends At{constructor(){super(...arguments);this.commandName=he.String();this.args=he.Proxy()}static{this.paths=[[\"exec\"]]}static{this.usage=at.Usage({description:\"execute a shell script\",details:`\n      This command simply executes a shell script within the context of the root directory of the active workspace using the portable shell.\n\n      It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment).\n    `,examples:[[\"Execute a single shell command\",\"$0 exec echo Hello World\"],[\"Execute a shell script\",'$0 exec \"tsc & babel src --out-dir lib\"']]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,locator:a}=await Rt.find(r,this.context.cwd);return await s.restoreInstallState(),await Cn.executePackageShellcode(a,this.commandName,this.args,{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,project:s})}};qe();Vt();ul();var cC=class extends At{constructor(){super(...arguments);this.hash=he.String({required:!1,validator:Nx(SE(),[qB(/^p[0-9a-f]{6}$/)])})}static{this.paths=[[\"explain\",\"peer-requirements\"]]}static{this.usage=at.Usage({description:\"explain a set of peer requirements\",details:`\n      A peer requirement represents all peer requests that a subject must satisfy when providing a requested package to requesters.\n\n      When the hash argument is specified, this command prints a detailed explanation of the peer requirement corresponding to the hash and whether it is satisfied or not.\n\n      When used without arguments, this command lists all peer requirements and the corresponding hash that can be used to get detailed information about a given requirement.\n\n      **Note:** A hash is a seven-letter code consisting of the letter 'p' followed by six characters that can be obtained from peer dependency warnings or from the list of all peer requirements(\\`yarn explain peer-requirements\\`).\n    `,examples:[[\"Explain the corresponding peer requirement for a hash\",\"$0 explain peer-requirements p1a4ed\"],[\"List all peer requirements\",\"$0 explain peer-requirements\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd);return await s.restoreInstallState({restoreResolutions:!1}),await s.applyLightResolution(),typeof this.hash<\"u\"?await iot(this.hash,s,{stdout:this.context.stdout}):await sot(s,{stdout:this.context.stdout})}};async function iot(e,t,r){let s=t.peerRequirementNodes.get(e);if(typeof s>\"u\")throw new Error(`No peerDependency requirements found for hash: \"${e}\"`);let a=new Set,n=p=>a.has(p.requester.locatorHash)?{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:p.children.size>0?[{value:pe.tuple(pe.Type.NO_HINT,\"...\")}]:[]}:(a.add(p.requester.locatorHash),{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:Object.fromEntries(Array.from(p.children.values(),h=>[j.stringifyLocator(h.requester),n(h)]))}),c=t.peerWarnings.find(p=>p.hash===e);return(await Ot.start({configuration:t.configuration,stdout:r.stdout,includeFooter:!1,includePrefix:!1},async p=>{let h=pe.mark(t.configuration),E=c?h.Cross:h.Check;if(p.reportInfo(0,`Package ${pe.pretty(t.configuration,s.subject,pe.Type.LOCATOR)} is requested to provide ${pe.pretty(t.configuration,s.ident,pe.Type.IDENT)} by its descendants`),p.reportSeparator(),p.reportInfo(0,pe.pretty(t.configuration,s.subject,pe.Type.LOCATOR)),Rs.emitTree({children:Object.fromEntries(Array.from(s.requests.values(),C=>[j.stringifyLocator(C.requester),n(C)]))},{configuration:t.configuration,stdout:r.stdout,json:!1}),p.reportSeparator(),s.provided.range===\"missing:\"){let C=c?\"\":\" , but all peer requests are optional\";p.reportInfo(0,`${E} Package ${pe.pretty(t.configuration,s.subject,pe.Type.LOCATOR)} does not provide ${pe.pretty(t.configuration,s.ident,pe.Type.IDENT)}${C}.`)}else{let C=t.storedResolutions.get(s.provided.descriptorHash);if(!C)throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let S=t.storedPackages.get(C);if(!S)throw new Error(\"Assertion failed: Expected the package to be registered\");p.reportInfo(0,`${E} Package ${pe.pretty(t.configuration,s.subject,pe.Type.LOCATOR)} provides ${pe.pretty(t.configuration,s.ident,pe.Type.IDENT)} with version ${j.prettyReference(t.configuration,S.version??\"0.0.0\")}, ${c?\"which does not satisfy all requests.\":\"which satisfies all requests\"}`),c?.type===3&&(c.range?p.reportInfo(0,`  The combined requested range is ${pe.pretty(t.configuration,c.range,pe.Type.RANGE)}`):p.reportInfo(0,\"  Unfortunately, the requested ranges have no overlap\"))}})).exitCode()}async function sot(e,t){return(await Ot.start({configuration:e.configuration,stdout:t.stdout,includeFooter:!1,includePrefix:!1},async s=>{let a=pe.mark(e.configuration),n=Ge.sortMap(e.peerRequirementNodes,[([,c])=>j.stringifyLocator(c.subject),([,c])=>j.stringifyIdent(c.ident)]);for(let[,c]of n.values()){if(!c.root)continue;let f=e.peerWarnings.find(E=>E.hash===c.hash),p=[...j.allPeerRequests(c)],h;if(p.length>2?h=` and ${p.length-1} other dependencies`:p.length===2?h=\" and 1 other dependency\":h=\"\",c.provided.range!==\"missing:\"){let E=e.storedResolutions.get(c.provided.descriptorHash);if(!E)throw new Error(\"Assertion failed: Expected the resolution to have been registered\");let C=e.storedPackages.get(E);if(!C)throw new Error(\"Assertion failed: Expected the provided package to have been registered\");let S=`${pe.pretty(e.configuration,c.hash,pe.Type.CODE)} \\u2192 ${f?a.Cross:a.Check} ${j.prettyLocator(e.configuration,c.subject)} provides ${j.prettyLocator(e.configuration,C)} to ${j.prettyLocator(e.configuration,p[0].requester)}${h}`;f?s.reportWarning(0,S):s.reportInfo(0,S)}else{let E=`${pe.pretty(e.configuration,c.hash,pe.Type.CODE)} \\u2192 ${f?a.Cross:a.Check} ${j.prettyLocator(e.configuration,c.subject)} doesn't provide ${j.prettyIdent(e.configuration,c.ident)} to ${j.prettyLocator(e.configuration,p[0].requester)}${h}`;f?s.reportWarning(0,E):s.reportInfo(0,E)}}})).exitCode()}qe();Vt();ul();qe();qe();Dt();Vt();var ide=et(pi()),uC=class extends At{constructor(){super(...arguments);this.useYarnPath=he.Boolean(\"--yarn-path\",{description:\"Set the yarnPath setting even if the version can be accessed by Corepack\"});this.onlyIfNeeded=he.Boolean(\"--only-if-needed\",!1,{description:\"Only lock the Yarn version if it isn't already locked\"});this.version=he.String()}static{this.paths=[[\"set\",\"version\"]]}static{this.usage=at.Usage({description:\"lock the Yarn version used by the project\",details:\"\\n      This command will set a specific release of Yarn to be used by Corepack: https://nodejs.org/api/corepack.html.\\n\\n      By default it only will set the `packageManager` field at the root of your project, but if the referenced release cannot be represented this way, if you already have `yarnPath` configured, or if you set the `--yarn-path` command line flag, then the release will also be downloaded from the Yarn GitHub repository, stored inside your project, and referenced via the `yarnPath` settings from your project `.yarnrc.yml` file.\\n\\n      A very good use case for this command is to enforce the version of Yarn used by any single member of your team inside the same project - by doing this you ensure that you have control over Yarn upgrades and downgrades (including on your deployment servers), and get rid of most of the headaches related to someone using a slightly different version and getting different behavior.\\n\\n      The version specifier can be:\\n\\n      - a tag:\\n        - `latest` / `berry` / `stable` -> the most recent stable berry (`>=2.0.0`) release\\n        - `canary` -> the most recent canary (release candidate) berry (`>=2.0.0`) release\\n        - `classic` -> the most recent classic (`^0.x || ^1.x`) release\\n\\n      - a semver range (e.g. `2.x`) -> the most recent version satisfying the range (limited to berry releases)\\n\\n      - a semver version (e.g. `2.4.1`, `1.22.1`)\\n\\n      - a local file referenced through either a relative or absolute path\\n\\n      - `self` -> the version used to invoke the command\\n    \",examples:[[\"Download the latest release from the Yarn repository\",\"$0 set version latest\"],[\"Download the latest canary release from the Yarn repository\",\"$0 set version canary\"],[\"Download the latest classic release from the Yarn repository\",\"$0 set version classic\"],[\"Download the most recent Yarn 3 build\",\"$0 set version 3.x\"],[\"Download a specific Yarn 2 build\",\"$0 set version 2.0.0-rc.30\"],[\"Switch back to a specific Yarn 1 release\",\"$0 set version 1.22.1\"],[\"Use a release from the local filesystem\",\"$0 set version ./yarn.cjs\"],[\"Use a release from a URL\",\"$0 set version https://repo.yarnpkg.com/3.1.0/packages/yarnpkg-cli/bin/yarn.js\"],[\"Download the version used to invoke the command\",\"$0 set version self\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);if(this.onlyIfNeeded&&r.get(\"yarnPath\")){let f=r.sources.get(\"yarnPath\");if(!f)throw new Error(\"Assertion failed: Expected 'yarnPath' to have a source\");let p=r.projectCwd??r.startingCwd;if(K.contains(p,f))return 0}let s=()=>{if(typeof An>\"u\")throw new st(\"The --install flag can only be used without explicit version specifier from the Yarn CLI\");return`file://${process.argv[1]}`},a,n=(f,p)=>({version:p,url:f.replace(/\\{\\}/g,p)});if(this.version===\"self\")a={url:s(),version:An??\"self\"};else if(this.version===\"latest\"||this.version===\"berry\"||this.version===\"stable\")a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",await Xv(r,\"stable\"));else if(this.version===\"canary\")a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",await Xv(r,\"canary\"));else if(this.version===\"classic\")a={url:\"https://classic.yarnpkg.com/latest.js\",version:\"classic\"};else if(this.version.match(/^https?:/))a={url:this.version,version:\"remote\"};else if(this.version.match(/^\\.{0,2}[\\\\/]/)||fe.isAbsolute(this.version))a={url:`file://${K.resolve(fe.toPortablePath(this.version))}`,version:\"file\"};else if(Fr.satisfiesWithPrereleases(this.version,\">=2.0.0\"))a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",this.version);else if(Fr.satisfiesWithPrereleases(this.version,\"^0.x || ^1.x\"))a=n(\"https://github.com/yarnpkg/yarn/releases/download/v{}/yarn-{}.js\",this.version);else if(Fr.validRange(this.version))a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",await oot(r,this.version));else throw new st(`Invalid version descriptor \"${this.version}\"`);return(await Ot.start({configuration:r,stdout:this.context.stdout,includeLogs:!this.context.quiet},async f=>{let p=async()=>{let h=\"file://\";return a.url.startsWith(h)?(f.reportInfo(0,`Retrieving ${pe.pretty(r,a.url,pe.Type.PATH)}`),await le.readFilePromise(a.url.slice(h.length))):(f.reportInfo(0,`Downloading ${pe.pretty(r,a.url,pe.Type.URL)}`),await nn.get(a.url,{configuration:r}))};await h5(r,a.version,p,{report:f,useYarnPath:this.useYarnPath})})).exitCode()}};async function oot(e,t){let s=(await nn.get(\"https://repo.yarnpkg.com/tags\",{configuration:e,jsonResponse:!0})).tags.filter(a=>Fr.satisfiesWithPrereleases(a,t));if(s.length===0)throw new st(`No matching release found for range ${pe.pretty(e,t,pe.Type.RANGE)}.`);return s[0]}async function Xv(e,t){let r=await nn.get(\"https://repo.yarnpkg.com/tags\",{configuration:e,jsonResponse:!0});if(!r.latest[t])throw new st(`Tag ${pe.pretty(e,t,pe.Type.RANGE)} not found`);return r.latest[t]}async function h5(e,t,r,{report:s,useYarnPath:a}){let n,c=async()=>(typeof n>\"u\"&&(n=await r()),n);if(t===null){let te=await c();await le.mktempPromise(async ie=>{let ue=K.join(ie,\"yarn.cjs\");await le.writeFilePromise(ue,te);let{stdout:ae}=await qr.execvp(process.execPath,[fe.fromPortablePath(ue),\"--version\"],{cwd:ie,env:{...e.env,YARN_IGNORE_PATH:\"1\"}});if(t=ae.trim(),!ide.default.valid(t))throw new Error(`Invalid semver version. ${pe.pretty(e,\"yarn --version\",pe.Type.CODE)} returned:\n${t}`)})}let f=e.projectCwd??e.startingCwd,p=K.resolve(f,\".yarn/releases\"),h=K.resolve(p,`yarn-${t}.cjs`),E=K.relative(e.startingCwd,h),C=Ge.isTaggedYarnVersion(t),S=e.get(\"yarnPath\"),x=!C,I=x||!!S||!!a;if(a===!1){if(x)throw new _t(0,\"You explicitly opted out of yarnPath usage in your command line, but the version you specified cannot be represented by Corepack\");I=!1}else!I&&!process.env.COREPACK_ROOT&&(s.reportWarning(0,`You don't seem to have ${pe.applyHyperlink(e,\"Corepack\",\"https://nodejs.org/api/corepack.html\")} enabled; we'll have to rely on ${pe.applyHyperlink(e,\"yarnPath\",\"https://yarnpkg.com/configuration/yarnrc#yarnPath\")} instead`),I=!0);if(I){let te=await c();s.reportInfo(0,`Saving the new release in ${pe.pretty(e,E,\"magenta\")}`),await le.removePromise(K.dirname(h)),await le.mkdirPromise(K.dirname(h),{recursive:!0}),await le.writeFilePromise(h,te,{mode:493}),await ze.updateConfiguration(f,{yarnPath:K.relative(f,h)})}else await le.removePromise(K.dirname(h)),await ze.updateConfiguration(f,{yarnPath:ze.deleteProperty});let T=await Ut.tryFind(f)||new Ut;T.packageManager=`yarn@${C?t:await Xv(e,\"stable\")}`;let O={};T.exportTo(O);let U=K.join(f,Ut.fileName),Y=`${JSON.stringify(O,null,T.indent)}\n`;return await le.changeFilePromise(U,Y,{automaticNewlines:!0}),{bundleVersion:t}}function sde(e){return Br[jx(e)]}var aot=/## (?<code>YN[0-9]{4}) - `(?<name>[A-Z_]+)`\\n\\n(?<details>(?:.(?!##))+)/gs;async function lot(e){let r=`https://repo.yarnpkg.com/${Ge.isTaggedYarnVersion(An)?An:await Xv(e,\"canary\")}/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx`,s=await nn.get(r,{configuration:e});return new Map(Array.from(s.toString().matchAll(aot),({groups:a})=>{if(!a)throw new Error(\"Assertion failed: Expected the match to have been successful\");let n=sde(a.code);if(a.name!==n)throw new Error(`Assertion failed: Invalid error code data: Expected \"${a.name}\" to be named \"${n}\"`);return[a.code,a.details]}))}var fC=class extends At{constructor(){super(...arguments);this.code=he.String({required:!1,validator:WB(SE(),[qB(/^YN[0-9]{4}$/)])});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"explain\"]]}static{this.usage=at.Usage({description:\"explain an error code\",details:`\n      When the code argument is specified, this command prints its name and its details.\n\n      When used without arguments, this command lists all error codes and their names.\n    `,examples:[[\"Explain an error code\",\"$0 explain YN0006\"],[\"List all error codes\",\"$0 explain\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);if(typeof this.code<\"u\"){let s=sde(this.code),a=pe.pretty(r,s,pe.Type.CODE),n=this.cli.format().header(`${this.code} - ${a}`),f=(await lot(r)).get(this.code),p=typeof f<\"u\"?pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.MARKDOWN,{text:f,format:this.cli.format(),paragraphs:!0})):`This error code does not have a description.\n\nYou can help us by editing this page on GitHub \\u{1F642}:\n${pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.URL,\"https://github.com/yarnpkg/berry/blob/master/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx\"))}\n`;this.json?this.context.stdout.write(`${JSON.stringify({code:this.code,name:s,details:p})}\n`):this.context.stdout.write(`${n}\n\n${p}\n`)}else{let s={children:Ge.mapAndFilter(Object.entries(Br),([a,n])=>Number.isNaN(Number(a))?Ge.mapAndFilter.skip:{label:Kf(Number(a)),value:pe.tuple(pe.Type.CODE,n)})};Rs.emitTree(s,{configuration:r,stdout:this.context.stdout,json:this.json})}}};qe();Dt();Vt();var ode=et(Jo()),AC=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"-A,--all\",!1,{description:\"Print versions of a package from the whole project\"});this.recursive=he.Boolean(\"-R,--recursive\",!1,{description:\"Print information for all packages, including transitive dependencies\"});this.extra=he.Array(\"-X,--extra\",[],{description:\"An array of requests of extra data provided by plugins\"});this.cache=he.Boolean(\"--cache\",!1,{description:\"Print information about the cache entry of a package (path, size, checksum)\"});this.dependents=he.Boolean(\"--dependents\",!1,{description:\"Print all dependents for each matching package\"});this.manifest=he.Boolean(\"--manifest\",!1,{description:\"Print data obtained by looking at the package archive (license, homepage, ...)\"});this.nameOnly=he.Boolean(\"--name-only\",!1,{description:\"Only print the name for the matching packages\"});this.virtuals=he.Boolean(\"--virtuals\",!1,{description:\"Print each instance of the virtual packages\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.patterns=he.Rest()}static{this.paths=[[\"info\"]]}static{this.usage=at.Usage({description:\"see information related to packages\",details:\"\\n      This command prints various information related to the specified packages, accepting glob patterns.\\n\\n      By default, if the locator reference is missing, Yarn will default to print the information about all the matching direct dependencies of the package for the active workspace. To instead print all versions of the package that are direct dependencies of any of your workspaces, use the `-A,--all` flag. Adding the `-R,--recursive` flag will also report transitive dependencies.\\n\\n      Some fields will be hidden by default in order to keep the output readable, but can be selectively displayed by using additional options (`--dependents`, `--manifest`, `--virtuals`, ...) described in the option descriptions.\\n\\n      Note that this command will only print the information directly related to the selected packages - if you wish to know why the package is there in the first place, use `yarn why` which will do just that (it also provides a `-R,--recursive` flag that may be of some help).\\n    \",examples:[[\"Show information about Lodash\",\"$0 info lodash\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a&&!this.all)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState();let c=new Set(this.extra);this.cache&&c.add(\"cache\"),this.dependents&&c.add(\"dependents\"),this.manifest&&c.add(\"manifest\");let f=(ie,{recursive:ue})=>{let ae=ie.anchoredLocator.locatorHash,de=new Map,Ae=[ae];for(;Ae.length>0;){let Ce=Ae.shift();if(de.has(Ce))continue;let Ee=s.storedPackages.get(Ce);if(typeof Ee>\"u\")throw new Error(\"Assertion failed: Expected the package to be registered\");if(de.set(Ce,Ee),j.isVirtualLocator(Ee)&&Ae.push(j.devirtualizeLocator(Ee).locatorHash),!(!ue&&Ce!==ae))for(let g of Ee.dependencies.values()){let Se=s.storedResolutions.get(g.descriptorHash);if(typeof Se>\"u\")throw new Error(\"Assertion failed: Expected the resolution to be registered\");Ae.push(Se)}}return de.values()},p=({recursive:ie})=>{let ue=new Map;for(let ae of s.workspaces)for(let de of f(ae,{recursive:ie}))ue.set(de.locatorHash,de);return ue.values()},h=({all:ie,recursive:ue})=>ie&&ue?s.storedPackages.values():ie?p({recursive:ue}):f(a,{recursive:ue}),E=({all:ie,recursive:ue})=>{let ae=h({all:ie,recursive:ue}),de=this.patterns.map(Ee=>{let g=j.parseLocator(Ee),Se=ode.default.makeRe(j.stringifyIdent(g)),Be=j.isVirtualLocator(g),me=Be?j.devirtualizeLocator(g):g;return ce=>{let X=j.stringifyIdent(ce);if(!Se.test(X))return!1;if(g.reference===\"unknown\")return!0;let De=j.isVirtualLocator(ce),Qe=De?j.devirtualizeLocator(ce):ce;return!(Be&&De&&g.reference!==ce.reference||me.reference!==Qe.reference)}}),Ae=Ge.sortMap([...ae],Ee=>j.stringifyLocator(Ee));return{selection:Ae.filter(Ee=>de.length===0||de.some(g=>g(Ee))),sortedLookup:Ae}},{selection:C,sortedLookup:S}=E({all:this.all,recursive:this.recursive});if(C.length===0)throw new st(\"No package matched your request\");let x=new Map;if(this.dependents)for(let ie of S)for(let ue of ie.dependencies.values()){let ae=s.storedResolutions.get(ue.descriptorHash);if(typeof ae>\"u\")throw new Error(\"Assertion failed: Expected the resolution to be registered\");Ge.getArrayWithDefault(x,ae).push(ie)}let I=new Map;for(let ie of S){if(!j.isVirtualLocator(ie))continue;let ue=j.devirtualizeLocator(ie);Ge.getArrayWithDefault(I,ue.locatorHash).push(ie)}let T={},O={children:T},U=r.makeFetcher(),Y={project:s,fetcher:U,cache:n,checksums:s.storedChecksums,report:new ki,cacheOptions:{skipIntegrityCheck:!0}},te=[async(ie,ue,ae)=>{if(!ue.has(\"manifest\"))return;let de=await U.fetch(ie,Y),Ae;try{Ae=await Ut.find(de.prefixPath,{baseFs:de.packageFs})}finally{de.releaseFs?.()}ae(\"Manifest\",{License:pe.tuple(pe.Type.NO_HINT,Ae.license),Homepage:pe.tuple(pe.Type.URL,Ae.raw.homepage??null)})},async(ie,ue,ae)=>{if(!ue.has(\"cache\"))return;let de=s.storedChecksums.get(ie.locatorHash)??null,Ae=n.getLocatorPath(ie,de),Ce;if(Ae!==null)try{Ce=await le.statPromise(Ae)}catch{}let Ee=typeof Ce<\"u\"?[Ce.size,pe.Type.SIZE]:void 0;ae(\"Cache\",{Checksum:pe.tuple(pe.Type.NO_HINT,de),Path:pe.tuple(pe.Type.PATH,Ae),Size:Ee})}];for(let ie of C){let ue=j.isVirtualLocator(ie);if(!this.virtuals&&ue)continue;let ae={},de={value:[ie,pe.Type.LOCATOR],children:ae};if(T[j.stringifyLocator(ie)]=de,this.nameOnly){delete de.children;continue}let Ae=I.get(ie.locatorHash);typeof Ae<\"u\"&&(ae.Instances={label:\"Instances\",value:pe.tuple(pe.Type.NUMBER,Ae.length)}),ae.Version={label:\"Version\",value:pe.tuple(pe.Type.NO_HINT,ie.version)};let Ce=(g,Se)=>{let Be={};if(ae[g]=Be,Array.isArray(Se))Be.children=Se.map(me=>({value:me}));else{let me={};Be.children=me;for(let[ce,X]of Object.entries(Se))typeof X>\"u\"||(me[ce]={label:ce,value:X})}};if(!ue){for(let g of te)await g(ie,c,Ce);await r.triggerHook(g=>g.fetchPackageInfo,ie,c,Ce)}ie.bin.size>0&&!ue&&Ce(\"Exported Binaries\",[...ie.bin.keys()].map(g=>pe.tuple(pe.Type.PATH,g)));let Ee=x.get(ie.locatorHash);typeof Ee<\"u\"&&Ee.length>0&&Ce(\"Dependents\",Ee.map(g=>pe.tuple(pe.Type.LOCATOR,g))),ie.dependencies.size>0&&!ue&&Ce(\"Dependencies\",[...ie.dependencies.values()].map(g=>{let Se=s.storedResolutions.get(g.descriptorHash),Be=typeof Se<\"u\"?s.storedPackages.get(Se)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:Be})})),ie.peerDependencies.size>0&&ue&&Ce(\"Peer dependencies\",[...ie.peerDependencies.values()].map(g=>{let Se=ie.dependencies.get(g.identHash),Be=typeof Se<\"u\"?s.storedResolutions.get(Se.descriptorHash)??null:null,me=Be!==null?s.storedPackages.get(Be)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:me})}))}Rs.emitTree(O,{configuration:r,json:this.json,stdout:this.context.stdout,separators:this.nameOnly?0:2})}};qe();Dt();Bc();var HT=et(Rd());Vt();var g5=et(pi());ul();var cot=[{selector:e=>e===-1,name:\"nodeLinker\",value:\"node-modules\"},{selector:e=>e!==-1&&e<8,name:\"enableGlobalCache\",value:!1},{selector:e=>e!==-1&&e<8,name:\"compressionLevel\",value:\"mixed\"}],pC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.immutable=he.Boolean(\"--immutable\",{description:\"Abort with an error exit code if the lockfile was to be modified\"});this.immutableCache=he.Boolean(\"--immutable-cache\",{description:\"Abort with an error exit code if the cache folder was to be modified\"});this.refreshLockfile=he.Boolean(\"--refresh-lockfile\",{description:\"Refresh the package metadata stored in the lockfile\"});this.checkCache=he.Boolean(\"--check-cache\",{description:\"Always refetch the packages and ensure that their checksums are consistent\"});this.checkResolutions=he.Boolean(\"--check-resolutions\",{description:\"Validates that the package resolutions are coherent\"});this.inlineBuilds=he.Boolean(\"--inline-builds\",{description:\"Verbosely print the output of the build steps of dependencies\"});this.mode=he.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:ks(Na)});this.cacheFolder=he.String(\"--cache-folder\",{hidden:!0});this.frozenLockfile=he.Boolean(\"--frozen-lockfile\",{hidden:!0});this.ignoreEngines=he.Boolean(\"--ignore-engines\",{hidden:!0});this.nonInteractive=he.Boolean(\"--non-interactive\",{hidden:!0});this.preferOffline=he.Boolean(\"--prefer-offline\",{hidden:!0});this.production=he.Boolean(\"--production\",{hidden:!0});this.registry=he.String(\"--registry\",{hidden:!0});this.silent=he.Boolean(\"--silent\",{hidden:!0});this.networkTimeout=he.String(\"--network-timeout\",{hidden:!0})}static{this.paths=[[\"install\"],at.Default]}static{this.usage=at.Usage({description:\"install the project dependencies\",details:\"\\n      This command sets up your project if needed. The installation is split into four different steps that each have their own characteristics:\\n\\n      - **Resolution:** First the package manager will resolve your dependencies. The exact way a dependency version is privileged over another isn't standardized outside of the regular semver guarantees. If a package doesn't resolve to what you would expect, check that all dependencies are correctly declared (also check our website for more information: ).\\n\\n      - **Fetch:** Then we download all the dependencies if needed, and make sure that they're all stored within our cache (check the value of `cacheFolder` in `yarn config` to see where the cache files are stored).\\n\\n      - **Link:** Then we send the dependency tree information to internal plugins tasked with writing them on the disk in some form (for example by generating the `.pnp.cjs` file you might know).\\n\\n      - **Build:** Once the dependency tree has been written on the disk, the package manager will now be free to run the build scripts for all packages that might need it, in a topological order compatible with the way they depend on one another. See https://yarnpkg.com/advanced/lifecycle-scripts for detail.\\n\\n      Note that running this command is not part of the recommended workflow. Yarn supports zero-installs, which means that as long as you store your cache and your `.pnp.cjs` file inside your repository, everything will work without requiring any install right after cloning your repository or switching branches.\\n\\n      If the `--immutable` option is set (defaults to true on CI), Yarn will abort with an error exit code if the lockfile was to be modified (other paths can be added using the `immutablePatterns` configuration setting). For backward compatibility we offer an alias under the name of `--frozen-lockfile`, but it will be removed in a later release.\\n\\n      If the `--immutable-cache` option is set, Yarn will abort with an error exit code if the cache folder was to be modified (either because files would be added, or because they'd be removed).\\n\\n      If the `--refresh-lockfile` option is set, Yarn will keep the same resolution for the packages currently in the lockfile but will refresh their metadata. If used together with `--immutable`, it can validate that the lockfile information are consistent. This flag is enabled by default when Yarn detects it runs within a pull request context.\\n\\n      If the `--check-cache` option is set, Yarn will always refetch the packages and will ensure that their checksum matches what's 1/ described in the lockfile 2/ inside the existing cache files (if present). This is recommended as part of your CI workflow if you're both following the Zero-Installs model and accepting PRs from third-parties, as they'd otherwise have the ability to alter the checked-in packages before submitting them.\\n\\n      If the `--inline-builds` option is set, Yarn will verbosely print the output of the build steps of your dependencies (instead of writing them into individual files). This is likely useful mostly for debug purposes only when using Docker-like environments.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n    \",examples:[[\"Install the project\",\"$0 install\"],[\"Validate a project when using Zero-Installs\",\"$0 install --immutable --immutable-cache\"],[\"Validate a project when using Zero-Installs (slightly safer if you accept external PRs)\",\"$0 install --immutable --immutable-cache --check-cache\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);typeof this.inlineBuilds<\"u\"&&r.useWithSource(\"<cli>\",{enableInlineBuilds:this.inlineBuilds},r.startingCwd,{overwrite:!0});let s=!!process.env.FUNCTION_TARGET||!!process.env.GOOGLE_RUNTIME,a=await PI({configuration:r,stdout:this.context.stdout},[{option:this.ignoreEngines,message:\"The --ignore-engines option is deprecated; engine checking isn't a core feature anymore\",error:!HT.default.VERCEL},{option:this.registry,message:\"The --registry option is deprecated; prefer setting npmRegistryServer in your .yarnrc.yml file\"},{option:this.preferOffline,message:\"The --prefer-offline flag is deprecated; use the --cached flag with 'yarn add' instead\",error:!HT.default.VERCEL},{option:this.production,message:\"The --production option is deprecated on 'install'; use 'yarn workspaces focus' instead\",error:!0},{option:this.nonInteractive,message:\"The --non-interactive option is deprecated\",error:!s},{option:this.frozenLockfile,message:\"The --frozen-lockfile option is deprecated; use --immutable and/or --immutable-cache instead\",callback:()=>this.immutable=this.frozenLockfile},{option:this.cacheFolder,message:\"The cache-folder option has been deprecated; use rc settings instead\",error:!HT.default.NETLIFY}]);if(a!==null)return a;let n=this.mode===\"update-lockfile\";if(n&&(this.immutable||this.immutableCache))throw new st(`${pe.pretty(r,\"--immutable\",pe.Type.CODE)} and ${pe.pretty(r,\"--immutable-cache\",pe.Type.CODE)} cannot be used with ${pe.pretty(r,\"--mode=update-lockfile\",pe.Type.CODE)}`);let c=(this.immutable??r.get(\"enableImmutableInstalls\"))&&!n,f=this.immutableCache&&!n;if(r.projectCwd!==null){let T=await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async O=>{let U=!1;await Aot(r,c)&&(O.reportInfo(48,\"Automatically removed core plugins that are now builtins \\u{1F44D}\"),U=!0),await fot(r,c)&&(O.reportInfo(48,\"Automatically fixed merge conflicts \\u{1F44D}\"),U=!0),U&&O.reportSeparator()});if(T.hasErrors())return T.exitCode()}if(r.projectCwd!==null){let T=await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async O=>{if(ze.telemetry?.isNew)ze.telemetry.commitTips(),O.reportInfo(65,\"Yarn will periodically gather anonymous telemetry: https://yarnpkg.com/advanced/telemetry\"),O.reportInfo(65,`Run ${pe.pretty(r,\"yarn config set --home enableTelemetry 0\",pe.Type.CODE)} to disable`),O.reportSeparator();else if(ze.telemetry?.shouldShowTips){let U=await nn.get(\"https://repo.yarnpkg.com/tags\",{configuration:r,jsonResponse:!0}).catch(()=>null);if(U!==null){let Y=null;if(An!==null){let ie=g5.default.prerelease(An)?\"canary\":\"stable\",ue=U.latest[ie];ue!==null&&g5.default.gt(ue,An)&&(Y=[ie,ue])}if(Y)ze.telemetry.commitTips(),O.reportInfo(88,`${pe.applyStyle(r,`A new ${Y[0]} version of Yarn is available:`,pe.Style.BOLD)} ${j.prettyReference(r,Y[1])}!`),O.reportInfo(88,`Upgrade now by running ${pe.pretty(r,`yarn set version ${Y[1]}`,pe.Type.CODE)}`),O.reportSeparator();else{let te=ze.telemetry.selectTip(U.tips);te&&(O.reportInfo(89,pe.pretty(r,te.message,pe.Type.MARKDOWN_INLINE)),te.url&&O.reportInfo(89,`Learn more at ${te.url}`),O.reportSeparator())}}}});if(T.hasErrors())return T.exitCode()}let{project:p,workspace:h}=await Rt.find(r,this.context.cwd),E=p.lockfileLastVersion;if(E!==null){let T=await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async O=>{let U={};for(let Y of cot)Y.selector(E)&&typeof r.sources.get(Y.name)>\"u\"&&(r.use(\"<compat>\",{[Y.name]:Y.value},p.cwd,{overwrite:!0}),U[Y.name]=Y.value);Object.keys(U).length>0&&(await ze.updateConfiguration(p.cwd,U),O.reportInfo(87,\"Migrated your project to the latest Yarn version \\u{1F680}\"),O.reportSeparator())});if(T.hasErrors())return T.exitCode()}let C=await Jr.find(r,{immutable:f,check:this.checkCache});if(!h)throw new ar(p.cwd,this.context.cwd);await p.restoreInstallState({restoreResolutions:!1});let S=r.get(\"enableHardenedMode\");S&&typeof r.sources.get(\"enableHardenedMode\")>\"u\"&&await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async T=>{T.reportWarning(0,\"Yarn detected that the current workflow is executed from a public pull request. For safety the hardened mode has been enabled.\"),T.reportWarning(0,`It will prevent malicious lockfile manipulations, in exchange for a slower install time. You can opt-out if necessary; check our ${pe.applyHyperlink(r,\"documentation\",\"https://yarnpkg.com/features/security#hardened-mode\")} for more details.`),T.reportSeparator()}),(this.refreshLockfile??S)&&(p.lockfileNeedsRefresh=!0);let x=this.checkResolutions??S;return(await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout,forceSectionAlignment:!0,includeLogs:!0,includeVersion:!0},async T=>{await p.install({cache:C,report:T,immutable:c,checkResolutions:x,mode:this.mode})})).exitCode()}},uot=\"<<<<<<<\";async function fot(e,t){if(!e.projectCwd)return!1;let r=K.join(e.projectCwd,Er.lockfile);if(!await le.existsPromise(r)||!(await le.readFilePromise(r,\"utf8\")).includes(uot))return!1;if(t)throw new _t(47,\"Cannot autofix a lockfile when running an immutable install\");let a=await qr.execvp(\"git\",[\"rev-parse\",\"MERGE_HEAD\",\"HEAD\"],{cwd:e.projectCwd});if(a.code!==0&&(a=await qr.execvp(\"git\",[\"rev-parse\",\"REBASE_HEAD\",\"HEAD\"],{cwd:e.projectCwd})),a.code!==0&&(a=await qr.execvp(\"git\",[\"rev-parse\",\"CHERRY_PICK_HEAD\",\"HEAD\"],{cwd:e.projectCwd})),a.code!==0)throw new _t(83,\"Git returned an error when trying to find the commits pertaining to the conflict\");let n=await Promise.all(a.stdout.trim().split(/\\n/).map(async f=>{let p=await qr.execvp(\"git\",[\"show\",`${f}:./${Er.lockfile}`],{cwd:e.projectCwd});if(p.code!==0)throw new _t(83,`Git returned an error when trying to access the lockfile content in ${f}`);try{return cs(p.stdout)}catch{throw new _t(46,\"A variant of the conflicting lockfile failed to parse\")}}));n=n.filter(f=>!!f.__metadata);for(let f of n){if(f.__metadata.version<7)for(let p of Object.keys(f)){if(p===\"__metadata\")continue;let h=j.parseDescriptor(p,!0),E=e.normalizeDependency(h),C=j.stringifyDescriptor(E);C!==p&&(f[C]=f[p],delete f[p])}for(let p of Object.keys(f)){if(p===\"__metadata\")continue;let h=f[p].checksum;typeof h>\"u\"||h.includes(\"/\")||(f[p].checksum=`${f.__metadata.cacheKey}/${h}`)}}let c=Object.assign({},...n);c.__metadata.version=`${Math.min(...n.map(f=>parseInt(f.__metadata.version??0)))}`,c.__metadata.cacheKey=\"merged\";for(let[f,p]of Object.entries(c))typeof p==\"string\"&&delete c[f];return await le.changeFilePromise(r,cl(c),{automaticNewlines:!0}),!0}async function Aot(e,t){if(!e.projectCwd)return!1;let r=[],s=K.join(e.projectCwd,\".yarn/plugins/@yarnpkg\");return await ze.updateConfiguration(e.projectCwd,{plugins:n=>{if(!Array.isArray(n))return n;let c=n.filter(f=>{if(!f.path)return!0;let p=K.resolve(e.projectCwd,f.path),h=X2.has(f.spec)&&K.contains(s,p);return h&&r.push(p),!h});return c.length===0?ze.deleteProperty:c.length===n.length?n:c}},{immutable:t})?(await Promise.all(r.map(async n=>{await le.removePromise(n)})),!0):!1}qe();Dt();Vt();var hC=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"-A,--all\",!1,{description:\"Link all workspaces belonging to the target projects to the current one\"});this.private=he.Boolean(\"-p,--private\",!1,{description:\"Also link private workspaces belonging to the target projects to the current one\"});this.relative=he.Boolean(\"-r,--relative\",!1,{description:\"Link workspaces using relative paths instead of absolute paths\"});this.destinations=he.Rest()}static{this.paths=[[\"link\"]]}static{this.usage=at.Usage({description:\"connect the local project to another one\",details:\"\\n      This command will set a new `resolutions` field in the project-level manifest and point it to the workspace at the specified location (even if part of another project).\\n    \",examples:[[\"Register one or more remote workspaces for use in the current project\",\"$0 link ~/ts-loader ~/jest\"],[\"Register all workspaces from a remote project for use in the current project\",\"$0 link ~/jest --all\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let c=s.topLevelWorkspace,f=[];for(let p of this.destinations){let h=K.resolve(this.context.cwd,fe.toPortablePath(p)),E=await ze.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:C,workspace:S}=await Rt.find(E,h);if(s.cwd===C.cwd)throw new st(`Invalid destination '${p}'; Can't link the project to itself`);if(!S)throw new ar(C.cwd,h);if(this.all){let x=!1;for(let I of C.workspaces)I.manifest.name&&(!I.manifest.private||this.private)&&(f.push(I),x=!0);if(!x)throw new st(`No workspace found to be linked in the target project: ${p}`)}else{if(!S.manifest.name)throw new st(`The target workspace at '${p}' doesn't have a name and thus cannot be linked`);if(S.manifest.private&&!this.private)throw new st(`The target workspace at '${p}' is marked private - use the --private flag to link it anyway`);f.push(S)}}for(let p of f){let h=j.stringifyIdent(p.anchoredLocator),E=this.relative?K.relative(s.cwd,p.cwd):p.cwd;c.manifest.resolutions.push({pattern:{descriptor:{fullName:h}},reference:`portal:${E}`})}return await s.installWithNewReport({stdout:this.context.stdout},{cache:n})}};Vt();var gC=class extends At{constructor(){super(...arguments);this.args=he.Proxy()}static{this.paths=[[\"node\"]]}static{this.usage=at.Usage({description:\"run node with the hook already setup\",details:`\n      This command simply runs Node. It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment).\n\n      The Node process will use the exact same version of Node as the one used to run Yarn itself, which might be a good way to ensure that your commands always use a consistent Node version.\n    `,examples:[[\"Run a Node script\",\"$0 node ./my-script.js\"]]})}async execute(){return this.cli.run([\"exec\",\"node\",...this.args])}};qe();Vt();var dC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"plugin\",\"check\"]]}static{this.usage=at.Usage({category:\"Plugin-related commands\",description:\"find all third-party plugins that differ from their own spec\",details:`\n      Check only the plugins from https.\n\n      If this command detects any plugin differences in the CI environment, it will throw an error.\n    `,examples:[[\"find all third-party plugins that differ from their own spec\",\"$0 plugin check\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=await ze.findRcFiles(this.context.cwd);return(await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{for(let c of s)if(c.data?.plugins)for(let f of c.data.plugins){if(!f.checksum||!f.spec.match(/^https?:/))continue;let p=await nn.get(f.spec,{configuration:r}),h=Ln.makeHash(p);if(f.checksum===h)continue;let E=pe.pretty(r,f.path,pe.Type.PATH),C=pe.pretty(r,f.spec,pe.Type.URL),S=`${E} is different from the file provided by ${C}`;n.reportJson({...f,newChecksum:h}),n.reportError(0,S)}})).exitCode()}};qe();qe();Dt();Vt();var fde=Ie(\"os\");qe();Dt();Vt();var ade=Ie(\"os\");qe();Bc();Vt();var pot=\"https://raw.githubusercontent.com/yarnpkg/berry/master/plugins.yml\";async function Pm(e,t){let r=await nn.get(pot,{configuration:e}),s=cs(r.toString());return Object.fromEntries(Object.entries(s).filter(([a,n])=>!t||Fr.satisfiesWithPrereleases(t,n.range??\"<4.0.0-rc.1\")))}var mC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"plugin\",\"list\"]]}static{this.usage=at.Usage({category:\"Plugin-related commands\",description:\"list the available official plugins\",details:\"\\n      This command prints the plugins available directly from the Yarn repository. Only those plugins can be referenced by name in `yarn plugin import`.\\n    \",examples:[[\"List the official plugins\",\"$0 plugin list\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);return(await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{let n=await Pm(r,An);for(let[c,{experimental:f,...p}]of Object.entries(n)){let h=c;f&&(h+=\" [experimental]\"),a.reportJson({name:c,experimental:f,...p}),a.reportInfo(null,h)}})).exitCode()}};var hot=/^[0-9]+$/,got=process.platform===\"win32\";function lde(e){return hot.test(e)?`pull/${e}/head`:e}var dot=({repository:e,branch:t},r)=>[[\"git\",\"init\",fe.fromPortablePath(r)],[\"git\",\"remote\",\"add\",\"origin\",e],[\"git\",\"fetch\",\"origin\",\"--depth=1\",lde(t)],[\"git\",\"reset\",\"--hard\",\"FETCH_HEAD\"]],mot=({branch:e})=>[[\"git\",\"fetch\",\"origin\",\"--depth=1\",lde(e),\"--force\"],[\"git\",\"reset\",\"--hard\",\"FETCH_HEAD\"],[\"git\",\"clean\",\"-dfx\",\"-e\",\"packages/yarnpkg-cli/bundles\"]],yot=({plugins:e,noMinify:t},r,s)=>[[\"yarn\",\"build:cli\",...new Array().concat(...e.map(a=>[\"--plugin\",K.resolve(s,a)])),...t?[\"--no-minify\"]:[],\"|\"],[got?\"move\":\"mv\",\"packages/yarnpkg-cli/bundles/yarn.js\",fe.fromPortablePath(r),\"|\"]],yC=class extends At{constructor(){super(...arguments);this.installPath=he.String(\"--path\",{description:\"The path where the repository should be cloned to\"});this.repository=he.String(\"--repository\",\"https://github.com/yarnpkg/berry.git\",{description:\"The repository that should be cloned\"});this.branch=he.String(\"--branch\",\"master\",{description:\"The branch of the repository that should be cloned\"});this.plugins=he.Array(\"--plugin\",[],{description:\"An array of additional plugins that should be included in the bundle\"});this.dryRun=he.Boolean(\"-n,--dry-run\",!1,{description:\"If set, the bundle will be built but not added to the project\"});this.noMinify=he.Boolean(\"--no-minify\",!1,{description:\"Build a bundle for development (debugging) - non-minified and non-mangled\"});this.force=he.Boolean(\"-f,--force\",!1,{description:\"Always clone the repository instead of trying to fetch the latest commits\"});this.skipPlugins=he.Boolean(\"--skip-plugins\",!1,{description:\"Skip updating the contrib plugins\"})}static{this.paths=[[\"set\",\"version\",\"from\",\"sources\"]]}static{this.usage=at.Usage({description:\"build Yarn from master\",details:`\n      This command will clone the Yarn repository into a temporary folder, then build it. The resulting bundle will then be copied into the local project.\n\n      By default, it also updates all contrib plugins to the same commit the bundle is built from. This behavior can be disabled by using the \\`--skip-plugins\\` flag.\n    `,examples:[[\"Build Yarn from master\",\"$0 set version from sources\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd),a=typeof this.installPath<\"u\"?K.resolve(this.context.cwd,fe.toPortablePath(this.installPath)):K.resolve(fe.toPortablePath((0,ade.tmpdir)()),\"yarnpkg-sources\",Ln.makeHash(this.repository).slice(0,6));return(await Ot.start({configuration:r,stdout:this.context.stdout},async c=>{await d5(this,{configuration:r,report:c,target:a}),c.reportSeparator(),c.reportInfo(0,\"Building a fresh bundle\"),c.reportSeparator();let f=await qr.execvp(\"git\",[\"rev-parse\",\"--short\",\"HEAD\"],{cwd:a,strict:!0}),p=K.join(a,`packages/yarnpkg-cli/bundles/yarn-${f.stdout.trim()}.js`);le.existsSync(p)||(await $v(yot(this,p,a),{configuration:r,context:this.context,target:a}),c.reportSeparator());let h=await le.readFilePromise(p);if(!this.dryRun){let{bundleVersion:E}=await h5(r,null,async()=>h,{report:c});this.skipPlugins||await Eot(this,E,{project:s,report:c,target:a})}})).exitCode()}};async function $v(e,{configuration:t,context:r,target:s}){for(let[a,...n]of e){let c=n[n.length-1]===\"|\";if(c&&n.pop(),c)await qr.pipevp(a,n,{cwd:s,stdin:r.stdin,stdout:r.stdout,stderr:r.stderr,strict:!0});else{r.stdout.write(`${pe.pretty(t,`  $ ${[a,...n].join(\" \")}`,\"grey\")}\n`);try{await qr.execvp(a,n,{cwd:s,strict:!0})}catch(f){throw r.stdout.write(f.stdout||f.stack),f}}}}async function d5(e,{configuration:t,report:r,target:s}){let a=!1;if(!e.force&&le.existsSync(K.join(s,\".git\"))){r.reportInfo(0,\"Fetching the latest commits\"),r.reportSeparator();try{await $v(mot(e),{configuration:t,context:e.context,target:s}),a=!0}catch{r.reportSeparator(),r.reportWarning(0,\"Repository update failed; we'll try to regenerate it\")}}a||(r.reportInfo(0,\"Cloning the remote repository\"),r.reportSeparator(),await le.removePromise(s),await le.mkdirPromise(s,{recursive:!0}),await $v(dot(e,s),{configuration:t,context:e.context,target:s}))}async function Eot(e,t,{project:r,report:s,target:a}){let n=await Pm(r.configuration,t),c=new Set(Object.keys(n));for(let f of r.configuration.plugins.keys())c.has(f)&&await m5(f,e,{project:r,report:s,target:a})}qe();qe();Dt();Vt();var cde=et(pi()),ude=Ie(\"vm\");var EC=class extends At{constructor(){super(...arguments);this.name=he.String();this.checksum=he.Boolean(\"--checksum\",!0,{description:\"Whether to care if this plugin is modified\"})}static{this.paths=[[\"plugin\",\"import\"]]}static{this.usage=at.Usage({category:\"Plugin-related commands\",description:\"download a plugin\",details:`\n      This command downloads the specified plugin from its remote location and updates the configuration to reference it in further CLI invocations.\n\n      Three types of plugin references are accepted:\n\n      - If the plugin is stored within the Yarn repository, it can be referenced by name.\n      - Third-party plugins can be referenced directly through their public urls.\n      - Local plugins can be referenced by their path on the disk.\n\n      If the \\`--no-checksum\\` option is set, Yarn will no longer care if the plugin is modified.\n\n      Plugins cannot be downloaded from the npm registry, and aren't allowed to have dependencies (they need to be bundled into a single file, possibly thanks to the \\`@yarnpkg/builder\\` package).\n    `,examples:[['Download and activate the \"@yarnpkg/plugin-exec\" plugin',\"$0 plugin import @yarnpkg/plugin-exec\"],['Download and activate the \"@yarnpkg/plugin-exec\" plugin (shorthand)',\"$0 plugin import exec\"],[\"Download and activate a community plugin\",\"$0 plugin import https://example.org/path/to/plugin.js\"],[\"Activate a local plugin\",\"$0 plugin import ./path/to/plugin.js\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);return(await Ot.start({configuration:r,stdout:this.context.stdout},async a=>{let{project:n}=await Rt.find(r,this.context.cwd),c,f;if(this.name.match(/^\\.{0,2}[\\\\/]/)||fe.isAbsolute(this.name)){let p=K.resolve(this.context.cwd,fe.toPortablePath(this.name));a.reportInfo(0,`Reading ${pe.pretty(r,p,pe.Type.PATH)}`),c=K.relative(n.cwd,p),f=await le.readFilePromise(p)}else{let p;if(this.name.match(/^https?:/)){try{new URL(this.name)}catch{throw new _t(52,`Plugin specifier \"${this.name}\" is neither a plugin name nor a valid url`)}c=this.name,p=this.name}else{let h=j.parseLocator(this.name.replace(/^((@yarnpkg\\/)?plugin-)?/,\"@yarnpkg/plugin-\"));if(h.reference!==\"unknown\"&&!cde.default.valid(h.reference))throw new _t(0,\"Official plugins only accept strict version references. Use an explicit URL if you wish to download them from another location.\");let E=j.stringifyIdent(h),C=await Pm(r,An);if(!Object.hasOwn(C,E)){let S=`Couldn't find a plugin named ${j.prettyIdent(r,h)} on the remote registry.\n`;throw r.plugins.has(E)?S+=`A plugin named ${j.prettyIdent(r,h)} is already installed; possibly attempting to import a built-in plugin.`:S+=`Note that only the plugins referenced on our website (${pe.pretty(r,\"https://github.com/yarnpkg/berry/blob/master/plugins.yml\",pe.Type.URL)}) can be referenced by their name; any other plugin will have to be referenced through its public url (for example ${pe.pretty(r,\"https://github.com/yarnpkg/berry/raw/master/packages/plugin-typescript/bin/%40yarnpkg/plugin-typescript.js\",pe.Type.URL)}).`,new _t(51,S)}c=E,p=C[E].url,h.reference!==\"unknown\"?p=p.replace(/\\/master\\//,`/${E}/${h.reference}/`):An!==null&&(p=p.replace(/\\/master\\//,`/@yarnpkg/cli/${An}/`))}a.reportInfo(0,`Downloading ${pe.pretty(r,p,\"green\")}`),f=await nn.get(p,{configuration:r})}await y5(c,f,{checksum:this.checksum,project:n,report:a})})).exitCode()}};async function y5(e,t,{checksum:r=!0,project:s,report:a}){let{configuration:n}=s,c={},f={exports:c};(0,ude.runInNewContext)(t.toString(),{module:f,exports:c});let h=`.yarn/plugins/${f.exports.name}.cjs`,E=K.resolve(s.cwd,h);a.reportInfo(0,`Saving the new plugin in ${pe.pretty(n,h,\"magenta\")}`),await le.mkdirPromise(K.dirname(E),{recursive:!0}),await le.writeFilePromise(E,t);let C={path:h,spec:e};r&&(C.checksum=Ln.makeHash(t)),await ze.addPlugin(s.cwd,[C])}var Iot=({pluginName:e,noMinify:t},r)=>[[\"yarn\",`build:${e}`,...t?[\"--no-minify\"]:[],\"|\"]],IC=class extends At{constructor(){super(...arguments);this.installPath=he.String(\"--path\",{description:\"The path where the repository should be cloned to\"});this.repository=he.String(\"--repository\",\"https://github.com/yarnpkg/berry.git\",{description:\"The repository that should be cloned\"});this.branch=he.String(\"--branch\",\"master\",{description:\"The branch of the repository that should be cloned\"});this.noMinify=he.Boolean(\"--no-minify\",!1,{description:\"Build a plugin for development (debugging) - non-minified and non-mangled\"});this.force=he.Boolean(\"-f,--force\",!1,{description:\"Always clone the repository instead of trying to fetch the latest commits\"});this.name=he.String()}static{this.paths=[[\"plugin\",\"import\",\"from\",\"sources\"]]}static{this.usage=at.Usage({category:\"Plugin-related commands\",description:\"build a plugin from sources\",details:`\n      This command clones the Yarn repository into a temporary folder, builds the specified contrib plugin and updates the configuration to reference it in further CLI invocations.\n\n      The plugins can be referenced by their short name if sourced from the official Yarn repository.\n    `,examples:[['Build and activate the \"@yarnpkg/plugin-exec\" plugin',\"$0 plugin import from sources @yarnpkg/plugin-exec\"],['Build and activate the \"@yarnpkg/plugin-exec\" plugin (shorthand)',\"$0 plugin import from sources exec\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=typeof this.installPath<\"u\"?K.resolve(this.context.cwd,fe.toPortablePath(this.installPath)):K.resolve(fe.toPortablePath((0,fde.tmpdir)()),\"yarnpkg-sources\",Ln.makeHash(this.repository).slice(0,6));return(await Ot.start({configuration:r,stdout:this.context.stdout},async n=>{let{project:c}=await Rt.find(r,this.context.cwd),f=j.parseIdent(this.name.replace(/^((@yarnpkg\\/)?plugin-)?/,\"@yarnpkg/plugin-\")),p=j.stringifyIdent(f),h=await Pm(r,An);if(!Object.hasOwn(h,p))throw new _t(51,`Couldn't find a plugin named \"${p}\" on the remote registry. Note that only the plugins referenced on our website (https://github.com/yarnpkg/berry/blob/master/plugins.yml) can be built and imported from sources.`);let E=p;await d5(this,{configuration:r,report:n,target:s}),await m5(E,this,{project:c,report:n,target:s})})).exitCode()}};async function m5(e,{context:t,noMinify:r},{project:s,report:a,target:n}){let c=e.replace(/@yarnpkg\\//,\"\"),{configuration:f}=s;a.reportSeparator(),a.reportInfo(0,`Building a fresh ${c}`),a.reportSeparator(),await $v(Iot({pluginName:c,noMinify:r},n),{configuration:f,context:t,target:n}),a.reportSeparator();let p=K.resolve(n,`packages/${c}/bundles/${e}.js`),h=await le.readFilePromise(p);await y5(e,h,{project:s,report:a})}qe();Dt();Vt();var CC=class extends At{constructor(){super(...arguments);this.name=he.String()}static{this.paths=[[\"plugin\",\"remove\"]]}static{this.usage=at.Usage({category:\"Plugin-related commands\",description:\"remove a plugin\",details:`\n      This command deletes the specified plugin from the .yarn/plugins folder and removes it from the configuration.\n\n      **Note:** The plugins have to be referenced by their name property, which can be obtained using the \\`yarn plugin runtime\\` command. Shorthands are not allowed.\n   `,examples:[[\"Remove a plugin imported from the Yarn repository\",\"$0 plugin remove @yarnpkg/plugin-typescript\"],[\"Remove a plugin imported from a local file\",\"$0 plugin remove my-local-plugin\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd);return(await Ot.start({configuration:r,stdout:this.context.stdout},async n=>{let c=this.name,f=j.parseIdent(c);if(!r.plugins.has(c))throw new st(`${j.prettyIdent(r,f)} isn't referenced by the current configuration`);let p=`.yarn/plugins/${c}.cjs`,h=K.resolve(s.cwd,p);le.existsSync(h)&&(n.reportInfo(0,`Removing ${pe.pretty(r,p,pe.Type.PATH)}...`),await le.removePromise(h)),n.reportInfo(0,\"Updating the configuration...\"),await ze.updateConfiguration(s.cwd,{plugins:E=>{if(!Array.isArray(E))return E;let C=E.filter(S=>S.path!==p);return C.length===0?ze.deleteProperty:C.length===E.length?E:C}})})).exitCode()}};qe();Vt();var wC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"plugin\",\"runtime\"]]}static{this.usage=at.Usage({category:\"Plugin-related commands\",description:\"list the active plugins\",details:`\n      This command prints the currently active plugins. Will be displayed both builtin plugins and external plugins.\n    `,examples:[[\"List the currently active plugins\",\"$0 plugin runtime\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins);return(await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{for(let n of r.plugins.keys()){let c=this.context.plugins.plugins.has(n),f=n;c&&(f+=\" [builtin]\"),a.reportJson({name:n,builtin:c}),a.reportInfo(null,`${f}`)}})).exitCode()}};qe();qe();Vt();var BC=class extends At{constructor(){super(...arguments);this.idents=he.Rest()}static{this.paths=[[\"rebuild\"]]}static{this.usage=at.Usage({description:\"rebuild the project's native packages\",details:`\n      This command will automatically cause Yarn to forget about previous compilations of the given packages and to run them again.\n\n      Note that while Yarn forgets the compilation, the previous artifacts aren't erased from the filesystem and may affect the next builds (in good or bad). To avoid this, you may remove the .yarn/unplugged folder, or any other relevant location where packages might have been stored (Yarn may offer a way to do that automatically in the future).\n\n      By default all packages will be rebuilt, but you can filter the list by specifying the names of the packages you want to clear from memory.\n    `,examples:[[\"Rebuild all packages\",\"$0 rebuild\"],[\"Rebuild fsevents only\",\"$0 rebuild fsevents\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);let c=new Set;for(let f of this.idents)c.add(j.parseIdent(f).identHash);if(await s.restoreInstallState({restoreResolutions:!1}),await s.resolveEverything({cache:n,report:new ki}),c.size>0)for(let f of s.storedPackages.values())c.has(f.identHash)&&(s.storedBuildState.delete(f.locatorHash),s.skippedBuilds.delete(f.locatorHash));else s.storedBuildState.clear(),s.skippedBuilds.clear();return await s.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};qe();qe();qe();Vt();var E5=et(Jo());ul();var vC=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"-A,--all\",!1,{description:\"Apply the operation to all workspaces from the current project\"});this.mode=he.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:ks(Na)});this.patterns=he.Rest()}static{this.paths=[[\"remove\"]]}static{this.usage=at.Usage({description:\"remove dependencies from the project\",details:`\n      This command will remove the packages matching the specified patterns from the current workspace.\n\n      If the \\`--mode=<mode>\\` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n      - \\`skip-build\\` will not run the build scripts at all. Note that this is different from setting \\`enableScripts\\` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n      - \\`update-lockfile\\` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n      This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n    `,examples:[[\"Remove a dependency from the current project\",\"$0 remove lodash\"],[\"Remove a dependency from all workspaces at once\",\"$0 remove lodash --all\"],[\"Remove all dependencies starting with `eslint-`\",\"$0 remove 'eslint-*'\"],[\"Remove all dependencies with the `@babel` scope\",\"$0 remove '@babel/*'\"],[\"Remove all dependencies matching `react-dom` or `react-helmet`\",\"$0 remove 'react-{dom,helmet}'\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let c=this.all?s.workspaces:[a],f=[\"dependencies\",\"devDependencies\",\"peerDependencies\"],p=[],h=!1,E=[];for(let I of this.patterns){let T=!1,O=j.parseIdent(I);for(let U of c){let Y=[...U.manifest.peerDependenciesMeta.keys()];for(let te of(0,E5.default)(Y,I))U.manifest.peerDependenciesMeta.delete(te),h=!0,T=!0;for(let te of f){let ie=U.manifest.getForScope(te),ue=[...ie.values()].map(ae=>j.stringifyIdent(ae));for(let ae of(0,E5.default)(ue,j.stringifyIdent(O))){let{identHash:de}=j.parseIdent(ae),Ae=ie.get(de);if(typeof Ae>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");U.manifest[te].delete(de),E.push([U,te,Ae]),h=!0,T=!0}}}T||p.push(I)}let C=p.length>1?\"Patterns\":\"Pattern\",S=p.length>1?\"don't\":\"doesn't\",x=this.all?\"any\":\"this\";if(p.length>0)throw new st(`${C} ${pe.prettyList(r,p,pe.Type.CODE)} ${S} match any packages referenced by ${x} workspace`);return h?(await r.triggerMultipleHooks(I=>I.afterWorkspaceDependencyRemoval,E),await s.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})):0}};qe();qe();Vt();var Ade=Ie(\"util\"),SC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"run\"]]}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);return(await Ot.start({configuration:r,stdout:this.context.stdout,json:this.json},async c=>{let f=a.manifest.scripts,p=Ge.sortMap(f.keys(),C=>C),h={breakLength:1/0,colors:r.get(\"enableColors\"),maxArrayLength:2},E=p.reduce((C,S)=>Math.max(C,S.length),0);for(let[C,S]of f.entries())c.reportInfo(null,`${C.padEnd(E,\" \")}   ${(0,Ade.inspect)(S,h)}`),c.reportJson({name:C,script:S})})).exitCode()}};qe();qe();Vt();var DC=class extends At{constructor(){super(...arguments);this.inspect=he.String(\"--inspect\",!1,{tolerateBoolean:!0,description:\"Forwarded to the underlying Node process when executing a binary\"});this.inspectBrk=he.String(\"--inspect-brk\",!1,{tolerateBoolean:!0,description:\"Forwarded to the underlying Node process when executing a binary\"});this.topLevel=he.Boolean(\"-T,--top-level\",!1,{description:\"Check the root workspace for scripts and/or binaries instead of the current one\"});this.binariesOnly=he.Boolean(\"-B,--binaries-only\",!1,{description:\"Ignore any user defined scripts and only check for binaries\"});this.require=he.String(\"--require\",{description:\"Forwarded to the underlying Node process when executing a binary\"});this.silent=he.Boolean(\"--silent\",{hidden:!0});this.scriptName=he.String();this.args=he.Proxy()}static{this.paths=[[\"run\"]]}static{this.usage=at.Usage({description:\"run a script defined in the package.json\",details:`\n      This command will run a tool. The exact tool that will be executed will depend on the current state of your workspace:\n\n      - If the \\`scripts\\` field from your local package.json contains a matching script name, its definition will get executed.\n\n      - Otherwise, if one of the local workspace's dependencies exposes a binary with a matching name, this binary will get executed.\n\n      - Otherwise, if the specified name contains a colon character and if one of the workspaces in the project contains exactly one script with a matching name, then this script will get executed.\n\n      Whatever happens, the cwd of the spawned process will be the workspace that declares the script (which makes it possible to call commands cross-workspaces using the third syntax).\n    `,examples:[[\"Run the tests from the local workspace\",\"$0 run test\"],['Same thing, but without the \"run\" keyword',\"$0 test\"],[\"Inspect Webpack while running\",\"$0 run --inspect-brk webpack\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a,locator:n}=await Rt.find(r,this.context.cwd);await s.restoreInstallState();let c=this.topLevel?s.topLevelWorkspace.anchoredLocator:n;if(!this.binariesOnly&&await Cn.hasPackageScript(c,this.scriptName,{project:s}))return await Cn.executePackageScript(c,this.scriptName,this.args,{project:s,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});let f=await Cn.getPackageAccessibleBinaries(c,{project:s});if(f.get(this.scriptName)){let h=[];return this.inspect&&(typeof this.inspect==\"string\"?h.push(`--inspect=${this.inspect}`):h.push(\"--inspect\")),this.inspectBrk&&(typeof this.inspectBrk==\"string\"?h.push(`--inspect-brk=${this.inspectBrk}`):h.push(\"--inspect-brk\")),this.require&&h.push(`--require=${this.require}`),await Cn.executePackageAccessibleBinary(c,this.scriptName,this.args,{cwd:this.context.cwd,project:s,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,nodeArgs:h,packageAccessibleBinaries:f})}if(!this.topLevel&&!this.binariesOnly&&a&&this.scriptName.includes(\":\")){let E=(await Promise.all(s.workspaces.map(async C=>C.manifest.scripts.has(this.scriptName)?C:null))).filter(C=>C!==null);if(E.length===1)return await Cn.executeWorkspaceScript(E[0],this.scriptName,this.args,{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}if(this.topLevel)throw this.scriptName===\"node-gyp\"?new st(`Couldn't find a script name \"${this.scriptName}\" in the top-level (used by ${j.prettyLocator(r,n)}). This typically happens because some package depends on \"node-gyp\" to build itself, but didn't list it in their dependencies. To fix that, please run \"yarn add node-gyp\" into your top-level workspace. You also can open an issue on the repository of the specified package to suggest them to use an optional peer dependency.`):new st(`Couldn't find a script name \"${this.scriptName}\" in the top-level (used by ${j.prettyLocator(r,n)}).`);{if(this.scriptName===\"global\")throw new st(\"The 'yarn global' commands have been removed in 2.x - consider using 'yarn dlx' or a third-party plugin instead\");let h=[this.scriptName].concat(this.args);for(let[E,C]of qI)for(let S of C)if(h.length>=S.length&&JSON.stringify(h.slice(0,S.length))===JSON.stringify(S))throw new st(`Couldn't find a script named \"${this.scriptName}\", but a matching command can be found in the ${E} plugin. You can install it with \"yarn plugin import ${E}\".`);throw new st(`Couldn't find a script named \"${this.scriptName}\".`)}}};qe();qe();Vt();var bC=class extends At{constructor(){super(...arguments);this.descriptor=he.String();this.resolution=he.String()}static{this.paths=[[\"set\",\"resolution\"]]}static{this.usage=at.Usage({description:\"enforce a package resolution\",details:'\\n      This command updates the resolution table so that `descriptor` is resolved by `resolution`.\\n\\n      Note that by default this command only affect the current resolution table - meaning that this \"manual override\" will disappear if you remove the lockfile, or if the package disappear from the table. If you wish to make the enforced resolution persist whatever happens, edit the `resolutions` field in your top-level manifest.\\n\\n      Note that no attempt is made at validating that `resolution` is a valid resolution entry for `descriptor`.\\n    ',examples:[[\"Force all instances of lodash@npm:^1.2.3 to resolve to 1.5.0\",\"$0 set resolution lodash@npm:^1.2.3 npm:1.5.0\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(await s.restoreInstallState({restoreResolutions:!1}),!a)throw new ar(s.cwd,this.context.cwd);let c=j.parseDescriptor(this.descriptor,!0),f=j.makeDescriptor(c,this.resolution);return s.storedDescriptors.set(c.descriptorHash,c),s.storedDescriptors.set(f.descriptorHash,f),s.resolutionAliases.set(c.descriptorHash,f.descriptorHash),await s.installWithNewReport({stdout:this.context.stdout},{cache:n})}};qe();Dt();Vt();var pde=et(Jo()),PC=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"-A,--all\",!1,{description:\"Unlink all workspaces belonging to the target project from the current one\"});this.leadingArguments=he.Rest()}static{this.paths=[[\"unlink\"]]}static{this.usage=at.Usage({description:\"disconnect the local project from another one\",details:`\n      This command will remove any resolutions in the project-level manifest that would have been added via a yarn link with similar arguments.\n    `,examples:[[\"Unregister a remote workspace in the current project\",\"$0 unlink ~/ts-loader\"],[\"Unregister all workspaces from a remote project in the current project\",\"$0 unlink ~/jest --all\"],[\"Unregister all previously linked workspaces\",\"$0 unlink --all\"],[\"Unregister all workspaces matching a glob\",\"$0 unlink '@babel/*' 'pkg-{a,b}'\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);let c=s.topLevelWorkspace,f=new Set;if(this.leadingArguments.length===0&&this.all)for(let{pattern:p,reference:h}of c.manifest.resolutions)h.startsWith(\"portal:\")&&f.add(p.descriptor.fullName);if(this.leadingArguments.length>0)for(let p of this.leadingArguments){let h=K.resolve(this.context.cwd,fe.toPortablePath(p));if(Ge.isPathLike(p)){let E=await ze.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:C,workspace:S}=await Rt.find(E,h);if(!S)throw new ar(C.cwd,h);if(this.all){for(let x of C.workspaces)x.manifest.name&&f.add(j.stringifyIdent(x.anchoredLocator));if(f.size===0)throw new st(\"No workspace found to be unlinked in the target project\")}else{if(!S.manifest.name)throw new st(\"The target workspace doesn't have a name and thus cannot be unlinked\");f.add(j.stringifyIdent(S.anchoredLocator))}}else{let E=[...c.manifest.resolutions.map(({pattern:C})=>C.descriptor.fullName)];for(let C of(0,pde.default)(E,p))f.add(C)}}return c.manifest.resolutions=c.manifest.resolutions.filter(({pattern:p})=>!f.has(p.descriptor.fullName)),await s.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};qe();qe();qe();Vt();var hde=et(Yv()),I5=et(Jo());ul();var xC=class extends At{constructor(){super(...arguments);this.interactive=he.Boolean(\"-i,--interactive\",{description:\"Offer various choices, depending on the detected upgrade paths\"});this.fixed=he.Boolean(\"-F,--fixed\",!1,{description:\"Store dependency tags as-is instead of resolving them\"});this.exact=he.Boolean(\"-E,--exact\",!1,{description:\"Don't use any semver modifier on the resolved range\"});this.tilde=he.Boolean(\"-T,--tilde\",!1,{description:\"Use the `~` semver modifier on the resolved range\"});this.caret=he.Boolean(\"-C,--caret\",!1,{description:\"Use the `^` semver modifier on the resolved range\"});this.recursive=he.Boolean(\"-R,--recursive\",!1,{description:\"Resolve again ALL resolutions for those packages\"});this.mode=he.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:ks(Na)});this.patterns=he.Rest()}static{this.paths=[[\"up\"]]}static{this.usage=at.Usage({description:\"upgrade dependencies across the project\",details:\"\\n      This command upgrades the packages matching the list of specified patterns to their latest available version across the whole project (regardless of whether they're part of `dependencies` or `devDependencies` - `peerDependencies` won't be affected). This is a project-wide command: all workspaces will be upgraded in the process.\\n\\n      If `-R,--recursive` is set the command will change behavior and no other switch will be allowed. When operating under this mode `yarn up` will force all ranges matching the selected packages to be resolved again (often to the highest available versions) before being stored in the lockfile. It however won't touch your manifests anymore, so depending on your needs you might want to run both `yarn up` and `yarn up -R` to cover all bases.\\n\\n      If `-i,--interactive` is set (or if the `preferInteractive` settings is toggled on) the command will offer various choices, depending on the detected upgrade paths. Some upgrades require this flag in order to resolve ambiguities.\\n\\n      The, `-C,--caret`, `-E,--exact` and  `-T,--tilde` options have the same meaning as in the `add` command (they change the modifier used when the range is missing or a tag, and are ignored when the range is explicitly set).\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n\\n      Generally you can see `yarn up` as a counterpart to what was `yarn upgrade --latest` in Yarn 1 (ie it ignores the ranges previously listed in your manifests), but unlike `yarn upgrade` which only upgraded dependencies in the current workspace, `yarn up` will upgrade all workspaces at the same time.\\n\\n      This command accepts glob patterns as arguments (if valid Descriptors and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\\n\\n      **Note:** The ranges have to be static, only the package scopes and names can contain glob patterns.\\n    \",examples:[[\"Upgrade all instances of lodash to the latest release\",\"$0 up lodash\"],[\"Upgrade all instances of lodash to the latest release, but ask confirmation for each\",\"$0 up lodash -i\"],[\"Upgrade all instances of lodash to 1.2.3\",\"$0 up lodash@1.2.3\"],[\"Upgrade all instances of packages with the `@babel` scope to the latest release\",\"$0 up '@babel/*'\"],[\"Upgrade all instances of packages containing the word `jest` to the latest release\",\"$0 up '*jest*'\"],[\"Upgrade all instances of packages with the `@babel` scope to 7.0.0\",\"$0 up '@babel/*@7.0.0'\"]]})}static{this.schema=[YB(\"recursive\",Vf.Forbids,[\"interactive\",\"exact\",\"tilde\",\"caret\"],{ignore:[void 0,!1]})]}async execute(){return this.recursive?await this.executeUpRecursive():await this.executeUpClassic()}async executeUpRecursive(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let c=[...s.storedDescriptors.values()],f=c.map(E=>j.stringifyIdent(E)),p=new Set;for(let E of this.patterns){if(j.parseDescriptor(E).range!==\"unknown\")throw new st(\"Ranges aren't allowed when using --recursive\");for(let C of(0,I5.default)(f,E)){let S=j.parseIdent(C);p.add(S.identHash)}}let h=c.filter(E=>p.has(E.identHash));for(let E of h)s.storedDescriptors.delete(E.descriptorHash),s.storedResolutions.delete(E.descriptorHash);return await s.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}async executeUpClassic(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let c=this.fixed,f=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=Jv(this,s),h=f?[\"keep\",\"reuse\",\"project\",\"latest\"]:[\"project\",\"latest\"],E=[],C=[];for(let O of this.patterns){let U=!1,Y=j.parseDescriptor(O),te=j.stringifyIdent(Y);for(let ie of s.workspaces)for(let ue of[\"dependencies\",\"devDependencies\"]){let de=[...ie.manifest.getForScope(ue).values()].map(Ce=>j.stringifyIdent(Ce)),Ae=te===\"*\"?de:(0,I5.default)(de,te);for(let Ce of Ae){let Ee=j.parseIdent(Ce),g=ie.manifest[ue].get(Ee.identHash);if(typeof g>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let Se=j.makeDescriptor(Ee,Y.range);E.push(Promise.resolve().then(async()=>[ie,ue,g,await zv(Se,{project:s,workspace:ie,cache:n,target:ue,fixed:c,modifier:p,strategies:h})])),U=!0}}U||C.push(O)}if(C.length>1)throw new st(`Patterns ${pe.prettyList(r,C,pe.Type.CODE)} don't match any packages referenced by any workspace`);if(C.length>0)throw new st(`Pattern ${pe.prettyList(r,C,pe.Type.CODE)} doesn't match any packages referenced by any workspace`);let S=await Promise.all(E),x=await cA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async O=>{for(let[,,U,{suggestions:Y,rejections:te}]of S){let ie=Y.filter(ue=>ue.descriptor!==null);if(ie.length===0){let[ue]=te;if(typeof ue>\"u\")throw new Error(\"Assertion failed: Expected an error to have been set\");let ae=this.cli.error(ue);s.configuration.get(\"enableNetwork\")?O.reportError(27,`${j.prettyDescriptor(r,U)} can't be resolved to a satisfying range\n\n${ae}`):O.reportError(27,`${j.prettyDescriptor(r,U)} can't be resolved to a satisfying range (note: network resolution has been disabled)\n\n${ae}`)}else ie.length>1&&!f&&O.reportError(27,`${j.prettyDescriptor(r,U)} has multiple possible upgrade strategies; use -i to disambiguate manually`)}});if(x.hasErrors())return x.exitCode();let I=!1,T=[];for(let[O,U,,{suggestions:Y}]of S){let te,ie=Y.filter(Ae=>Ae.descriptor!==null),ue=ie[0].descriptor,ae=ie.every(Ae=>j.areDescriptorsEqual(Ae.descriptor,ue));ie.length===1||ae?te=ue:(I=!0,{answer:te}=await(0,hde.prompt)({type:\"select\",name:\"answer\",message:`Which range do you want to use in ${j.prettyWorkspace(r,O)} \\u276F ${U}?`,choices:Y.map(({descriptor:Ae,name:Ce,reason:Ee})=>Ae?{name:Ce,hint:Ee,descriptor:Ae}:{name:Ce,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(Ae){return this.find(Ae,\"descriptor\")},stdin:this.context.stdin,stdout:this.context.stdout}));let de=O.manifest[U].get(te.identHash);if(typeof de>\"u\")throw new Error(\"Assertion failed: This descriptor should have a matching entry\");if(de.descriptorHash!==te.descriptorHash)O.manifest[U].set(te.identHash,te),T.push([O,U,de,te]);else{let Ae=r.makeResolver(),Ce={project:s,resolver:Ae},Ee=r.normalizeDependency(de),g=Ae.bindDescriptor(Ee,O.anchoredLocator,Ce);s.forgetResolution(g)}}return await r.triggerMultipleHooks(O=>O.afterWorkspaceDependencyReplacement,T),I&&this.context.stdout.write(`\n`),await s.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}};qe();qe();qe();Vt();var kC=class extends At{constructor(){super(...arguments);this.recursive=he.Boolean(\"-R,--recursive\",!1,{description:\"List, for each workspace, what are all the paths that lead to the dependency\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.peers=he.Boolean(\"--peers\",!1,{description:\"Also print the peer dependencies that match the specified name\"});this.package=he.String()}static{this.paths=[[\"why\"]]}static{this.usage=at.Usage({description:\"display the reason why a package is needed\",details:`\n      This command prints the exact reasons why a package appears in the dependency tree.\n\n      If \\`-R,--recursive\\` is set, the listing will go in depth and will list, for each workspaces, what are all the paths that lead to the dependency. Note that the display is somewhat optimized in that it will not print the package listing twice for a single package, so if you see a leaf named \"Foo\" when looking for \"Bar\", it means that \"Foo\" already got printed higher in the tree.\n    `,examples:[[\"Explain why lodash is used in your project\",\"$0 why lodash\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState();let n=j.parseIdent(this.package).identHash,c=this.recursive?wot(s,n,{configuration:r,peers:this.peers}):Cot(s,n,{configuration:r,peers:this.peers});Rs.emitTree(c,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1})}};function Cot(e,t,{configuration:r,peers:s}){let a=Ge.sortMap(e.storedPackages.values(),f=>j.stringifyLocator(f)),n={},c={children:n};for(let f of a){let p={};for(let E of f.dependencies.values()){if(!s&&f.peerDependencies.has(E.identHash))continue;let C=e.storedResolutions.get(E.descriptorHash);if(!C)throw new Error(\"Assertion failed: The resolution should have been registered\");let S=e.storedPackages.get(C);if(!S)throw new Error(\"Assertion failed: The package should have been registered\");if(S.identHash!==t)continue;{let I=j.stringifyLocator(f);n[I]={value:[f,pe.Type.LOCATOR],children:p}}let x=j.stringifyLocator(S);p[x]={value:[{descriptor:E,locator:S},pe.Type.DEPENDENT]}}}return c}function wot(e,t,{configuration:r,peers:s}){let a=Ge.sortMap(e.workspaces,S=>j.stringifyLocator(S.anchoredLocator)),n=new Set,c=new Set,f=S=>{if(n.has(S.locatorHash))return c.has(S.locatorHash);if(n.add(S.locatorHash),S.identHash===t)return c.add(S.locatorHash),!0;let x=!1;S.identHash===t&&(x=!0);for(let I of S.dependencies.values()){if(!s&&S.peerDependencies.has(I.identHash))continue;let T=e.storedResolutions.get(I.descriptorHash);if(!T)throw new Error(\"Assertion failed: The resolution should have been registered\");let O=e.storedPackages.get(T);if(!O)throw new Error(\"Assertion failed: The package should have been registered\");f(O)&&(x=!0)}return x&&c.add(S.locatorHash),x};for(let S of a)f(S.anchoredPackage);let p=new Set,h={},E={children:h},C=(S,x,I)=>{if(!c.has(S.locatorHash))return;let T=I!==null?pe.tuple(pe.Type.DEPENDENT,{locator:S,descriptor:I}):pe.tuple(pe.Type.LOCATOR,S),O={},U={value:T,children:O},Y=j.stringifyLocator(S);if(x[Y]=U,!(I!==null&&e.tryWorkspaceByLocator(S))&&!p.has(S.locatorHash)){p.add(S.locatorHash);for(let te of S.dependencies.values()){if(!s&&S.peerDependencies.has(te.identHash))continue;let ie=e.storedResolutions.get(te.descriptorHash);if(!ie)throw new Error(\"Assertion failed: The resolution should have been registered\");let ue=e.storedPackages.get(ie);if(!ue)throw new Error(\"Assertion failed: The package should have been registered\");C(ue,O,te)}}};for(let S of a)C(S.anchoredPackage,h,null);return E}qe();var k5={};Yt(k5,{GitFetcher:()=>tS,GitResolver:()=>rS,default:()=>Got,gitUtils:()=>Oa});qe();Dt();var Oa={};Yt(Oa,{TreeishProtocols:()=>eS,clone:()=>x5,fetchBase:()=>Nde,fetchChangedFiles:()=>Ode,fetchChangedWorkspaces:()=>Hot,fetchRoot:()=>Fde,isGitUrl:()=>TC,lsRemote:()=>Tde,normalizeLocator:()=>_ot,normalizeRepoUrl:()=>QC,resolveUrl:()=>P5,splitRepoUrl:()=>G0,validateRepoUrl:()=>b5});qe();Dt();Vt();Jl();var Qde=et(Pde()),RC=et(Ie(\"querystring\")),S5=et(pi());function v5(e,t,r){let s=e.indexOf(r);return e.lastIndexOf(t,s>-1?s:1/0)}function xde(e){try{return new URL(e)}catch{return}}function Mot(e){let t=v5(e,\"@\",\"#\"),r=v5(e,\":\",\"#\");return r>t&&(e=`${e.slice(0,r)}/${e.slice(r+1)}`),v5(e,\":\",\"#\")===-1&&e.indexOf(\"//\")===-1&&(e=`ssh://${e}`),e}function kde(e){return xde(e)||xde(Mot(e))}function QC(e,{git:t=!1}={}){if(e=e.replace(/^git\\+https:/,\"https:\"),e=e.replace(/^(?:github:|https:\\/\\/github\\.com\\/|git:\\/\\/github\\.com\\/)?(?!\\.{1,2}\\/)([a-zA-Z0-9._-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)(?:\\.git)?(#.*)?$/,\"https://github.com/$1/$2.git$3\"),e=e.replace(/^https:\\/\\/github\\.com\\/(?!\\.{1,2}\\/)([a-zA-Z0-9._-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\\/tarball\\/(.+)?$/,\"https://github.com/$1/$2.git#$3\"),t){let r=kde(e);r&&(e=r.href),e=e.replace(/^git\\+([^:]+):/,\"$1:\")}return e}function Rde(){return{...process.env,GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||`${process.env.GIT_SSH||\"ssh\"} -o BatchMode=yes`}}var Uot=[/^ssh:/,/^git(?:\\+[^:]+)?:/,/^(?:git\\+)?https?:[^#]+\\/[^#]+(?:\\.git)(?:#.*)?$/,/^git@[^#]+\\/[^#]+\\.git(?:#.*)?$/,/^(?:github:|https:\\/\\/github\\.com\\/)?(?!\\.{1,2}\\/)([a-zA-Z._0-9-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z._0-9-]+?)(?:\\.git)?(?:#.*)?$/,/^https:\\/\\/github\\.com\\/(?!\\.{1,2}\\/)([a-zA-Z0-9._-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\\/tarball\\/(.+)?$/],eS=(a=>(a.Commit=\"commit\",a.Head=\"head\",a.Tag=\"tag\",a.Semver=\"semver\",a))(eS||{});function TC(e){return e?Uot.some(t=>!!e.match(t)):!1}function G0(e){e=QC(e);let t=e.indexOf(\"#\");if(t===-1)return{repo:e,treeish:{protocol:\"head\",request:\"HEAD\"},extra:{}};let r=e.slice(0,t),s=e.slice(t+1);if(s.match(/^[a-z]+=/)){let a=RC.default.parse(s);for(let[p,h]of Object.entries(a))if(typeof h!=\"string\")throw new Error(`Assertion failed: The ${p} parameter must be a literal string`);let n=Object.values(eS).find(p=>Object.hasOwn(a,p)),[c,f]=typeof n<\"u\"?[n,a[n]]:[\"head\",\"HEAD\"];for(let p of Object.values(eS))delete a[p];return{repo:r,treeish:{protocol:c,request:f},extra:a}}else{let a=s.indexOf(\":\"),[n,c]=a===-1?[null,s]:[s.slice(0,a),s.slice(a+1)];return{repo:r,treeish:{protocol:n,request:c},extra:{}}}}function _ot(e){return j.makeLocator(e,QC(e.reference))}function b5(e,{configuration:t}){let r=QC(e,{git:!0});if(!nn.getNetworkSettings(`https://${(0,Qde.default)(r).resource}`,{configuration:t}).enableNetwork)throw new _t(80,`Request to '${r}' has been blocked because of your configuration settings`);return r}async function Tde(e,t){let r=b5(e,{configuration:t}),s=await D5(\"listing refs\",[\"ls-remote\",r],{cwd:t.startingCwd,env:Rde()},{configuration:t,normalizedRepoUrl:r}),a=new Map,n=/^([a-f0-9]{40})\\t([^\\n]+)/gm,c;for(;(c=n.exec(s.stdout))!==null;)a.set(c[2],c[1]);return a}async function P5(e,t){let{repo:r,treeish:{protocol:s,request:a},extra:n}=G0(e),c=await Tde(r,t),f=(h,E)=>{switch(h){case\"commit\":{if(!E.match(/^[a-f0-9]{40}$/))throw new Error(\"Invalid commit hash\");return RC.default.stringify({...n,commit:E})}case\"head\":{let C=c.get(E===\"HEAD\"?E:`refs/heads/${E}`);if(typeof C>\"u\")throw new Error(`Unknown head (\"${E}\")`);return RC.default.stringify({...n,commit:C})}case\"tag\":{let C=c.get(`refs/tags/${E}`);if(typeof C>\"u\")throw new Error(`Unknown tag (\"${E}\")`);return RC.default.stringify({...n,commit:C})}case\"semver\":{let C=Fr.validRange(E);if(!C)throw new Error(`Invalid range (\"${E}\")`);let S=new Map([...c.entries()].filter(([I])=>I.startsWith(\"refs/tags/\")).map(([I,T])=>[S5.default.parse(I.slice(10)),T]).filter(I=>I[0]!==null)),x=S5.default.maxSatisfying([...S.keys()],C);if(x===null)throw new Error(`No matching range (\"${E}\")`);return RC.default.stringify({...n,commit:S.get(x)})}case null:{let C;if((C=p(\"commit\",E))!==null||(C=p(\"tag\",E))!==null||(C=p(\"head\",E))!==null)return C;throw E.match(/^[a-f0-9]+$/)?new Error(`Couldn't resolve \"${E}\" as either a commit, a tag, or a head - if a commit, use the 40-characters commit hash`):new Error(`Couldn't resolve \"${E}\" as either a commit, a tag, or a head`)}default:throw new Error(`Invalid Git resolution protocol (\"${h}\")`)}},p=(h,E)=>{try{return f(h,E)}catch{return null}};return QC(`${r}#${f(s,a)}`)}async function x5(e,t){return await t.getLimit(\"cloneConcurrency\")(async()=>{let{repo:r,treeish:{protocol:s,request:a}}=G0(e);if(s!==\"commit\")throw new Error(\"Invalid treeish protocol when cloning\");let n=b5(r,{configuration:t}),c=await le.mktempPromise(),f={cwd:c,env:Rde()};return await D5(\"cloning the repository\",[\"clone\",\"-c\",\"core.autocrlf=false\",n,fe.fromPortablePath(c)],f,{configuration:t,normalizedRepoUrl:n}),await D5(\"switching branch\",[\"checkout\",`${a}`],f,{configuration:t,normalizedRepoUrl:n}),c})}async function Fde(e){let t,r=e;do{if(t=r,await le.existsPromise(K.join(t,\".git\")))return t;r=K.dirname(t)}while(r!==t);return null}async function Nde(e,{baseRefs:t}){if(t.length===0)throw new st(\"Can't run this command with zero base refs specified.\");let r=[];for(let f of t){let{code:p}=await qr.execvp(\"git\",[\"merge-base\",f,\"HEAD\"],{cwd:e});p===0&&r.push(f)}if(r.length===0)throw new st(`No ancestor could be found between any of HEAD and ${t.join(\", \")}`);let{stdout:s}=await qr.execvp(\"git\",[\"merge-base\",\"HEAD\",...r],{cwd:e,strict:!0}),a=s.trim(),{stdout:n}=await qr.execvp(\"git\",[\"show\",\"--quiet\",\"--pretty=format:%s\",a],{cwd:e,strict:!0}),c=n.trim();return{hash:a,title:c}}async function Ode(e,{base:t,project:r}){let s=Ge.buildIgnorePattern(r.configuration.get(\"changesetIgnorePatterns\")),{stdout:a}=await qr.execvp(\"git\",[\"diff\",\"--name-only\",`${t}`],{cwd:e,strict:!0}),n=a.split(/\\r\\n|\\r|\\n/).filter(h=>h.length>0).map(h=>K.resolve(e,fe.toPortablePath(h))),{stdout:c}=await qr.execvp(\"git\",[\"ls-files\",\"--others\",\"--exclude-standard\"],{cwd:e,strict:!0}),f=c.split(/\\r\\n|\\r|\\n/).filter(h=>h.length>0).map(h=>K.resolve(e,fe.toPortablePath(h))),p=[...new Set([...n,...f].sort())];return s?p.filter(h=>!K.relative(r.cwd,h).match(s)):p}async function Hot({ref:e,project:t}){if(t.configuration.projectCwd===null)throw new st(\"This command can only be run from within a Yarn project\");let r=[K.resolve(t.cwd,Er.lockfile),K.resolve(t.cwd,t.configuration.get(\"cacheFolder\")),K.resolve(t.cwd,t.configuration.get(\"installStatePath\")),K.resolve(t.cwd,t.configuration.get(\"virtualFolder\"))];await t.configuration.triggerHook(c=>c.populateYarnPaths,t,c=>{c!=null&&r.push(c)});let s=await Fde(t.configuration.projectCwd);if(s==null)throw new st(\"This command can only be run on Git repositories\");let a=await Nde(s,{baseRefs:typeof e==\"string\"?[e]:t.configuration.get(\"changesetBaseRefs\")}),n=await Ode(s,{base:a.hash,project:t});return new Set(Ge.mapAndFilter(n,c=>{let f=t.tryWorkspaceByFilePath(c);return f===null?Ge.mapAndFilter.skip:r.some(p=>c.startsWith(p))?Ge.mapAndFilter.skip:f}))}async function D5(e,t,r,{configuration:s,normalizedRepoUrl:a}){try{return await qr.execvp(\"git\",t,{...r,strict:!0})}catch(n){if(!(n instanceof qr.ExecError))throw n;let c=n.reportExtra,f=n.stderr.toString();throw new _t(1,`Failed ${e}`,p=>{p.reportError(1,`  ${pe.prettyField(s,{label:\"Repository URL\",value:pe.tuple(pe.Type.URL,a)})}`);for(let h of f.matchAll(/^(.+?): (.*)$/gm)){let[,E,C]=h;E=E.toLowerCase();let S=E===\"error\"?\"Error\":`${E2(E)} Error`;p.reportError(1,`  ${pe.prettyField(s,{label:S,value:pe.tuple(pe.Type.NO_HINT,C)})}`)}c?.(p)})}}var tS=class{supports(t,r){return TC(t.reference)}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,a=new Map(r.checksums);a.set(t.locatorHash,s);let n={...r,checksums:a},c=await this.downloadHosted(t,n);if(c!==null)return c;let[f,p,h]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the remote repository`),loader:()=>this.cloneFromRemote(t,n),...r.cacheOptions});return{packageFs:f,releaseFs:p,prefixPath:j.getIdentVendorPath(t),checksum:h}}async downloadHosted(t,r){return r.project.configuration.reduceHook(s=>s.fetchHostedRepository,null,t,r)}async cloneFromRemote(t,r){let s=G0(t.reference),a=await x5(t.reference,r.project.configuration),n=K.resolve(a,s.extra.cwd??vt.dot),c=K.join(n,\"package.tgz\");await Cn.prepareExternalProject(n,c,{configuration:r.project.configuration,report:r.report,workspace:s.extra.workspace,locator:t});let f=await le.readFilePromise(c);return await Ge.releaseAfterUseAsync(async()=>await ds.convertToZip(f,{configuration:r.project.configuration,prefixPath:j.getIdentVendorPath(t),stripComponents:1}))}};qe();qe();var rS=class{supportsDescriptor(t,r){return TC(t.range)}supportsLocator(t,r){return TC(t.reference)}shouldPersistResolution(t,r){return!0}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){let a=await P5(t.range,s.project.configuration);return[j.makeLocator(t,a)]}async getSatisfying(t,r,s,a){let n=G0(t.range);return{locators:s.filter(f=>{if(f.identHash!==t.identHash)return!1;let p=G0(f.reference);return!(n.repo!==p.repo||n.treeish.protocol===\"commit\"&&n.treeish.request!==p.treeish.request)}),sorted:!1}}async resolve(t,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let s=await r.fetchOptions.fetcher.fetch(t,r.fetchOptions),a=await Ge.releaseAfterUseAsync(async()=>await Ut.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...t,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var jot={configuration:{changesetBaseRefs:{description:\"The base git refs that the current HEAD is compared against when detecting changes. Supports git branches, tags, and commits.\",type:\"STRING\",isArray:!0,isNullable:!1,default:[\"master\",\"origin/master\",\"upstream/master\",\"main\",\"origin/main\",\"upstream/main\"]},changesetIgnorePatterns:{description:\"Array of glob patterns; files matching them will be ignored when fetching the changed files\",type:\"STRING\",default:[],isArray:!0},cloneConcurrency:{description:\"Maximal number of concurrent clones\",type:\"NUMBER\",default:2}},fetchers:[tS],resolvers:[rS]};var Got=jot;Vt();var FC=class extends At{constructor(){super(...arguments);this.since=he.String(\"--since\",{description:\"Only include workspaces that have been changed since the specified ref.\",tolerateBoolean:!0});this.recursive=he.Boolean(\"-R,--recursive\",!1,{description:\"Find packages via dependencies/devDependencies instead of using the workspaces field\"});this.noPrivate=he.Boolean(\"--no-private\",{description:\"Exclude workspaces that have the private field set to true\"});this.verbose=he.Boolean(\"-v,--verbose\",!1,{description:\"Also return the cross-dependencies between workspaces\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"workspaces\",\"list\"]]}static{this.usage=at.Usage({category:\"Workspace-related commands\",description:\"list all available workspaces\",details:\"\\n      This command will print the list of all workspaces in the project.\\n\\n      - If `--since` is set, Yarn will only list workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\\n\\n      - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\\n\\n      - If `--no-private` is set, Yarn will not list any workspaces that have the `private` field set to `true`.\\n\\n      - If both the `-v,--verbose` and `--json` options are set, Yarn will also return the cross-dependencies between each workspaces (useful when you wish to automatically generate Buck / Bazel rules).\\n    \"})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd);return(await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{let c=this.since?await Oa.fetchChangedWorkspaces({ref:this.since,project:s}):s.workspaces,f=new Set(c);if(this.recursive)for(let p of[...c].map(h=>h.getRecursiveWorkspaceDependents()))for(let h of p)f.add(h);for(let p of f){let{manifest:h}=p;if(h.private&&this.noPrivate)continue;let E;if(this.verbose){let C=new Set,S=new Set;for(let x of Ut.hardDependencies)for(let[I,T]of h.getForScope(x)){let O=s.tryWorkspaceByDescriptor(T);O===null?s.workspacesByIdent.has(I)&&S.add(T):C.add(O)}E={workspaceDependencies:Array.from(C).map(x=>x.relativeCwd),mismatchedWorkspaceDependencies:Array.from(S).map(x=>j.stringifyDescriptor(x))}}n.reportInfo(null,`${p.relativeCwd}`),n.reportJson({location:p.relativeCwd,name:h.name?j.stringifyIdent(h.name):null,...E})}})).exitCode()}};qe();qe();Vt();var NC=class extends At{constructor(){super(...arguments);this.workspaceName=he.String();this.commandName=he.String();this.args=he.Proxy()}static{this.paths=[[\"workspace\"]]}static{this.usage=at.Usage({category:\"Workspace-related commands\",description:\"run a command within the specified workspace\",details:`\n      This command will run a given sub-command on a single workspace.\n    `,examples:[[\"Add a package to a single workspace\",\"yarn workspace components add -D react\"],[\"Run build script on a single workspace\",\"yarn workspace components run build\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);let n=s.workspaces,c=new Map(n.map(p=>[j.stringifyIdent(p.anchoredLocator),p])),f=c.get(this.workspaceName);if(f===void 0){let p=Array.from(c.keys()).sort();throw new st(`Workspace '${this.workspaceName}' not found. Did you mean any of the following:\n  - ${p.join(`\n  - `)}?`)}return this.cli.run([this.commandName,...this.args],{cwd:f.cwd})}};var qot={configuration:{enableImmutableInstalls:{description:\"If true (the default on CI), prevents the install command from modifying the lockfile\",type:\"BOOLEAN\",default:Lde.isCI},defaultSemverRangePrefix:{description:\"The default save prefix: '^', '~' or ''\",type:\"STRING\",values:[\"^\",\"~\",\"\"],default:\"^\"},preferReuse:{description:\"If true, `yarn add` will attempt to reuse the most common dependency range in other workspaces.\",type:\"BOOLEAN\",default:!1}},commands:[XI,$I,eC,tC,bC,yC,uC,FC,iC,sC,oC,aC,zI,ZI,rC,nC,lC,cC,fC,AC,pC,hC,PC,gC,dC,IC,EC,CC,mC,wC,BC,vC,SC,DC,xC,kC,NC]},Wot=qot;var N5={};Yt(N5,{default:()=>Jot});qe();qe();var R5=\"catalog:\";var T5=e=>e.startsWith(R5),Vot=e=>e.range.slice(R5.length)||null,Mde=e=>e===null?\"default catalog\":`catalog \"${e}\"`,Yot=e=>e.scope?`@${e.scope}/${e.name}`:e.name,F5=(e,t,r,s)=>{let a=Vot(t),n;if(a===null)n=e.configuration.get(\"catalog\");else try{let E=e.configuration.get(\"catalogs\");E&&(n=E.get(a))}catch{n=void 0}if(!n||n.size===0)throw new _t(82,`${j.prettyDescriptor(e.configuration,t)}: ${Mde(a)} not found or empty`);let c=Yot(t),f=n.get(c);if(!f)throw new _t(82,`${j.prettyDescriptor(e.configuration,t)}: entry not found in ${Mde(a)}`);let p=e.configuration.normalizeDependency(j.makeDescriptor(t,f));return r.supportsDescriptor(p,s)?r.bindDescriptor(p,e.topLevelWorkspace.anchoredLocator,s):p};var Kot={configuration:{catalog:{description:\"The default catalog of packages\",type:\"MAP\",valueDefinition:{description:\"The catalog of packages\",type:\"STRING\"}},catalogs:{description:\"Named catalogs of packages\",type:\"MAP\",valueDefinition:{description:\"A named catalog\",type:\"MAP\",valueDefinition:{description:\"Package version in the catalog\",type:\"STRING\"}}}},hooks:{beforeWorkspacePacking:(e,t)=>{let r=e.project,s=r.configuration.makeResolver(),a={project:r,resolver:s,report:new ki};for(let n of Ut.allDependencies){let c=t[n];if(c)for(let[f,p]of Object.entries(c)){if(typeof p!=\"string\"||!T5(p))continue;let h=j.parseIdent(f),E=j.makeDescriptor(h,p),C=F5(r,E,s,a),{protocol:S,source:x,params:I,selector:T}=j.parseRange(j.convertToManifestRange(C.range));S===e.project.configuration.get(\"defaultProtocol\")&&(S=null),c[f]=j.makeRange({protocol:S,source:x,params:I,selector:T})}}},reduceDependency:async(e,t,r,s,{resolver:a,resolveOptions:n})=>T5(e.range)?F5(t,e,a,n):e}},Jot=Kot;var _5={};Yt(_5,{default:()=>Zot});qe();var Qt={optional:!0},O5=[[\"@tailwindcss/aspect-ratio@<0.2.1\",{peerDependencies:{tailwindcss:\"^2.0.2\"}}],[\"@tailwindcss/line-clamp@<0.2.1\",{peerDependencies:{tailwindcss:\"^2.0.2\"}}],[\"@fullhuman/postcss-purgecss@3.1.3 || 3.1.3-alpha.0\",{peerDependencies:{postcss:\"^8.0.0\"}}],[\"@samverschueren/stream-to-observable@<0.3.1\",{peerDependenciesMeta:{rxjs:Qt,zenObservable:Qt}}],[\"any-observable@<0.5.1\",{peerDependenciesMeta:{rxjs:Qt,zenObservable:Qt}}],[\"@pm2/agent@<1.0.4\",{dependencies:{debug:\"*\"}}],[\"debug@<4.2.0\",{peerDependenciesMeta:{\"supports-color\":Qt}}],[\"got@<11\",{dependencies:{\"@types/responselike\":\"^1.0.0\",\"@types/keyv\":\"^3.1.1\"}}],[\"cacheable-lookup@<4.1.2\",{dependencies:{\"@types/keyv\":\"^3.1.1\"}}],[\"http-link-dataloader@*\",{peerDependencies:{graphql:\"^0.13.1 || ^14.0.0\"}}],[\"typescript-language-server@*\",{dependencies:{\"vscode-jsonrpc\":\"^5.0.1\",\"vscode-languageserver-protocol\":\"^3.15.0\"}}],[\"postcss-syntax@*\",{peerDependenciesMeta:{\"postcss-html\":Qt,\"postcss-jsx\":Qt,\"postcss-less\":Qt,\"postcss-markdown\":Qt,\"postcss-scss\":Qt}}],[\"jss-plugin-rule-value-function@<=10.1.1\",{dependencies:{\"tiny-warning\":\"^1.0.2\"}}],[\"ink-select-input@<4.1.0\",{peerDependencies:{react:\"^16.8.2\"}}],[\"license-webpack-plugin@<2.3.18\",{peerDependenciesMeta:{webpack:Qt}}],[\"snowpack@>=3.3.0\",{dependencies:{\"node-gyp\":\"^7.1.0\"}}],[\"promise-inflight@*\",{peerDependenciesMeta:{bluebird:Qt}}],[\"reactcss@*\",{peerDependencies:{react:\"*\"}}],[\"react-color@<=2.19.0\",{peerDependencies:{react:\"*\"}}],[\"gatsby-plugin-i18n@*\",{dependencies:{ramda:\"^0.24.1\"}}],[\"useragent@^2.0.0\",{dependencies:{request:\"^2.88.0\",yamlparser:\"0.0.x\",semver:\"5.5.x\"}}],[\"@apollographql/apollo-tools@<=0.5.2\",{peerDependencies:{graphql:\"^14.2.1 || ^15.0.0\"}}],[\"material-table@^2.0.0\",{dependencies:{\"@babel/runtime\":\"^7.11.2\"}}],[\"@babel/parser@*\",{dependencies:{\"@babel/types\":\"^7.8.3\"}}],[\"fork-ts-checker-webpack-plugin@<=6.3.4\",{peerDependencies:{eslint:\">= 6\",typescript:\">= 2.7\",webpack:\">= 4\",\"vue-template-compiler\":\"*\"},peerDependenciesMeta:{eslint:Qt,\"vue-template-compiler\":Qt}}],[\"rc-animate@<=3.1.1\",{peerDependencies:{react:\">=16.9.0\",\"react-dom\":\">=16.9.0\"}}],[\"react-bootstrap-table2-paginator@*\",{dependencies:{classnames:\"^2.2.6\"}}],[\"react-draggable@<=4.4.3\",{peerDependencies:{react:\">= 16.3.0\",\"react-dom\":\">= 16.3.0\"}}],[\"apollo-upload-client@<14\",{peerDependencies:{graphql:\"14 - 15\"}}],[\"react-instantsearch-core@<=6.7.0\",{peerDependencies:{algoliasearch:\">= 3.1 < 5\"}}],[\"react-instantsearch-dom@<=6.7.0\",{dependencies:{\"react-fast-compare\":\"^3.0.0\"}}],[\"ws@<7.2.1\",{peerDependencies:{bufferutil:\"^4.0.1\",\"utf-8-validate\":\"^5.0.2\"},peerDependenciesMeta:{bufferutil:Qt,\"utf-8-validate\":Qt}}],[\"react-portal@<4.2.2\",{peerDependencies:{\"react-dom\":\"^15.0.0-0 || ^16.0.0-0 || ^17.0.0-0\"}}],[\"react-scripts@<=4.0.1\",{peerDependencies:{react:\"*\"}}],[\"testcafe@<=1.10.1\",{dependencies:{\"@babel/plugin-transform-for-of\":\"^7.12.1\",\"@babel/runtime\":\"^7.12.5\"}}],[\"testcafe-legacy-api@<=4.2.0\",{dependencies:{\"testcafe-hammerhead\":\"^17.0.1\",\"read-file-relative\":\"^1.2.0\"}}],[\"@google-cloud/firestore@<=4.9.3\",{dependencies:{protobufjs:\"^6.8.6\"}}],[\"gatsby-source-apiserver@*\",{dependencies:{\"babel-polyfill\":\"^6.26.0\"}}],[\"@webpack-cli/package-utils@<=1.0.1-alpha.4\",{dependencies:{\"cross-spawn\":\"^7.0.3\"}}],[\"gatsby-remark-prismjs@<3.3.28\",{dependencies:{lodash:\"^4\"}}],[\"gatsby-plugin-favicon@*\",{peerDependencies:{webpack:\"*\"}}],[\"gatsby-plugin-sharp@<=4.6.0-next.3\",{dependencies:{debug:\"^4.3.1\"}}],[\"gatsby-react-router-scroll@<=5.6.0-next.0\",{dependencies:{\"prop-types\":\"^15.7.2\"}}],[\"@rebass/forms@*\",{dependencies:{\"@styled-system/should-forward-prop\":\"^5.0.0\"},peerDependencies:{react:\"^16.8.6\"}}],[\"rebass@*\",{peerDependencies:{react:\"^16.8.6\"}}],[\"@ant-design/react-slick@<=0.28.3\",{peerDependencies:{react:\">=16.0.0\"}}],[\"mqtt@<4.2.7\",{dependencies:{duplexify:\"^4.1.1\"}}],[\"vue-cli-plugin-vuetify@<=2.0.3\",{dependencies:{semver:\"^6.3.0\"},peerDependenciesMeta:{\"sass-loader\":Qt,\"vuetify-loader\":Qt}}],[\"vue-cli-plugin-vuetify@<=2.0.4\",{dependencies:{\"null-loader\":\"^3.0.0\"}}],[\"vue-cli-plugin-vuetify@>=2.4.3\",{peerDependencies:{vue:\"*\"}}],[\"@vuetify/cli-plugin-utils@<=0.0.4\",{dependencies:{semver:\"^6.3.0\"},peerDependenciesMeta:{\"sass-loader\":Qt}}],[\"@vue/cli-plugin-typescript@<=5.0.0-alpha.0\",{dependencies:{\"babel-loader\":\"^8.1.0\"}}],[\"@vue/cli-plugin-typescript@<=5.0.0-beta.0\",{dependencies:{\"@babel/core\":\"^7.12.16\"},peerDependencies:{\"vue-template-compiler\":\"^2.0.0\"},peerDependenciesMeta:{\"vue-template-compiler\":Qt}}],[\"cordova-ios@<=6.3.0\",{dependencies:{underscore:\"^1.9.2\"}}],[\"cordova-lib@<=10.0.1\",{dependencies:{underscore:\"^1.9.2\"}}],[\"git-node-fs@*\",{peerDependencies:{\"js-git\":\"^0.7.8\"},peerDependenciesMeta:{\"js-git\":Qt}}],[\"consolidate@<0.16.0\",{peerDependencies:{mustache:\"^3.0.0\"},peerDependenciesMeta:{mustache:Qt}}],[\"consolidate@<=0.16.0\",{peerDependencies:{velocityjs:\"^2.0.1\",tinyliquid:\"^0.2.34\",\"liquid-node\":\"^3.0.1\",jade:\"^1.11.0\",\"then-jade\":\"*\",dust:\"^0.3.0\",\"dustjs-helpers\":\"^1.7.4\",\"dustjs-linkedin\":\"^2.7.5\",swig:\"^1.4.2\",\"swig-templates\":\"^2.0.3\",\"razor-tmpl\":\"^1.3.1\",atpl:\">=0.7.6\",liquor:\"^0.0.5\",twig:\"^1.15.2\",ejs:\"^3.1.5\",eco:\"^1.1.0-rc-3\",jazz:\"^0.0.18\",jqtpl:\"~1.1.0\",hamljs:\"^0.6.2\",hamlet:\"^0.3.3\",whiskers:\"^0.4.0\",\"haml-coffee\":\"^1.14.1\",\"hogan.js\":\"^3.0.2\",templayed:\">=0.2.3\",handlebars:\"^4.7.6\",underscore:\"^1.11.0\",lodash:\"^4.17.20\",pug:\"^3.0.0\",\"then-pug\":\"*\",qejs:\"^3.0.5\",walrus:\"^0.10.1\",mustache:\"^4.0.1\",just:\"^0.1.8\",ect:\"^0.5.9\",mote:\"^0.2.0\",toffee:\"^0.3.6\",dot:\"^1.1.3\",\"bracket-template\":\"^1.1.5\",ractive:\"^1.3.12\",nunjucks:\"^3.2.2\",htmling:\"^0.0.8\",\"babel-core\":\"^6.26.3\",plates:\"~0.4.11\",\"react-dom\":\"^16.13.1\",react:\"^16.13.1\",\"arc-templates\":\"^0.5.3\",vash:\"^0.13.0\",slm:\"^2.0.0\",marko:\"^3.14.4\",teacup:\"^2.0.0\",\"coffee-script\":\"^1.12.7\",squirrelly:\"^5.1.0\",twing:\"^5.0.2\"},peerDependenciesMeta:{velocityjs:Qt,tinyliquid:Qt,\"liquid-node\":Qt,jade:Qt,\"then-jade\":Qt,dust:Qt,\"dustjs-helpers\":Qt,\"dustjs-linkedin\":Qt,swig:Qt,\"swig-templates\":Qt,\"razor-tmpl\":Qt,atpl:Qt,liquor:Qt,twig:Qt,ejs:Qt,eco:Qt,jazz:Qt,jqtpl:Qt,hamljs:Qt,hamlet:Qt,whiskers:Qt,\"haml-coffee\":Qt,\"hogan.js\":Qt,templayed:Qt,handlebars:Qt,underscore:Qt,lodash:Qt,pug:Qt,\"then-pug\":Qt,qejs:Qt,walrus:Qt,mustache:Qt,just:Qt,ect:Qt,mote:Qt,toffee:Qt,dot:Qt,\"bracket-template\":Qt,ractive:Qt,nunjucks:Qt,htmling:Qt,\"babel-core\":Qt,plates:Qt,\"react-dom\":Qt,react:Qt,\"arc-templates\":Qt,vash:Qt,slm:Qt,marko:Qt,teacup:Qt,\"coffee-script\":Qt,squirrelly:Qt,twing:Qt}}],[\"vue-loader@<=16.3.3\",{peerDependencies:{\"@vue/compiler-sfc\":\"^3.0.8\",webpack:\"^4.1.0 || ^5.0.0-0\"},peerDependenciesMeta:{\"@vue/compiler-sfc\":Qt}}],[\"vue-loader@^16.7.0\",{peerDependencies:{\"@vue/compiler-sfc\":\"^3.0.8\",vue:\"^3.2.13\"},peerDependenciesMeta:{\"@vue/compiler-sfc\":Qt,vue:Qt}}],[\"scss-parser@<=1.0.5\",{dependencies:{lodash:\"^4.17.21\"}}],[\"query-ast@<1.0.5\",{dependencies:{lodash:\"^4.17.21\"}}],[\"redux-thunk@<=2.3.0\",{peerDependencies:{redux:\"^4.0.0\"}}],[\"skypack@<=0.3.2\",{dependencies:{tar:\"^6.1.0\"}}],[\"@npmcli/metavuln-calculator@<2.0.0\",{dependencies:{\"json-parse-even-better-errors\":\"^2.3.1\"}}],[\"bin-links@<2.3.0\",{dependencies:{\"mkdirp-infer-owner\":\"^1.0.2\"}}],[\"rollup-plugin-polyfill-node@<=0.8.0\",{peerDependencies:{rollup:\"^1.20.0 || ^2.0.0\"}}],[\"snowpack@<3.8.6\",{dependencies:{\"magic-string\":\"^0.25.7\"}}],[\"elm-webpack-loader@*\",{dependencies:{temp:\"^0.9.4\"}}],[\"winston-transport@<=4.4.0\",{dependencies:{logform:\"^2.2.0\"}}],[\"jest-vue-preprocessor@*\",{dependencies:{\"@babel/core\":\"7.8.7\",\"@babel/template\":\"7.8.6\"},peerDependencies:{pug:\"^2.0.4\"},peerDependenciesMeta:{pug:Qt}}],[\"redux-persist@*\",{peerDependencies:{react:\">=16\"},peerDependenciesMeta:{react:Qt}}],[\"sodium@>=3\",{dependencies:{\"node-gyp\":\"^3.8.0\"}}],[\"babel-plugin-graphql-tag@<=3.1.0\",{peerDependencies:{graphql:\"^14.0.0 || ^15.0.0\"}}],[\"@playwright/test@<=1.14.1\",{dependencies:{\"jest-matcher-utils\":\"^26.4.2\"}}],...[\"babel-plugin-remove-graphql-queries@<3.14.0-next.1\",\"babel-preset-gatsby-package@<1.14.0-next.1\",\"create-gatsby@<1.14.0-next.1\",\"gatsby-admin@<0.24.0-next.1\",\"gatsby-cli@<3.14.0-next.1\",\"gatsby-core-utils@<2.14.0-next.1\",\"gatsby-design-tokens@<3.14.0-next.1\",\"gatsby-legacy-polyfills@<1.14.0-next.1\",\"gatsby-plugin-benchmark-reporting@<1.14.0-next.1\",\"gatsby-plugin-graphql-config@<0.23.0-next.1\",\"gatsby-plugin-image@<1.14.0-next.1\",\"gatsby-plugin-mdx@<2.14.0-next.1\",\"gatsby-plugin-netlify-cms@<5.14.0-next.1\",\"gatsby-plugin-no-sourcemaps@<3.14.0-next.1\",\"gatsby-plugin-page-creator@<3.14.0-next.1\",\"gatsby-plugin-preact@<5.14.0-next.1\",\"gatsby-plugin-preload-fonts@<2.14.0-next.1\",\"gatsby-plugin-schema-snapshot@<2.14.0-next.1\",\"gatsby-plugin-styletron@<6.14.0-next.1\",\"gatsby-plugin-subfont@<3.14.0-next.1\",\"gatsby-plugin-utils@<1.14.0-next.1\",\"gatsby-recipes@<0.25.0-next.1\",\"gatsby-source-shopify@<5.6.0-next.1\",\"gatsby-source-wikipedia@<3.14.0-next.1\",\"gatsby-transformer-screenshot@<3.14.0-next.1\",\"gatsby-worker@<0.5.0-next.1\"].map(e=>[e,{dependencies:{\"@babel/runtime\":\"^7.14.8\"}}]),[\"gatsby-core-utils@<2.14.0-next.1\",{dependencies:{got:\"8.3.2\"}}],[\"gatsby-plugin-gatsby-cloud@<=3.1.0-next.0\",{dependencies:{\"gatsby-core-utils\":\"^2.13.0-next.0\"}}],[\"gatsby-plugin-gatsby-cloud@<=3.2.0-next.1\",{peerDependencies:{webpack:\"*\"}}],[\"babel-plugin-remove-graphql-queries@<=3.14.0-next.1\",{dependencies:{\"gatsby-core-utils\":\"^2.8.0-next.1\"}}],[\"gatsby-plugin-netlify@3.13.0-next.1\",{dependencies:{\"gatsby-core-utils\":\"^2.13.0-next.0\"}}],[\"clipanion-v3-codemod@<=0.2.0\",{peerDependencies:{jscodeshift:\"^0.11.0\"}}],[\"react-live@*\",{peerDependencies:{\"react-dom\":\"*\",react:\"*\"}}],[\"webpack@<4.44.1\",{peerDependenciesMeta:{\"webpack-cli\":Qt,\"webpack-command\":Qt}}],[\"webpack@<5.0.0-beta.23\",{peerDependenciesMeta:{\"webpack-cli\":Qt}}],[\"webpack-dev-server@<3.10.2\",{peerDependenciesMeta:{\"webpack-cli\":Qt}}],[\"@docusaurus/responsive-loader@<1.5.0\",{peerDependenciesMeta:{sharp:Qt,jimp:Qt}}],[\"eslint-module-utils@*\",{peerDependenciesMeta:{\"eslint-import-resolver-node\":Qt,\"eslint-import-resolver-typescript\":Qt,\"eslint-import-resolver-webpack\":Qt,\"@typescript-eslint/parser\":Qt}}],[\"eslint-plugin-import@*\",{peerDependenciesMeta:{\"@typescript-eslint/parser\":Qt}}],[\"critters-webpack-plugin@<3.0.2\",{peerDependenciesMeta:{\"html-webpack-plugin\":Qt}}],[\"terser@<=5.10.0\",{dependencies:{acorn:\"^8.5.0\"}}],[\"babel-preset-react-app@10.0.x <10.0.2\",{dependencies:{\"@babel/plugin-proposal-private-property-in-object\":\"^7.16.7\"}}],[\"eslint-config-react-app@*\",{peerDependenciesMeta:{typescript:Qt}}],[\"@vue/eslint-config-typescript@<11.0.0\",{peerDependenciesMeta:{typescript:Qt}}],[\"unplugin-vue2-script-setup@<0.9.1\",{peerDependencies:{\"@vue/composition-api\":\"^1.4.3\",\"@vue/runtime-dom\":\"^3.2.26\"}}],[\"@cypress/snapshot@*\",{dependencies:{debug:\"^3.2.7\"}}],[\"auto-relay@<=0.14.0\",{peerDependencies:{\"reflect-metadata\":\"^0.1.13\"}}],[\"vue-template-babel-compiler@<1.2.0\",{peerDependencies:{\"vue-template-compiler\":\"^2.6.0\"}}],[\"@parcel/transformer-image@<2.5.0\",{peerDependencies:{\"@parcel/core\":\"*\"}}],[\"@parcel/transformer-js@<2.5.0\",{peerDependencies:{\"@parcel/core\":\"*\"}}],[\"parcel@*\",{peerDependenciesMeta:{\"@parcel/core\":Qt}}],[\"react-scripts@*\",{peerDependencies:{eslint:\"*\"}}],[\"focus-trap-react@^8.0.0\",{dependencies:{tabbable:\"^5.3.2\"}}],[\"react-rnd@<10.3.7\",{peerDependencies:{react:\">=16.3.0\",\"react-dom\":\">=16.3.0\"}}],[\"connect-mongo@<5.0.0\",{peerDependencies:{\"express-session\":\"^1.17.1\"}}],[\"vue-i18n@<9\",{peerDependencies:{vue:\"^2\"}}],[\"vue-router@<4\",{peerDependencies:{vue:\"^2\"}}],[\"unified@<10\",{dependencies:{\"@types/unist\":\"^2.0.0\"}}],[\"react-github-btn@<=1.3.0\",{peerDependencies:{react:\">=16.3.0\"}}],[\"react-dev-utils@*\",{peerDependencies:{typescript:\">=2.7\",webpack:\">=4\"},peerDependenciesMeta:{typescript:Qt}}],[\"@asyncapi/react-component@<=1.0.0-next.39\",{peerDependencies:{react:\">=16.8.0\",\"react-dom\":\">=16.8.0\"}}],[\"xo@*\",{peerDependencies:{webpack:\">=1.11.0\"},peerDependenciesMeta:{webpack:Qt}}],[\"babel-plugin-remove-graphql-queries@<=4.20.0-next.0\",{dependencies:{\"@babel/types\":\"^7.15.4\"}}],[\"gatsby-plugin-page-creator@<=4.20.0-next.1\",{dependencies:{\"fs-extra\":\"^10.1.0\"}}],[\"gatsby-plugin-utils@<=3.14.0-next.1\",{dependencies:{fastq:\"^1.13.0\"},peerDependencies:{graphql:\"^15.0.0\"}}],[\"gatsby-plugin-mdx@<3.1.0-next.1\",{dependencies:{mkdirp:\"^1.0.4\"}}],[\"gatsby-plugin-mdx@^2\",{peerDependencies:{gatsby:\"^3.0.0-next\"}}],[\"fdir@<=5.2.0\",{peerDependencies:{picomatch:\"2.x\"},peerDependenciesMeta:{picomatch:Qt}}],[\"babel-plugin-transform-typescript-metadata@<=0.3.2\",{peerDependencies:{\"@babel/core\":\"^7\",\"@babel/traverse\":\"^7\"},peerDependenciesMeta:{\"@babel/traverse\":Qt}}],[\"graphql-compose@>=9.0.10\",{peerDependencies:{graphql:\"^14.2.0 || ^15.0.0 || ^16.0.0\"}}],[\"vite-plugin-vuetify@<=1.0.2\",{peerDependencies:{vue:\"^3.0.0\"}}],[\"webpack-plugin-vuetify@<=2.0.1\",{peerDependencies:{vue:\"^3.2.6\"}}],[\"eslint-import-resolver-vite@<2.0.1\",{dependencies:{debug:\"^4.3.4\",resolve:\"^1.22.8\"}}],[\"notistack@^3.0.0\",{dependencies:{csstype:\"^3.0.10\"}}],[\"@fastify/type-provider-typebox@^5.0.0\",{peerDependencies:{fastify:\"^5.0.0\"}}],[\"@fastify/type-provider-typebox@^4.0.0\",{peerDependencies:{fastify:\"^4.0.0\"}}]];var L5;function Ude(){return typeof L5>\"u\"&&(L5=Ie(\"zlib\").brotliDecompressSync(Buffer.from(\"G7weAByFTVk3Vs7UfHhq4yykgEM7pbW7TI43SG2S5tvGrwHBAzdz+s/npQ6tgEvobvxisrPIadkXeUAJotBn5bDZ5kAhcRqsIHe3F75Walet5hNalwgFDtxb0BiDUjiUQkjG0yW2hto9HPgiCkm316d6bC0kST72YN7D7rfkhCE9x4J0XwB0yavalxpUu2t9xszHrmtwalOxT7VslsxWcB1qpqZwERUra4psWhTV8BgwWeizurec82Caf1ABL11YMfbf8FJ9JBceZOkgmvrQPbC9DUldX/yMbmX06UQluCEjSwUoyO+EZPIjofr+/oAZUck2enraRD+oWLlnlYnj8xB+gwSo9lmmks4fXv574qSqcWA6z21uYkzMu3EWj+K23RxeQlLqiE35/rC8GcS4CGkKHKKq+zAIQwD9iRDNfiAqueLLpicFFrNsAI4zeTD/eO9MHcnRa5m8UT+M2+V+AkFST4BlKneiAQRSdST8KEAIyFlULt6wa9EBd0Ds28VmpaxquJdVt+nwdEs5xUskI13OVtFyY0UrQIRAlCuvvWivvlSKQfTO+2Q8OyUR1W5RvetaPz4jD27hdtwHFFA1Ptx6Ee/t2cY2rg2G46M1pNDRf2pWhvpy8pqMnuI3++4OF3+7OFIWXGjh+o7Nr2jNvbiYcQdQS1h903/jVFgOpA0yJ78z+x759bFA0rq+6aY5qPB4FzS3oYoLupDUhD9nDz6F6H7hpnlMf18KNKDu4IKjTWwrAnY6MFQw1W6ymOALHlFyCZmQhldg1MQHaMVVQTVgDC60TfaBqG++Y8PEoFhN/PBTZT175KNP/BlHDYGOOBmnBdzqJKplZ/ljiVG0ZBzfqeBRrrUkn6rA54462SgiliKoYVnbeptMdXNfAuaupIEi0bApF10TlgHfmEJAPUVidRVFyDupSem5po5vErPqWKhKbUIp0LozpYsIKK57dM/HKr+nguF+7924IIWMICkQ8JUigs9D+W+c4LnNoRtPPKNRUiCYmP+Jfo2lfKCKw8qpraEeWU3uiNRO6zcyKQoXPR5htmzzLznke7b4YbXW3I1lIRzmgG02Udb58U+7TpwyN7XymCgH+wuPDthZVQvRZuEP+SnLtMicz9m5zASWOBiAcLmkuFlTKuHspSIhCBD0yUPKcxu81A+4YD78rA2vtwsUEday9WNyrShyrl60rWmA+SmbYZkQOwFJWArxRYYc5jGhA5ikxYw1rx3ei4NmeX/lKiwpZ9Ln1tV2Ae7sArvxuVLbJjqJRjW1vFXAyHpvLG+8MJ6T2Ubx5M2KDa2SN6vuIGxJ9WQM9Mk3Q7aCNiZONXllhqq24DmoLbQfW2rYWsOgHWjtOmIQMyMKdiHZDjoyIq5+U700nZ6odJAoYXPQBvFNiQ78d5jaXliBqLTJEqUCwi+LiH2mx92EmNKDsJL74Z613+3lf20pxkV1+erOrjj8pW00vsPaahKUM+05ssd5uwM7K482KWEf3TCwlg/o3e5ngto7qSMz7YteIgCsF1UOcsLk7F7MxWbvrPMY473ew0G+noVL8EPbkmEMftMSeL6HFub/zy+2JQ==\",\"base64\")).toString()),L5}var M5;function _de(){return typeof M5>\"u\"&&(M5=Ie(\"zlib\").brotliDecompressSync(Buffer.from(\"G8MSIIzURnVBnObTcvb3XE6v2S9Qgc2K801Oa5otNKEtK8BINZNcaQHy+9/vf/WXBimwutXC33P2DPc64pps5rz7NGGWaOKNSPL4Y2KRE8twut2lFOIN+OXPtRmPMRhMTILib2bEQx43az2I5d3YS8Roa5UZpF/ujHb3Djd3GDvYUfvFYSUQ39vb2cmifp/rgB4J/65JK3wRBTvMBoNBmn3mbXC63/gbBkW/2IRPri0O8bcsRBsmarF328pAln04nyJFkwUAvNu934supAqLtyerZZpJ8I8suJHhf/ocMV+scKwa8NOiDKIPXw6Ex/EEZD6TEGaW8N5zvNHYF10l6Lfooj7D5W2k3dgvQSbp2Wv8TGOayS978gxlOLVjTGXs66ozewbrjwElLtyrYNnWTfzzdEutgROUFPVMhnMoy8EjJLLlWwIEoySxliim9kYW30JUHiPVyjt0iAw/ZpPmCbUCltYPnq6ZNblIKhTNhqS/oqC9iya5sGKZTOVsTEg34n92uZTf2iPpcZih8rPW8CzA+adIGmyCPcKdLMsBLShd+zuEbTrqpwuh+DLmracZcjPC5Sdf5odDAhKpFuOsQS67RT+1VgWWygSv3YwxDnylc04/PYuaMeIzhBkLrvs7e/OUzRTF56MmfY6rI63QtEjEQzq637zQqJ39nNhu3NmoRRhW/086bHGBUtx0PE0j3aEGvkdh9WJC8y8j8mqqke9/dQ5la+Q3ba4RlhvTbnfQhPDDab3tUifkjKuOsp13mXEmO00Mu88F/M67R7LXfoFDFLNtgCSWjWX+3Jn1371pJTK9xPBiMJafvDjtFyAzu8rxeQ0TKMQXNPs5xxiBOd+BRJP8KP88XPtJIbZKh/cdW8KvBUkpqKpGoiIaA32c3/JnQr4efXt85mXvidOvn/eU3Pase1typLYBalJ14mCso9h79nuMOuCa/kZAOkJHmTjP5RM2WNoPasZUAnT1TAE/NH25hUxcQv6hQWR/m1PKk4ooXMcM4SR1iYU3fUohvqk4RY2hbmTVVIXv6TvqO+0doOjgeVFAcom+RlwJQmOVH7pr1Q9LoJT6n1DeQEB+NHygsATbIwTcOKZlJsY8G4+suX1uQLjUWwLjjs0mvSvZcLTpIGAekeR7GCgl8eo3ndAqEe2XCav4huliHjdbIPBsGJuPX7lrO9HX1UbXRH5opOe1x6JsOSgHZR+EaxuXVhpLLxm6jk1LJtZfHSc6BKPun3CpYYVMJGwEUyk8MTGG0XL5MfEwaXpnc9TKnBmlGn6nHiGREc3ysn47XIBDzA+YvFdjZzVIEDcKGpS6PbUJehFRjEne8D0lVU1XuRtlgszq6pTNlQ/3MzNOEgCWPyTct22V2mEi2krizn5VDo9B19/X2DB3hCGRMM7ONbtnAcIx/OWB1u5uPbW1gsH8irXxT/IzG0PoXWYjhbMsH3KTuoOl5o17PulcgvsfTSnKFM354GWI8luqZnrswWjiXy3G+Vbyo1KMopFmmvBwNELgaS8z8dNZchx/Cl/xjddxhMcyqtzFyONb2Zdu90NkI8pAeufe7YlXrp53v8Dj/l8vWeVspRKBGXScBBPI/HinSTGmLDOGGOCIyH0JFdOZx0gWsacNlQLJMIrBhqRxXxHF/5pseWwejlAAvZ3klZSDSYY8mkToaWejXhgNomeGtx1DTLEUFMRkgF5yFB22WYdJnaWN14r1YJj81hGi45+jrADS5nYRhCiSlCJJ1nL8pYX+HDSMhdTEWyRcgHVp/IsUIZYMfT+YYncUQPgcxNGCHfZ88vDdrcUuaGIl6zhAsiaq7R5dfqrqXH/JcBhfjT8D0azayIyEz75Nxp6YkcyDxlJq3EXnJUpqDohJJOysL1t1uNiHESlvsxPb5cpbW0+ICZqJmUZus1BMW0F5IVBODLIo2zHHjA0=\",\"base64\")).toString()),M5}var U5;function Hde(){return typeof U5>\"u\"&&(U5=Ie(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),U5}var jde=new Map([[j.makeIdent(null,\"fsevents\").identHash,Ude],[j.makeIdent(null,\"resolve\").identHash,_de],[j.makeIdent(null,\"typescript\").identHash,Hde]]),zot={hooks:{registerPackageExtensions:async(e,t)=>{for(let[r,s]of O5)t(j.parseDescriptor(r,!0),s)},getBuiltinPatch:async(e,t)=>{let r=\"compat/\";if(!t.startsWith(r))return;let s=j.parseIdent(t.slice(r.length)),a=jde.get(s.identHash)?.();return typeof a<\"u\"?a:null},reduceDependency:async(e,t,r,s)=>typeof jde.get(e.identHash)>\"u\"?e:j.makeDescriptor(e,j.makeRange({protocol:\"patch:\",source:j.stringifyDescriptor(e),selector:`optional!builtin<compat/${j.stringifyIdent(e)}>`,params:null}))}},Zot=zot;var nq={};Yt(nq,{ConstraintsCheckCommand:()=>GC,ConstraintsQueryCommand:()=>HC,ConstraintsSourceCommand:()=>jC,default:()=>dat});qe();qe();iS();var LC=class{constructor(t){this.project=t}createEnvironment(){let t=new OC([\"cwd\",\"ident\"]),r=new OC([\"workspace\",\"type\",\"ident\"]),s=new OC([\"ident\"]),a={manifestUpdates:new Map,reportedErrors:new Map},n=new Map,c=new Map;for(let f of this.project.storedPackages.values()){let p=Array.from(f.peerDependencies.values(),h=>[j.stringifyIdent(h),h.range]);n.set(f.locatorHash,{workspace:null,ident:j.stringifyIdent(f),version:f.version,dependencies:new Map,peerDependencies:new Map(p.filter(([h])=>f.peerDependenciesMeta.get(h)?.optional!==!0)),optionalPeerDependencies:new Map(p.filter(([h])=>f.peerDependenciesMeta.get(h)?.optional===!0))})}for(let f of this.project.storedPackages.values()){let p=n.get(f.locatorHash);p.dependencies=new Map(Array.from(f.dependencies.values(),h=>{let E=this.project.storedResolutions.get(h.descriptorHash);if(typeof E>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");let C=n.get(E);if(typeof C>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");return[j.stringifyIdent(h),C]})),p.dependencies.delete(p.ident)}for(let f of this.project.workspaces){let p=j.stringifyIdent(f.anchoredLocator),h=f.manifest.exportTo({}),E=n.get(f.anchoredLocator.locatorHash);if(typeof E>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");let C=(T,O,{caller:U=Ui.getCaller()}={})=>{let Y=nS(T),te=Ge.getMapWithDefault(a.manifestUpdates,f.cwd),ie=Ge.getMapWithDefault(te,Y),ue=Ge.getSetWithDefault(ie,O);U!==null&&ue.add(U)},S=T=>C(T,void 0,{caller:Ui.getCaller()}),x=T=>{Ge.getArrayWithDefault(a.reportedErrors,f.cwd).push(T)},I=t.insert({cwd:f.relativeCwd,ident:p,manifest:h,pkg:E,set:C,unset:S,error:x});c.set(f,I);for(let T of Ut.allDependencies)for(let O of f.manifest[T].values()){let U=j.stringifyIdent(O),Y=()=>{C([T,U],void 0,{caller:Ui.getCaller()})},te=ue=>{C([T,U],ue,{caller:Ui.getCaller()})},ie=null;if(T!==\"peerDependencies\"&&(T!==\"dependencies\"||!f.manifest.devDependencies.has(O.identHash))){let ue=f.anchoredPackage.dependencies.get(O.identHash);if(ue){if(typeof ue>\"u\")throw new Error(\"Assertion failed: The dependency should have been registered\");let ae=this.project.storedResolutions.get(ue.descriptorHash);if(typeof ae>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");let de=n.get(ae);if(typeof de>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");ie=de}}r.insert({workspace:I,ident:U,range:O.range,type:T,resolution:ie,update:te,delete:Y,error:x})}}for(let f of this.project.storedPackages.values()){let p=this.project.tryWorkspaceByLocator(f);if(!p)continue;let h=c.get(p);if(typeof h>\"u\")throw new Error(\"Assertion failed: The workspace should have been registered\");let E=n.get(f.locatorHash);if(typeof E>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");E.workspace=h}return{workspaces:t,dependencies:r,packages:s,result:a}}async process(){let t=this.createEnvironment(),r={Yarn:{workspace:a=>t.workspaces.find(a)[0]??null,workspaces:a=>t.workspaces.find(a),dependency:a=>t.dependencies.find(a)[0]??null,dependencies:a=>t.dependencies.find(a),package:a=>t.packages.find(a)[0]??null,packages:a=>t.packages.find(a)}},s=await this.project.loadUserConfig();return s?.constraints?(await s.constraints(r),t.result):null}};qe();qe();Vt();var HC=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.query=he.String()}static{this.paths=[[\"constraints\",\"query\"]]}static{this.usage=at.Usage({category:\"Constraints-related commands\",description:\"query the constraints fact database\",details:`\n      This command will output all matches to the given prolog query.\n    `,examples:[[\"List all dependencies throughout the workspace\",\"yarn constraints query 'workspace_has_dependency(_, DependencyName, _, _).'\"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(lS(),aS)),s=await ze.find(this.context.cwd,this.context.plugins),{project:a}=await Rt.find(s,this.context.cwd),n=await r.find(a),c=this.query;return c.endsWith(\".\")||(c=`${c}.`),(await Ot.start({configuration:s,json:this.json,stdout:this.context.stdout},async p=>{for await(let h of n.query(c)){let E=Array.from(Object.entries(h)),C=E.length,S=E.reduce((x,[I])=>Math.max(x,I.length),0);for(let x=0;x<C;x++){let[I,T]=E[x];p.reportInfo(null,`${hat(x,C)}${I.padEnd(S,\" \")} = ${pat(T)}`)}p.reportJson(h)}})).exitCode()}};function pat(e){return typeof e!=\"string\"?`${e}`:e.match(/^[a-zA-Z][a-zA-Z0-9_]+$/)?e:`'${e}'`}function hat(e,t){let r=e===0,s=e===t-1;return r&&s?\"\":r?\"\\u250C \":s?\"\\u2514 \":\"\\u2502 \"}qe();Vt();var jC=class extends At{constructor(){super(...arguments);this.verbose=he.Boolean(\"-v,--verbose\",!1,{description:\"Also print the fact database automatically compiled from the workspace manifests\"})}static{this.paths=[[\"constraints\",\"source\"]]}static{this.usage=at.Usage({category:\"Constraints-related commands\",description:\"print the source code for the constraints\",details:\"\\n      This command will print the Prolog source code used by the constraints engine. Adding the `-v,--verbose` flag will print the *full* source code, including the fact database automatically compiled from the workspace manifests.\\n    \",examples:[[\"Prints the source code\",\"yarn constraints source\"],[\"Print the source code and the fact database\",\"yarn constraints source -v\"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(lS(),aS)),s=await ze.find(this.context.cwd,this.context.plugins),{project:a}=await Rt.find(s,this.context.cwd),n=await r.find(a);this.context.stdout.write(this.verbose?n.fullSource:n.source)}};qe();qe();Vt();iS();var GC=class extends At{constructor(){super(...arguments);this.fix=he.Boolean(\"--fix\",!1,{description:\"Attempt to automatically fix unambiguous issues, following a multi-pass process\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"constraints\"]]}static{this.usage=at.Usage({category:\"Constraints-related commands\",description:\"check that the project constraints are met\",details:`\n      This command will run constraints on your project and emit errors for each one that is found but isn't met. If any error is emitted the process will exit with a non-zero exit code.\n\n      If the \\`--fix\\` flag is used, Yarn will attempt to automatically fix the issues the best it can, following a multi-pass process (with a maximum of 10 iterations). Some ambiguous patterns cannot be autofixed, in which case you'll have to manually specify the right resolution.\n\n      For more information as to how to write constraints, please consult our dedicated page on our website: https://yarnpkg.com/features/constraints.\n    `,examples:[[\"Check that all constraints are satisfied\",\"yarn constraints\"],[\"Autofix all unmet constraints\",\"yarn constraints --fix\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd);await s.restoreInstallState();let a=await s.loadUserConfig(),n;if(a?.constraints)n=new LC(s);else{let{Constraints:h}=await Promise.resolve().then(()=>(lS(),aS));n=await h.find(s)}let c,f=!1,p=!1;for(let h=this.fix?10:1;h>0;--h){let E=await n.process();if(!E)break;let{changedWorkspaces:C,remainingErrors:S}=jT(s,E,{fix:this.fix}),x=[];for(let[I,T]of C){let O=I.manifest.indent;I.manifest=new Ut,I.manifest.indent=O,I.manifest.load(T),x.push(I.persistManifest())}if(await Promise.all(x),!(C.size>0&&h>1)){c=Gde(S,{configuration:r}),f=!1,p=!0;for(let[,I]of S)for(let T of I)T.fixable?f=!0:p=!1}}if(c.children.length===0)return 0;if(f){let h=p?`Those errors can all be fixed by running ${pe.pretty(r,\"yarn constraints --fix\",pe.Type.CODE)}`:`Errors prefixed by '\\u2699' can be fixed by running ${pe.pretty(r,\"yarn constraints --fix\",pe.Type.CODE)}`;await Ot.start({configuration:r,stdout:this.context.stdout,includeNames:!1,includeFooter:!1},async E=>{E.reportInfo(0,h),E.reportSeparator()})}return c.children=Ge.sortMap(c.children,h=>h.value[1]),Rs.emitTree(c,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1}),1}};iS();var gat={configuration:{enableConstraintsChecks:{description:\"If true, constraints will run during installs\",type:\"BOOLEAN\",default:!1},constraintsPath:{description:\"The path of the constraints file.\",type:\"ABSOLUTE_PATH\",default:\"./constraints.pro\"}},commands:[HC,jC,GC],hooks:{async validateProjectAfterInstall(e,{reportError:t}){if(!e.configuration.get(\"enableConstraintsChecks\"))return;let r=await e.loadUserConfig(),s;if(r?.constraints)s=new LC(e);else{let{Constraints:c}=await Promise.resolve().then(()=>(lS(),aS));s=await c.find(e)}let a=await s.process();if(!a)return;let{remainingErrors:n}=jT(e,a);if(n.size!==0)if(e.configuration.isCI)for(let[c,f]of n)for(let p of f)t(84,`${pe.pretty(e.configuration,c.anchoredLocator,pe.Type.IDENT)}: ${p.text}`);else t(84,`Constraint check failed; run ${pe.pretty(e.configuration,\"yarn constraints\",pe.Type.CODE)} for more details`)}}},dat=gat;var iq={};Yt(iq,{CreateCommand:()=>qC,DlxCommand:()=>WC,default:()=>yat});qe();Vt();var qC=class extends At{constructor(){super(...arguments);this.pkg=he.String(\"-p,--package\",{description:\"The package to run the provided command from\"});this.quiet=he.Boolean(\"-q,--quiet\",!1,{description:\"Only report critical errors instead of printing the full install logs\"});this.command=he.String();this.args=he.Proxy()}static{this.paths=[[\"create\"]]}async execute(){let r=[];this.pkg&&r.push(\"--package\",this.pkg),this.quiet&&r.push(\"--quiet\");let s=this.command.replace(/^(@[^@/]+)(@|$)/,\"$1/create$2\"),a=j.parseDescriptor(s),n=a.name.match(/^create(-|$)/)?a:a.scope?j.makeIdent(a.scope,`create-${a.name}`):j.makeIdent(null,`create-${a.name}`),c=j.stringifyIdent(n);return a.range!==\"unknown\"&&(c+=`@${a.range}`),this.cli.run([\"dlx\",...r,c,...this.args])}};qe();qe();Dt();Vt();var WC=class extends At{constructor(){super(...arguments);this.packages=he.Array(\"-p,--package\",{description:\"The package(s) to install before running the command\"});this.quiet=he.Boolean(\"-q,--quiet\",!1,{description:\"Only report critical errors instead of printing the full install logs\"});this.command=he.String();this.args=he.Proxy()}static{this.paths=[[\"dlx\"]]}static{this.usage=at.Usage({description:\"run a package in a temporary environment\",details:\"\\n      This command will install a package within a temporary environment, and run its binary script if it contains any. The binary will run within the current cwd.\\n\\n      By default Yarn will download the package named `command`, but this can be changed through the use of the `-p,--package` flag which will instruct Yarn to still run the same command but from a different package.\\n\\n      Using `yarn dlx` as a replacement of `yarn add` isn't recommended, as it makes your project non-deterministic (Yarn doesn't keep track of the packages installed through `dlx` - neither their name, nor their version).\\n    \",examples:[[\"Use create-vite to scaffold a new Vite project\",\"yarn dlx create-vite\"],[\"Install multiple packages for a single command\",`yarn dlx -p typescript -p ts-node ts-node --transpile-only -e \"console.log('hello!')\"`]]})}async execute(){return ze.telemetry=null,await le.mktempPromise(async r=>{let s=K.join(r,`dlx-${process.pid}`);await le.mkdirPromise(s),await le.writeFilePromise(K.join(s,\"package.json\"),`{}\n`),await le.writeFilePromise(K.join(s,\"yarn.lock\"),\"\");let a=K.join(s,\".yarnrc.yml\"),n=await ze.findProjectCwd(this.context.cwd),f={enableGlobalCache:!(await ze.find(this.context.cwd,null,{strict:!1})).get(\"enableGlobalCache\"),enableTelemetry:!1,logFilters:[{code:Kf(68),level:pe.LogLevel.Discard}]},p=n!==null?K.join(n,\".yarnrc.yml\"):null;p!==null&&le.existsSync(p)?(await le.copyFilePromise(p,a),await ze.updateConfiguration(s,O=>{let U=Ge.toMerged(O,f);return Array.isArray(O.plugins)&&(U.plugins=O.plugins.map(Y=>{let te=typeof Y==\"string\"?Y:Y.path,ie=fe.isAbsolute(te)?te:fe.resolve(fe.fromPortablePath(n),te);return typeof Y==\"string\"?ie:{path:ie,spec:Y.spec}})),U})):await le.writeJsonPromise(a,f);let h=this.packages??[this.command],E=j.parseDescriptor(this.command).name,C=await this.cli.run([\"add\",\"--fixed\",\"--\",...h],{cwd:s,quiet:this.quiet});if(C!==0)return C;this.quiet||this.context.stdout.write(`\n`);let S=await ze.find(s,this.context.plugins),{project:x,workspace:I}=await Rt.find(S,s);if(I===null)throw new ar(x.cwd,s);await x.restoreInstallState();let T=await Cn.getWorkspaceAccessibleBinaries(I);return T.has(E)===!1&&T.size===1&&typeof this.packages>\"u\"&&(E=Array.from(T)[0][0]),await Cn.executeWorkspaceAccessibleBinary(I,E,this.args,{packageAccessibleBinaries:T,cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})})}};var mat={commands:[qC,WC]},yat=mat;var aq={};Yt(aq,{ExecFetcher:()=>uS,ExecResolver:()=>fS,default:()=>Cat,execUtils:()=>VT});qe();qe();Dt();var uA=\"exec:\";var VT={};Yt(VT,{loadGeneratorFile:()=>cS,makeLocator:()=>oq,makeSpec:()=>gme,parseSpec:()=>sq});qe();Dt();function sq(e){let{params:t,selector:r}=j.parseRange(e),s=fe.toPortablePath(r);return{parentLocator:t&&typeof t.locator==\"string\"?j.parseLocator(t.locator):null,path:s}}function gme({parentLocator:e,path:t,generatorHash:r,protocol:s}){let a=e!==null?{locator:j.stringifyLocator(e)}:{},n=typeof r<\"u\"?{hash:r}:{};return j.makeRange({protocol:s,source:t,selector:t,params:{...n,...a}})}function oq(e,{parentLocator:t,path:r,generatorHash:s,protocol:a}){return j.makeLocator(e,gme({parentLocator:t,path:r,generatorHash:s,protocol:a}))}async function cS(e,t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(e,{protocol:t}),n=K.isAbsolute(a)?{packageFs:new bn(vt.root),prefixPath:vt.dot,localPath:vt.root}:await r.fetcher.fetch(s,r),c=n.localPath?{packageFs:new bn(vt.root),prefixPath:K.relative(vt.root,n.localPath)}:n;n!==c&&n.releaseFs&&n.releaseFs();let f=c.packageFs,p=K.join(c.prefixPath,a);return await f.readFilePromise(p,\"utf8\")}var uS=class{supports(t,r){return!!t.reference.startsWith(uA)}getLocalPath(t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(t.reference,{protocol:uA});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(s,r);return n===null?null:K.resolve(n,a)}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t),loader:()=>this.fetchFromDisk(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),localPath:this.getLocalPath(t,r),checksum:c}}async fetchFromDisk(t,r){let s=await cS(t.reference,uA,r);return le.mktempPromise(async a=>{let n=K.join(a,\"generator.js\");return await le.writeFilePromise(n,s),le.mktempPromise(async c=>{if(await this.generatePackage(c,t,n,r),!le.existsSync(K.join(c,\"build\")))throw new Error(\"The script should have generated a build directory\");return await ds.makeArchiveFromDirectory(K.join(c,\"build\"),{prefixPath:j.getIdentVendorPath(t),compressionLevel:r.project.configuration.get(\"compressionLevel\")})})})}async generatePackage(t,r,s,a){return await le.mktempPromise(async n=>{let c=await Cn.makeScriptEnv({project:a.project,binFolder:n}),f=K.join(t,\"runtime.js\");return await le.mktempPromise(async p=>{let h=K.join(p,\"buildfile.log\"),E=K.join(t,\"generator\"),C=K.join(t,\"build\");await le.mkdirPromise(E),await le.mkdirPromise(C);let S={tempDir:fe.fromPortablePath(E),buildDir:fe.fromPortablePath(C),locator:j.stringifyLocator(r)};await le.writeFilePromise(f,`\n          // Expose 'Module' as a global variable\n          Object.defineProperty(global, 'Module', {\n            get: () => require('module'),\n            configurable: true,\n            enumerable: false,\n          });\n\n          // Expose non-hidden built-in modules as global variables\n          for (const name of Module.builtinModules.filter((name) => name !== 'module' && !name.startsWith('_'))) {\n            Object.defineProperty(global, name, {\n              get: () => require(name),\n              configurable: true,\n              enumerable: false,\n            });\n          }\n\n          // Expose the 'execEnv' global variable\n          Object.defineProperty(global, 'execEnv', {\n            value: {\n              ...${JSON.stringify(S)},\n            },\n            enumerable: true,\n          });\n        `);let x=c.NODE_OPTIONS||\"\",I=/\\s*--require\\s+\\S*\\.pnp\\.c?js\\s*/g;x=x.replace(I,\" \").trim(),c.NODE_OPTIONS=x;let{stdout:T,stderr:O}=a.project.configuration.getSubprocessStreams(h,{header:`# This file contains the result of Yarn generating a package (${j.stringifyLocator(r)})\n`,prefix:j.prettyLocator(a.project.configuration,r),report:a.report}),{code:U}=await qr.pipevp(process.execPath,[\"--require\",fe.fromPortablePath(f),fe.fromPortablePath(s),j.stringifyIdent(r)],{cwd:t,env:c,stdin:null,stdout:T,stderr:O});if(U!==0)throw le.detachTemp(p),new Error(`Package generation failed (exit code ${U}, logs can be found here: ${pe.pretty(a.project.configuration,h,pe.Type.PATH)})`)})})}};qe();qe();var Eat=2,fS=class{supportsDescriptor(t,r){return!!t.range.startsWith(uA)}supportsLocator(t,r){return!!t.reference.startsWith(uA)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){return j.bindDescriptor(t,{locator:j.stringifyLocator(r)})}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){if(!s.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{path:a,parentLocator:n}=sq(t.range);if(n===null)throw new Error(\"Assertion failed: The descriptor should have been bound\");let c=await cS(j.makeRange({protocol:uA,source:a,selector:a,params:{locator:j.stringifyLocator(n)}}),uA,s.fetchOptions),f=Ln.makeHash(`${Eat}`,c).slice(0,6);return[oq(t,{parentLocator:n,path:a,generatorHash:f,protocol:uA})]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let s=await r.fetchOptions.fetcher.fetch(t,r.fetchOptions),a=await Ge.releaseAfterUseAsync(async()=>await Ut.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...t,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var Iat={fetchers:[uS],resolvers:[fS]},Cat=Iat;var cq={};Yt(cq,{FileFetcher:()=>gS,FileResolver:()=>dS,TarballFileFetcher:()=>mS,TarballFileResolver:()=>yS,default:()=>vat,fileUtils:()=>Rm});qe();Dt();var VC=/^(?:[a-zA-Z]:[\\\\/]|\\.{0,2}\\/)/,AS=/^[^?]*\\.(?:tar\\.gz|tgz)(?:::.*)?$/,ts=\"file:\";var Rm={};Yt(Rm,{fetchArchiveFromLocator:()=>hS,makeArchiveFromLocator:()=>YT,makeBufferFromLocator:()=>lq,makeLocator:()=>YC,makeSpec:()=>dme,parseSpec:()=>pS});qe();Dt();function pS(e){let{params:t,selector:r}=j.parseRange(e),s=fe.toPortablePath(r);return{parentLocator:t&&typeof t.locator==\"string\"?j.parseLocator(t.locator):null,path:s}}function dme({parentLocator:e,path:t,hash:r,protocol:s}){let a=e!==null?{locator:j.stringifyLocator(e)}:{},n=typeof r<\"u\"?{hash:r}:{};return j.makeRange({protocol:s,source:t,selector:t,params:{...n,...a}})}function YC(e,{parentLocator:t,path:r,hash:s,protocol:a}){return j.makeLocator(e,dme({parentLocator:t,path:r,hash:s,protocol:a}))}async function hS(e,t){let{parentLocator:r,path:s}=j.parseFileStyleRange(e.reference,{protocol:ts}),a=K.isAbsolute(s)?{packageFs:new bn(vt.root),prefixPath:vt.dot,localPath:vt.root}:await t.fetcher.fetch(r,t),n=a.localPath?{packageFs:new bn(vt.root),prefixPath:K.relative(vt.root,a.localPath)}:a;a!==n&&a.releaseFs&&a.releaseFs();let c=n.packageFs,f=K.join(n.prefixPath,s);return await Ge.releaseAfterUseAsync(async()=>await c.readFilePromise(f),n.releaseFs)}async function YT(e,{protocol:t,fetchOptions:r,inMemory:s=!1}){let{parentLocator:a,path:n}=j.parseFileStyleRange(e.reference,{protocol:t}),c=K.isAbsolute(n)?{packageFs:new bn(vt.root),prefixPath:vt.dot,localPath:vt.root}:await r.fetcher.fetch(a,r),f=c.localPath?{packageFs:new bn(vt.root),prefixPath:K.relative(vt.root,c.localPath)}:c;c!==f&&c.releaseFs&&c.releaseFs();let p=f.packageFs,h=K.join(f.prefixPath,n);return await Ge.releaseAfterUseAsync(async()=>await ds.makeArchiveFromDirectory(h,{baseFs:p,prefixPath:j.getIdentVendorPath(e),compressionLevel:r.project.configuration.get(\"compressionLevel\"),inMemory:s}),f.releaseFs)}async function lq(e,{protocol:t,fetchOptions:r}){return(await YT(e,{protocol:t,fetchOptions:r,inMemory:!0})).getBufferAndClose()}var gS=class{supports(t,r){return!!t.reference.startsWith(ts)}getLocalPath(t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(t.reference,{protocol:ts});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(s,r);return n===null?null:K.resolve(n,a)}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),localPath:this.getLocalPath(t,r),checksum:c}}async fetchFromDisk(t,r){return YT(t,{protocol:ts,fetchOptions:r})}};qe();qe();var wat=2,dS=class{supportsDescriptor(t,r){return t.range.match(VC)?!0:!!t.range.startsWith(ts)}supportsLocator(t,r){return!!t.reference.startsWith(ts)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){return VC.test(t.range)&&(t=j.makeDescriptor(t,`${ts}${t.range}`)),j.bindDescriptor(t,{locator:j.stringifyLocator(r)})}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){if(!s.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{path:a,parentLocator:n}=pS(t.range);if(n===null)throw new Error(\"Assertion failed: The descriptor should have been bound\");let c=await lq(j.makeLocator(t,j.makeRange({protocol:ts,source:a,selector:a,params:{locator:j.stringifyLocator(n)}})),{protocol:ts,fetchOptions:s.fetchOptions}),f=Ln.makeHash(`${wat}`,c).slice(0,6);return[YC(t,{parentLocator:n,path:a,hash:f,protocol:ts})]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let s=await r.fetchOptions.fetcher.fetch(t,r.fetchOptions),a=await Ge.releaseAfterUseAsync(async()=>await Ut.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...t,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};qe();var mS=class{supports(t,r){return AS.test(t.reference)?!!t.reference.startsWith(ts):!1}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),checksum:c}}async fetchFromDisk(t,r){let s=await hS(t,r);return await ds.convertToZip(s,{configuration:r.project.configuration,prefixPath:j.getIdentVendorPath(t),stripComponents:1})}};qe();qe();qe();var yS=class{supportsDescriptor(t,r){return AS.test(t.range)?!!(t.range.startsWith(ts)||VC.test(t.range)):!1}supportsLocator(t,r){return AS.test(t.reference)?!!t.reference.startsWith(ts):!1}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){return VC.test(t.range)&&(t=j.makeDescriptor(t,`${ts}${t.range}`)),j.bindDescriptor(t,{locator:j.stringifyLocator(r)})}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){if(!s.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{path:a,parentLocator:n}=pS(t.range);if(n===null)throw new Error(\"Assertion failed: The descriptor should have been bound\");let c=YC(t,{parentLocator:n,path:a,hash:\"\",protocol:ts}),f=await hS(c,s.fetchOptions),p=Ln.makeHash(f).slice(0,6);return[YC(t,{parentLocator:n,path:a,hash:p,protocol:ts})]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let s=await r.fetchOptions.fetcher.fetch(t,r.fetchOptions),a=await Ge.releaseAfterUseAsync(async()=>await Ut.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...t,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var Bat={fetchers:[mS,gS],resolvers:[yS,dS]},vat=Bat;var Aq={};Yt(Aq,{GithubFetcher:()=>ES,default:()=>Dat,githubUtils:()=>KT});qe();Dt();var KT={};Yt(KT,{invalidGithubUrlMessage:()=>Eme,isGithubUrl:()=>uq,parseGithubUrl:()=>fq});var mme=et(Ie(\"querystring\")),yme=[/^https?:\\/\\/(?:([^/]+?)@)?github.com\\/([^/#]+)\\/([^/#]+)\\/tarball\\/([^/#]+)(?:#(.*))?$/,/^https?:\\/\\/(?:([^/]+?)@)?github.com\\/([^/#]+)\\/([^/#]+?)(?:\\.git)?(?:#(.*))?$/];function uq(e){return e?yme.some(t=>!!e.match(t)):!1}function fq(e){let t;for(let f of yme)if(t=e.match(f),t)break;if(!t)throw new Error(Eme(e));let[,r,s,a,n=\"master\"]=t,{commit:c}=mme.default.parse(n);return n=c||n.replace(/[^:]*:/,\"\"),{auth:r,username:s,reponame:a,treeish:n}}function Eme(e){return`Input cannot be parsed as a valid GitHub URL ('${e}').`}var ES=class{supports(t,r){return!!uq(t.reference)}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from GitHub`),loader:()=>this.fetchFromNetwork(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),checksum:c}}async fetchFromNetwork(t,r){let s=await nn.get(this.getLocatorUrl(t,r),{configuration:r.project.configuration});return await le.mktempPromise(async a=>{let n=new bn(a);await ds.extractArchiveTo(s,n,{stripComponents:1});let c=Oa.splitRepoUrl(t.reference),f=K.join(a,\"package.tgz\");await Cn.prepareExternalProject(a,f,{configuration:r.project.configuration,report:r.report,workspace:c.extra.workspace,locator:t});let p=await le.readFilePromise(f);return await ds.convertToZip(p,{configuration:r.project.configuration,prefixPath:j.getIdentVendorPath(t),stripComponents:1})})}getLocatorUrl(t,r){let{auth:s,username:a,reponame:n,treeish:c}=fq(t.reference);return`https://${s?`${s}@`:\"\"}github.com/${a}/${n}/archive/${c}.tar.gz`}};var Sat={hooks:{async fetchHostedRepository(e,t,r){if(e!==null)return e;let s=new ES;if(!s.supports(t,r))return null;try{return await s.fetch(t,r)}catch{return null}}}},Dat=Sat;var pq={};Yt(pq,{TarballHttpFetcher:()=>CS,TarballHttpResolver:()=>wS,default:()=>Pat});qe();function IS(e){let t;try{t=new URL(e)}catch{return!1}return!(t.protocol!==\"http:\"&&t.protocol!==\"https:\"||!t.pathname.match(/(\\.tar\\.gz|\\.tgz|\\/[^.]+)$/))}var CS=class{supports(t,r){return IS(t.reference)}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),checksum:c}}async fetchFromNetwork(t,r){let s=await nn.get(t.reference,{configuration:r.project.configuration});return await ds.convertToZip(s,{configuration:r.project.configuration,prefixPath:j.getIdentVendorPath(t),stripComponents:1})}};qe();qe();var wS=class{supportsDescriptor(t,r){return IS(t.range)}supportsLocator(t,r){return IS(t.reference)}shouldPersistResolution(t,r){return!0}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){return[j.convertDescriptorToLocator(t)]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let s=await r.fetchOptions.fetcher.fetch(t,r.fetchOptions),a=await Ge.releaseAfterUseAsync(async()=>await Ut.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...t,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var bat={fetchers:[CS],resolvers:[wS]},Pat=bat;var hq={};Yt(hq,{InitCommand:()=>K0,InitInitializerCommand:()=>KC,default:()=>kat});Vt();qe();qe();Dt();Vt();var K0=class extends At{constructor(){super(...arguments);this.private=he.Boolean(\"-p,--private\",!1,{description:\"Initialize a private package\"});this.workspace=he.Boolean(\"-w,--workspace\",!1,{description:\"Initialize a workspace root with a `packages/` directory\"});this.install=he.String(\"-i,--install\",!1,{tolerateBoolean:!0,description:\"Initialize a package with a specific bundle that will be locked in the project\"});this.name=he.String(\"-n,--name\",{description:\"Initialize a package with the given name\"});this.usev2=he.Boolean(\"-2\",!1,{hidden:!0});this.yes=he.Boolean(\"-y,--yes\",{hidden:!0})}static{this.paths=[[\"init\"]]}static{this.usage=at.Usage({description:\"create a new package\",details:\"\\n      This command will setup a new package in your local directory.\\n\\n      If the `-p,--private` or `-w,--workspace` options are set, the package will be private by default.\\n\\n      If the `-w,--workspace` option is set, the package will be configured to accept a set of workspaces in the `packages/` directory.\\n\\n      If the `-i,--install` option is given a value, Yarn will first download it using `yarn set version` and only then forward the init call to the newly downloaded bundle. Without arguments, the downloaded bundle will be `latest`.\\n\\n      The initial settings of the manifest can be changed by using the `initScope` and `initFields` configuration values. Additionally, Yarn will generate an EditorConfig file whose rules can be altered via `initEditorConfig`, and will initialize a Git repository in the current directory.\\n    \",examples:[[\"Create a new package in the local directory\",\"yarn init\"],[\"Create a new private package in the local directory\",\"yarn init -p\"],[\"Create a new package and store the Yarn release inside\",\"yarn init -i=latest\"],[\"Create a new private package and defines it as a workspace root\",\"yarn init -w\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=typeof this.install==\"string\"?this.install:this.usev2||this.install===!0?\"latest\":null;return s!==null?await this.executeProxy(r,s):await this.executeRegular(r)}async executeProxy(r,s){if(r.projectCwd!==null&&r.projectCwd!==this.context.cwd)throw new st(\"Cannot use the --install flag from within a project subdirectory\");le.existsSync(this.context.cwd)||await le.mkdirPromise(this.context.cwd,{recursive:!0});let a=K.join(this.context.cwd,Er.lockfile);le.existsSync(a)||await le.writeFilePromise(a,\"\");let n=await this.cli.run([\"set\",\"version\",s],{quiet:!0});if(n!==0)return n;let c=[];return this.private&&c.push(\"-p\"),this.workspace&&c.push(\"-w\"),this.name&&c.push(`-n=${this.name}`),this.yes&&c.push(\"-y\"),await le.mktempPromise(async f=>{let{code:p}=await qr.pipevp(\"yarn\",[\"init\",...c],{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,env:await Cn.makeScriptEnv({binFolder:f})});return p})}async initialize(){}async executeRegular(r){let s=null;try{s=(await Rt.find(r,this.context.cwd)).project}catch{s=null}le.existsSync(this.context.cwd)||await le.mkdirPromise(this.context.cwd,{recursive:!0});let a=await Ut.tryFind(this.context.cwd),n=a??new Ut,c=Object.fromEntries(r.get(\"initFields\").entries());n.load(c),n.name=n.name??j.makeIdent(r.get(\"initScope\"),this.name??K.basename(this.context.cwd)),n.packageManager=An&&Ge.isTaggedYarnVersion(An)?`yarn@${An}`:null,(!a&&this.workspace||this.private)&&(n.private=!0),this.workspace&&n.workspaceDefinitions.length===0&&(await le.mkdirPromise(K.join(this.context.cwd,\"packages\"),{recursive:!0}),n.workspaceDefinitions=[{pattern:\"packages/*\"}]);let f={};n.exportTo(f);let p=K.join(this.context.cwd,Ut.fileName);await le.changeFilePromise(p,`${JSON.stringify(f,null,2)}\n`,{automaticNewlines:!0});let h=[p],E=K.join(this.context.cwd,\"README.md\");if(le.existsSync(E)||(await le.writeFilePromise(E,`# ${j.stringifyIdent(n.name)}\n`),h.push(E)),!s||s.cwd===this.context.cwd){let C=K.join(this.context.cwd,Er.lockfile);le.existsSync(C)||(await le.writeFilePromise(C,\"\"),h.push(C));let x=[\".yarn/*\",\"!.yarn/patches\",\"!.yarn/plugins\",\"!.yarn/releases\",\"!.yarn/sdks\",\"!.yarn/versions\",\"\",\"# Whether you use PnP or not, the node_modules folder is often used to store\",\"# build artifacts that should be gitignored\",\"node_modules\",\"\",\"# Swap the comments on the following lines if you wish to use zero-installs\",\"# In that case, don't forget to run `yarn config set enableGlobalCache false`!\",\"# Documentation here: https://yarnpkg.com/features/caching#zero-installs\",\"\",\"#!.yarn/cache\",\".pnp.*\"].map(ue=>`${ue}\n`).join(\"\"),I=K.join(this.context.cwd,\".gitignore\");le.existsSync(I)||(await le.writeFilePromise(I,x),h.push(I));let O=[\"/.yarn/**            linguist-vendored\",\"/.yarn/releases/*    binary\",\"/.yarn/plugins/**/*  binary\",\"/.pnp.*              binary linguist-generated\"].map(ue=>`${ue}\n`).join(\"\"),U=K.join(this.context.cwd,\".gitattributes\");le.existsSync(U)||(await le.writeFilePromise(U,O),h.push(U));let Y={\"*\":{charset:\"utf-8\",endOfLine:\"lf\",indentSize:2,indentStyle:\"space\",insertFinalNewline:!0}};Ge.mergeIntoTarget(Y,r.get(\"initEditorConfig\"));let te=`root = true\n`;for(let[ue,ae]of Object.entries(Y)){te+=`\n[${ue}]\n`;for(let[de,Ae]of Object.entries(ae)){let Ce=de.replace(/[A-Z]/g,Ee=>`_${Ee.toLowerCase()}`);te+=`${Ce} = ${Ae}\n`}}let ie=K.join(this.context.cwd,\".editorconfig\");le.existsSync(ie)||(await le.writeFilePromise(ie,te),h.push(ie)),await this.cli.run([\"install\"],{quiet:!0}),await this.initialize(),le.existsSync(K.join(this.context.cwd,\".git\"))||(await qr.execvp(\"git\",[\"init\"],{cwd:this.context.cwd}),await qr.execvp(\"git\",[\"add\",\"--\",...h],{cwd:this.context.cwd}),await qr.execvp(\"git\",[\"commit\",\"--allow-empty\",\"-m\",\"First commit\"],{cwd:this.context.cwd}))}}};var KC=class extends K0{constructor(){super(...arguments);this.initializer=he.String();this.argv=he.Proxy()}static{this.paths=[[\"init\"]]}async initialize(){this.context.stdout.write(`\n`),await this.cli.run([\"dlx\",this.initializer,...this.argv],{quiet:!0})}};var xat={configuration:{initScope:{description:\"Scope used when creating packages via the init command\",type:\"STRING\",default:null},initFields:{description:\"Additional fields to set when creating packages via the init command\",type:\"MAP\",valueDefinition:{description:\"\",type:\"ANY\"}},initEditorConfig:{description:\"Extra rules to define in the generator editorconfig\",type:\"MAP\",valueDefinition:{description:\"\",type:\"ANY\"}}},commands:[K0,KC]},kat=xat;var fW={};Yt(fW,{SearchCommand:()=>Aw,UpgradeInteractiveCommand:()=>pw,default:()=>_pt});qe();var Cme=et(Ie(\"os\"));function JC({stdout:e}){if(Cme.default.endianness()===\"BE\")throw new Error(\"Interactive commands cannot be used on big-endian systems because ink depends on yoga-layout-prebuilt which only supports little-endian architectures\");if(!e.isTTY)throw new Error(\"Interactive commands can only be used inside a TTY environment\")}Vt();var Tye=et(Rq()),Tq={appId:\"OFCNCOG2CU\",apiKey:\"6fe4476ee5a1832882e326b506d14126\",indexName:\"npm-search\"},bct=(0,Tye.default)(Tq.appId,Tq.apiKey).initIndex(Tq.indexName),Fq=async(e,t=0)=>await bct.search(e,{analyticsTags:[\"yarn-plugin-interactive-tools\"],attributesToRetrieve:[\"name\",\"version\",\"owner\",\"repository\",\"humanDownloadsLast30Days\"],page:t,hitsPerPage:10});var CD=[\"regular\",\"dev\",\"peer\"],Aw=class extends At{static{this.paths=[[\"search\"]]}static{this.usage=at.Usage({category:\"Interactive commands\",description:\"open the search interface\",details:`\n    This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry.\n    `,examples:[[\"Open the search window\",\"yarn search\"]]})}async execute(){JC(this.context);let{Gem:t}=await Promise.resolve().then(()=>(xF(),eW)),{ScrollableItems:r}=await Promise.resolve().then(()=>(TF(),RF)),{useKeypress:s}=await Promise.resolve().then(()=>(fw(),tW)),{useMinistore:a}=await Promise.resolve().then(()=>(oW(),sW)),{renderForm:n}=await Promise.resolve().then(()=>(LF(),OF)),{default:c}=await Promise.resolve().then(()=>et(ywe())),{Box:f,Text:p}=await Promise.resolve().then(()=>et(Gc())),{default:h,useEffect:E,useState:C}=await Promise.resolve().then(()=>et(gn())),S=await ze.find(this.context.cwd,this.context.plugins),x=()=>h.createElement(f,{flexDirection:\"row\"},h.createElement(f,{flexDirection:\"column\",width:48},h.createElement(f,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<up>\"),\"/\",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<down>\"),\" to move between packages.\")),h.createElement(f,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<space>\"),\" to select a package.\")),h.createElement(f,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<space>\"),\" again to change the target.\"))),h.createElement(f,{flexDirection:\"column\"},h.createElement(f,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<enter>\"),\" to install the selected packages.\")),h.createElement(f,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<ctrl+c>\"),\" to abort.\")))),I=()=>h.createElement(h.Fragment,null,h.createElement(f,{width:15},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Owner\")),h.createElement(f,{width:11},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Version\")),h.createElement(f,{width:10},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Downloads\"))),T=()=>h.createElement(f,{width:17},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Target\")),O=({hit:Ae,active:Ce})=>{let[Ee,g]=a(Ae.name,null);s({active:Ce},(me,ce)=>{if(ce.name!==\"space\")return;if(!Ee){g(CD[0]);return}let X=CD.indexOf(Ee)+1;X===CD.length?g(null):g(CD[X])},[Ee,g]);let Se=j.parseIdent(Ae.name),Be=j.prettyIdent(S,Se);return h.createElement(f,null,h.createElement(f,{width:45},h.createElement(p,{bold:!0,wrap:\"wrap\"},Be)),h.createElement(f,{width:14,marginLeft:1},h.createElement(p,{bold:!0,wrap:\"truncate\"},Ae.owner.name)),h.createElement(f,{width:10,marginLeft:1},h.createElement(p,{italic:!0,wrap:\"truncate\"},Ae.version)),h.createElement(f,{width:16,marginLeft:1},h.createElement(p,null,Ae.humanDownloadsLast30Days)))},U=({name:Ae,active:Ce})=>{let[Ee]=a(Ae,null),g=j.parseIdent(Ae);return h.createElement(f,null,h.createElement(f,{width:47},h.createElement(p,{bold:!0},\" - \",j.prettyIdent(S,g))),CD.map(Se=>h.createElement(f,{key:Se,width:14,marginLeft:1},h.createElement(p,null,\" \",h.createElement(t,{active:Ee===Se}),\" \",h.createElement(p,{bold:!0},Se)))))},Y=()=>h.createElement(f,{marginTop:1},h.createElement(p,null,\"Powered by Algolia.\")),ie=await n(({useSubmit:Ae})=>{let Ce=a();Ae(Ce);let Ee=Array.from(Ce.keys()).filter(_=>Ce.get(_)!==null),[g,Se]=C(\"\"),[Be,me]=C(0),[ce,X]=C([]),De=_=>{_.match(/\\t| /)||Se(_)},Qe=async()=>{me(0);let _=await Fq(g);_.query===g&&X(_.hits)},it=async()=>{let _=await Fq(g,Be+1);_.query===g&&_.page-1===Be&&(me(_.page),X([...ce,..._.hits]))};return E(()=>{g?Qe():X([])},[g]),h.createElement(f,{flexDirection:\"column\"},h.createElement(x,null),h.createElement(f,{flexDirection:\"row\",marginTop:1},h.createElement(p,{bold:!0},\"Search: \"),h.createElement(f,{width:41},h.createElement(c,{value:g,onChange:De,placeholder:\"i.e. babel, webpack, react...\",showCursor:!1})),h.createElement(I,null)),ce.length?h.createElement(r,{radius:2,loop:!1,children:ce.map(_=>h.createElement(O,{key:_.name,hit:_,active:!1})),willReachEnd:it}):h.createElement(p,{color:\"gray\"},\"Start typing...\"),h.createElement(f,{flexDirection:\"row\",marginTop:1},h.createElement(f,{width:49},h.createElement(p,{bold:!0},\"Selected:\")),h.createElement(T,null)),Ee.length?Ee.map(_=>h.createElement(U,{key:_,name:_,active:!1})):h.createElement(p,{color:\"gray\"},\"No selected packages...\"),h.createElement(Y,null))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof ie>\"u\")return 1;let ue=Array.from(ie.keys()).filter(Ae=>ie.get(Ae)===\"regular\"),ae=Array.from(ie.keys()).filter(Ae=>ie.get(Ae)===\"dev\"),de=Array.from(ie.keys()).filter(Ae=>ie.get(Ae)===\"peer\");return ue.length&&await this.cli.run([\"add\",...ue]),ae.length&&await this.cli.run([\"add\",\"--dev\",...ae]),de&&await this.cli.run([\"add\",\"--peer\",...de]),0}};qe();Vt();cG();var Swe=et(pi());ul();var vwe=/^((?:[\\^~]|>=?)?)([0-9]+)(\\.[0-9]+)(\\.[0-9]+)((?:-\\S+)?)$/;function Dwe(e,t){return e.length>0?[e.slice(0,t)].concat(Dwe(e.slice(t),t)):[]}var pw=class extends At{constructor(){super(...arguments);this.mode=he.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:ks(Na)})}static{this.paths=[[\"upgrade-interactive\"]]}static{this.usage=at.Usage({category:\"Interactive commands\",description:\"open the upgrade interface\",details:\"\\n      This command opens a fullscreen terminal interface where you can see any out of date packages used by your application, their status compared to the latest versions available on the remote registry, and select packages to upgrade.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n    \",examples:[[\"Open the upgrade window\",\"yarn upgrade-interactive\"]]})}async execute(){JC(this.context);let{ItemOptions:r}=await Promise.resolve().then(()=>(Bwe(),wwe)),{Pad:s}=await Promise.resolve().then(()=>(uW(),Cwe)),{ScrollableItems:a}=await Promise.resolve().then(()=>(TF(),RF)),{useMinistore:n,useMinistoreSetAll:c}=await Promise.resolve().then(()=>(oW(),sW)),{useKeypress:f}=await Promise.resolve().then(()=>(fw(),tW)),{renderForm:p}=await Promise.resolve().then(()=>(LF(),OF)),{Box:h,Text:E}=await Promise.resolve().then(()=>et(Gc())),{default:C,useCallback:S,useEffect:x,useRef:I,useState:T}=await Promise.resolve().then(()=>et(gn())),O=await ze.find(this.context.cwd,this.context.plugins),{project:U,workspace:Y}=await Rt.find(O,this.context.cwd),te=await Jr.find(O);if(!Y)throw new ar(U.cwd,this.context.cwd);await U.restoreInstallState({restoreResolutions:!1});let ie=this.context.stdout.rows-8,ue=(X,De)=>{let Qe=i0e(X,De),it=\"\";for(let _ of Qe)_.added?it+=pe.pretty(O,_.value,\"green\"):_.removed||(it+=_.value);return it},ae=(X,De)=>{if(X===De)return De;let Qe=j.parseRange(X),it=j.parseRange(De),_=Qe.selector.match(vwe),tt=it.selector.match(vwe);if(!_||!tt)return ue(X,De);let Ne=[\"gray\",\"red\",\"yellow\",\"green\",\"magenta\"],ke=null,be=\"\";for(let je=1;je<Ne.length;++je)ke!==null||_[je]!==tt[je]?(ke===null&&(ke=Ne[je-1]),be+=pe.pretty(O,tt[je],ke)):be+=tt[je];return be},de=async(X,De,Qe)=>{let it=await $u.fetchDescriptorFrom(X,Qe,{project:U,cache:te,preserveModifier:De,workspace:Y});return it!==null?it.range:X.range},Ae=async X=>{let De=Swe.default.valid(X.range)?`^${X.range}`:X.range,[Qe,it]=await Promise.all([de(X,X.range,De).catch(()=>null),de(X,X.range,\"latest\").catch(()=>null)]),_=[{value:null,label:X.range}];return Qe&&Qe!==X.range?_.push({value:Qe,label:ae(X.range,Qe)}):_.push({value:null,label:\"\"}),it&&it!==Qe&&it!==X.range?_.push({value:it,label:ae(X.range,it)}):_.push({value:null,label:\"\"}),_},Ce=()=>C.createElement(h,{flexDirection:\"row\"},C.createElement(h,{flexDirection:\"column\",width:49},C.createElement(h,{marginLeft:1},C.createElement(E,null,\"Press \",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"<up>\"),\"/\",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"<down>\"),\" to select packages.\")),C.createElement(h,{marginLeft:1},C.createElement(E,null,\"Press \",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"<left>\"),\"/\",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"<right>\"),\" to select versions.\")),C.createElement(h,{marginLeft:1},C.createElement(E,null,\"Press \",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"c\"),\"/\",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"r\"),\"/\",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"l\"),\" to select all \",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"current\"),\"/\",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"range\"),\"/\",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"latest\"),\".\"))),C.createElement(h,{flexDirection:\"column\"},C.createElement(h,{marginLeft:1},C.createElement(E,null,\"Press \",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"<enter>\"),\" to install.\")),C.createElement(h,{marginLeft:1},C.createElement(E,null,\"Press \",C.createElement(E,{bold:!0,color:\"cyanBright\"},\"<ctrl+c>\"),\" to abort.\")))),Ee=()=>C.createElement(h,{flexDirection:\"row\",paddingTop:1,paddingBottom:1},C.createElement(h,{width:50},C.createElement(E,{bold:!0},C.createElement(E,{color:\"greenBright\"},\"?\"),\" Pick the packages you want to upgrade.\")),C.createElement(h,{width:17},C.createElement(E,{bold:!0,underline:!0,color:\"gray\"},\"Current\")),C.createElement(h,{width:17},C.createElement(E,{bold:!0,underline:!0,color:\"gray\"},\"Range\")),C.createElement(h,{width:17},C.createElement(E,{bold:!0,underline:!0,color:\"gray\"},\"Latest\"))),g=({active:X,descriptor:De,suggestions:Qe})=>{let[it,_]=n(De.descriptorHash,null),tt=j.stringifyIdent(De),Ne=Math.max(0,45-tt.length);return C.createElement(C.Fragment,null,C.createElement(h,null,C.createElement(h,{width:45},C.createElement(E,{bold:!0},j.prettyIdent(O,De)),C.createElement(s,{active:X,length:Ne})),C.createElement(r,{active:X,options:Qe,value:it,skewer:!0,onChange:_,sizes:[17,17,17]})))},Se=({dependencies:X})=>{let De=c(),[Qe,it]=T(X.map(()=>null)),_=I(!0),tt=async ke=>{let be=await Ae(ke);return be.filter(je=>je.label!==\"\").length<=1?null:{descriptor:ke,suggestions:be}};x(()=>()=>{_.current=!1},[]),x(()=>{let ke=Math.trunc(ie*1.75),be=X.slice(0,ke),je=X.slice(ke),Re=Dwe(je,ie),ct=be.map(tt).reduce(async(Me,P)=>{await Me;let w=await P;w!==null&&_.current&&it(b=>{let y=b.findIndex(z=>z===null),F=[...b];return F[y]=w,F})},Promise.resolve());Re.reduce((Me,P)=>Promise.all(P.map(w=>Promise.resolve().then(()=>tt(w)))).then(async w=>{w=w.filter(b=>b!==null),await Me,_.current&&it(b=>{let y=b.findIndex(F=>F===null);return b.slice(0,y).concat(w).concat(b.slice(y+w.length))})}),ct).then(()=>{_.current&&it(Me=>Me.filter(P=>P!==null))})},[]);let Ne=S(ke=>{if(ke!==\"c\"&&ke!==\"r\"&&ke!==\"l\")return;let be=[];for(let je of Qe){if(je===null)continue;let Re;ke===\"c\"?Re=null:ke===\"r\"?Re=je.suggestions[1].value:Re=je.suggestions[2].value??je.suggestions[1].value,be.push([je.descriptor.descriptorHash,Re])}De(be)},[Qe,De]);return f({active:!0},Ne,[Ne]),Qe.length?C.createElement(a,{radius:ie>>1,children:Qe.map((ke,be)=>ke!==null?C.createElement(g,{key:be,active:!1,descriptor:ke.descriptor,suggestions:ke.suggestions}):C.createElement(E,{key:be},\"Loading...\"))}):C.createElement(E,null,\"No upgrades found\")},me=await p(({useSubmit:X})=>{X(n());let De=new Map;for(let it of U.workspaces)for(let _ of[\"dependencies\",\"devDependencies\"])for(let tt of it.manifest[_].values())U.tryWorkspaceByDescriptor(tt)===null&&(tt.range.startsWith(\"link:\")||De.set(tt.descriptorHash,tt));let Qe=Ge.sortMap(De.values(),it=>j.stringifyDescriptor(it));return C.createElement(h,{flexDirection:\"column\"},C.createElement(Ce,null),C.createElement(Ee,null),C.createElement(Se,{dependencies:Qe}))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof me>\"u\")return 1;let ce=!1;for(let X of U.workspaces)for(let De of[\"dependencies\",\"devDependencies\"]){let Qe=X.manifest[De];for(let it of Qe.values()){let _=me.get(it.descriptorHash);typeof _<\"u\"&&_!==null&&(Qe.set(it.identHash,j.makeDescriptor(it,_)),ce=!0)}}return ce?await U.installWithNewReport({quiet:this.context.quiet,stdout:this.context.stdout},{cache:te,mode:this.mode}):0}};var Upt={commands:[Aw,pw]},_pt=Upt;var pW={};Yt(pW,{default:()=>qpt});qe();var BD=\"jsr:\";qe();qe();function hw(e){let t=e.range.slice(4);if(Fr.validRange(t))return j.makeDescriptor(e,`npm:${j.stringifyIdent(j.wrapIdentIntoScope(e,\"jsr\"))}@${t}`);let r=j.tryParseDescriptor(t,!0);if(r!==null)return j.makeDescriptor(e,`npm:${j.stringifyIdent(j.wrapIdentIntoScope(r,\"jsr\"))}@${r.range}`);throw new Error(`Invalid range: ${e.range}`)}function gw(e){return j.makeLocator(j.wrapIdentIntoScope(e,\"jsr\"),`npm:${e.reference.slice(4)}`)}function AW(e){return j.makeLocator(j.unwrapIdentFromScope(e,\"jsr\"),`jsr:${e.reference.slice(4)}`)}var MF=class{supports(t,r){return t.reference.startsWith(BD)}getLocalPath(t,r){let s=gw(t);return r.fetcher.getLocalPath(s,r)}fetch(t,r){let s=gw(t);return r.fetcher.fetch(s,r)}};var UF=class{supportsDescriptor(t,r){return!!t.range.startsWith(BD)}supportsLocator(t,r){return!!t.reference.startsWith(BD)}shouldPersistResolution(t,r){let s=gw(t);return r.resolver.shouldPersistResolution(s,r)}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{inner:hw(t)}}async getCandidates(t,r,s){let a=s.project.configuration.normalizeDependency(hw(t));return(await s.resolver.getCandidates(a,r,s)).map(c=>AW(c))}async getSatisfying(t,r,s,a){let n=a.project.configuration.normalizeDependency(hw(t));return a.resolver.getSatisfying(n,r,s,a)}async resolve(t,r){let s=gw(t),a=await r.resolver.resolve(s,r);return{...a,...AW(a)}}};var Hpt=[\"dependencies\",\"devDependencies\",\"peerDependencies\"];function jpt(e,t){for(let r of Hpt)for(let s of e.manifest.getForScope(r).values()){if(!s.range.startsWith(\"jsr:\"))continue;let a=hw(s),n=r===\"dependencies\"?j.makeDescriptor(s,\"unknown\"):null,c=n!==null&&e.manifest.ensureDependencyMeta(n).optional?\"optionalDependencies\":r;t[c][j.stringifyIdent(s)]=a.range}}var Gpt={hooks:{beforeWorkspacePacking:jpt},resolvers:[UF],fetchers:[MF]},qpt=Gpt;var hW={};Yt(hW,{LinkFetcher:()=>vD,LinkResolver:()=>SD,PortalFetcher:()=>DD,PortalResolver:()=>bD,default:()=>Vpt});qe();Dt();var eh=\"portal:\",th=\"link:\";var vD=class{supports(t,r){return!!t.reference.startsWith(th)}getLocalPath(t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(t.reference,{protocol:th});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(s,r);return n===null?null:K.resolve(n,a)}async fetch(t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(t.reference,{protocol:th}),n=K.isAbsolute(a)?{packageFs:new bn(vt.root),prefixPath:vt.dot,localPath:vt.root}:await r.fetcher.fetch(s,r),c=n.localPath?{packageFs:new bn(vt.root),prefixPath:K.relative(vt.root,n.localPath),localPath:vt.root}:n;n!==c&&n.releaseFs&&n.releaseFs();let f=c.packageFs,p=K.resolve(c.localPath??c.packageFs.getRealPath(),c.prefixPath,a);return n.localPath?{packageFs:new bn(p,{baseFs:f}),releaseFs:c.releaseFs,prefixPath:vt.dot,discardFromLookup:!0,localPath:p}:{packageFs:new Gf(p,{baseFs:f}),releaseFs:c.releaseFs,prefixPath:vt.dot,discardFromLookup:!0}}};qe();Dt();var SD=class{supportsDescriptor(t,r){return!!t.range.startsWith(th)}supportsLocator(t,r){return!!t.reference.startsWith(th)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){return j.bindDescriptor(t,{locator:j.stringifyLocator(r)})}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){let a=t.range.slice(th.length);return[j.makeLocator(t,`${th}${fe.toPortablePath(a)}`)]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){return{...t,version:\"0.0.0\",languageName:r.project.configuration.get(\"defaultLanguageName\"),linkType:\"SOFT\",conditions:null,dependencies:new Map,peerDependencies:new Map,dependenciesMeta:new Map,peerDependenciesMeta:new Map,bin:new Map}}};qe();Dt();var DD=class{supports(t,r){return!!t.reference.startsWith(eh)}getLocalPath(t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(t.reference,{protocol:eh});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(s,r);return n===null?null:K.resolve(n,a)}async fetch(t,r){let{parentLocator:s,path:a}=j.parseFileStyleRange(t.reference,{protocol:eh}),n=K.isAbsolute(a)?{packageFs:new bn(vt.root),prefixPath:vt.dot,localPath:vt.root}:await r.fetcher.fetch(s,r),c=n.localPath?{packageFs:new bn(vt.root),prefixPath:K.relative(vt.root,n.localPath),localPath:vt.root}:n;n!==c&&n.releaseFs&&n.releaseFs();let f=c.packageFs,p=K.resolve(c.localPath??c.packageFs.getRealPath(),c.prefixPath,a);return n.localPath?{packageFs:new bn(p,{baseFs:f}),releaseFs:c.releaseFs,prefixPath:vt.dot,localPath:p}:{packageFs:new Gf(p,{baseFs:f}),releaseFs:c.releaseFs,prefixPath:vt.dot}}};qe();qe();Dt();var bD=class{supportsDescriptor(t,r){return!!t.range.startsWith(eh)}supportsLocator(t,r){return!!t.reference.startsWith(eh)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){return j.bindDescriptor(t,{locator:j.stringifyLocator(r)})}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){let a=t.range.slice(eh.length);return[j.makeLocator(t,`${eh}${fe.toPortablePath(a)}`)]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let s=await r.fetchOptions.fetcher.fetch(t,r.fetchOptions),a=await Ge.releaseAfterUseAsync(async()=>await Ut.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...t,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"SOFT\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var Wpt={fetchers:[vD,DD],resolvers:[SD,bD]},Vpt=Wpt;var ZW={};Yt(ZW,{NodeModulesLinker:()=>jD,NodeModulesMode:()=>YW,PnpLooseLinker:()=>GD,default:()=>c0t});Dt();qe();Dt();Dt();var dW=(e,t)=>`${e}@${t}`,bwe=(e,t)=>{let r=t.indexOf(\"#\"),s=r>=0?t.substring(r+1):t;return dW(e,s)};var xwe=(e,t={})=>{let r=t.debugLevel||Number(process.env.NM_DEBUG_LEVEL||-1),s=t.check||r>=9,a=t.hoistingLimits||new Map,n={check:s,debugLevel:r,hoistingLimits:a,fastLookupPossible:!0},c;n.debugLevel>=0&&(c=Date.now());let f=$pt(e,n),p=!1,h=0;do{let E=mW(f,[f],new Set([f.locator]),new Map,n);p=E.anotherRoundNeeded||E.isGraphChanged,n.fastLookupPossible=!1,h++}while(p);if(n.debugLevel>=0&&console.log(`hoist time: ${Date.now()-c}ms, rounds: ${h}`),n.debugLevel>=1){let E=PD(f);if(mW(f,[f],new Set([f.locator]),new Map,n).isGraphChanged)throw new Error(`The hoisting result is not terminal, prev tree:\n${E}, next tree:\n${PD(f)}`);let S=kwe(f);if(S)throw new Error(`${S}, after hoisting finished:\n${PD(f)}`)}return n.debugLevel>=2&&console.log(PD(f)),eht(f)},Ypt=e=>{let t=e[e.length-1],r=new Map,s=new Set,a=n=>{if(!s.has(n)){s.add(n);for(let c of n.hoistedDependencies.values())r.set(c.name,c);for(let c of n.dependencies.values())n.peerNames.has(c.name)||a(c)}};return a(t),r},Kpt=e=>{let t=e[e.length-1],r=new Map,s=new Set,a=new Set,n=(c,f)=>{if(s.has(c))return;s.add(c);for(let h of c.hoistedDependencies.values())if(!f.has(h.name)){let E;for(let C of e)E=C.dependencies.get(h.name),E&&r.set(E.name,E)}let p=new Set;for(let h of c.dependencies.values())p.add(h.name);for(let h of c.dependencies.values())c.peerNames.has(h.name)||n(h,p)};return n(t,a),r},Pwe=(e,t)=>{if(t.decoupled)return t;let{name:r,references:s,ident:a,locator:n,dependencies:c,originalDependencies:f,hoistedDependencies:p,peerNames:h,reasons:E,isHoistBorder:C,hoistPriority:S,dependencyKind:x,hoistedFrom:I,hoistedTo:T}=t,O={name:r,references:new Set(s),ident:a,locator:n,dependencies:new Map(c),originalDependencies:new Map(f),hoistedDependencies:new Map(p),peerNames:new Set(h),reasons:new Map(E),decoupled:!0,isHoistBorder:C,hoistPriority:S,dependencyKind:x,hoistedFrom:new Map(I),hoistedTo:new Map(T)},U=O.dependencies.get(r);return U&&U.ident==O.ident&&O.dependencies.set(r,O),e.dependencies.set(O.name,O),O},Jpt=(e,t)=>{let r=new Map([[e.name,[e.ident]]]);for(let a of e.dependencies.values())e.peerNames.has(a.name)||r.set(a.name,[a.ident]);let s=Array.from(t.keys());s.sort((a,n)=>{let c=t.get(a),f=t.get(n);if(f.hoistPriority!==c.hoistPriority)return f.hoistPriority-c.hoistPriority;{let p=c.dependents.size+c.peerDependents.size;return f.dependents.size+f.peerDependents.size-p}});for(let a of s){let n=a.substring(0,a.indexOf(\"@\",1)),c=a.substring(n.length+1);if(!e.peerNames.has(n)){let f=r.get(n);f||(f=[],r.set(n,f)),f.indexOf(c)<0&&f.push(c)}}return r},gW=e=>{let t=new Set,r=(s,a=new Set)=>{if(!a.has(s)){a.add(s);for(let n of s.peerNames)if(!e.peerNames.has(n)){let c=e.dependencies.get(n);c&&!t.has(c)&&r(c,a)}t.add(s)}};for(let s of e.dependencies.values())e.peerNames.has(s.name)||r(s);return t},mW=(e,t,r,s,a,n=new Set)=>{let c=t[t.length-1];if(n.has(c))return{anotherRoundNeeded:!1,isGraphChanged:!1};n.add(c);let f=tht(c),p=Jpt(c,f),h=e==c?new Map:a.fastLookupPossible?Ypt(t):Kpt(t),E,C=!1,S=!1,x=new Map(Array.from(p.entries()).map(([T,O])=>[T,O[0]])),I=new Map;do{let T=Xpt(e,t,r,h,x,p,s,I,a);T.isGraphChanged&&(S=!0),T.anotherRoundNeeded&&(C=!0),E=!1;for(let[O,U]of p)U.length>1&&!c.dependencies.has(O)&&(x.delete(O),U.shift(),x.set(O,U[0]),E=!0)}while(E);for(let T of c.dependencies.values())if(!c.peerNames.has(T.name)&&!r.has(T.locator)){r.add(T.locator);let O=mW(e,[...t,T],r,I,a);O.isGraphChanged&&(S=!0),O.anotherRoundNeeded&&(C=!0),r.delete(T.locator)}return{anotherRoundNeeded:C,isGraphChanged:S}},zpt=e=>{for(let[t,r]of e.dependencies)if(!e.peerNames.has(t)&&r.ident!==e.ident)return!0;return!1},Zpt=(e,t,r,s,a,n,c,f,{outputReason:p,fastLookupPossible:h})=>{let E,C=null,S=new Set;p&&(E=`${Array.from(t).map(O=>Bo(O)).join(\"\\u2192\")}`);let x=r[r.length-1],T=!(s.ident===x.ident);if(p&&!T&&(C=\"- self-reference\"),T&&(T=s.dependencyKind!==1,p&&!T&&(C=\"- workspace\")),T&&s.dependencyKind===2&&(T=!zpt(s),p&&!T&&(C=\"- external soft link with unhoisted dependencies\")),T&&(T=!e.peerNames.has(s.name),p&&!T&&(C=`- cannot shadow peer: ${Bo(e.originalDependencies.get(s.name).locator)} at ${E}`)),T){let O=!1,U=a.get(s.name);if(O=!U||U.ident===s.ident,p&&!O&&(C=`- filled by: ${Bo(U.locator)} at ${E}`),O)for(let Y=r.length-1;Y>=1;Y--){let ie=r[Y].dependencies.get(s.name);if(ie&&ie.ident!==s.ident){O=!1;let ue=f.get(x);ue||(ue=new Set,f.set(x,ue)),ue.add(s.name),p&&(C=`- filled by ${Bo(ie.locator)} at ${r.slice(0,Y).map(ae=>Bo(ae.locator)).join(\"\\u2192\")}`);break}}T=O}if(T&&(T=n.get(s.name)===s.ident,p&&!T&&(C=`- filled by: ${Bo(c.get(s.name)[0])} at ${E}`)),T){let O=!0,U=new Set(s.peerNames);for(let Y=r.length-1;Y>=1;Y--){let te=r[Y];for(let ie of U){if(te.peerNames.has(ie)&&te.originalDependencies.has(ie))continue;let ue=te.dependencies.get(ie);ue&&e.dependencies.get(ie)!==ue&&(Y===r.length-1?S.add(ue):(S=null,O=!1,p&&(C=`- peer dependency ${Bo(ue.locator)} from parent ${Bo(te.locator)} was not hoisted to ${E}`))),U.delete(ie)}if(!O)break}T=O}if(T&&!h)for(let O of s.hoistedDependencies.values()){let U=a.get(O.name)||e.dependencies.get(O.name);if(!U||O.ident!==U.ident){T=!1,p&&(C=`- previously hoisted dependency mismatch, needed: ${Bo(O.locator)}, available: ${Bo(U?.locator)}`);break}}return S!==null&&S.size>0?{isHoistable:2,dependsOn:S,reason:C}:{isHoistable:T?0:1,reason:C}},_F=e=>`${e.name}@${e.locator}`,Xpt=(e,t,r,s,a,n,c,f,p)=>{let h=t[t.length-1],E=new Set,C=!1,S=!1,x=(U,Y,te,ie,ue)=>{if(E.has(ie))return;let ae=[...Y,_F(ie)],de=[...te,_F(ie)],Ae=new Map,Ce=new Map;for(let me of gW(ie)){let ce=Zpt(h,r,[h,...U,ie],me,s,a,n,f,{outputReason:p.debugLevel>=2,fastLookupPossible:p.fastLookupPossible});if(Ce.set(me,ce),ce.isHoistable===2)for(let X of ce.dependsOn){let De=Ae.get(X.name)||new Set;De.add(me.name),Ae.set(X.name,De)}}let Ee=new Set,g=(me,ce,X)=>{if(!Ee.has(me)){Ee.add(me),Ce.set(me,{isHoistable:1,reason:X});for(let De of Ae.get(me.name)||[])g(ie.dependencies.get(De),ce,p.debugLevel>=2?`- peer dependency ${Bo(me.locator)} from parent ${Bo(ie.locator)} was not hoisted`:\"\")}};for(let[me,ce]of Ce)ce.isHoistable===1&&g(me,ce,ce.reason);let Se=!1;for(let me of Ce.keys())if(!Ee.has(me)){S=!0;let ce=c.get(ie);ce&&ce.has(me.name)&&(C=!0),Se=!0,ie.dependencies.delete(me.name),ie.hoistedDependencies.set(me.name,me),ie.reasons.delete(me.name);let X=h.dependencies.get(me.name);if(p.debugLevel>=2){let De=Array.from(Y).concat([ie.locator]).map(it=>Bo(it)).join(\"\\u2192\"),Qe=h.hoistedFrom.get(me.name);Qe||(Qe=[],h.hoistedFrom.set(me.name,Qe)),Qe.push(De),ie.hoistedTo.set(me.name,Array.from(t).map(it=>Bo(it.locator)).join(\"\\u2192\"))}if(!X)h.ident!==me.ident&&(h.dependencies.set(me.name,me),ue.add(me));else for(let De of me.references)X.references.add(De)}if(ie.dependencyKind===2&&Se&&(C=!0),p.check){let me=kwe(e);if(me)throw new Error(`${me}, after hoisting dependencies of ${[h,...U,ie].map(ce=>Bo(ce.locator)).join(\"\\u2192\")}:\n${PD(e)}`)}let Be=gW(ie);for(let me of Be)if(Ee.has(me)){let ce=Ce.get(me);if((a.get(me.name)===me.ident||!ie.reasons.has(me.name))&&ce.isHoistable!==0&&ie.reasons.set(me.name,ce.reason),!me.isHoistBorder&&de.indexOf(_F(me))<0){E.add(ie);let De=Pwe(ie,me);x([...U,ie],ae,de,De,T),E.delete(ie)}}},I,T=new Set(gW(h)),O=Array.from(t).map(U=>_F(U));do{I=T,T=new Set;for(let U of I){if(U.locator===h.locator||U.isHoistBorder)continue;let Y=Pwe(h,U);x([],Array.from(r),O,Y,T)}}while(T.size>0);return{anotherRoundNeeded:C,isGraphChanged:S}},kwe=e=>{let t=[],r=new Set,s=new Set,a=(n,c,f)=>{if(r.has(n)||(r.add(n),s.has(n)))return;let p=new Map(c);for(let h of n.dependencies.values())n.peerNames.has(h.name)||p.set(h.name,h);for(let h of n.originalDependencies.values()){let E=p.get(h.name),C=()=>`${Array.from(s).concat([n]).map(S=>Bo(S.locator)).join(\"\\u2192\")}`;if(n.peerNames.has(h.name)){let S=c.get(h.name);(S!==E||!S||S.ident!==h.ident)&&t.push(`${C()} - broken peer promise: expected ${h.ident} but found ${S&&S.ident}`)}else{let S=f.hoistedFrom.get(n.name),x=n.hoistedTo.get(h.name),I=`${S?` hoisted from ${S.join(\", \")}`:\"\"}`,T=`${x?` hoisted to ${x}`:\"\"}`,O=`${C()}${I}`;E?E.ident!==h.ident&&t.push(`${O} - broken require promise for ${h.name}${T}: expected ${h.ident}, but found: ${E.ident}`):t.push(`${O} - broken require promise: no required dependency ${h.name}${T} found`)}}s.add(n);for(let h of n.dependencies.values())n.peerNames.has(h.name)||a(h,p,n);s.delete(n)};return a(e,e.dependencies,e),t.join(`\n`)},$pt=(e,t)=>{let{identName:r,name:s,reference:a,peerNames:n}=e,c={name:s,references:new Set([a]),locator:dW(r,a),ident:bwe(r,a),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(n),reasons:new Map,decoupled:!0,isHoistBorder:!0,hoistPriority:0,dependencyKind:1,hoistedFrom:new Map,hoistedTo:new Map},f=new Map([[e,c]]),p=(h,E)=>{let C=f.get(h),S=!!C;if(!C){let{name:x,identName:I,reference:T,peerNames:O,hoistPriority:U,dependencyKind:Y}=h,te=t.hoistingLimits.get(E.locator);C={name:x,references:new Set([T]),locator:dW(I,T),ident:bwe(I,T),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(O),reasons:new Map,decoupled:!0,isHoistBorder:te?te.has(x):!1,hoistPriority:U||0,dependencyKind:Y||0,hoistedFrom:new Map,hoistedTo:new Map},f.set(h,C)}if(E.dependencies.set(h.name,C),E.originalDependencies.set(h.name,C),S){let x=new Set,I=T=>{if(!x.has(T)){x.add(T),T.decoupled=!1;for(let O of T.dependencies.values())T.peerNames.has(O.name)||I(O)}};I(C)}else for(let x of h.dependencies)p(x,C)};for(let h of e.dependencies)p(h,c);return c},yW=e=>e.substring(0,e.indexOf(\"@\",1)),eht=e=>{let t={name:e.name,identName:yW(e.locator),references:new Set(e.references),dependencies:new Set},r=new Set([e]),s=(a,n,c)=>{let f=r.has(a),p;if(n===a)p=c;else{let{name:h,references:E,locator:C}=a;p={name:h,identName:yW(C),references:E,dependencies:new Set}}if(c.dependencies.add(p),!f){r.add(a);for(let h of a.dependencies.values())a.peerNames.has(h.name)||s(h,a,p);r.delete(a)}};for(let a of e.dependencies.values())s(a,e,t);return t},tht=e=>{let t=new Map,r=new Set([e]),s=c=>`${c.name}@${c.ident}`,a=c=>{let f=s(c),p=t.get(f);return p||(p={dependents:new Set,peerDependents:new Set,hoistPriority:0},t.set(f,p)),p},n=(c,f)=>{let p=!!r.has(f);if(a(f).dependents.add(c.ident),!p){r.add(f);for(let E of f.dependencies.values()){let C=a(E);C.hoistPriority=Math.max(C.hoistPriority,E.hoistPriority),f.peerNames.has(E.name)?C.peerDependents.add(f.ident):n(f,E)}}};for(let c of e.dependencies.values())e.peerNames.has(c.name)||n(e,c);return t},Bo=e=>{if(!e)return\"none\";let t=e.indexOf(\"@\",1),r=e.substring(0,t);r.endsWith(\"$wsroot$\")&&(r=`wh:${r.replace(\"$wsroot$\",\"\")}`);let s=e.substring(t+1);if(s===\"workspace:.\")return\".\";if(s){let a=(s.indexOf(\"#\")>0?s.split(\"#\")[1]:s).replace(\"npm:\",\"\");return s.startsWith(\"virtual\")&&(r=`v:${r}`),a.startsWith(\"workspace\")&&(r=`w:${r}`,a=\"\"),`${r}${a?`@${a}`:\"\"}`}else return`${r}`};var PD=e=>{let t=0,r=(a,n,c=\"\")=>{if(t>5e4||n.has(a))return\"\";t++;let f=Array.from(a.dependencies.values()).sort((h,E)=>h.name===E.name?0:h.name>E.name?1:-1),p=\"\";n.add(a);for(let h=0;h<f.length;h++){let E=f[h];if(!a.peerNames.has(E.name)&&E!==a){let C=a.reasons.get(E.name),S=yW(E.locator);p+=`${c}${h<f.length-1?\"\\u251C\\u2500\":\"\\u2514\\u2500\"}${(n.has(E)?\">\":\"\")+(S!==E.name?`a:${E.name}:`:\"\")+Bo(E.locator)+(C?` ${C}`:\"\")}\n`,p+=r(E,n,`${c}${h<f.length-1?\"\\u2502 \":\"  \"}`)}}return n.delete(a),p};return r(e,new Set)+(t>5e4?`\nTree is too large, part of the tree has been dunped\n`:\"\")};var xD=(s=>(s.WORKSPACES=\"workspaces\",s.DEPENDENCIES=\"dependencies\",s.NONE=\"none\",s))(xD||{}),Qwe=\"node_modules\",eg=\"$wsroot$\";var kD=(e,t)=>{let{packageTree:r,hoistingLimits:s,errors:a,preserveSymlinksRequired:n}=nht(e,t),c=null;if(a.length===0){let f=xwe(r,{hoistingLimits:s});c=sht(e,f,t)}return{tree:c,errors:a,preserveSymlinksRequired:n}},hA=e=>`${e.name}@${e.reference}`,IW=e=>{let t=new Map;for(let[r,s]of e.entries())if(!s.dirList){let a=t.get(s.locator);a||(a={target:s.target,linkType:s.linkType,locations:[],aliases:s.aliases},t.set(s.locator,a)),a.locations.push(r)}for(let r of t.values())r.locations=r.locations.sort((s,a)=>{let n=s.split(K.delimiter).length,c=a.split(K.delimiter).length;return a===s?0:n!==c?c-n:a>s?1:-1});return t},Rwe=(e,t)=>{let r=j.isVirtualLocator(e)?j.devirtualizeLocator(e):e,s=j.isVirtualLocator(t)?j.devirtualizeLocator(t):t;return j.areLocatorsEqual(r,s)},EW=(e,t,r,s)=>{if(e.linkType!==\"SOFT\")return!1;let a=fe.toPortablePath(r.resolveVirtual&&t.reference&&t.reference.startsWith(\"virtual:\")?r.resolveVirtual(e.packageLocation):e.packageLocation);return K.contains(s,a)===null},rht=e=>{let t=e.getPackageInformation(e.topLevel);if(t===null)throw new Error(\"Assertion failed: Expected the top-level package to have been registered\");if(e.findPackageLocator(t.packageLocation)===null)throw new Error(\"Assertion failed: Expected the top-level package to have a physical locator\");let s=fe.toPortablePath(t.packageLocation.slice(0,-1)),a=new Map,n={children:new Map},c=e.getDependencyTreeRoots(),f=new Map,p=new Set,h=(S,x)=>{let I=hA(S);if(p.has(I))return;p.add(I);let T=e.getPackageInformation(S);if(T){let O=x?hA(x):\"\";if(hA(S)!==O&&T.linkType===\"SOFT\"&&!S.reference.startsWith(\"link:\")&&!EW(T,S,e,s)){let U=Twe(T,S,e);(!f.get(U)||S.reference.startsWith(\"workspace:\"))&&f.set(U,S)}for(let[U,Y]of T.packageDependencies)Y!==null&&(T.packagePeers.has(U)||h(e.getLocator(U,Y),S))}};for(let S of c)h(S,null);let E=s.split(K.sep);for(let S of f.values()){let x=e.getPackageInformation(S),T=fe.toPortablePath(x.packageLocation.slice(0,-1)).split(K.sep).slice(E.length),O=n;for(let U of T){let Y=O.children.get(U);Y||(Y={children:new Map},O.children.set(U,Y)),O=Y}O.workspaceLocator=S}let C=(S,x)=>{if(S.workspaceLocator){let I=hA(x),T=a.get(I);T||(T=new Set,a.set(I,T)),T.add(S.workspaceLocator)}for(let I of S.children.values())C(I,S.workspaceLocator||x)};for(let S of n.children.values())C(S,n.workspaceLocator);return a},nht=(e,t)=>{let r=[],s=!1,a=new Map,n=rht(e),c=e.getPackageInformation(e.topLevel);if(c===null)throw new Error(\"Assertion failed: Expected the top-level package to have been registered\");let f=e.findPackageLocator(c.packageLocation);if(f===null)throw new Error(\"Assertion failed: Expected the top-level package to have a physical locator\");let p=fe.toPortablePath(c.packageLocation.slice(0,-1)),h={name:f.name,identName:f.name,reference:f.reference,peerNames:c.packagePeers,dependencies:new Set,dependencyKind:1},E=new Map,C=(x,I)=>`${hA(I)}:${x}`,S=(x,I,T,O,U,Y,te,ie)=>{let ue=C(x,T),ae=E.get(ue),de=!!ae;!de&&T.name===f.name&&T.reference===f.reference&&(ae=h,E.set(ue,h));let Ae=EW(I,T,e,p);if(!ae){let me=0;Ae?me=2:I.linkType===\"SOFT\"&&T.name.endsWith(eg)&&(me=1),ae={name:x,identName:T.name,reference:T.reference,dependencies:new Set,peerNames:me===1?new Set:I.packagePeers,dependencyKind:me},E.set(ue,ae)}let Ce;if(Ae?Ce=2:U.linkType===\"SOFT\"?Ce=1:Ce=0,ae.hoistPriority=Math.max(ae.hoistPriority||0,Ce),ie&&!Ae){let me=hA({name:O.identName,reference:O.reference}),ce=a.get(me)||new Set;a.set(me,ce),ce.add(ae.name)}let Ee=new Map(I.packageDependencies);if(t.project){let me=t.project.workspacesByCwd.get(fe.toPortablePath(I.packageLocation.slice(0,-1)));if(me){let ce=new Set([...Array.from(me.manifest.peerDependencies.values(),X=>j.stringifyIdent(X)),...Array.from(me.manifest.peerDependenciesMeta.keys())]);for(let X of ce)Ee.has(X)||(Ee.set(X,Y.get(X)||null),ae.peerNames.add(X))}}let g=hA({name:T.name.replace(eg,\"\"),reference:T.reference}),Se=n.get(g);if(Se)for(let me of Se)Ee.set(`${me.name}${eg}`,me.reference);(I!==U||I.linkType!==\"SOFT\"||!Ae&&(!t.selfReferencesByCwd||t.selfReferencesByCwd.get(te)))&&O.dependencies.add(ae);let Be=T!==f&&I.linkType===\"SOFT\"&&!T.name.endsWith(eg)&&!Ae;if(!de&&!Be){let me=new Map;for(let[ce,X]of Ee)if(X!==null){let De=e.getLocator(ce,X),Qe=e.getLocator(ce.replace(eg,\"\"),X),it=e.getPackageInformation(Qe);if(it===null)throw new Error(\"Assertion failed: Expected the package to have been registered\");let _=EW(it,De,e,p);if(t.validateExternalSoftLinks&&t.project&&_){it.packageDependencies.size>0&&(s=!0);for(let[je,Re]of it.packageDependencies)if(Re!==null){let ct=j.parseLocator(Array.isArray(Re)?`${Re[0]}@${Re[1]}`:`${je}@${Re}`);if(hA(ct)!==hA(De)){let Me=Ee.get(je);if(Me){let P=j.parseLocator(Array.isArray(Me)?`${Me[0]}@${Me[1]}`:`${je}@${Me}`);Rwe(P,ct)||r.push({messageName:71,text:`Cannot link ${j.prettyIdent(t.project.configuration,j.parseIdent(De.name))} into ${j.prettyLocator(t.project.configuration,j.parseLocator(`${T.name}@${T.reference}`))} dependency ${j.prettyLocator(t.project.configuration,ct)} conflicts with parent dependency ${j.prettyLocator(t.project.configuration,P)}`})}else{let P=me.get(je);if(P){let w=P.target,b=j.parseLocator(Array.isArray(w)?`${w[0]}@${w[1]}`:`${je}@${w}`);Rwe(b,ct)||r.push({messageName:71,text:`Cannot link ${j.prettyIdent(t.project.configuration,j.parseIdent(De.name))} into ${j.prettyLocator(t.project.configuration,j.parseLocator(`${T.name}@${T.reference}`))} dependency ${j.prettyLocator(t.project.configuration,ct)} conflicts with dependency ${j.prettyLocator(t.project.configuration,b)} from sibling portal ${j.prettyIdent(t.project.configuration,j.parseIdent(P.portal.name))}`})}else me.set(je,{target:ct.reference,portal:De})}}}}let tt=t.hoistingLimitsByCwd?.get(te),Ne=_?te:K.relative(p,fe.toPortablePath(it.packageLocation))||vt.dot,ke=t.hoistingLimitsByCwd?.get(Ne);S(ce,it,De,ae,I,Ee,Ne,tt===\"dependencies\"||ke===\"dependencies\"||ke===\"workspaces\")}}};return S(f.name,c,f,h,c,c.packageDependencies,vt.dot,!1),{packageTree:h,hoistingLimits:a,errors:r,preserveSymlinksRequired:s}};function Twe(e,t,r){let s=r.resolveVirtual&&t.reference&&t.reference.startsWith(\"virtual:\")?r.resolveVirtual(e.packageLocation):e.packageLocation;return fe.toPortablePath(s||e.packageLocation)}function iht(e,t,r){let s=t.getLocator(e.name.replace(eg,\"\"),e.reference),a=t.getPackageInformation(s);if(a===null)throw new Error(\"Assertion failed: Expected the package to be registered\");return r.pnpifyFs?{linkType:\"SOFT\",target:fe.toPortablePath(a.packageLocation)}:{linkType:a.linkType,target:Twe(a,e,t)}}var sht=(e,t,r)=>{let s=new Map,a=(E,C,S)=>{let{linkType:x,target:I}=iht(E,e,r);return{locator:hA(E),nodePath:C,target:I,linkType:x,aliases:S}},n=E=>{let[C,S]=E.split(\"/\");return S?{scope:C,name:S}:{scope:null,name:C}},c=new Set,f=(E,C,S)=>{if(c.has(E))return;c.add(E);let x=Array.from(E.references).sort().join(\"#\");for(let I of E.dependencies){let T=Array.from(I.references).sort().join(\"#\");if(I.identName===E.identName.replace(eg,\"\")&&T===x)continue;let O=Array.from(I.references).sort(),U={name:I.identName,reference:O[0]},{name:Y,scope:te}=n(I.name),ie=te?[te,Y]:[Y],ue=K.join(C,Qwe),ae=K.join(ue,...ie),de=`${S}/${U.name}`,Ae=a(U,S,O.slice(1)),Ce=!1;if(Ae.linkType===\"SOFT\"&&r.project){let Ee=r.project.workspacesByCwd.get(Ae.target.slice(0,-1));Ce=!!(Ee&&!Ee.manifest.name)}if(!I.name.endsWith(eg)&&!Ce){let Ee=s.get(ae);if(Ee){if(Ee.dirList)throw new Error(`Assertion failed: ${ae} cannot merge dir node with leaf node`);{let Be=j.parseLocator(Ee.locator),me=j.parseLocator(Ae.locator);if(Ee.linkType!==Ae.linkType)throw new Error(`Assertion failed: ${ae} cannot merge nodes with different link types ${Ee.nodePath}/${j.stringifyLocator(Be)} and ${S}/${j.stringifyLocator(me)}`);if(Be.identHash!==me.identHash)throw new Error(`Assertion failed: ${ae} cannot merge nodes with different idents ${Ee.nodePath}/${j.stringifyLocator(Be)} and ${S}/s${j.stringifyLocator(me)}`);Ae.aliases=[...Ae.aliases,...Ee.aliases,j.parseLocator(Ee.locator).reference]}}s.set(ae,Ae);let g=ae.split(\"/\"),Se=g.indexOf(Qwe);for(let Be=g.length-1;Se>=0&&Be>Se;Be--){let me=fe.toPortablePath(g.slice(0,Be).join(K.sep)),ce=g[Be],X=s.get(me);if(!X)s.set(me,{dirList:new Set([ce])});else if(X.dirList){if(X.dirList.has(ce))break;X.dirList.add(ce)}}}f(I,Ae.linkType===\"SOFT\"?Ae.target:ae,de)}},p=a({name:t.name,reference:Array.from(t.references)[0]},\"\",[]),h=p.target;return s.set(h,p),f(t,h,\"\"),s};qe();qe();Dt();Dt();rA();Bc();var UW={};Yt(UW,{PnpInstaller:()=>Vm,PnpLinker:()=>ng,UnplugCommand:()=>mw,default:()=>Nht,getPnpPath:()=>ig,jsInstallUtils:()=>dA,pnpUtils:()=>HD,quotePathIfNeeded:()=>m1e});Dt();var d1e=Ie(\"url\");qe();qe();Dt();Dt();var Fwe={DEFAULT:{collapsed:!1,next:{\"*\":\"DEFAULT\"}},TOP_LEVEL:{collapsed:!1,next:{fallbackExclusionList:\"FALLBACK_EXCLUSION_LIST\",packageRegistryData:\"PACKAGE_REGISTRY_DATA\",\"*\":\"DEFAULT\"}},FALLBACK_EXCLUSION_LIST:{collapsed:!1,next:{\"*\":\"FALLBACK_EXCLUSION_ENTRIES\"}},FALLBACK_EXCLUSION_ENTRIES:{collapsed:!0,next:{\"*\":\"FALLBACK_EXCLUSION_DATA\"}},FALLBACK_EXCLUSION_DATA:{collapsed:!0,next:{\"*\":\"DEFAULT\"}},PACKAGE_REGISTRY_DATA:{collapsed:!1,next:{\"*\":\"PACKAGE_REGISTRY_ENTRIES\"}},PACKAGE_REGISTRY_ENTRIES:{collapsed:!0,next:{\"*\":\"PACKAGE_STORE_DATA\"}},PACKAGE_STORE_DATA:{collapsed:!1,next:{\"*\":\"PACKAGE_STORE_ENTRIES\"}},PACKAGE_STORE_ENTRIES:{collapsed:!0,next:{\"*\":\"PACKAGE_INFORMATION_DATA\"}},PACKAGE_INFORMATION_DATA:{collapsed:!1,next:{packageDependencies:\"PACKAGE_DEPENDENCIES\",\"*\":\"DEFAULT\"}},PACKAGE_DEPENDENCIES:{collapsed:!1,next:{\"*\":\"PACKAGE_DEPENDENCY\"}},PACKAGE_DEPENDENCY:{collapsed:!0,next:{\"*\":\"DEFAULT\"}}};function oht(e,t,r){let s=\"\";s+=\"[\";for(let a=0,n=e.length;a<n;++a)s+=HF(String(a),e[a],t,r).replace(/^ +/g,\"\"),a+1<n&&(s+=\", \");return s+=\"]\",s}function aht(e,t,r){let s=`${r}  `,a=\"\";a+=r,a+=`[\n`;for(let n=0,c=e.length;n<c;++n)a+=s+HF(String(n),e[n],t,s).replace(/^ +/,\"\"),n+1<c&&(a+=\",\"),a+=`\n`;return a+=r,a+=\"]\",a}function lht(e,t,r){let s=Object.keys(e),a=\"\";a+=\"{\";for(let n=0,c=s.length,f=0;n<c;++n){let p=s[n],h=e[p];typeof h>\"u\"||(f!==0&&(a+=\", \"),a+=JSON.stringify(p),a+=\": \",a+=HF(p,h,t,r).replace(/^ +/g,\"\"),f+=1)}return a+=\"}\",a}function cht(e,t,r){let s=Object.keys(e),a=`${r}  `,n=\"\";n+=r,n+=`{\n`;let c=0;for(let f=0,p=s.length;f<p;++f){let h=s[f],E=e[h];typeof E>\"u\"||(c!==0&&(n+=\",\",n+=`\n`),n+=a,n+=JSON.stringify(h),n+=\": \",n+=HF(h,E,t,a).replace(/^ +/g,\"\"),c+=1)}return c!==0&&(n+=`\n`),n+=r,n+=\"}\",n}function HF(e,t,r,s){let{next:a}=Fwe[r],n=a[e]||a[\"*\"];return Nwe(t,n,s)}function Nwe(e,t,r){let{collapsed:s}=Fwe[t];return Array.isArray(e)?s?oht(e,t,r):aht(e,t,r):typeof e==\"object\"&&e!==null?s?lht(e,t,r):cht(e,t,r):JSON.stringify(e)}function Owe(e){return Nwe(e,\"TOP_LEVEL\",\"\")}function QD(e,t){let r=Array.from(e);Array.isArray(t)||(t=[t]);let s=[];for(let n of t)s.push(r.map(c=>n(c)));let a=r.map((n,c)=>c);return a.sort((n,c)=>{for(let f of s){let p=f[n]<f[c]?-1:f[n]>f[c]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function uht(e){let t=new Map,r=QD(e.fallbackExclusionList||[],[({name:s,reference:a})=>s,({name:s,reference:a})=>a]);for(let{name:s,reference:a}of r){let n=t.get(s);typeof n>\"u\"&&t.set(s,n=new Set),n.add(a)}return Array.from(t).map(([s,a])=>[s,Array.from(a)])}function fht(e){return QD(e.fallbackPool||[],([t])=>t)}function Aht(e){let t=[],r=e.dependencyTreeRoots.find(s=>e.packageRegistry.get(s.name)?.get(s.reference)?.packageLocation===\"./\");for(let[s,a]of QD(e.packageRegistry,([n])=>n===null?\"0\":`1${n}`)){if(s===null)continue;let n=[];t.push([s,n]);for(let[c,{packageLocation:f,packageDependencies:p,packagePeers:h,linkType:E,discardFromLookup:C}]of QD(a,([S])=>S===null?\"0\":`1${S}`)){if(c===null)continue;let S=[];s!==null&&c!==null&&!p.has(s)&&S.push([s,c]);for(let[U,Y]of p)S.push([U,Y]);let x=QD(S,([U])=>U),I=h&&h.size>0?Array.from(h):void 0,O={packageLocation:f,packageDependencies:x,packagePeers:I,linkType:E,discardFromLookup:C||void 0};n.push([c,O]),r&&s===r.name&&c===r.reference&&t.unshift([null,[[null,O]]])}}return t}function RD(e){return{__info:[\"This file is automatically generated. Do not touch it, or risk\",\"your modifications being lost.\"],dependencyTreeRoots:e.dependencyTreeRoots,enableTopLevelFallback:e.enableTopLevelFallback||!1,ignorePatternData:e.ignorePattern||null,pnpZipBackend:e.pnpZipBackend,fallbackExclusionList:uht(e),fallbackPool:fht(e),packageRegistryData:Aht(e)}}var Uwe=et(Mwe());function _we(e,t){return[e?`${e}\n`:\"\",`/* eslint-disable */\n`,`// @ts-nocheck\n`,`\"use strict\";\n`,`\n`,t,`\n`,(0,Uwe.default)()].join(\"\")}function pht(e){return JSON.stringify(e,null,2)}function hht(e){return`'${e.replace(/\\\\/g,\"\\\\\\\\\").replace(/'/g,\"\\\\'\").replace(/\\n/g,`\\\\\n`)}'`}function ght(e){return[`const RAW_RUNTIME_STATE =\n`,`${hht(Owe(e))};\n\n`,`function $$SETUP_STATE(hydrateRuntimeState, basePath) {\n`,`  return hydrateRuntimeState(JSON.parse(RAW_RUNTIME_STATE), {basePath: basePath || __dirname});\n`,`}\n`].join(\"\")}function dht(){return[`function $$SETUP_STATE(hydrateRuntimeState, basePath) {\n`,`  const fs = require('fs');\n`,`  const path = require('path');\n`,`  const pnpDataFilepath = path.resolve(__dirname, ${JSON.stringify(Er.pnpData)});\n`,`  return hydrateRuntimeState(JSON.parse(fs.readFileSync(pnpDataFilepath, 'utf8')), {basePath: basePath || __dirname});\n`,`}\n`].join(\"\")}function Hwe(e){let t=RD(e),r=ght(t);return _we(e.shebang,r)}function jwe(e){let t=RD(e),r=dht(),s=_we(e.shebang,r);return{dataFile:pht(t),loaderFile:s}}Dt();function wW(e,{basePath:t}){let r=fe.toPortablePath(t),s=K.resolve(r),a=e.ignorePatternData!==null?new RegExp(e.ignorePatternData):null,n=new Map,c=new Map(e.packageRegistryData.map(([C,S])=>[C,new Map(S.map(([x,I])=>{if(C===null!=(x===null))throw new Error(\"Assertion failed: The name and reference should be null, or neither should\");let T=I.discardFromLookup??!1,O={name:C,reference:x},U=n.get(I.packageLocation);U?(U.discardFromLookup=U.discardFromLookup&&T,T||(U.locator=O)):n.set(I.packageLocation,{locator:O,discardFromLookup:T});let Y=null;return[x,{packageDependencies:new Map(I.packageDependencies),packagePeers:new Set(I.packagePeers),linkType:I.linkType,discardFromLookup:T,get packageLocation(){return Y||(Y=K.join(s,I.packageLocation))}}]}))])),f=new Map(e.fallbackExclusionList.map(([C,S])=>[C,new Set(S)])),p=new Map(e.fallbackPool),h=e.dependencyTreeRoots,E=e.enableTopLevelFallback;return{basePath:r,dependencyTreeRoots:h,enableTopLevelFallback:E,fallbackExclusionList:f,pnpZipBackend:e.pnpZipBackend,fallbackPool:p,ignorePattern:a,packageLocatorsByLocations:n,packageRegistry:c}}Dt();Dt();var nh=Ie(\"module\"),Wm=Ie(\"url\"),RW=Ie(\"util\");var sa=Ie(\"url\");var Vwe=et(Ie(\"assert\"));var BW=Array.isArray,TD=JSON.stringify,FD=Object.getOwnPropertyNames,qm=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),vW=(e,t)=>RegExp.prototype.exec.call(e,t),SW=(e,...t)=>RegExp.prototype[Symbol.replace].apply(e,t),tg=(e,...t)=>String.prototype.endsWith.apply(e,t),DW=(e,...t)=>String.prototype.includes.apply(e,t),bW=(e,...t)=>String.prototype.lastIndexOf.apply(e,t),ND=(e,...t)=>String.prototype.indexOf.apply(e,t),Gwe=(e,...t)=>String.prototype.replace.apply(e,t),rg=(e,...t)=>String.prototype.slice.apply(e,t),gA=(e,...t)=>String.prototype.startsWith.apply(e,t),qwe=Map,Wwe=JSON.parse;function OD(e,t,r){return class extends r{constructor(...s){super(t(...s)),this.code=e,this.name=`${r.name} [${e}]`}}}var Ywe=OD(\"ERR_PACKAGE_IMPORT_NOT_DEFINED\",(e,t,r)=>`Package import specifier \"${e}\" is not defined${t?` in package ${t}package.json`:\"\"} imported from ${r}`,TypeError),PW=OD(\"ERR_INVALID_MODULE_SPECIFIER\",(e,t,r=void 0)=>`Invalid module \"${e}\" ${t}${r?` imported from ${r}`:\"\"}`,TypeError),Kwe=OD(\"ERR_INVALID_PACKAGE_TARGET\",(e,t,r,s=!1,a=void 0)=>{let n=typeof r==\"string\"&&!s&&r.length&&!gA(r,\"./\");return t===\".\"?((0,Vwe.default)(s===!1),`Invalid \"exports\" main target ${TD(r)} defined in the package config ${e}package.json${a?` imported from ${a}`:\"\"}${n?'; targets must start with \"./\"':\"\"}`):`Invalid \"${s?\"imports\":\"exports\"}\" target ${TD(r)} defined for '${t}' in the package config ${e}package.json${a?` imported from ${a}`:\"\"}${n?'; targets must start with \"./\"':\"\"}`},Error),LD=OD(\"ERR_INVALID_PACKAGE_CONFIG\",(e,t,r)=>`Invalid package config ${e}${t?` while importing ${t}`:\"\"}${r?`. ${r}`:\"\"}`,Error),Jwe=OD(\"ERR_PACKAGE_PATH_NOT_EXPORTED\",(e,t,r=void 0)=>t===\".\"?`No \"exports\" main defined in ${e}package.json${r?` imported from ${r}`:\"\"}`:`Package subpath '${t}' is not defined by \"exports\" in ${e}package.json${r?` imported from ${r}`:\"\"}`,Error);var GF=Ie(\"url\");function zwe(e,t){let r=Object.create(null);for(let s=0;s<t.length;s++){let a=t[s];qm(e,a)&&(r[a]=e[a])}return r}var jF=new qwe;function mht(e,t,r,s){let a=jF.get(e);if(a!==void 0)return a;let n=s(e);if(n===void 0){let x={pjsonPath:e,exists:!1,main:void 0,name:void 0,type:\"none\",exports:void 0,imports:void 0};return jF.set(e,x),x}let c;try{c=Wwe(n)}catch(x){throw new LD(e,(r?`\"${t}\" from `:\"\")+(0,GF.fileURLToPath)(r||t),x.message)}let{imports:f,main:p,name:h,type:E}=zwe(c,[\"imports\",\"main\",\"name\",\"type\"]),C=qm(c,\"exports\")?c.exports:void 0;(typeof f!=\"object\"||f===null)&&(f=void 0),typeof p!=\"string\"&&(p=void 0),typeof h!=\"string\"&&(h=void 0),E!==\"module\"&&E!==\"commonjs\"&&(E=\"none\");let S={pjsonPath:e,exists:!0,main:p,name:h,type:E,exports:C,imports:f};return jF.set(e,S),S}function Zwe(e,t){let r=new URL(\"./package.json\",e);for(;;){let n=r.pathname;if(tg(n,\"node_modules/package.json\"))break;let c=mht((0,GF.fileURLToPath)(r),e,void 0,t);if(c.exists)return c;let f=r;if(r=new URL(\"../package.json\",r),r.pathname===f.pathname)break}let s=(0,GF.fileURLToPath)(r),a={pjsonPath:s,exists:!1,main:void 0,name:void 0,type:\"none\",exports:void 0,imports:void 0};return jF.set(s,a),a}function yht(e,t,r){throw new Ywe(e,t&&(0,sa.fileURLToPath)(new URL(\".\",t)),(0,sa.fileURLToPath)(r))}function Eht(e,t,r,s){let a=`request is not a valid subpath for the \"${r?\"imports\":\"exports\"}\" resolution of ${(0,sa.fileURLToPath)(t)}`;throw new PW(e,a,s&&(0,sa.fileURLToPath)(s))}function MD(e,t,r,s,a){throw typeof t==\"object\"&&t!==null?t=TD(t,null,\"\"):t=`${t}`,new Kwe((0,sa.fileURLToPath)(new URL(\".\",r)),e,t,s,a&&(0,sa.fileURLToPath)(a))}var Xwe=/(^|\\\\|\\/)((\\.|%2e)(\\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\\\|\\/|$)/i,$we=/\\*/g;function Iht(e,t,r,s,a,n,c,f){if(t!==\"\"&&!n&&e[e.length-1]!==\"/\"&&MD(r,e,s,c,a),!gA(e,\"./\")){if(c&&!gA(e,\"../\")&&!gA(e,\"/\")){let C=!1;try{new URL(e),C=!0}catch{}if(!C)return n?SW($we,e,()=>t):e+t}MD(r,e,s,c,a)}vW(Xwe,rg(e,2))!==null&&MD(r,e,s,c,a);let p=new URL(e,s),h=p.pathname,E=new URL(\".\",s).pathname;if(gA(h,E)||MD(r,e,s,c,a),t===\"\")return p;if(vW(Xwe,t)!==null){let C=n?Gwe(r,\"*\",()=>t):r+t;Eht(C,s,c,a)}return n?new URL(SW($we,p.href,()=>t)):new URL(t,p)}function Cht(e){let t=+e;return`${t}`!==e?!1:t>=0&&t<4294967295}function dw(e,t,r,s,a,n,c,f){if(typeof t==\"string\")return Iht(t,r,s,e,a,n,c,f);if(BW(t)){if(t.length===0)return null;let p;for(let h=0;h<t.length;h++){let E=t[h],C;try{C=dw(e,E,r,s,a,n,c,f)}catch(S){if(p=S,S.code===\"ERR_INVALID_PACKAGE_TARGET\")continue;throw S}if(C!==void 0){if(C===null){p=null;continue}return C}}if(p==null)return p;throw p}else if(typeof t==\"object\"&&t!==null){let p=FD(t);for(let h=0;h<p.length;h++){let E=p[h];if(Cht(E))throw new LD((0,sa.fileURLToPath)(e),a,'\"exports\" cannot contain numeric property keys.')}for(let h=0;h<p.length;h++){let E=p[h];if(E===\"default\"||f.has(E)){let C=t[E],S=dw(e,C,r,s,a,n,c,f);if(S===void 0)continue;return S}}return}else if(t===null)return null;MD(s,t,e,c,a)}function t1e(e,t){let r=ND(e,\"*\"),s=ND(t,\"*\"),a=r===-1?e.length:r+1,n=s===-1?t.length:s+1;return a>n?-1:n>a||r===-1?1:s===-1||e.length>t.length?-1:t.length>e.length?1:0}function wht(e,t,r){if(typeof e==\"string\"||BW(e))return!0;if(typeof e!=\"object\"||e===null)return!1;let s=FD(e),a=!1,n=0;for(let c=0;c<s.length;c++){let f=s[c],p=f===\"\"||f[0]!==\".\";if(n++===0)a=p;else if(a!==p)throw new LD((0,sa.fileURLToPath)(t),r,`\"exports\" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.`)}return a}function xW(e,t,r){throw new Jwe((0,sa.fileURLToPath)(new URL(\".\",t)),e,r&&(0,sa.fileURLToPath)(r))}var e1e=new Set;function Bht(e,t,r){let s=(0,sa.fileURLToPath)(t);e1e.has(s+\"|\"+e)||(e1e.add(s+\"|\"+e),process.emitWarning(`Use of deprecated trailing slash pattern mapping \"${e}\" in the \"exports\" field module resolution of the package at ${s}${r?` imported from ${(0,sa.fileURLToPath)(r)}`:\"\"}. Mapping specifiers ending in \"/\" is no longer supported.`,\"DeprecationWarning\",\"DEP0155\"))}function r1e({packageJSONUrl:e,packageSubpath:t,exports:r,base:s,conditions:a}){if(wht(r,e,s)&&(r={\".\":r}),qm(r,t)&&!DW(t,\"*\")&&!tg(t,\"/\")){let p=r[t],h=dw(e,p,\"\",t,s,!1,!1,a);return h==null&&xW(t,e,s),h}let n=\"\",c,f=FD(r);for(let p=0;p<f.length;p++){let h=f[p],E=ND(h,\"*\");if(E!==-1&&gA(t,rg(h,0,E))){tg(t,\"/\")&&Bht(t,e,s);let C=rg(h,E+1);t.length>=h.length&&tg(t,C)&&t1e(n,h)===1&&bW(h,\"*\")===E&&(n=h,c=rg(t,E,t.length-C.length))}}if(n){let p=r[n],h=dw(e,p,c,n,s,!0,!1,a);return h==null&&xW(t,e,s),h}xW(t,e,s)}function n1e({name:e,base:t,conditions:r,readFileSyncFn:s}){if(e===\"#\"||gA(e,\"#/\")||tg(e,\"/\")){let c=\"is not a valid internal imports specifier name\";throw new PW(e,c,(0,sa.fileURLToPath)(t))}let a,n=Zwe(t,s);if(n.exists){a=(0,sa.pathToFileURL)(n.pjsonPath);let c=n.imports;if(c)if(qm(c,e)&&!DW(e,\"*\")){let f=dw(a,c[e],\"\",e,t,!1,!0,r);if(f!=null)return f}else{let f=\"\",p,h=FD(c);for(let E=0;E<h.length;E++){let C=h[E],S=ND(C,\"*\");if(S!==-1&&gA(e,rg(C,0,S))){let x=rg(C,S+1);e.length>=C.length&&tg(e,x)&&t1e(f,C)===1&&bW(C,\"*\")===S&&(f=C,p=rg(e,S,e.length-x.length))}}if(f){let E=c[f],C=dw(a,E,p,f,t,!0,!0,r);if(C!=null)return C}}}yht(e,a,t)}Dt();var vht=new Set([\"BUILTIN_NODE_RESOLUTION_FAILED\",\"MISSING_DEPENDENCY\",\"MISSING_PEER_DEPENDENCY\",\"QUALIFIED_PATH_RESOLUTION_FAILED\",\"UNDECLARED_DEPENDENCY\"]);function ys(e,t,r={},s){s??=vht.has(e)?\"MODULE_NOT_FOUND\":e;let a={configurable:!0,writable:!0,enumerable:!1};return Object.defineProperties(new Error(t),{code:{...a,value:s},pnpCode:{...a,value:e},data:{...a,value:r}})}function uf(e){return fe.normalize(fe.fromPortablePath(e))}var a1e=et(s1e());function l1e(e){return Sht(),QW[e]}var QW;function Sht(){QW||(QW={\"--conditions\":[],...o1e(Dht()),...o1e(process.execArgv)})}function o1e(e){return(0,a1e.default)({\"--conditions\":[String],\"-C\":\"--conditions\"},{argv:e,permissive:!0})}function Dht(){let e=[],t=bht(process.env.NODE_OPTIONS||\"\",e);return e.length,t}function bht(e,t){let r=[],s=!1,a=!0;for(let n=0;n<e.length;++n){let c=e[n];if(c===\"\\\\\"&&s){if(n+1===e.length)return t.push(`invalid value for NODE_OPTIONS (invalid escape)\n`),r;c=e[++n]}else if(c===\" \"&&!s){a=!0;continue}else if(c==='\"'){s=!s;continue}a?(r.push(c),a=!1):r[r.length-1]+=c}return s&&t.push(`invalid value for NODE_OPTIONS (unterminated string)\n`),r}Dt();var[Bl,rh]=process.versions.node.split(\".\").map(e=>parseInt(e,10)),c1e=Bl>19||Bl===19&&rh>=2||Bl===18&&rh>=13,GJt=Bl===20&&rh<6||Bl===19&&rh>=3,qJt=Bl>19||Bl===19&&rh>=6,WJt=Bl>=21||Bl===20&&rh>=10||Bl===18&&rh>=19,VJt=Bl>=21||Bl===20&&rh>=10||Bl===18&&rh>=20,YJt=Bl>=22;function u1e(e){if(process.env.WATCH_REPORT_DEPENDENCIES&&process.send)if(e=e.map(t=>fe.fromPortablePath(mo.resolveVirtual(fe.toPortablePath(t)))),c1e)process.send({\"watch:require\":e});else for(let t of e)process.send({\"watch:require\":t})}function TW(e,t){let r=Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK)>0,s=Number(process.env.PNP_DEBUG_LEVEL),a=/^(?![a-zA-Z]:[\\\\/]|\\\\\\\\|\\.{0,2}(?:\\/|$))((?:node:)?(?:@[^/]+\\/)?[^/]+)\\/*(.*|)$/,n=/^(\\/|\\.{1,2}(\\/|$))/,c=/\\/$/,f=/^\\.{0,2}\\//,p={name:null,reference:null},h=[],E=new Set;if(e.enableTopLevelFallback===!0&&h.push(p),t.compatibilityMode!==!1)for(let Ne of[\"react-scripts\",\"gatsby\"]){let ke=e.packageRegistry.get(Ne);if(ke)for(let be of ke.keys()){if(be===null)throw new Error(\"Assertion failed: This reference shouldn't be null\");h.push({name:Ne,reference:be})}}let{ignorePattern:C,packageRegistry:S,packageLocatorsByLocations:x}=e;function I(Ne,ke){return{fn:Ne,args:ke,error:null,result:null}}function T(Ne){let ke=process.stderr?.hasColors?.()??process.stdout.isTTY,be=(ct,Me)=>`\\x1B[${ct}m${Me}\\x1B[0m`,je=Ne.error;console.error(je?be(\"31;1\",`\\u2716 ${Ne.error?.message.replace(/\\n.*/s,\"\")}`):be(\"33;1\",\"\\u203C Resolution\")),Ne.args.length>0&&console.error();for(let ct of Ne.args)console.error(`  ${be(\"37;1\",\"In \\u2190\")} ${(0,RW.inspect)(ct,{colors:ke,compact:!0})}`);Ne.result&&(console.error(),console.error(`  ${be(\"37;1\",\"Out \\u2192\")} ${(0,RW.inspect)(Ne.result,{colors:ke,compact:!0})}`));let Re=new Error().stack.match(/(?<=^ +)at.*/gm)?.slice(2)??[];if(Re.length>0){console.error();for(let ct of Re)console.error(`  ${be(\"38;5;244\",ct)}`)}console.error()}function O(Ne,ke){if(t.allowDebug===!1)return ke;if(Number.isFinite(s)){if(s>=2)return(...be)=>{let je=I(Ne,be);try{return je.result=ke(...be)}catch(Re){throw je.error=Re}finally{T(je)}};if(s>=1)return(...be)=>{try{return ke(...be)}catch(je){let Re=I(Ne,be);throw Re.error=je,T(Re),je}}}return ke}function U(Ne){let ke=g(Ne);if(!ke)throw ys(\"INTERNAL\",\"Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)\");return ke}function Y(Ne){if(Ne.name===null)return!0;for(let ke of e.dependencyTreeRoots)if(ke.name===Ne.name&&ke.reference===Ne.reference)return!0;return!1}let te=new Set([\"node\",\"require\",...l1e(\"--conditions\")]);function ie(Ne,ke=te,be){let je=me(K.join(Ne,\"internal.js\"),{resolveIgnored:!0,includeDiscardFromLookup:!0});if(je===null)throw ys(\"INTERNAL\",`The locator that owns the \"${Ne}\" path can't be found inside the dependency tree (this is probably an internal error)`);let{packageLocation:Re}=U(je),ct=K.join(Re,Er.manifest);if(!t.fakeFs.existsSync(ct))return null;let Me=JSON.parse(t.fakeFs.readFileSync(ct,\"utf8\"));if(Me.exports==null)return null;let P=K.contains(Re,Ne);if(P===null)throw ys(\"INTERNAL\",\"unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)\");P!==\".\"&&!f.test(P)&&(P=`./${P}`);try{let w=r1e({packageJSONUrl:(0,Wm.pathToFileURL)(fe.fromPortablePath(ct)),packageSubpath:P,exports:Me.exports,base:be?(0,Wm.pathToFileURL)(fe.fromPortablePath(be)):null,conditions:ke});return fe.toPortablePath((0,Wm.fileURLToPath)(w))}catch(w){throw ys(\"EXPORTS_RESOLUTION_FAILED\",w.message,{unqualifiedPath:uf(Ne),locator:je,pkgJson:Me,subpath:uf(P),conditions:ke},w.code)}}function ue(Ne,ke,{extensions:be}){let je;try{ke.push(Ne),je=t.fakeFs.statSync(Ne)}catch{}if(je&&!je.isDirectory())return t.fakeFs.realpathSync(Ne);if(je&&je.isDirectory()){let Re;try{Re=JSON.parse(t.fakeFs.readFileSync(K.join(Ne,Er.manifest),\"utf8\"))}catch{}let ct;if(Re&&Re.main&&(ct=K.resolve(Ne,Re.main)),ct&&ct!==Ne){let Me=ue(ct,ke,{extensions:be});if(Me!==null)return Me}}for(let Re=0,ct=be.length;Re<ct;Re++){let Me=`${Ne}${be[Re]}`;if(ke.push(Me),t.fakeFs.existsSync(Me))return Me}if(je&&je.isDirectory())for(let Re=0,ct=be.length;Re<ct;Re++){let Me=K.format({dir:Ne,name:\"index\",ext:be[Re]});if(ke.push(Me),t.fakeFs.existsSync(Me))return Me}return null}function ae(Ne){let ke=new nh.Module(Ne,null);return ke.filename=Ne,ke.paths=nh.Module._nodeModulePaths(Ne),ke}function de(Ne,ke){return ke.endsWith(\"/\")&&(ke=K.join(ke,\"internal.js\")),nh.Module._resolveFilename(fe.fromPortablePath(Ne),ae(fe.fromPortablePath(ke)),!1,{plugnplay:!1})}function Ae(Ne){if(C===null)return!1;let ke=K.contains(e.basePath,Ne);return ke===null?!1:!!C.test(ke.replace(/\\/$/,\"\"))}let Ce={std:3,resolveVirtual:1,getAllLocators:1},Ee=p;function g({name:Ne,reference:ke}){let be=S.get(Ne);if(!be)return null;let je=be.get(ke);return je||null}function Se({name:Ne,reference:ke}){let be=[];for(let[je,Re]of S)if(je!==null)for(let[ct,Me]of Re)ct===null||Me.packageDependencies.get(Ne)!==ke||je===Ne&&ct===ke||be.push({name:je,reference:ct});return be}function Be(Ne,ke){let be=new Map,je=new Set,Re=Me=>{let P=JSON.stringify(Me.name);if(je.has(P))return;je.add(P);let w=Se(Me);for(let b of w)if(U(b).packagePeers.has(Ne))Re(b);else{let F=be.get(b.name);typeof F>\"u\"&&be.set(b.name,F=new Set),F.add(b.reference)}};Re(ke);let ct=[];for(let Me of[...be.keys()].sort())for(let P of[...be.get(Me)].sort())ct.push({name:Me,reference:P});return ct}function me(Ne,{resolveIgnored:ke=!1,includeDiscardFromLookup:be=!1}={}){if(Ae(Ne)&&!ke)return null;let je=K.relative(e.basePath,Ne);je.match(n)||(je=`./${je}`),je.endsWith(\"/\")||(je=`${je}/`);do{let Re=x.get(je);if(typeof Re>\"u\"||Re.discardFromLookup&&!be){je=je.substring(0,je.lastIndexOf(\"/\",je.length-2)+1);continue}return Re.locator}while(je!==\"\");return null}function ce(Ne){try{return t.fakeFs.readFileSync(fe.toPortablePath(Ne),\"utf8\")}catch(ke){if(ke.code===\"ENOENT\")return;throw ke}}function X(Ne,ke,{considerBuiltins:be=!0}={}){if(Ne.startsWith(\"#\"))throw new Error(\"resolveToUnqualified can not handle private import mappings\");if(Ne===\"pnpapi\")return fe.toPortablePath(t.pnpapiResolution);if(be&&(0,nh.isBuiltin)(Ne))return null;let je=uf(Ne),Re=ke&&uf(ke);if(ke&&Ae(ke)&&(!K.isAbsolute(Ne)||me(Ne)===null)){let P=de(Ne,ke);if(P===!1)throw ys(\"BUILTIN_NODE_RESOLUTION_FAILED\",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp)\n\nRequire request: \"${je}\"\nRequired by: ${Re}\n`,{request:je,issuer:Re});return fe.toPortablePath(P)}let ct,Me=Ne.match(a);if(Me){if(!ke)throw ys(\"API_ERROR\",\"The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute\",{request:je,issuer:Re});let[,P,w]=Me,b=me(ke);if(!b){let Fe=de(Ne,ke);if(Fe===!1)throw ys(\"BUILTIN_NODE_RESOLUTION_FAILED\",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree).\n\nRequire path: \"${je}\"\nRequired by: ${Re}\n`,{request:je,issuer:Re});return fe.toPortablePath(Fe)}let F=U(b).packageDependencies.get(P),z=null;if(F==null&&b.name!==null){let Fe=e.fallbackExclusionList.get(b.name);if(!Fe||!Fe.has(b.reference)){for(let Ct=0,qt=h.length;Ct<qt;++Ct){let Pt=U(h[Ct]).packageDependencies.get(P);if(Pt!=null){r?z=Pt:F=Pt;break}}if(e.enableTopLevelFallback&&F==null&&z===null){let Ct=e.fallbackPool.get(P);Ct!=null&&(z=Ct)}}}let Z=null;if(F===null)if(Y(b))Z=ys(\"MISSING_PEER_DEPENDENCY\",`Your application tried to access ${P} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${Re}\n`,{request:je,issuer:Re,dependencyName:P});else{let Fe=Be(P,b);Fe.every(ut=>Y(ut))?Z=ys(\"MISSING_PEER_DEPENDENCY\",`${b.name} tried to access ${P} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${b.name}@${b.reference} (via ${Re})\n${Fe.map(ut=>`Ancestor breaking the chain: ${ut.name}@${ut.reference}\n`).join(\"\")}\n`,{request:je,issuer:Re,issuerLocator:Object.assign({},b),dependencyName:P,brokenAncestors:Fe}):Z=ys(\"MISSING_PEER_DEPENDENCY\",`${b.name} tried to access ${P} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${b.name}@${b.reference} (via ${Re})\n\n${Fe.map(ut=>`Ancestor breaking the chain: ${ut.name}@${ut.reference}\n`).join(\"\")}\n`,{request:je,issuer:Re,issuerLocator:Object.assign({},b),dependencyName:P,brokenAncestors:Fe})}else F===void 0&&(!be&&(0,nh.isBuiltin)(Ne)?Y(b)?Z=ys(\"UNDECLARED_DEPENDENCY\",`Your application tried to access ${P}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${P} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${Re}\n`,{request:je,issuer:Re,dependencyName:P}):Z=ys(\"UNDECLARED_DEPENDENCY\",`${b.name} tried to access ${P}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${P} isn't otherwise declared in ${b.name}'s dependencies, this makes the require call ambiguous and unsound.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${Re}\n`,{request:je,issuer:Re,issuerLocator:Object.assign({},b),dependencyName:P}):Y(b)?Z=ys(\"UNDECLARED_DEPENDENCY\",`Your application tried to access ${P}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${Re}\n`,{request:je,issuer:Re,dependencyName:P}):Z=ys(\"UNDECLARED_DEPENDENCY\",`${b.name} tried to access ${P}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.\n\nRequired package: ${P}${P!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${b.name}@${b.reference} (via ${Re})\n`,{request:je,issuer:Re,issuerLocator:Object.assign({},b),dependencyName:P}));if(F==null){if(z===null||Z===null)throw Z||new Error(\"Assertion failed: Expected an error to have been set\");F=z;let Fe=Z.message.replace(/\\n.*/g,\"\");Z.message=Fe,!E.has(Fe)&&s!==0&&(E.add(Fe),process.emitWarning(Z))}let $=Array.isArray(F)?{name:F[0],reference:F[1]}:{name:P,reference:F},se=U($);if(!se.packageLocation)throw ys(\"MISSING_DEPENDENCY\",`A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod.\n\nRequired package: ${$.name}@${$.reference}${$.name!==je?` (via \"${je}\")`:\"\"}\nRequired by: ${b.name}@${b.reference} (via ${Re})\n`,{request:je,issuer:Re,dependencyLocator:Object.assign({},$)});let xe=se.packageLocation;w?ct=K.join(xe,w):ct=xe}else if(K.isAbsolute(Ne))ct=K.normalize(Ne);else{if(!ke)throw ys(\"API_ERROR\",\"The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute\",{request:je,issuer:Re});let P=K.resolve(ke);ke.match(c)?ct=K.normalize(K.join(P,Ne)):ct=K.normalize(K.join(K.dirname(P),Ne))}return K.normalize(ct)}function De(Ne,ke,be=te,je){if(n.test(Ne))return ke;let Re=ie(ke,be,je);return Re?K.normalize(Re):ke}function Qe(Ne,{extensions:ke=Object.keys(nh.Module._extensions)}={}){let be=[],je=ue(Ne,be,{extensions:ke});if(je)return K.normalize(je);{u1e(be.map(Me=>fe.fromPortablePath(Me)));let Re=uf(Ne),ct=me(Ne);if(ct){let{packageLocation:Me}=U(ct),P=!0;try{t.fakeFs.accessSync(Me)}catch(w){if(w?.code===\"ENOENT\")P=!1;else{let b=(w?.message??w??\"empty exception thrown\").replace(/^[A-Z]/,y=>y.toLowerCase());throw ys(\"QUALIFIED_PATH_RESOLUTION_FAILED\",`Required package exists but could not be accessed (${b}).\n\nMissing package: ${ct.name}@${ct.reference}\nExpected package location: ${uf(Me)}\n`,{unqualifiedPath:Re,extensions:ke})}}if(!P){let w=Me.includes(\"/unplugged/\")?\"Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).\":\"Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.\";throw ys(\"QUALIFIED_PATH_RESOLUTION_FAILED\",`${w}\n\nMissing package: ${ct.name}@${ct.reference}\nExpected package location: ${uf(Me)}\n`,{unqualifiedPath:Re,extensions:ke})}}throw ys(\"QUALIFIED_PATH_RESOLUTION_FAILED\",`Qualified path resolution failed: we looked for the following paths, but none could be accessed.\n\nSource path: ${Re}\n${be.map(Me=>`Not found: ${uf(Me)}\n`).join(\"\")}`,{unqualifiedPath:Re,extensions:ke})}}function it(Ne,ke,be){if(!ke)throw new Error(\"Assertion failed: An issuer is required to resolve private import mappings\");let je=n1e({name:Ne,base:(0,Wm.pathToFileURL)(fe.fromPortablePath(ke)),conditions:be.conditions??te,readFileSyncFn:ce});if(je instanceof URL)return Qe(fe.toPortablePath((0,Wm.fileURLToPath)(je)),{extensions:be.extensions});if(je.startsWith(\"#\"))throw new Error(\"Mapping from one private import to another isn't allowed\");return _(je,ke,be)}function _(Ne,ke,be={}){try{if(Ne.startsWith(\"#\"))return it(Ne,ke,be);let{considerBuiltins:je,extensions:Re,conditions:ct}=be,Me=X(Ne,ke,{considerBuiltins:je});if(Ne===\"pnpapi\")return Me;if(Me===null)return null;let P=()=>ke!==null?Ae(ke):!1,w=(!je||!(0,nh.isBuiltin)(Ne))&&!P()?De(Ne,Me,ct,ke):Me;return Qe(w,{extensions:Re})}catch(je){throw Object.hasOwn(je,\"pnpCode\")&&Object.assign(je.data,{request:uf(Ne),issuer:ke&&uf(ke)}),je}}function tt(Ne){let ke=K.normalize(Ne),be=mo.resolveVirtual(ke);return be!==ke?be:null}return{VERSIONS:Ce,topLevel:Ee,getLocator:(Ne,ke)=>Array.isArray(ke)?{name:ke[0],reference:ke[1]}:{name:Ne,reference:ke},getDependencyTreeRoots:()=>[...e.dependencyTreeRoots],getAllLocators(){let Ne=[];for(let[ke,be]of S)for(let je of be.keys())ke!==null&&je!==null&&Ne.push({name:ke,reference:je});return Ne},getPackageInformation:Ne=>{let ke=g(Ne);if(ke===null)return null;let be=fe.fromPortablePath(ke.packageLocation);return{...ke,packageLocation:be}},findPackageLocator:Ne=>me(fe.toPortablePath(Ne)),resolveToUnqualified:O(\"resolveToUnqualified\",(Ne,ke,be)=>{let je=ke!==null?fe.toPortablePath(ke):null,Re=X(fe.toPortablePath(Ne),je,be);return Re===null?null:fe.fromPortablePath(Re)}),resolveUnqualified:O(\"resolveUnqualified\",(Ne,ke)=>fe.fromPortablePath(Qe(fe.toPortablePath(Ne),ke))),resolveRequest:O(\"resolveRequest\",(Ne,ke,be)=>{let je=ke!==null?fe.toPortablePath(ke):null,Re=_(fe.toPortablePath(Ne),je,be);return Re===null?null:fe.fromPortablePath(Re)}),resolveVirtual:O(\"resolveVirtual\",Ne=>{let ke=tt(fe.toPortablePath(Ne));return ke!==null?fe.fromPortablePath(ke):null})}}Dt();var f1e=(e,t,r)=>{let s=RD(e),a=wW(s,{basePath:t}),n=fe.join(t,Er.pnpCjs);return TW(a,{fakeFs:r,pnpapiResolution:n})};var NW=et(p1e());Vt();var dA={};Yt(dA,{checkManifestCompatibility:()=>h1e,extractBuildRequest:()=>qF,getExtractHint:()=>OW,hasBindingGyp:()=>LW});qe();Dt();function h1e(e){return j.isPackageCompatible(e,Ui.getArchitectureSet())}function qF(e,t,r,{configuration:s}){let a=[];for(let n of[\"preinstall\",\"install\",\"postinstall\"])t.manifest.scripts.has(n)&&a.push({type:0,script:n});return!t.manifest.scripts.has(\"install\")&&t.misc.hasBindingGyp&&a.push({type:1,script:\"node-gyp rebuild\"}),a.length===0?null:e.linkType!==\"HARD\"?{skipped:!0,explain:n=>n.reportWarningOnce(6,`${j.prettyLocator(s,e)} lists build scripts, but is referenced through a soft link. Soft links don't support build scripts, so they'll be ignored.`)}:r&&r.built===!1?{skipped:!0,explain:n=>n.reportInfoOnce(5,`${j.prettyLocator(s,e)} lists build scripts, but its build has been explicitly disabled through configuration.`)}:!s.get(\"enableScripts\")&&!r.built?{skipped:!0,explain:n=>n.reportWarningOnce(4,`${j.prettyLocator(s,e)} lists build scripts, but all build scripts have been disabled.`)}:h1e(e)?{skipped:!1,directives:a}:{skipped:!0,explain:n=>n.reportWarningOnce(76,`${j.prettyLocator(s,e)} The ${Ui.getArchitectureName()} architecture is incompatible with this package, build skipped.`)}}var xht=new Set([\".exe\",\".bin\",\".h\",\".hh\",\".hpp\",\".c\",\".cc\",\".cpp\",\".java\",\".jar\",\".node\"]);function OW(e){return e.packageFs.getExtractHint({relevantExtensions:xht})}function LW(e){let t=K.join(e.prefixPath,\"binding.gyp\");return e.packageFs.existsSync(t)}var HD={};Yt(HD,{getUnpluggedPath:()=>_D});qe();Dt();function _D(e,{configuration:t}){return K.resolve(t.get(\"pnpUnpluggedFolder\"),j.slugifyLocator(e))}var kht=new Set([j.makeIdent(null,\"open\").identHash,j.makeIdent(null,\"opn\").identHash]),ng=class{constructor(){this.mode=\"strict\";this.pnpCache=new Map}getCustomDataKey(){return JSON.stringify({name:\"PnpLinker\",version:2})}supportsPackage(t,r){return this.isEnabled(r)}async findPackageLocation(t,r){if(!this.isEnabled(r))throw new Error(\"Assertion failed: Expected the PnP linker to be enabled\");let s=ig(r.project).cjs;if(!le.existsSync(s))throw new st(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let a=Ge.getFactoryWithDefault(this.pnpCache,s,()=>Ge.dynamicRequire(s,{cachingStrategy:Ge.CachingStrategy.FsTime})),n={name:j.stringifyIdent(t),reference:t.reference},c=a.getPackageInformation(n);if(!c)throw new st(`Couldn't find ${j.prettyLocator(r.project.configuration,t)} in the currently installed PnP map - running an install might help`);return fe.toPortablePath(c.packageLocation)}async findPackageLocator(t,r){if(!this.isEnabled(r))return null;let s=ig(r.project).cjs;if(!le.existsSync(s))return null;let n=Ge.getFactoryWithDefault(this.pnpCache,s,()=>Ge.dynamicRequire(s,{cachingStrategy:Ge.CachingStrategy.FsTime})).findPackageLocator(fe.fromPortablePath(t));return n?j.makeLocator(j.parseIdent(n.name),n.reference):null}makeInstaller(t){return new Vm(t)}isEnabled(t){return!(t.project.configuration.get(\"nodeLinker\")!==\"pnp\"||t.project.configuration.get(\"pnpMode\")!==this.mode)}},Vm=class{constructor(t){this.opts=t;this.mode=\"strict\";this.asyncActions=new Ge.AsyncActions(10);this.packageRegistry=new Map;this.virtualTemplates=new Map;this.isESMLoaderRequired=!1;this.customData={store:new Map};this.unpluggedPaths=new Set;this.opts=t}attachCustomData(t){this.customData=t}async installPackage(t,r,s){let a=j.stringifyIdent(t),n=t.reference,c=!!this.opts.project.tryWorkspaceByLocator(t),f=j.isVirtualLocator(t),p=t.peerDependencies.size>0&&!f,h=!p&&!c,E=!p&&t.linkType!==\"SOFT\",C,S;if(h||E){let te=f?j.devirtualizeLocator(t):t;C=this.customData.store.get(te.locatorHash),typeof C>\"u\"&&(C=await Qht(r),t.linkType===\"HARD\"&&this.customData.store.set(te.locatorHash,C)),C.manifest.type===\"module\"&&(this.isESMLoaderRequired=!0),S=this.opts.project.getDependencyMeta(te,t.version)}let x=h?qF(t,C,S,{configuration:this.opts.project.configuration}):null,I=E?await this.unplugPackageIfNeeded(t,C,r,S,s):r.packageFs;if(K.isAbsolute(r.prefixPath))throw new Error(`Assertion failed: Expected the prefix path (${r.prefixPath}) to be relative to the parent`);let T=K.resolve(I.getRealPath(),r.prefixPath),O=MW(this.opts.project.cwd,T),U=new Map,Y=new Set;if(f){for(let te of t.peerDependencies.values())U.set(j.stringifyIdent(te),null),Y.add(j.stringifyIdent(te));if(!c){let te=j.devirtualizeLocator(t);this.virtualTemplates.set(te.locatorHash,{location:MW(this.opts.project.cwd,mo.resolveVirtual(T)),locator:te})}}return Ge.getMapWithDefault(this.packageRegistry,a).set(n,{packageLocation:O,packageDependencies:U,packagePeers:Y,linkType:t.linkType,discardFromLookup:r.discardFromLookup||!1}),{packageLocation:T,buildRequest:x}}async attachInternalDependencies(t,r){let s=this.getPackageInformation(t);for(let[a,n]of r){let c=j.areIdentsEqual(a,n)?n.reference:[j.stringifyIdent(n),n.reference];s.packageDependencies.set(j.stringifyIdent(a),c)}}async attachExternalDependents(t,r){for(let s of r)this.getDiskInformation(s).packageDependencies.set(j.stringifyIdent(t),t.reference)}async finalizeInstall(){if(this.opts.project.configuration.get(\"pnpMode\")!==this.mode)return;let t=ig(this.opts.project);if(this.isEsmEnabled()||await le.removePromise(t.esmLoader),this.opts.project.configuration.get(\"nodeLinker\")!==\"pnp\"){await le.removePromise(t.cjs),await le.removePromise(t.data),await le.removePromise(t.esmLoader),await le.removePromise(this.opts.project.configuration.get(\"pnpUnpluggedFolder\"));return}for(let{locator:C,location:S}of this.virtualTemplates.values())Ge.getMapWithDefault(this.packageRegistry,j.stringifyIdent(C)).set(C.reference,{packageLocation:S,packageDependencies:new Map,packagePeers:new Set,linkType:\"SOFT\",discardFromLookup:!1});let r=this.opts.project.configuration.get(\"pnpFallbackMode\"),s=this.opts.project.workspaces.map(({anchoredLocator:C})=>({name:j.stringifyIdent(C),reference:C.reference})),a=r!==\"none\",n=[],c=new Map,f=Ge.buildIgnorePattern([\".yarn/sdks/**\",...this.opts.project.configuration.get(\"pnpIgnorePatterns\")]),p=this.packageRegistry,h=this.opts.project.configuration.get(\"pnpShebang\"),E=this.opts.project.configuration.get(\"pnpZipBackend\");if(r===\"dependencies-only\")for(let C of this.opts.project.storedPackages.values())this.opts.project.tryWorkspaceByLocator(C)&&n.push({name:j.stringifyIdent(C),reference:C.reference});return await this.asyncActions.wait(),await this.finalizeInstallWithPnp({dependencyTreeRoots:s,enableTopLevelFallback:a,fallbackExclusionList:n,fallbackPool:c,ignorePattern:f,pnpZipBackend:E,packageRegistry:p,shebang:h}),{customData:this.customData}}async transformPnpSettings(t){}isEsmEnabled(){if(this.opts.project.configuration.sources.has(\"pnpEnableEsmLoader\"))return this.opts.project.configuration.get(\"pnpEnableEsmLoader\");if(this.isESMLoaderRequired)return!0;for(let t of this.opts.project.workspaces)if(t.manifest.type===\"module\")return!0;return!1}async finalizeInstallWithPnp(t){let r=ig(this.opts.project),s=await this.locateNodeModules(t.ignorePattern);if(s.length>0){this.opts.report.reportWarning(31,\"One or more node_modules have been detected and will be removed. This operation may take some time.\");for(let n of s)await le.removePromise(n)}if(await this.transformPnpSettings(t),this.opts.project.configuration.get(\"pnpEnableInlining\")){let n=Hwe(t);await le.changeFilePromise(r.cjs,n,{automaticNewlines:!0,mode:493}),await le.removePromise(r.data)}else{let{dataFile:n,loaderFile:c}=jwe(t);await le.changeFilePromise(r.cjs,c,{automaticNewlines:!0,mode:493}),await le.changeFilePromise(r.data,n,{automaticNewlines:!0,mode:420})}this.isEsmEnabled()&&(this.opts.report.reportWarning(0,\"ESM support for PnP uses the experimental loader API and is therefore experimental\"),await le.changeFilePromise(r.esmLoader,(0,NW.default)(),{automaticNewlines:!0,mode:420}));let a=this.opts.project.configuration.get(\"pnpUnpluggedFolder\");if(this.unpluggedPaths.size===0)await le.removePromise(a);else for(let n of await le.readdirPromise(a)){let c=K.resolve(a,n);this.unpluggedPaths.has(c)||await le.removePromise(c)}}async locateNodeModules(t){let r=[],s=t?new RegExp(t):null;for(let a of this.opts.project.workspaces){let n=K.join(a.cwd,\"node_modules\");if(s&&s.test(K.relative(this.opts.project.cwd,a.cwd))||!le.existsSync(n))continue;let c=await le.readdirPromise(n,{withFileTypes:!0}),f=c.filter(p=>!p.isDirectory()||p.name===\".bin\"||!p.name.startsWith(\".\"));if(f.length===c.length)r.push(n);else for(let p of f)r.push(K.join(n,p.name))}return r}async unplugPackageIfNeeded(t,r,s,a,n){return this.shouldBeUnplugged(t,r,a)?this.unplugPackage(t,s,n):s.packageFs}shouldBeUnplugged(t,r,s){return typeof s.unplugged<\"u\"?s.unplugged:kht.has(t.identHash)||t.conditions!=null?!0:r.manifest.preferUnplugged!==null?r.manifest.preferUnplugged:!!(qF(t,r,s,{configuration:this.opts.project.configuration})?.skipped===!1||r.misc.extractHint)}async unplugPackage(t,r,s){let a=_D(t,{configuration:this.opts.project.configuration});return this.opts.project.disabledLocators.has(t.locatorHash)?new jf(a,{baseFs:r.packageFs,pathUtils:K}):(this.unpluggedPaths.add(a),s.holdFetchResult(this.asyncActions.set(t.locatorHash,async()=>{let n=K.join(a,r.prefixPath,\".ready\");await le.existsPromise(n)||(this.opts.project.storedBuildState.delete(t.locatorHash),await le.mkdirPromise(a,{recursive:!0}),await le.copyPromise(a,vt.dot,{baseFs:r.packageFs,overwrite:!1}),await le.writeFilePromise(n,\"\"))})),new bn(a))}getPackageInformation(t){let r=j.stringifyIdent(t),s=t.reference,a=this.packageRegistry.get(r);if(!a)throw new Error(`Assertion failed: The package information store should have been available (for ${j.prettyIdent(this.opts.project.configuration,t)})`);let n=a.get(s);if(!n)throw new Error(`Assertion failed: The package information should have been available (for ${j.prettyLocator(this.opts.project.configuration,t)})`);return n}getDiskInformation(t){let r=Ge.getMapWithDefault(this.packageRegistry,\"@@disk\"),s=MW(this.opts.project.cwd,t);return Ge.getFactoryWithDefault(r,s,()=>({packageLocation:s,packageDependencies:new Map,packagePeers:new Set,linkType:\"SOFT\",discardFromLookup:!1}))}};function MW(e,t){let r=K.relative(e,t);return r.match(/^\\.{0,2}\\//)||(r=`./${r}`),r.replace(/\\/?$/,\"/\")}async function Qht(e){let t=await Ut.tryFind(e.prefixPath,{baseFs:e.packageFs})??new Ut,r=new Set([\"preinstall\",\"install\",\"postinstall\"]);for(let s of t.scripts.keys())r.has(s)||t.scripts.delete(s);return{manifest:{scripts:t.scripts,preferUnplugged:t.preferUnplugged,type:t.type},misc:{extractHint:OW(e),hasBindingGyp:LW(e)}}}qe();qe();Vt();var g1e=et(Jo());var mw=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"-A,--all\",!1,{description:\"Unplug direct dependencies from the entire project\"});this.recursive=he.Boolean(\"-R,--recursive\",!1,{description:\"Unplug both direct and transitive dependencies\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.patterns=he.Rest()}static{this.paths=[[\"unplug\"]]}static{this.usage=at.Usage({description:\"force the unpacking of a list of packages\",details:\"\\n      This command will add the selectors matching the specified patterns to the list of packages that must be unplugged when installed.\\n\\n      A package being unplugged means that instead of being referenced directly through its archive, it will be unpacked at install time in the directory configured via `pnpUnpluggedFolder`. Note that unpacking packages this way is generally not recommended because it'll make it harder to store your packages within the repository. However, it's a good approach to quickly and safely debug some packages, and can even sometimes be required depending on the context (for example when the package contains shellscripts).\\n\\n      Running the command will set a persistent flag inside your top-level `package.json`, in the `dependenciesMeta` field. As such, to undo its effects, you'll need to revert the changes made to the manifest and run `yarn install` to apply the modification.\\n\\n      By default, only direct dependencies from the current workspace are affected. If `-A,--all` is set, direct dependencies from the entire project are affected. Using the `-R,--recursive` flag will affect transitive dependencies as well as direct ones.\\n\\n      This command accepts glob patterns inside the scope and name components (not the range). Make sure to escape the patterns to prevent your own shell from trying to expand them.\\n    \",examples:[[\"Unplug the lodash dependency from the active workspace\",\"yarn unplug lodash\"],[\"Unplug all instances of lodash referenced by any workspace\",\"yarn unplug lodash -A\"],[\"Unplug all instances of lodash referenced by the active workspace and its dependencies\",\"yarn unplug lodash -R\"],[\"Unplug all instances of lodash, anywhere\",\"yarn unplug lodash -AR\"],[\"Unplug one specific version of lodash\",\"yarn unplug lodash@1.2.3\"],[\"Unplug all packages with the `@babel` scope\",\"yarn unplug '@babel/*'\"],[\"Unplug all packages (only for testing, not recommended)\",\"yarn unplug -R '*'\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);if(r.get(\"nodeLinker\")!==\"pnp\")throw new st(\"This command can only be used if the `nodeLinker` option is set to `pnp`\");await s.restoreInstallState();let c=new Set(this.patterns),f=this.patterns.map(x=>{let I=j.parseDescriptor(x),T=I.range!==\"unknown\"?I:j.makeDescriptor(I,\"*\");if(!Fr.validRange(T.range))throw new st(`The range of the descriptor patterns must be a valid semver range (${j.prettyDescriptor(r,T)})`);return O=>{let U=j.stringifyIdent(O);return!g1e.default.isMatch(U,j.stringifyIdent(T))||O.version&&!Fr.satisfiesWithPrereleases(O.version,T.range)?!1:(c.delete(x),!0)}}),p=()=>{let x=[];for(let I of s.storedPackages.values())!s.tryWorkspaceByLocator(I)&&!j.isVirtualLocator(I)&&f.some(T=>T(I))&&x.push(I);return x},h=x=>{let I=new Set,T=[],O=(U,Y)=>{if(I.has(U.locatorHash))return;let te=!!s.tryWorkspaceByLocator(U);if(!(Y>0&&!this.recursive&&te)&&(I.add(U.locatorHash),!s.tryWorkspaceByLocator(U)&&f.some(ie=>ie(U))&&T.push(U),!(Y>0&&!this.recursive)))for(let ie of U.dependencies.values()){let ue=s.storedResolutions.get(ie.descriptorHash);if(!ue)throw new Error(\"Assertion failed: The resolution should have been registered\");let ae=s.storedPackages.get(ue);if(!ae)throw new Error(\"Assertion failed: The package should have been registered\");O(ae,Y+1)}};for(let U of x)O(U.anchoredPackage,0);return T},E,C;if(this.all&&this.recursive?(E=p(),C=\"the project\"):this.all?(E=h(s.workspaces),C=\"any workspace\"):(E=h([a]),C=\"this workspace\"),c.size>1)throw new st(`Patterns ${pe.prettyList(r,c,pe.Type.CODE)} don't match any packages referenced by ${C}`);if(c.size>0)throw new st(`Pattern ${pe.prettyList(r,c,pe.Type.CODE)} doesn't match any packages referenced by ${C}`);E=Ge.sortMap(E,x=>j.stringifyLocator(x));let S=await Ot.start({configuration:r,stdout:this.context.stdout,json:this.json},async x=>{for(let I of E){let T=I.version??\"unknown\",O=s.topLevelWorkspace.manifest.ensureDependencyMeta(j.makeDescriptor(I,T));O.unplugged=!0,x.reportInfo(0,`Will unpack ${j.prettyLocator(r,I)} to ${pe.pretty(r,_D(I,{configuration:r}),pe.Type.PATH)}`),x.reportJson({locator:j.stringifyLocator(I),version:T})}await s.topLevelWorkspace.persistManifest(),this.json||x.reportSeparator()});return S.hasErrors()?S.exitCode():await s.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};var ig=e=>({cjs:K.join(e.cwd,Er.pnpCjs),data:K.join(e.cwd,Er.pnpData),esmLoader:K.join(e.cwd,Er.pnpEsmLoader)}),m1e=e=>/\\s/.test(e)?JSON.stringify(e):e;async function Rht(e,t,r){let s=/\\s*--require\\s+\\S*\\.pnp\\.c?js\\s*/g,a=/\\s*--experimental-loader\\s+\\S*\\.pnp\\.loader\\.mjs\\s*/,n=(t.NODE_OPTIONS??\"\").replace(s,\" \").replace(a,\" \").trim();if(e.configuration.get(\"nodeLinker\")!==\"pnp\"){t.NODE_OPTIONS=n||void 0;return}let c=ig(e),f=`--require ${m1e(fe.fromPortablePath(c.cjs))}`;le.existsSync(c.esmLoader)&&(f=`${f} --experimental-loader ${(0,d1e.pathToFileURL)(fe.fromPortablePath(c.esmLoader)).href}`),le.existsSync(c.cjs)&&(t.NODE_OPTIONS=n?`${f} ${n}`:f)}async function Tht(e,t){let r=ig(e);t(r.cjs),t(r.data),t(r.esmLoader),t(e.configuration.get(\"pnpUnpluggedFolder\"))}var Fht={hooks:{populateYarnPaths:Tht,setupScriptEnvironment:Rht},configuration:{nodeLinker:{description:'The linker used for installing Node packages, one of: \"pnp\", \"pnpm\", or \"node-modules\"',type:\"STRING\",default:\"pnp\"},minizip:{description:\"Whether Yarn should use minizip to extract archives\",type:\"BOOLEAN\",default:!1},winLinkType:{description:\"Whether Yarn should use Windows Junctions or symlinks when creating links on Windows.\",type:\"STRING\",values:[\"junctions\",\"symlinks\"],default:\"junctions\"},pnpMode:{description:\"If 'strict', generates standard PnP maps. If 'loose', merges them with the n_m resolution.\",type:\"STRING\",default:\"strict\"},pnpShebang:{description:\"String to prepend to the generated PnP script\",type:\"STRING\",default:\"#!/usr/bin/env node\"},pnpIgnorePatterns:{description:\"Array of glob patterns; files matching them will use the classic resolution\",type:\"STRING\",default:[],isArray:!0},pnpZipBackend:{description:\"Whether to use the experimental js implementation for the ZipFS\",type:\"STRING\",values:[\"libzip\",\"js\"],default:\"libzip\"},pnpEnableEsmLoader:{description:\"If true, Yarn will generate an ESM loader (`.pnp.loader.mjs`). If this is not explicitly set Yarn tries to automatically detect whether ESM support is required.\",type:\"BOOLEAN\",default:!1},pnpEnableInlining:{description:\"If true, the PnP data will be inlined along with the generated loader\",type:\"BOOLEAN\",default:!0},pnpFallbackMode:{description:\"If true, the generated PnP loader will follow the top-level fallback rule\",type:\"STRING\",default:\"dependencies-only\"},pnpUnpluggedFolder:{description:\"Folder where the unplugged packages must be stored\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/unplugged\"}},linkers:[ng],commands:[mw]},Nht=Fht;var S1e=et(w1e());Vt();var VW=et(Ie(\"crypto\")),D1e=et(Ie(\"fs\")),b1e=1,Ri=\"node_modules\",WF=\".bin\",P1e=\".yarn-state.yml\",Xht=1e3,YW=(s=>(s.CLASSIC=\"classic\",s.HARDLINKS_LOCAL=\"hardlinks-local\",s.HARDLINKS_GLOBAL=\"hardlinks-global\",s))(YW||{}),jD=class{constructor(){this.installStateCache=new Map}getCustomDataKey(){return JSON.stringify({name:\"NodeModulesLinker\",version:3})}supportsPackage(t,r){return this.isEnabled(r)}async findPackageLocation(t,r){if(!this.isEnabled(r))throw new Error(\"Assertion failed: Expected the node-modules linker to be enabled\");let s=r.project.tryWorkspaceByLocator(t);if(s)return s.cwd;let a=await Ge.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await WW(r.project,{unrollAliases:!0}));if(a===null)throw new st(\"Couldn't find the node_modules state file - running an install might help (findPackageLocation)\");let n=a.locatorMap.get(j.stringifyLocator(t));if(!n){let p=new st(`Couldn't find ${j.prettyLocator(r.project.configuration,t)} in the currently installed node_modules map - running an install might help`);throw p.code=\"LOCATOR_NOT_INSTALLED\",p}let c=n.locations.sort((p,h)=>p.split(K.sep).length-h.split(K.sep).length),f=K.join(r.project.configuration.startingCwd,Ri);return c.find(p=>K.contains(f,p))||n.locations[0]}async findPackageLocator(t,r){if(!this.isEnabled(r))return null;let s=await Ge.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await WW(r.project,{unrollAliases:!0}));if(s===null)return null;let{locationRoot:a,segments:n}=VF(K.resolve(t),{skipPrefix:r.project.cwd}),c=s.locationTree.get(a);if(!c)return null;let f=c.locator;for(let p of n){if(c=c.children.get(p),!c)break;f=c.locator||f}return j.parseLocator(f)}makeInstaller(t){return new qW(t)}isEnabled(t){return t.project.configuration.get(\"nodeLinker\")===\"node-modules\"}},qW=class{constructor(t){this.opts=t;this.localStore=new Map;this.realLocatorChecksums=new Map;this.customData={store:new Map}}attachCustomData(t){this.customData=t}async installPackage(t,r){let s=K.resolve(r.packageFs.getRealPath(),r.prefixPath),a=this.customData.store.get(t.locatorHash);if(typeof a>\"u\"&&(a=await $ht(t,r),t.linkType===\"HARD\"&&this.customData.store.set(t.locatorHash,a)),!j.isPackageCompatible(t,this.opts.project.configuration.getSupportedArchitectures()))return{packageLocation:null,buildRequest:null};let n=new Map,c=new Set;n.has(j.stringifyIdent(t))||n.set(j.stringifyIdent(t),t.reference);let f=t;if(j.isVirtualLocator(t)){f=j.devirtualizeLocator(t);for(let E of t.peerDependencies.values())n.set(j.stringifyIdent(E),null),c.add(j.stringifyIdent(E))}let p={packageLocation:`${fe.fromPortablePath(s)}/`,packageDependencies:n,packagePeers:c,linkType:t.linkType,discardFromLookup:r.discardFromLookup??!1};this.localStore.set(t.locatorHash,{pkg:t,customPackageData:a,dependencyMeta:this.opts.project.getDependencyMeta(t,t.version),pnpNode:p});let h=r.checksum?r.checksum.substring(r.checksum.indexOf(\"/\")+1):null;return this.realLocatorChecksums.set(f.locatorHash,h),{packageLocation:s,buildRequest:null}}async attachInternalDependencies(t,r){let s=this.localStore.get(t.locatorHash);if(typeof s>\"u\")throw new Error(\"Assertion failed: Expected information object to have been registered\");for(let[a,n]of r){let c=j.areIdentsEqual(a,n)?n.reference:[j.stringifyIdent(n),n.reference];s.pnpNode.packageDependencies.set(j.stringifyIdent(a),c)}}async attachExternalDependents(t,r){throw new Error(\"External dependencies haven't been implemented for the node-modules linker\")}async finalizeInstall(){if(this.opts.project.configuration.get(\"nodeLinker\")!==\"node-modules\")return;let t=new mo({baseFs:new tA({maxOpenFiles:80,readOnlyArchives:!0})}),r=await WW(this.opts.project),s=this.opts.project.configuration.get(\"nmMode\");(r===null||s!==r.nmMode)&&(this.opts.project.storedBuildState.clear(),r={locatorMap:new Map,binSymlinks:new Map,locationTree:new Map,nmMode:s,mtimeMs:0});let a=new Map(this.opts.project.workspaces.map(S=>{let x=this.opts.project.configuration.get(\"nmHoistingLimits\");try{x=Ge.validateEnum(xD,S.manifest.installConfig?.hoistingLimits??x)}catch{let I=j.prettyWorkspace(this.opts.project.configuration,S);this.opts.report.reportWarning(57,`${I}: Invalid 'installConfig.hoistingLimits' value. Expected one of ${Object.values(xD).join(\", \")}, using default: \"${x}\"`)}return[S.relativeCwd,x]})),n=new Map(this.opts.project.workspaces.map(S=>{let x=this.opts.project.configuration.get(\"nmSelfReferences\");return x=S.manifest.installConfig?.selfReferences??x,[S.relativeCwd,x]})),c={VERSIONS:{std:1},topLevel:{name:null,reference:null},getLocator:(S,x)=>Array.isArray(x)?{name:x[0],reference:x[1]}:{name:S,reference:x},getDependencyTreeRoots:()=>this.opts.project.workspaces.map(S=>{let x=S.anchoredLocator;return{name:j.stringifyIdent(x),reference:x.reference}}),getPackageInformation:S=>{let x=S.reference===null?this.opts.project.topLevelWorkspace.anchoredLocator:j.makeLocator(j.parseIdent(S.name),S.reference),I=this.localStore.get(x.locatorHash);if(typeof I>\"u\")throw new Error(\"Assertion failed: Expected the package reference to have been registered\");return I.pnpNode},findPackageLocator:S=>{let x=this.opts.project.tryWorkspaceByCwd(fe.toPortablePath(S));if(x!==null){let I=x.anchoredLocator;return{name:j.stringifyIdent(I),reference:I.reference}}throw new Error(\"Assertion failed: Unimplemented\")},resolveToUnqualified:()=>{throw new Error(\"Assertion failed: Unimplemented\")},resolveUnqualified:()=>{throw new Error(\"Assertion failed: Unimplemented\")},resolveRequest:()=>{throw new Error(\"Assertion failed: Unimplemented\")},resolveVirtual:S=>fe.fromPortablePath(mo.resolveVirtual(fe.toPortablePath(S)))},{tree:f,errors:p,preserveSymlinksRequired:h}=kD(c,{pnpifyFs:!1,validateExternalSoftLinks:!0,hoistingLimitsByCwd:a,project:this.opts.project,selfReferencesByCwd:n});if(!f){for(let{messageName:S,text:x}of p)this.opts.report.reportError(S,x);return}let E=IW(f);await o0t(r,E,{baseFs:t,project:this.opts.project,report:this.opts.report,realLocatorChecksums:this.realLocatorChecksums,loadManifest:async S=>{let x=j.parseLocator(S),I=this.localStore.get(x.locatorHash);if(typeof I>\"u\")throw new Error(\"Assertion failed: Expected the slot to exist\");return I.customPackageData.manifest}});let C=[];for(let[S,x]of E.entries()){if(Q1e(S))continue;let I=j.parseLocator(S),T=this.localStore.get(I.locatorHash);if(typeof T>\"u\")throw new Error(\"Assertion failed: Expected the slot to exist\");if(this.opts.project.tryWorkspaceByLocator(T.pkg))continue;let O=dA.extractBuildRequest(T.pkg,T.customPackageData,T.dependencyMeta,{configuration:this.opts.project.configuration});O&&C.push({buildLocations:x.locations,locator:I,buildRequest:O})}return h&&this.opts.report.reportWarning(72,`The application uses portals and that's why ${pe.pretty(this.opts.project.configuration,\"--preserve-symlinks\",pe.Type.CODE)} Node option is required for launching it`),{customData:this.customData,records:C}}};async function $ht(e,t){let r=await Ut.tryFind(t.prefixPath,{baseFs:t.packageFs})??new Ut,s=new Set([\"preinstall\",\"install\",\"postinstall\"]);for(let a of r.scripts.keys())s.has(a)||r.scripts.delete(a);return{manifest:{bin:r.bin,scripts:r.scripts},misc:{hasBindingGyp:dA.hasBindingGyp(t)}}}async function e0t(e,t,r,s,{installChangedByUser:a}){let n=\"\";n+=`# Warning: This file is automatically generated. Removing it is fine, but will\n`,n+=`# cause your node_modules installation to become invalidated.\n`,n+=`\n`,n+=`__metadata:\n`,n+=`  version: ${b1e}\n`,n+=`  nmMode: ${s.value}\n`;let c=Array.from(t.keys()).sort(),f=j.stringifyLocator(e.topLevelWorkspace.anchoredLocator);for(let E of c){let C=t.get(E);n+=`\n`,n+=`${JSON.stringify(E)}:\n`,n+=`  locations:\n`;for(let S of C.locations){let x=K.contains(e.cwd,S);if(x===null)throw new Error(`Assertion failed: Expected the path to be within the project (${S})`);n+=`    - ${JSON.stringify(x)}\n`}if(C.aliases.length>0){n+=`  aliases:\n`;for(let S of C.aliases)n+=`    - ${JSON.stringify(S)}\n`}if(E===f&&r.size>0){n+=`  bin:\n`;for(let[S,x]of r){let I=K.contains(e.cwd,S);if(I===null)throw new Error(`Assertion failed: Expected the path to be within the project (${S})`);n+=`    ${JSON.stringify(I)}:\n`;for(let[T,O]of x){let U=K.relative(K.join(S,Ri),O);n+=`      ${JSON.stringify(T)}: ${JSON.stringify(U)}\n`}}}}let p=e.cwd,h=K.join(p,Ri,P1e);a&&await le.removePromise(h),await le.changeFilePromise(h,n,{automaticNewlines:!0})}async function WW(e,{unrollAliases:t=!1}={}){let r=e.cwd,s=K.join(r,Ri,P1e),a;try{a=await le.statPromise(s)}catch{}if(!a)return null;let n=cs(await le.readFilePromise(s,\"utf8\"));if(n.__metadata.version>b1e)return null;let c=n.__metadata.nmMode||\"classic\",f=new Map,p=new Map;delete n.__metadata;for(let[h,E]of Object.entries(n)){let C=E.locations.map(x=>K.join(r,x)),S=E.bin;if(S)for(let[x,I]of Object.entries(S)){let T=K.join(r,fe.toPortablePath(x)),O=Ge.getMapWithDefault(p,T);for(let[U,Y]of Object.entries(I))O.set(U,fe.toPortablePath([T,Ri,Y].join(K.sep)))}if(f.set(h,{target:vt.dot,linkType:\"HARD\",locations:C,aliases:E.aliases||[]}),t&&E.aliases)for(let x of E.aliases){let{scope:I,name:T}=j.parseLocator(h),O=j.makeLocator(j.makeIdent(I,T),x),U=j.stringifyLocator(O);f.set(U,{target:vt.dot,linkType:\"HARD\",locations:C,aliases:[]})}}return{locatorMap:f,binSymlinks:p,locationTree:x1e(f,{skipPrefix:e.cwd}),nmMode:c,mtimeMs:a.mtimeMs}}var Ew=async(e,t)=>{if(e.split(K.sep).indexOf(Ri)<0)throw new Error(`Assertion failed: trying to remove dir that doesn't contain node_modules: ${e}`);try{let r;if(!t.innerLoop&&(r=await le.lstatPromise(e),!r.isDirectory()&&!r.isSymbolicLink()||r.isSymbolicLink()&&!t.isWorkspaceDir)){await le.unlinkPromise(e);return}let s=await le.readdirPromise(e,{withFileTypes:!0});for(let n of s){let c=K.join(e,n.name);n.isDirectory()?(n.name!==Ri||t&&t.innerLoop)&&await Ew(c,{innerLoop:!0,contentsOnly:!1}):await le.unlinkPromise(c)}let a=!t.innerLoop&&t.isWorkspaceDir&&r?.isSymbolicLink();!t.contentsOnly&&!a&&await le.rmdirPromise(e)}catch(r){if(r.code!==\"ENOENT\"&&r.code!==\"ENOTEMPTY\")throw r}},B1e=4,VF=(e,{skipPrefix:t})=>{let r=K.contains(t,e);if(r===null)throw new Error(`Assertion failed: Writing attempt prevented to ${e} which is outside project root: ${t}`);let s=r.split(K.sep).filter(p=>p!==\"\"),a=s.indexOf(Ri),n=s.slice(0,a).join(K.sep),c=K.join(t,n),f=s.slice(a);return{locationRoot:c,segments:f}},x1e=(e,{skipPrefix:t})=>{let r=new Map;if(e===null)return r;let s=()=>({children:new Map,linkType:\"HARD\"});for(let[a,n]of e.entries()){if(n.linkType===\"SOFT\"&&K.contains(t,n.target)!==null){let f=Ge.getFactoryWithDefault(r,n.target,s);f.locator=a,f.linkType=n.linkType}for(let c of n.locations){let{locationRoot:f,segments:p}=VF(c,{skipPrefix:t}),h=Ge.getFactoryWithDefault(r,f,s);for(let E=0;E<p.length;++E){let C=p[E];if(C!==\".\"){let S=Ge.getFactoryWithDefault(h.children,C,s);h.children.set(C,S),h=S}E===p.length-1&&(h.locator=a,h.linkType=n.linkType)}}}return r},KW=async(e,t,r)=>{if(process.platform===\"win32\"&&r===\"junctions\"){let s;try{s=await le.lstatPromise(e)}catch{}if(!s||s.isDirectory()){await le.symlinkPromise(e,t,\"junction\");return}}await le.symlinkPromise(K.relative(K.dirname(t),e),t)};async function k1e(e,t,r){let s=K.join(e,`${VW.default.randomBytes(16).toString(\"hex\")}.tmp`);try{await le.writeFilePromise(s,r);try{await le.linkPromise(s,t)}catch{}}finally{await le.unlinkPromise(s)}}async function t0t({srcPath:e,dstPath:t,entry:r,globalHardlinksStore:s,baseFs:a,nmMode:n}){if(r.kind===\"file\"){if(n.value===\"hardlinks-global\"&&s&&r.digest){let f=K.join(s,r.digest.substring(0,2),`${r.digest.substring(2)}.dat`),p;try{let h=await le.statPromise(f);if(h&&(!r.mtimeMs||h.mtimeMs>r.mtimeMs||h.mtimeMs<r.mtimeMs-Xht))if(await Ln.checksumFile(f,{baseFs:le,algorithm:\"sha1\"})!==r.digest){let C=K.join(s,`${VW.default.randomBytes(16).toString(\"hex\")}.tmp`);await le.renamePromise(f,C);let S=await a.readFilePromise(e);await le.writeFilePromise(C,S);try{await le.linkPromise(C,f),r.mtimeMs=new Date().getTime(),await le.unlinkPromise(C)}catch{}}else r.mtimeMs||(r.mtimeMs=Math.ceil(h.mtimeMs));await le.linkPromise(f,t),p=!0}catch{p=!1}if(!p){let h=await a.readFilePromise(e);await k1e(s,f,h),r.mtimeMs=new Date().getTime();try{await le.linkPromise(f,t)}catch(E){E&&E.code&&E.code==\"EXDEV\"&&(n.value=\"hardlinks-local\",await a.copyFilePromise(e,t))}}}else await a.copyFilePromise(e,t);let c=r.mode&511;c!==420&&await le.chmodPromise(t,c)}}var r0t=async(e,t,{baseFs:r,globalHardlinksStore:s,nmMode:a,windowsLinkType:n,packageChecksum:c})=>{await le.mkdirPromise(e,{recursive:!0});let f=async(E=vt.dot)=>{let C=K.join(t,E),S=await r.readdirPromise(C,{withFileTypes:!0}),x=new Map;for(let I of S){let T=K.join(E,I.name),O,U=K.join(C,I.name);if(I.isFile()){if(O={kind:\"file\",mode:(await r.lstatPromise(U)).mode},a.value===\"hardlinks-global\"){let Y=await Ln.checksumFile(U,{baseFs:r,algorithm:\"sha1\"});O.digest=Y}}else if(I.isDirectory())O={kind:\"directory\"};else if(I.isSymbolicLink())O={kind:\"symlink\",symlinkTo:await r.readlinkPromise(U)};else throw new Error(`Unsupported file type (file: ${U}, mode: 0o${await r.statSync(U).mode.toString(8).padStart(6,\"0\")})`);if(x.set(T,O),I.isDirectory()&&T!==Ri){let Y=await f(T);for(let[te,ie]of Y)x.set(te,ie)}}return x},p;if(a.value===\"hardlinks-global\"&&s&&c){let E=K.join(s,c.substring(0,2),`${c.substring(2)}.json`);try{p=new Map(Object.entries(JSON.parse(await le.readFilePromise(E,\"utf8\"))))}catch{p=await f()}}else p=await f();let h=!1;for(let[E,C]of p){let S=K.join(t,E),x=K.join(e,E);if(C.kind===\"directory\")await le.mkdirPromise(x,{recursive:!0});else if(C.kind===\"file\"){let I=C.mtimeMs;await t0t({srcPath:S,dstPath:x,entry:C,nmMode:a,baseFs:r,globalHardlinksStore:s}),C.mtimeMs!==I&&(h=!0)}else C.kind===\"symlink\"&&await KW(K.resolve(K.dirname(x),C.symlinkTo),x,n)}if(a.value===\"hardlinks-global\"&&s&&h&&c){let E=K.join(s,c.substring(0,2),`${c.substring(2)}.json`);await le.removePromise(E),await k1e(s,E,Buffer.from(JSON.stringify(Object.fromEntries(p))))}};function n0t(e,t,r,s){let a=new Map,n=new Map,c=new Map,f=!1,p=(h,E,C,S,x)=>{let I=!0,T=K.join(h,E),O=new Set;if(E===Ri||E.startsWith(\"@\")){let Y;try{Y=le.statSync(T)}catch{}I=!!Y,Y?Y.mtimeMs>r?(f=!0,O=new Set(le.readdirSync(T))):O=new Set(C.children.get(E).children.keys()):f=!0;let te=t.get(h);if(te){let ie=K.join(h,Ri,WF),ue;try{ue=le.statSync(ie)}catch{}if(!ue)f=!0;else if(ue.mtimeMs>r){f=!0;let ae=new Set(le.readdirSync(ie)),de=new Map;n.set(h,de);for(let[Ae,Ce]of te)ae.has(Ae)&&de.set(Ae,Ce)}else n.set(h,te)}}else I=x.has(E);let U=C.children.get(E);if(I){let{linkType:Y,locator:te}=U,ie={children:new Map,linkType:Y,locator:te};if(S.children.set(E,ie),te){let ue=Ge.getSetWithDefault(c,te);ue.add(T),c.set(te,ue)}for(let ue of U.children.keys())p(T,ue,U,ie,O)}else U.locator&&s.storedBuildState.delete(j.parseLocator(U.locator).locatorHash)};for(let[h,E]of e){let{linkType:C,locator:S}=E,x={children:new Map,linkType:C,locator:S};if(a.set(h,x),S){let I=Ge.getSetWithDefault(c,E.locator);I.add(h),c.set(E.locator,I)}E.children.has(Ri)&&p(h,Ri,E,x,new Set)}return{locationTree:a,binSymlinks:n,locatorLocations:c,installChangedByUser:f}}function Q1e(e){let t=j.parseDescriptor(e);return j.isVirtualDescriptor(t)&&(t=j.devirtualizeDescriptor(t)),t.range.startsWith(\"link:\")}async function i0t(e,t,r,{loadManifest:s}){let a=new Map;for(let[f,{locations:p}]of e){let h=Q1e(f)?null:await s(f,p[0]),E=new Map;if(h)for(let[C,S]of h.bin){let x=K.join(p[0],S);S!==\"\"&&le.existsSync(x)&&E.set(C,S)}a.set(f,E)}let n=new Map,c=(f,p,h)=>{let E=new Map,C=K.contains(r,f);if(h.locator&&C!==null){let S=a.get(h.locator);for(let[x,I]of S){let T=K.join(f,fe.toPortablePath(I));E.set(x,T)}for(let[x,I]of h.children){let T=K.join(f,x),O=c(T,T,I);O.size>0&&n.set(f,new Map([...n.get(f)||new Map,...O]))}}else for(let[S,x]of h.children){let I=c(K.join(f,S),p,x);for(let[T,O]of I)E.set(T,O)}return E};for(let[f,p]of t){let h=c(f,f,p);h.size>0&&n.set(f,new Map([...n.get(f)||new Map,...h]))}return n}var v1e=(e,t)=>{if(!e||!t)return e===t;let r=j.parseLocator(e);j.isVirtualLocator(r)&&(r=j.devirtualizeLocator(r));let s=j.parseLocator(t);return j.isVirtualLocator(s)&&(s=j.devirtualizeLocator(s)),j.areLocatorsEqual(r,s)};function JW(e){return K.join(e.get(\"globalFolder\"),\"store\")}function s0t(e,t){let r=s=>{let a=s.split(K.sep),n=a.lastIndexOf(Ri);if(n<0||n==a.length-1)throw new Error(`Assertion failed. Path is outside of any node_modules package ${s}`);return a.slice(0,n+(a[n+1].startsWith(\"@\")?3:2)).join(K.sep)};for(let s of e.values())for(let[a,n]of s)t.has(r(n))&&s.delete(a)}async function o0t(e,t,{baseFs:r,project:s,report:a,loadManifest:n,realLocatorChecksums:c}){let f=K.join(s.cwd,Ri),{locationTree:p,binSymlinks:h,locatorLocations:E,installChangedByUser:C}=n0t(e.locationTree,e.binSymlinks,e.mtimeMs,s),S=x1e(t,{skipPrefix:s.cwd}),x=[],I=async({srcDir:Ce,dstDir:Ee,linkType:g,globalHardlinksStore:Se,nmMode:Be,windowsLinkType:me,packageChecksum:ce})=>{let X=(async()=>{try{g===\"SOFT\"?(await le.mkdirPromise(K.dirname(Ee),{recursive:!0}),await KW(K.resolve(Ce),Ee,me)):await r0t(Ee,Ce,{baseFs:r,globalHardlinksStore:Se,nmMode:Be,windowsLinkType:me,packageChecksum:ce})}catch(De){throw De.message=`While persisting ${Ce} -> ${Ee} ${De.message}`,De}finally{ie.tick()}})().then(()=>x.splice(x.indexOf(X),1));x.push(X),x.length>B1e&&await Promise.race(x)},T=async(Ce,Ee,g)=>{let Se=(async()=>{let Be=async(me,ce,X)=>{try{X.innerLoop||await le.mkdirPromise(ce,{recursive:!0});let De=await le.readdirPromise(me,{withFileTypes:!0});for(let Qe of De){if(!X.innerLoop&&Qe.name===WF)continue;let it=K.join(me,Qe.name),_=K.join(ce,Qe.name);Qe.isDirectory()?(Qe.name!==Ri||X&&X.innerLoop)&&(await le.mkdirPromise(_,{recursive:!0}),await Be(it,_,{...X,innerLoop:!0})):de.value===\"hardlinks-local\"||de.value===\"hardlinks-global\"?await le.linkPromise(it,_):await le.copyFilePromise(it,_,D1e.default.constants.COPYFILE_FICLONE)}}catch(De){throw X.innerLoop||(De.message=`While cloning ${me} -> ${ce} ${De.message}`),De}finally{X.innerLoop||ie.tick()}};await Be(Ce,Ee,g)})().then(()=>x.splice(x.indexOf(Se),1));x.push(Se),x.length>B1e&&await Promise.race(x)},O=async(Ce,Ee,g)=>{if(g)for(let[Se,Be]of Ee.children){let me=g.children.get(Se);await O(K.join(Ce,Se),Be,me)}else{Ee.children.has(Ri)&&await Ew(K.join(Ce,Ri),{contentsOnly:!1});let Se=K.basename(Ce)===Ri&&p.has(K.join(K.dirname(Ce)));await Ew(Ce,{contentsOnly:Ce===f,isWorkspaceDir:Se})}};for(let[Ce,Ee]of p){let g=S.get(Ce);for(let[Se,Be]of Ee.children){if(Se===\".\")continue;let me=g&&g.children.get(Se),ce=K.join(Ce,Se);await O(ce,Be,me)}}let U=async(Ce,Ee,g)=>{if(g){v1e(Ee.locator,g.locator)||await Ew(Ce,{contentsOnly:Ee.linkType===\"HARD\"});for(let[Se,Be]of Ee.children){let me=g.children.get(Se);await U(K.join(Ce,Se),Be,me)}}else{Ee.children.has(Ri)&&await Ew(K.join(Ce,Ri),{contentsOnly:!0});let Se=K.basename(Ce)===Ri&&S.has(K.join(K.dirname(Ce)));await Ew(Ce,{contentsOnly:Ee.linkType===\"HARD\",isWorkspaceDir:Se})}};for(let[Ce,Ee]of S){let g=p.get(Ce);for(let[Se,Be]of Ee.children){if(Se===\".\")continue;let me=g&&g.children.get(Se);await U(K.join(Ce,Se),Be,me)}}let Y=new Map,te=[];for(let[Ce,Ee]of E)for(let g of Ee){let{locationRoot:Se,segments:Be}=VF(g,{skipPrefix:s.cwd}),me=S.get(Se),ce=Se;if(me){for(let X of Be)if(ce=K.join(ce,X),me=me.children.get(X),!me)break;if(me){let X=v1e(me.locator,Ce),De=t.get(me.locator),Qe=De.target,it=ce,_=De.linkType;if(X)Y.has(Qe)||Y.set(Qe,it);else if(Qe!==it){let tt=j.parseLocator(me.locator);j.isVirtualLocator(tt)&&(tt=j.devirtualizeLocator(tt)),te.push({srcDir:Qe,dstDir:it,linkType:_,realLocatorHash:tt.locatorHash})}}}}for(let[Ce,{locations:Ee}]of t.entries())for(let g of Ee){let{locationRoot:Se,segments:Be}=VF(g,{skipPrefix:s.cwd}),me=p.get(Se),ce=S.get(Se),X=Se,De=t.get(Ce),Qe=j.parseLocator(Ce);j.isVirtualLocator(Qe)&&(Qe=j.devirtualizeLocator(Qe));let it=Qe.locatorHash,_=De.target,tt=g;if(_===tt)continue;let Ne=De.linkType;for(let ke of Be)ce=ce.children.get(ke);if(!me)te.push({srcDir:_,dstDir:tt,linkType:Ne,realLocatorHash:it});else for(let ke of Be)if(X=K.join(X,ke),me=me.children.get(ke),!me){te.push({srcDir:_,dstDir:tt,linkType:Ne,realLocatorHash:it});break}}let ie=yo.progressViaCounter(te.length),ue=a.reportProgress(ie),ae=s.configuration.get(\"nmMode\"),de={value:ae},Ae=s.configuration.get(\"winLinkType\");try{let Ce=de.value===\"hardlinks-global\"?`${JW(s.configuration)}/v1`:null;if(Ce&&!await le.existsPromise(Ce)){await le.mkdirpPromise(Ce);for(let g=0;g<256;g++)await le.mkdirPromise(K.join(Ce,g.toString(16).padStart(2,\"0\")))}for(let g of te)(g.linkType===\"SOFT\"||!Y.has(g.srcDir))&&(Y.set(g.srcDir,g.dstDir),await I({...g,globalHardlinksStore:Ce,nmMode:de,windowsLinkType:Ae,packageChecksum:c.get(g.realLocatorHash)||null}));await Promise.all(x),x.length=0;for(let g of te){let Se=Y.get(g.srcDir);g.linkType!==\"SOFT\"&&g.dstDir!==Se&&await T(Se,g.dstDir,{nmMode:de})}await Promise.all(x),await le.mkdirPromise(f,{recursive:!0}),s0t(h,new Set(te.map(g=>g.dstDir)));let Ee=await i0t(t,S,s.cwd,{loadManifest:n});await a0t(h,Ee,s.cwd,Ae),await e0t(s,t,Ee,de,{installChangedByUser:C}),ae==\"hardlinks-global\"&&de.value==\"hardlinks-local\"&&a.reportWarningOnce(74,\"'nmMode' has been downgraded to 'hardlinks-local' due to global cache and install folder being on different devices\")}finally{ue.stop()}}async function a0t(e,t,r,s){for(let a of e.keys()){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);if(!t.has(a)){let n=K.join(a,Ri,WF);await le.removePromise(n)}}for(let[a,n]of t){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);let c=K.join(a,Ri,WF),f=e.get(a)||new Map;await le.mkdirPromise(c,{recursive:!0});for(let p of f.keys())n.has(p)||(await le.removePromise(K.join(c,p)),process.platform===\"win32\"&&await le.removePromise(K.join(c,`${p}.cmd`)));for(let[p,h]of n){let E=f.get(p),C=K.join(c,p);E!==h&&(process.platform===\"win32\"?await(0,S1e.default)(fe.fromPortablePath(h),fe.fromPortablePath(C),{createPwshFile:!1}):(await le.removePromise(C),await KW(h,C,s),K.contains(r,await le.realpathPromise(h))!==null&&await le.chmodPromise(h,493)))}}}qe();Dt();rA();var GD=class extends ng{constructor(){super(...arguments);this.mode=\"loose\"}makeInstaller(r){return new zW(r)}},zW=class extends Vm{constructor(){super(...arguments);this.mode=\"loose\"}async transformPnpSettings(r){let s=new mo({baseFs:new tA({maxOpenFiles:80,readOnlyArchives:!0})}),a=f1e(r,this.opts.project.cwd,s),{tree:n,errors:c}=kD(a,{pnpifyFs:!1,project:this.opts.project});if(!n){for(let{messageName:C,text:S}of c)this.opts.report.reportError(C,S);return}let f=new Map;r.fallbackPool=f;let p=(C,S)=>{let x=j.parseLocator(S.locator),I=j.stringifyIdent(x);I===C?f.set(C,x.reference):f.set(C,[I,x.reference])},h=K.join(this.opts.project.cwd,Er.nodeModules),E=n.get(h);if(!(typeof E>\"u\")){if(\"target\"in E)throw new Error(\"Assertion failed: Expected the root junction point to be a directory\");for(let C of E.dirList){let S=K.join(h,C),x=n.get(S);if(typeof x>\"u\")throw new Error(\"Assertion failed: Expected the child to have been registered\");if(\"target\"in x)p(C,x);else for(let I of x.dirList){let T=K.join(S,I),O=n.get(T);if(typeof O>\"u\")throw new Error(\"Assertion failed: Expected the subchild to have been registered\");if(\"target\"in O)p(`${C}/${I}`,O);else throw new Error(\"Assertion failed: Expected the leaf junction to be a package\")}}}}};var l0t={hooks:{cleanGlobalArtifacts:async e=>{let t=JW(e);await le.removePromise(t)}},configuration:{nmHoistingLimits:{description:\"Prevents packages to be hoisted past specific levels\",type:\"STRING\",values:[\"workspaces\",\"dependencies\",\"none\"],default:\"none\"},nmMode:{description:\"Defines in which measure Yarn must use hardlinks and symlinks when generated `node_modules` directories.\",type:\"STRING\",values:[\"classic\",\"hardlinks-local\",\"hardlinks-global\"],default:\"classic\"},nmSelfReferences:{description:\"Defines whether the linker should generate self-referencing symlinks for workspaces.\",type:\"BOOLEAN\",default:!0}},linkers:[jD,GD]},c0t=l0t;var ZK={};Yt(ZK,{NpmHttpFetcher:()=>YD,NpmRemapResolver:()=>KD,NpmSemverFetcher:()=>ih,NpmSemverResolver:()=>JD,NpmTagResolver:()=>zD,default:()=>vvt,npmConfigUtils:()=>gi,npmHttpUtils:()=>en,npmPublishUtils:()=>d1});qe();var U1e=et(pi());var ei=\"npm:\";var en={};Yt(en,{AuthType:()=>O1e,customPackageError:()=>Ym,del:()=>D0t,get:()=>Km,getIdentUrl:()=>WD,getPackageMetadata:()=>Bw,handleInvalidAuthenticationError:()=>sg,post:()=>v0t,put:()=>S0t});qe();qe();Dt();var eV=et(Yv());Jl();var N1e=et(pi());var gi={};Yt(gi,{RegistryType:()=>T1e,getAuditRegistry:()=>u0t,getAuthConfiguration:()=>$W,getDefaultRegistry:()=>qD,getPublishRegistry:()=>f0t,getRegistryConfiguration:()=>F1e,getScopeConfiguration:()=>XW,getScopeRegistry:()=>Iw,isPackageApproved:()=>Cw,normalizeRegistry:()=>Vc});qe();var R1e=et(Jo()),T1e=(s=>(s.AUDIT_REGISTRY=\"npmAuditRegistry\",s.FETCH_REGISTRY=\"npmRegistryServer\",s.PUBLISH_REGISTRY=\"npmPublishRegistry\",s))(T1e||{});function Vc(e){return e.replace(/\\/$/,\"\")}function u0t({configuration:e}){return qD({configuration:e,type:\"npmAuditRegistry\"})}function f0t(e,{configuration:t}){return e.publishConfig?.registry?Vc(e.publishConfig.registry):e.name?Iw(e.name.scope,{configuration:t,type:\"npmPublishRegistry\"}):qD({configuration:t,type:\"npmPublishRegistry\"})}function Iw(e,{configuration:t,type:r=\"npmRegistryServer\"}){let s=XW(e,{configuration:t});if(s===null)return qD({configuration:t,type:r});let a=s.get(r);return a===null?qD({configuration:t,type:r}):Vc(a)}function qD({configuration:e,type:t=\"npmRegistryServer\"}){let r=e.get(t);return Vc(r!==null?r:e.get(\"npmRegistryServer\"))}function F1e(e,{configuration:t}){let r=t.get(\"npmRegistries\"),s=Vc(e),a=r.get(s);if(typeof a<\"u\")return a;let n=r.get(s.replace(/^[a-z]+:/,\"\"));return typeof n<\"u\"?n:null}var A0t=new Map([[\"npmRegistryServer\",\"https://npm.jsr.io/\"]]);function XW(e,{configuration:t}){if(e===null)return null;let s=t.get(\"npmScopes\").get(e);return s||(e===\"jsr\"?A0t:null)}function $W(e,{configuration:t,ident:r}){let s=r&&XW(r.scope,{configuration:t});return s?.get(\"npmAuthIdent\")||s?.get(\"npmAuthToken\")?s:F1e(e,{configuration:t})||t}function p0t({configuration:e,version:t,publishTimes:r}){let s=e.get(\"npmMinimalAgeGate\");if(s){let a=r?.[t];if(typeof a>\"u\"||(new Date().getTime()-new Date(a).getTime())/60/1e3<s)return!0}return!1}function h0t(e,t,r){let s=j.tryParseDescriptor(r);if(!s||s.identHash!==e.identHash&&!R1e.default.isMatch(j.stringifyIdent(e),j.stringifyIdent(s)))return!1;if(s.range===\"unknown\")return!0;let a=Fr.validRange(s.range);return!(!a||!a.test(t))}function g0t({configuration:e,ident:t,version:r}){return e.get(\"npmPreapprovedPackages\").some(s=>h0t(t,r,s))}function Cw(e){return!p0t(e)||g0t(e)}var O1e=(a=>(a[a.NO_AUTH=0]=\"NO_AUTH\",a[a.BEST_EFFORT=1]=\"BEST_EFFORT\",a[a.CONFIGURATION=2]=\"CONFIGURATION\",a[a.ALWAYS_AUTH=3]=\"ALWAYS_AUTH\",a))(O1e||{});async function sg(e,{attemptedAs:t,registry:r,headers:s,configuration:a}){if(KF(e))throw new _t(41,\"Invalid OTP token\");if(e.originalError?.name===\"HTTPError\"&&e.originalError?.response.statusCode===401)throw new _t(41,`Invalid authentication (${typeof t!=\"string\"?`as ${await P0t(r,s,{configuration:a})}`:`attempted as ${t}`})`)}function Ym(e,t){let r=e.response?.statusCode;return r?r===404?\"Package not found\":r>=500&&r<600?`The registry appears to be down (using a ${pe.applyHyperlink(t,\"local cache\",\"https://yarnpkg.com/advanced/lexicon#local-cache\")} might have protected you against such outages)`:null:null}function WD(e){return e.scope?`/@${e.scope}%2f${e.name}`:`/${e.name}`}var L1e=new Map,d0t=new Map;async function m0t(e){return await Ge.getFactoryWithDefault(L1e,e,async()=>{let t=null;try{t=await le.readJsonPromise(e)}catch{}return t})}async function y0t(e,t,{configuration:r,cached:s,registry:a,headers:n,version:c,...f}){return await Ge.getFactoryWithDefault(d0t,e,async()=>await Km(WD(t),{...f,customErrorMessage:Ym,configuration:r,registry:a,ident:t,headers:{...n,\"If-None-Match\":s?.etag,\"If-Modified-Since\":s?.lastModified},wrapNetworkRequest:async p=>async()=>{let h=await p();if(h.statusCode===304){if(s===null)throw new Error(\"Assertion failed: cachedMetadata should not be null\");return{...h,body:s.metadata}}let E=I0t(JSON.parse(h.body.toString())),C={metadata:E,etag:h.headers.etag,lastModified:h.headers[\"last-modified\"]};return L1e.set(e,Promise.resolve(C)),Promise.resolve().then(async()=>{let S=`${e}-${process.pid}.tmp`;await le.mkdirPromise(K.dirname(S),{recursive:!0}),await le.writeJsonPromise(S,C,{compact:!0}),await le.renamePromise(S,e)}).catch(()=>{}),{...h,body:E}}}))}function E0t(e){return e.scope!==null?`@${e.scope}-${e.name}-${e.scope.length}`:e.name}async function Bw(e,{cache:t,project:r,registry:s,headers:a,version:n,...c}){let{configuration:f}=r;s=VD(f,{ident:e,registry:s});let p=w0t(f,s),h=K.join(p,`${E0t(e)}.json`),E=null;if(!r.lockfileNeedsRefresh&&(E=await m0t(h),E)){if(typeof n<\"u\"&&typeof E.metadata.versions[n]<\"u\")return E.metadata;if(f.get(\"enableOfflineMode\")){let C=structuredClone(E.metadata),S=new Set;if(t){for(let I of Object.keys(C.versions)){let T=j.makeLocator(e,`npm:${I}`),O=t.getLocatorMirrorPath(T);(!O||!le.existsSync(O))&&(delete C.versions[I],S.add(I))}let x=C[\"dist-tags\"].latest;if(S.has(x)){let I=Object.keys(E.metadata.versions).sort(N1e.default.compare),T=I.indexOf(x);for(;S.has(I[T])&&T>=0;)T-=1;T>=0?C[\"dist-tags\"].latest=I[T]:delete C[\"dist-tags\"].latest}}return C}}return await y0t(h,e,{...c,configuration:f,cached:E,registry:s,headers:a,version:n})}var M1e=[\"name\",\"dist.tarball\",\"bin\",\"scripts\",\"os\",\"cpu\",\"libc\",\"dependencies\",\"dependenciesMeta\",\"optionalDependencies\",\"peerDependencies\",\"peerDependenciesMeta\",\"deprecated\"];function I0t(e){return{\"dist-tags\":e[\"dist-tags\"],versions:Object.fromEntries(Object.entries(e.versions).map(([t,r])=>[t,Yd(r,M1e)])),time:e.time}}var C0t=Ln.makeHash(\"time\",...M1e).slice(0,6);function w0t(e,t){let r=B0t(e),s=new URL(t);return K.join(r,C0t,s.hostname)}function B0t(e){return K.join(e.get(\"globalFolder\"),\"metadata/npm\")}async function Km(e,{configuration:t,headers:r,ident:s,authType:a,allowOidc:n,registry:c,...f}){c=VD(t,{ident:s,registry:c}),s&&s.scope&&typeof a>\"u\"&&(a=1);let p=await YF(c,{authType:a,allowOidc:n,configuration:t,ident:s});p&&(r={...r,authorization:p});try{return await nn.get(e.charAt(0)===\"/\"?`${c}${e}`:e,{configuration:t,headers:r,...f})}catch(h){throw await sg(h,{registry:c,configuration:t,headers:r}),h}}async function v0t(e,t,{attemptedAs:r,configuration:s,headers:a,ident:n,authType:c=3,allowOidc:f,registry:p,otp:h,...E}){p=VD(s,{ident:n,registry:p});let C=await YF(p,{authType:c,allowOidc:f,configuration:s,ident:n});C&&(a={...a,authorization:C}),h&&(a={...a,...ww(h)});try{return await nn.post(p+e,t,{configuration:s,headers:a,...E})}catch(S){if(!KF(S)||h)throw await sg(S,{attemptedAs:r,registry:p,configuration:s,headers:a}),S;h=await tV(S,{configuration:s});let x={...a,...ww(h)};try{return await nn.post(`${p}${e}`,t,{configuration:s,headers:x,...E})}catch(I){throw await sg(I,{attemptedAs:r,registry:p,configuration:s,headers:a}),I}}}async function S0t(e,t,{attemptedAs:r,configuration:s,headers:a,ident:n,authType:c=3,allowOidc:f,registry:p,otp:h,...E}){p=VD(s,{ident:n,registry:p});let C=await YF(p,{authType:c,allowOidc:f,configuration:s,ident:n});C&&(a={...a,authorization:C}),h&&(a={...a,...ww(h)});try{return await nn.put(p+e,t,{configuration:s,headers:a,...E})}catch(S){if(!KF(S))throw await sg(S,{attemptedAs:r,registry:p,configuration:s,headers:a}),S;h=await tV(S,{configuration:s});let x={...a,...ww(h)};try{return await nn.put(`${p}${e}`,t,{configuration:s,headers:x,...E})}catch(I){throw await sg(I,{attemptedAs:r,registry:p,configuration:s,headers:a}),I}}}async function D0t(e,{attemptedAs:t,configuration:r,headers:s,ident:a,authType:n=3,allowOidc:c,registry:f,otp:p,...h}){f=VD(r,{ident:a,registry:f});let E=await YF(f,{authType:n,allowOidc:c,configuration:r,ident:a});E&&(s={...s,authorization:E}),p&&(s={...s,...ww(p)});try{return await nn.del(f+e,{configuration:r,headers:s,...h})}catch(C){if(!KF(C)||p)throw await sg(C,{attemptedAs:t,registry:f,configuration:r,headers:s}),C;p=await tV(C,{configuration:r});let S={...s,...ww(p)};try{return await nn.del(`${f}${e}`,{configuration:r,headers:S,...h})}catch(x){throw await sg(x,{attemptedAs:t,registry:f,configuration:r,headers:s}),x}}}function VD(e,{ident:t,registry:r}){if(typeof r>\"u\"&&t)return Iw(t.scope,{configuration:e});if(typeof r!=\"string\")throw new Error(\"Assertion failed: The registry should be a string\");return Vc(r)}async function YF(e,{authType:t=2,allowOidc:r=!1,configuration:s,ident:a}){let n=$W(e,{configuration:s,ident:a}),c=b0t(n,t);if(!c)return null;let f=await s.reduceHook(p=>p.getNpmAuthenticationHeader,void 0,e,{configuration:s,ident:a});if(f)return f;if(n.get(\"npmAuthToken\"))return`Bearer ${n.get(\"npmAuthToken\")}`;if(n.get(\"npmAuthIdent\")){let p=n.get(\"npmAuthIdent\");return p.includes(\":\")?`Basic ${Buffer.from(p).toString(\"base64\")}`:`Basic ${p}`}if(r&&a){let p=await x0t(e,{configuration:s,ident:a});if(p)return`Bearer ${p}`}if(c&&t!==1)throw new _t(33,\"No authentication configured for request\");return null}function b0t(e,t){switch(t){case 2:return e.get(\"npmAlwaysAuth\");case 1:case 3:return!0;case 0:return!1;default:throw new Error(\"Unreachable\")}}async function P0t(e,t,{configuration:r}){if(typeof t>\"u\"||typeof t.authorization>\"u\")return\"an anonymous user\";try{return(await nn.get(new URL(`${e}/-/whoami`).href,{configuration:r,headers:t,jsonResponse:!0})).username??\"an unknown user\"}catch{return\"an unknown user\"}}async function tV(e,{configuration:t}){let r=e.originalError?.response.headers[\"npm-notice\"];if(r&&(await Ot.start({configuration:t,stdout:process.stdout,includeFooter:!1},async a=>{if(a.reportInfo(0,r.replace(/(https?:\\/\\/\\S+)/g,pe.pretty(t,\"$1\",pe.Type.URL))),!process.env.YARN_IS_TEST_ENV){let n=r.match(/open (https?:\\/\\/\\S+)/i);if(n&&Ui.openUrl){let{openNow:c}=await(0,eV.prompt)({type:\"confirm\",name:\"openNow\",message:\"Do you want to try to open this url now?\",required:!0,initial:!0,onCancel:()=>process.exit(130)});c&&(await Ui.openUrl(n[1])||(a.reportSeparator(),a.reportWarning(0,\"We failed to automatically open the url; you'll have to open it yourself in your browser of choice.\")))}}}),process.stdout.write(`\n`)),process.env.YARN_IS_TEST_ENV)return process.env.YARN_INJECT_NPM_2FA_TOKEN||\"\";let{otp:s}=await(0,eV.prompt)({type:\"password\",name:\"otp\",message:\"One-time password:\",required:!0,onCancel:()=>process.exit(130)});return process.stdout.write(`\n`),s}function KF(e){if(e.originalError?.name!==\"HTTPError\")return!1;try{return(e.originalError?.response.headers[\"www-authenticate\"].split(/,\\s*/).map(r=>r.toLowerCase())).includes(\"otp\")}catch{return!1}}function ww(e){return{\"npm-otp\":e}}async function x0t(e,{configuration:t,ident:r}){let s=null;if(process.env.GITLAB_CI)s=process.env.NPM_ID_TOKEN||null;else if(process.env.GITHUB_ACTIONS){if(!(process.env.ACTIONS_ID_TOKEN_REQUEST_URL&&process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN))return null;let a=`npm:${new URL(e).host.replace(\"registry.yarnpkg.com\",\"registry.npmjs.org\").replace(\"yarn.npmjs.org\",\"registry.npmjs.org\")}`,n=new URL(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);n.searchParams.append(\"audience\",a),s=(await nn.get(n.href,{configuration:t,jsonResponse:!0,headers:{Authorization:`Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`}})).value}if(!s)return null;try{return(await nn.post(`${e}/-/npm/v1/oidc/token/exchange/package${WD(r)}`,null,{configuration:t,jsonResponse:!0,headers:{Authorization:`Bearer ${s}`}})).token||null}catch{}return null}var YD=class{supports(t,r){if(!t.reference.startsWith(ei))return!1;let{selector:s,params:a}=j.parseRange(t.reference);return!(!U1e.default.valid(s)||a===null||typeof a.__archiveUrl!=\"string\")}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),checksum:c}}async fetchFromNetwork(t,r){let{params:s}=j.parseRange(t.reference);if(s===null||typeof s.__archiveUrl!=\"string\")throw new Error(\"Assertion failed: The archiveUrl querystring parameter should have been available\");let a=await Km(s.__archiveUrl,{customErrorMessage:Ym,configuration:r.project.configuration,ident:t});return await ds.convertToZip(a,{configuration:r.project.configuration,prefixPath:j.getIdentVendorPath(t),stripComponents:1})}};qe();var KD=class{supportsDescriptor(t,r){return!(!t.range.startsWith(ei)||!j.tryParseDescriptor(t.range.slice(ei.length),!0))}supportsLocator(t,r){return!1}shouldPersistResolution(t,r){throw new Error(\"Unreachable\")}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){let s=r.project.configuration.normalizeDependency(j.parseDescriptor(t.range.slice(ei.length),!0));return r.resolver.getResolutionDependencies(s,r)}async getCandidates(t,r,s){let a=s.project.configuration.normalizeDependency(j.parseDescriptor(t.range.slice(ei.length),!0));return await s.resolver.getCandidates(a,r,s)}async getSatisfying(t,r,s,a){let n=a.project.configuration.normalizeDependency(j.parseDescriptor(t.range.slice(ei.length),!0));return a.resolver.getSatisfying(n,r,s,a)}resolve(t,r){throw new Error(\"Unreachable\")}};qe();qe();var _1e=et(pi());var ih=class e{supports(t,r){if(!t.reference.startsWith(ei))return!1;let s=new URL(t.reference);return!(!_1e.default.valid(s.pathname)||s.searchParams.has(\"__archiveUrl\"))}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the remote registry`),loader:()=>this.fetchFromNetwork(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),checksum:c}}async fetchFromNetwork(t,r){let s;try{s=await Km(e.getLocatorUrl(t),{customErrorMessage:Ym,configuration:r.project.configuration,ident:t})}catch{s=await Km(e.getLocatorUrl(t).replace(/%2f/g,\"/\"),{customErrorMessage:Ym,configuration:r.project.configuration,ident:t})}return await ds.convertToZip(s,{configuration:r.project.configuration,prefixPath:j.getIdentVendorPath(t),stripComponents:1})}static isConventionalTarballUrl(t,r,{configuration:s}){let a=Iw(t.scope,{configuration:s}),n=e.getLocatorUrl(t);return r=r.replace(/^https?:(\\/\\/(?:[^/]+\\.)?npmjs.org(?:$|\\/))/,\"https:$1\"),a=a.replace(/^https:\\/\\/registry\\.npmjs\\.org($|\\/)/,\"https://registry.yarnpkg.com$1\"),r=r.replace(/^https:\\/\\/registry\\.npmjs\\.org($|\\/)/,\"https://registry.yarnpkg.com$1\"),r===a+n||r===a+n.replace(/%2f/g,\"/\")}static getLocatorUrl(t){let r=Fr.clean(t.reference.slice(ei.length));if(r===null)throw new _t(10,\"The npm semver resolver got selected, but the version isn't semver\");return`${WD(t)}/-/${t.name}-${r}.tgz`}};qe();qe();qe();var rV=et(pi());var JF=j.makeIdent(null,\"node-gyp\"),k0t=/\\b(node-gyp|prebuild-install)\\b/,JD=class{supportsDescriptor(t,r){return t.range.startsWith(ei)?!!Fr.validRange(t.range.slice(ei.length)):!1}supportsLocator(t,r){if(!t.reference.startsWith(ei))return!1;let{selector:s}=j.parseRange(t.reference);return!!rV.default.valid(s)}shouldPersistResolution(t,r){return!0}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){let a=Fr.validRange(t.range.slice(ei.length));if(a===null)throw new Error(`Expected a valid range, got ${t.range.slice(ei.length)}`);let n=await Bw(t,{cache:s.fetchOptions?.cache,project:s.project,version:rV.default.valid(a.raw)?a.raw:void 0}),c=Ge.mapAndFilter(Object.keys(n.versions),E=>{try{let C=new Fr.SemVer(E);if(a.test(C))return C}catch{}return Ge.mapAndFilter.skip}),f=c.filter(E=>Cw({configuration:s.project.configuration,ident:t,version:E.raw,publishTimes:n.time}));if(c.length>0&&f.length===0)throw new _t(16,`All versions satisfying \"${t.range.slice(ei.length)}\" are quarantined`);let p=f.filter(E=>!n.versions[E.raw].deprecated),h=p.length>0?p:f;return h.sort((E,C)=>-E.compare(C)),h.map(E=>{let C=j.makeLocator(t,`${ei}${E.raw}`),S=n.versions[E.raw].dist.tarball;return ih.isConventionalTarballUrl(C,S,{configuration:s.project.configuration})?C:j.bindLocator(C,{__archiveUrl:S})})}async getSatisfying(t,r,s,a){let n=Fr.validRange(t.range.slice(ei.length));if(n===null)throw new Error(`Expected a valid range, got ${t.range.slice(ei.length)}`);return{locators:Ge.mapAndFilter(s,p=>{if(p.identHash!==t.identHash)return Ge.mapAndFilter.skip;let h=j.tryParseRange(p.reference,{requireProtocol:ei});if(!h)return Ge.mapAndFilter.skip;let E=new Fr.SemVer(h.selector);return n.test(E)?{locator:p,version:E}:Ge.mapAndFilter.skip}).sort((p,h)=>-p.version.compare(h.version)).map(({locator:p})=>p),sorted:!0}}async resolve(t,r){let{selector:s}=j.parseRange(t.reference),a=Fr.clean(s);if(a===null)throw new _t(10,\"The npm semver resolver got selected, but the version isn't semver\");let n=await Bw(t,{cache:r.fetchOptions?.cache,project:r.project,version:a});if(!Object.hasOwn(n,\"versions\"))throw new _t(15,'Registry returned invalid data for - missing \"versions\" field');if(!Object.hasOwn(n.versions,a))throw new _t(16,`Registry failed to return reference \"${a}\"`);let c=new Ut;if(c.load(n.versions[a]),!c.dependencies.has(JF.identHash)&&!c.peerDependencies.has(JF.identHash)){for(let f of c.scripts.values())if(f.match(k0t)){c.dependencies.set(JF.identHash,j.makeDescriptor(JF,\"latest\"));break}}return{...t,version:a,languageName:\"node\",linkType:\"HARD\",conditions:c.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(c.dependencies),peerDependencies:c.peerDependencies,dependenciesMeta:c.dependenciesMeta,peerDependenciesMeta:c.peerDependenciesMeta,bin:c.bin}}};qe();qe();var zF=et(pi());var zD=class{supportsDescriptor(t,r){return!(!t.range.startsWith(ei)||!Up.test(t.range.slice(ei.length)))}supportsLocator(t,r){return!1}shouldPersistResolution(t,r){throw new Error(\"Unreachable\")}bindDescriptor(t,r,s){return t}getResolutionDependencies(t,r){return{}}async getCandidates(t,r,s){let a=t.range.slice(ei.length),n=await Bw(t,{cache:s.fetchOptions?.cache,project:s.project});if(!Object.hasOwn(n,\"dist-tags\"))throw new _t(15,'Registry returned invalid data - missing \"dist-tags\" field');let c=n[\"dist-tags\"];if(!Object.hasOwn(c,a))throw new _t(16,`Registry failed to return tag \"${a}\"`);let f=Object.keys(n.versions),p=n.time,h=c[a];if(a===\"latest\"&&!Cw({configuration:s.project.configuration,ident:t,version:h,publishTimes:p})){let S=h.includes(\"-\"),x=zF.default.rsort(f).find(I=>zF.default.lt(I,h)&&(S||!I.includes(\"-\"))&&Cw({configuration:s.project.configuration,ident:t,version:I,publishTimes:p}));if(!x)throw new _t(16,`The version for tag \"${a}\" is quarantined, and no lower version is available`);h=x}let E=j.makeLocator(t,`${ei}${h}`),C=n.versions[h].dist.tarball;return ih.isConventionalTarballUrl(E,C,{configuration:s.project.configuration})?[E]:[j.bindLocator(E,{__archiveUrl:C})]}async getSatisfying(t,r,s,a){let n=[];for(let c of s){if(c.identHash!==t.identHash)continue;let f=j.tryParseRange(c.reference,{requireProtocol:ei});if(!(!f||!zF.default.valid(f.selector))){if(f.params?.__archiveUrl){let p=j.makeRange({protocol:ei,selector:f.selector,source:null,params:null}),[h]=await a.resolver.getCandidates(j.makeDescriptor(t,p),r,a);if(c.reference!==h.reference)continue}n.push(c)}}return{locators:n,sorted:!1}}async resolve(t,r){throw new Error(\"Unreachable\")}};var d1={};Yt(d1,{getGitHead:()=>Cvt,getPublishAccess:()=>kbe,getReadmeContent:()=>Qbe,makePublishBody:()=>Ivt});qe();qe();Dt();var qV={};Yt(qV,{PackCommand:()=>Fw,default:()=>cmt,packUtils:()=>EA});qe();qe();qe();Dt();Vt();var EA={};Yt(EA,{genPackList:()=>EN,genPackStream:()=>GV,genPackageManifest:()=>m2e,hasPackScripts:()=>HV,prepareForPack:()=>jV});qe();Dt();var _V=et(Jo()),g2e=et(f2e()),d2e=Ie(\"zlib\"),Xdt=[\"/package.json\",\"/readme\",\"/readme.*\",\"/license\",\"/license.*\",\"/licence\",\"/licence.*\",\"/changelog\",\"/changelog.*\"],$dt=[\"/package.tgz\",\".github\",\".git\",\".hg\",\"node_modules\",\".npmignore\",\".gitignore\",\".#*\",\".DS_Store\"];async function HV(e){return!!(Cn.hasWorkspaceScript(e,\"prepack\")||Cn.hasWorkspaceScript(e,\"postpack\"))}async function jV(e,{report:t},r){await Cn.maybeExecuteWorkspaceLifecycleScript(e,\"prepack\",{report:t});try{let s=K.join(e.cwd,Ut.fileName);await le.existsPromise(s)&&await e.manifest.loadFile(s,{baseFs:le}),await r()}finally{await Cn.maybeExecuteWorkspaceLifecycleScript(e,\"postpack\",{report:t})}}async function GV(e,t){typeof t>\"u\"&&(t=await EN(e));let r=new Set;for(let n of e.manifest.publishConfig?.executableFiles??new Set)r.add(K.normalize(n));for(let n of e.manifest.bin.values())r.add(K.normalize(n));let s=g2e.default.pack();process.nextTick(async()=>{for(let n of t){let c=K.normalize(n),f=K.resolve(e.cwd,c),p=K.join(\"package\",c),h=await le.lstatPromise(f),E={name:p,mtime:new Date(Ai.SAFE_TIME*1e3)},C=r.has(c)?493:420,S,x,I=new Promise((O,U)=>{S=O,x=U}),T=O=>{O?x(O):S()};if(h.isFile()){let O;c===\"package.json\"?O=Buffer.from(JSON.stringify(await m2e(e),null,2)):O=await le.readFilePromise(f),s.entry({...E,mode:C,type:\"file\"},O,T)}else h.isSymbolicLink()?s.entry({...E,mode:C,type:\"symlink\",linkname:await le.readlinkPromise(f)},T):T(new Error(`Unsupported file type ${h.mode} for ${fe.fromPortablePath(c)}`));await I}s.finalize()});let a=(0,d2e.createGzip)();return s.pipe(a),a}async function m2e(e){let t=JSON.parse(JSON.stringify(e.manifest.raw));return await e.project.configuration.triggerHook(r=>r.beforeWorkspacePacking,e,t),t}async function EN(e){let t=e.project,r=t.configuration,s={accept:[],reject:[]};for(let C of $dt)s.reject.push(C);for(let C of Xdt)s.accept.push(C);s.reject.push(r.get(\"rcFilename\"));let a=C=>{if(C===null||!C.startsWith(`${e.cwd}/`))return;let S=K.relative(e.cwd,C),x=K.resolve(vt.root,S);s.reject.push(x)};a(K.resolve(t.cwd,Er.lockfile)),a(r.get(\"cacheFolder\")),a(r.get(\"globalFolder\")),a(r.get(\"installStatePath\")),a(r.get(\"virtualFolder\")),a(r.get(\"yarnPath\")),await r.triggerHook(C=>C.populateYarnPaths,t,C=>{a(C)});for(let C of t.workspaces){let S=K.relative(e.cwd,C.cwd);S!==\"\"&&!S.match(/^(\\.\\.)?\\//)&&s.reject.push(`/${S}`)}let n={accept:[],reject:[]},c=e.manifest.publishConfig?.main??e.manifest.main,f=e.manifest.publishConfig?.module??e.manifest.module,p=e.manifest.publishConfig?.browser??e.manifest.browser,h=e.manifest.publishConfig?.bin??e.manifest.bin;c!=null&&n.accept.push(K.resolve(vt.root,c)),f!=null&&n.accept.push(K.resolve(vt.root,f)),typeof p==\"string\"&&n.accept.push(K.resolve(vt.root,p));for(let C of h.values())n.accept.push(K.resolve(vt.root,C));if(p instanceof Map)for(let[C,S]of p.entries())n.accept.push(K.resolve(vt.root,C)),typeof S==\"string\"&&n.accept.push(K.resolve(vt.root,S));let E=e.manifest.files!==null;if(E){n.reject.push(\"/*\");for(let C of e.manifest.files)y2e(n.accept,C,{cwd:vt.root})}return await emt(e.cwd,{hasExplicitFileList:E,globalList:s,ignoreList:n})}async function emt(e,{hasExplicitFileList:t,globalList:r,ignoreList:s}){let a=[],n=new Gf(e),c=[[vt.root,[s]]];for(;c.length>0;){let[f,p]=c.pop(),h=await n.lstatPromise(f);if(!p2e(f,{globalList:r,ignoreLists:h.isDirectory()?null:p}))if(h.isDirectory()){let E=await n.readdirPromise(f),C=!1,S=!1;if(!t||f!==vt.root)for(let T of E)C=C||T===\".gitignore\",S=S||T===\".npmignore\";let x=S?await A2e(n,f,\".npmignore\"):C?await A2e(n,f,\".gitignore\"):null,I=x!==null?[x].concat(p):p;p2e(f,{globalList:r,ignoreLists:p})&&(I=[...p,{accept:[],reject:[\"**/*\"]}]);for(let T of E)c.push([K.resolve(f,T),I])}else(h.isFile()||h.isSymbolicLink())&&a.push(K.relative(vt.root,f))}return a.sort()}async function A2e(e,t,r){let s={accept:[],reject:[]},a=await e.readFilePromise(K.join(t,r),\"utf8\");for(let n of a.split(/\\n/g))y2e(s.reject,n,{cwd:t});return s}function tmt(e,{cwd:t}){let r=e[0]===\"!\";return r&&(e=e.slice(1)),e.match(/\\.{0,1}\\//)&&(e=K.resolve(t,e)),r&&(e=`!${e}`),e}function y2e(e,t,{cwd:r}){let s=t.trim();s===\"\"||s[0]===\"#\"||e.push(tmt(s,{cwd:r}))}function p2e(e,{globalList:t,ignoreLists:r}){let s=yN(e,t.accept);if(s!==0)return s===2;let a=yN(e,t.reject);if(a!==0)return a===1;if(r!==null)for(let n of r){let c=yN(e,n.accept);if(c!==0)return c===2;let f=yN(e,n.reject);if(f!==0)return f===1}return!1}function yN(e,t){let r=t,s=[];for(let a=0;a<t.length;++a)t[a][0]!==\"!\"?r!==t&&r.push(t[a]):(r===t&&(r=t.slice(0,a)),s.push(t[a].slice(1)));return h2e(e,s)?2:h2e(e,r)?1:0}function h2e(e,t){let r=t,s=[];for(let a=0;a<t.length;++a)t[a].includes(\"/\")?r!==t&&r.push(t[a]):(r===t&&(r=t.slice(0,a)),s.push(t[a]));return!!(_V.default.isMatch(e,r,{dot:!0,nocase:!0})||_V.default.isMatch(e,s,{dot:!0,basename:!0,nocase:!0}))}var Fw=class extends At{constructor(){super(...arguments);this.installIfNeeded=he.Boolean(\"--install-if-needed\",!1,{description:\"Run a preliminary `yarn install` if the package contains build scripts\"});this.dryRun=he.Boolean(\"-n,--dry-run\",!1,{description:\"Print the file paths without actually generating the package archive\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.out=he.String(\"-o,--out\",{description:\"Create the archive at the specified path\"});this.filename=he.String(\"--filename\",{hidden:!0})}static{this.paths=[[\"pack\"]]}static{this.usage=at.Usage({description:\"generate a tarball from the active workspace\",details:\"\\n      This command will turn the active workspace into a compressed archive suitable for publishing. The archive will by default be stored at the root of the workspace (`package.tgz`).\\n\\n      If the `-o,--out` is set the archive will be created at the specified path. The `%s` and `%v` variables can be used within the path and will be respectively replaced by the package name and version.\\n    \",examples:[[\"Create an archive from the active workspace\",\"yarn pack\"],[\"List the files that would be made part of the workspace's archive\",\"yarn pack --dry-run\"],[\"Name and output the archive in a dedicated folder\",\"yarn pack --out /artifacts/%s-%v.tgz\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);await HV(a)&&(this.installIfNeeded?await s.install({cache:await Jr.find(r),report:new ki}):await s.restoreInstallState());let n=this.out??this.filename,c=typeof n<\"u\"?K.resolve(this.context.cwd,rmt(n,{workspace:a})):K.resolve(a.cwd,\"package.tgz\");return(await Ot.start({configuration:r,stdout:this.context.stdout,json:this.json},async p=>{await jV(a,{report:p},async()=>{p.reportJson({base:fe.fromPortablePath(a.cwd)});let h=await EN(a);for(let E of h)p.reportInfo(null,fe.fromPortablePath(E)),p.reportJson({location:fe.fromPortablePath(E)});if(!this.dryRun){let E=await GV(a,h);await le.mkdirPromise(K.dirname(c),{recursive:!0});let C=le.createWriteStream(c);E.pipe(C),await new Promise(S=>{C.on(\"finish\",S)})}}),this.dryRun||(p.reportInfo(0,`Package archive generated in ${pe.pretty(r,c,pe.Type.PATH)}`),p.reportJson({output:fe.fromPortablePath(c)}))})).exitCode()}};function rmt(e,{workspace:t}){let r=e.replace(\"%s\",nmt(t)).replace(\"%v\",imt(t));return fe.toPortablePath(r)}function nmt(e){return e.manifest.name!==null?j.slugifyIdent(e.manifest.name):\"package\"}function imt(e){return e.manifest.version!==null?e.manifest.version:\"unknown\"}var smt=[\"dependencies\",\"devDependencies\",\"peerDependencies\"],omt=\"workspace:\",amt=(e,t)=>{t.publishConfig&&(t.publishConfig.type&&(t.type=t.publishConfig.type),t.publishConfig.main&&(t.main=t.publishConfig.main),t.publishConfig.browser&&(t.browser=t.publishConfig.browser),t.publishConfig.module&&(t.module=t.publishConfig.module),t.publishConfig.exports&&(t.exports=t.publishConfig.exports),t.publishConfig.imports&&(t.imports=t.publishConfig.imports),t.publishConfig.bin&&(t.bin=t.publishConfig.bin));let r=e.project;for(let s of smt)for(let a of e.manifest.getForScope(s).values()){let n=r.tryWorkspaceByDescriptor(a),c=j.parseRange(a.range);if(c.protocol===omt)if(n===null){if(r.tryWorkspaceByIdent(a)===null)throw new _t(21,`${j.prettyDescriptor(r.configuration,a)}: No local workspace found for this range`)}else{let f;j.areDescriptorsEqual(a,n.anchoredDescriptor)||c.selector===\"*\"?f=n.manifest.version??\"0.0.0\":c.selector===\"~\"||c.selector===\"^\"?f=`${c.selector}${n.manifest.version??\"0.0.0\"}`:f=c.selector;let p=s===\"dependencies\"?j.makeDescriptor(a,\"unknown\"):null,h=p!==null&&e.manifest.ensureDependencyMeta(p).optional?\"optionalDependencies\":s;t[h][j.stringifyIdent(a)]=f}}},lmt={hooks:{beforeWorkspacePacking:amt},commands:[Fw]},cmt=lmt;var xbe=et(b2e());qe();var bbe=et(Dbe()),{env:Bt}=process,fvt=\"application/vnd.in-toto+json\",Avt=\"https://in-toto.io/Statement/v0.1\",pvt=\"https://in-toto.io/Statement/v1\",hvt=\"https://slsa.dev/provenance/v0.2\",gvt=\"https://slsa.dev/provenance/v1\",dvt=\"https://github.com/actions/runner\",mvt=\"https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1\",yvt=\"https://github.com/npm/cli/gitlab\",Evt=\"v0alpha1\",Pbe=async(e,t)=>{let r;if(Bt.GITHUB_ACTIONS){if(!Bt.ACTIONS_ID_TOKEN_REQUEST_URL)throw new _t(91,'Provenance generation in GitHub Actions requires \"write\" access to the \"id-token\" permission');let s=(Bt.GITHUB_WORKFLOW_REF||\"\").replace(`${Bt.GITHUB_REPOSITORY}/`,\"\"),a=s.indexOf(\"@\"),n=s.slice(0,a),c=s.slice(a+1);r={_type:pvt,subject:e,predicateType:gvt,predicate:{buildDefinition:{buildType:mvt,externalParameters:{workflow:{ref:c,repository:`${Bt.GITHUB_SERVER_URL}/${Bt.GITHUB_REPOSITORY}`,path:n}},internalParameters:{github:{event_name:Bt.GITHUB_EVENT_NAME,repository_id:Bt.GITHUB_REPOSITORY_ID,repository_owner_id:Bt.GITHUB_REPOSITORY_OWNER_ID}},resolvedDependencies:[{uri:`git+${Bt.GITHUB_SERVER_URL}/${Bt.GITHUB_REPOSITORY}@${Bt.GITHUB_REF}`,digest:{gitCommit:Bt.GITHUB_SHA}}]},runDetails:{builder:{id:`${dvt}/${Bt.RUNNER_ENVIRONMENT}`},metadata:{invocationId:`${Bt.GITHUB_SERVER_URL}/${Bt.GITHUB_REPOSITORY}/actions/runs/${Bt.GITHUB_RUN_ID}/attempts/${Bt.GITHUB_RUN_ATTEMPT}`}}}}}else if(Bt.GITLAB_CI){if(!Bt.SIGSTORE_ID_TOKEN)throw new _t(91,`Provenance generation in GitLab CI requires \"SIGSTORE_ID_TOKEN\" with \"sigstore\" audience to be present in \"id_tokens\". For more info see:\nhttps://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html`);r={_type:Avt,subject:e,predicateType:hvt,predicate:{buildType:`${yvt}/${Evt}`,builder:{id:`${Bt.CI_PROJECT_URL}/-/runners/${Bt.CI_RUNNER_ID}`},invocation:{configSource:{uri:`git+${Bt.CI_PROJECT_URL}`,digest:{sha1:Bt.CI_COMMIT_SHA},entryPoint:Bt.CI_JOB_NAME},parameters:{CI:Bt.CI,CI_API_GRAPHQL_URL:Bt.CI_API_GRAPHQL_URL,CI_API_V4_URL:Bt.CI_API_V4_URL,CI_BUILD_BEFORE_SHA:Bt.CI_BUILD_BEFORE_SHA,CI_BUILD_ID:Bt.CI_BUILD_ID,CI_BUILD_NAME:Bt.CI_BUILD_NAME,CI_BUILD_REF:Bt.CI_BUILD_REF,CI_BUILD_REF_NAME:Bt.CI_BUILD_REF_NAME,CI_BUILD_REF_SLUG:Bt.CI_BUILD_REF_SLUG,CI_BUILD_STAGE:Bt.CI_BUILD_STAGE,CI_COMMIT_BEFORE_SHA:Bt.CI_COMMIT_BEFORE_SHA,CI_COMMIT_BRANCH:Bt.CI_COMMIT_BRANCH,CI_COMMIT_REF_NAME:Bt.CI_COMMIT_REF_NAME,CI_COMMIT_REF_PROTECTED:Bt.CI_COMMIT_REF_PROTECTED,CI_COMMIT_REF_SLUG:Bt.CI_COMMIT_REF_SLUG,CI_COMMIT_SHA:Bt.CI_COMMIT_SHA,CI_COMMIT_SHORT_SHA:Bt.CI_COMMIT_SHORT_SHA,CI_COMMIT_TIMESTAMP:Bt.CI_COMMIT_TIMESTAMP,CI_COMMIT_TITLE:Bt.CI_COMMIT_TITLE,CI_CONFIG_PATH:Bt.CI_CONFIG_PATH,CI_DEFAULT_BRANCH:Bt.CI_DEFAULT_BRANCH,CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX:Bt.CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX,CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX:Bt.CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX,CI_DEPENDENCY_PROXY_SERVER:Bt.CI_DEPENDENCY_PROXY_SERVER,CI_DEPENDENCY_PROXY_USER:Bt.CI_DEPENDENCY_PROXY_USER,CI_JOB_ID:Bt.CI_JOB_ID,CI_JOB_NAME:Bt.CI_JOB_NAME,CI_JOB_NAME_SLUG:Bt.CI_JOB_NAME_SLUG,CI_JOB_STAGE:Bt.CI_JOB_STAGE,CI_JOB_STARTED_AT:Bt.CI_JOB_STARTED_AT,CI_JOB_URL:Bt.CI_JOB_URL,CI_NODE_TOTAL:Bt.CI_NODE_TOTAL,CI_PAGES_DOMAIN:Bt.CI_PAGES_DOMAIN,CI_PAGES_URL:Bt.CI_PAGES_URL,CI_PIPELINE_CREATED_AT:Bt.CI_PIPELINE_CREATED_AT,CI_PIPELINE_ID:Bt.CI_PIPELINE_ID,CI_PIPELINE_IID:Bt.CI_PIPELINE_IID,CI_PIPELINE_SOURCE:Bt.CI_PIPELINE_SOURCE,CI_PIPELINE_URL:Bt.CI_PIPELINE_URL,CI_PROJECT_CLASSIFICATION_LABEL:Bt.CI_PROJECT_CLASSIFICATION_LABEL,CI_PROJECT_DESCRIPTION:Bt.CI_PROJECT_DESCRIPTION,CI_PROJECT_ID:Bt.CI_PROJECT_ID,CI_PROJECT_NAME:Bt.CI_PROJECT_NAME,CI_PROJECT_NAMESPACE:Bt.CI_PROJECT_NAMESPACE,CI_PROJECT_NAMESPACE_ID:Bt.CI_PROJECT_NAMESPACE_ID,CI_PROJECT_PATH:Bt.CI_PROJECT_PATH,CI_PROJECT_PATH_SLUG:Bt.CI_PROJECT_PATH_SLUG,CI_PROJECT_REPOSITORY_LANGUAGES:Bt.CI_PROJECT_REPOSITORY_LANGUAGES,CI_PROJECT_ROOT_NAMESPACE:Bt.CI_PROJECT_ROOT_NAMESPACE,CI_PROJECT_TITLE:Bt.CI_PROJECT_TITLE,CI_PROJECT_URL:Bt.CI_PROJECT_URL,CI_PROJECT_VISIBILITY:Bt.CI_PROJECT_VISIBILITY,CI_REGISTRY:Bt.CI_REGISTRY,CI_REGISTRY_IMAGE:Bt.CI_REGISTRY_IMAGE,CI_REGISTRY_USER:Bt.CI_REGISTRY_USER,CI_RUNNER_DESCRIPTION:Bt.CI_RUNNER_DESCRIPTION,CI_RUNNER_ID:Bt.CI_RUNNER_ID,CI_RUNNER_TAGS:Bt.CI_RUNNER_TAGS,CI_SERVER_HOST:Bt.CI_SERVER_HOST,CI_SERVER_NAME:Bt.CI_SERVER_NAME,CI_SERVER_PORT:Bt.CI_SERVER_PORT,CI_SERVER_PROTOCOL:Bt.CI_SERVER_PROTOCOL,CI_SERVER_REVISION:Bt.CI_SERVER_REVISION,CI_SERVER_SHELL_SSH_HOST:Bt.CI_SERVER_SHELL_SSH_HOST,CI_SERVER_SHELL_SSH_PORT:Bt.CI_SERVER_SHELL_SSH_PORT,CI_SERVER_URL:Bt.CI_SERVER_URL,CI_SERVER_VERSION:Bt.CI_SERVER_VERSION,CI_SERVER_VERSION_MAJOR:Bt.CI_SERVER_VERSION_MAJOR,CI_SERVER_VERSION_MINOR:Bt.CI_SERVER_VERSION_MINOR,CI_SERVER_VERSION_PATCH:Bt.CI_SERVER_VERSION_PATCH,CI_TEMPLATE_REGISTRY_HOST:Bt.CI_TEMPLATE_REGISTRY_HOST,GITLAB_CI:Bt.GITLAB_CI,GITLAB_FEATURES:Bt.GITLAB_FEATURES,GITLAB_USER_ID:Bt.GITLAB_USER_ID,GITLAB_USER_LOGIN:Bt.GITLAB_USER_LOGIN,RUNNER_GENERATE_ARTIFACTS_METADATA:Bt.RUNNER_GENERATE_ARTIFACTS_METADATA},environment:{name:Bt.CI_RUNNER_DESCRIPTION,architecture:Bt.CI_RUNNER_EXECUTABLE_ARCH,server:Bt.CI_SERVER_URL,project:Bt.CI_PROJECT_PATH,job:{id:Bt.CI_JOB_ID},pipeline:{id:Bt.CI_PIPELINE_ID,ref:Bt.CI_CONFIG_PATH}}},metadata:{buildInvocationId:`${Bt.CI_JOB_URL}`,completeness:{parameters:!0,environment:!0,materials:!1},reproducible:!1},materials:[{uri:`git+${Bt.CI_PROJECT_URL}`,digest:{sha1:Bt.CI_COMMIT_SHA}}]}}}else throw new _t(91,\"Provenance generation is only supported in GitHub Actions and GitLab CI\");return bbe.attest(Buffer.from(JSON.stringify(r)),fvt,t)};async function Ivt(e,t,{access:r,tag:s,registry:a,gitHead:n,provenance:c}){let f=e.manifest.name,p=e.manifest.version,h=j.stringifyIdent(f),E=xbe.default.fromData(t,{algorithms:[\"sha1\",\"sha512\"]}),C=r??kbe(e,f),S=await Qbe(e),x=await EA.genPackageManifest(e),I=`${h}-${p}.tgz`,T=new URL(`${Vc(a)}/${h}/-/${I}`),O={[I]:{content_type:\"application/octet-stream\",data:t.toString(\"base64\"),length:t.length}};if(c){let U={name:`pkg:npm/${h.replace(/^@/,\"%40\")}@${p}`,digest:{sha512:E.sha512[0].hexDigest()}},Y=await Pbe([U]),te=JSON.stringify(Y);O[`${h}-${p}.sigstore`]={content_type:Y.mediaType,data:te,length:te.length}}return{_id:h,_attachments:O,name:h,access:C,\"dist-tags\":{[s]:p},versions:{[p]:{...x,_id:`${h}@${p}`,name:h,version:p,gitHead:n,dist:{shasum:E.sha1[0].hexDigest(),integrity:E.sha512[0].toString(),tarball:T.toString()}}},readme:S}}async function Cvt(e){try{let{stdout:t}=await qr.execvp(\"git\",[\"rev-parse\",\"--revs-only\",\"HEAD\"],{cwd:e});return t.trim()===\"\"?void 0:t.trim()}catch{return}}function kbe(e,t){let r=e.project.configuration;return e.manifest.publishConfig&&typeof e.manifest.publishConfig.access==\"string\"?e.manifest.publishConfig.access:r.get(\"npmPublishAccess\")!==null?r.get(\"npmPublishAccess\"):t.scope?\"restricted\":\"public\"}async function Qbe(e){let t=fe.toPortablePath(`${e.cwd}/README.md`),r=e.manifest.name,a=`# ${j.stringifyIdent(r)}\n`;try{a=await le.readFilePromise(t,\"utf8\")}catch(n){if(n.code===\"ENOENT\")return a;throw n}return a}var zK={npmAlwaysAuth:{description:\"URL of the selected npm registry (note: npm enterprise isn't supported)\",type:\"BOOLEAN\",default:!1},npmAuthIdent:{description:\"Authentication identity for the npm registry (_auth in npm and yarn v1)\",type:\"SECRET\",default:null},npmAuthToken:{description:\"Authentication token for the npm registry (_authToken in npm and yarn v1)\",type:\"SECRET\",default:null}},Rbe={npmAuditRegistry:{description:\"Registry to query for audit reports\",type:\"STRING\",default:null},npmPublishRegistry:{description:\"Registry to push packages to\",type:\"STRING\",default:null},npmRegistryServer:{description:\"URL of the selected npm registry (note: npm enterprise isn't supported)\",type:\"STRING\",default:\"https://registry.yarnpkg.com\"}},wvt={npmMinimalAgeGate:{description:\"Minimum age of a package version according to the publish date on the npm registry to be considered for installation\",type:\"DURATION\",unit:\"m\",default:\"0m\"},npmPreapprovedPackages:{description:\"Array of package descriptors or package name glob patterns to exclude from the minimum release age check\",type:\"STRING\",isArray:!0,default:[]}},Bvt={configuration:{...zK,...Rbe,...wvt,npmScopes:{description:\"Settings per package scope\",type:\"MAP\",valueDefinition:{description:\"\",type:\"SHAPE\",properties:{...zK,...Rbe}}},npmRegistries:{description:\"Settings per registry\",type:\"MAP\",normalizeKeys:Vc,valueDefinition:{description:\"\",type:\"SHAPE\",properties:{...zK}}}},fetchers:[YD,ih],resolvers:[KD,JD,zD]},vvt=Bvt;var aJ={};Yt(aJ,{NpmAuditCommand:()=>y1,NpmInfoCommand:()=>E1,NpmLoginCommand:()=>I1,NpmLogoutCommand:()=>w1,NpmPublishCommand:()=>B1,NpmTagAddCommand:()=>S1,NpmTagListCommand:()=>v1,NpmTagRemoveCommand:()=>D1,NpmWhoamiCommand:()=>b1,default:()=>Ovt,npmAuditTypes:()=>zb,npmAuditUtils:()=>hL});qe();qe();Vt();var rJ=et(Jo());ul();var zb={};Yt(zb,{Environment:()=>Kb,Severity:()=>Jb});var Kb=(s=>(s.All=\"all\",s.Production=\"production\",s.Development=\"development\",s))(Kb||{}),Jb=(n=>(n.Info=\"info\",n.Low=\"low\",n.Moderate=\"moderate\",n.High=\"high\",n.Critical=\"critical\",n))(Jb||{});var hL={};Yt(hL,{allSeverities:()=>m1,getPackages:()=>tJ,getReportTree:()=>$K,getSeverityInclusions:()=>XK,getTopLevelDependencies:()=>eJ});qe();var Tbe=et(pi());var m1=[\"info\",\"low\",\"moderate\",\"high\",\"critical\"];function XK(e){if(typeof e>\"u\")return new Set(m1);let t=m1.indexOf(e),r=m1.slice(t);return new Set(r)}function $K(e){let t={},r={children:t};for(let[s,a]of Ge.sortMap(Object.entries(e),n=>n[0]))for(let n of Ge.sortMap(a,c=>`${c.id}`))t[`${s}/${n.id}`]={value:pe.tuple(pe.Type.IDENT,j.parseIdent(s)),children:{ID:typeof n.id<\"u\"&&{label:\"ID\",value:pe.tuple(pe.Type.ID,n.id)},Issue:{label:\"Issue\",value:pe.tuple(pe.Type.NO_HINT,n.title)},URL:typeof n.url<\"u\"&&{label:\"URL\",value:pe.tuple(pe.Type.URL,n.url)},Severity:{label:\"Severity\",value:pe.tuple(pe.Type.NO_HINT,n.severity)},\"Vulnerable Versions\":{label:\"Vulnerable Versions\",value:pe.tuple(pe.Type.RANGE,n.vulnerable_versions)},\"Tree Versions\":{label:\"Tree Versions\",children:[...n.versions].sort(Tbe.default.compare).map(c=>({value:pe.tuple(pe.Type.REFERENCE,c)}))},Dependents:{label:\"Dependents\",children:Ge.sortMap(n.dependents,c=>j.stringifyLocator(c)).map(c=>({value:pe.tuple(pe.Type.LOCATOR,c)}))}}};return r}function eJ(e,t,{all:r,environment:s}){let a=[],n=r?e.workspaces:[t],c=[\"all\",\"production\"].includes(s),f=[\"all\",\"development\"].includes(s);for(let p of n)for(let h of p.anchoredPackage.dependencies.values())(p.manifest.devDependencies.has(h.identHash)?!f:!c)||a.push({workspace:p,dependency:h});return a}function tJ(e,t,{recursive:r}){let s=new Map,a=new Set,n=[],c=e.configuration.makeResolver(),f={project:e,resolver:c},p=(h,E)=>{let C=e.storedResolutions.get(E.descriptorHash);if(typeof C>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");if(!a.has(C))a.add(C);else return;let S=e.storedPackages.get(C);if(typeof S>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");let x=j.ensureDevirtualizedDescriptor(E);if(c.supportsDescriptor(x,f)){let T=c.getResolutionDependencies(x,f);if(Object.keys(T).length>0)for(let O of Object.values(T))p(h,O)}if(j.ensureDevirtualizedLocator(S).reference.startsWith(\"npm:\")&&S.version!==null){let T=j.stringifyIdent(S),O=Ge.getMapWithDefault(s,T);Ge.getArrayWithDefault(O,S.version).push(h)}if(r)for(let T of S.dependencies.values())n.push([S,T])};for(let{workspace:h,dependency:E}of t)n.push([h.anchoredLocator,E]);for(;n.length>0;){let[h,E]=n.shift();p(h,E)}return s}var y1=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"-A,--all\",!1,{description:\"Audit dependencies from all workspaces\"});this.recursive=he.Boolean(\"-R,--recursive\",!1,{description:\"Audit transitive dependencies as well\"});this.environment=he.String(\"--environment\",\"all\",{description:\"Which environments to cover\",validator:ks(Kb)});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.noDeprecations=he.Boolean(\"--no-deprecations\",!1,{description:\"Don't warn about deprecated packages\"});this.severity=he.String(\"--severity\",\"info\",{description:\"Minimal severity requested for packages to be displayed\",validator:ks(Jb)});this.excludes=he.Array(\"--exclude\",[],{description:\"Array of glob patterns of packages to exclude from audit\"});this.ignores=he.Array(\"--ignore\",[],{description:\"Array of glob patterns of advisory ID's to ignore in the audit report\"})}static{this.paths=[[\"npm\",\"audit\"]]}static{this.usage=at.Usage({description:\"perform a vulnerability audit against the installed packages\",details:`\n      This command checks for known security reports on the packages you use. The reports are by default extracted from the npm registry, and may or may not be relevant to your actual program (not all vulnerabilities affect all code paths).\n\n      For consistency with our other commands the default is to only check the direct dependencies for the active workspace. To extend this search to all workspaces, use \\`-A,--all\\`. To extend this search to both direct and transitive dependencies, use \\`-R,--recursive\\`.\n\n      Applying the \\`--severity\\` flag will limit the audit table to vulnerabilities of the corresponding severity and above. Valid values are ${m1.map(r=>`\\`${r}\\``).join(\", \")}.\n\n      If the \\`--json\\` flag is set, Yarn will print the output exactly as received from the registry. Regardless of this flag, the process will exit with a non-zero exit code if a report is found for the selected packages.\n\n      If certain packages produce false positives for a particular environment, the \\`--exclude\\` flag can be used to exclude any number of packages from the audit. This can also be set in the configuration file with the \\`npmAuditExcludePackages\\` option.\n\n      If particular advisories are needed to be ignored, the \\`--ignore\\` flag can be used with Advisory ID's to ignore any number of advisories in the audit report. This can also be set in the configuration file with the \\`npmAuditIgnoreAdvisories\\` option.\n\n      To understand the dependency tree requiring vulnerable packages, check the raw report with the \\`--json\\` flag or use \\`yarn why package\\` to get more information as to who depends on them.\n    `,examples:[[\"Checks for known security issues with the installed packages. The output is a list of known issues.\",\"yarn npm audit\"],[\"Audit dependencies in all workspaces\",\"yarn npm audit --all\"],[\"Limit auditing to `dependencies` (excludes `devDependencies`)\",\"yarn npm audit --environment production\"],[\"Show audit report as valid JSON\",\"yarn npm audit --json\"],[\"Audit all direct and transitive dependencies\",\"yarn npm audit --recursive\"],[\"Output moderate (or more severe) vulnerabilities\",\"yarn npm audit --severity moderate\"],[\"Exclude certain packages\",\"yarn npm audit --exclude package1 --exclude package2\"],[\"Ignore specific advisories\",\"yarn npm audit --ignore 1234567 --ignore 7654321\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState();let n=eJ(s,a,{all:this.all,environment:this.environment}),c=tJ(s,n,{recursive:this.recursive}),f=Array.from(new Set([...r.get(\"npmAuditExcludePackages\"),...this.excludes])),p=Object.create(null);for(let[O,U]of c)f.some(Y=>rJ.default.isMatch(O,Y))||(p[O]=[...U.keys()]);let h=gi.getAuditRegistry({configuration:r}),E,C=await cA.start({configuration:r,stdout:this.context.stdout},async()=>{let O=en.post(\"/-/npm/v1/security/advisories/bulk\",p,{authType:en.AuthType.BEST_EFFORT,configuration:r,jsonResponse:!0,registry:h}),U=this.noDeprecations?[]:await Promise.all(Array.from(Object.entries(p),async([te,ie])=>{let ue=await en.getPackageMetadata(j.parseIdent(te),{project:s});return Ge.mapAndFilter(ie,ae=>{let{deprecated:de}=ue.versions[ae];return de?[te,ae,de]:Ge.mapAndFilter.skip})})),Y=await O;for(let[te,ie,ue]of U.flat(1))Object.hasOwn(Y,te)&&Y[te].some(ae=>Fr.satisfiesWithPrereleases(ie,ae.vulnerable_versions))||(Y[te]??=[],Y[te].push({id:`${te} (deprecation)`,title:(typeof ue==\"string\"?ue:\"\").trim()||\"This package has been deprecated.\",severity:\"moderate\",vulnerable_versions:ie}));E=Y});if(C.hasErrors())return C.exitCode();let S=XK(this.severity),x=Array.from(new Set([...r.get(\"npmAuditIgnoreAdvisories\"),...this.ignores])),I=Object.create(null);for(let[O,U]of Object.entries(E)){let Y=U.filter(te=>!rJ.default.isMatch(`${te.id}`,x)&&S.has(te.severity));Y.length>0&&(I[O]=Y.map(te=>{let ie=c.get(O);if(typeof ie>\"u\")throw new Error(\"Assertion failed: Expected the registry to only return packages that were requested\");let ue=[...ie.keys()].filter(de=>Fr.satisfiesWithPrereleases(de,te.vulnerable_versions)),ae=new Map;for(let de of ue)for(let Ae of ie.get(de))ae.set(Ae.locatorHash,Ae);return{...te,versions:ue,dependents:[...ae.values()]}}))}let T=Object.keys(I).length>0;return T?(Rs.emitTree($K(I),{configuration:r,json:this.json,stdout:this.context.stdout,separators:2}),1):(await Ot.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async O=>{O.reportInfo(1,\"No audit suggestions\")}),T?1:0)}};qe();qe();Dt();Vt();var nJ=et(pi()),iJ=Ie(\"util\"),E1=class extends At{constructor(){super(...arguments);this.fields=he.String(\"-f,--fields\",{description:\"A comma-separated list of manifest fields that should be displayed\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.packages=he.Rest()}static{this.paths=[[\"npm\",\"info\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"show information about a package\",details:\"\\n      This command fetches information about a package from the npm registry and prints it in a tree format.\\n\\n      The package does not have to be installed locally, but needs to have been published (in particular, local changes will be ignored even for workspaces).\\n\\n      Append `@<range>` to the package argument to provide information specific to the latest version that satisfies the range or to the corresponding tagged version. If the range is invalid or if there is no version satisfying the range, the command will print a warning and fall back to the latest version.\\n\\n      If the `-f,--fields` option is set, it's a comma-separated list of fields which will be used to only display part of the package information.\\n\\n      By default, this command won't return the `dist`, `readme`, and `users` fields, since they are often very long. To explicitly request those fields, explicitly list them with the `--fields` flag or request the output in JSON mode.\\n    \",examples:[[\"Show all available information about react (except the `dist`, `readme`, and `users` fields)\",\"yarn npm info react\"],[\"Show all available information about react as valid JSON (including the `dist`, `readme`, and `users` fields)\",\"yarn npm info react --json\"],[\"Show all available information about react@16.12.0\",\"yarn npm info react@16.12.0\"],[\"Show all available information about react@next\",\"yarn npm info react@next\"],[\"Show the description of react\",\"yarn npm info react --fields description\"],[\"Show all available versions of react\",\"yarn npm info react --fields versions\"],[\"Show the readme of react\",\"yarn npm info react --fields readme\"],[\"Show a few fields of react\",\"yarn npm info react --fields homepage,repository\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd),a=typeof this.fields<\"u\"?new Set([\"name\",...this.fields.split(/\\s*,\\s*/)]):null,n=[],c=!1,f=await Ot.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async p=>{for(let h of this.packages){let E;if(h===\".\"){let ie=s.topLevelWorkspace;if(!ie.manifest.name)throw new st(`Missing ${pe.pretty(r,\"name\",pe.Type.CODE)} field in ${fe.fromPortablePath(K.join(ie.cwd,Er.manifest))}`);E=j.makeDescriptor(ie.manifest.name,\"unknown\")}else E=j.parseDescriptor(h);let C=en.getIdentUrl(E),S=sJ(await en.get(C,{configuration:r,ident:E,jsonResponse:!0,customErrorMessage:en.customPackageError})),x=Object.keys(S.versions).sort(nJ.default.compareLoose),T=S[\"dist-tags\"].latest||x[x.length-1],O=Fr.validRange(E.range);if(O){let ie=nJ.default.maxSatisfying(x,O);ie!==null?T=ie:(p.reportWarning(0,`Unmet range ${j.prettyRange(r,E.range)}; falling back to the latest version`),c=!0)}else Object.hasOwn(S[\"dist-tags\"],E.range)?T=S[\"dist-tags\"][E.range]:E.range!==\"unknown\"&&(p.reportWarning(0,`Unknown tag ${j.prettyRange(r,E.range)}; falling back to the latest version`),c=!0);let U=S.versions[T],Y={...S,...U,version:T,versions:x},te;if(a!==null){te={};for(let ie of a){let ue=Y[ie];if(typeof ue<\"u\")te[ie]=ue;else{p.reportWarning(1,`The ${pe.pretty(r,ie,pe.Type.CODE)} field doesn't exist inside ${j.prettyIdent(r,E)}'s information`),c=!0;continue}}}else this.json||(delete Y.dist,delete Y.readme,delete Y.users),te=Y;p.reportJson(te),this.json||n.push(te)}});iJ.inspect.styles.name=\"cyan\";for(let p of n)(p!==n[0]||c)&&this.context.stdout.write(`\n`),this.context.stdout.write(`${(0,iJ.inspect)(p,{depth:1/0,colors:!0,compact:!1})}\n`);return f.exitCode()}};function sJ(e){if(Array.isArray(e)){let t=[];for(let r of e)r=sJ(r),r&&t.push(r);return t}else if(typeof e==\"object\"&&e!==null){let t={};for(let r of Object.keys(e)){if(r.startsWith(\"_\"))continue;let s=sJ(e[r]);s&&(t[r]=s)}return t}else return e||null}qe();qe();Vt();var oJ=et(Yv()),I1=class extends At{constructor(){super(...arguments);this.scope=he.String(\"-s,--scope\",{description:\"Login to the registry configured for a given scope\"});this.publish=he.Boolean(\"--publish\",!1,{description:\"Login to the publish registry\"});this.alwaysAuth=he.Boolean(\"--always-auth\",{description:\"Set the npmAlwaysAuth configuration\"});this.webLogin=he.Boolean(\"--web-login\",{description:\"Enable web login\"})}static{this.paths=[[\"npm\",\"login\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"store new login info to access the npm registry\",details:\"\\n      This command will ask you for your username, password, and 2FA One-Time-Password (when it applies). It will then modify your local configuration (in your home folder, never in the project itself) to reference the new tokens thus generated.\\n\\n      Adding the `-s,--scope` flag will cause the authentication to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\\n\\n      Adding the `--publish` flag will cause the authentication to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\\n    \",examples:[[\"Login to the default registry\",\"yarn npm login\"],[\"Login to the registry linked to the @my-scope registry\",\"yarn npm login --scope my-scope\"],[\"Login to the publish registry for the current package\",\"yarn npm login --publish\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=await gL({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope});return(await Ot.start({configuration:r,stdout:this.context.stdout,includeFooter:!1},async n=>{let c=await xvt({registry:s,configuration:r,report:n,webLogin:this.webLogin,stdin:this.context.stdin,stdout:this.context.stdout});return await Qvt(s,c,{alwaysAuth:this.alwaysAuth,scope:this.scope}),n.reportInfo(0,\"Successfully logged in\")})).exitCode()}};async function gL({scope:e,publish:t,configuration:r,cwd:s}){return e&&t?gi.getScopeRegistry(e,{configuration:r,type:gi.RegistryType.PUBLISH_REGISTRY}):e?gi.getScopeRegistry(e,{configuration:r}):t?gi.getPublishRegistry((await WI(r,s)).manifest,{configuration:r}):gi.getDefaultRegistry({configuration:r})}async function Svt(e,t){let r;try{r=await en.post(\"/-/v1/login\",null,{configuration:t,registry:e,authType:en.AuthType.NO_AUTH,jsonResponse:!0,headers:{\"npm-auth-type\":\"web\"}})}catch{return null}return r}async function Dvt(e,t){let r=await nn.request(e,null,{configuration:t,jsonResponse:!0});if(r.statusCode===202){let s=r.headers[\"retry-after\"]??\"1\";return{type:\"waiting\",sleep:parseInt(s,10)}}return r.statusCode===200?{type:\"success\",token:r.body.token}:null}async function bvt({registry:e,configuration:t,report:r}){let s=await Svt(e,t);if(!s)return null;if(Ui.openUrl){r.reportInfo(0,\"Starting the web login process...\"),r.reportSeparator();let{openNow:a}=await(0,oJ.prompt)({type:\"confirm\",name:\"openNow\",message:\"Do you want to try to open your browser now?\",required:!0,initial:!0,onCancel:()=>process.exit(130)});r.reportSeparator(),(!a||!await Ui.openUrl(s.loginUrl))&&(r.reportWarning(0,\"We failed to automatically open the url; you'll have to open it yourself in your browser of choice:\"),r.reportWarning(0,pe.pretty(t,s.loginUrl,pe.Type.URL)),r.reportSeparator())}for(;;){let a=await Dvt(s.doneUrl,t);if(a===null)return null;if(a.type===\"waiting\")await new Promise(n=>setTimeout(n,a.sleep*1e3));else return a.token}}var Pvt=[\"https://registry.yarnpkg.com\",\"https://registry.npmjs.org\"];async function xvt(e){if(e.webLogin??Pvt.includes(e.registry)){let t=await bvt(e);if(t!==null)return t}return await kvt(e)}async function kvt({registry:e,configuration:t,report:r,stdin:s,stdout:a}){let n=await Rvt({configuration:t,registry:e,report:r,stdin:s,stdout:a}),c=`/-/user/org.couchdb.user:${encodeURIComponent(n.name)}`,f={_id:`org.couchdb.user:${n.name}`,name:n.name,password:n.password,type:\"user\",roles:[],date:new Date().toISOString()},p={attemptedAs:n.name,configuration:t,registry:e,jsonResponse:!0,authType:en.AuthType.NO_AUTH};try{return(await en.put(c,f,p)).token}catch(x){if(!(x.originalError?.name===\"HTTPError\"&&x.originalError?.response.statusCode===409))throw x}let h={...p,authType:en.AuthType.NO_AUTH,headers:{authorization:`Basic ${Buffer.from(`${n.name}:${n.password}`).toString(\"base64\")}`}},E=await en.get(c,h);for(let[x,I]of Object.entries(E))(!f[x]||x===\"roles\")&&(f[x]=I);let C=`${c}/-rev/${f._rev}`;return(await en.put(C,f,h)).token}async function Qvt(e,t,{alwaysAuth:r,scope:s}){let a=c=>f=>{let p=Ge.isIndexableObject(f)?f:{},h=p[c],E=Ge.isIndexableObject(h)?h:{};return{...p,[c]:{...E,...r!==void 0?{npmAlwaysAuth:r}:{},npmAuthToken:t}}},n=s?{npmScopes:a(s)}:{npmRegistries:a(e)};return await ze.updateHomeConfiguration(n)}async function Rvt({configuration:e,registry:t,report:r,stdin:s,stdout:a}){r.reportInfo(0,`Logging in to ${pe.pretty(e,t,pe.Type.URL)}`);let n=!1;if(t.match(/^https:\\/\\/npm\\.pkg\\.github\\.com(\\/|$)/)&&(r.reportInfo(0,\"You seem to be using the GitHub Package Registry. Tokens must be generated with the 'repo', 'write:packages', and 'read:packages' permissions.\"),n=!0),r.reportSeparator(),e.env.YARN_IS_TEST_ENV)return{name:e.env.YARN_INJECT_NPM_USER||\"\",password:e.env.YARN_INJECT_NPM_PASSWORD||\"\"};let c=await(0,oJ.prompt)([{type:\"input\",name:\"name\",message:\"Username:\",required:!0,onCancel:()=>process.exit(130),stdin:s,stdout:a},{type:\"password\",name:\"password\",message:n?\"Token:\":\"Password:\",required:!0,onCancel:()=>process.exit(130),stdin:s,stdout:a}]);return r.reportSeparator(),c}qe();qe();Vt();var C1=new Set([\"npmAuthIdent\",\"npmAuthToken\"]),w1=class extends At{constructor(){super(...arguments);this.scope=he.String(\"-s,--scope\",{description:\"Logout of the registry configured for a given scope\"});this.publish=he.Boolean(\"--publish\",!1,{description:\"Logout of the publish registry\"});this.all=he.Boolean(\"-A,--all\",!1,{description:\"Logout of all registries\"})}static{this.paths=[[\"npm\",\"logout\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"logout of the npm registry\",details:\"\\n      This command will log you out by modifying your local configuration (in your home folder, never in the project itself) to delete all credentials linked to a registry.\\n\\n      Adding the `-s,--scope` flag will cause the deletion to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\\n\\n      Adding the `--publish` flag will cause the deletion to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\\n\\n      Adding the `-A,--all` flag will cause the deletion to be done against all registries and scopes.\\n    \",examples:[[\"Logout of the default registry\",\"yarn npm logout\"],[\"Logout of the @my-scope scope\",\"yarn npm logout --scope my-scope\"],[\"Logout of the publish registry for the current package\",\"yarn npm logout --publish\"],[\"Logout of all registries\",\"yarn npm logout --all\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s=async()=>{let n=await gL({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope}),c=await ze.find(this.context.cwd,this.context.plugins),f=j.makeIdent(this.scope??null,\"pkg\");return!gi.getAuthConfiguration(n,{configuration:c,ident:f}).get(\"npmAuthToken\")};return(await Ot.start({configuration:r,stdout:this.context.stdout},async n=>{if(this.all&&(await Fvt(),n.reportInfo(0,\"Successfully logged out from everything\")),this.scope){await Fbe(\"npmScopes\",this.scope),await s()?n.reportInfo(0,`Successfully logged out from ${this.scope}`):n.reportWarning(0,\"Scope authentication settings removed, but some other ones settings still apply to it\");return}let c=await gL({configuration:r,cwd:this.context.cwd,publish:this.publish});await Fbe(\"npmRegistries\",c),await s()?n.reportInfo(0,`Successfully logged out from ${c}`):n.reportWarning(0,\"Registry authentication settings removed, but some other ones settings still apply to it\")})).exitCode()}};function Tvt(e,t){let r=e[t];if(!Ge.isIndexableObject(r))return!1;let s=new Set(Object.keys(r));if([...C1].every(n=>!s.has(n)))return!1;for(let n of C1)s.delete(n);if(s.size===0)return e[t]=void 0,!0;let a={...r};for(let n of C1)delete a[n];return e[t]=a,!0}async function Fvt(){let e=t=>{let r=!1,s=Ge.isIndexableObject(t)?{...t}:{};s.npmAuthToken&&(delete s.npmAuthToken,r=!0);for(let a of Object.keys(s))Tvt(s,a)&&(r=!0);if(Object.keys(s).length!==0)return r?s:t};return await ze.updateHomeConfiguration({npmRegistries:e,npmScopes:e})}async function Fbe(e,t){return await ze.updateHomeConfiguration({[e]:r=>{let s=Ge.isIndexableObject(r)?r:{};if(!Object.hasOwn(s,t))return r;let a=s[t],n=Ge.isIndexableObject(a)?a:{},c=new Set(Object.keys(n));if([...C1].every(p=>!c.has(p)))return r;for(let p of C1)c.delete(p);if(c.size===0)return Object.keys(s).length===1?void 0:{...s,[t]:void 0};let f={};for(let p of C1)f[p]=void 0;return{...s,[t]:{...n,...f}}}})}qe();Dt();Vt();var B1=class extends At{constructor(){super(...arguments);this.access=he.String(\"--access\",{description:\"The access for the published package (public or restricted)\"});this.tag=he.String(\"--tag\",\"latest\",{description:\"The tag on the registry that the package should be attached to\"});this.tolerateRepublish=he.Boolean(\"--tolerate-republish\",!1,{description:\"Warn and exit when republishing an already existing version of a package\"});this.otp=he.String(\"--otp\",{description:\"The OTP token to use with the command\"});this.provenance=he.Boolean(\"--provenance\",!1,{description:\"Generate provenance for the package. Only available in GitHub Actions and GitLab CI. Can be set globally through the `npmPublishProvenance` setting or the `YARN_NPM_CONFIG_PROVENANCE` environment variable, or per-package through the `publishConfig.provenance` field in package.json.\"});this.dryRun=he.Boolean(\"-n,--dry-run\",!1,{description:\"Show what would be published without actually publishing\"});this.json=he.Boolean(\"--json\",!1,{description:\"Output the result in JSON format\"})}static{this.paths=[[\"npm\",\"publish\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"publish the active workspace to the npm registry\",details:'\\n      This command will pack the active workspace into a fresh archive and upload it to the npm registry.\\n\\n      The package will by default be attached to the `latest` tag on the registry, but this behavior can be overridden by using the `--tag` option.\\n\\n      Note that for legacy reasons scoped packages are by default published with an access set to `restricted` (aka \"private packages\"). This requires you to register for a paid npm plan. In case you simply wish to publish a public scoped package to the registry (for free), just add the `--access public` flag. This behavior can be enabled by default through the `npmPublishAccess` settings.\\n    ',examples:[[\"Publish the active workspace\",\"yarn npm publish\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);if(a.manifest.private)throw new st(\"Private workspaces cannot be published\");if(a.manifest.name===null||a.manifest.version===null)throw new st(\"Workspaces must have valid names and versions to be published on an external registry\");await s.restoreInstallState();let n=a.manifest.name,c=a.manifest.version,f=gi.getPublishRegistry(a.manifest,{configuration:r});return(await Ot.start({configuration:r,stdout:this.context.stdout,json:this.json},async h=>{if(h.reportInfo(0,`Publishing to ${f} with tag ${this.tag}`),this.tolerateRepublish)try{let E=await en.get(en.getIdentUrl(n),{configuration:r,registry:f,ident:n,jsonResponse:!0});if(!Object.hasOwn(E,\"versions\"))throw new _t(15,'Registry returned invalid data for - missing \"versions\" field');if(Object.hasOwn(E.versions,c)){let C=`Registry already knows about version ${c}; skipping.`;h.reportWarning(0,C),h.reportJson({name:j.stringifyIdent(n),version:c,registry:f,warning:C,skipped:!0});return}}catch(E){if(E.originalError?.response?.statusCode!==404)throw E}await Cn.maybeExecuteWorkspaceLifecycleScript(a,\"prepublish\",{report:h}),await EA.prepareForPack(a,{report:h},async()=>{let E=await EA.genPackList(a);for(let Y of E)h.reportInfo(null,fe.fromPortablePath(Y)),h.reportJson({file:fe.fromPortablePath(Y)});let C=await EA.genPackStream(a,E),S=await Ge.bufferStream(C),x=await d1.getGitHead(a.cwd),I=!1,T=\"\";a.manifest.publishConfig&&\"provenance\"in a.manifest.publishConfig?(I=!!a.manifest.publishConfig.provenance,T=I?\"Generating provenance statement because `publishConfig.provenance` field is set.\":\"Skipping provenance statement because `publishConfig.provenance` field is set to false.\"):this.provenance?(I=!0,T=\"Generating provenance statement because `--provenance` flag is set.\"):r.get(\"npmPublishProvenance\")&&(I=!0,T=\"Generating provenance statement because `npmPublishProvenance` setting is set.\"),T&&(h.reportInfo(null,T),h.reportJson({type:\"provenance\",enabled:I,provenanceMessage:T}));let O=await d1.makePublishBody(a,S,{access:this.access,tag:this.tag,registry:f,gitHead:x,provenance:I});this.dryRun||await en.put(en.getIdentUrl(n),O,{configuration:r,registry:f,ident:n,otp:this.otp,jsonResponse:!0,allowOidc:!!(process.env.CI&&(process.env.GITHUB_ACTIONS||process.env.GITLAB_CI))});let U=this.dryRun?\"Package archive not published (dry run)\":\"Package archive published\";h.reportInfo(0,U),h.reportJson({name:j.stringifyIdent(n),version:c,registry:f,tag:this.tag||\"latest\",files:E.map(Y=>fe.fromPortablePath(Y)),access:this.access||null,dryRun:this.dryRun,published:!this.dryRun,message:U,provenance:!!I})})})).exitCode()}};qe();Vt();var Nbe=et(pi());qe();Dt();Vt();var v1=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.package=he.String({required:!1})}static{this.paths=[[\"npm\",\"tag\",\"list\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"list all dist-tags of a package\",details:`\n      This command will list all tags of a package from the npm registry.\n\n      If the package is not specified, Yarn will default to the current workspace.\n    `,examples:[[\"List all tags of package `my-pkg`\",\"yarn npm tag list my-pkg\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n;if(typeof this.package<\"u\")n=j.parseIdent(this.package);else{if(!a)throw new ar(s.cwd,this.context.cwd);if(!a.manifest.name)throw new st(`Missing 'name' field in ${fe.fromPortablePath(K.join(a.cwd,Er.manifest))}`);n=a.manifest.name}let c=await Zb(n,r),p={children:Ge.sortMap(Object.entries(c),([h])=>h).map(([h,E])=>({value:pe.tuple(pe.Type.RESOLUTION,{descriptor:j.makeDescriptor(n,h),locator:j.makeLocator(n,E)})}))};return Rs.emitTree(p,{configuration:r,json:this.json,stdout:this.context.stdout})}};async function Zb(e,t){let r=`/-/package${en.getIdentUrl(e)}/dist-tags`;return en.get(r,{configuration:t,ident:e,jsonResponse:!0,customErrorMessage:en.customPackageError})}var S1=class extends At{constructor(){super(...arguments);this.package=he.String();this.tag=he.String()}static{this.paths=[[\"npm\",\"tag\",\"add\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"add a tag for a specific version of a package\",details:`\n      This command will add a tag to the npm registry for a specific version of a package. If the tag already exists, it will be overwritten.\n    `,examples:[[\"Add a `beta` tag for version `2.3.4-beta.4` of package `my-pkg`\",\"yarn npm tag add my-pkg@2.3.4-beta.4 beta\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);let n=j.parseDescriptor(this.package,!0),c=n.range;if(!Nbe.default.valid(c))throw new st(`The range ${pe.pretty(r,n.range,pe.Type.RANGE)} must be a valid semver version`);let f=gi.getPublishRegistry(a.manifest,{configuration:r}),p=pe.pretty(r,n,pe.Type.IDENT),h=pe.pretty(r,c,pe.Type.RANGE),E=pe.pretty(r,this.tag,pe.Type.CODE);return(await Ot.start({configuration:r,stdout:this.context.stdout},async S=>{let x=await Zb(n,r);Object.hasOwn(x,this.tag)&&x[this.tag]===c&&S.reportWarning(0,`Tag ${E} is already set to version ${h}`);let I=`/-/package${en.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await en.put(I,c,{configuration:r,registry:f,ident:n,jsonRequest:!0,jsonResponse:!0}),S.reportInfo(0,`Tag ${E} added to version ${h} of package ${p}`)})).exitCode()}};qe();Vt();var D1=class extends At{constructor(){super(...arguments);this.package=he.String();this.tag=he.String()}static{this.paths=[[\"npm\",\"tag\",\"remove\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"remove a tag from a package\",details:`\n      This command will remove a tag from a package from the npm registry.\n    `,examples:[[\"Remove the `beta` tag from package `my-pkg`\",\"yarn npm tag remove my-pkg beta\"]]})}async execute(){if(this.tag===\"latest\")throw new st(\"The 'latest' tag cannot be removed.\");let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);let n=j.parseIdent(this.package),c=gi.getPublishRegistry(a.manifest,{configuration:r}),f=pe.pretty(r,this.tag,pe.Type.CODE),p=pe.pretty(r,n,pe.Type.IDENT),h=await Zb(n,r);if(!Object.hasOwn(h,this.tag))throw new st(`${f} is not a tag of package ${p}`);return(await Ot.start({configuration:r,stdout:this.context.stdout},async C=>{let S=`/-/package${en.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await en.del(S,{configuration:r,registry:c,ident:n,jsonResponse:!0}),C.reportInfo(0,`Tag ${f} removed from package ${p}`)})).exitCode()}};qe();qe();Vt();var b1=class extends At{constructor(){super(...arguments);this.scope=he.String(\"-s,--scope\",{description:\"Print username for the registry configured for a given scope\"});this.publish=he.Boolean(\"--publish\",!1,{description:\"Print username for the publish registry\"})}static{this.paths=[[\"npm\",\"whoami\"]]}static{this.usage=at.Usage({category:\"Npm-related commands\",description:\"display the name of the authenticated user\",details:\"\\n      Print the username associated with the current authentication settings to the standard output.\\n\\n      When using `-s,--scope`, the username printed will be the one that matches the authentication settings of the registry associated with the given scope (those settings can be overriden using the `npmRegistries` map, and the registry associated with the scope is configured via the `npmScopes` map).\\n\\n      When using `--publish`, the registry we'll select will by default be the one used when publishing packages (`publishConfig.registry` or `npmPublishRegistry` if available, otherwise we'll fallback to the regular `npmRegistryServer`).\\n    \",examples:[[\"Print username for the default registry\",\"yarn npm whoami\"],[\"Print username for the registry on a given scope\",\"yarn npm whoami --scope company\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),s;return this.scope&&this.publish?s=gi.getScopeRegistry(this.scope,{configuration:r,type:gi.RegistryType.PUBLISH_REGISTRY}):this.scope?s=gi.getScopeRegistry(this.scope,{configuration:r}):this.publish?s=gi.getPublishRegistry((await WI(r,this.context.cwd)).manifest,{configuration:r}):s=gi.getDefaultRegistry({configuration:r}),(await Ot.start({configuration:r,stdout:this.context.stdout},async n=>{let c;try{c=await en.get(\"/-/whoami\",{configuration:r,registry:s,authType:en.AuthType.ALWAYS_AUTH,jsonResponse:!0,ident:this.scope?j.makeIdent(this.scope,\"\"):void 0})}catch(f){if(f.response?.statusCode===401||f.response?.statusCode===403){n.reportError(41,\"Authentication failed - your credentials may have expired\");return}else throw f}n.reportInfo(0,c.username)})).exitCode()}};var Nvt={configuration:{npmPublishAccess:{description:\"Default access of the published packages\",type:\"STRING\",default:null},npmPublishProvenance:{description:\"Whether to generate provenance for the published packages\",type:\"BOOLEAN\",default:!1},npmAuditExcludePackages:{description:\"Array of glob patterns of packages to exclude from npm audit\",type:\"STRING\",default:[],isArray:!0},npmAuditIgnoreAdvisories:{description:\"Array of glob patterns of advisory IDs to exclude from npm audit\",type:\"STRING\",default:[],isArray:!0}},commands:[y1,E1,I1,w1,B1,S1,v1,D1,b1]},Ovt=Nvt;var hJ={};Yt(hJ,{PatchCommand:()=>T1,PatchCommitCommand:()=>R1,PatchFetcher:()=>rP,PatchResolver:()=>nP,default:()=>eSt,patchUtils:()=>yy});qe();qe();Dt();rA();var yy={};Yt(yy,{applyPatchFile:()=>mL,diffFolders:()=>AJ,ensureUnpatchedDescriptor:()=>lJ,ensureUnpatchedLocator:()=>EL,extractPackageToDisk:()=>fJ,extractPatchFlags:()=>jbe,isParentRequired:()=>uJ,isPatchDescriptor:()=>yL,isPatchLocator:()=>Qg,loadPatchFiles:()=>tP,makeDescriptor:()=>IL,makeLocator:()=>cJ,makePatchHash:()=>pJ,parseDescriptor:()=>$b,parseLocator:()=>eP,parsePatchFile:()=>Xb,unpatchDescriptor:()=>Zvt,unpatchLocator:()=>Xvt});qe();Dt();qe();Dt();var Lvt=/^@@ -(\\d+)(,(\\d+))? \\+(\\d+)(,(\\d+))? @@.*/;function P1(e){return K.relative(vt.root,K.resolve(vt.root,fe.toPortablePath(e)))}function Mvt(e){let t=e.trim().match(Lvt);if(!t)throw new Error(`Bad header line: '${e}'`);return{original:{start:Math.max(Number(t[1]),1),length:Number(t[3]||1)},patched:{start:Math.max(Number(t[4]),1),length:Number(t[6]||1)}}}var Uvt=420,_vt=493;var Obe=()=>({semverExclusivity:null,diffLineFromPath:null,diffLineToPath:null,oldMode:null,newMode:null,deletedFileMode:null,newFileMode:null,renameFrom:null,renameTo:null,beforeHash:null,afterHash:null,fromPath:null,toPath:null,hunks:null}),Hvt=e=>({header:Mvt(e),parts:[]}),jvt={\"@\":\"header\",\"-\":\"deletion\",\"+\":\"insertion\",\" \":\"context\",\"\\\\\":\"pragma\",undefined:\"context\"};function Gvt(e){let t=[],r=Obe(),s=\"parsing header\",a=null,n=null;function c(){a&&(n&&(a.parts.push(n),n=null),r.hunks.push(a),a=null)}function f(){c(),t.push(r),r=Obe()}for(let p=0;p<e.length;p++){let h=e[p];if(s===\"parsing header\")if(h.startsWith(\"@@\"))s=\"parsing hunks\",r.hunks=[],p-=1;else if(h.startsWith(\"diff --git \")){r&&r.diffLineFromPath&&f();let E=h.match(/^diff --git a\\/(.*?) b\\/(.*?)\\s*$/);if(!E)throw new Error(`Bad diff line: ${h}`);r.diffLineFromPath=E[1],r.diffLineToPath=E[2]}else if(h.startsWith(\"old mode \"))r.oldMode=h.slice(9).trim();else if(h.startsWith(\"new mode \"))r.newMode=h.slice(9).trim();else if(h.startsWith(\"deleted file mode \"))r.deletedFileMode=h.slice(18).trim();else if(h.startsWith(\"new file mode \"))r.newFileMode=h.slice(14).trim();else if(h.startsWith(\"rename from \"))r.renameFrom=h.slice(12).trim();else if(h.startsWith(\"rename to \"))r.renameTo=h.slice(10).trim();else if(h.startsWith(\"index \")){let E=h.match(/(\\w+)\\.\\.(\\w+)/);if(!E)continue;r.beforeHash=E[1],r.afterHash=E[2]}else h.startsWith(\"semver exclusivity \")?r.semverExclusivity=h.slice(19).trim():h.startsWith(\"--- \")?r.fromPath=h.slice(6).trim():h.startsWith(\"+++ \")&&(r.toPath=h.slice(6).trim());else{let E=jvt[h[0]]||null;switch(E){case\"header\":c(),a=Hvt(h);break;case null:s=\"parsing header\",f(),p-=1;break;case\"pragma\":{if(!h.startsWith(\"\\\\ No newline at end of file\"))throw new Error(`Unrecognized pragma in patch file: ${h}`);if(!n)throw new Error(\"Bad parser state: No newline at EOF pragma encountered without context\");n.noNewlineAtEndOfFile=!0}break;case\"context\":case\"deletion\":case\"insertion\":{if(!a)throw new Error(\"Bad parser state: Hunk lines encountered before hunk header\");n&&n.type!==E&&(a.parts.push(n),n=null),n||(n={type:E,lines:[],noNewlineAtEndOfFile:!1}),n.lines.push(h.slice(1))}break;default:Ge.assertNever(E);break}}}f();for(let{hunks:p}of t)if(p)for(let h of p)Wvt(h);return t}function qvt(e){let t=[];for(let r of e){let{semverExclusivity:s,diffLineFromPath:a,diffLineToPath:n,oldMode:c,newMode:f,deletedFileMode:p,newFileMode:h,renameFrom:E,renameTo:C,beforeHash:S,afterHash:x,fromPath:I,toPath:T,hunks:O}=r,U=E?\"rename\":p?\"file deletion\":h?\"file creation\":O&&O.length>0?\"patch\":\"mode change\",Y=null;switch(U){case\"rename\":{if(!E||!C)throw new Error(\"Bad parser state: rename from & to not given\");t.push({type:\"rename\",semverExclusivity:s,fromPath:P1(E),toPath:P1(C)}),Y=C}break;case\"file deletion\":{let te=a||I;if(!te)throw new Error(\"Bad parse state: no path given for file deletion\");t.push({type:\"file deletion\",semverExclusivity:s,hunk:O&&O[0]||null,path:P1(te),mode:dL(p),hash:S})}break;case\"file creation\":{let te=n||T;if(!te)throw new Error(\"Bad parse state: no path given for file creation\");t.push({type:\"file creation\",semverExclusivity:s,hunk:O&&O[0]||null,path:P1(te),mode:dL(h),hash:x})}break;case\"patch\":case\"mode change\":Y=T||n;break;default:Ge.assertNever(U);break}Y&&c&&f&&c!==f&&t.push({type:\"mode change\",semverExclusivity:s,path:P1(Y),oldMode:dL(c),newMode:dL(f)}),Y&&O&&O.length&&t.push({type:\"patch\",semverExclusivity:s,path:P1(Y),hunks:O,beforeHash:S,afterHash:x})}if(t.length===0)throw new Error(\"Unable to parse patch file: No changes found. Make sure the patch is a valid UTF8 encoded string\");return t}function dL(e){let t=parseInt(e,8)&511;if(t!==Uvt&&t!==_vt)throw new Error(`Unexpected file mode string: ${e}`);return t}function Xb(e){let t=e.split(/\\n/g);return t[t.length-1]===\"\"&&t.pop(),qvt(Gvt(t))}function Wvt(e){let t=0,r=0;for(let{type:s,lines:a}of e.parts)switch(s){case\"context\":r+=a.length,t+=a.length;break;case\"deletion\":t+=a.length;break;case\"insertion\":r+=a.length;break;default:Ge.assertNever(s);break}if(t!==e.header.original.length||r!==e.header.patched.length){let s=a=>a<0?a:`+${a}`;throw new Error(`hunk header integrity check failed (expected @@ ${s(e.header.original.length)} ${s(e.header.patched.length)} @@, got @@ ${s(t)} ${s(r)} @@)`)}}qe();Dt();var x1=class extends Error{constructor(r,s){super(`Cannot apply hunk #${r+1}`);this.hunk=s}};async function k1(e,t,r){let s=await e.lstatPromise(t),a=await r();typeof a<\"u\"&&(t=a),await e.lutimesPromise(t,s.atime,s.mtime)}async function mL(e,{baseFs:t=new Yn,dryRun:r=!1,version:s=null}={}){for(let a of e)if(!(a.semverExclusivity!==null&&s!==null&&!Fr.satisfiesWithPrereleases(s,a.semverExclusivity)))switch(a.type){case\"file deletion\":if(r){if(!t.existsSync(a.path))throw new Error(`Trying to delete a file that doesn't exist: ${a.path}`)}else await k1(t,K.dirname(a.path),async()=>{await t.unlinkPromise(a.path)});break;case\"rename\":if(r){if(!t.existsSync(a.fromPath))throw new Error(`Trying to move a file that doesn't exist: ${a.fromPath}`)}else await k1(t,K.dirname(a.fromPath),async()=>{await k1(t,K.dirname(a.toPath),async()=>{await k1(t,a.fromPath,async()=>(await t.movePromise(a.fromPath,a.toPath),a.toPath))})});break;case\"file creation\":if(r){if(t.existsSync(a.path))throw new Error(`Trying to create a file that already exists: ${a.path}`)}else{let n=a.hunk?a.hunk.parts[0].lines.join(`\n`)+(a.hunk.parts[0].noNewlineAtEndOfFile?\"\":`\n`):\"\";await t.mkdirpPromise(K.dirname(a.path),{chmod:493,utimes:[Ai.SAFE_TIME,Ai.SAFE_TIME]}),await t.writeFilePromise(a.path,n,{mode:a.mode}),await t.utimesPromise(a.path,Ai.SAFE_TIME,Ai.SAFE_TIME)}break;case\"patch\":await k1(t,a.path,async()=>{await Kvt(a,{baseFs:t,dryRun:r})});break;case\"mode change\":{let c=(await t.statPromise(a.path)).mode;if(Lbe(a.newMode)!==Lbe(c))continue;await k1(t,a.path,async()=>{await t.chmodPromise(a.path,a.newMode)})}break;default:Ge.assertNever(a);break}}function Lbe(e){return(e&64)>0}function Mbe(e){return e.replace(/\\s+$/,\"\")}function Yvt(e,t){return Mbe(e)===Mbe(t)}async function Kvt({hunks:e,path:t},{baseFs:r,dryRun:s=!1}){let a=await r.statSync(t).mode,c=(await r.readFileSync(t,\"utf8\")).split(/\\n/),f=[],p=0,h=0;for(let C of e){let S=Math.max(h,C.header.patched.start+p),x=Math.max(0,S-h),I=Math.max(0,c.length-S-C.header.original.length),T=Math.max(x,I),O=0,U=0,Y=null;for(;O<=T;){if(O<=x&&(U=S-O,Y=Ube(C,c,U),Y!==null)){O=-O;break}if(O<=I&&(U=S+O,Y=Ube(C,c,U),Y!==null))break;O+=1}if(Y===null)throw new x1(e.indexOf(C),C);f.push(Y),p+=O,h=U+C.header.original.length}if(s)return;let E=0;for(let C of f)for(let S of C)switch(S.type){case\"splice\":{let x=S.index+E;c.splice(x,S.numToDelete,...S.linesToInsert),E+=S.linesToInsert.length-S.numToDelete}break;case\"pop\":c.pop();break;case\"push\":c.push(S.line);break;default:Ge.assertNever(S);break}await r.writeFilePromise(t,c.join(`\n`),{mode:a})}function Ube(e,t,r){let s=[];for(let a of e.parts)switch(a.type){case\"context\":case\"deletion\":{for(let n of a.lines){let c=t[r];if(c==null||!Yvt(c,n))return null;r+=1}a.type===\"deletion\"&&(s.push({type:\"splice\",index:r-a.lines.length,numToDelete:a.lines.length,linesToInsert:[]}),a.noNewlineAtEndOfFile&&s.push({type:\"push\",line:\"\"}))}break;case\"insertion\":s.push({type:\"splice\",index:r,numToDelete:0,linesToInsert:a.lines}),a.noNewlineAtEndOfFile&&s.push({type:\"pop\"});break;default:Ge.assertNever(a.type);break}return s}var zvt=/^builtin<([^>]+)>$/;function Q1(e,t){let{protocol:r,source:s,selector:a,params:n}=j.parseRange(e);if(r!==\"patch:\")throw new Error(\"Invalid patch range\");if(s===null)throw new Error(\"Patch locators must explicitly define their source\");let c=a?a.split(/&/).map(E=>fe.toPortablePath(E)):[],f=n&&typeof n.locator==\"string\"?j.parseLocator(n.locator):null,p=n&&typeof n.version==\"string\"?n.version:null,h=t(s);return{parentLocator:f,sourceItem:h,patchPaths:c,sourceVersion:p}}function yL(e){return e.range.startsWith(\"patch:\")}function Qg(e){return e.reference.startsWith(\"patch:\")}function $b(e){let{sourceItem:t,...r}=Q1(e.range,j.parseDescriptor);return{...r,sourceDescriptor:t}}function eP(e){let{sourceItem:t,...r}=Q1(e.reference,j.parseLocator);return{...r,sourceLocator:t}}function Zvt(e){let{sourceItem:t}=Q1(e.range,j.parseDescriptor);return t}function Xvt(e){let{sourceItem:t}=Q1(e.reference,j.parseLocator);return t}function lJ(e){if(!yL(e))return e;let{sourceItem:t}=Q1(e.range,j.parseDescriptor);return t}function EL(e){if(!Qg(e))return e;let{sourceItem:t}=Q1(e.reference,j.parseLocator);return t}function _be({parentLocator:e,sourceItem:t,patchPaths:r,sourceVersion:s,patchHash:a},n){let c=e!==null?{locator:j.stringifyLocator(e)}:{},f=typeof s<\"u\"?{version:s}:{},p=typeof a<\"u\"?{hash:a}:{};return j.makeRange({protocol:\"patch:\",source:n(t),selector:r.join(\"&\"),params:{...f,...p,...c}})}function IL(e,{parentLocator:t,sourceDescriptor:r,patchPaths:s}){return j.makeDescriptor(e,_be({parentLocator:t,sourceItem:r,patchPaths:s},j.stringifyDescriptor))}function cJ(e,{parentLocator:t,sourcePackage:r,patchPaths:s,patchHash:a}){return j.makeLocator(e,_be({parentLocator:t,sourceItem:r,sourceVersion:r.version,patchPaths:s,patchHash:a},j.stringifyLocator))}function Hbe({onAbsolute:e,onRelative:t,onProject:r,onBuiltin:s},a){let n=a.lastIndexOf(\"!\");n!==-1&&(a=a.slice(n+1));let c=a.match(zvt);return c!==null?s(c[1]):a.startsWith(\"~/\")?r(a.slice(2)):K.isAbsolute(a)?e(a):t(a)}function jbe(e){let t=e.lastIndexOf(\"!\");return{optional:(t!==-1?new Set(e.slice(0,t).split(/!/)):new Set).has(\"optional\")}}function uJ(e){return Hbe({onAbsolute:()=>!1,onRelative:()=>!0,onProject:()=>!1,onBuiltin:()=>!1},e)}async function tP(e,t,r){let s=e!==null?await r.fetcher.fetch(e,r):null,a=s&&s.localPath?{packageFs:new bn(vt.root),prefixPath:K.relative(vt.root,s.localPath)}:s;s&&s!==a&&s.releaseFs&&s.releaseFs();let n=await Ge.releaseAfterUseAsync(async()=>await Promise.all(t.map(async c=>{let f=jbe(c),p=await Hbe({onAbsolute:async h=>await le.readFilePromise(h,\"utf8\"),onRelative:async h=>{if(a===null)throw new Error(\"Assertion failed: The parent locator should have been fetched\");return await a.packageFs.readFilePromise(K.join(a.prefixPath,h),\"utf8\")},onProject:async h=>await le.readFilePromise(K.join(r.project.cwd,h),\"utf8\"),onBuiltin:async h=>await r.project.configuration.firstHook(E=>E.getBuiltinPatch,r.project,h)},c);return{...f,source:p}})));for(let c of n)typeof c.source==\"string\"&&(c.source=c.source.replace(/\\r\\n?/g,`\n`));return n}async function fJ(e,{cache:t,project:r}){let s=r.storedPackages.get(e.locatorHash);if(typeof s>\"u\")throw new Error(\"Assertion failed: Expected the package to be registered\");let a=EL(e),n=r.storedChecksums,c=new ki,f=await le.mktempPromise(),p=K.join(f,\"source\"),h=K.join(f,\"user\"),E=K.join(f,\".yarn-patch.json\"),C=r.configuration.makeFetcher(),S=[];try{let x,I;if(e.locatorHash===a.locatorHash){let T=await C.fetch(e,{cache:t,project:r,fetcher:C,checksums:n,report:c});S.push(()=>T.releaseFs?.()),x=T,I=T}else x=await C.fetch(e,{cache:t,project:r,fetcher:C,checksums:n,report:c}),S.push(()=>x.releaseFs?.()),I=await C.fetch(e,{cache:t,project:r,fetcher:C,checksums:n,report:c}),S.push(()=>I.releaseFs?.());await Promise.all([le.copyPromise(p,x.prefixPath,{baseFs:x.packageFs}),le.copyPromise(h,I.prefixPath,{baseFs:I.packageFs}),le.writeJsonPromise(E,{locator:j.stringifyLocator(e),version:s.version})])}finally{for(let x of S)x()}return le.detachTemp(f),h}async function AJ(e,t){let r=fe.fromPortablePath(e).replace(/\\\\/g,\"/\"),s=fe.fromPortablePath(t).replace(/\\\\/g,\"/\"),{stdout:a,stderr:n}=await qr.execvp(\"git\",[\"-c\",\"core.safecrlf=false\",\"diff\",\"--src-prefix=a/\",\"--dst-prefix=b/\",\"--ignore-cr-at-eol\",\"--full-index\",\"--no-index\",\"--no-renames\",\"--text\",r,s],{cwd:fe.toPortablePath(process.cwd()),env:{...process.env,GIT_CONFIG_NOSYSTEM:\"1\",HOME:\"\",XDG_CONFIG_HOME:\"\",USERPROFILE:\"\"}});if(n.length>0)throw new Error(`Unable to diff directories. Make sure you have a recent version of 'git' available in PATH.\nThe following error was reported by 'git':\n${n}`);let c=r.startsWith(\"/\")?f=>f.slice(1):f=>f;return a.replace(new RegExp(`(a|b)(${Ge.escapeRegExp(`/${c(r)}/`)})`,\"g\"),\"$1/\").replace(new RegExp(`(a|b)${Ge.escapeRegExp(`/${c(s)}/`)}`,\"g\"),\"$1/\").replace(new RegExp(Ge.escapeRegExp(`${r}/`),\"g\"),\"\").replace(new RegExp(Ge.escapeRegExp(`${s}/`),\"g\"),\"\")}function pJ(e,t){let r=[];for(let{source:s}of e){if(s===null)continue;let a=Xb(s);for(let n of a){let{semverExclusivity:c,...f}=n;c!==null&&t!==null&&!Fr.satisfiesWithPrereleases(t,c)||r.push(JSON.stringify(f))}}return Ln.makeHash(`${3}`,...r).slice(0,6)}qe();function Gbe(e,{configuration:t,report:r}){for(let s of e.parts)for(let a of s.lines)switch(s.type){case\"context\":r.reportInfo(null,`  ${pe.pretty(t,a,\"grey\")}`);break;case\"deletion\":r.reportError(28,`- ${pe.pretty(t,a,pe.Type.REMOVED)}`);break;case\"insertion\":r.reportError(28,`+ ${pe.pretty(t,a,pe.Type.ADDED)}`);break;default:Ge.assertNever(s.type)}}var rP=class{supports(t,r){return!!Qg(t)}getLocalPath(t,r){return null}async fetch(t,r){let s=r.checksums.get(t.locatorHash)||null,[a,n,c]=await r.cache.fetchPackageFromCache(t,s,{onHit:()=>r.report.reportCacheHit(t),onMiss:()=>r.report.reportCacheMiss(t,`${j.prettyLocator(r.project.configuration,t)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.patchPackage(t,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:j.getIdentVendorPath(t),localPath:this.getLocalPath(t,r),checksum:c}}async patchPackage(t,r){let{parentLocator:s,sourceLocator:a,sourceVersion:n,patchPaths:c}=eP(t),f=await tP(s,c,r),p=await le.mktempPromise(),h=K.join(p,\"current.zip\"),E=await r.fetcher.fetch(a,r),C=j.getIdentVendorPath(t),S=new ps(h,{create:!0,level:r.project.configuration.get(\"compressionLevel\")});await Ge.releaseAfterUseAsync(async()=>{await S.copyPromise(C,E.prefixPath,{baseFs:E.packageFs,stableSort:!0})},E.releaseFs),S.saveAndClose();for(let{source:x,optional:I}of f){if(x===null)continue;let T=new ps(h,{level:r.project.configuration.get(\"compressionLevel\")}),O=new bn(K.resolve(vt.root,C),{baseFs:T});try{await mL(Xb(x),{baseFs:O,version:n})}catch(U){if(!(U instanceof x1))throw U;let Y=r.project.configuration.get(\"enableInlineHunks\"),te=!Y&&!I?\" (set enableInlineHunks for details)\":\"\",ie=`${j.prettyLocator(r.project.configuration,t)}: ${U.message}${te}`,ue=ae=>{Y&&Gbe(U.hunk,{configuration:r.project.configuration,report:ae})};if(T.discardAndClose(),I){r.report.reportWarningOnce(66,ie,{reportExtra:ue});continue}else throw new _t(66,ie,ue)}T.saveAndClose()}return new ps(h,{level:r.project.configuration.get(\"compressionLevel\")})}};qe();var nP=class{supportsDescriptor(t,r){return!!yL(t)}supportsLocator(t,r){return!!Qg(t)}shouldPersistResolution(t,r){return!1}bindDescriptor(t,r,s){let{patchPaths:a}=$b(t);return a.every(n=>!uJ(n))?t:j.bindDescriptor(t,{locator:j.stringifyLocator(r)})}getResolutionDependencies(t,r){let{sourceDescriptor:s}=$b(t);return{sourceDescriptor:r.project.configuration.normalizeDependency(s)}}async getCandidates(t,r,s){if(!s.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{parentLocator:a,patchPaths:n}=$b(t),c=await tP(a,n,s.fetchOptions),f=r.sourceDescriptor;if(typeof f>\"u\")throw new Error(\"Assertion failed: The dependency should have been resolved\");let p=pJ(c,f.version);return[cJ(t,{parentLocator:a,sourcePackage:f,patchPaths:n,patchHash:p})]}async getSatisfying(t,r,s,a){let[n]=await this.getCandidates(t,r,a);return{locators:s.filter(c=>c.locatorHash===n.locatorHash),sorted:!1}}async resolve(t,r){let{sourceLocator:s}=eP(t);return{...await r.resolver.resolve(s,r),...t}}};qe();Dt();Vt();var R1=class extends At{constructor(){super(...arguments);this.save=he.Boolean(\"-s,--save\",!1,{description:\"Add the patch to your resolution entries\"});this.patchFolder=he.String()}static{this.paths=[[\"patch-commit\"]]}static{this.usage=at.Usage({description:\"generate a patch out of a directory\",details:\"\\n      By default, this will print a patchfile on stdout based on the diff between the folder passed in and the original version of the package. Such file is suitable for consumption with the `patch:` protocol.\\n\\n      With the `-s,--save` option set, the patchfile won't be printed on stdout anymore and will instead be stored within a local file (by default kept within `.yarn/patches`, but configurable via the `patchFolder` setting). A `resolutions` entry will also be added to your top-level manifest, referencing the patched package via the `patch:` protocol.\\n\\n      Note that only folders generated by `yarn patch` are accepted as valid input for `yarn patch-commit`.\\n    \"})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState();let n=K.resolve(this.context.cwd,fe.toPortablePath(this.patchFolder)),c=K.join(n,\"../source\"),f=K.join(n,\"../.yarn-patch.json\");if(!le.existsSync(c))throw new st(\"The argument folder didn't get created by 'yarn patch'\");let p=await AJ(c,n),h=await le.readJsonPromise(f),E=j.parseLocator(h.locator,!0);if(!s.storedPackages.has(E.locatorHash))throw new st(\"No package found in the project for the given locator\");if(!this.save){this.context.stdout.write(p);return}let C=r.get(\"patchFolder\"),S=K.join(C,`${j.slugifyLocator(E)}.patch`);await le.mkdirPromise(C,{recursive:!0}),await le.writeFilePromise(S,p);let x=[],I=new Map;for(let T of s.storedPackages.values()){if(j.isVirtualLocator(T))continue;let O=T.dependencies.get(E.identHash);if(!O)continue;let U=j.ensureDevirtualizedDescriptor(O),Y=lJ(U),te=s.storedResolutions.get(Y.descriptorHash);if(!te)throw new Error(\"Assertion failed: Expected the resolution to have been registered\");if(!s.storedPackages.get(te))throw new Error(\"Assertion failed: Expected the package to have been registered\");let ue=s.tryWorkspaceByLocator(T);if(ue)x.push(ue);else{let ae=s.originalPackages.get(T.locatorHash);if(!ae)throw new Error(\"Assertion failed: Expected the original package to have been registered\");let de=ae.dependencies.get(O.identHash);if(!de)throw new Error(\"Assertion failed: Expected the original dependency to have been registered\");I.set(de.descriptorHash,de)}}for(let T of x)for(let O of Ut.hardDependencies){let U=T.manifest[O].get(E.identHash);if(!U)continue;let Y=IL(U,{parentLocator:null,sourceDescriptor:j.convertLocatorToDescriptor(E),patchPaths:[K.join(Er.home,K.relative(s.cwd,S))]});T.manifest[O].set(U.identHash,Y)}for(let T of I.values()){let O=IL(T,{parentLocator:null,sourceDescriptor:j.convertLocatorToDescriptor(E),patchPaths:[K.join(Er.home,K.relative(s.cwd,S))]});s.topLevelWorkspace.manifest.resolutions.push({pattern:{descriptor:{fullName:j.stringifyIdent(O),description:T.range}},reference:O.range})}await s.persist()}};qe();Dt();Vt();var T1=class extends At{constructor(){super(...arguments);this.update=he.Boolean(\"-u,--update\",!1,{description:\"Reapply local patches that already apply to this packages\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.package=he.String()}static{this.paths=[[\"patch\"]]}static{this.usage=at.Usage({description:\"prepare a package for patching\",details:\"\\n      This command will cause a package to be extracted in a temporary directory intended to be editable at will.\\n\\n      Once you're done with your changes, run `yarn patch-commit -s path` (with `path` being the temporary directory you received) to generate a patchfile and register it into your top-level manifest via the `patch:` protocol. Run `yarn patch-commit -h` for more details.\\n\\n      Calling the command when you already have a patch won't import it by default (in other words, the default behavior is to reset existing patches). However, adding the `-u,--update` flag will import any current patch.\\n    \"})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState();let c=j.parseLocator(this.package);if(c.reference===\"unknown\"){let f=Ge.mapAndFilter([...s.storedPackages.values()],p=>p.identHash!==c.identHash?Ge.mapAndFilter.skip:j.isVirtualLocator(p)?Ge.mapAndFilter.skip:Qg(p)!==this.update?Ge.mapAndFilter.skip:p);if(f.length===0)throw new st(\"No package found in the project for the given locator\");if(f.length>1)throw new st(`Multiple candidate packages found; explicitly choose one of them (use \\`yarn why <package>\\` to get more information as to who depends on them):\n${f.map(p=>`\n- ${j.prettyLocator(r,p)}`).join(\"\")}`);c=f[0]}if(!s.storedPackages.has(c.locatorHash))throw new st(\"No package found in the project for the given locator\");await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async f=>{let p=EL(c),h=await fJ(c,{cache:n,project:s});f.reportJson({locator:j.stringifyLocator(p),path:fe.fromPortablePath(h)});let E=this.update?\" along with its current modifications\":\"\";f.reportInfo(0,`Package ${j.prettyLocator(r,p)} got extracted with success${E}!`),f.reportInfo(0,`You can now edit the following folder: ${pe.pretty(r,fe.fromPortablePath(h),\"magenta\")}`),f.reportInfo(0,`Once you are done run ${pe.pretty(r,`yarn patch-commit -s ${process.platform===\"win32\"?'\"':\"\"}${fe.fromPortablePath(h)}${process.platform===\"win32\"?'\"':\"\"}`,\"cyan\")} and Yarn will store a patchfile based on your changes.`)})}};var $vt={configuration:{enableInlineHunks:{description:\"If true, the installs will print unmatched patch hunks\",type:\"BOOLEAN\",default:!1},patchFolder:{description:\"Folder where the patch files must be written\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/patches\"}},commands:[R1,T1],fetchers:[rP],resolvers:[nP]},eSt=$vt;var mJ={};Yt(mJ,{PnpmLinker:()=>iP,default:()=>oSt});qe();Dt();Vt();var iP=class{getCustomDataKey(){return JSON.stringify({name:\"PnpmLinker\",version:3})}supportsPackage(t,r){return this.isEnabled(r)}async findPackageLocation(t,r){if(!this.isEnabled(r))throw new Error(\"Assertion failed: Expected the pnpm linker to be enabled\");let s=this.getCustomDataKey(),a=r.project.linkersCustomData.get(s);if(!a)throw new st(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=a.pathsByLocator.get(t.locatorHash);if(typeof n>\"u\")throw new st(`Couldn't find ${j.prettyLocator(r.project.configuration,t)} in the currently installed pnpm map - running an install might help`);return n.packageLocation}async findPackageLocator(t,r){if(!this.isEnabled(r))return null;let s=this.getCustomDataKey(),a=r.project.linkersCustomData.get(s);if(!a)throw new st(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=t.match(/(^.*\\/node_modules\\/(@[^/]*\\/)?[^/]+)(\\/.*$)/);if(n){let p=a.locatorByPath.get(n[1]);if(p)return p}let c=t,f=t;do{f=c,c=K.dirname(f);let p=a.locatorByPath.get(f);if(p)return p}while(c!==f);return null}makeInstaller(t){return new gJ(t)}isEnabled(t){return t.project.configuration.get(\"nodeLinker\")===\"pnpm\"}},gJ=class{constructor(t){this.opts=t;this.asyncActions=new Ge.AsyncActions(10);this.customData={pathsByLocator:new Map,locatorByPath:new Map};this.indexFolderPromise=$P(le,{indexPath:K.join(t.project.configuration.get(\"globalFolder\"),\"index\")})}attachCustomData(t){}async installPackage(t,r,s){switch(t.linkType){case\"SOFT\":return this.installPackageSoft(t,r,s);case\"HARD\":return this.installPackageHard(t,r,s)}throw new Error(\"Assertion failed: Unsupported package link type\")}async installPackageSoft(t,r,s){let a=K.resolve(r.packageFs.getRealPath(),r.prefixPath),n=this.opts.project.tryWorkspaceByLocator(t)?K.join(a,Er.nodeModules):null;return this.customData.pathsByLocator.set(t.locatorHash,{packageLocation:a,dependenciesLocation:n}),{packageLocation:a,buildRequest:null}}async installPackageHard(t,r,s){let a=rSt(t,{project:this.opts.project}),n=a.packageLocation;this.customData.locatorByPath.set(n,j.stringifyLocator(t)),this.customData.pathsByLocator.set(t.locatorHash,a),s.holdFetchResult(this.asyncActions.set(t.locatorHash,async()=>{await le.mkdirPromise(n,{recursive:!0}),await le.copyPromise(n,r.prefixPath,{baseFs:r.packageFs,overwrite:!1,linkStrategy:{type:\"HardlinkFromIndex\",indexPath:await this.indexFolderPromise,autoRepair:!0}})}));let f=j.isVirtualLocator(t)?j.devirtualizeLocator(t):t,p={manifest:await Ut.tryFind(r.prefixPath,{baseFs:r.packageFs})??new Ut,misc:{hasBindingGyp:dA.hasBindingGyp(r)}},h=this.opts.project.getDependencyMeta(f,t.version),E=dA.extractBuildRequest(t,p,h,{configuration:this.opts.project.configuration});return{packageLocation:n,buildRequest:E}}async attachInternalDependencies(t,r){if(this.opts.project.configuration.get(\"nodeLinker\")!==\"pnpm\"||!qbe(t,{project:this.opts.project}))return;let s=this.customData.pathsByLocator.get(t.locatorHash);if(typeof s>\"u\")throw new Error(`Assertion failed: Expected the package to have been registered (${j.stringifyLocator(t)})`);let{dependenciesLocation:a}=s;a&&this.asyncActions.reduce(t.locatorHash,async n=>{await le.mkdirPromise(a,{recursive:!0});let c=await nSt(a),f=new Map(c),p=[n],h=(C,S)=>{let x=S;qbe(S,{project:this.opts.project})||(this.opts.report.reportWarningOnce(0,\"The pnpm linker doesn't support providing different versions to workspaces' peer dependencies\"),x=j.devirtualizeLocator(S));let I=this.customData.pathsByLocator.get(x.locatorHash);if(typeof I>\"u\")throw new Error(`Assertion failed: Expected the package to have been registered (${j.stringifyLocator(S)})`);let T=j.stringifyIdent(C),O=K.join(a,T),U=K.relative(K.dirname(O),I.packageLocation),Y=f.get(T);f.delete(T),p.push(Promise.resolve().then(async()=>{if(Y){if(Y.isSymbolicLink()&&await le.readlinkPromise(O)===U)return;await le.removePromise(O)}await le.mkdirpPromise(K.dirname(O)),process.platform==\"win32\"&&this.opts.project.configuration.get(\"winLinkType\")===\"junctions\"?await le.symlinkPromise(I.packageLocation,O,\"junction\"):await le.symlinkPromise(U,O)}))},E=!1;for(let[C,S]of r)C.identHash===t.identHash&&(E=!0),h(C,S);!E&&!this.opts.project.tryWorkspaceByLocator(t)&&h(j.convertLocatorToDescriptor(t),t),p.push(iSt(a,f)),await Promise.all(p)})}async attachExternalDependents(t,r){throw new Error(\"External dependencies haven't been implemented for the pnpm linker\")}async finalizeInstall(){let t=Wbe(this.opts.project);if(this.opts.project.configuration.get(\"nodeLinker\")!==\"pnpm\")await le.removePromise(t);else{let r;try{r=new Set(await le.readdirPromise(t))}catch{r=new Set}for(let{dependenciesLocation:s}of this.customData.pathsByLocator.values()){if(!s)continue;let a=K.contains(t,s);if(a===null)continue;let[n]=a.split(K.sep);r.delete(n)}await Promise.all([...r].map(async s=>{await le.removePromise(K.join(t,s))}))}return await this.asyncActions.wait(),await dJ(t),this.opts.project.configuration.get(\"nodeLinker\")!==\"node-modules\"&&await dJ(tSt(this.opts.project)),{customData:this.customData}}};function tSt(e){return K.join(e.cwd,Er.nodeModules)}function Wbe(e){return e.configuration.get(\"pnpmStoreFolder\")}function rSt(e,{project:t}){let r=j.slugifyLocator(e),s=Wbe(t),a=K.join(s,r,\"package\"),n=K.join(s,r,Er.nodeModules);return{packageLocation:a,dependenciesLocation:n}}function qbe(e,{project:t}){return!j.isVirtualLocator(e)||!t.tryWorkspaceByLocator(e)}async function nSt(e){let t=new Map,r=[];try{r=await le.readdirPromise(e,{withFileTypes:!0})}catch(s){if(s.code!==\"ENOENT\")throw s}try{for(let s of r)if(!s.name.startsWith(\".\"))if(s.name.startsWith(\"@\")){let a=await le.readdirPromise(K.join(e,s.name),{withFileTypes:!0});if(a.length===0)t.set(s.name,s);else for(let n of a)t.set(`${s.name}/${n.name}`,n)}else t.set(s.name,s)}catch(s){if(s.code!==\"ENOENT\")throw s}return t}async function iSt(e,t){let r=[],s=new Set;for(let a of t.keys()){r.push(le.removePromise(K.join(e,a)));let n=j.tryParseIdent(a)?.scope;n&&s.add(`@${n}`)}return Promise.all(r).then(()=>Promise.all([...s].map(a=>dJ(K.join(e,a)))))}async function dJ(e){try{await le.rmdirPromise(e)}catch(t){if(t.code!==\"ENOENT\"&&t.code!==\"ENOTEMPTY\"&&t.code!==\"EBUSY\")throw t}}var sSt={configuration:{pnpmStoreFolder:{description:\"By default, the store is stored in the 'node_modules/.store' of the project. Sometimes in CI scenario's it is convenient to store this in a different location so it can be cached and reused.\",type:\"ABSOLUTE_PATH\",default:\"./node_modules/.store\"}},linkers:[iP]},oSt=sSt;var vJ={};Yt(vJ,{StageCommand:()=>F1,default:()=>mSt,stageUtils:()=>wL});qe();Dt();Vt();qe();Dt();var wL={};Yt(wL,{ActionType:()=>yJ,checkConsensus:()=>CL,expandDirectory:()=>CJ,findConsensus:()=>wJ,findVcsRoot:()=>EJ,genCommitMessage:()=>BJ,getCommitPrefix:()=>Vbe,isYarnFile:()=>IJ});Dt();var yJ=(n=>(n[n.CREATE=0]=\"CREATE\",n[n.DELETE=1]=\"DELETE\",n[n.ADD=2]=\"ADD\",n[n.REMOVE=3]=\"REMOVE\",n[n.MODIFY=4]=\"MODIFY\",n))(yJ||{});async function EJ(e,{marker:t}){do if(!le.existsSync(K.join(e,t)))e=K.dirname(e);else return e;while(e!==\"/\");return null}function IJ(e,{roots:t,names:r}){if(r.has(K.basename(e)))return!0;do if(!t.has(e))e=K.dirname(e);else return!0;while(e!==\"/\");return!1}function CJ(e){let t=[],r=[e];for(;r.length>0;){let s=r.pop(),a=le.readdirSync(s);for(let n of a){let c=K.resolve(s,n);le.lstatSync(c).isDirectory()?r.push(c):t.push(c)}}return t}function CL(e,t){let r=0,s=0;for(let a of e)a!==\"wip\"&&(t.test(a)?r+=1:s+=1);return r>=s}function wJ(e){let t=CL(e,/^(\\w\\(\\w+\\):\\s*)?\\w+s/),r=CL(e,/^(\\w\\(\\w+\\):\\s*)?[A-Z]/),s=CL(e,/^\\w\\(\\w+\\):/);return{useThirdPerson:t,useUpperCase:r,useComponent:s}}function Vbe(e){return e.useComponent?\"chore(yarn): \":\"\"}var aSt=new Map([[0,\"create\"],[1,\"delete\"],[2,\"add\"],[3,\"remove\"],[4,\"update\"]]);function BJ(e,t){let r=Vbe(e),s=[],a=t.slice().sort((n,c)=>n[0]-c[0]);for(;a.length>0;){let[n,c]=a.shift(),f=aSt.get(n);e.useUpperCase&&s.length===0&&(f=`${f[0].toUpperCase()}${f.slice(1)}`),e.useThirdPerson&&(f+=\"s\");let p=[c];for(;a.length>0&&a[0][0]===n;){let[,E]=a.shift();p.push(E)}p.sort();let h=p.shift();p.length===1?h+=\" (and one other)\":p.length>1&&(h+=` (and ${p.length} others)`),s.push(`${f} ${h}`)}return`${r}${s.join(\", \")}`}var lSt=\"Commit generated via `yarn stage`\",cSt=11;async function Ybe(e){let{code:t,stdout:r}=await qr.execvp(\"git\",[\"log\",\"-1\",\"--pretty=format:%H\"],{cwd:e});return t===0?r.trim():null}async function uSt(e,t){let r=[],s=t.filter(h=>K.basename(h.path)===\"package.json\");for(let{action:h,path:E}of s){let C=K.relative(e,E);if(h===4){let S=await Ybe(e),{stdout:x}=await qr.execvp(\"git\",[\"show\",`${S}:${C}`],{cwd:e,strict:!0}),I=await Ut.fromText(x),T=await Ut.fromFile(E),O=new Map([...T.dependencies,...T.devDependencies]),U=new Map([...I.dependencies,...I.devDependencies]);for(let[Y,te]of U){let ie=j.stringifyIdent(te),ue=O.get(Y);ue?ue.range!==te.range&&r.push([4,`${ie} to ${ue.range}`]):r.push([3,ie])}for(let[Y,te]of O)U.has(Y)||r.push([2,j.stringifyIdent(te)])}else if(h===0){let S=await Ut.fromFile(E);S.name?r.push([0,j.stringifyIdent(S.name)]):r.push([0,\"a package\"])}else if(h===1){let S=await Ybe(e),{stdout:x}=await qr.execvp(\"git\",[\"show\",`${S}:${C}`],{cwd:e,strict:!0}),I=await Ut.fromText(x);I.name?r.push([1,j.stringifyIdent(I.name)]):r.push([1,\"a package\"])}else throw new Error(\"Assertion failed: Unsupported action type\")}let{code:a,stdout:n}=await qr.execvp(\"git\",[\"log\",`-${cSt}`,\"--pretty=format:%s\"],{cwd:e}),c=a===0?n.split(/\\n/g).filter(h=>h!==\"\"):[],f=wJ(c);return BJ(f,r)}var fSt={0:[\" A \",\"?? \"],4:[\" M \"],1:[\" D \"]},ASt={0:[\"A  \"],4:[\"M  \"],1:[\"D  \"]},Kbe={async findRoot(e){return await EJ(e,{marker:\".git\"})},async filterChanges(e,t,r,s){let{stdout:a}=await qr.execvp(\"git\",[\"status\",\"-s\"],{cwd:e,strict:!0}),n=a.toString().split(/\\n/g),c=s?.staged?ASt:fSt;return[].concat(...n.map(p=>{if(p===\"\")return[];let h=p.slice(0,3),E=K.resolve(e,p.slice(3));if(!s?.staged&&h===\"?? \"&&p.endsWith(\"/\"))return CJ(E).map(C=>({action:0,path:C}));{let S=[0,4,1].find(x=>c[x].includes(h));return S!==void 0?[{action:S,path:E}]:[]}})).filter(p=>IJ(p.path,{roots:t,names:r}))},async genCommitMessage(e,t){return await uSt(e,t)},async makeStage(e,t){let r=t.map(s=>fe.fromPortablePath(s.path));await qr.execvp(\"git\",[\"add\",\"--\",...r],{cwd:e,strict:!0})},async makeCommit(e,t,r){let s=t.map(a=>fe.fromPortablePath(a.path));await qr.execvp(\"git\",[\"add\",\"-N\",\"--\",...s],{cwd:e,strict:!0}),await qr.execvp(\"git\",[\"commit\",\"-m\",`${r}\n\n${lSt}\n`,\"--\",...s],{cwd:e,strict:!0})},async makeReset(e,t){let r=t.map(s=>fe.fromPortablePath(s.path));await qr.execvp(\"git\",[\"reset\",\"HEAD\",\"--\",...r],{cwd:e,strict:!0})}};var pSt=[Kbe],F1=class extends At{constructor(){super(...arguments);this.commit=he.Boolean(\"-c,--commit\",!1,{description:\"Commit the staged files\"});this.reset=he.Boolean(\"-r,--reset\",!1,{description:\"Remove all files from the staging area\"});this.dryRun=he.Boolean(\"-n,--dry-run\",!1,{description:\"Print the commit message and the list of modified files without staging / committing\"});this.update=he.Boolean(\"-u,--update\",!1,{hidden:!0})}static{this.paths=[[\"stage\"]]}static{this.usage=at.Usage({description:\"add all yarn files to your vcs\",details:\"\\n      This command will add to your staging area the files belonging to Yarn (typically any modified `package.json` and `.yarnrc.yml` files, but also linker-generated files, cache data, etc). It will take your ignore list into account, so the cache files won't be added if the cache is ignored in a `.gitignore` file (assuming you use Git).\\n\\n      Running `--reset` will instead remove them from the staging area (the changes will still be there, but won't be committed until you stage them back).\\n\\n      Since the staging area is a non-existent concept in Mercurial, Yarn will always create a new commit when running this command on Mercurial repositories. You can get this behavior when using Git by using the `--commit` flag which will directly create a commit.\\n    \",examples:[[\"Adds all modified project files to the staging area\",\"yarn stage\"],[\"Creates a new commit containing all modified project files\",\"yarn stage --commit\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s}=await Rt.find(r,this.context.cwd),{driver:a,root:n}=await hSt(s.cwd),c=[r.get(\"cacheFolder\"),r.get(\"globalFolder\"),r.get(\"virtualFolder\"),r.get(\"yarnPath\")];await r.triggerHook(C=>C.populateYarnPaths,s,C=>{c.push(C)});let f=new Set;for(let C of c)for(let S of gSt(n,C))f.add(S);let p=new Set([r.get(\"rcFilename\"),Er.lockfile,Er.manifest]),h=await a.filterChanges(n,f,p),E=await a.genCommitMessage(n,h);if(this.dryRun)if(this.commit)this.context.stdout.write(`${E}\n`);else for(let C of h)this.context.stdout.write(`${fe.fromPortablePath(C.path)}\n`);else if(this.reset){let C=await a.filterChanges(n,f,p,{staged:!0});C.length===0?this.context.stdout.write(\"No staged changes found!\"):await a.makeReset(n,C)}else h.length===0?this.context.stdout.write(\"No changes found!\"):this.commit?await a.makeCommit(n,h,E):(await a.makeStage(n,h),this.context.stdout.write(E))}};async function hSt(e){let t=null,r=null;for(let s of pSt)if((r=await s.findRoot(e))!==null){t=s;break}if(t===null||r===null)throw new st(\"No stage driver has been found for your current project\");return{driver:t,root:r}}function gSt(e,t){let r=[];if(t===null)return r;for(;;){(t===e||t.startsWith(`${e}/`))&&r.push(t);let s;try{s=le.statSync(t)}catch{break}if(s.isSymbolicLink())t=K.resolve(K.dirname(t),le.readlinkSync(t));else break}return r}var dSt={commands:[F1]},mSt=dSt;var SJ={};Yt(SJ,{default:()=>SSt});qe();qe();Dt();var Zbe=et(pi());qe();var Jbe=et(Rq()),ySt=\"e8e1bd300d860104bb8c58453ffa1eb4\",ESt=\"OFCNCOG2CU\",zbe=async(e,t)=>{let r=j.stringifyIdent(e),a=ISt(t).initIndex(\"npm-search\");try{return(await a.getObject(r,{attributesToRetrieve:[\"types\"]})).types?.ts===\"definitely-typed\"}catch{return!1}},ISt=e=>(0,Jbe.default)(ESt,ySt,{requester:{async send(r){try{let s=await nn.request(r.url,r.data||null,{configuration:e,headers:r.headers});return{content:s.body,isTimedOut:!1,status:s.statusCode}}catch(s){return{content:s.response.body,isTimedOut:!1,status:s.response.statusCode}}}}});var Xbe=e=>e.scope?`${e.scope}__${e.name}`:`${e.name}`,CSt=async(e,t,r,s)=>{if(r.scope===\"types\")return;let{project:a}=e,{configuration:n}=a;if(!(n.get(\"tsEnableAutoTypes\")??(le.existsSync(K.join(e.cwd,\"tsconfig.json\"))||le.existsSync(K.join(a.cwd,\"tsconfig.json\")))))return;let f=n.makeResolver(),p={project:a,resolver:f,report:new ki};if(!await zbe(r,n))return;let E=Xbe(r),C=j.parseRange(r.range).selector;if(!Fr.validRange(C)){let O=n.normalizeDependency(r),U=await f.getCandidates(O,{},p);C=j.parseRange(U[0].reference).selector}let S=Zbe.default.coerce(C);if(S===null)return;let x=`${$u.Modifier.CARET}${S.major}`,I=j.makeDescriptor(j.makeIdent(\"types\",E),x),T=Ge.mapAndFind(a.workspaces,O=>{let U=O.manifest.dependencies.get(r.identHash)?.descriptorHash,Y=O.manifest.devDependencies.get(r.identHash)?.descriptorHash;if(U!==r.descriptorHash&&Y!==r.descriptorHash)return Ge.mapAndFind.skip;let te=[];for(let ie of Ut.allDependencies){let ue=O.manifest[ie].get(I.identHash);typeof ue>\"u\"||te.push([ie,ue])}return te.length===0?Ge.mapAndFind.skip:te});if(typeof T<\"u\")for(let[O,U]of T)e.manifest[O].set(U.identHash,U);else{try{let O=n.normalizeDependency(I);if((await f.getCandidates(O,{},p)).length===0)return}catch{return}e.manifest[$u.Target.DEVELOPMENT].set(I.identHash,I)}},wSt=async(e,t,r)=>{if(r.scope===\"types\")return;let{project:s}=e,{configuration:a}=s;if(!(a.get(\"tsEnableAutoTypes\")??(le.existsSync(K.join(e.cwd,\"tsconfig.json\"))||le.existsSync(K.join(s.cwd,\"tsconfig.json\")))))return;let c=Xbe(r),f=j.makeIdent(\"types\",c);for(let p of Ut.allDependencies)typeof e.manifest[p].get(f.identHash)>\"u\"||e.manifest[p].delete(f.identHash)},BSt=(e,t)=>{t.publishConfig&&t.publishConfig.typings&&(t.typings=t.publishConfig.typings),t.publishConfig&&t.publishConfig.types&&(t.types=t.publishConfig.types)},vSt={configuration:{tsEnableAutoTypes:{description:\"Whether Yarn should auto-install @types/ dependencies on 'yarn add'\",type:\"BOOLEAN\",isNullable:!0,default:null}},hooks:{afterWorkspaceDependencyAddition:CSt,afterWorkspaceDependencyRemoval:wSt,beforeWorkspacePacking:BSt}},SSt=vSt;var kJ={};Yt(kJ,{VersionApplyCommand:()=>M1,VersionCheckCommand:()=>U1,VersionCommand:()=>_1,default:()=>kSt,versionUtils:()=>L1});qe();qe();Vt();var L1={};Yt(L1,{Decision:()=>N1,applyPrerelease:()=>$be,applyReleases:()=>xJ,applyStrategy:()=>sP,clearVersionFiles:()=>DJ,getUndecidedDependentWorkspaces:()=>aP,getUndecidedWorkspaces:()=>BL,openVersionFile:()=>O1,requireMoreDecisions:()=>bSt,resolveVersionFiles:()=>oP,suggestStrategy:()=>PJ,updateVersionFiles:()=>bJ,validateReleaseDecision:()=>Ey});qe();Dt();Bc();Vt();Jl();var QA=et(pi()),DSt=/^(>=|[~^]|)(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$/,N1=(h=>(h.UNDECIDED=\"undecided\",h.DECLINE=\"decline\",h.MAJOR=\"major\",h.MINOR=\"minor\",h.PATCH=\"patch\",h.PREMAJOR=\"premajor\",h.PREMINOR=\"preminor\",h.PREPATCH=\"prepatch\",h.PRERELEASE=\"prerelease\",h))(N1||{});function Ey(e){let t=QA.default.valid(e);return t||Ge.validateEnum(I4(N1,\"UNDECIDED\"),e)}async function oP(e,{prerelease:t=null}={}){let r=new Map,s=e.configuration.get(\"deferredVersionFolder\");if(!le.existsSync(s))return r;let a=await le.readdirPromise(s);for(let n of a){if(!n.endsWith(\".yml\"))continue;let c=K.join(s,n),f=await le.readFilePromise(c,\"utf8\"),p=cs(f);for(let[h,E]of Object.entries(p.releases||{})){if(E===\"decline\")continue;let C=j.parseIdent(h),S=e.tryWorkspaceByIdent(C);if(S===null)throw new Error(`Assertion failed: Expected a release definition file to only reference existing workspaces (${K.basename(c)} references ${h})`);if(S.manifest.version===null)throw new Error(`Assertion failed: Expected the workspace to have a version (${j.prettyLocator(e.configuration,S.anchoredLocator)})`);let x=S.manifest.raw.stableVersion??S.manifest.version,I=r.get(S),T=sP(E===\"prerelease\"?S.manifest.version:x,Ey(E));if(T===null)throw new Error(`Assertion failed: Expected ${x} to support being bumped via strategy ${E}`);let O=typeof I<\"u\"?QA.default.gt(T,I)?T:I:T;r.set(S,O)}}return t&&(r=new Map([...r].map(([n,c])=>[n,$be(c,{current:n.manifest.version,prerelease:t})]))),r}async function DJ(e){let t=e.configuration.get(\"deferredVersionFolder\");le.existsSync(t)&&await le.removePromise(t)}async function bJ(e,t){let r=new Set(t),s=e.configuration.get(\"deferredVersionFolder\");if(!le.existsSync(s))return;let a=await le.readdirPromise(s);for(let n of a){if(!n.endsWith(\".yml\"))continue;let c=K.join(s,n),f=await le.readFilePromise(c,\"utf8\"),p=cs(f),h=p?.releases;if(h){for(let E of Object.keys(h)){let C=j.parseIdent(E),S=e.tryWorkspaceByIdent(C);(S===null||r.has(S))&&delete p.releases[E]}Object.keys(p.releases).length>0?await le.changeFilePromise(c,cl(new cl.PreserveOrdering(p))):await le.unlinkPromise(c)}}}async function O1(e,{allowEmpty:t=!1}={}){let r=e.configuration;if(r.projectCwd===null)throw new st(\"This command can only be run from within a Yarn project\");let s=await Oa.fetchRoot(r.projectCwd),a=s!==null?await Oa.fetchBase(s,{baseRefs:r.get(\"changesetBaseRefs\")}):null,n=s!==null?await Oa.fetchChangedFiles(s,{base:a.hash,project:e}):[],c=r.get(\"deferredVersionFolder\"),f=n.filter(x=>K.contains(c,x)!==null);if(f.length>1)throw new st(`Your current branch contains multiple versioning files; this isn't supported:\n- ${f.map(x=>fe.fromPortablePath(x)).join(`\n- `)}`);let p=new Set(Ge.mapAndFilter(n,x=>{let I=e.tryWorkspaceByFilePath(x);return I===null?Ge.mapAndFilter.skip:I}));if(f.length===0&&p.size===0&&!t)return null;let h=f.length===1?f[0]:K.join(c,`${Ln.makeHash(Math.random().toString()).slice(0,8)}.yml`),E=le.existsSync(h)?await le.readFilePromise(h,\"utf8\"):\"{}\",C=cs(E),S=new Map;for(let x of C.declined||[]){let I=j.parseIdent(x),T=e.getWorkspaceByIdent(I);S.set(T,\"decline\")}for(let[x,I]of Object.entries(C.releases||{})){let T=j.parseIdent(x),O=e.getWorkspaceByIdent(T);S.set(O,Ey(I))}return{project:e,root:s,baseHash:a!==null?a.hash:null,baseTitle:a!==null?a.title:null,changedFiles:new Set(n),changedWorkspaces:p,releaseRoots:new Set([...p].filter(x=>x.manifest.version!==null)),releases:S,async saveAll(){let x={},I=[],T=[];for(let O of e.workspaces){if(O.manifest.version===null)continue;let U=j.stringifyIdent(O.anchoredLocator),Y=S.get(O);Y===\"decline\"?I.push(U):typeof Y<\"u\"?x[U]=Ey(Y):p.has(O)&&T.push(U)}await le.mkdirPromise(K.dirname(h),{recursive:!0}),await le.changeFilePromise(h,cl(new cl.PreserveOrdering({releases:Object.keys(x).length>0?x:void 0,declined:I.length>0?I:void 0,undecided:T.length>0?T:void 0})))}}}function bSt(e){return BL(e).size>0||aP(e).length>0}function BL(e){let t=new Set;for(let r of e.changedWorkspaces)r.manifest.version!==null&&(e.releases.has(r)||t.add(r));return t}function aP(e,{include:t=new Set}={}){let r=[],s=new Map(Ge.mapAndFilter([...e.releases],([n,c])=>c===\"decline\"?Ge.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n])),a=new Map(Ge.mapAndFilter([...e.releases],([n,c])=>c!==\"decline\"?Ge.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n]));for(let n of e.project.workspaces)if(!(!t.has(n)&&(a.has(n.anchoredLocator.locatorHash)||s.has(n.anchoredLocator.locatorHash)))&&n.manifest.version!==null)for(let c of Ut.hardDependencies)for(let f of n.manifest.getForScope(c).values()){let p=e.project.tryWorkspaceByDescriptor(f);p!==null&&s.has(p.anchoredLocator.locatorHash)&&r.push([n,p])}return r}function PJ(e,t){let r=QA.default.clean(t);for(let s of Object.values(N1))if(s!==\"undecided\"&&s!==\"decline\"&&QA.default.inc(e,s)===r)return s;return null}function sP(e,t){if(QA.default.valid(t))return t;if(e===null)throw new st(`Cannot apply the release strategy \"${t}\" unless the workspace already has a valid version`);if(!QA.default.valid(e))throw new st(`Cannot apply the release strategy \"${t}\" on a non-semver version (${e})`);let r=QA.default.inc(e,t);if(r===null)throw new st(`Cannot apply the release strategy \"${t}\" on the specified version (${e})`);return r}function xJ(e,t,{report:r,exact:s}){let a=new Map;for(let n of e.workspaces)for(let c of Ut.allDependencies)for(let f of n.manifest[c].values()){let p=e.tryWorkspaceByDescriptor(f);if(p===null||!t.has(p))continue;Ge.getArrayWithDefault(a,p).push([n,c,f.identHash])}for(let[n,c]of t){let f=n.manifest.version;n.manifest.version=c,QA.default.prerelease(c)===null?delete n.manifest.raw.stableVersion:n.manifest.raw.stableVersion||(n.manifest.raw.stableVersion=f);let p=n.manifest.name!==null?j.stringifyIdent(n.manifest.name):null;r.reportInfo(0,`${j.prettyLocator(e.configuration,n.anchoredLocator)}: Bumped to ${c}`),r.reportJson({cwd:fe.fromPortablePath(n.cwd),ident:p,oldVersion:f,newVersion:c});let h=a.get(n);if(!(typeof h>\"u\"))for(let[E,C,S]of h){let x=E.manifest[C].get(S);if(typeof x>\"u\")throw new Error(\"Assertion failed: The dependency should have existed\");let I=x.range,T=!1;if(I.startsWith(Ii.protocol)&&(I=I.slice(Ii.protocol.length),T=!0,I===n.relativeCwd))continue;let O=I.match(DSt);if(!O){r.reportWarning(0,`Couldn't auto-upgrade range ${I} (in ${j.prettyLocator(e.configuration,E.anchoredLocator)})`);continue}let U=s?`${c}`:`${O[1]}${c}`;T&&(U=`${Ii.protocol}${U}`);let Y=j.makeDescriptor(x,U);E.manifest[C].set(S,Y)}}}var PSt=new Map([[\"%n\",{extract:e=>e.length>=1?[e[0],e.slice(1)]:null,generate:(e=0)=>`${e+1}`}]]);function $be(e,{current:t,prerelease:r}){let s=new QA.default.SemVer(t),a=s.prerelease.slice(),n=[];s.prerelease=[],s.format()!==e&&(a.length=0);let c=!0,f=r.split(/\\./g);for(let p of f){let h=PSt.get(p);if(typeof h>\"u\")n.push(p),a[0]===p?a.shift():c=!1;else{let E=c?h.extract(a):null;E!==null&&typeof E[0]==\"number\"?(n.push(h.generate(E[0])),a=E[1]):(n.push(h.generate()),c=!1)}}return s.prerelease&&(s.prerelease=[]),`${e}-${n.join(\".\")}`}var M1=class extends At{constructor(){super(...arguments);this.all=he.Boolean(\"--all\",!1,{description:\"Apply the deferred version changes on all workspaces\"});this.dryRun=he.Boolean(\"--dry-run\",!1,{description:\"Print the versions without actually generating the package archive\"});this.prerelease=he.String(\"--prerelease\",{description:\"Add a prerelease identifier to new versions\",tolerateBoolean:!0});this.exact=he.Boolean(\"--exact\",!1,{description:\"Use the exact version of each package, removes any range. Useful for nightly releases where the range might match another version.\"});this.recursive=he.Boolean(\"-R,--recursive\",{description:\"Release the transitive workspaces as well\"});this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"version\",\"apply\"]]}static{this.usage=at.Usage({category:\"Release-related commands\",description:\"apply all the deferred version bumps at once\",details:`\n      This command will apply the deferred version changes and remove their definitions from the repository.\n\n      Note that if \\`--prerelease\\` is set, the given prerelease identifier (by default \\`rc.%n\\`) will be used on all new versions and the version definitions will be kept as-is.\n\n      By default only the current workspace will be bumped, but you can configure this behavior by using one of:\n\n      - \\`--recursive\\` to also apply the version bump on its dependencies\n      - \\`--all\\` to apply the version bump on all packages in the repository\n\n      Note that this command will also update the \\`workspace:\\` references across all your local workspaces, thus ensuring that they keep referring to the same workspaces even after the version bump.\n    `,examples:[[\"Apply the version change to the local workspace\",\"yarn version apply\"],[\"Apply the version change to all the workspaces in the local workspace\",\"yarn version apply --all\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);if(!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let c=await Ot.start({configuration:r,json:this.json,stdout:this.context.stdout},async f=>{let p=this.prerelease?typeof this.prerelease!=\"boolean\"?this.prerelease:\"rc.%n\":null,h=await oP(s,{prerelease:p}),E=new Map;if(this.all)E=h;else{let C=this.recursive?a.getRecursiveWorkspaceDependencies():[a];for(let S of C){let x=h.get(S);typeof x<\"u\"&&E.set(S,x)}}if(E.size===0){let C=h.size>0?\" Did you want to add --all?\":\"\";f.reportWarning(0,`The current workspace doesn't seem to require a version bump.${C}`);return}xJ(s,E,{report:f,exact:this.exact}),this.dryRun||(p||(this.all?await DJ(s):await bJ(s,[...E.keys()])),f.reportSeparator())});return this.dryRun||c.hasErrors()?c.exitCode():await s.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};qe();Dt();Vt();var vL=et(pi());var U1=class extends At{constructor(){super(...arguments);this.interactive=he.Boolean(\"-i,--interactive\",{description:\"Open an interactive interface used to set version bumps\"})}static{this.paths=[[\"version\",\"check\"]]}static{this.usage=at.Usage({category:\"Release-related commands\",description:\"check that all the relevant packages have been bumped\",details:\"\\n      **Warning:** This command currently requires Git.\\n\\n      This command will check that all the packages covered by the files listed in argument have been properly bumped or declined to bump.\\n\\n      In the case of a bump, the check will also cover transitive packages - meaning that should `Foo` be bumped, a package `Bar` depending on `Foo` will require a decision as to whether `Bar` will need to be bumped. This check doesn't cross packages that have declined to bump.\\n\\n      In case no arguments are passed to the function, the list of modified files will be generated by comparing the HEAD against `master`.\\n    \",examples:[[\"Check whether the modified packages need a bump\",\"yarn version check\"]]})}async execute(){return this.interactive?await this.executeInteractive():await this.executeStandard()}async executeInteractive(){JC(this.context);let{Gem:r}=await Promise.resolve().then(()=>(xF(),eW)),{ScrollableItems:s}=await Promise.resolve().then(()=>(TF(),RF)),{FocusRequest:a}=await Promise.resolve().then(()=>(nW(),uwe)),{useListInput:n}=await Promise.resolve().then(()=>(QF(),fwe)),{renderForm:c}=await Promise.resolve().then(()=>(LF(),OF)),{Box:f,Text:p}=await Promise.resolve().then(()=>et(Gc())),{default:h,useCallback:E,useState:C}=await Promise.resolve().then(()=>et(gn())),S=await ze.find(this.context.cwd,this.context.plugins),{project:x,workspace:I}=await Rt.find(S,this.context.cwd);if(!I)throw new ar(x.cwd,this.context.cwd);await x.restoreInstallState();let T=await O1(x);if(T===null||T.releaseRoots.size===0)return 0;if(T.root===null)throw new st(\"This command can only be run on Git repositories\");let O=()=>h.createElement(f,{flexDirection:\"row\",paddingBottom:1},h.createElement(f,{flexDirection:\"column\",width:60},h.createElement(f,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<up>\"),\"/\",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<down>\"),\" to select workspaces.\")),h.createElement(f,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<left>\"),\"/\",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<right>\"),\" to select release strategies.\"))),h.createElement(f,{flexDirection:\"column\"},h.createElement(f,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<enter>\"),\" to save.\")),h.createElement(f,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<ctrl+c>\"),\" to abort.\")))),U=({workspace:de,active:Ae,decision:Ce,setDecision:Ee})=>{let g=de.manifest.raw.stableVersion??de.manifest.version;if(g===null)throw new Error(`Assertion failed: The version should have been set (${j.prettyLocator(S,de.anchoredLocator)})`);if(vL.default.prerelease(g)!==null)throw new Error(`Assertion failed: Prerelease identifiers shouldn't be found (${g})`);let Se=[\"undecided\",\"decline\",\"patch\",\"minor\",\"major\"];n(Ce,Se,{active:Ae,minus:\"left\",plus:\"right\",set:Ee});let Be=Ce===\"undecided\"?h.createElement(p,{color:\"yellow\"},g):Ce===\"decline\"?h.createElement(p,{color:\"green\"},g):h.createElement(p,null,h.createElement(p,{color:\"magenta\"},g),\" \\u2192 \",h.createElement(p,{color:\"green\"},vL.default.valid(Ce)?Ce:vL.default.inc(g,Ce)));return h.createElement(f,{flexDirection:\"column\"},h.createElement(f,null,h.createElement(p,null,j.prettyLocator(S,de.anchoredLocator),\" - \",Be)),h.createElement(f,null,Se.map(me=>h.createElement(f,{key:me,paddingLeft:2},h.createElement(p,null,h.createElement(r,{active:me===Ce}),\" \",me)))))},Y=de=>{let Ae=new Set(T.releaseRoots),Ce=new Map([...de].filter(([Ee])=>Ae.has(Ee)));for(;;){let Ee=aP({project:T.project,releases:Ce}),g=!1;if(Ee.length>0){for(let[Se]of Ee)if(!Ae.has(Se)){Ae.add(Se),g=!0;let Be=de.get(Se);typeof Be<\"u\"&&Ce.set(Se,Be)}}if(!g)break}return{relevantWorkspaces:Ae,relevantReleases:Ce}},te=()=>{let[de,Ae]=C(()=>new Map(T.releases)),Ce=E((Ee,g)=>{let Se=new Map(de);g!==\"undecided\"?Se.set(Ee,g):Se.delete(Ee);let{relevantReleases:Be}=Y(Se);Ae(Be)},[de,Ae]);return[de,Ce]},ie=({workspaces:de,releases:Ae})=>{let Ce=[];Ce.push(`${de.size} total`);let Ee=0,g=0;for(let Se of de){let Be=Ae.get(Se);typeof Be>\"u\"?g+=1:Be!==\"decline\"&&(Ee+=1)}return Ce.push(`${Ee} release${Ee===1?\"\":\"s\"}`),Ce.push(`${g} remaining`),h.createElement(p,{color:\"yellow\"},Ce.join(\", \"))},ae=await c(({useSubmit:de})=>{let[Ae,Ce]=te();de(Ae);let{relevantWorkspaces:Ee}=Y(Ae),g=new Set([...Ee].filter(ce=>!T.releaseRoots.has(ce))),[Se,Be]=C(0),me=E(ce=>{switch(ce){case a.BEFORE:Be(Se-1);break;case a.AFTER:Be(Se+1);break}},[Se,Be]);return h.createElement(f,{flexDirection:\"column\"},h.createElement(O,null),h.createElement(f,null,h.createElement(p,{wrap:\"wrap\"},\"The following files have been modified in your local checkout.\")),h.createElement(f,{flexDirection:\"column\",marginTop:1,paddingLeft:2},[...T.changedFiles].map(ce=>h.createElement(f,{key:ce},h.createElement(p,null,h.createElement(p,{color:\"grey\"},fe.fromPortablePath(T.root)),fe.sep,fe.relative(fe.fromPortablePath(T.root),fe.fromPortablePath(ce)))))),T.releaseRoots.size>0&&h.createElement(h.Fragment,null,h.createElement(f,{marginTop:1},h.createElement(p,{wrap:\"wrap\"},\"Because of those files having been modified, the following workspaces may need to be released again (note that private workspaces are also shown here, because even though they won't be published, releasing them will allow us to flag their dependents for potential re-release):\")),g.size>3?h.createElement(f,{marginTop:1},h.createElement(ie,{workspaces:T.releaseRoots,releases:Ae})):null,h.createElement(f,{marginTop:1,flexDirection:\"column\"},h.createElement(s,{active:Se%2===0,radius:1,size:2,onFocusRequest:me},[...T.releaseRoots].map(ce=>h.createElement(U,{key:ce.cwd,workspace:ce,decision:Ae.get(ce)||\"undecided\",setDecision:X=>Ce(ce,X)}))))),g.size>0?h.createElement(h.Fragment,null,h.createElement(f,{marginTop:1},h.createElement(p,{wrap:\"wrap\"},\"The following workspaces depend on other workspaces that have been marked for release, and thus may need to be released as well:\")),h.createElement(f,null,h.createElement(p,null,\"(Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<tab>\"),\" to move the focus between the workspace groups.)\")),g.size>5?h.createElement(f,{marginTop:1},h.createElement(ie,{workspaces:g,releases:Ae})):null,h.createElement(f,{marginTop:1,flexDirection:\"column\"},h.createElement(s,{active:Se%2===1,radius:2,size:2,onFocusRequest:me},[...g].map(ce=>h.createElement(U,{key:ce.cwd,workspace:ce,decision:Ae.get(ce)||\"undecided\",setDecision:X=>Ce(ce,X)}))))):null)},{versionFile:T},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof ae>\"u\")return 1;T.releases.clear();for(let[de,Ae]of ae)T.releases.set(de,Ae);await T.saveAll()}async executeStandard(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);return await s.restoreInstallState(),(await Ot.start({configuration:r,stdout:this.context.stdout},async c=>{let f=await O1(s);if(f===null||f.releaseRoots.size===0)return;if(f.root===null)throw new st(\"This command can only be run on Git repositories\");if(c.reportInfo(0,`Your PR was started right after ${pe.pretty(r,f.baseHash.slice(0,7),\"yellow\")} ${pe.pretty(r,f.baseTitle,\"magenta\")}`),f.changedFiles.size>0){c.reportInfo(0,\"You have changed the following files since then:\"),c.reportSeparator();for(let S of f.changedFiles)c.reportInfo(null,`${pe.pretty(r,fe.fromPortablePath(f.root),\"gray\")}${fe.sep}${fe.relative(fe.fromPortablePath(f.root),fe.fromPortablePath(S))}`)}let p=!1,h=!1,E=BL(f);if(E.size>0){p||c.reportSeparator();for(let S of E)c.reportError(0,`${j.prettyLocator(r,S.anchoredLocator)} has been modified but doesn't have a release strategy attached`);p=!0}let C=aP(f);for(let[S,x]of C)h||c.reportSeparator(),c.reportError(0,`${j.prettyLocator(r,S.anchoredLocator)} doesn't have a release strategy attached, but depends on ${j.prettyWorkspace(r,x)} which is planned for release.`),h=!0;(p||h)&&(c.reportSeparator(),c.reportInfo(0,\"This command detected that at least some workspaces have received modifications without explicit instructions as to how they had to be released (if needed).\"),c.reportInfo(0,\"To correct these errors, run `yarn version check --interactive` then follow the instructions.\"))})).exitCode()}};qe();Vt();var SL=et(pi());var _1=class extends At{constructor(){super(...arguments);this.deferred=he.Boolean(\"-d,--deferred\",{description:\"Prepare the version to be bumped during the next release cycle\"});this.immediate=he.Boolean(\"-i,--immediate\",{description:\"Bump the version immediately\"});this.strategy=he.String()}static{this.paths=[[\"version\"]]}static{this.usage=at.Usage({category:\"Release-related commands\",description:\"apply a new version to the current package\",details:\"\\n      This command will bump the version number for the given package, following the specified strategy:\\n\\n      - If `major`, the first number from the semver range will be increased (`X.0.0`).\\n      - If `minor`, the second number from the semver range will be increased (`0.X.0`).\\n      - If `patch`, the third number from the semver range will be increased (`0.0.X`).\\n      - If prefixed by `pre` (`premajor`, ...), a `-0` suffix will be set (`0.0.0-0`).\\n      - If `prerelease`, the suffix will be increased (`0.0.0-X`); the third number from the semver range will also be increased if there was no suffix in the previous version.\\n      - If `decline`, the nonce will be increased for `yarn version check` to pass without version bump.\\n      - If a valid semver range, it will be used as new version.\\n      - If unspecified, Yarn will ask you for guidance.\\n\\n      For more information about the `--deferred` flag, consult our documentation (https://yarnpkg.com/features/release-workflow#deferred-versioning).\\n    \",examples:[[\"Immediately bump the version to the next major\",\"yarn version major\"],[\"Prepare the version to be bumped to the next major\",\"yarn version major --deferred\"]]})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!a)throw new ar(s.cwd,this.context.cwd);let n=r.get(\"preferDeferredVersions\");this.deferred&&(n=!0),this.immediate&&(n=!1);let c=SL.default.valid(this.strategy),f=this.strategy===\"decline\",p;if(c)if(a.manifest.version!==null){let E=PJ(a.manifest.version,this.strategy);E!==null?p=E:p=this.strategy}else p=this.strategy;else{let E=a.manifest.version;if(!f){if(E===null)throw new st(\"Can't bump the version if there wasn't a version to begin with - use 0.0.0 as initial version then run the command again.\");if(typeof E!=\"string\"||!SL.default.valid(E))throw new st(`Can't bump the version (${E}) if it's not valid semver`)}p=Ey(this.strategy)}if(!n){let C=(await oP(s)).get(a);if(typeof C<\"u\"&&p!==\"decline\"){let S=sP(a.manifest.version,p);if(SL.default.lt(S,C))throw new st(`Can't bump the version to one that would be lower than the current deferred one (${C})`)}}let h=await O1(s,{allowEmpty:!0});return h.releases.set(a,p),await h.saveAll(),n?0:await this.cli.run([\"version\",\"apply\"])}};var xSt={configuration:{deferredVersionFolder:{description:\"Folder where are stored the versioning files\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/versions\"},preferDeferredVersions:{description:\"If true, running `yarn version` will assume the `--deferred` flag unless `--immediate` is set\",type:\"BOOLEAN\",default:!1}},commands:[M1,U1,_1]},kSt=xSt;var QJ={};Yt(QJ,{WorkspacesFocusCommand:()=>H1,WorkspacesForeachCommand:()=>G1,default:()=>TSt});qe();qe();Vt();var H1=class extends At{constructor(){super(...arguments);this.json=he.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.production=he.Boolean(\"--production\",!1,{description:\"Only install regular dependencies by omitting dev dependencies\"});this.all=he.Boolean(\"-A,--all\",!1,{description:\"Install the entire project\"});this.workspaces=he.Rest()}static{this.paths=[[\"workspaces\",\"focus\"]]}static{this.usage=at.Usage({category:\"Workspace-related commands\",description:\"install a single workspace and its dependencies\",details:\"\\n      This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\\n\\n      Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\\n\\n      If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\\n    \"})}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd),n=await Jr.find(r);await s.restoreInstallState({restoreResolutions:!1});let c;if(this.all)c=new Set(s.workspaces);else if(this.workspaces.length===0){if(!a)throw new ar(s.cwd,this.context.cwd);c=new Set([a])}else c=new Set(this.workspaces.map(f=>s.getWorkspaceByIdent(j.parseIdent(f))));for(let f of c)for(let p of this.production?[\"dependencies\"]:Ut.hardDependencies)for(let h of f.manifest.getForScope(p).values()){let E=s.tryWorkspaceByDescriptor(h);E!==null&&c.add(E)}for(let f of s.workspaces)c.has(f)?this.production&&f.manifest.devDependencies.clear():(f.manifest.installConfig=f.manifest.installConfig||{},f.manifest.installConfig.selfReferences=!1,f.manifest.dependencies.clear(),f.manifest.devDependencies.clear(),f.manifest.peerDependencies.clear(),f.manifest.scripts.clear());return await s.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n,persistProject:!1})}};qe();qe();qe();Vt();var j1=et(Jo()),tPe=et(Nd());ul();var G1=class extends At{constructor(){super(...arguments);this.from=he.Array(\"--from\",{description:\"An array of glob pattern idents or paths from which to base any recursion\"});this.all=he.Boolean(\"-A,--all\",{description:\"Run the command on all workspaces of a project\"});this.recursive=he.Boolean(\"-R,--recursive\",{description:\"Run the command on the current workspace and all of its recursive dependencies\"});this.worktree=he.Boolean(\"-W,--worktree\",{description:\"Run the command on all workspaces of the current worktree\"});this.verbose=he.Counter(\"-v,--verbose\",{description:\"Increase level of logging verbosity up to 2 times\"});this.parallel=he.Boolean(\"-p,--parallel\",!1,{description:\"Run the commands in parallel\"});this.interlaced=he.Boolean(\"-i,--interlaced\",!1,{description:\"Print the output of commands in real-time instead of buffering it\"});this.jobs=he.String(\"-j,--jobs\",{description:\"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`\",validator:$U([ks([\"unlimited\"]),WB(XU(),[t_(),e_(1)])])});this.topological=he.Boolean(\"-t,--topological\",!1,{description:\"Run the command after all workspaces it depends on (regular) have finished\"});this.topologicalDev=he.Boolean(\"--topological-dev\",!1,{description:\"Run the command after all workspaces it depends on (regular + dev) have finished\"});this.include=he.Array(\"--include\",[],{description:\"An array of glob pattern idents or paths; only matching workspaces will be traversed\"});this.exclude=he.Array(\"--exclude\",[],{description:\"An array of glob pattern idents or paths; matching workspaces won't be traversed\"});this.publicOnly=he.Boolean(\"--no-private\",{description:\"Avoid running the command on private workspaces\"});this.since=he.String(\"--since\",{description:\"Only include workspaces that have been changed since the specified ref.\",tolerateBoolean:!0});this.dryRun=he.Boolean(\"-n,--dry-run\",{description:\"Print the commands that would be run, without actually running them\"});this.commandName=he.String();this.args=he.Proxy()}static{this.paths=[[\"workspaces\",\"foreach\"]]}static{this.usage=at.Usage({category:\"Workspace-related commands\",description:\"run a command on all workspaces\",details:\"\\n      This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\\n\\n      - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\\n\\n      - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\\n\\n      - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\\n\\n      - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project.\\n\\n      - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\\n\\n      - If `-W,--worktree` is set, Yarn will find workspaces to run the command on by looking at the current worktree.\\n\\n      - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\\n\\n      - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\\n\\n      - If `--dry-run` is set, Yarn will explain what it would do without actually doing anything.\\n\\n      - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them. You can also use the `--no-private` flag to avoid running the command in private workspaces.\\n\\n      The `-v,--verbose` flag can be passed up to twice: once to prefix output lines with the originating workspace's name, and again to include start/finish/timing log lines. Maximum verbosity is enabled by default in terminal environments.\\n\\n      If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\\n    \",examples:[[\"Publish all packages\",\"yarn workspaces foreach -A --no-private npm publish --tolerate-republish\"],[\"Run the build script on all descendant packages\",\"yarn workspaces foreach -A run build\"],[\"Run the build script on current and all descendant packages in parallel, building package dependencies first\",\"yarn workspaces foreach -Apt run build\"],[\"Run the build script on several packages and all their dependencies, building dependencies first\",\"yarn workspaces foreach -Rpt --from '{workspace-a,workspace-b}' run build\"]]})}static{this.schema=[YB(\"all\",Vf.Forbids,[\"from\",\"recursive\",\"since\",\"worktree\"],{missingIf:\"undefined\"}),r_([\"all\",\"recursive\",\"since\",\"worktree\"],{missingIf:\"undefined\"})]}async execute(){let r=await ze.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Rt.find(r,this.context.cwd);if(!this.all&&!a)throw new ar(s.cwd,this.context.cwd);await s.restoreInstallState();let n=this.cli.process([this.commandName,...this.args]),c=n.path.length===1&&n.path[0]===\"run\"&&typeof n.scriptName<\"u\"?n.scriptName:null;if(n.path.length===0)throw new st(\"Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script\");let f=Ee=>{this.dryRun&&this.context.stdout.write(`${Ee}\n`)},p=()=>{let Ee=this.from.map(g=>j1.default.matcher(g));return s.workspaces.filter(g=>{let Se=j.stringifyIdent(g.anchoredLocator),Be=g.relativeCwd;return Ee.some(me=>me(Se)||me(Be))})},h=[];if(this.since?(f(\"Option --since is set; selecting the changed workspaces as root for workspace selection\"),h=Array.from(await Oa.fetchChangedWorkspaces({ref:this.since,project:s}))):this.from?(f(\"Option --from is set; selecting the specified workspaces\"),h=[...p()]):this.worktree?(f(\"Option --worktree is set; selecting the current workspace\"),h=[a]):this.recursive?(f(\"Option --recursive is set; selecting the current workspace\"),h=[a]):this.all&&(f(\"Option --all is set; selecting all workspaces\"),h=[...s.workspaces]),this.dryRun&&!this.all){for(let Ee of h)f(`\n- ${Ee.relativeCwd}\n  ${j.prettyLocator(r,Ee.anchoredLocator)}`);h.length>0&&f(\"\")}let E;if(this.recursive?this.since?(f(\"Option --recursive --since is set; recursively selecting all dependent workspaces\"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependents()]).flat())):(f(\"Option --recursive is set; recursively selecting all transitive dependencies\"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependencies()]).flat())):this.worktree?(f(\"Option --worktree is set; recursively selecting all nested workspaces\"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceChildren()]).flat())):E=null,E!==null&&(h=[...new Set([...h,...E])],this.dryRun))for(let Ee of E)f(`\n- ${Ee.relativeCwd}\n  ${j.prettyLocator(r,Ee.anchoredLocator)}`);let C=[],S=!1;if(c?.includes(\":\")){for(let Ee of s.workspaces)if(Ee.manifest.scripts.has(c)&&(S=!S,S===!1))break}for(let Ee of h){if(c&&!Ee.manifest.scripts.has(c)&&!S&&!(await Cn.getWorkspaceAccessibleBinaries(Ee)).has(c)){f(`Excluding ${Ee.relativeCwd} because it doesn't have a \"${c}\" script`);continue}if(!(c===r.env.npm_lifecycle_event&&Ee.cwd===a.cwd)){if(this.include.length>0&&!j1.default.isMatch(j.stringifyIdent(Ee.anchoredLocator),this.include)&&!j1.default.isMatch(Ee.relativeCwd,this.include)){f(`Excluding ${Ee.relativeCwd} because it doesn't match the --include filter`);continue}if(this.exclude.length>0&&(j1.default.isMatch(j.stringifyIdent(Ee.anchoredLocator),this.exclude)||j1.default.isMatch(Ee.relativeCwd,this.exclude))){f(`Excluding ${Ee.relativeCwd} because it matches the --exclude filter`);continue}if(this.publicOnly&&Ee.manifest.private===!0){f(`Excluding ${Ee.relativeCwd} because it's a private workspace and --no-private was set`);continue}C.push(Ee)}}if(C.sort((Ee,g)=>j.stringifyIdent(Ee.anchoredLocator).localeCompare(j.stringifyIdent(g.anchoredLocator))),this.dryRun)return 0;let x=this.verbose??(this.context.stdout.isTTY?1/0:0),I=x>0,T=x>1,O=this.parallel?this.jobs===\"unlimited\"?1/0:Number(this.jobs)||Math.ceil(Ui.availableParallelism()/2):1,U=O===1?!1:this.parallel,Y=U?this.interlaced:!0,te=(0,tPe.default)(O),ie=new Map,ue=new Set,ae=0,de=null,Ae=!1,Ce=await Ot.start({configuration:r,stdout:this.context.stdout,includePrefix:!1},async Ee=>{let g=async(Se,{commandIndex:Be})=>{if(Ae)return-1;!U&&T&&Be>1&&Ee.reportSeparator();let me=QSt(Se,{configuration:r,label:I,commandIndex:Be}),[ce,X]=ePe(Ee,{prefix:me,interlaced:Y}),[De,Qe]=ePe(Ee,{prefix:me,interlaced:Y});try{T&&Ee.reportInfo(null,`${me?`${me} `:\"\"}Process started`);let it=Date.now(),_=await this.cli.run([this.commandName,...this.args],{cwd:Se.cwd,stdout:ce,stderr:De})||0;ce.end(),De.end(),await X,await Qe;let tt=Date.now();if(T){let Ne=r.get(\"enableTimers\")?`, completed in ${pe.pretty(r,tt-it,pe.Type.DURATION)}`:\"\";Ee.reportInfo(null,`${me?`${me} `:\"\"}Process exited (exit code ${_})${Ne}`)}return _===130&&(Ae=!0,de=_),_}catch(it){throw ce.end(),De.end(),await X,await Qe,it}};for(let Se of C)ie.set(Se.anchoredLocator.locatorHash,Se);for(;ie.size>0&&!Ee.hasErrors();){let Se=[];for(let[X,De]of ie){if(ue.has(De.anchoredDescriptor.descriptorHash))continue;let Qe=!0;if(this.topological||this.topologicalDev){let it=this.topologicalDev?new Map([...De.manifest.dependencies,...De.manifest.devDependencies]):De.manifest.dependencies;for(let _ of it.values()){let tt=s.tryWorkspaceByDescriptor(_);if(Qe=tt===null||!ie.has(tt.anchoredLocator.locatorHash),!Qe)break}}if(Qe&&(ue.add(De.anchoredDescriptor.descriptorHash),Se.push(te(async()=>{let it=await g(De,{commandIndex:++ae});return ie.delete(X),ue.delete(De.anchoredDescriptor.descriptorHash),{workspace:De,exitCode:it}})),!U))break}if(Se.length===0){let X=Array.from(ie.values()).map(De=>j.prettyLocator(r,De.anchoredLocator)).join(\", \");Ee.reportError(3,`Dependency cycle detected (${X})`);return}let Be=await Promise.all(Se);Be.forEach(({workspace:X,exitCode:De})=>{De!==0&&Ee.reportError(0,`The command failed in workspace ${j.prettyLocator(r,X.anchoredLocator)} with exit code ${De}`)});let ce=Be.map(X=>X.exitCode).find(X=>X!==0);(this.topological||this.topologicalDev)&&typeof ce<\"u\"&&Ee.reportError(0,\"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph\")}});return de!==null?de:Ce.exitCode()}};function ePe(e,{prefix:t,interlaced:r}){let s=e.createStreamReporter(t),a=new Ge.DefaultStream;a.pipe(s,{end:!1}),a.on(\"finish\",()=>{s.end()});let n=new Promise(f=>{s.on(\"finish\",()=>{f(a.active)})});if(r)return[a,n];let c=new Ge.BufferStream;return c.pipe(a,{end:!1}),c.on(\"finish\",()=>{a.end()}),[c,n]}function QSt(e,{configuration:t,commandIndex:r,label:s}){if(!s)return null;let n=`[${j.stringifyIdent(e.anchoredLocator)}]:`,c=[\"#2E86AB\",\"#A23B72\",\"#F18F01\",\"#C73E1D\",\"#CCE2A3\"],f=c[r%c.length];return pe.pretty(t,n,f)}var RSt={commands:[H1,G1]},TSt=RSt;var VI=()=>({modules:new Map([[\"@yarnpkg/cli\",Gv],[\"@yarnpkg/core\",jv],[\"@yarnpkg/fslib\",RB],[\"@yarnpkg/libzip\",nv],[\"@yarnpkg/parsers\",_B],[\"@yarnpkg/shell\",cv],[\"clipanion\",XB],[\"semver\",FSt],[\"typanion\",Yo],[\"@yarnpkg/plugin-essentials\",Q5],[\"@yarnpkg/plugin-catalog\",N5],[\"@yarnpkg/plugin-compat\",_5],[\"@yarnpkg/plugin-constraints\",nq],[\"@yarnpkg/plugin-dlx\",iq],[\"@yarnpkg/plugin-exec\",aq],[\"@yarnpkg/plugin-file\",cq],[\"@yarnpkg/plugin-git\",k5],[\"@yarnpkg/plugin-github\",Aq],[\"@yarnpkg/plugin-http\",pq],[\"@yarnpkg/plugin-init\",hq],[\"@yarnpkg/plugin-interactive-tools\",fW],[\"@yarnpkg/plugin-jsr\",pW],[\"@yarnpkg/plugin-link\",hW],[\"@yarnpkg/plugin-nm\",ZW],[\"@yarnpkg/plugin-npm\",ZK],[\"@yarnpkg/plugin-npm-cli\",aJ],[\"@yarnpkg/plugin-pack\",qV],[\"@yarnpkg/plugin-patch\",hJ],[\"@yarnpkg/plugin-pnp\",UW],[\"@yarnpkg/plugin-pnpm\",mJ],[\"@yarnpkg/plugin-stage\",vJ],[\"@yarnpkg/plugin-typescript\",SJ],[\"@yarnpkg/plugin-version\",kJ],[\"@yarnpkg/plugin-workspace-tools\",QJ]]),plugins:new Set([\"@yarnpkg/plugin-essentials\",\"@yarnpkg/plugin-catalog\",\"@yarnpkg/plugin-compat\",\"@yarnpkg/plugin-constraints\",\"@yarnpkg/plugin-dlx\",\"@yarnpkg/plugin-exec\",\"@yarnpkg/plugin-file\",\"@yarnpkg/plugin-git\",\"@yarnpkg/plugin-github\",\"@yarnpkg/plugin-http\",\"@yarnpkg/plugin-init\",\"@yarnpkg/plugin-interactive-tools\",\"@yarnpkg/plugin-jsr\",\"@yarnpkg/plugin-link\",\"@yarnpkg/plugin-nm\",\"@yarnpkg/plugin-npm\",\"@yarnpkg/plugin-npm-cli\",\"@yarnpkg/plugin-pack\",\"@yarnpkg/plugin-patch\",\"@yarnpkg/plugin-pnp\",\"@yarnpkg/plugin-pnpm\",\"@yarnpkg/plugin-stage\",\"@yarnpkg/plugin-typescript\",\"@yarnpkg/plugin-version\",\"@yarnpkg/plugin-workspace-tools\"])});function iPe({cwd:e,pluginConfiguration:t}){let r=new va({binaryLabel:\"Yarn Package Manager\",binaryName:\"yarn\",binaryVersion:An??\"<unknown>\"});return Object.assign(r,{defaultContext:{...va.defaultContext,cwd:e,plugins:t,quiet:!1,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr}})}function NSt(e){if(Ge.parseOptionalBoolean(process.env.YARN_IGNORE_NODE))return!0;let r=process.versions.node,s=\">=18.12.0\";if(Fr.satisfiesWithPrereleases(r,s))return!0;let a=new st(`This tool requires a Node version compatible with ${s} (got ${r}). Upgrade Node, or set \\`YARN_IGNORE_NODE=1\\` in your environment.`);return va.defaultContext.stdout.write(e.error(a)),!1}async function sPe({selfPath:e,pluginConfiguration:t}){return await ze.find(fe.toPortablePath(process.cwd()),t,{strict:!1,usePathCheck:e})}function OSt(e,t,{yarnPath:r}){if(!le.existsSync(r))return e.error(new Error(`The \"yarn-path\" option has been set, but the specified location doesn't exist (${r}).`)),1;process.on(\"SIGINT\",()=>{});let s={stdio:\"inherit\",env:{...process.env,YARN_IGNORE_PATH:\"1\"}};try{(0,rPe.execFileSync)(process.execPath,[fe.fromPortablePath(r),...t],s)}catch(a){return a.status??1}return 0}function LSt(e,t){let r=null,s=t;return t.length>=2&&t[0]===\"--cwd\"?(r=fe.toPortablePath(t[1]),s=t.slice(2)):t.length>=1&&t[0].startsWith(\"--cwd=\")?(r=fe.toPortablePath(t[0].slice(6)),s=t.slice(1)):t[0]===\"add\"&&t[t.length-2]===\"--cwd\"&&(r=fe.toPortablePath(t[t.length-1]),s=t.slice(0,t.length-2)),e.defaultContext.cwd=r!==null?K.resolve(r):K.cwd(),s}function MSt(e,{configuration:t}){if(!t.get(\"enableTelemetry\")||nPe.isCI||!process.stdout.isTTY)return;ze.telemetry=new GI(t,\"puba9cdc10ec5790a2cf4969dd413a47270\");let s=/^@yarnpkg\\/plugin-(.*)$/;for(let a of t.plugins.keys())qI.has(a.match(s)?.[1]??\"\")&&ze.telemetry?.reportPluginName(a);e.binaryVersion&&ze.telemetry.reportVersion(e.binaryVersion)}function oPe(e,{configuration:t}){for(let r of t.plugins.values())for(let s of r.commands||[])e.register(s)}async function USt(e,t,{selfPath:r,pluginConfiguration:s}){if(!NSt(e))return 1;let a=await sPe({selfPath:r,pluginConfiguration:s}),n=a.get(\"yarnPath\"),c=a.get(\"ignorePath\");if(n&&!c)return OSt(e,t,{yarnPath:n});delete process.env.YARN_IGNORE_PATH;let f=LSt(e,t);MSt(e,{configuration:a}),oPe(e,{configuration:a});let p=e.process(f,e.defaultContext);return p.help||ze.telemetry?.reportCommandName(p.path.join(\" \")),await e.run(p,e.defaultContext)}async function h0e({cwd:e=K.cwd(),pluginConfiguration:t=VI()}={}){let r=iPe({cwd:e,pluginConfiguration:t}),s=await sPe({pluginConfiguration:t,selfPath:null});return oPe(r,{configuration:s}),r}async function QT(e,{cwd:t=K.cwd(),selfPath:r,pluginConfiguration:s}){let a=iPe({cwd:t,pluginConfiguration:s});function n(){va.defaultContext.stdout.write(`ERROR: Yarn is terminating due to an unexpected empty event loop.\nPlease report this issue at https://github.com/yarnpkg/berry/issues.`)}process.once(\"beforeExit\",n);try{process.exitCode=42,process.exitCode=await USt(a,e,{selfPath:r,pluginConfiguration:s})}catch(c){va.defaultContext.stdout.write(a.error(c)),process.exitCode=1}finally{process.off(\"beforeExit\",n),await le.rmtempPromise()}}QT(process.argv.slice(2),{cwd:K.cwd(),selfPath:fe.toPortablePath(fe.resolve(process.argv[1])),pluginConfiguration:VI()});})();\n/**\n  @license\n  Copyright (c) 2015, Rebecca Turner\n\n  Permission to use, copy, modify, and/or distribute this software for any\n  purpose with or without fee is hereby granted, provided that the above\n  copyright notice and this permission notice appear in all copies.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\n  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n  PERFORMANCE OF THIS SOFTWARE.\n */\n/**\n  @license\n  Copyright Node.js contributors. All rights reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to\n  deal in the Software without restriction, including without limitation the\n  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n  sell copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n  IN THE SOFTWARE.\n*/\n/**\n  @license\n  The MIT License (MIT)\n\n  Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n/**\n  @license\n  Copyright Joyent, Inc. and other Node contributors.\n\n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the\n  \"Software\"), to deal in the Software without restriction, including\n  without limitation the rights to use, copy, modify, merge, publish,\n  distribute, sublicense, and/or sell copies of the Software, and to permit\n  persons to whom the Software is furnished to do so, subject to the\n  following conditions:\n\n  The above copyright notice and this permission notice shall be included\n  in all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n  NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n  USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/*! Bundled license information:\n\nis-number/index.js:\n  (*!\n   * is-number <https://github.com/jonschlinkert/is-number>\n   *\n   * Copyright (c) 2014-present, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n\nto-regex-range/index.js:\n  (*!\n   * to-regex-range <https://github.com/micromatch/to-regex-range>\n   *\n   * Copyright (c) 2015-present, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n\nfill-range/index.js:\n  (*!\n   * fill-range <https://github.com/jonschlinkert/fill-range>\n   *\n   * Copyright (c) 2014-present, Jon Schlinkert.\n   * Licensed under the MIT License.\n   *)\n\nis-extglob/index.js:\n  (*!\n   * is-extglob <https://github.com/jonschlinkert/is-extglob>\n   *\n   * Copyright (c) 2014-2016, Jon Schlinkert.\n   * Licensed under the MIT License.\n   *)\n\nis-glob/index.js:\n  (*!\n   * is-glob <https://github.com/jonschlinkert/is-glob>\n   *\n   * Copyright (c) 2014-2017, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n\nqueue-microtask/index.js:\n  (*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)\n\nrun-parallel/index.js:\n  (*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)\n\ngit-url-parse/lib/index.js:\n  (*!\n   * buildToken\n   * Builds OAuth token prefix (helper function)\n   *\n   * @name buildToken\n   * @function\n   * @param {GitUrl} obj The parsed Git url object.\n   * @return {String} token prefix\n   *)\n\nobject-assign/index.js:\n  (*\n  object-assign\n  (c) Sindre Sorhus\n  @license MIT\n  *)\n\nreact/cjs/react.production.min.js:\n  (** @license React v17.0.2\n   * react.production.min.js\n   *\n   * Copyright (c) Facebook, Inc. and its affiliates.\n   *\n   * This source code is licensed under the MIT license found in the\n   * LICENSE file in the root directory of this source tree.\n   *)\n\nscheduler/cjs/scheduler.production.min.js:\n  (** @license React v0.20.2\n   * scheduler.production.min.js\n   *\n   * Copyright (c) Facebook, Inc. and its affiliates.\n   *\n   * This source code is licensed under the MIT license found in the\n   * LICENSE file in the root directory of this source tree.\n   *)\n\nreact-reconciler/cjs/react-reconciler.production.min.js:\n  (** @license React v0.26.2\n   * react-reconciler.production.min.js\n   *\n   * Copyright (c) Facebook, Inc. and its affiliates.\n   *\n   * This source code is licensed under the MIT license found in the\n   * LICENSE file in the root directory of this source tree.\n   *)\n\nis-windows/index.js:\n  (*!\n   * is-windows <https://github.com/jonschlinkert/is-windows>\n   *\n   * Copyright © 2015-2018, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n*/\n"
  },
  {
    "path": ".yarnrc.yml",
    "content": "yarnPath: .yarn/releases/yarn-4.13.0.cjs\ndefaultSemverRangePrefix: ''\nnodeLinker: node-modules\n\n# Gitlab artifacts are only supported folders relative to the repository. Disable global cache so yarn will store the cache in .yarn/cache.\n# See https://docs.gitlab.com/ee/ci/jobs/job_artifacts.html#create-job-artifacts\n# See https://yarnpkg.com/configuration/yarnrc#enableGlobalCache\nenableGlobalCache: false\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# Datadog Browser SDK\n\nBrowser SDK for collecting Real User Monitoring (RUM) and logging data from web applications.\n\n## Package Manager\n\nThis project uses Yarn workspaces (v4.12.0). Never use `npm` or `npx`.\n\n## Key Commands\n\n```bash\n# Development server\nyarn dev\n\n# Build all packages\nyarn build\n\n# build test apps (for E2E and performance testing)\nyarn build:apps\n\n# Run unit tests\nyarn test:unit\n\n# Run specific test file\nyarn test:unit --spec packages/core/src/path/to/feature.spec.ts\n\n# Run tests on a specific seed\nyarn test:unit --seed 123\n\n# setup E2E tests (installs Playwright and builds test apps)\nyarn test:e2e:init\n\n# Run E2E tests\nyarn test:e2e\n\n# Run specific E2E test which names match “unhandled rejections”\nyarn test:e2e -g \"unhandled rejections\"\n\n# Type checking\nyarn typecheck\n\n# Linting\nyarn lint\n\n# Format code\nyarn format\n```\n\n## Monorepo Structure\n\n```\npackages/\n├── core/           # Shared utilities (Observable, configuration, transport)\n├── rum-core/       # Core RUM functionality\n├── rum/            # Full RUM package\n├── rum-slim/       # Lightweight RUM\n├── rum-react/      # React integration\n├── logs/           # Browser logging\n└── worker/         # Web Worker support\n\ndeveloper-extension/ # Chrome DevTools extension\n\ndocs/                # Repository documentation\n\ntest/\n├── apps/            # Test apps for E2E and performance testing\n├── e2e/             # Playwright E2E test scenarios\n├── performance/     # Performance benchmarking tests\n└── unit/            # Karma/Jasmine unit test configuration\n\nscripts/             # Build, deploy, release automation\n```\n\n## Documentation\n\nFor deeper context, see:\n\n- `docs/DEVELOPMENT.md` — commit conventions, dependency management, schema generation, TS compatibility\n- `docs/CONVENTIONS.md` — coding style, file organization, size control\n- `docs/ARCHITECTURE.md` — package dependencies, data pipeline\n- `docs/TESTING.md` — local testing strategies, debugging flaky tests\n- `scripts/AGENTS.md` — writing and organizing scripts in this codebase\n- `test/e2e/AGENTS.md` — E2E test writing guide (createTest builder, IntakeRegistry, patterns)\n\n## Critical Patterns\n\n### Unit Tests\n\n- Test framework: Jasmine + Karma. Spec files co-located with implementation: `feature.ts` → `feature.spec.ts`\n- Focus tests with `fit()` / `fdescribe()`, skip with `xit()` / `xdescribe()`\n- Use `registerCleanupTask()` for cleanup, NOT `afterEach()`\n- Mock values/functions: wrap with `mockable()` in source, use `replaceMockable()` or `replaceMockableWithSpy()` in tests (auto-cleanup)\n\n### Naming Conventions\n\n- Use **camelCase** for all internal variables and object properties\n- Conversion to snake_case/pascal_case happens at the serialization boundary (just before sending events)\n- Never use snake_case in internal code, even if the final event format requires it\n\n### TypeScript Patterns\n\n- Prefer **TypeScript type narrowing** over runtime type assertions (e.g., don't use `typeof x === 'object'` when proper return types can express the shape)\n- Use discriminated unions and return types to make invalid states unrepresentable at compile time\n\n### Telemetry Usage\n\n- `addTelemetryUsage` tracks **which public API the customer calls and which options they pass** (static call-site information)\n- Do NOT include runtime state analysis (e.g., whether a view was active, whether a value was overwritten) in telemetry usage — that belongs elsewhere\n\n### Auto-Generated Files\n\n- **NEVER manually edit auto-generated files.** They have a `DO NOT MODIFY IT BY HAND` comment at the top — respect it\n- Example: `telemetryEvent.types.ts` is generated from the `rum-events-format` schema repository\n- Any changes to these files require a **corresponding PR in the upstream source repo first**, then regeneration\n\n## Commit Messages\n\nUse gitmoji conventions — see `docs/DEVELOPMENT.md` for the full reference.\n\n## Git Workflow\n\n- Branch naming: `<username>/<feature>` (e.g., `john.doe/fix-session-bug`)\n- Always branch from `main` unless explicitly decided otherwise\n- PR title follows commit message convention (used when squashing to main)\n- PR template at `.github/PULL_REQUEST_TEMPLATE.md` - use it for all PRs\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n> **Legend**\n>\n> - 💥 **Breaking change** - Breaking API changes\n> - ✨ **New feature** - New public API, behavior, event, property\n> - 🐛 **Bug fix** - Fix bugs, regressions, crashes\n> - ⚡️ **Performance** - Improve performance, reduce bundle size\n> - 📝 **Documentation** - User-facing documentation\n> - ⚗️ **Experimental** - New public feature behind a feature flag\n>\n> See [Gitmoji](https://gitmoji.dev/) for a guide on the emojis used.\n\n---\n\n## v6.32.0\n\n**Public Changes:**\n\n- ✨ feat: enable LCP subparts collection by default ([#4368](https://github.com/DataDog/browser-sdk/pull/4368)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- ✨[RUM-15126] Allow updates of `error.handling_stack` ([#4357](https://github.com/DataDog/browser-sdk/pull/4357)) [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE]\n- ✨ add vuePlugin and addVueError ([#4327](https://github.com/DataDog/browser-sdk/pull/4327)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- ✨ NextJS- addNextjsError component ([#4343](https://github.com/DataDog/browser-sdk/pull/4343)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- ✨ scaffold @datadog/browser-rum-vue package ([#4325](https://github.com/DataDog/browser-sdk/pull/4325)) [RUM-VUE]\n- 🐛 Fix changelog legend after doc move to docs/DEVELOPMENT.md ([#4400](https://github.com/DataDog/browser-sdk/pull/4400))\n- 🐛 Skip new view on query-param-only changes in Angular router ([#4392](https://github.com/DataDog/browser-sdk/pull/4392)) [RUM-ANGULAR]\n- 🐛 [RUM-11614][URL polyfill] Handle null iframe.contentWindow ([#4361](https://github.com/DataDog/browser-sdk/pull/4361)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n\n**Internal Changes:**\n\n- 👷 replace lerna publish with yarn npm publish ([#4276](https://github.com/DataDog/browser-sdk/pull/4276)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- 👷 [e2e] group ignored browser log tags by matched pattern ([#4389](https://github.com/DataDog/browser-sdk/pull/4389))\n- 👷📝 Move some internal doc inside the repo ([#4362](https://github.com/DataDog/browser-sdk/pull/4362))\n- 👷[Renovate] Bump node max memory ([#4374](https://github.com/DataDog/browser-sdk/pull/4374))\n- 👷 Fix TypeScript 6.x compatibility check deprecation errors ([#4373](https://github.com/DataDog/browser-sdk/pull/4373))\n- 👷 NextJS- Make NextJS plugin private ([#4346](https://github.com/DataDog/browser-sdk/pull/4346)) [RUM-NEXTJS]\n- 👷 add dev-server CLI + manual-testing skill ([#4337](https://github.com/DataDog/browser-sdk/pull/4337))\n- 👷 fix missing yarn.lock entries for rum-vue dependencies ([#4347](https://github.com/DataDog/browser-sdk/pull/4347)) [RUM-VUE]\n- 🔧 Add Vue documentation and make package public ([#4402](https://github.com/DataDog/browser-sdk/pull/4402)) [RUM-VUE]\n- 🔧 Add Next.js documentation and make package public ([#4384](https://github.com/DataDog/browser-sdk/pull/4384)) [RUM-NEXTJS]\n- 🔧 report unused eslint-disable directives as errors ([#4398](https://github.com/DataDog/browser-sdk/pull/4398)) [RUM-ANGULAR]\n- 🔧 update repository.datadog.yml integration branch config ([#4390](https://github.com/DataDog/browser-sdk/pull/4390))\n- 🔧 Prepare @datadog/browser-rum-angular for beta release ([#4386](https://github.com/DataDog/browser-sdk/pull/4386)) [RUM-ANGULAR]\n- 🔧 disable renovate ([#4381](https://github.com/DataDog/browser-sdk/pull/4381))\n- 🔧 add prepack script to all packages to build before packing ([#4366](https://github.com/DataDog/browser-sdk/pull/4366)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- 🔧 make rum-vue package private until it's ready ([#4350](https://github.com/DataDog/browser-sdk/pull/4350)) [RUM-VUE]\n- 🎨 [PANA-6657] Make session replay team CODEOWNERS of recorder e2e tests ([#4388](https://github.com/DataDog/browser-sdk/pull/4388))\n- 🎨 [PANA-6365] Fix type definition for RumMutationRecord ([#4306](https://github.com/DataDog/browser-sdk/pull/4306)) [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE]\n- ✅ allow running e2e tests offline ([#4336](https://github.com/DataDog/browser-sdk/pull/4336))\n- ♻️ substitute Vue Router catch-all pattern with actual path ([#4393](https://github.com/DataDog/browser-sdk/pull/4393)) [RUM-VUE]\n- [PANA-6072] follow up review #4211 ([#4367](https://github.com/DataDog/browser-sdk/pull/4367)) [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE]\n- Update CODEOWNERS ([#4363](https://github.com/DataDog/browser-sdk/pull/4363))\n- ♻️ set global context in e2e worker setup ([#4380](https://github.com/DataDog/browser-sdk/pull/4380))\n- 🔥 [PANA-6634] Remove support for FrustrationRecords ([#4370](https://github.com/DataDog/browser-sdk/pull/4370)) [RUM]\n- ♻️ inline `lazyLoadRecorder` into `postStartStrategy` using `mockable()` ([#4326](https://github.com/DataDog/browser-sdk/pull/4326)) [RUM]\n- ⚗️ Angular- Add error handling integration ([#4358](https://github.com/DataDog/browser-sdk/pull/4358)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- ⚗️ add Vue Router v4 view tracking ([#4328](https://github.com/DataDog/browser-sdk/pull/4328)) [RUM-VUE]\n- ⚗ NextJS- add nextjs error boundary component ([#4352](https://github.com/DataDog/browser-sdk/pull/4352)) [RUM-NEXTJS]\n- ⚗️ Add Angular Router integration ([#4315](https://github.com/DataDog/browser-sdk/pull/4315)) [RUM-ANGULAR]\n- ⚗️ Refactor nextjs plugin ([#4365](https://github.com/DataDog/browser-sdk/pull/4365)) [RUM-NEXTJS]\n- [PANA-6072] add composedPathSelector to click actions target behind FF ([#4211](https://github.com/DataDog/browser-sdk/pull/4211)) [LOGS] [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE] [WORKER]\n- ♻️ refactor build-test-apps script with CLI arg support ([#4359](https://github.com/DataDog/browser-sdk/pull/4359))\n- ⬆️ update rum-events-format ([#4349](https://github.com/DataDog/browser-sdk/pull/4349))\n- 🔥 remove flagging package ([#4342](https://github.com/DataDog/browser-sdk/pull/4342)) [FLAGGING]\n- ♻️ React- Replace addEvent for AddError, Export Error Boundary ([#4317](https://github.com/DataDog/browser-sdk/pull/4317)) [RUM] [RUM-ANGULAR] [RUM-NEXTJS] [RUM-SLIM] [RUM-VUE]\n\n## v6.31.0\n\n**Public Changes:**\n\n- ✨ [RUM-14619] Add setViewLoadingTime() public API ([#4180](https://github.com/DataDog/browser-sdk/pull/4180)) [FLAGGING] [LOGS] [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨[RUM-14826] Add source code context to feature operations ([#4297](https://github.com/DataDog/browser-sdk/pull/4297)) [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM-6798] Capture resource content type ([#4270](https://github.com/DataDog/browser-sdk/pull/4270)) [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM]\n- ✨ NextJS Pages Router Integration ([#4290](https://github.com/DataDog/browser-sdk/pull/4290)) [RUM-NEXTJS]\n- ✨ [PANA-6283] Support incremental mutation Change records ([#4287](https://github.com/DataDog/browser-sdk/pull/4287)) [RUM]\n- ✨ [RUM-14736] Add size to ResourceStopOptions ([#4296](https://github.com/DataDog/browser-sdk/pull/4296)) [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM]\n- ✨ NextJS App Router Integration ([#4254](https://github.com/DataDog/browser-sdk/pull/4254)) [RUM-NEXTJS]\n- ✨ Add url option to startView API ([#4199](https://github.com/DataDog/browser-sdk/pull/4199)) [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM]\n- ✨ Add action and vital metadata to profiles ([#4148](https://github.com/DataDog/browser-sdk/pull/4148)) [FLAGGING] [LOGS] [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 fix queueMicrotask to avoid binding to globalObject ([#4320](https://github.com/DataDog/browser-sdk/pull/4320)) [FLAGGING] [LOGS] [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM] [WORKER]\n- [RUM-13793] 🐛 Skip potential sanitize updates on unaltered fields ([#4298](https://github.com/DataDog/browser-sdk/pull/4298)) [FLAGGING] [LOGS] [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM Profiler] Fix long tasks query using wrong clock for duration computation ([#4227](https://github.com/DataDog/browser-sdk/pull/4227)) [RUM]\n- 🐛 retry transient 503 errors in telemetry error checking ([#4273](https://github.com/DataDog/browser-sdk/pull/4273))\n- 🐛 [PANA-6258] More robustly prevent serialization of <style> children ([#4283](https://github.com/DataDog/browser-sdk/pull/4283)) [RUM]\n- 🐛 [devext] fix replay tab broken with SDK v7 cookies ([#4280](https://github.com/DataDog/browser-sdk/pull/4280))\n- 🐛 filter non-directory entries in packagesDirectoryNames ([#4271](https://github.com/DataDog/browser-sdk/pull/4271))\n\n**Internal Changes:**\n\n- 👷 Update dependency undici to v7.24.0 [SECURITY] ([#4338](https://github.com/DataDog/browser-sdk/pull/4338))\n- 👷 Sign CI Docker image with ddsign ([#4313](https://github.com/DataDog/browser-sdk/pull/4313))\n- 👷 Add ci.browser-sdk to CLA allowlist ([#4312](https://github.com/DataDog/browser-sdk/pull/4312))\n- 👷 Bump chrome to 146.0.7680.71-1 ([#4311](https://github.com/DataDog/browser-sdk/pull/4311))\n- 👷 Bump next from 15.3.3 to 15.5.10 ([#4292](https://github.com/DataDog/browser-sdk/pull/4292)) [RUM-NEXTJS]\n- 👷 remove usages of \"lerna\" in `yarn release` ([#4275](https://github.com/DataDog/browser-sdk/pull/4275))\n- 🔧 Fix octo-sts pull_request policy subject pattern ([#4310](https://github.com/DataDog/browser-sdk/pull/4310))\n- 🎨 Rename mockedLocationHref to locationHref ([#4288](https://github.com/DataDog/browser-sdk/pull/4288)) [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM]\n- ✅ [RUM-14696] Improve microfrontend e2e test - plugin + module federation ([#4220](https://github.com/DataDog/browser-sdk/pull/4220))\n- 🔊 add debug context to \"Too many requests\" telemetry ([#4278](https://github.com/DataDog/browser-sdk/pull/4278)) [FLAGGING] [LOGS] [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ NextJS- Rename test app and update e2e tests. ([#4316](https://github.com/DataDog/browser-sdk/pull/4316)) [RUM-NEXTJS]\n- ⬆️ [PANA-6354] Update replay sandbox version in extension to support Change records ([#4305](https://github.com/DataDog/browser-sdk/pull/4305))\n- [PROF-13923] Upload source maps to org2 on every deployment ([#4282](https://github.com/DataDog/browser-sdk/pull/4282))\n- Bump rollup from 4.57.1 to 4.59.0 in /test/apps/react-heavy-spa ([#4293](https://github.com/DataDog/browser-sdk/pull/4293))\n- 🚧 [PANA-6282] Add USE_INCREMENTAL_CHANGE_RECORDS feature flag ([#4284](https://github.com/DataDog/browser-sdk/pull/4284)) [FLAGGING] [LOGS] [RUM] [RUM-NEXTJS] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [PANA-6193] Add an Observer for DOM serializations ([#4277](https://github.com/DataDog/browser-sdk/pull/4277)) [RUM]\n- ♻️ [PANA-5947] Convert Change records to V1 records using a VDOM ([#4165](https://github.com/DataDog/browser-sdk/pull/4165)) [RUM]\n\n## v6.30.1\n\n**Internal Changes:**\n\n- 👷 upgrade minimatch to 10.2.4 to fix npm publish packaging issue ([#4267](https://github.com/DataDog/browser-sdk/pull/4267))\n\n## v6.30.0\n\n**Public Changes:**\n\n- ✨[MFE] Source code context event enrichment ([#4255](https://github.com/DataDog/browser-sdk/pull/4255)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 fix LogsEventDomainContext fallback to undefined instead of never ([#4264](https://github.com/DataDog/browser-sdk/pull/4264)) [LOGS]\n- 🐛 fix stale closure bug in watchCookieFallback ([#4259](https://github.com/DataDog/browser-sdk/pull/4259)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 🧹 remove unused eslint-disable directives from generated type files ([#4260](https://github.com/DataDog/browser-sdk/pull/4260)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.29.0\n\n**Public Changes:**\n\n- ✨ support per-value synthetics globals/cookies with a unified context object ([#4236](https://github.com/DataDog/browser-sdk/pull/4236)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ Compute session tracking type in developer extension for SDK v7 support ([#4202](https://github.com/DataDog/browser-sdk/pull/4202)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ⚗✨ [RUM-14736] Add type to ResourceStopOptions ([#4232](https://github.com/DataDog/browser-sdk/pull/4232)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 Update dependency minimatch to v10.2.3 [SECURITY] ([#4257](https://github.com/DataDog/browser-sdk/pull/4257))\n- 👷 Update all non-major dependencies ([#4256](https://github.com/DataDog/browser-sdk/pull/4256))\n- ⚗️feat: collect INP sub-parts RUM-14310 ([#4158](https://github.com/DataDog/browser-sdk/pull/4158)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.28.1\n\n**Public Changes:**\n\n- 🐛 Compute duration from timestamps in event tracker ([#4233](https://github.com/DataDog/browser-sdk/pull/4233)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM Profiler] Fix stateReason not updated on stop and cleanup tasks accumulation ([#4171](https://github.com/DataDog/browser-sdk/pull/4171)) [RUM]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#4186](https://github.com/DataDog/browser-sdk/pull/4186)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update dependency eslint-plugin-unicorn to v63 ([#4221](https://github.com/DataDog/browser-sdk/pull/4221))\n- 👷 Update dependency @playwright/test to v1.58.2 ([#4187](https://github.com/DataDog/browser-sdk/pull/4187))\n- ⚗️ [RUM-13259] Add shadow DOM support for action selectors ([#4097](https://github.com/DataDog/browser-sdk/pull/4097)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.28.0\n\n**Public Changes:**\n\n- ✨ `localStorage` strategy for remote configuration ([#4071](https://github.com/DataDog/browser-sdk/pull/4071)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM-13680] Add support for GraphQL GET requests with query params (APQ) ([#4125](https://github.com/DataDog/browser-sdk/pull/4125)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 Regenerate anonymousId when session cookie is altered without preserving aid ([#4203](https://github.com/DataDog/browser-sdk/pull/4203)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-5645] Avoid fetch keepAlive ([#4192](https://github.com/DataDog/browser-sdk/pull/4192)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚡️ rebuild worker only when needed ([#4170](https://github.com/DataDog/browser-sdk/pull/4170))\n- 📝 Add critical patterns documentation to AGENTS.md ([#4183](https://github.com/DataDog/browser-sdk/pull/4183))\n- ⚗ [RUM-11393] Add Start/StopResource API ([#4110](https://github.com/DataDog/browser-sdk/pull/4110)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Skip BrowserStack tests on next major branch ([#4215](https://github.com/DataDog/browser-sdk/pull/4215))\n- 👷 use dynamic port for dev server to avoid conflicts ([#4218](https://github.com/DataDog/browser-sdk/pull/4218))\n- 👷 Load BrowserStack credentials from .env file ([#4189](https://github.com/DataDog/browser-sdk/pull/4189))\n- 👷 Skip check-staging-merge for PRs targeting next major version branch ([#4181](https://github.com/DataDog/browser-sdk/pull/4181))\n- 🔧 disable ADMS ([#4191](https://github.com/DataDog/browser-sdk/pull/4191))\n- ✅ fix mockCookies flaky interception on Safari 12.1.2 ([#4214](https://github.com/DataDog/browser-sdk/pull/4214)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ Fix flaky remote configuration E2E tests ([#4210](https://github.com/DataDog/browser-sdk/pull/4210))\n- ✅ fix flaky tests related to experimental features ([#4207](https://github.com/DataDog/browser-sdk/pull/4207)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ Introduce a new way to mock values in unit tests ([#4129](https://github.com/DataDog/browser-sdk/pull/4129)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [PANA-5982] Make the serialization code more configurable and testable ([#4185](https://github.com/DataDog/browser-sdk/pull/4185)) [RUM]\n- ♻️ move long task contexts to profiler ([#4046](https://github.com/DataDog/browser-sdk/pull/4046)) [RUM] [RUM-REACT] [RUM-SLIM]\n- [RUM/PROF] Add profiling context to actions and vitals' \\_dd field ([#4200](https://github.com/DataDog/browser-sdk/pull/4200)) [RUM]\n- ♻️ [PANA-5948] Make some small improvements to ItemId management ([#4164](https://github.com/DataDog/browser-sdk/pull/4164)) [RUM]\n- ♻️ Refactor e2e service worker setup into a composable builder pattern ([#4162](https://github.com/DataDog/browser-sdk/pull/4162))\n\n## v6.27.1\n\n**Public Changes:**\n\n- 🐛 Changed tracked action to accept ClocksState ([#4177](https://github.com/DataDog/browser-sdk/pull/4177)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM Profiler] Fix profiler stuck in \"stopped\" mode when session expires ([#4152](https://github.com/DataDog/browser-sdk/pull/4152)) [RUM]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#4150](https://github.com/DataDog/browser-sdk/pull/4150)) [FLAGGING] [RUM-REACT] [WORKER]\n- 👷 Show actual scenario file locations in E2E test output ([#4166](https://github.com/DataDog/browser-sdk/pull/4166))\n- 👷 Update dependency @playwright/test to v1.58.1 ([#4151](https://github.com/DataDog/browser-sdk/pull/4151))\n- 👷 Update build process in developer-extension ([#4153](https://github.com/DataDog/browser-sdk/pull/4153))\n- 👷 allow gh-worker-dd-devflow bots to bypass CLA check ([#4161](https://github.com/DataDog/browser-sdk/pull/4161))\n- ✅ fix flaky test ([#4168](https://github.com/DataDog/browser-sdk/pull/4168)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ improve unit test setup ([#4149](https://github.com/DataDog/browser-sdk/pull/4149)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [PANA-5945] Support child list InsertionCursors ([#4163](https://github.com/DataDog/browser-sdk/pull/4163)) [RUM]\n\n## v6.27.0\n\n**Public Changes:**\n\n- ✨ [RUM-11654] Add in-memory session persistence option ([#4124](https://github.com/DataDog/browser-sdk/pull/4124)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-14142] Add source code context to vitals and manual view ([#4137](https://github.com/DataDog/browser-sdk/pull/4137)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-13741] Fix sibling uniqueness check for elements in DocumentFragment ([#4115](https://github.com/DataDog/browser-sdk/pull/4115)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ⚗️ [RUM-13818] Collect LCP subparts ([#4104](https://github.com/DataDog/browser-sdk/pull/4104)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 fix code coverage upload ([#4155](https://github.com/DataDog/browser-sdk/pull/4155))\n- 👷 Fix source maps upload for versioned canary builds ([#4146](https://github.com/DataDog/browser-sdk/pull/4146))\n- 👷 Lock file maintenance ([#4141](https://github.com/DataDog/browser-sdk/pull/4141))\n- 👷 Update all non-major dependencies ([#4138](https://github.com/DataDog/browser-sdk/pull/4138)) [RUM-REACT]\n- 👷 skip BrowserStack tests for non-code changes ([#4136](https://github.com/DataDog/browser-sdk/pull/4136))\n- 👷 Update dependency @playwright/test to v1.58.0 ([#4139](https://github.com/DataDog/browser-sdk/pull/4139))\n- 👷 Bump slack-notifier version ([#4142](https://github.com/DataDog/browser-sdk/pull/4142))\n- 👷 Use RUM Profiling Schema from RUM-Events-Format ([#4080](https://github.com/DataDog/browser-sdk/pull/4080)) [RUM]\n- 👷 set NEXT_MAJOR_BRANCH to v7 ([#4132](https://github.com/DataDog/browser-sdk/pull/4132))\n- 🔧 Use hardcoded v7 instead of $NEXT_MAJOR_BRANCH variable ([#4135](https://github.com/DataDog/browser-sdk/pull/4135))\n- 🔧 Add integration-branch config for v7 ([#4134](https://github.com/DataDog/browser-sdk/pull/4134))\n- 🔧 Ignore Claude Code local files ([#4130](https://github.com/DataDog/browser-sdk/pull/4130))\n- ci: Removing usage of legacy runners ([#4106](https://github.com/DataDog/browser-sdk/pull/4106))\n- ♻️ move telemetry to pre-start step ([#4107](https://github.com/DataDog/browser-sdk/pull/4107)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.26.0\n\n**Public Changes:**\n\n- ⚡️ Use native fetch to avoid Zone.js change detection in Angular apps ([#4117](https://github.com/DataDog/browser-sdk/pull/4117)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Support stylesheet serialization in Safari iOS 16.x ([#4126](https://github.com/DataDog/browser-sdk/pull/4126)) [RUM]\n- ⚗️ [RUM-11393] Add Start/StopAction API ([#4038](https://github.com/DataDog/browser-sdk/pull/4038))\n- ⚗️ [MFE] Source code context event enrichment ([#3926](https://github.com/DataDog/browser-sdk/pull/3926))\n- 📝 Add comprehensive AGENTS.md for Browser SDK, scripts, and E2E testing ([#4109](https://github.com/DataDog/browser-sdk/pull/4109))\n- 📝 Add new command for revising AGENTS.md with session learnings ([#4112](https://github.com/DataDog/browser-sdk/pull/4112))\n\n**Internal Changes:**\n\n- 🔊 extend or remove expired telemetry debug ([#4102](https://github.com/DataDog/browser-sdk/pull/4102))\n- ♻️ Update rum-events-format ([#4114](https://github.com/DataDog/browser-sdk/pull/4114))\n- 👷 Bump iOS version ([#4119](https://github.com/DataDog/browser-sdk/pull/4119))\n- 👷 improve check-schemas script ([#4123](https://github.com/DataDog/browser-sdk/pull/4123)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 Update all non-major dependencies ([#4116](https://github.com/DataDog/browser-sdk/pull/4116))\n- 👷 Handle function values for configuration in developer extension ([#4042](https://github.com/DataDog/browser-sdk/pull/4042))\n- 👷 Update react-router monorepo to v7 (major) ([#4100](https://github.com/DataDog/browser-sdk/pull/4100))\n- 👷 Update dependency recharts to v3 ([#4075](https://github.com/DataDog/browser-sdk/pull/4075))\n- 👷 Update dependency eslint-plugin-jsdoc to v62 ([#4098](https://github.com/DataDog/browser-sdk/pull/4098))\n- 👷 Update react monorepo to v19 ([#4101](https://github.com/DataDog/browser-sdk/pull/4101))\n- 👷 Update all non-major dependencies ([#4099](https://github.com/DataDog/browser-sdk/pull/4099)) [RUM-REACT]\n- 👷 Fix deployment gate timing to ensure 30-minute duration ([#4096](https://github.com/DataDog/browser-sdk/pull/4096))\n\n## v6.25.4\n\n**Public Changes:**\n\n- 🐛 [PANA-5375] Treat Change records as full snapshots when appropriate ([#4078](https://github.com/DataDog/browser-sdk/pull/4078)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-13693] make sure click actions are sent on page exit ([#4070](https://github.com/DataDog/browser-sdk/pull/4070)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 manage checkTelemetryError connexion pool ([#4094](https://github.com/DataDog/browser-sdk/pull/4094))\n- 👷 Update dependency globals to v17 ([#4074](https://github.com/DataDog/browser-sdk/pull/4074))\n- 👷 Update dependency vite to v7 ([#4076](https://github.com/DataDog/browser-sdk/pull/4076))\n- 👷 Update all non-major dependencies ([#4073](https://github.com/DataDog/browser-sdk/pull/4073))\n- 👷 do not rely on hardcoded list of DCs ([#4037](https://github.com/DataDog/browser-sdk/pull/4037))\n- 👷 Update dependency react-router to v7.12.0 [SECURITY] ([#4065](https://github.com/DataDog/browser-sdk/pull/4065)) [RUM-REACT]\n- 👷 handle rate limiting in checkTelemetryErrors ([#4069](https://github.com/DataDog/browser-sdk/pull/4069))\n- 👷 Update Node.js to v25 ([#3940](https://github.com/DataDog/browser-sdk/pull/3940))\n- 👷 Update dependency react-window to v2 ([#4052](https://github.com/DataDog/browser-sdk/pull/4052))\n- 🔧 Update deploy-\\*.yml to use arch:amd64 runner ([#4086](https://github.com/DataDog/browser-sdk/pull/4086))\n- 🔧 fix deploy auto notification job dependency ([#4084](https://github.com/DataDog/browser-sdk/pull/4084))\n- ⚗️ [PANA-3971] Add a more compact experimental DOM mutation encoding ([#4060](https://github.com/DataDog/browser-sdk/pull/4060)) [RUM]\n- ⚗️ [PANA-5359] Support change records in the developer extension ([#4072](https://github.com/DataDog/browser-sdk/pull/4072))\n- ⚗️ [RUM-13259]Track action names in shadow dom ([#4044](https://github.com/DataDog/browser-sdk/pull/4044)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 📈 [PANA-5371] Add telemetry to help evaluate new DOM mutation encoding ([#4077](https://github.com/DataDog/browser-sdk/pull/4077)) [RUM]\n\n## v6.25.3\n\n**Public Changes:**\n\n- 🐛 fix reading cookies containing special characters ([#4066](https://github.com/DataDog/browser-sdk/pull/4066)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Fix developer extension crash due to missing build variable ([#4061](https://github.com/DataDog/browser-sdk/pull/4061)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-13615] fix remote config tracing options support ([#4062](https://github.com/DataDog/browser-sdk/pull/4062)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 do not rely on monitors for deployment gate ([#3973](https://github.com/DataDog/browser-sdk/pull/3973))\n- 👷 Update dependency @vitejs/plugin-react to v5 ([#4032](https://github.com/DataDog/browser-sdk/pull/4032))\n- 👷 Update dependency @playwright/test to v1.57.0 ([#4005](https://github.com/DataDog/browser-sdk/pull/4005))\n- 👷 Update all non-major dependencies ([#4031](https://github.com/DataDog/browser-sdk/pull/4031)) [FLAGGING] [RUM-REACT] [WORKER]\n\n## v6.25.2\n\n**Public Changes:**\n\n- 🐛 Fix profiling <-> long task association regression ([#4045](https://github.com/DataDog/browser-sdk/pull/4045)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 Fix flaky long task <-> action correlation ([#4050](https://github.com/DataDog/browser-sdk/pull/4050)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ✨[PANA-5288] Update rum-events-format to pull in BrowserChangeRecord ([#4035](https://github.com/DataDog/browser-sdk/pull/4035)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Revert \"👷 disable deploy-prod-canary during the freeze ([#4053](https://github.com/DataDog/browser-sdk/pull/4053))\" ([#4058](https://github.com/DataDog/browser-sdk/pull/4058))\n- 👷 disable deploy-prod-canary during the freeze ([#4053](https://github.com/DataDog/browser-sdk/pull/4053))\n- 👷 update the token to AWS after renewing it ([#4048](https://github.com/DataDog/browser-sdk/pull/4048))\n- 🎨 [PANA-5260] Consolidate recorder object id tracking code ([#4049](https://github.com/DataDog/browser-sdk/pull/4049)) [RUM]\n- 🔊 add debug logs to npm publishing command ([#4047](https://github.com/DataDog/browser-sdk/pull/4047))\n\n## v6.25.1\n\n**Public Changes:**\n\n- ✨[PANA-5156] Expose better session replay internal API ([#4018](https://github.com/DataDog/browser-sdk/pull/4018)) [RUM]\n- 🐛 Fix action <-> long task correlation [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 clear chain after finalize ([#4027](https://github.com/DataDog/browser-sdk/pull/4027)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 fix developer extension packaging ([#4024](https://github.com/DataDog/browser-sdk/pull/4024))\n\n**Internal Changes:**\n\n- 👷 improve static analysis ([#4030](https://github.com/DataDog/browser-sdk/pull/4030)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 when webpack has errors, print stats and fail the script ([#4029](https://github.com/DataDog/browser-sdk/pull/4029))\n- 👷 Lock file maintenance ([#4017](https://github.com/DataDog/browser-sdk/pull/4017))\n- 👷 Other strategy to handle test app lockfiles with renovate ([#4028](https://github.com/DataDog/browser-sdk/pull/4028))\n- 👷 Enable more renovate flags... ([#4023](https://github.com/DataDog/browser-sdk/pull/4023))\n- 👷 add a script to easily create an access token ([#4020](https://github.com/DataDog/browser-sdk/pull/4020))\n- 👷 Ensure that renovate do a full install ([#4021](https://github.com/DataDog/browser-sdk/pull/4021))\n- 👷 Ensure to have tarballs built at install ([#4019](https://github.com/DataDog/browser-sdk/pull/4019))\n- 👷: migrate config renovate.json ([#4016](https://github.com/DataDog/browser-sdk/pull/4016))\n- 👷 Update dependency vite to v5.4.21 [SECURITY] ([#4015](https://github.com/DataDog/browser-sdk/pull/4015))\n- 👷 Configure test apps dependencies ([#4014](https://github.com/DataDog/browser-sdk/pull/4014))\n- 🎨 [PANA-5053] Separate DOM and virtual attribute serialization ([#3998](https://github.com/DataDog/browser-sdk/pull/3998)) [RUM]\n- 🎨 [PANA-5222] Make CODEOWNERS more accurate for recording code ([#4034](https://github.com/DataDog/browser-sdk/pull/4034))\n- Update errors_count field to error_count ([#4039](https://github.com/DataDog/browser-sdk/pull/4039)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ [PANA-5123] Assign node ids in preorder when serializing ([#4002](https://github.com/DataDog/browser-sdk/pull/4002)) [RUM]\n- ♻️ [PANA-5105] Serialize all DOM attribute values as strings ([#3999](https://github.com/DataDog/browser-sdk/pull/3999)) [RUM]\n- ♻️ Replace longTaskRegistry by longTaskContexts ([#4013](https://github.com/DataDog/browser-sdk/pull/4013)) [RUM] [RUM-REACT] [RUM-SLIM]\n- Add flagEvaluationEndpointBuilder to TransportConfiguration interface. ([#4025](https://github.com/DataDog/browser-sdk/pull/4025)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- [RUM Browser Profiler] stop profiler when session expires ([#4011](https://github.com/DataDog/browser-sdk/pull/4011)) [RUM]\n\n## v6.25.0\n\n**Public Changes:**\n\n- ✨ add logs to service worker extension ([#3987](https://github.com/DataDog/browser-sdk/pull/3987))\n- ✨ add support for persisted GraphQL Queries ([#3979](https://github.com/DataDog/browser-sdk/pull/3979)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ extend masking cases to include aria-label and name ([#3961](https://github.com/DataDog/browser-sdk/pull/3961)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 add support for arbitrary Error causes ([#3860](https://github.com/DataDog/browser-sdk/pull/3860)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Update dependency vite to v5.4.21 [SECURITY] ([#4010](https://github.com/DataDog/browser-sdk/pull/4010))\n- 👷 Include test apps in renovate scan ([#4009](https://github.com/DataDog/browser-sdk/pull/4009))\n- 👷 restore canary deployment ([#4008](https://github.com/DataDog/browser-sdk/pull/4008))\n- 👷 Update all non-major dependencies ([#3980](https://github.com/DataDog/browser-sdk/pull/3980)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 configure renovate to not create PRs before stable ([#4006](https://github.com/DataDog/browser-sdk/pull/4006))\n- 👷 Exclude renovate from CLA Assistant check ([#4007](https://github.com/DataDog/browser-sdk/pull/4007))\n- 👷 extend monitor date ([#3990](https://github.com/DataDog/browser-sdk/pull/3990)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update actions/checkout action to v6 ([#3989](https://github.com/DataDog/browser-sdk/pull/3989))\n- 👷 disable deploy-prod-canary during the freeze ([#3984](https://github.com/DataDog/browser-sdk/pull/3984))\n- 👷 fix temporal dead zone ([#3974](https://github.com/DataDog/browser-sdk/pull/3974))\n- 👷 check package.json files for each PR ([#3970](https://github.com/DataDog/browser-sdk/pull/3970))\n- 👷 [EX-1236] Add support for flagevaluation track. ([#3976](https://github.com/DataDog/browser-sdk/pull/3976)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Add CLA bot GitHub action ([#3995](https://github.com/DataDog/browser-sdk/pull/3995))\n- 👷 Add more complete tests for DOM attribute serialization ([#3994](https://github.com/DataDog/browser-sdk/pull/3994)) [RUM]\n- 👷 [RUM-12600] Refine Continuous Benchmarking ([#3977](https://github.com/DataDog/browser-sdk/pull/3977))\n- 🔧 migrate the developer-extension to wxt ([#3962](https://github.com/DataDog/browser-sdk/pull/3962))\n- 🎨 [PANA-4929] Add the concept of serialization transactions and reorganize state ([#3982](https://github.com/DataDog/browser-sdk/pull/3982)) [RUM]\n- 🎨 [PANA-4976] Separate emission of replay records and serialization stats ([#3978](https://github.com/DataDog/browser-sdk/pull/3978)) [RUM]\n- ♻️ separate RUM event collection ([#3985](https://github.com/DataDog/browser-sdk/pull/3985)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔥 remove the `performances/` script ([#3986](https://github.com/DataDog/browser-sdk/pull/3986))\n- 🔉 add \\_dd.configuration.trace_sample_rate ([#3946](https://github.com/DataDog/browser-sdk/pull/3946)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.24.1\n\n**Public Changes:**\n\n- 🐛 [RUM-12503] Add mask-unless-allowlisted privacy level support for standard attr ([#3907](https://github.com/DataDog/browser-sdk/pull/3907)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 fix temporal dead zone ([#3974](https://github.com/DataDog/browser-sdk/pull/3974))\n- 👷 check package.json files for each PR ([#3970](https://github.com/DataDog/browser-sdk/pull/3970))\n- 👷 handle undefined api key for source-maps upload to new DC ([#3971](https://github.com/DataDog/browser-sdk/pull/3971))\n- 👷 Update actions/setup-node action to v6 ([#3930](https://github.com/DataDog/browser-sdk/pull/3930))\n- 👷 remove version number from private packages ([#3969](https://github.com/DataDog/browser-sdk/pull/3969))\n- 👷 fix prtest00 site ([#3967](https://github.com/DataDog/browser-sdk/pull/3967)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update dependency @playwright/test to v1.56.1 ([#3917](https://github.com/DataDog/browser-sdk/pull/3917))\n- 👷 Update dependency eslint-plugin-unicorn to v62 ([#3941](https://github.com/DataDog/browser-sdk/pull/3941))\n- 👷 Update all non-major dependencies ([#3954](https://github.com/DataDog/browser-sdk/pull/3954)) [RUM-REACT]\n- 👷 Reduce packages boilerplate a bit more ([#3957](https://github.com/DataDog/browser-sdk/pull/3957)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 fix: Add name field to e2e package.json ([#3959](https://github.com/DataDog/browser-sdk/pull/3959))\n- ♻️ refactor new datacenter workflow ([#3964](https://github.com/DataDog/browser-sdk/pull/3964))\n- 👷 Fix gitignore ([#3963](https://github.com/DataDog/browser-sdk/pull/3963))\n- 👷 Add Continuous Benchmarking ([#3927](https://github.com/DataDog/browser-sdk/pull/3927))\n- ♻️ remove constants from the `Configuration` object ([#3960](https://github.com/DataDog/browser-sdk/pull/3960)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.24.0\n\n**Public Changes:**\n\n- ✨[RUM-12672] Allow graphql variables field to be modifiable in beforeSend ([#3949](https://github.com/DataDog/browser-sdk/pull/3949)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM-12133] Track GraphQl Response ([#3921](https://github.com/DataDog/browser-sdk/pull/3921)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 📝 [DOCS-12292] Improve Vital API documentation ([#3945](https://github.com/DataDog/browser-sdk/pull/3945)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 reduce build boilerplate ([#3938](https://github.com/DataDog/browser-sdk/pull/3938)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 remove glob dependency in favor of native glob from node:fs ([#3950](https://github.com/DataDog/browser-sdk/pull/3950))\n- 👷 Lock file maintenance ([#3942](https://github.com/DataDog/browser-sdk/pull/3942))\n- 👷 fix MODULE_TYPELESS_PACKAGE_JSON warning ([#3906](https://github.com/DataDog/browser-sdk/pull/3906)) [FLAGGING] [LOGS] [RUM-SLIM] [RUM] [WORKER]\n- 👷 Update all non-major dependencies ([#3908](https://github.com/DataDog/browser-sdk/pull/3908)) [FLAGGING] [RUM-REACT] [WORKER]\n- 🔧 factorize typedoc category order ([#3947](https://github.com/DataDog/browser-sdk/pull/3947)) [LOGS] [RUM-REACT] [RUM-SLIM] [RUM]\n- 🔧 Improve manual deploy job ([#3934](https://github.com/DataDog/browser-sdk/pull/3934))\n- 🔧 Bump chrome-webstore-upload from 4.0.0 to 4.0.3 ([#3933](https://github.com/DataDog/browser-sdk/pull/3933))\n- ⚗️ Add beta feature for encoding cookie options ([#3951](https://github.com/DataDog/browser-sdk/pull/3951)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🧹 Refactor Puppeteer imports to use named import 'launch' . ([#3953](https://github.com/DataDog/browser-sdk/pull/3953))\n- fix telemetry errors ([#3952](https://github.com/DataDog/browser-sdk/pull/3952)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Added 'import/enforce-node-protocol-usage' ([#3943](https://github.com/DataDog/browser-sdk/pull/3943))\n\n## v6.23.0\n\n**Public Changes:**\n\n- 🐛 [RUM-11850] Remove anonymous Id when consent is not granted ([#3883](https://github.com/DataDog/browser-sdk/pull/3883)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 📝 improve API documentation ([#3894](https://github.com/DataDog/browser-sdk/pull/3894)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ⚗️ [RUM-5645] Add a ff to avoid using \"fetch keepalive\" ([#3640](https://github.com/DataDog/browser-sdk/pull/3640)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Add check to skip private packages in update-peer-dependency-versions script ([#3929](https://github.com/DataDog/browser-sdk/pull/3929))\n- 👷 Lock file maintenance ([#3931](https://github.com/DataDog/browser-sdk/pull/3931))\n- 👷 Remove version field from package.json in flagging and performances packages ([#3928](https://github.com/DataDog/browser-sdk/pull/3928)) [FLAGGING]\n- 👷 fix check-release script to ignore sub-packages ([#3925](https://github.com/DataDog/browser-sdk/pull/3925))\n- 👷 Update github/codeql-action action to v4 ([#3919](https://github.com/DataDog/browser-sdk/pull/3919))\n- 👷 Update dependency eslint-plugin-jsdoc to v61 ([#3918](https://github.com/DataDog/browser-sdk/pull/3918))\n- 👷 Update dependency chrome-webstore-upload to v4 ([#3920](https://github.com/DataDog/browser-sdk/pull/3920))\n- 👷 Lock file maintenance ([#3909](https://github.com/DataDog/browser-sdk/pull/3909))\n- 👷 Update all non-major dependencies ([#3896](https://github.com/DataDog/browser-sdk/pull/3896)) [RUM-REACT]\n- ✅ fix flaky test ([#3902](https://github.com/DataDog/browser-sdk/pull/3902)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🏷️ update rum-events-format ([#3923](https://github.com/DataDog/browser-sdk/pull/3923)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗️ encode cookie options in cookie value ([#3905](https://github.com/DataDog/browser-sdk/pull/3905)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.22.0\n\n**Public Changes:**\n\n- ✨ enable rum profiler compression when possible ([#3861](https://github.com/DataDog/browser-sdk/pull/3861)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-11434] add support for GraphQL request ([#3891](https://github.com/DataDog/browser-sdk/pull/3891)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Fix react-router peer dependency ([#3892](https://github.com/DataDog/browser-sdk/pull/3892)) [RUM-REACT]\n- 🔥 enforce allowedTrackingOrigin config when initializing the SDK from an extension ([#3885](https://github.com/DataDog/browser-sdk/pull/3885)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Lock file maintenance ([#3899](https://github.com/DataDog/browser-sdk/pull/3899))\n- 👷 Update dependency @playwright/test to v1.55.1 ([#3897](https://github.com/DataDog/browser-sdk/pull/3897))\n- 👷 Update dependency lerna to v9 ([#3898](https://github.com/DataDog/browser-sdk/pull/3898))\n- 👷 Update dependency @playwright/test to v1.55.0 ([#3798](https://github.com/DataDog/browser-sdk/pull/3798))\n- 👷 Update all non-major dependencies ([#3878](https://github.com/DataDog/browser-sdk/pull/3878))\n- 👷 Update dependency eslint-plugin-jsdoc to v60 ([#3880](https://github.com/DataDog/browser-sdk/pull/3880))\n- 👷 Lock file maintenance ([#3881](https://github.com/DataDog/browser-sdk/pull/3881))\n- 🎨 [PANA-4398] Convert SerializeOptions#parentNodePrivacyLevel into a normal function argument ([#3893](https://github.com/DataDog/browser-sdk/pull/3893)) [RUM]\n- 🎨 [PANA-4372] Explicitly scope serialization state ([#3887](https://github.com/DataDog/browser-sdk/pull/3887)) [RUM]\n- 🎨 [PANA-4378] Eliminate need for getTextContent's ignoreWhiteSpace option ([#3889](https://github.com/DataDog/browser-sdk/pull/3889)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔊 delay the session cookie debug telemetry date ([#3895](https://github.com/DataDog/browser-sdk/pull/3895)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- update description ([#3900](https://github.com/DataDog/browser-sdk/pull/3900)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Remove ff for graphql tracking ([#3886](https://github.com/DataDog/browser-sdk/pull/3886)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👥 [PANA-4375] Transfer replay code to session-replay-sdk team in CODEOWNERS ([#3888](https://github.com/DataDog/browser-sdk/pull/3888))\n\n## v6.21.2\n\n**Public Changes:**\n\n- 🐛 [RUM-11596] fix cookie domain within pages with empty location ([#3866](https://github.com/DataDog/browser-sdk/pull/3866)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 add missing ddtags to telemetry events ([#3873](https://github.com/DataDog/browser-sdk/pull/3873)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛[RUM-11247] Pass down error stack to isAllowedTrackingOrigins ([#3824](https://github.com/DataDog/browser-sdk/pull/3824)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 improve condition to worker flag ([#3870](https://github.com/DataDog/browser-sdk/pull/3870)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Pr comment markdown table alignment ([#3876](https://github.com/DataDog/browser-sdk/pull/3876))\n- [devext] fix `yarn dev` command ([#3872](https://github.com/DataDog/browser-sdk/pull/3872))\n\n## v6.21.1\n\n**Public Changes:**\n\n- 📝 adjust Public Api and Init configuration categories ([#3855](https://github.com/DataDog/browser-sdk/pull/3855)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷[RUM-11488] enforce specifying an expiration date for temporary telemetry ([#3825](https://github.com/DataDog/browser-sdk/pull/3825)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Lock file maintenance ([#3864](https://github.com/DataDog/browser-sdk/pull/3864))\n- 👷🐛[performance] fix reporting on main branch ([#3868](https://github.com/DataDog/browser-sdk/pull/3868))\n- 👷 [mob-session] make `test-performances` more resilient ([#3862](https://github.com/DataDog/browser-sdk/pull/3862))\n- 👷 Update dependency lerna to v8.2.4 ([#3863](https://github.com/DataDog/browser-sdk/pull/3863))\n- 👷🐛 fix `create-github-release` ([#3857](https://github.com/DataDog/browser-sdk/pull/3857))\n- 🔧 ignore internal Docker package ([#3865](https://github.com/DataDog/browser-sdk/pull/3865))\n- 🔊 [RUM-11233] collect remote configuration metrics ([#3779](https://github.com/DataDog/browser-sdk/pull/3779)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Remove extra url data collected in telemetry ([#3867](https://github.com/DataDog/browser-sdk/pull/3867)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.21.0\n\n**Public Changes:**\n\n- ✨ [RUM-9181] Service Worker support for Logs ([#3769](https://github.com/DataDog/browser-sdk/pull/3769)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-10146] implement `trackEarlyRequests` ([#3846](https://github.com/DataDog/browser-sdk/pull/3846)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 when a request fails, display the response error ([#3853](https://github.com/DataDog/browser-sdk/pull/3853))\n- 👷 [Performance script] fix regression on size increase warnings ([#3845](https://github.com/DataDog/browser-sdk/pull/3845))\n- 🔧 configure renovate to wait 1 week before upgrading dependencies ([#3850](https://github.com/DataDog/browser-sdk/pull/3850))\n- 👷 [RUM Profiler] send view names as event attributes ([#3851](https://github.com/DataDog/browser-sdk/pull/3851)) [RUM]\n- 🐛 [PANA-4236] Fix flaky startRecorderInitTelemetry test ([#3852](https://github.com/DataDog/browser-sdk/pull/3852)) [RUM]\n\n## v6.20.0\n\n**Public Changes:**\n\n- ✨ [RUM-11701] Add unity as a source override ([#3838](https://github.com/DataDog/browser-sdk/pull/3838)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨⚗️[RUM-11398] Add feature operation step vital APIs ([#3804](https://github.com/DataDog/browser-sdk/pull/3804)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨[RUM-10962][Remote config] support js strategy ([#3766](https://github.com/DataDog/browser-sdk/pull/3766)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 Update dependency eslint-plugin-jsdoc to v57 ([#3842](https://github.com/DataDog/browser-sdk/pull/3842))\n- 👷 Update all non-major dependencies ([#3840](https://github.com/DataDog/browser-sdk/pull/3840)) [RUM-REACT]\n- 👷 Lock file maintenance ([#3843](https://github.com/DataDog/browser-sdk/pull/3843))\n- 👷 Lock file maintenance ([#3831](https://github.com/DataDog/browser-sdk/pull/3831))\n- 👷 Update dependency eslint-plugin-unicorn to v61 ([#3830](https://github.com/DataDog/browser-sdk/pull/3830))\n- 👷 Update actions/upload-pages-artifact action to v4 ([#3829](https://github.com/DataDog/browser-sdk/pull/3829))\n- 👷 Update actions/stale action to v10 ([#3828](https://github.com/DataDog/browser-sdk/pull/3828))\n- 👷 Update actions/setup-node action to v5 ([#3827](https://github.com/DataDog/browser-sdk/pull/3827))\n- 👷 Update all non-major dependencies ([#3826](https://github.com/DataDog/browser-sdk/pull/3826))\n- 👷 Fix Octo release policy ([#3821](https://github.com/DataDog/browser-sdk/pull/3821))\n- ✅ fix flaky test ([#3837](https://github.com/DataDog/browser-sdk/pull/3837)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ improve format validation error output ([#3834](https://github.com/DataDog/browser-sdk/pull/3834)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔊 add telemetry for unexpected session id changes ([#3815](https://github.com/DataDog/browser-sdk/pull/3815)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🏷️ update rum-events-format ([#3847](https://github.com/DataDog/browser-sdk/pull/3847)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗️ [RUM-11434] GraphQL support ([#3805](https://github.com/DataDog/browser-sdk/pull/3805)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ improve browser extension e2e tests ([#3823](https://github.com/DataDog/browser-sdk/pull/3823))\n- 🚨 add a lint rule to forbid `declare global` usage ([#3836](https://github.com/DataDog/browser-sdk/pull/3836))\n- 🔉 report missing configuration options ([#3832](https://github.com/DataDog/browser-sdk/pull/3832)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ci: bump slack-notifier to v3-sdm ([#3809](https://github.com/DataDog/browser-sdk/pull/3809))\n- [RUM-10415] [alt] add privacy allowlist support treewalker ([#3803](https://github.com/DataDog/browser-sdk/pull/3803)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.19.0\n\n**Public Changes:**\n\n- ✨[RUM-10962][Remote config] support dynamic options ([#3743](https://github.com/DataDog/browser-sdk/pull/3743)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [PANA-3960] Allow more queued request data for better session replay reliability ([#3807](https://github.com/DataDog/browser-sdk/pull/3807)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-11439] Fix deflate encoder sending data twice in some cases ([#3806](https://github.com/DataDog/browser-sdk/pull/3806)) [RUM]\n\n**Internal Changes:**\n\n- ✨ [RUM-10044] Support for overriding the source ([#3659](https://github.com/DataDog/browser-sdk/pull/3659)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Fix playwright version in BrowserStack to match package.json ([#3810](https://github.com/DataDog/browser-sdk/pull/3810))\n- 👷 Lock file maintenance ([#3785](https://github.com/DataDog/browser-sdk/pull/3785))\n- 👷 Update all non-major dependencies ([#3782](https://github.com/DataDog/browser-sdk/pull/3782)) [FLAGGING] [RUM-REACT] [RUM] [WORKER]\n- 👷 Update actions/checkout action to v5 ([#3783](https://github.com/DataDog/browser-sdk/pull/3783))\n- 👷 Update dependency eslint-plugin-jsdoc to v54 ([#3784](https://github.com/DataDog/browser-sdk/pull/3784))\n- 👷 Fix create-github-release job ([#3799](https://github.com/DataDog/browser-sdk/pull/3799))\n- 🔧 👷 convert webpack configuration files to TS, improve overall TS config ([#3797](https://github.com/DataDog/browser-sdk/pull/3797)) [FLAGGING] [LOGS] [RUM-SLIM] [RUM] [WORKER]\n- 🔊[RUM-11233] add `remote_configuration_id` to configuration telemetry ([#3778](https://github.com/DataDog/browser-sdk/pull/3778)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.18.1\n\n**Public Changes:**\n\n- 🐛 Support error.dd_context for addReactError API ([#3791](https://github.com/DataDog/browser-sdk/pull/3791)) [RUM-REACT]\n\n**Internal Changes:**\n\n- ✨⚗️ [RUM-10146] implement early request collection ([#3740](https://github.com/DataDog/browser-sdk/pull/3740)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 [RUM-11361] Replace github PAT by using dd octo ([#3725](https://github.com/DataDog/browser-sdk/pull/3725))\n- 👷 [RUM-11361] Fix read octo policy ([#3789](https://github.com/DataDog/browser-sdk/pull/3789))\n- 👷 [RUM-11361] Add octo policies ([#3787](https://github.com/DataDog/browser-sdk/pull/3787))\n- 👷‍♀️ [RUM-11139] Improve textual content extraction for action names ([#3759](https://github.com/DataDog/browser-sdk/pull/3759)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 add `consistent-type-specifier-style: 'prefer-top-level'` eslint rule ([#3780](https://github.com/DataDog/browser-sdk/pull/3780)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 Lock file maintenance ([#3772](https://github.com/DataDog/browser-sdk/pull/3772))\n- 🔧 Rename state.yml to stale.yml ([#3781](https://github.com/DataDog/browser-sdk/pull/3781))\n- 🎨 [PANA-3877] Consolidate sample rates for replay telemetry ([#3795](https://github.com/DataDog/browser-sdk/pull/3795)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✅ [RUM-10146] mock global performance buffer when mocking PerformanceObserver ([#3752](https://github.com/DataDog/browser-sdk/pull/3752)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔊[PANA-3819] Add telemetry for recorder initialization ([#3793](https://github.com/DataDog/browser-sdk/pull/3793)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔊[PANA-3818] Add telemetry for DOM serialization performance ([#3792](https://github.com/DataDog/browser-sdk/pull/3792)) [RUM]\n- 🔊[PANA-3817] Add telemetry for initial view metrics ([#3788](https://github.com/DataDog/browser-sdk/pull/3788)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ⚡♻️ simplify replica ([#3552](https://github.com/DataDog/browser-sdk/pull/3552)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ use exclicit resource management for octo tokens ([#3790](https://github.com/DataDog/browser-sdk/pull/3790))\n- Pin GitHub Actions ([#3786](https://github.com/DataDog/browser-sdk/pull/3786))\n\n## v6.18.0\n\n**Public Changes:**\n\n- ✨[RUM-10960][Remote config] add support for new static fields ([#3731](https://github.com/DataDog/browser-sdk/pull/3731)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM-REACT] Fix react V7 import and add E2E test ([#3758](https://github.com/DataDog/browser-sdk/pull/3758)) [RUM-REACT]\n- 🐛 [RUM Profiler] Fix discrepancy on view-id correlation ([#3776](https://github.com/DataDog/browser-sdk/pull/3776)) [RUM]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#3771](https://github.com/DataDog/browser-sdk/pull/3771)) [RUM-REACT]\n- 👷 remove watch_cookie_without_lock experimental feature flag ([#3773](https://github.com/DataDog/browser-sdk/pull/3773)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Bump chrome to 139.0.7258.66-1 ([#3764](https://github.com/DataDog/browser-sdk/pull/3764))\n- 👷 Update all non-major dependencies ([#3753](https://github.com/DataDog/browser-sdk/pull/3753)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🔊 Add Url Extension Telemetry ([#3768](https://github.com/DataDog/browser-sdk/pull/3768)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.17.0\n\n**Public Changes:**\n\n- ✨ don't write lock to cookie for read only operation ([#3728](https://github.com/DataDog/browser-sdk/pull/3728)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [FFL-450] Add support for exposures track ([#3738](https://github.com/DataDog/browser-sdk/pull/3738)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨[RUM-10825] Add hot-reload to developer-extension ([#3687](https://github.com/DataDog/browser-sdk/pull/3687))\n- 📝 Reference the api reference ([#3739](https://github.com/DataDog/browser-sdk/pull/3739))\n- 📝 Typedoc setup and theme ([#3676](https://github.com/DataDog/browser-sdk/pull/3676))\n\n**Internal Changes:**\n\n- 👷 Update dependency eslint-plugin-jsdoc to v52 ([#3755](https://github.com/DataDog/browser-sdk/pull/3755))\n- 👷 Lock file maintenance ([#3757](https://github.com/DataDog/browser-sdk/pull/3757))\n- 👷 Allow `merge-into-stating` CI job to fail ([#3750](https://github.com/DataDog/browser-sdk/pull/3750))\n- 👷 🏷️ `scripts/` TS migration ([#3732](https://github.com/DataDog/browser-sdk/pull/3732)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 add a stale issue workflow ([#3707](https://github.com/DataDog/browser-sdk/pull/3707))\n- 👷 Update dependency eslint-plugin-unicorn to v60 ([#3734](https://github.com/DataDog/browser-sdk/pull/3734))\n- 👷 Update all non-major dependencies ([#3704](https://github.com/DataDog/browser-sdk/pull/3704)) [FLAGGING] [RUM-REACT] [WORKER]\n- 👷add back html coverage ([#3741](https://github.com/DataDog/browser-sdk/pull/3741))\n- 👷 Update actions/configure-pages action to v5 ([#3733](https://github.com/DataDog/browser-sdk/pull/3733))\n- 👷 hide tag sanitization console warning in unit tests ([#3736](https://github.com/DataDog/browser-sdk/pull/3736)) [LOGS]\n- 👷 Update dependency webpack-cli to v6 ([#3735](https://github.com/DataDog/browser-sdk/pull/3735))\n- 👷 Lock file maintenance ([#3705](https://github.com/DataDog/browser-sdk/pull/3705))\n- 👷 First deploy for api reference + fix yaml ([#3727](https://github.com/DataDog/browser-sdk/pull/3727))\n- 👷 fix coverage report directory ([#3737](https://github.com/DataDog/browser-sdk/pull/3737))\n- Revert \"👷 hide tag sanitization console warning in unit tests\" [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 hide tag sanitization console warning in unit tests [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 upload code coverage report to datadog ([#3710](https://github.com/DataDog/browser-sdk/pull/3710))\n- 👷 Add more telemetry debug for cookie configuration ([#3709](https://github.com/DataDog/browser-sdk/pull/3709)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ [Remote config] add a remote config e2e scenario ([#3721](https://github.com/DataDog/browser-sdk/pull/3721)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔊 [RUM-11144] Apply telemetry context to early telemetry message ([#3745](https://github.com/DataDog/browser-sdk/pull/3745)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗ [PANA-3411] Add telemetry for session replay reliability ([#3688](https://github.com/DataDog/browser-sdk/pull/3688)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ use fetch to retrieve remote configuration ([#3723](https://github.com/DataDog/browser-sdk/pull/3723)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ Move customer context from assembly to collection ([#3681](https://github.com/DataDog/browser-sdk/pull/3681)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.16.0\n\n**Public Changes:**\n\n- Revert \"✨ don't write lock to cookie for read only operation ([#3652](https://github.com/DataDog/browser-sdk/pull/3652))\" ([#3719](https://github.com/DataDog/browser-sdk/pull/3719)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-8313] Remove URL polyfill and retrieve native URL constructor ([#3682](https://github.com/DataDog/browser-sdk/pull/3682)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 bump playwright to match browserStack version ([#3714](https://github.com/DataDog/browser-sdk/pull/3714))\n- Add telemetry to isUnsupportedExtensionEnvironment warning ([#3717](https://github.com/DataDog/browser-sdk/pull/3717)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Bump OS and device version, and fix the spec ([#3716](https://github.com/DataDog/browser-sdk/pull/3716)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.15.0\n\n**Public Changes:**\n\n- ✨ [PANA-3449] Apply separate event limits for different kinds of telemetry ([#3692](https://github.com/DataDog/browser-sdk/pull/3692)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-10006] add tagging capabilities to loggers in the Logs SDK ([#3616](https://github.com/DataDog/browser-sdk/pull/3616)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 prevent log reporting after consent revocation ([#3680](https://github.com/DataDog/browser-sdk/pull/3680)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 📝 [RUM-10899] Add API reference using typedoc ([#3677](https://github.com/DataDog/browser-sdk/pull/3677)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 reduce the number of concurrent workers used by playwright ([#3706](https://github.com/DataDog/browser-sdk/pull/3706))\n- 👷 simplify test apps build ([#3702](https://github.com/DataDog/browser-sdk/pull/3702))\n- 👷 use SIGKILL instead of SIGTERM to kill child jobs ([#3699](https://github.com/DataDog/browser-sdk/pull/3699))\n- 👷 use our own `deepClone` method instead of `structuredClone` ([#3700](https://github.com/DataDog/browser-sdk/pull/3700)) [RUM]\n- 👷 Add cookie options to telemetry debug ([#3693](https://github.com/DataDog/browser-sdk/pull/3693)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [Remote config] use types from JSON schema ([#3694](https://github.com/DataDog/browser-sdk/pull/3694)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Bump device version in unit tests ([#3703](https://github.com/DataDog/browser-sdk/pull/3703))\n- [RUM Profiler] fix unit test, remove RegExp lookbehind ([#3701](https://github.com/DataDog/browser-sdk/pull/3701)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.14.0\n\n**Public Changes:**\n\n- ✨ [RUM-10145] collect errors on module evaluation ([#3622](https://github.com/DataDog/browser-sdk/pull/3622)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ don't write lock to cookie for read only operation ([#3652](https://github.com/DataDog/browser-sdk/pull/3652)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-10223] Add locale and timezone data to view event ([#3598](https://github.com/DataDog/browser-sdk/pull/3598)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Allow service and version to be modifiable for long_task and vital events ([#3691](https://github.com/DataDog/browser-sdk/pull/3691)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [PANA-3447] Don't send customer data telemetry for any batch with no RUM events ([#3689](https://github.com/DataDog/browser-sdk/pull/3689)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🏷️ add ap2 site to TypeScript types ([#3672](https://github.com/DataDog/browser-sdk/pull/3672)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 simplify test apps build ([#3702](https://github.com/DataDog/browser-sdk/pull/3702))\n- 👷 use SIGKILL instead of SIGTERM to kill child jobs ([#3699](https://github.com/DataDog/browser-sdk/pull/3699))\n- 👷 use our own `deepClone` method instead of `structuredClone` ([#3700](https://github.com/DataDog/browser-sdk/pull/3700)) [RUM]\n- 👷 Add cookie options to telemetry debug ([#3693](https://github.com/DataDog/browser-sdk/pull/3693)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update all non-major dependencies ([#3673](https://github.com/DataDog/browser-sdk/pull/3673)) [FLAGGING] [WORKER]\n- 👷 Lock file maintenance ([#3675](https://github.com/DataDog/browser-sdk/pull/3675))\n- 👷 fix `yarn test` and `yarn test:unit:watch` commands ([#3684](https://github.com/DataDog/browser-sdk/pull/3684))\n- 👷 fix `yarn test` and `yarn test:unit:watch` commands ([#3683](https://github.com/DataDog/browser-sdk/pull/3683))\n- 👷 Update Node.js to v24 ([#3522](https://github.com/DataDog/browser-sdk/pull/3522)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷‍♀️ [devx] Add cursor rules to improve testing experience ([#3662](https://github.com/DataDog/browser-sdk/pull/3662))\n- 👷 add `--spec` option to `yarn test:unit` ([#3678](https://github.com/DataDog/browser-sdk/pull/3678))\n- 👷 add `step-7_` prefix to `create-github-release` ci job ([#3668](https://github.com/DataDog/browser-sdk/pull/3668))\n- 👷 ignore @playwright/test updates ([#3666](https://github.com/DataDog/browser-sdk/pull/3666))\n- ♻️ [Remote config] use types from JSON schema ([#3694](https://github.com/DataDog/browser-sdk/pull/3694)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Bump device version in unit tests ([#3703](https://github.com/DataDog/browser-sdk/pull/3703))\n- [RUM Profiler] fix unit test, remove RegExp lookbehind ([#3701](https://github.com/DataDog/browser-sdk/pull/3701)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ [RUM-10900] Introduce assemble telemetry hook ([#3685](https://github.com/DataDog/browser-sdk/pull/3685)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ Enforce using interface over type ([#3686](https://github.com/DataDog/browser-sdk/pull/3686)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- [RUM Profiler] add default view names to profiles ([#3669](https://github.com/DataDog/browser-sdk/pull/3669)) [RUM]\n\n## v6.13.0\n\n**Public Changes:**\n\n- 🐛 [RUM-146] Modify label behavior in dead click logic ([#3642](https://github.com/DataDog/browser-sdk/pull/3642)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM Profiler] Sticky sampling based on session ([#3661](https://github.com/DataDog/browser-sdk/pull/3661)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 [RUM-9918] add a node version check ([#3663](https://github.com/DataDog/browser-sdk/pull/3663))\n- 👷 Update dependency eslint-plugin-jsdoc to v51 ([#3636](https://github.com/DataDog/browser-sdk/pull/3636))\n- 👷 Update actions/checkout action to v4 ([#3565](https://github.com/DataDog/browser-sdk/pull/3565))\n- 👷 Lock file maintenance ([#3540](https://github.com/DataDog/browser-sdk/pull/3540))\n- 👷 Update all non-major dependencies ([#3635](https://github.com/DataDog/browser-sdk/pull/3635)) [RUM-REACT]\n- 👷 [RUM-9218] Adjust E2E setup to use cross-origin URLs for loading CDN bundles ([#3657](https://github.com/DataDog/browser-sdk/pull/3657)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 Bump chrome to 138.0.7204.49-1 ([#3658](https://github.com/DataDog/browser-sdk/pull/3658))\n- ♻️ [RUM-10005] Exposes `addEvent` instead of `strategy` to plugins ([#3567](https://github.com/DataDog/browser-sdk/pull/3567)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-10407] Use hooks for Logs SDK to decouple session ([#3643](https://github.com/DataDog/browser-sdk/pull/3643)) [LOGS]\n- 👷 [RUM Profiler] Add `_dd.profiling` context to Long Task and View events ([#3583](https://github.com/DataDog/browser-sdk/pull/3583)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.12.3\n\n**Plublic Changes:**\n\n- 🐛fix: skip unwanted stackframe on custom errors for faulty browsers ([#3555](https://github.com/DataDog/browser-sdk/pull/3555)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛🍒 [RUM-10101] Persist session cookie to one year when opt-in anonymous user tracking ([#3559](https://github.com/DataDog/browser-sdk/pull/3559)) ([#3654](https://github.com/DataDog/browser-sdk/pull/3654)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.12.2\n\n**Public Changes:**\n\n- 🐛 ignore init() if Synthetics will inject its own instance of RUM ([#3649](https://github.com/DataDog/browser-sdk/pull/3649)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 reduce playwright workers to improve reliability ([#3650](https://github.com/DataDog/browser-sdk/pull/3650))\n- 🔊 add cookie data in debug logs ([#3647](https://github.com/DataDog/browser-sdk/pull/3647)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.12.1\n\n**Public Changes:**\n\n- 🐛 [RUM-10366] mitigate cookie dead lock ([#3637](https://github.com/DataDog/browser-sdk/pull/3637)) [LOGS] [RUM] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 🔧 create a GitHub release when deploying ([#3644](https://github.com/DataDog/browser-sdk/pull/3644))\n- ♻️ [RUM-10311] Use hooks for Logs SDK to decouple user ([#3620](https://github.com/DataDog/browser-sdk/pull/3620)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.12.0\n\n**Public Changes:**\n\n- ✨[RUM Profiler] remove profiling experimental flag ([#3639](https://github.com/DataDog/browser-sdk/pull/3639)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 fix typecheck issue + increase base tsconfig coverage ([#3625](https://github.com/DataDog/browser-sdk/pull/3625))\n- 🔊 [IR-39238] Add session diagnostic telemetry and improve configuration timing ([#3629](https://github.com/DataDog/browser-sdk/pull/3629)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-10074] Use createTest in developer extensions tests ([#3628](https://github.com/DataDog/browser-sdk/pull/3628))\n- Update changelog-to-confluence: Update secret names, name of page being published ([#3631](https://github.com/DataDog/browser-sdk/pull/3631))\n\n## v6.11.0\n\n**Public Changes:**\n\n- ✨ [RUM-7213] DOM mutation ignoring ([#3606](https://github.com/DataDog/browser-sdk/pull/3606)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#3615](https://github.com/DataDog/browser-sdk/pull/3615)) [RUM-REACT]\n- 👷 Configure devflow integration branch ([#3619](https://github.com/DataDog/browser-sdk/pull/3619))\n- 👷[RUM-9996] move ap2 deployment to minor dcs ([#3601](https://github.com/DataDog/browser-sdk/pull/3601))\n- 👷 fix update-branch script success condition ([#3612](https://github.com/DataDog/browser-sdk/pull/3612))\n- 👌 [RUM-10290] Remove built extensions from ignored in eslint.config ([#3609](https://github.com/DataDog/browser-sdk/pull/3609))\n- 👷 [Events] Add `_dd.sdk_name` to common context ([#3611](https://github.com/DataDog/browser-sdk/pull/3611)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🔈 [RUM-10284] collect telemetry before starting the session manager ([#3602](https://github.com/DataDog/browser-sdk/pull/3602)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.10.1\n\n**Public Changes:**\n\n- Revert \"🐛 [RUM-10101] Persist session cookie to one year when opt-in anonymous user tracking ([#3559](https://github.com/DataDog/browser-sdk/pull/3559))\" ([#3608](https://github.com/DataDog/browser-sdk/pull/3608)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷release: do not try to update lockfiles of ignore app ([#3600](https://github.com/DataDog/browser-sdk/pull/3600))\n- ♻️ [RUM-10256] Use hooks for Logs SDK to decouple global context ([#3594](https://github.com/DataDog/browser-sdk/pull/3594)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.10.0\n\n**Public Changes:**\n\n- ✨[RUM-9915] add `allowedTrackingOrigins` for Extensions ([#3517](https://github.com/DataDog/browser-sdk/pull/3517)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 move testing extensions folder ([#3595](https://github.com/DataDog/browser-sdk/pull/3595))\n- 👷 [RUM-9996] configure ap2 monitor check + sourcemap upload\n- 👷 Update all non-major dependencies ([#3589](https://github.com/DataDog/browser-sdk/pull/3589)) [RUM-REACT] [WORKER]\n- 🔧 update yarn version to 4.9.1 in package.json ([#3591](https://github.com/DataDog/browser-sdk/pull/3591))\n- ♻️ [RUM-10238] Use hooks for Logs SDK to decouple account ([#3590](https://github.com/DataDog/browser-sdk/pull/3590)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗ Interim integration instructions/script for unpublished flagging npm package. ([#3585](https://github.com/DataDog/browser-sdk/pull/3585)) [FLAGGING]\n\n## v6.9.0\n\n**Public Changes:**\n\n- ✨ use error.dd_context when logging an error ([#3562](https://github.com/DataDog/browser-sdk/pull/3562)) [LOGS]\n- ✨[RUM-260] Support bfcache restore for web vitals ([#3527](https://github.com/DataDog/browser-sdk/pull/3527)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-10002] Verify the document was not hidden while loading ([#3573](https://github.com/DataDog/browser-sdk/pull/3573)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM-9987] Bump attribute data url limit to 1Mb ([#3551](https://github.com/DataDog/browser-sdk/pull/3551)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔥 🐛 fix Next.js 12 + swcMinify compatibility ([#3577](https://github.com/DataDog/browser-sdk/pull/3577)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 📝 update bundle list ([#3572](https://github.com/DataDog/browser-sdk/pull/3572))\n\n**Internal Changes:**\n\n- 👷 Bump chrome to 137.0.7151.55-1 ([#3578](https://github.com/DataDog/browser-sdk/pull/3578))\n- ✅ Automatic mock clock cleanup ([#3581](https://github.com/DataDog/browser-sdk/pull/3581)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ Fix usage of non-existent configuration options in remoteConfiguration.spec.ts ([#3576](https://github.com/DataDog/browser-sdk/pull/3576)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM Profiler] Simplify & fix logic for Long Task registry ([#3569](https://github.com/DataDog/browser-sdk/pull/3569)) [RUM]\n\n## v6.8.0\n\n**Public Changes:**\n\n- ✨ [RUM-10010] Send the user, account and session using the trace baggage header ([#3547](https://github.com/DataDog/browser-sdk/pull/3547)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-10101] Persist session cookie to one year when opt-in anonymous user tracking ([#3559](https://github.com/DataDog/browser-sdk/pull/3559)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [devext] synchronize network rules on extension start ([#3560](https://github.com/DataDog/browser-sdk/pull/3560))\n- ⚡️ [RUM-10104] avoid polling the cookie for `ciVisibilityContext` ([#3561](https://github.com/DataDog/browser-sdk/pull/3561)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 [FFL-23] Create datadog-flagging package ([#3553](https://github.com/DataDog/browser-sdk/pull/3553)) [FLAGGING]\n- 👷️ [RUM-9996] fix internal source maps upload for root upload type ([#3544](https://github.com/DataDog/browser-sdk/pull/3544))\n- 👷 Update all non-major dependencies ([#3539](https://github.com/DataDog/browser-sdk/pull/3539)) [RUM-REACT]\n- 🔧 add flagging path to tsconfig ([#3566](https://github.com/DataDog/browser-sdk/pull/3566))\n- 🔧 apply sourcemaps to unit tests common chunk ([#3545](https://github.com/DataDog/browser-sdk/pull/3545))\n- Add Workflow: Changelog To Confluence ([#3546](https://github.com/DataDog/browser-sdk/pull/3546))\n- ♻️ [RUM-9990] Use hooks for Logs SDK to decouple rumInternalContext ([#3537](https://github.com/DataDog/browser-sdk/pull/3537)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗ [RUM-7213] DOM mutation ignoring ([#3276](https://github.com/DataDog/browser-sdk/pull/3276)) [FLAGGING] [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.7.0\n\n**Public Changes:**\n\n- ✨ Allow overriding service and version for views events in beforeSend ([#3530](https://github.com/DataDog/browser-sdk/pull/3530)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ Add developer extension support for replay sandbox local development ([#3511](https://github.com/DataDog/browser-sdk/pull/3511))\n- 🐛 [RUM-9738] quickfix switchToAbsoluteUrl ([#3518](https://github.com/DataDog/browser-sdk/pull/3518)) [RUM]\n- 📝 mention missing `compressIntakeRequests` support in rum-slim readme ([#3531](https://github.com/DataDog/browser-sdk/pull/3531)) [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷️[RUM-9996] Support deployment for ap2 datacenter ([#3538](https://github.com/DataDog/browser-sdk/pull/3538))\n- 👷 Lock file maintenance ([#3526](https://github.com/DataDog/browser-sdk/pull/3526))\n- 👷️enable renovate `lockFileMaintenance` ([#3525](https://github.com/DataDog/browser-sdk/pull/3525))\n- 👷️Bump nx resolution ([#3523](https://github.com/DataDog/browser-sdk/pull/3523))\n- 👷 Update mantine monorepo to v8 ([#3521](https://github.com/DataDog/browser-sdk/pull/3521))\n- 👷 Update all non-major dependencies ([#3520](https://github.com/DataDog/browser-sdk/pull/3520)) [RUM-REACT] [WORKER]\n- 👷 Update all non-major dependencies ([#3515](https://github.com/DataDog/browser-sdk/pull/3515)) [RUM-REACT]\n- 👷 Update dependency eslint-plugin-unicorn to v59 ([#3504](https://github.com/DataDog/browser-sdk/pull/3504))\n- 👷 Update all non-major dependencies ([#3503](https://github.com/DataDog/browser-sdk/pull/3503)) [RUM-REACT] [WORKER]\n- 🔧 [RUM-9766] include bundle chunks in NPM packages ([#3513](https://github.com/DataDog/browser-sdk/pull/3513)) [LOGS] [RUM-SLIM] [RUM] [WORKER]\n- Add dd trusted to extension visibilityChange events ([#3536](https://github.com/DataDog/browser-sdk/pull/3536))\n- ♻️ [RUM-9614] Decouple default context from assembly using hooks ([#3498](https://github.com/DataDog/browser-sdk/pull/3498)) [RUM] [RUM-REACT] [RUM-SLIM]\n- [RUM Profiler] Use clocks for start/end time ([#3510](https://github.com/DataDog/browser-sdk/pull/3510)) [RUM]\n- ⚗ Add experimental feature flag to enable intake request tracking ([#3509](https://github.com/DataDog/browser-sdk/pull/3509)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Bump replay sandbox to 0.119.0 ([#3508](https://github.com/DataDog/browser-sdk/pull/3508))\n- ♻️ [RUM-9667] refactor stack trace computation ([#3499](https://github.com/DataDog/browser-sdk/pull/3499)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.6.4\n\n**Public Changes:**\n\n- ✨ Add publicPath configuration to webpack setups ([#3488](https://github.com/DataDog/browser-sdk/pull/3488)) [LOGS] [RUM-SLIM] [RUM] [WORKER]\n- ✨ Allow to retrieve records in the developer-extension Replay tab ([#3482](https://github.com/DataDog/browser-sdk/pull/3482))\n- ✨ [RUM-9302] Page state consolidation ([#3454](https://github.com/DataDog/browser-sdk/pull/3454)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [devext] fix \"Use development bundle on NPM setup\" ([#3502](https://github.com/DataDog/browser-sdk/pull/3502)) [LOGS] [RUM-SLIM] [RUM] [WORKER]\n- 🐛 [RUM-9465] Add support for parsing Safari Wasm stack trace ([#3481](https://github.com/DataDog/browser-sdk/pull/3481)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Add profiler chunk URL to redirect rules and constants ([#3485](https://github.com/DataDog/browser-sdk/pull/3485))\n- 🐛 Improve context properties sanitization ([#3475](https://github.com/DataDog/browser-sdk/pull/3475)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷️scripts: extract test:e2e:init ([#3501](https://github.com/DataDog/browser-sdk/pull/3501))\n- 👷 Update PR template ([#3490](https://github.com/DataDog/browser-sdk/pull/3490))\n- 👷 Update dependency express to v5 ([#3473](https://github.com/DataDog/browser-sdk/pull/3473))\n- 👷 Update all non-major dependencies ([#3495](https://github.com/DataDog/browser-sdk/pull/3495)) [RUM-REACT] [WORKER]\n- 👷 Update all non-major dependencies ([#3472](https://github.com/DataDog/browser-sdk/pull/3472)) [RUM-REACT] [WORKER]\n- 👷 Enable timestamps for GitLab CI logs in configuration ([#3462](https://github.com/DataDog/browser-sdk/pull/3462))\n- 👷 Update chunk name formatting to use underscore instead of dash ([#3483](https://github.com/DataDog/browser-sdk/pull/3483))\n- 👷 use dash instead of dot for joining chunk name in size stats ([#3474](https://github.com/DataDog/browser-sdk/pull/3474))\n- 👷 [RUM-9370] Remove unused code ([#3470](https://github.com/DataDog/browser-sdk/pull/3470)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 add lazy loaded bundles sizes ([#3468](https://github.com/DataDog/browser-sdk/pull/3468))\n- ✅ hide unexpected unit test logs ([#3486](https://github.com/DataDog/browser-sdk/pull/3486)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗️️✨️[RUM-9672] trace baggage: rename `usr` to `user` ([#3505](https://github.com/DataDog/browser-sdk/pull/3505)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ [RUM-9549] Decouple the session context from assembly using hooks ([#3489](https://github.com/DataDog/browser-sdk/pull/3489)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔥 Remove url missing telemetry ([#3497](https://github.com/DataDog/browser-sdk/pull/3497)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️trackCumulativeLayoutShift: Return the source with the biggest impacting area [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ Decouple the connectivity context from assembly using hooks ([#3494](https://github.com/DataDog/browser-sdk/pull/3494)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ Decouple the display context from assembly using hooks ([#3493](https://github.com/DataDog/browser-sdk/pull/3493)) [RUM] [RUM-REACT] [RUM-SLIM]\n- [RUM-8527] remove react doc ([#3487](https://github.com/DataDog/browser-sdk/pull/3487)) [RUM-REACT]\n- ⚗️ ✨ [RUM-8365] Propagate session id in `baggage` header ([#3430](https://github.com/DataDog/browser-sdk/pull/3430)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ [RUM-8767] Use assembly hooks for global, user and account context ([#3457](https://github.com/DataDog/browser-sdk/pull/3457)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.6.3\n\n**Public Changes:**\n\n- 🐛 Add missing original error for beforeSend context ([#3442](https://github.com/DataDog/browser-sdk/pull/3442)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚡️ Remove customer data track for perf and bundle size ([#3393](https://github.com/DataDog/browser-sdk/pull/3393)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Filter out package.json files from test/apps directory in release check script ([#3466](https://github.com/DataDog/browser-sdk/pull/3466))\n- 👷 [RUM-8159] E2E test for the react integration ([#3428](https://github.com/DataDog/browser-sdk/pull/3428))\n- 👷 Bump chrome to 135.0.7049.52-1 ([#3458](https://github.com/DataDog/browser-sdk/pull/3458))\n- 👷 [RUM-259] update test/app to use local tarballs ([#3335](https://github.com/DataDog/browser-sdk/pull/3335)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update dependency eslint-plugin-unicorn to v58 ([#3452](https://github.com/DataDog/browser-sdk/pull/3452))\n- 👷 Update all non-major dependencies ([#3451](https://github.com/DataDog/browser-sdk/pull/3451)) [RUM-REACT]\n- use baggage for user.id / account.id forwarding ([#3445](https://github.com/DataDog/browser-sdk/pull/3445)) [RUM] [RUM-REACT] [RUM-SLIM]\n- Lazy load profiler error handling + simplify profilerAPI ([#3460](https://github.com/DataDog/browser-sdk/pull/3460)) [RUM]\n- 🐛 Update .npmignore to include react-router 7 ([#3464](https://github.com/DataDog/browser-sdk/pull/3464)) [RUM-REACT]\n- [RUM Profiler] Fix collection of profiles after visibility change ([#3459](https://github.com/DataDog/browser-sdk/pull/3459)) [RUM]\n- ♻️ Refactor cookieObservable to not rely on cookieStore ([#3456](https://github.com/DataDog/browser-sdk/pull/3456)) [RUM] [RUM-REACT] [RUM-SLIM]\n- [RUM Profiler] Improvements around Views and Long Tasks ([#3450](https://github.com/DataDog/browser-sdk/pull/3450)) [RUM]\n- ♻️ [RUM-9126] Decouple common contexts from rumPublicApi ([#3432](https://github.com/DataDog/browser-sdk/pull/3432)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.6.2\n\n**Public Changes:**\n\n- 🐛 fix TypeScript 4 compatibility ([#3448](https://github.com/DataDog/browser-sdk/pull/3448)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-99] don't stop RUM/Replay on beforeunload ([#3406](https://github.com/DataDog/browser-sdk/pull/3406)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- ✨ Update TypeScript configuration for e2e tests to include 'noEmit' option ([#3437](https://github.com/DataDog/browser-sdk/pull/3437))\n- 👷 Update all non-major dependencies ([#3438](https://github.com/DataDog/browser-sdk/pull/3438)) [RUM-REACT]\n- 👌 [RUM-99] don't set views as inactive when the page is exiting ([#3446](https://github.com/DataDog/browser-sdk/pull/3446)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.6.1\n\n**Public Changes:**\n\n- Revert \"⚡️ use `import()` for lazy loading chunks ([#3399](https://github.com/DataDog/browser-sdk/pull/3399))\" ([#3440](https://github.com/DataDog/browser-sdk/pull/3440))\n- 📝 [RUM-7705] Add js doc about option that need to be aligned ([#3410](https://github.com/DataDog/browser-sdk/pull/3410)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.6.0\n\n**Public Changes:**\n\n- ✨ [RUM-7387] Add user id and account id to trace header ([#3395](https://github.com/DataDog/browser-sdk/pull/3395)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-8606] Track First Hidden before init ([#3391](https://github.com/DataDog/browser-sdk/pull/3391)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [devex] fix non-string log message ([#3426](https://github.com/DataDog/browser-sdk/pull/3426))\n- ⚡️ use `import()` for lazy loading chunks ([#3399](https://github.com/DataDog/browser-sdk/pull/3399))\n- ⚡️ [RUM-8664] do not update customer data when value does not changes ([#3384](https://github.com/DataDog/browser-sdk/pull/3384)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 [RUM-105] use local dev server for local e2e tests ([#3420](https://github.com/DataDog/browser-sdk/pull/3420))\n- 👷 Enable the Terser 'unsafe' option ([#3418](https://github.com/DataDog/browser-sdk/pull/3418))\n- 👷 Update all non-major dependencies ([#3408](https://github.com/DataDog/browser-sdk/pull/3408)) [RUM-REACT]\n- 👷 Enable Terser's unsafe_methods option ([#3416](https://github.com/DataDog/browser-sdk/pull/3416))\n- 👷 Use four Terser passes ([#3414](https://github.com/DataDog/browser-sdk/pull/3414))\n- 👷 Bump chrome to 134.0.6998.35-1 with signed commit ([#3392](https://github.com/DataDog/browser-sdk/pull/3392))\n- 🔧 Update GitLab CI configuration to exclude current staging branch from performance tests ([#3425](https://github.com/DataDog/browser-sdk/pull/3425))\n- ♻️ [RUM-8795] Replace XHR with Fetch for HTTP requests ([#3417](https://github.com/DataDog/browser-sdk/pull/3417)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗️[RUM Profiler] Integrate Profiler into SDK ([#3340](https://github.com/DataDog/browser-sdk/pull/3340)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🚨 [RUM-8945] add a rule to make sure we don't import dev deps in prod files ([#3412](https://github.com/DataDog/browser-sdk/pull/3412))\n\n## v6.5.1\n\n**Public Changes:**\n\n- 🐛 fix `@datadog/browser-rum-react/react-router-vX` import ([#3405](https://github.com/DataDog/browser-sdk/pull/3405)) [RUM-REACT]\n- 🐛 [RUM-8429] Report an error when lazy loading the recorder module fails ([#3326](https://github.com/DataDog/browser-sdk/pull/3326)) [RUM]\n\n**Internal Changes:**\n\n- 👷 Update dependency copy-webpack-plugin to v13 ([#3387](https://github.com/DataDog/browser-sdk/pull/3387))\n- 👷 filter out \"Layout was forced...\" console warning in e2e tests on Firefox ([#3397](https://github.com/DataDog/browser-sdk/pull/3397))\n- 🔧 update volta config ([#3403](https://github.com/DataDog/browser-sdk/pull/3403))\n- docs: add missing JSDoc comment for beforeSend configuration option ([#3404](https://github.com/DataDog/browser-sdk/pull/3404)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.5.0\n\n**Public Changes:**\n\n- ✨ [RUM-8622] introduce session-consistent trace sample rate ([#3381](https://github.com/DataDog/browser-sdk/pull/3381)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-8744] CLS tracking: provide cls `devicePixelRatio` to adjust cls rect scale ([#3389](https://github.com/DataDog/browser-sdk/pull/3389)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#3386](https://github.com/DataDog/browser-sdk/pull/3386)) [RUM-REACT]\n- 👷 fix tags to match the test optimisation configuration attributes ([#3337](https://github.com/DataDog/browser-sdk/pull/3337)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ Clean logs in unit tests ([#3390](https://github.com/DataDog/browser-sdk/pull/3390)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Bump serialize-javascript from 6.0.1 to 6.0.2 in /test/app ([#3383](https://github.com/DataDog/browser-sdk/pull/3383))\n- ♻️ [RUM-8716] Use assembly hook for page states ([#3362](https://github.com/DataDog/browser-sdk/pull/3362)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.4.0\n\n**Public Changes:**\n\n- ✨ [RUM-5500] React-router v7 support ([#3299](https://github.com/DataDog/browser-sdk/pull/3299)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-7459] Collect error context from a custom Error field ([#3320](https://github.com/DataDog/browser-sdk/pull/3320)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-7958] Deprecate setUser without required Id ([#3262](https://github.com/DataDog/browser-sdk/pull/3262)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-7019] Add setAccount API and account in RUM events ([#3242](https://github.com/DataDog/browser-sdk/pull/3242)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Fix empty string for resource url in LCP ([#3378](https://github.com/DataDog/browser-sdk/pull/3378)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [extension] fix Vital events rendering ([#3366](https://github.com/DataDog/browser-sdk/pull/3366)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 remove webdriverio dependency ([#3373](https://github.com/DataDog/browser-sdk/pull/3373))\n- 👷 remove unused global jasmine types ([#3374](https://github.com/DataDog/browser-sdk/pull/3374)) [RUM]\n- 👷 Update all non-major dependencies ([#3367](https://github.com/DataDog/browser-sdk/pull/3367))\n- 👷 Update dependency globals to v16 ([#3370](https://github.com/DataDog/browser-sdk/pull/3370))\n- 👷 Update Node.js to v23 ([#3368](https://github.com/DataDog/browser-sdk/pull/3368))\n- 👷 Update dependency eslint-plugin-unicorn to v57 ([#3369](https://github.com/DataDog/browser-sdk/pull/3369))\n- 👷 format rum event format validation errors ([#3363](https://github.com/DataDog/browser-sdk/pull/3363))\n- 👷 Update dependency ajv to v8 ([#3348](https://github.com/DataDog/browser-sdk/pull/3348)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 👷 only connect to background script when the extension is actually loaded ([#3350](https://github.com/DataDog/browser-sdk/pull/3350))\n- 👷 Update dependency emoji-name-map to v2 ([#3344](https://github.com/DataDog/browser-sdk/pull/3344))\n- 👷 Update all non-major dependencies ([#3332](https://github.com/DataDog/browser-sdk/pull/3332)) [RUM-REACT] [WORKER]\n- 👷 Update react monorepo to v19 (major) ([#3201](https://github.com/DataDog/browser-sdk/pull/3201)) [RUM-REACT]\n- ✅ Change flush sync into act ([#3364](https://github.com/DataDog/browser-sdk/pull/3364)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗️✨ [RUM-8622] session consistent trace sampling ([#3352](https://github.com/DataDog/browser-sdk/pull/3352)) [RUM] [RUM-REACT] [RUM-SLIM]\n- Define an error type and message for handling stacks ([#3359](https://github.com/DataDog/browser-sdk/pull/3359)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-8649] Use assembly hook for feature flags ([#3353](https://github.com/DataDog/browser-sdk/pull/3353)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ refactor npm scripts ([#3345](https://github.com/DataDog/browser-sdk/pull/3345))\n- ♻️ use playwright for e2e ([#3159](https://github.com/DataDog/browser-sdk/pull/3159)) [RUM]\n- Add modifiable field path for lcp resource_url ([#3346](https://github.com/DataDog/browser-sdk/pull/3346)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ Use window.crypto instead of getCrypto wrapper [RUM] [RUM-REACT] [RUM-SLIM]\n- 🔥 remove some workarounds related to unsupported browsers ([#3336](https://github.com/DataDog/browser-sdk/pull/3336)) [RUM] [RUM-REACT] [RUM-SLIM]\n- Add flag to always publish all pacakages ([#3343](https://github.com/DataDog/browser-sdk/pull/3343))\n- ♻️ [RUM-8340] Use assembly hook for ci and synthetics contexts ([#3310](https://github.com/DataDog/browser-sdk/pull/3310)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ [RUM-8319] Use assembly hook for action ([#3305](https://github.com/DataDog/browser-sdk/pull/3305)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.3.0\n\n**Public Changes:**\n\n- ✨ Allow to modify source_url and invoker properties in LoAF script attributions ([#3325](https://github.com/DataDog/browser-sdk/pull/3325)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ GA remote configuration ([#3329](https://github.com/DataDog/browser-sdk/pull/3329)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-4908] Add `only` Link to Facet List in Developer Extension ([#2830](https://github.com/DataDog/browser-sdk/pull/2830))\n- 🐛 [RUM-8428] Make developer extension compatible with lazy loaded recorder module ([#3324](https://github.com/DataDog/browser-sdk/pull/3324))\n- 🐛 Fix missing URL context ([#3323](https://github.com/DataDog/browser-sdk/pull/3323)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷‍♀️ [RUM-8295] Change anonymous id format to uuid ([#3306](https://github.com/DataDog/browser-sdk/pull/3306)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update all non-major dependencies ([#3300](https://github.com/DataDog/browser-sdk/pull/3300)) [RUM-REACT]\n- 👷 Bump chrome to 133.0.6943.53-1 ([#3321](https://github.com/DataDog/browser-sdk/pull/3321))\n- 🔧✅ enable splitChunk for tests again ([#3308](https://github.com/DataDog/browser-sdk/pull/3308))\n- 👷‍♀️ Remove ff for action name masking ([#3334](https://github.com/DataDog/browser-sdk/pull/3334)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-8123] Introduce a hook to assemble events ([#3330](https://github.com/DataDog/browser-sdk/pull/3330)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ♻️ Custom sanitizer for Context Manager ([#3290](https://github.com/DataDog/browser-sdk/pull/3290)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🔥 Remove RumContext type ([#3319](https://github.com/DataDog/browser-sdk/pull/3319)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.2.1\n\n**Public Changes:**\n\n- 🐛 [RUM-7694] - Keep more ReplayStats history to avoid wrongly marking views as having no replay ([#3318](https://github.com/DataDog/browser-sdk/pull/3318)) [RUM]\n\n## v6.2.0\n\n**Public Changes:**\n\n- ✨ [RUM-6563] Attribute ressource URL to LCP ([#3154](https://github.com/DataDog/browser-sdk/pull/3154)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM-8353] Throttle view context update ([#3314](https://github.com/DataDog/browser-sdk/pull/3314)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 fix document resource duration ([#3307](https://github.com/DataDog/browser-sdk/pull/3307)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ✅ fix failing skipped test ([#3309](https://github.com/DataDog/browser-sdk/pull/3309)) [RUM]\n- 🔊 Revert hooks and add missing URL context telemetry ([#3313](https://github.com/DataDog/browser-sdk/pull/3313)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🔊 Add telemetry on missing URL context ([#3304](https://github.com/DataDog/browser-sdk/pull/3304)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ⚗️Update RC to support new format and URL [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🚨 enforce consistent type export ([#3302](https://github.com/DataDog/browser-sdk/pull/3302)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-8123] Introduce a hook to assemble events ([#3289](https://github.com/DataDog/browser-sdk/pull/3289)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v6.1.0\n\n**Public Changes:**\n\n- ✨ Report original error from `addReactError` instead of fake rendering error ([#3293](https://github.com/DataDog/browser-sdk/pull/3293)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✨ [RUM-6581] Add an init parameter to chose feature flags event collection ([#3283](https://github.com/DataDog/browser-sdk/pull/3283)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ Capture previous and current rects in CLS attribution data ([#3269](https://github.com/DataDog/browser-sdk/pull/3269)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM-7572] Add get api of view specific context ([#3266](https://github.com/DataDog/browser-sdk/pull/3266)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM-6567] Generate new web vitals attribution fields ([#3251](https://github.com/DataDog/browser-sdk/pull/3251)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Prevent collecting the webpack ChunkLoadError ([#3280](https://github.com/DataDog/browser-sdk/pull/3280)) [RUM]\n- ⚡️ [RUM-7650] GA delaying the viewport dimension collection ([#3248](https://github.com/DataDog/browser-sdk/pull/3248)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷‍♀️ [RUM-7963] Add anonymous user id e2e test and cleanup ([#3268](https://github.com/DataDog/browser-sdk/pull/3268)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 fix eslint error on UNSTABLE_ReactComponentTracker case ([#3298](https://github.com/DataDog/browser-sdk/pull/3298)) [RUM-REACT]\n- 👷 Bump chrome to 132.0.6834.110-1 ([#3296](https://github.com/DataDog/browser-sdk/pull/3296))\n- 👷 various tiny fixes ([#3291](https://github.com/DataDog/browser-sdk/pull/3291)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update all non-major dependencies ([#3292](https://github.com/DataDog/browser-sdk/pull/3292)) [RUM-REACT]\n- 👷 upload source maps for next major canary ([#3288](https://github.com/DataDog/browser-sdk/pull/3288))\n- 👷 Update all non-major dependencies ([#3246](https://github.com/DataDog/browser-sdk/pull/3246))\n- 👷 Update dependency puppeteer to v24 ([#3275](https://github.com/DataDog/browser-sdk/pull/3275))\n- 👷: migrate renovate config ([#3279](https://github.com/DataDog/browser-sdk/pull/3279))\n- ✅ Add e2e test for telemetry usage ([#3222](https://github.com/DataDog/browser-sdk/pull/3222)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ mitigate e2e protocol latency ([#3295](https://github.com/DataDog/browser-sdk/pull/3295))\n- ✅ don't rely on segment counts on e2e tests ([#3278](https://github.com/DataDog/browser-sdk/pull/3278)) [RUM]\n- ✅ clear identifier implementation cache between tests ([#3282](https://github.com/DataDog/browser-sdk/pull/3282)) [RUM] [RUM-REACT] [RUM-SLIM]\n- [React RUM] Add a ReactComponentTracker component ([#3086](https://github.com/DataDog/browser-sdk/pull/3086)) [RUM-REACT]\n- ⬆️ Update eslint to v9 / flat config ([#3259](https://github.com/DataDog/browser-sdk/pull/3259)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v6.0.0\n\nSee our [upgrade guide](https://docs.datadoghq.com/real_user_monitoring/guide/browser-sdk-upgrade/#from-v5-to-v6) for a comprehensive list of breaking changes introduced by this major version.\n\n**Public Changes:**\n\n- 💥 [RUM-7704] Remove anonymous user feature flag for v6 ([#3216](https://github.com/DataDog/browser-sdk/pull/3216)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 default traceContextInjection to sampled ([#3212](https://github.com/DataDog/browser-sdk/pull/3212)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 💥 new default for track\\* initialization options ([#3190](https://github.com/DataDog/browser-sdk/pull/3190)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 💥 [RUM-6816] remove sendLogsAfterSessionExpiration ([#3183](https://github.com/DataDog/browser-sdk/pull/3183)) [LOGS]\n- 💥 [RUM 6075] Save anonymous id in session cookie ([#2985](https://github.com/DataDog/browser-sdk/pull/2985)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 remove useCrossSiteSessionCookie option ([#3179](https://github.com/DataDog/browser-sdk/pull/3179)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 remove Object.\\* Polyfills ([#2908](https://github.com/DataDog/browser-sdk/pull/2908)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 remove some polyfills ([#2857](https://github.com/DataDog/browser-sdk/pull/2857)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 build using ES2018 target ([#2882](https://github.com/DataDog/browser-sdk/pull/2882)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 💥 Collect long animation frames as long task events ([#3272](https://github.com/DataDog/browser-sdk/pull/3272)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 [RUM-175] sanitize RegExp and Event ([#3188](https://github.com/DataDog/browser-sdk/pull/3188)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 [RUM-6814] strongly type site parameter ([#3161](https://github.com/DataDog/browser-sdk/pull/3161)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 💥 [RUM-1919] Add tracestate header when using tracecontext propagator ([#3163](https://github.com/DataDog/browser-sdk/pull/3163)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 Prevent collecting the webpack ChunkLoadError ([#3280](https://github.com/DataDog/browser-sdk/pull/3280)) [RUM]\n- ⚡️ [RUM-6813] Lazy load session replay ([#3152](https://github.com/DataDog/browser-sdk/pull/3152)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 [RUM-5282] Remove ie11 tests ([#2856](https://github.com/DataDog/browser-sdk/pull/2856)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 do not rename bundle file when name does not change ([#3273](https://github.com/DataDog/browser-sdk/pull/3273))\n- 👷 skip merge-into-next-major-job if branch don't exist ([#3270](https://github.com/DataDog/browser-sdk/pull/3270))\n- 👷 enable check staging merge ([#3264](https://github.com/DataDog/browser-sdk/pull/3264))\n- 👷 fix comment about performance.timing.navigationStart ([#3180](https://github.com/DataDog/browser-sdk/pull/3180)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 fix comment on browser support for unicode character escape ([#3177](https://github.com/DataDog/browser-sdk/pull/3177)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 [RUM-6366] disable browserStack tests ([#3089](https://github.com/DataDog/browser-sdk/pull/3089))\n- 👷 fix next major deploy job config ([#2988](https://github.com/DataDog/browser-sdk/pull/2988))\n- 👷 add canary deploy job for next major ([#2938](https://github.com/DataDog/browser-sdk/pull/2938))\n- 🧪 Update browser matrix for tests ([#2884](https://github.com/DataDog/browser-sdk/pull/2884)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ fix session store e2e to account for anonymous id ([#3265](https://github.com/DataDog/browser-sdk/pull/3265))\n- ✅ Make tests robust to an instrumentMethod that does not always rewrap ([#3231](https://github.com/DataDog/browser-sdk/pull/3231)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ [RUM-6813] Use promise in `collectAsyncCalls` instead of a callback ([#3168](https://github.com/DataDog/browser-sdk/pull/3168)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.35.0\n\n**Public Changes:**\n\n- ✨ [RUM-5001] introduce a `sessionPersistence` config option to force using local storage ([#3244](https://github.com/DataDog/browser-sdk/pull/3244)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- feat: support custom schema on Electron ([#3204](https://github.com/DataDog/browser-sdk/pull/3204)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- Revert \"👷 freeze canary deploy ([#3238](https://github.com/DataDog/browser-sdk/pull/3238))\" ([#3252](https://github.com/DataDog/browser-sdk/pull/3252))\n- 👷 Update all non-major dependencies ([#3240](https://github.com/DataDog/browser-sdk/pull/3240)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update dependency webpack-cli to v6 ([#3241](https://github.com/DataDog/browser-sdk/pull/3241))\n- 👷 freeze canary deploy ([#3238](https://github.com/DataDog/browser-sdk/pull/3238))\n- ✅ fix leak detection issues ([#3245](https://github.com/DataDog/browser-sdk/pull/3245)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 💚 fix CI PR comment ([#3250](https://github.com/DataDog/browser-sdk/pull/3250))\n- ♻️ move traceSampleRate default to config validation ([#3197](https://github.com/DataDog/browser-sdk/pull/3197)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n## v5.34.1\n\n**Public Changes:**\n\n- 🐛 AddError should support all instances of type Error ([#3228](https://github.com/DataDog/browser-sdk/pull/3228)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 🐛 Fix unobserve error for non-Element parameter ([#3218](https://github.com/DataDog/browser-sdk/pull/3218)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ⚗️ ⚡️ [RUM-7650] Delay the viewport dimension collection ([#3209](https://github.com/DataDog/browser-sdk/pull/3209)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update all non-major dependencies ([#3200](https://github.com/DataDog/browser-sdk/pull/3200)) [RUM-REACT] [WORKER]\n- 👷 [RUM-7634] Add deploy and source maps upload scripts tests ([#3211](https://github.com/DataDog/browser-sdk/pull/3211))\n- 📦️ update typescript-eslint ([#3192](https://github.com/DataDog/browser-sdk/pull/3192)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.34.0\n\n**Public Changes:**\n\n- 🐛 [RUM-6322] Use window.open observable ([#3215](https://github.com/DataDog/browser-sdk/pull/3215)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ⚗️ ✨ [RUM-6868] implement consistent probabilistic trace sampling ([#3186](https://github.com/DataDog/browser-sdk/pull/3186)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Test anonymous id on staging behind ff ([#3206](https://github.com/DataDog/browser-sdk/pull/3206)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.33.0\n\n**Public Changes:**\n\n- ✨ [RUM-6182] don't start recording automatically when sample is 0 ([#3162](https://github.com/DataDog/browser-sdk/pull/3162)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨ [RUM-6799] Add new delivery type property ([#3166](https://github.com/DataDog/browser-sdk/pull/3166)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM-87] AddError should support Error instances coming from other JS contexts ([#3144](https://github.com/DataDog/browser-sdk/pull/3144)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#3157](https://github.com/DataDog/browser-sdk/pull/3157)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ✅ [RUM-6813]Fix recorder tests ([#3191](https://github.com/DataDog/browser-sdk/pull/3191)) [RUM]\n- ♻️ [RUM-6813] Split the recorder API module ([#3181](https://github.com/DataDog/browser-sdk/pull/3181)) [RUM]\n- Adds a prepare script to @datadog/browser-rum-react ([#3182](https://github.com/DataDog/browser-sdk/pull/3182)) [RUM-REACT]\n\n## v5.32.0\n\n**Public Changes:**\n\n- ✨ [RUM-7371] move React integration out of beta ([#3160](https://github.com/DataDog/browser-sdk/pull/3160)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 [RUM-6411] RUM should not crash with puppeteer injection ([#3153](https://github.com/DataDog/browser-sdk/pull/3153)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- ✨ [RUM-6956] Add action name source ([#3115](https://github.com/DataDog/browser-sdk/pull/3115)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.31.1\n\n**Public Changes:**\n\n- 🐛 skip worker timing when no worker is used ([#3147](https://github.com/DataDog/browser-sdk/pull/3147)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ⚗️🐛 [RUM-6226] fix for empty splats ([#3142](https://github.com/DataDog/browser-sdk/pull/3142)) [RUM-REACT]\n\n## v5.31.0\n\n**Public Changes:**\n\n- 🐛 Use EventTarget.prototype.addEventListener instead of the method ([#3137](https://github.com/DataDog/browser-sdk/pull/3137)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- [RUM-6801] Collect resource worker processing time ([#3118](https://github.com/DataDog/browser-sdk/pull/3118)) [RUM] [RUM-REACT] [RUM-SLIM]\n- Fix trackViewsManually JS doc comment ([#3117](https://github.com/DataDog/browser-sdk/pull/3117)) [RUM] [RUM-REACT] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#3139](https://github.com/DataDog/browser-sdk/pull/3139))\n- 👷 Bump chrome to 131.0.6778.69-1 ([#3127](https://github.com/DataDog/browser-sdk/pull/3127))\n- ✅ Fix test cleanup tasks order ([#3141](https://github.com/DataDog/browser-sdk/pull/3141)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.30.1\n\n**Public Changes:**\n\n- 🐛 [RUM-6226][rum-react] improve routes wildcard substitution ([#3105](https://github.com/DataDog/browser-sdk/pull/3105)) [RUM-REACT]\n- ⚡️ [RUM-6929] delay resource collection ([#3102](https://github.com/DataDog/browser-sdk/pull/3102)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- Add @session.id in Logs along to @session_id ([#3125](https://github.com/DataDog/browser-sdk/pull/3125)) [LOGS]\n\n**Internal Changes:**\n\n- 👷 do not include staging bump commit to changelog ([#3129](https://github.com/DataDog/browser-sdk/pull/3129))\n- 👷 Update all non-major dependencies ([#3106](https://github.com/DataDog/browser-sdk/pull/3106)) [RUM-REACT] [WORKER]\n\n## v5.30.0\n\n**Public Changes:**\n\n- ✨ add new privacy rule for autocomplete password value ([#3094](https://github.com/DataDog/browser-sdk/pull/3094)) [RUM] [RUM-REACT] [RUM-SLIM]\n- ✨[RUM-5090] Collect ressource protocol ([#3087](https://github.com/DataDog/browser-sdk/pull/3087)) [RUM] [RUM-REACT] [RUM-SLIM]\n- 🐛 allow untrusted event for httpRequest xhr event listeners ([#3123](https://github.com/DataDog/browser-sdk/pull/3123)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 [RUM-6562] Enable and rename update view name API ([#3099](https://github.com/DataDog/browser-sdk/pull/3099)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 Update all non-major dependencies ([#3082](https://github.com/DataDog/browser-sdk/pull/3082)) [RUM-REACT]\n- 👷[IR-30972] Include older version intake urls matching ([#3059](https://github.com/DataDog/browser-sdk/pull/3059)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- 👷 disable datadog static analysis ([#3091](https://github.com/DataDog/browser-sdk/pull/3091))\n- ✅👷 kill browserstack execution early ([#3096](https://github.com/DataDog/browser-sdk/pull/3096))\n\n## v5.29.1\n\n**Internal Changes:**\n\n- 👷 CI - Enable yarn strategy on the repository ([#3079](https://github.com/DataDog/browser-sdk/pull/3079))\n- 👷 publish chrome extension to all users ([#3084](https://github.com/DataDog/browser-sdk/pull/3084))\n- 👷 CI - assign static resources for e2e-bs job ([#3080](https://github.com/DataDog/browser-sdk/pull/3080))\n- 👷 Enable reduced Session Replay data batch time limit ([#3088](https://github.com/DataDog/browser-sdk/pull/3088)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.29.0\n\n**Public Changes:**\n\n- 🐛 [RUM-6483] Investigate reducing the batch time limit for Replay ([#3077](https://github.com/DataDog/browser-sdk/pull/3077)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Bump chrome to 130.0.6723.58-1 ([#3074](https://github.com/DataDog/browser-sdk/pull/3074))\n- 👷 skip merge into next major on scheduled pipelines ([#3075](https://github.com/DataDog/browser-sdk/pull/3075))\n- 👷 Update all non-major dependencies ([#3070](https://github.com/DataDog/browser-sdk/pull/3070)) [RUM-REACT]\n- 👷 Update dependency eslint-plugin-unicorn to v56 ([#3071](https://github.com/DataDog/browser-sdk/pull/3071))\n- 🔧 [RUM-6226] tweak rum-react dependencies ([#3054](https://github.com/DataDog/browser-sdk/pull/3054)) [RUM-REACT]\n- ♻️ Use registerCleanupTask for mock cleanups ([#3069](https://github.com/DataDog/browser-sdk/pull/3069)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-5101] Use registerCleanupTask for interceptor cleanup ([#3065](https://github.com/DataDog/browser-sdk/pull/3065)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- [RUM 5088] Reduce INP Null Target ([#2950](https://github.com/DataDog/browser-sdk/pull/2950)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-5101] Use registerCleanupTask for fetch and report cleanups ([#3066](https://github.com/DataDog/browser-sdk/pull/3066)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n- ♻️ Use registerCleanupTask for zonejs cleanup ([#3060](https://github.com/DataDog/browser-sdk/pull/3060)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]\n\n## v5.28.1\n\n**Public Changes:**\n\n- 🐛 ignore layout shifts that happen before view start ([#3058](https://github.com/DataDog/browser-sdk/pull/3058)) [RUM] [RUM-SLIM]\n- 🐛 add missing start_time field ([#3050](https://github.com/DataDog/browser-sdk/pull/3050)) [RUM] [RUM-SLIM]\n\n**Internal Changes:**\n\n- 👷🐛 fix generate-changelog script ([#3052](https://github.com/DataDog/browser-sdk/pull/3052))\n- 👷 Update Node.js to v22 ([#3049](https://github.com/DataDog/browser-sdk/pull/3049))\n- 👷 sync rum-events-format ([#3053](https://github.com/DataDog/browser-sdk/pull/3053)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 👷 Update all non-major dependencies ([#3046](https://github.com/DataDog/browser-sdk/pull/3046)) [RUM-REACT] [WORKER]\n- 👷 allow release to be merged into next major feature branch ([#3043](https://github.com/DataDog/browser-sdk/pull/3043))\n- 👷 bump e2e-bs ci job timeout to 35 minutes ([#3044](https://github.com/DataDog/browser-sdk/pull/3044))\n- 👷 Bump chrome to 129.0.6668.58-1 ([#3035](https://github.com/DataDog/browser-sdk/pull/3035))\n- 🔊 Add SDK setup telemetry ([#3045](https://github.com/DataDog/browser-sdk/pull/3045)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 🚨 enforce `scripts/` files conventions ([#3022](https://github.com/DataDog/browser-sdk/pull/3022))\n\n## v5.28.0\n\n**Public Changes:**\n\n- ✨ replace react-router wildcard routes with their actual path name ([#3023](https://github.com/DataDog/browser-sdk/pull/3023)) [RUM-REACT]\n- 🐛 fix to redirect v6-canary bundles urls to local dev bundles ([#3021](https://github.com/DataDog/browser-sdk/pull/3021))\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#3030](https://github.com/DataDog/browser-sdk/pull/3030)) [RUM-REACT]\n- 👷 Bump webpack from 5.76.0 to 5.94.0 in /test/app ([#3013](https://github.com/DataDog/browser-sdk/pull/3013))\n- ♻️ [RUM-6278] Use performance observer for layout shift entries ([#3028](https://github.com/DataDog/browser-sdk/pull/3028)) [RUM] [RUM-SLIM]\n- ✨ [RUM 4813] Remove feature flag for view specific context ([#3031](https://github.com/DataDog/browser-sdk/pull/3031)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 🐛 fix to redirect v6-canary bundles urls to local dev bundles ([#3021](https://github.com/DataDog/browser-sdk/pull/3021))\n- 👷 [RUM 6237] Add e2e test for view context API init ([#3025](https://github.com/DataDog/browser-sdk/pull/3025))\n- ♻️ [RUM-6188] Use performanceObserver for first input and event entries ([#2995](https://github.com/DataDog/browser-sdk/pull/2995)) [RUM] [RUM-SLIM]\n- ♻️ [RUM-6184] Use performanceObserver for paint entries ([#2991](https://github.com/DataDog/browser-sdk/pull/2991)) [RUM] [RUM-SLIM]\n- ✨ Increase INITIALIZATION_TIME_OUT_DELAY ([#3017](https://github.com/DataDog/browser-sdk/pull/3017)) [RUM]\n\n## v5.27.0\n\n**Public Changes**\n\n- ✨ Discard loading time when page is hidden ([#2965](https://github.com/DataDog/browser-sdk/pull/2965)) [RUM] [RUM-SLIM]\n- 🐛 [RUM-5785] fix missing navigation timings on Safari ([#2964](https://github.com/DataDog/browser-sdk/pull/2964)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 🐛 convert long animation frame times to nanoseconds ([#2994](https://github.com/DataDog/browser-sdk/pull/2994)) [RUM] [RUM-SLIM]\n- 🐛 [RUM-94] ignore performance resource timings with negative duration ([#2958](https://github.com/DataDog/browser-sdk/pull/2958)) [RUM] [RUM-SLIM]\n\n**Internal Changes**\n\n- 👷 Update all non-major dependencies ([#2992](https://github.com/DataDog/browser-sdk/pull/2992)) [RUM-REACT] [RUM]\n- 👷 timeout e2e-bs ci job after 30 minutes ([#2999](https://github.com/DataDog/browser-sdk/pull/2999))\n- 👷 Bump chrome to 128.0.6613.84-1 ([#2946](https://github.com/DataDog/browser-sdk/pull/2946))\n- 👷 allow job 'test-performance' to fail ([#2980](https://github.com/DataDog/browser-sdk/pull/2980))\n- 👷 Update all non-major dependencies ([#2975](https://github.com/DataDog/browser-sdk/pull/2975))\n- 🎨 [RUM-6203] Expose experimental features in init method ([#3006](https://github.com/DataDog/browser-sdk/pull/3006)) [RUM] [RUM-SLIM]\n- 🎨 [RUM-5100] Move away from testbuilder in test files - Pt 3 ([#2952](https://github.com/DataDog/browser-sdk/pull/2952)) [RUM] [RUM-SLIM]\n- ✅♻️ do not mock `navigationStart` in `mockClock` ([#2979](https://github.com/DataDog/browser-sdk/pull/2979)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-6181] Use performanceObserver for LCP entries ([#2990](https://github.com/DataDog/browser-sdk/pull/2990)) [RUM] [RUM-SLIM]\n- 🔥 cleanup unused Experimental Features ([#2996](https://github.com/DataDog/browser-sdk/pull/2996)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- ♻️ [RUM-6180] Use performanceObserver for long-task entries ([#2989](https://github.com/DataDog/browser-sdk/pull/2989)) [RUM] [RUM-SLIM]\n- ⚗️✨ [RUM 5983] Add set view context apis ([#2967](https://github.com/DataDog/browser-sdk/pull/2967)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n\n## v5.26.0\n\n**Public Changes:**\n\n- ✨ [RUM-5775] Make view local context writable ([#2939](https://github.com/DataDog/browser-sdk/pull/2939)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 🐛 Allow both history and History prototype to be patched by 3rd party ([#2968](https://github.com/DataDog/browser-sdk/pull/2968)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 🐛 [RUM-5920] Fix tags format warning ([#2947](https://github.com/DataDog/browser-sdk/pull/2947)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 Bump micromatch from 4.0.4 to 4.0.8 ([#2970](https://github.com/DataDog/browser-sdk/pull/2970))\n- 👷 add job to merge main into next major feature branch (v6) ([#2935](https://github.com/DataDog/browser-sdk/pull/2935))\n- 👷 Update all non-major dependencies ([#2962](https://github.com/DataDog/browser-sdk/pull/2962)) [RUM-REACT]\n- Bump micromatch from 4.0.5 to 4.0.8 in /test/app ([#2971](https://github.com/DataDog/browser-sdk/pull/2971))\n\n## v5.25.0\n\n**Public Changes:**\n\n- Remove custom_vitals FF ([#2957](https://github.com/DataDog/browser-sdk/pull/2957)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n\n**Internal Changes:**\n\n- 👷 don't print log messages twice in unit tests ([#2959](https://github.com/DataDog/browser-sdk/pull/2959))\n\n## v5.24.0\n\n**Public Changes:**\n\n- ✨ [RUM-5778] Custom Vitals Collection V3 ([#2929](https://github.com/DataDog/browser-sdk/pull/2929)) [RUM] [RUM-SLIM]\n- 🐛 bundle size: calculate diff from PR base instead of main ([#2910](https://github.com/DataDog/browser-sdk/pull/2910))\n\n**Internal Changes:**\n\n- 👷 Update dependency eslint-plugin-jsdoc to v50 ([#2932](https://github.com/DataDog/browser-sdk/pull/2932))\n- 👷 Update all non-major dependencies ([#2948](https://github.com/DataDog/browser-sdk/pull/2948)) [WORKER]\n- 👷 Update all non-major dependencies ([#2941](https://github.com/DataDog/browser-sdk/pull/2941)) [RUM-REACT]\n- 👷 use devflow to merge main into staging ([#2927](https://github.com/DataDog/browser-sdk/pull/2927))\n- 👷 Update all non-major dependencies ([#2920](https://github.com/DataDog/browser-sdk/pull/2920)) [RUM] [RUM-SLIM] [RUM-REACT]\n- 👷 Update dependency puppeteer to v23 ([#2933](https://github.com/DataDog/browser-sdk/pull/2933))\n- 👷 upgrade gitlab runner ([#2928](https://github.com/DataDog/browser-sdk/pull/2928))\n- 👷 [RUM-5673] Improve `test-performance` execution time ([#2914](https://github.com/DataDog/browser-sdk/pull/2914))\n- 👷 use devflow to merge main into staging ([#2917](https://github.com/DataDog/browser-sdk/pull/2917))\n- 👷 Update all non-major dependencies ([#2900](https://github.com/DataDog/browser-sdk/pull/2900))\n- 👷 Update dependency eslint-plugin-unicorn to v55 ([#2901](https://github.com/DataDog/browser-sdk/pull/2901))\n- 👷 Update dependency @types/node to v22 ([#2902](https://github.com/DataDog/browser-sdk/pull/2902))\n- 🎨 Refactor spec files and remove test setup builder ([#2913](https://github.com/DataDog/browser-sdk/pull/2913)) [RUM] [RUM-SLIM]\n- 🧪 Update browser matrix for tests ([#2884](https://github.com/DataDog/browser-sdk/pull/2884)) [LOGS] [RUM] [RUM-SLIM] [WORKER] [RUM-REACT]\n- Revert \"[RUM-5590] Add telemetry for INP null target ([#2895](https://github.com/DataDog/browser-sdk/pull/2895))\" ([#2955](https://github.com/DataDog/browser-sdk/pull/2955)) [RUM] [RUM-SLIM]\n- Fix history API instrumentation ([#2944](https://github.com/DataDog/browser-sdk/pull/2944)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- [RUM-5705] Collect Long Animation Frames ([#2924](https://github.com/DataDog/browser-sdk/pull/2924)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- ✨ [RUM-5712] add error.handling to logs ([#2918](https://github.com/DataDog/browser-sdk/pull/2918)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- Revert \"👷 use devflow to merge main into staging ([#2917](https://github.com/DataDog/browser-sdk/pull/2917))\" ([#2922](https://github.com/DataDog/browser-sdk/pull/2922))\n- ♻️ remove duplicate pageStateHistory.stop() ([#2912](https://github.com/DataDog/browser-sdk/pull/2912)) [RUM] [RUM-SLIM]\n- [RUM-5590] Add telemetry for INP null target ([#2895](https://github.com/DataDog/browser-sdk/pull/2895)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- Revert \"👷 disable test-performance job ([#2904](https://github.com/DataDog/browser-sdk/pull/2904))\" ([#2906](https://github.com/DataDog/browser-sdk/pull/2906))\n\n## v5.23.3\n\n**Internal Changes:**\n\n- 👷 disable test-performance job ([#2904](https://github.com/DataDog/browser-sdk/pull/2904))\n\n## v5.23.2\n\n**Public Changes:**\n\n- 🐛 fix unexpected exception when no entry type is supported in PerformanceObserver ([#2899](https://github.com/DataDog/browser-sdk/pull/2899)) [RUM] [RUM-SLIM]\n\n## v5.23.1\n\n**Public Changes:**\n\n- 🐛 Fix replay visual viewport resize support ([#2891](https://github.com/DataDog/browser-sdk/pull/2891)) [RUM] [RUM-SLIM]\n- 🐛 Handle non-object response and error ([#2860](https://github.com/DataDog/browser-sdk/pull/2860)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- ⚡️ Remove classes in favour of functions ([#2885](https://github.com/DataDog/browser-sdk/pull/2885)) [LOGS] [RUM] [RUM-SLIM] [WORKER] [RUM-REACT]\n- ⚡ Performance Friday Reduce Bundle Size ([#2875](https://github.com/DataDog/browser-sdk/pull/2875)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- ⚡️Reduce bundle size: simplify config, use const enum, remove str redundancies ([#2877](https://github.com/DataDog/browser-sdk/pull/2877)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n- 📝 [RUM-152] Add packages name modified next to commit in CHANGELOG ([#2889](https://github.com/DataDog/browser-sdk/pull/2889))\n- 📝 [RUM-5172] add react integration documentation ([#2873](https://github.com/DataDog/browser-sdk/pull/2873)) [RUM-REACT]\n\n**Internal Changes:**\n\n- 👷 Bump chrome to 127.0.6533.72-1 ([#2890](https://github.com/DataDog/browser-sdk/pull/2890))\n- 👷 retry gitlab jobs on runner_system_failure ([#2886](https://github.com/DataDog/browser-sdk/pull/2886))\n- 👷 Update all non-major dependencies ([#2881](https://github.com/DataDog/browser-sdk/pull/2881)) [RUM-REACT]\n- 👷 Update dependency minimatch to v10 ([#2863](https://github.com/DataDog/browser-sdk/pull/2863))\n- 👷 Update dependency glob to v11 ([#2862](https://github.com/DataDog/browser-sdk/pull/2862))\n- ♻️ [RUM-5294] Use performanceObserver for navigation entries ([#2855](https://github.com/DataDog/browser-sdk/pull/2855)) [RUM] [RUM-SLIM]\n- ⚗️ enable plugins as a beta feature ([#2872](https://github.com/DataDog/browser-sdk/pull/2872)) [LOGS] [RUM] [RUM-SLIM] [WORKER]\n\n## v5.23.0\n\n**Public Changes:**\n\n- ✨ [RUM-4781] Update Custom Web Vitals API ([#2801](https://github.com/DataDog/browser-sdk/pull/2801))\n- ✨ [RUM-4819] Add an experimental 'updateViewName' API ([#2808](https://github.com/DataDog/browser-sdk/pull/2808))\n- 🐛 Update path for contributing and changelog file ([#2867](https://github.com/DataDog/browser-sdk/pull/2867))\n- 🐛 Fix update view name api in context history ([#2853](https://github.com/DataDog/browser-sdk/pull/2853))\n- 🐛 [RUM-958] Fix performance observable compatibility with old browser version ([#2850](https://github.com/DataDog/browser-sdk/pull/2850))\n- 🐛 [RUM-5209] provide a span id for the initial document trace ([#2844](https://github.com/DataDog/browser-sdk/pull/2844))\n\n**Internal Changes:**\n\n- 👷 Update all non-major dependencies ([#2861](https://github.com/DataDog/browser-sdk/pull/2861))\n- 👷 Update all non-major dependencies ([#2848](https://github.com/DataDog/browser-sdk/pull/2848))\n- 👷 Update all non-major dependencies ([#2839](https://github.com/DataDog/browser-sdk/pull/2839))\n- 👷 Upgrade engine.io and socket.io-adapter packages to fix ws vulnerability ([#2842](https://github.com/DataDog/browser-sdk/pull/2842))\n- 🎨 Instrument fetch and XHR before trying to init consent ([#2834](https://github.com/DataDog/browser-sdk/pull/2834))\n- 🧪 Ensure skipped test do not fail ([#2821](https://github.com/DataDog/browser-sdk/pull/2821))\n- Update rum-react peerDependencies ([#2870](https://github.com/DataDog/browser-sdk/pull/2870))\n- ♻️ Get rid of setupBuilder from simple unit tests - pt 1 ([#2858](https://github.com/DataDog/browser-sdk/pull/2858))\n- ♻️ [RUM-159] Categorize changes as public or internal in the CHANGELOG ([#2851](https://github.com/DataDog/browser-sdk/pull/2851))\n- ♻️ [RUM-958] Use a performance observable instead of the lifecycle ([#2818](https://github.com/DataDog/browser-sdk/pull/2818))\n- ♻️ [RUM-67] Specialise type files ([#2845](https://github.com/DataDog/browser-sdk/pull/2845))\n- Specialise constant files ([#2841](https://github.com/DataDog/browser-sdk/pull/2841))\n- ⚗️✨ [RUM-4469] introduce an experimental React integration ([#2824](https://github.com/DataDog/browser-sdk/pull/2824))\n\n## v5.22.0\n\n- ✨⚗️ [RUM-4469] introduce a plugin system ([#2809](https://github.com/DataDog/browser-sdk/pull/2809))\n- ✨ [RUM-4014] DD_LOGS: add handling stack in beforeSend context ([#2786](https://github.com/DataDog/browser-sdk/pull/2786))\n- ✨ [RUM-3902] Add privacy control for action names ([#2707](https://github.com/DataDog/browser-sdk/pull/2707))\n- 🐛 Fix developer extension crashing when dev mode enabled ([#2810](https://github.com/DataDog/browser-sdk/pull/2810))\n- 🔮 [HADXVI-53] Browser SDK extension search bar improvement ([#2771](https://github.com/DataDog/browser-sdk/pull/2771))\n- ⚡️ [RUM-3570] Batch the records for 16ms minimum before processing them ([#2807](https://github.com/DataDog/browser-sdk/pull/2807))\n- Use the same service/version type in init() and startView() ([#2798](https://github.com/DataDog/browser-sdk/pull/2798))\n- ⚗️ [RUM-4780] Remote configuration ([#2799](https://github.com/DataDog/browser-sdk/pull/2799))\n\n## v5.21.0\n\n- ✨ [RUM-4659] Collect INP and CLS timestamp ([#2793](https://github.com/DataDog/browser-sdk/pull/2793))\n- ✨ [RUM-1310] Support all log statuses ([#2725](https://github.com/DataDog/browser-sdk/pull/2725))\n- ✨ [RUM-3965] make service and version fields modifiable ([#2788](https://github.com/DataDog/browser-sdk/pull/2788))\n- ✨ [RUM-3837] Force Replay recording on sampled-out sessions ([#2777](https://github.com/DataDog/browser-sdk/pull/2777))\n- 🐛 [RUM-4178] Update performance difference memory ([#2794](https://github.com/DataDog/browser-sdk/pull/2794))\n- ♻️ Sends the conf telemetry from preStartRum ([#2795](https://github.com/DataDog/browser-sdk/pull/2795))\n- ♻️ Set the experimental feature flags as early as possible ([#2796](https://github.com/DataDog/browser-sdk/pull/2796))\n- 📝 [RUM-158] Add jsdoc annotations on initConfiguration ([#2772](https://github.com/DataDog/browser-sdk/pull/2772))\n\n## v5.20.0\n\n- ✨ [RUM-4013] DD_RUM: add handling stack in beforeSend context ([#2730](https://github.com/DataDog/browser-sdk/pull/2730))\n- ✨[RUM-4178] Report memory impact to Datadog ([#2724](https://github.com/DataDog/browser-sdk/pull/2724))\n- 🐛 [RUM-98] Warn when SDK is loaded multiple times ([#2785](https://github.com/DataDog/browser-sdk/pull/2785))\n- ⚡️ [RUM-4468] improve CSS selector computation performance ([#2782](https://github.com/DataDog/browser-sdk/pull/2782))\n- 📝 [RUM-158] Add jsdoc to public APIs ([#2775](https://github.com/DataDog/browser-sdk/pull/2775))\n- 🔥 Remove unnecessary session checks in collections ([#2769](https://github.com/DataDog/browser-sdk/pull/2769))\n\n## v5.19.0\n\n- 🐛 [RUM-4629] accept `null` as env/version/service ([#2781](https://github.com/DataDog/browser-sdk/pull/2781))\n- 🐛 [RUM-4493] do not compute selectors for detached elements ([#2766](https://github.com/DataDog/browser-sdk/pull/2766))\n- 🐛 [RUM-2720] Send logs without session id when session inactive ([#2578](https://github.com/DataDog/browser-sdk/pull/2578))\n- 🐛 [RUM-1666] Don't set negative action loading time ([#2764](https://github.com/DataDog/browser-sdk/pull/2764))\n- 🐛 [RUM-4434] fix timing matching for the same resource requested twice at the same time ([#2747](https://github.com/DataDog/browser-sdk/pull/2747))\n- 🐛 [RUM-4436] fix detached node memory leak on CLS ([#2749](https://github.com/DataDog/browser-sdk/pull/2749))\n- ✅ fix clearing cookies between tests ([#2780](https://github.com/DataDog/browser-sdk/pull/2780))\n- 🔥 Cleanup experimental features ([#2768](https://github.com/DataDog/browser-sdk/pull/2768))\n- ✏️ various comment fixes ([#2760](https://github.com/DataDog/browser-sdk/pull/2760))\n\n## v5.18.0\n\n- 🔊[RUM-4360] monitor more API usages ([#2745](https://github.com/DataDog/browser-sdk/pull/2745))\n- 🔊 collect pre start telemetry ([#2755](https://github.com/DataDog/browser-sdk/pull/2755))\n- 🔊 Deduplicate telemetry events ([#2746](https://github.com/DataDog/browser-sdk/pull/2746))\n- 🐛 [RUM-97] Sanitize tags parameter in configuration ([#2744](https://github.com/DataDog/browser-sdk/pull/2744))\n\n## v5.17.1\n\n- 🐛fix deploy script ([#2742](https://github.com/DataDog/browser-sdk/pull/2742))\n\n## v5.17.0\n\n- ✨ [RUM-4052] Sanitize `site` parameter in configuration ([#2735](https://github.com/DataDog/browser-sdk/pull/2735))\n- ✨ [RUM-4287] Enable feature flags API ([#2728](https://github.com/DataDog/browser-sdk/pull/2728))\n- ✨ [RUM-3710] Update session ID handling to support cookie deletion ([#2673](https://github.com/DataDog/browser-sdk/pull/2673))\n- ✨⚗️ [RUM-4179] vital: collect `computed_value` property ([#2723](https://github.com/DataDog/browser-sdk/pull/2723))\n- ♻️ use browser.execute and browser.executeAsync directly ([#2700](https://github.com/DataDog/browser-sdk/pull/2700))\n- ♻️ move createHandlingStack to the tools folder ([#2727](https://github.com/DataDog/browser-sdk/pull/2727))\n\n## v5.16.0\n\n- ✨ [RUM-3684] Capture scroll record on shadow dom elements ([#2708](https://github.com/DataDog/browser-sdk/pull/2708))\n- ✨[RUM-3798] Report the cpu impact as a pr comment ([#2702](https://github.com/DataDog/browser-sdk/pull/2702))\n- ✨ [RUM-162] Truncate resources URL containing data URLs ([#2690](https://github.com/DataDog/browser-sdk/pull/2690))\n- 🐛[RUM-4109] Mask iframe srcdoc with privacy override ([#2714](https://github.com/DataDog/browser-sdk/pull/2714))\n- ⚗ [RUM-2782] Validate resource timings more granularly\n\n## v5.15.0\n\n- 🐛 fix beforeSend type definition for logs ([#2686](https://github.com/DataDog/browser-sdk/pull/2686))\n- 🐛 [RUM-2782] remove buggy redirect timing estimation based on fetchStart ([#2683](https://github.com/DataDog/browser-sdk/pull/2683))\n- [ci-visibility] Implement driver-agnostic integration with CI Visibility ([#2639](https://github.com/DataDog/browser-sdk/pull/2639))\n\n## v5.14.0\n\n- ✨ [RUM-3387] forward to beforeSend context ([#2665](https://github.com/DataDog/browser-sdk/pull/2665))\n- 🐛 [RUM-3581] Fix the selector computation due to properties partially supported on IE ([#2663](https://github.com/DataDog/browser-sdk/pull/2663))\n- 🐛 [RUM-96] Ignore frustrations on clicks resulting in scrolls ([#2669](https://github.com/DataDog/browser-sdk/pull/2669))\n- ♻️✅ Harmonize record observers ([#2659](https://github.com/DataDog/browser-sdk/pull/2659))\n\n## v5.13.0\n\n- ✨ [RUM-3542] Add trace context injection control in rum configuration ([#2656](https://github.com/DataDog/browser-sdk/pull/2656))\n- 🐛 [RUM-3599] do not define undefined instrumented method ([#2662](https://github.com/DataDog/browser-sdk/pull/2662))\n- 🐛 [RUM-3598] Ignore collecting requests to logs PCI intake as RUM resources ([#2655](https://github.com/DataDog/browser-sdk/pull/2655))\n- ⚡ [RUM-2633] Optimize DOM iteration in the recorder ([#2657](https://github.com/DataDog/browser-sdk/pull/2657))\n\n## v5.12.0\n\n- ✨ [RUM-3546] Add support of PCI compliant intake for browser logs ([#2648](https://github.com/DataDog/browser-sdk/pull/2648))\n- ✨ [RUM 3352] Extra resource event attributes to enable performance CWV troubleshooting ([#2646](https://github.com/DataDog/browser-sdk/pull/2646))\n- ✨ [RUM-2885] Collect CSP disposition ([#2635](https://github.com/DataDog/browser-sdk/pull/2635))\n- 🐛 [RUM-3440] Fix INP CSS selector computation\n- 🐛 [RUM-3502] fix fetch(url) tracing ([#2642](https://github.com/DataDog/browser-sdk/pull/2642))\n- 🔧 Enforce snake case for event type properties ([#2649](https://github.com/DataDog/browser-sdk/pull/2649))\n- 🔊 [RUM-3501] add `tracking_consent` to configuration telemetry ([#2640](https://github.com/DataDog/browser-sdk/pull/2640))\n- 🔧 configure renovate to deduplicate subdependencies ([#2643](https://github.com/DataDog/browser-sdk/pull/2643))\n\n## v5.11.0\n\n- ✨ [RUM-3349] enable the consent management API ([#2634](https://github.com/DataDog/browser-sdk/pull/2634))\n- ✨ [RUM-2203] Forward replay records to the bridge ([#2470](https://github.com/DataDog/browser-sdk/pull/2470))\n- 🐛 [RUM-2445] fix unexpected session renewal after expire() ([#2632](https://github.com/DataDog/browser-sdk/pull/2632))\n- ⚗️ [RUM-3234] Discard outdated vitals ([#2610](https://github.com/DataDog/browser-sdk/pull/2610))\n\n## v5.10.0\n\n- ✨ [RUM-2902] Add error causes to context when logging an error ([#2602](https://github.com/DataDog/browser-sdk/pull/2602))\n- ✨ [RUM-3151] Report bundle sizes to logs ([#2605](https://github.com/DataDog/browser-sdk/pull/2605))\n- ✨ [RUM-160] Collect PerformanceResourceTiming.responseStatus ([#2587](https://github.com/DataDog/browser-sdk/pull/2587))\n- 🐛 [RUM-3039] Fix missing pending mutations at view end ([#2598](https://github.com/DataDog/browser-sdk/pull/2598))\n- ⚗️[RUM-3235] collect vital.name attribute ([#2609](https://github.com/DataDog/browser-sdk/pull/2609))\n- ⚗️[RUM-2889] custom vitals improvements ([#2606](https://github.com/DataDog/browser-sdk/pull/2606))\n- 🔧 ignore karma-webpack for now ([#2604](https://github.com/DataDog/browser-sdk/pull/2604))\n- ⚗️[RUM-2889] Bootstrap custom vital APIs ([#2591](https://github.com/DataDog/browser-sdk/pull/2591))\n- ⚗ ️✨ [RUM-2445] implement Tracking Consent management ([#2589](https://github.com/DataDog/browser-sdk/pull/2589))\n\n## v5.9.0\n\n- ✨[Developer extension] npm setup override support ([#2304](https://github.com/DataDog/browser-sdk/pull/2304))\n- 🐛 Fix LCP with size < previous LCP ([#2586](https://github.com/DataDog/browser-sdk/pull/2586))\n- 🐛 [RUM-2940] fix normalize URL for relative paths ([#2576](https://github.com/DataDog/browser-sdk/pull/2576))\n- ♻️ register setupBuilder.cleanup as a cleanup task ([#2590](https://github.com/DataDog/browser-sdk/pull/2590))\n- ♻️ [RUM-2445] split RUM and Logs public APIs modules ([#2575](https://github.com/DataDog/browser-sdk/pull/2575))\n- ⚡️ [RUM-2893] optimize getNodePrivacyLevel by adding a cache ([#2579](https://github.com/DataDog/browser-sdk/pull/2579))\n- ♻️ [RUM-2203] Move record logic from startRecording to the record module ([#2574](https://github.com/DataDog/browser-sdk/pull/2574))\n\n## v5.8.0\n\n- ✨[RUM-2729] collect connectivity data ([#2560](https://github.com/DataDog/browser-sdk/pull/2560))\n- 🐛[RUM-2752] Replay: generate censored images with custom dimensions ([#2565](https://github.com/DataDog/browser-sdk/pull/2565))\n- 🐛[RUM-2735] Track request with undefined/null method\n- 📝 Document addTiming API relative time issue ([#2570](https://github.com/DataDog/browser-sdk/pull/2570))\n- ♻️ [RUM-2445] simplify context manager sync with local storage ([#2562](https://github.com/DataDog/browser-sdk/pull/2562))\n- ♻️ [RUM-2445] align rum and logs common context implementation ([#2564](https://github.com/DataDog/browser-sdk/pull/2564))\n- ♻️ [RUM-2445] use recorderApi directly ([#2563](https://github.com/DataDog/browser-sdk/pull/2563))\n\n## v5.7.0\n\n- 🐛 [RUM-2689] fix recorder crash when restarted quickly ([#2553](https://github.com/DataDog/browser-sdk/pull/2553))\n- 🔉 [RUM-253] adjust heavy customer data warning when compression is enabled ([#2529](https://github.com/DataDog/browser-sdk/pull/2529))\n- ♻️ [RUMF-1436] instrument method improvements ([#2551](https://github.com/DataDog/browser-sdk/pull/2551))\n- ✨⚗ [RUM-2682] writable resource.graphql field on Resource events ([#2550](https://github.com/DataDog/browser-sdk/pull/2550))\n- 📝 add @datadog/browser-worker package to readme ([#2537](https://github.com/DataDog/browser-sdk/pull/2537))\n- ♻️ pass the Observable instance to the onFirstSubscribe callback ([#2539](https://github.com/DataDog/browser-sdk/pull/2539))\n\n## v5.6.0\n\n- ✨[RUM-2436] add partitioned support for third party cookies ([#2535](https://github.com/DataDog/browser-sdk/pull/2535))\n- 🔊[RUM-2324] Telemetry on other wrong LCP cases ([#2531](https://github.com/DataDog/browser-sdk/pull/2531))\n\n## v5.5.1\n\n- 🐛 [RUM-2280] fix duplicated mutations when using Shadow DOM ([#2527](https://github.com/DataDog/browser-sdk/pull/2527))\n- 🔊[RUM-2324] Telemetry on LCP with startTime to 0 ([#2515](https://github.com/DataDog/browser-sdk/pull/2515))\n- ✅ import JSON schemas dynamically in tests ([#2521](https://github.com/DataDog/browser-sdk/pull/2521))\n\n## v5.5.0\n\n- ✨ Expose original report events in beforeSend ([#2510](https://github.com/DataDog/browser-sdk/pull/2510))\n- ✨ Developer Extension improvements ([#2516](https://github.com/DataDog/browser-sdk/pull/2516))\n- ♻️ [Logs] reorganise some components ([#2519](https://github.com/DataDog/browser-sdk/pull/2519))\n\n## v5.4.0\n\n- ✨ [RUM-1214] Collect core web vitals target selectors ([#2506](https://github.com/DataDog/browser-sdk/pull/2506))\n- ✨ [RUM-2158] Allow more flexible proxy URL ([#2502](https://github.com/DataDog/browser-sdk/pull/2502))\n\n## v5.3.0\n\n- ✨ [RUM-253] enable compression via the compressIntakeRequests parameter ([#2500](https://github.com/DataDog/browser-sdk/pull/2500))\n- 🐛 [RUM-1561] Fix CLS selector computation on detached node ([#2480](https://github.com/DataDog/browser-sdk/pull/2480))\n\n## v5.2.0\n\n- 🐛 [RUM-2016] don't collect useless resources events ([#2493](https://github.com/DataDog/browser-sdk/pull/2493))\n- 🐛 [RUM-1863] fix iOS webview detection ([#2486](https://github.com/DataDog/browser-sdk/pull/2486))\n- ⚡️[RUM-2017] optimize cookie accesses ([#2497](https://github.com/DataDog/browser-sdk/pull/2497))\n- ✅ [RUM-253] add E2E tests related to compression ([#2416](https://github.com/DataDog/browser-sdk/pull/2416))\n- ⚗️✨ [RUM-253] compress RUM data ([#2400](https://github.com/DataDog/browser-sdk/pull/2400))\n- 🔉 [RUM-1658] Add extra field to identify sessions recorded manually ([#2479](https://github.com/DataDog/browser-sdk/pull/2479))\n- 🔊 Add CLS target selector telemetry ([#2477](https://github.com/DataDog/browser-sdk/pull/2477))\n\n## v5.1.0\n\n- ✨ [RUM-1215] Collect INP #2355 ([#2448](https://github.com/DataDog/browser-sdk/pull/2448))\n- 🐛 Prevent console warning on Firefox on route change ([#2469](https://github.com/DataDog/browser-sdk/pull/2469))\n- 🐛 [RUM-1360] Cap INP outliers ([#2466](https://github.com/DataDog/browser-sdk/pull/2466))\n- ♻️ [RUM-1329] Merge tracekit into error folder ([#2450](https://github.com/DataDog/browser-sdk/pull/2450))\n\n## v5.0.0\n\nSee our [upgrade guide](https://docs.datadoghq.com/real_user_monitoring/guide/browser-sdk-upgrade/#from-v4-to-v5) for a comprehensive list of breaking changes introduced by this major version.\n\n- 💥 [RUMF-1589] automatically start recording ([#2275](https://github.com/DataDog/browser-sdk/pull/2275))\n- 💥 [RUMF-1587] Remove `premiumSampleRate` and `replaySampleRate` ([#2256](https://github.com/DataDog/browser-sdk/pull/2256))\n- 💥 [RUMF-1597] Drop plan and send sampled_for_replay ([#2293](https://github.com/DataDog/browser-sdk/pull/2293))\n- 💥 [RUMF-1578] Promote track frustration as default action behaviour ([#2232](https://github.com/DataDog/browser-sdk/pull/2232))\n- 💥 [RUMF-1230] Only apply main logger configuration to its own logs ([#2298](https://github.com/DataDog/browser-sdk/pull/2298))\n- 💥 [RUM-1210] Add W3C tracecontext to default propagator types ([#2443](https://github.com/DataDog/browser-sdk/pull/2343))\n- 💥 [RUMF-1473] Ignore untrusted event ([#2308](https://github.com/DataDog/browser-sdk/pull/2308))\n- 💥 [RUMF-1564] remove intake subdomains ([#2309](https://github.com/DataDog/browser-sdk/pull/2309))\n- 💥 [RUMF-1577] Stop collecting foreground periods ([#2311](https://github.com/DataDog/browser-sdk/pull/2311))\n- 💥 [RUMF-1557] beforeSend domain context: use PerformanceEntry ([#2300](https://github.com/DataDog/browser-sdk/pull/2300))\n- 💥 [RUMF-1556] Typings: consistent beforeSend return type ([#2303](https://github.com/DataDog/browser-sdk/pull/2303))\n- 💥 [RUMF-1229] Logs: remove `error.origin` attribute ([#2294](https://github.com/DataDog/browser-sdk/pull/2294))\n- 💥 [RUMF-1228] Remove console error message prefix ([#2289](https://github.com/DataDog/browser-sdk/pull/2289))\n- 💥 [RUMF-1555] Rework logger context APIs ([#2285](https://github.com/DataDog/browser-sdk/pull/2285))\n- 💥 [RUMF-1152] sanitize resource method names ([#2288](https://github.com/DataDog/browser-sdk/pull/2288))\n- 💥 [RUMF-1555] Remove `event` in action domain context ([#2286](https://github.com/DataDog/browser-sdk/pull/2286))\n- 💥 [RUMF-1588] Update default session replay behaviour ([#2257](https://github.com/DataDog/browser-sdk/pull/2257))\n- 💥 [RUMF-1554] Drop some deprecated public APIs ([#2241](https://github.com/DataDog/browser-sdk/pull/2241))\n- 💥 [RUMF-1554] Drop some deprecated config parameters ([#2238](https://github.com/DataDog/browser-sdk/pull/2238))\n- ✨ [RUM-255] add allowUntrustedEvents config parameter ([#2347](https://github.com/DataDog/browser-sdk/pull/2347))\n- 🐛 [RUMF-1499] Don't send duration for resources crossing a page frozen state ([#2271](https://github.com/DataDog/browser-sdk/pull/2271))\n- 🔥 [RUMF-1555] Remove `startTime` in xhr start context ([#2287](https://github.com/DataDog/browser-sdk/pull/2287))\n- ♻️ [RUMF-1555] Remove deprecated context manager APIs ([#2284](https://github.com/DataDog/browser-sdk/pull/2284))\n\n## v4.50.1\n\n- 🐛 [RUM-1325] fix memory leak when using shadow dom ([#2451](https://github.com/DataDog/browser-sdk/pull/2451))\n- 🐛 [RUM-1325] propagate privacy defined on shadow hosts ([#2454](https://github.com/DataDog/browser-sdk/pull/2454))\n- 🐛 [RUM-1196] escape CSS rules containing a colon for Safari compatibility ([#2440](https://github.com/DataDog/browser-sdk/pull/2440))\n- 🐛 [RUM-1062] remove message prefix when using the console handler ([#2452](https://github.com/DataDog/browser-sdk/pull/2452))\n- 🐛 [RUM-1211] fix compatibility with TS4.6/4.7 using ES2022 ([#2455](https://github.com/DataDog/browser-sdk/pull/2455))\n\n## v4.50.0\n\n- ✨ [RUM-1062] add a prefix to all console message displayed by the SDK ([#2432](https://github.com/DataDog/browser-sdk/pull/2432))\n- ✨ [extension] add columns to the event list ([#2372](https://github.com/DataDog/browser-sdk/pull/2372))\n- ✨ [extension] revamp event description and JSON viz ([#2371](https://github.com/DataDog/browser-sdk/pull/2371))\n- ✨ [extension] revamp filter UI ([#2370](https://github.com/DataDog/browser-sdk/pull/2370))\n- ✨ [extension] filter outdated events ([#2369](https://github.com/DataDog/browser-sdk/pull/2369))\n- 🐛 [RUM-1085] Remove lock usage from Local Storage strategy ([#2435](https://github.com/DataDog/browser-sdk/pull/2435))\n- ♻️ rename scroll fields ([#2439](https://github.com/DataDog/browser-sdk/pull/2439))\n- 🔇 Remove cwv attribution telemetry\n- ♻️ [RUM-1039] Harmonize view tests ([#2430](https://github.com/DataDog/browser-sdk/pull/2430))\n- Report scroll metrics when page is resized ([#2399](https://github.com/DataDog/browser-sdk/pull/2399))\n- ♻️ [RUM-253] adapt transport to send encoded data ([#2415](https://github.com/DataDog/browser-sdk/pull/2415))\n- 🔊 [RUM-253] customize deflate worker failure logs ([#2414](https://github.com/DataDog/browser-sdk/pull/2414))\n- ♻️ Use performance entry fixtures in tests ([#2428](https://github.com/DataDog/browser-sdk/pull/2428))\n- ⚗️ [RUM-1020] Collect core web vitals target selectors ([#2418](https://github.com/DataDog/browser-sdk/pull/2418))\n\n## v4.49.0\n\n- ✨[RUM-265] Store contexts across pages ([#2378](https://github.com/DataDog/browser-sdk/pull/2378))\n- ✨[RUM-1016] Allow to change \"view.name\" ([#2396](https://github.com/DataDog/browser-sdk/pull/2396))\n- ✨[RUM-1013] Early exit when no configuration provided ([#2417](https://github.com/DataDog/browser-sdk/pull/2417))\n- 🐛[RUM-89] Do not count discarded resources ([#2410](https://github.com/DataDog/browser-sdk/pull/2410))\n\n## v4.48.2\n\n- 🐛 fix dynamic style serialization ([#2397](https://github.com/DataDog/browser-sdk/pull/2397))\n\n## v4.48.1\n\n- 🐛 fix INP support detection ([#2405](https://github.com/DataDog/browser-sdk/pull/2405))\n\n## v4.48.0\n\n- ✨ [RUM-252] optimistic worker creation ([#2377](https://github.com/DataDog/browser-sdk/pull/2377))\n- 🐛 do not ignore @import rules pointing to inaccessible stylesheets ([#2398](https://github.com/DataDog/browser-sdk/pull/2398))\n- 🎨 [RUM-262] Move view metrics in dedicated files ([#2386](https://github.com/DataDog/browser-sdk/pull/2386))\n- ♻️ [RUM-253] refactor batch creation ([#2390](https://github.com/DataDog/browser-sdk/pull/2390))\n- ⚗️ [RUM-257] Collect INP ([#2355](https://github.com/DataDog/browser-sdk/pull/2355))\n- ♻️ [RUM-250] introduce a DeflateEncoder ([#2376](https://github.com/DataDog/browser-sdk/pull/2376))\n\n## v4.47.0\n\n- ✨ [RUM-233] add workerUrl initialization parameter ([#2354](https://github.com/DataDog/browser-sdk/pull/2354))\n- 🐛[RUM-142] fix the generation of some invalid selectors ([#2375](https://github.com/DataDog/browser-sdk/pull/2375))\n- ✨ enable scrollmap collection ([#2374](https://github.com/DataDog/browser-sdk/pull/2374))\n- 📝 [RUM-254] Document extension internally available on store ([#2368](https://github.com/DataDog/browser-sdk/pull/2368))\n- ♻️ Cherry-pick some changes from v5 to limit conflicts ([#2357](https://github.com/DataDog/browser-sdk/pull/2357))\n\n## v4.46.0\n\n- ⚗ [RUM][REPLAY] Try to reduce the size of the replay payload ([#2348](https://github.com/DataDog/browser-sdk/pull/2348))\n- ♻️ [RUM-249] update worker protocol ([#2346](https://github.com/DataDog/browser-sdk/pull/2346))\n- 🔈 Add web vital attribution telemetry debug ([#2344](https://github.com/DataDog/browser-sdk/pull/2344))\n- 📝 [developer-extension] Update extension instructions ([#2343](https://github.com/DataDog/browser-sdk/pull/2343))\n- 🔉 [developer-extension] bootstrap monitoring ([#2337](https://github.com/DataDog/browser-sdk/pull/2337))\n- 🐛 Avoid setting non-object values for contexts ([#2341](https://github.com/DataDog/browser-sdk/pull/2341))\n\n## v4.45.0\n\n- ✨ [RUM-235] add sample rates fields ([#2323](https://github.com/DataDog/browser-sdk/pull/2323))\n- 🐛 [RUM-238] Handle tracekit multilines message parsing ([#2332](https://github.com/DataDog/browser-sdk/pull/2332))\n- 🐛👷 Fix scope packages npm publication ([#2334](https://github.com/DataDog/browser-sdk/pull/2334))\n- 🔉 monitor reported errors ([#2335](https://github.com/DataDog/browser-sdk/pull/2335))\n\n## v4.44.2\n\n- 🐛👷 [RUM-232] fix worker/string package ([#2331](https://github.com/DataDog/browser-sdk/pull/2331))\n\n## v4.44.1\n\n- 🐛 Fix RUM slim npm package publication ([#2325](https://github.com/DataDog/browser-sdk/pull/2325))\n- 🐛 [RUM-231] Fix location.origin is \"null\" for file: URIs ([#2306](https://github.com/DataDog/browser-sdk/pull/2306))\n- ♻️ [RUM-232] create a `@datadog/browser-worker` package ([#2319](https://github.com/DataDog/browser-sdk/pull/2319))\n- 🔊 Add tracekit try parse message failing telemetry ([#2322](https://github.com/DataDog/browser-sdk/pull/2322))\n- 💬 Update heavy customer data warning ([#2316](https://github.com/DataDog/browser-sdk/pull/2316))\n\n## v4.44.0\n\n- ✨ Collect replay privacy level in views ([#2299](https://github.com/DataDog/browser-sdk/pull/2299))\n- 🐛 [RUMF-1613] fix session replay performance regression ([#2313](https://github.com/DataDog/browser-sdk/pull/2313))\n- ♻️ Base foreground computation on page lifecycle states ([#2253](https://github.com/DataDog/browser-sdk/pull/2253))\n- ⚗ Collect scroll metrics ([#2180](https://github.com/DataDog/browser-sdk/pull/2180))\n\n## v4.43.0\n\n- ✨ [RUMF-1580] Implement storage fallback ([#2261](https://github.com/DataDog/browser-sdk/pull/2261))\n- ✨ [RUMF-1580] Implement Local Storage ([#2260](https://github.com/DataDog/browser-sdk/pull/2260))\n- 🐛 Telemetry: do not scrub staging and canary frames ([#2273](https://github.com/DataDog/browser-sdk/pull/2273))\n- ♻️ [RUMF-1580] Decouple storage mechanism ([#2259](https://github.com/DataDog/browser-sdk/pull/2259))\n- ⚗️ [RUMF-1499] Don't send duration for resources crossing a page frozen state ([#2255](https://github.com/DataDog/browser-sdk/pull/2255))\n- 🔊 [RUMF-1577] Collect page lifecycle states ([#2229](https://github.com/DataDog/browser-sdk/pull/2229))\n\n## v4.42.2\n\n- 🐛 Fix TypeError when document.cookie is empty ([#2216](https://github.com/DataDog/browser-sdk/pull/2216))\n- 🐛 [RUMF-1583][recorder] do not ignore empty text node during serialization ([#2237](https://github.com/DataDog/browser-sdk/pull/2237))\n- 🐛 Fix `use_excluded_activity_urls` telemetry ([#2236](https://github.com/DataDog/browser-sdk/pull/2236))\n- 🐛 when bridge is present, send a final view update on page exit ([#2234](https://github.com/DataDog/browser-sdk/pull/2234))\n- 📝 Update FCP browser support ([#2187](https://github.com/DataDog/browser-sdk/pull/2187))\n- 👷 use a separate job to deploy US1 ([#2228](https://github.com/DataDog/browser-sdk/pull/2228))\n\n## v4.42.1\n\n- 🐛 fix isolatedModules support ([#2209](https://github.com/DataDog/browser-sdk/pull/2209))\n- 🐛 [RUMF-1576] fix support for tools that removes console.\\* references ([#2210](https://github.com/DataDog/browser-sdk/pull/2210))\n- 📦👷 include webpack, typescript and @types/express in common upgrades ([#2222](https://github.com/DataDog/browser-sdk/pull/2222))\n- ⚡ remove spec files from npm packages ([#2224](https://github.com/DataDog/browser-sdk/pull/2224))\n- 📦 [RUMF-1532] update webpack-related dependencies ([#2212](https://github.com/DataDog/browser-sdk/pull/2212))\n- 📦 update vulnerable subdependency engine.io ([#2211](https://github.com/DataDog/browser-sdk/pull/2211))\n\n## v4.42.0\n\n- ✨[RUMF-1573] Allow to provide custom fingerprint to RUM errors ([#2189](https://github.com/DataDog/browser-sdk/pull/2189))\n- ✨[RUMF-1508] Provide stack trace for all uncaught exceptions ([#2182](https://github.com/DataDog/browser-sdk/pull/2182))\n- ✨[RUMF-1573] allow to add modifiable field paths with beforeSend ([#2186](https://github.com/DataDog/browser-sdk/pull/2186))\n- 🐛 Revert Errors serialization behavior ([#2197](https://github.com/DataDog/browser-sdk/pull/2197))\n- ♻️ [RUMF-1508] reorganise error handling ([#2181](https://github.com/DataDog/browser-sdk/pull/2181))\n\n## v4.41.0\n\n- ✨ [RUMF-1470] enable sanitize for user-provided data ([#2175](https://github.com/DataDog/browser-sdk/pull/2175))\n\n## v4.40.0\n\n- ♻️ [RUMF-1508] refactor error types / constants ([#2179](https://github.com/DataDog/browser-sdk/pull/2179))\n- ✨ [RUMF-1530] enable sending replay metadata as json ([#2177](https://github.com/DataDog/browser-sdk/pull/2177))\n- ✨ [RUMF-1479] enable heatmaps collection ([#2178](https://github.com/DataDog/browser-sdk/pull/2178))\n- ✨ [RUMF-1534] send a view update when session is expiring ([#2166](https://github.com/DataDog/browser-sdk/pull/2166))\n- ✨ [RUMF-1534] allow (some) view updates after session expiration ([#2167](https://github.com/DataDog/browser-sdk/pull/2167))\n- 🐛 Fix exception when using wrong tracing parameters ([#2173](https://github.com/DataDog/browser-sdk/pull/2173))\n- 🚨 add require-await rule and remove useless async ([#2132](https://github.com/DataDog/browser-sdk/pull/2132))\n- ✨ [RUMF-1530] send replay metadata as json ([#2125](https://github.com/DataDog/browser-sdk/pull/2125))\n- ✨ [RUMF-1533] flush pending data on session expiration ([#2150](https://github.com/DataDog/browser-sdk/pull/2150))\n- ♻️ factorize LifeCycle and simplify its types ([#2165](https://github.com/DataDog/browser-sdk/pull/2165))\n\n## v4.39.0\n\n- ♻️ [RUMF-1533] extract the Flush logic into a reusable component ([#2144](https://github.com/DataDog/browser-sdk/pull/2144))\n- 🔥 Cleanup unnecessary flags ([#2145](https://github.com/DataDog/browser-sdk/pull/2145))\n- [REPLAY] Add public function to get the link to current Replay ([#2047](https://github.com/DataDog/browser-sdk/pull/2047))\n- 🐛 [RUMF-1544] Fix badly polyfilled URL ([#2141](https://github.com/DataDog/browser-sdk/pull/2141))\n- Add an eslint rule to disallow the use of too generic utility file names ([#2101](https://github.com/DataDog/browser-sdk/pull/2101))\n- ♻️ [RUMF-1517] split tools utils ([#2128](https://github.com/DataDog/browser-sdk/pull/2128))\n- ♻️ [RUMF-1505] make sure we don't use Zone.js addEventListener ([#2129](https://github.com/DataDog/browser-sdk/pull/2129))\n- 🏷️ improve addEventListener typings ([#2127](https://github.com/DataDog/browser-sdk/pull/2127))\n- 🐛[RUMF-1517] Remove specHelper export in src code ([#2126](https://github.com/DataDog/browser-sdk/pull/2126))\n- ♻️ rename performance utils ([#2136](https://github.com/DataDog/browser-sdk/pull/2136))\n- ✨ Support snippet as a valid file url for stack trace computation ([#2077](https://github.com/DataDog/browser-sdk/pull/2077))\n- ✅ Remove feature flag test warning noise\n\n## v4.38.0\n\n- ✨ [RUMF-1510] Warn the user when a heavy context is used ([#2120](https://github.com/DataDog/browser-sdk/pull/2120))\n- ♻️ [RUMF-1517] reorganise some components ([#2124](https://github.com/DataDog/browser-sdk/pull/2124))\n- 🐛 [RUMF-1470] Sanitize - Fix size computation ([#2116](https://github.com/DataDog/browser-sdk/pull/2116))\n- ✅ improve async calls collection ([#2123](https://github.com/DataDog/browser-sdk/pull/2123))\n- 🔊 Collect url and base on failing URL build telemetry ([#2062](https://github.com/DataDog/browser-sdk/pull/2062))\n- 📝 [RUMF-1526] simplify rum package README.md ([#2122](https://github.com/DataDog/browser-sdk/pull/2122))\n- 📝 [RUMF-1526] simplify logs package README.md ([#2121](https://github.com/DataDog/browser-sdk/pull/2121))\n- ♻️ [RUMF-1529] use an enum for experimental features ([#2113](https://github.com/DataDog/browser-sdk/pull/2113))\n- ♻️ [RUMF-1517] split rum test utils ([#2117](https://github.com/DataDog/browser-sdk/pull/2117))\n- ♻️ [RUMF-1517] split core specHelper ([#2111](https://github.com/DataDog/browser-sdk/pull/2111))\n- ♻️ [RUMF-1517] rework test utils ([#2118](https://github.com/DataDog/browser-sdk/pull/2118))\n- ♻️ [RUMF-1517] add test index files ([#2115](https://github.com/DataDog/browser-sdk/pull/2115))\n- ♻️ [RUMF-1517] split domain utils ([#2105](https://github.com/DataDog/browser-sdk/pull/2105))\n\n## v4.37.0\n\n- ♻️[RUMF-1517] split rum-core specHelper ([#2106](https://github.com/DataDog/browser-sdk/pull/2106))\n- ♻️[RUMF-1517] split scripts utils ([#2102](https://github.com/DataDog/browser-sdk/pull/2102))\n- ✨[RUMF-1500] Remove some references to legacy bundles ([#2097](https://github.com/DataDog/browser-sdk/pull/2097))\n- 📝 RUMF-1497 Update logger API documentation ([#2098](https://github.com/DataDog/browser-sdk/pull/2098))\n- ✨ [RUMF-1518] implement a new API to stop the RUM session ([#2064](https://github.com/DataDog/browser-sdk/pull/2064))\n- 🐛 ♻️ [RUMF 1470] Fix serialization issues ([#1971](https://github.com/DataDog/browser-sdk/pull/1971))\n- ♻️ [RUMF-1505] introduce a safe `setInterval` helper function ([#2044](https://github.com/DataDog/browser-sdk/pull/2044))\n\n## v4.36.0\n\n- ✨ [RUMF-1497] Allow logger APIs to pass an Error parameter ([#2029](https://github.com/DataDog/browser-sdk/pull/2029))\n- ⚗️ [RUMF-1522] Expose addFeatureFlagEvaluation ([#2096](https://github.com/DataDog/browser-sdk/pull/2096))\n- 🐛 [RUMF-1491] fix error when calling `fetch` with an unexpected value as first parameter ([#2061](https://github.com/DataDog/browser-sdk/pull/2061))\n\n## v4.35.0\n\n- ✨[RUMF-1500] deploy new datacenter files ([#2049](https://github.com/DataDog/browser-sdk/pull/2049))\n\n## v4.34.3\n\n- 🐛 Handle undefined cancel idle callback ([#2045](https://github.com/DataDog/browser-sdk/pull/2045))\n- ♻️ [RUMF-1500] tweak deployment scripts ([#2046](https://github.com/DataDog/browser-sdk/pull/2046))\n- ♻️ [RUMF-1505] introduce and use a safe `setTimeout` helper function ([#2032](https://github.com/DataDog/browser-sdk/pull/2032))\n- ♻️ [REPLAY] Avoid casting & add proper check instead of relying on try/catch ([#2016](https://github.com/DataDog/browser-sdk/pull/2016))\n\n## v4.34.2\n\n- 🐛 [RUMF-1443] fix Zone.js/Angular crash when recording the session ([#2030](https://github.com/DataDog/browser-sdk/pull/2030))\n- 🐛 [REPLAY] Fix serialization for checkbox & radio ([#2021](https://github.com/DataDog/browser-sdk/pull/2021))\n- ⚗️ [RUMF-1484] use pagehide as unload event ([#2020](https://github.com/DataDog/browser-sdk/pull/2020))\n\n## v4.34.1\n\n- 🐛 [RUMF-1493] Avoid infinite loop on `form > input[name=\"host\"]` element ([#2017](https://github.com/DataDog/browser-sdk/pull/2017))\n- 🐛 [RUMF-1485] Flush event when page becomes frozen ([#2015](https://github.com/DataDog/browser-sdk/pull/2015))\n- 🐛 [RUMF-1296][rumf-1293] Fix dead click computation ([#1998](https://github.com/DataDog/browser-sdk/pull/1998))\n\n## v4.34.0\n\n- 🐛 fix Shadow DOM support on Microsoft Edge ([#2003](https://github.com/DataDog/browser-sdk/pull/2003))\n- ✨ [RUMF-1469] introduce a new `proxy` initialization parameter ([#1947](https://github.com/DataDog/browser-sdk/pull/1947))\n\n## v4.33.0\n\n- 🐛 fix frustration animation in session replay ([#1999](https://github.com/DataDog/browser-sdk/pull/1999))\n- ✨ Add new intake strategy for ap1 ([#1997](https://github.com/DataDog/browser-sdk/pull/1997))\n- Revert \"🔊 add view document_count in non-view events ([#1892](https://github.com/DataDog/browser-sdk/pull/1892))\" ([#1959](https://github.com/DataDog/browser-sdk/pull/1959))\n- 🐛 [REPLAY] Discard mouse/touch event without x/y position ([#1993](https://github.com/DataDog/browser-sdk/pull/1993))\n\n## v4.32.1\n\n- 🐛[RUMF-1450] stop computing coordinates for focus/blur records ([#1985](https://github.com/DataDog/browser-sdk/pull/1985))\n\n## v4.32.0\n\n- 🐛 ignore contenteditable elements for dead clicks ([#1986](https://github.com/DataDog/browser-sdk/pull/1986))\n- 🐛 [RUMF-1476] Fix removednodes.foreach is not a function ([#1984](https://github.com/DataDog/browser-sdk/pull/1984))\n- 🐛⚗ [RUMF-1293] discard dead clicks when activity occurs on pointerdown ([#1979](https://github.com/DataDog/browser-sdk/pull/1979))\n- ⬆️ fix flaky test ([#1982](https://github.com/DataDog/browser-sdk/pull/1982))\n- 🔊 Enable customer data telemetry ([#1983](https://github.com/DataDog/browser-sdk/pull/1983))\n- ⚗🐛 [RUMF-1296] use pointerup to trigger click actions ([#1958](https://github.com/DataDog/browser-sdk/pull/1958))\n- [REPLAY] Add telemetry for shadow dom ([#1978](https://github.com/DataDog/browser-sdk/pull/1978))\n- ⬆️ fix Jasmine deprecation warning on unit tests/IE ([#1974](https://github.com/DataDog/browser-sdk/pull/1974))\n- 🐛[RUMF-1465] collect data for disturbed response ([#1977](https://github.com/DataDog/browser-sdk/pull/1977))\n- 🔊 [REPLAY] Add telemetry for shadow DOM ([#1975](https://github.com/DataDog/browser-sdk/pull/1975))\n\n## v4.31.0\n\n- ✨[REPLAY] Add support for shadow dom ([#1969](https://github.com/DataDog/browser-sdk/pull/1969))\n- ✨[REPLAY] Keep Href from link even when importing CSS ([#1960](https://github.com/DataDog/browser-sdk/pull/1960))\n- 🐛[RUMF-1465] fix missing data when fetch instrumented by zone.js ([#1942](https://github.com/DataDog/browser-sdk/pull/1942))\n- ⚗️ 🐛 reset input state at the beginning of each click ([#1968](https://github.com/DataDog/browser-sdk/pull/1968))\n- ⚗️ 🔊[RUMF-1467] Collect user data telemetry ([#1941](https://github.com/DataDog/browser-sdk/pull/1941))\n- ⚗️ 🔊 [RUMF-1445] Check if the page was discarded before a resource ([#1945](https://github.com/DataDog/browser-sdk/pull/1945))\n\n## v4.30.1\n\n- ⚗️ [REPLAY] Add support for `adoptedStyleSheets` ([#1916](https://github.com/DataDog/browser-sdk/pull/1916))\n- 🔊 [RUMF-1345] Revert log first untrusted events of each type ([#1940](https://github.com/DataDog/browser-sdk/pull/1940))\n- 🐛 Fix `getInitConfiguration()` behaviour ([#1893](https://github.com/DataDog/browser-sdk/pull/1893))\n- ⚡ Ignore modulepreload and prefetch in link tags ([#1921](https://github.com/DataDog/browser-sdk/pull/1921))\n- ⚗️🔊 Collect page lifecycle states in resources ([#1890](https://github.com/DataDog/browser-sdk/pull/1890))\n\n## v4.30.0\n\n- ✨[RUMF-1397] init parameter standardisation ([#1917](https://github.com/DataDog/browser-sdk/pull/1917))\n\n## v4.29.1\n\n- ⚗️ [REPLAY] Experiment support for shadow DOM ([#1787](https://github.com/DataDog/browser-sdk/pull/1787))\n- 🔊 [RUMF-1345] add telemetry logs on untrusted events ([#1910](https://github.com/DataDog/browser-sdk/pull/1910))\n- 🔊 add view document_count in non-view events ([#1892](https://github.com/DataDog/browser-sdk/pull/1892))\n\n## v4.29.0\n\n- 🐛 [RUMF-1435] do not retry status 0 request while online ([#1891](https://github.com/DataDog/browser-sdk/pull/1891))\n- ✨ [RUMF-1236] Add support for OTel headers ([#1832](https://github.com/DataDog/browser-sdk/pull/1832))\n- 🐛[RUMF-1435] don't retry opaque response ([#1877](https://github.com/DataDog/browser-sdk/pull/1877))\n- ✨ [RUMF-1425] enable request retry/throttle for replay intake ([#1819](https://github.com/DataDog/browser-sdk/pull/1819))\n- 🐛 [RUMF-1421] keep updating the view event counters after view end ([#1864](https://github.com/DataDog/browser-sdk/pull/1864))\n\n## v4.28.1\n\n- Re-release v4.28.0 to work around a NPM packaging issue\n\n## v4.28.0\n\n- 🐛 [RUMF-1337] Fix incorrect fetch duration ([#1875](https://github.com/DataDog/browser-sdk/pull/1875))\n\n## v4.27.1\n\n- 🐛 [RUMF-1449] fix Zone support when **symbol** is missing ([#1872](https://github.com/DataDog/browser-sdk/pull/1872))\n\n## v4.27.0\n\n- ✨Allow internal analytics subdomain ([#1863](https://github.com/DataDog/browser-sdk/pull/1863))\n- 🔊 Collect computed and perf entry durations ([#1861](https://github.com/DataDog/browser-sdk/pull/1861))\n- 🐛 [RUMF-1449] workaround for Firefox memory leak when using Zone.js ([#1860](https://github.com/DataDog/browser-sdk/pull/1860))\n- ✨ send data from the SDK to the extension ([#1850](https://github.com/DataDog/browser-sdk/pull/1850))\n- ♻️ [RUMF-1440] improve feature flag collection implementation ([#1839](https://github.com/DataDog/browser-sdk/pull/1839))\n\n## v4.26.0\n\n- 🐛 [RUMF-1421] improve counters by filtering child events ([#1837](https://github.com/DataDog/browser-sdk/pull/1837))\n- ✨ [RUMF-1435] Add transport api on events ([#1840](https://github.com/DataDog/browser-sdk/pull/1840))\n- ⚗️ [RUMF-1337] add `fetch_duration` experiment to resolve incorrect fetch duration ([#1810](https://github.com/DataDog/browser-sdk/pull/1810))\n- ✨ Move extension settings to a Settings panel ([#1847](https://github.com/DataDog/browser-sdk/pull/1847))\n- ✨ Clear event list on page reload for SDK extension ([#1825](https://github.com/DataDog/browser-sdk/pull/1825))\n- ⬆️ [RUMF-1434] fix yarn failing to install puppeteer on M1 mac ([#1843](https://github.com/DataDog/browser-sdk/pull/1843))\n- ⬆️ [RUMF-1434] fix running e2e tests on M1 macs ([#1842](https://github.com/DataDog/browser-sdk/pull/1842))\n- ✨ Improve event description message in developer extension ([#1831](https://github.com/DataDog/browser-sdk/pull/1831))\n- ✨ [RUMF-1396] migrate extension to manifest v3 ([#1828](https://github.com/DataDog/browser-sdk/pull/1828))\n\n## v4.25.0\n\n- ⚡️ ⚗ [RUMF-1438] Collect feature flags ([#1827](https://github.com/DataDog/browser-sdk/pull/1827))\n- ✨ Auto Flush for SDK extension ([#1824](https://github.com/DataDog/browser-sdk/pull/1824))\n\n## v4.24.1\n\n- ⏪ Revert \"🐛 [RUMF-1410] Allow serialization of objects with cyclic references ([#1783](https://github.com/DataDog/browser-sdk/pull/1783))\" ([#1821](https://github.com/DataDog/browser-sdk/pull/1821))\n- 📈[RUMF-1432] Collect trackResources and trackLongTasks configs ([#1814](https://github.com/DataDog/browser-sdk/pull/1814))\n- 🗑️ [RUMF-1433] Remove Preflight request Performance Entry check ([#1813](https://github.com/DataDog/browser-sdk/pull/1813))\n- ✨[RUMF-1435] Add some retry info on events ([#1817](https://github.com/DataDog/browser-sdk/pull/1817))\n\n## v4.24.0\n\n- ⚗️✨ [RUMF-1379] heatmaps: enable descendant combined selectors ([#1811](https://github.com/DataDog/browser-sdk/pull/1811))\n- ✨ [RUMF-1409] Provide setUser and related functions for logs SDK ([#1801](https://github.com/DataDog/browser-sdk/pull/1801))\n- ⚗️ ✨ [RUMF-1425] use the retry/throttle transport strategy to send segments ([#1807](https://github.com/DataDog/browser-sdk/pull/1807))\n- ♻️ [RUMF-1424] factorize page exit logic ([#1805](https://github.com/DataDog/browser-sdk/pull/1805))\n- 📝 Clarify log SDK usage in the readme ([#1767](https://github.com/DataDog/browser-sdk/pull/1767))\n\n## v4.23.3\n\n- 🐛 [REPLAY-1075] Convert relative URLS to absolute in stylesheets ([#1792](https://github.com/DataDog/browser-sdk/pull/1792))\n- 🐛 [RUMF-1423] prevent unexpected behavior when our xhr are reused ([#1797](https://github.com/DataDog/browser-sdk/pull/1797))\n- 🐛 [RUMF-1410] Allow serialization of objects with cyclic references ([#1783](https://github.com/DataDog/browser-sdk/pull/1783))\n\n## v4.23.2\n\n- 🔉[RUMF-1423] Investigation for retry issue - part 2 ([#1793](https://github.com/DataDog/browser-sdk/pull/1793))\n\n## v4.23.1\n\n- 🔉[RUMF-1423] Add debug log for retry issue ([#1790](https://github.com/DataDog/browser-sdk/pull/1790))\n\n## v4.23.0\n\n- ✨[RUMF-1377] Enable new request strategy ([#1770](https://github.com/DataDog/browser-sdk/pull/1770))\n- 🐛 [RUMF-1393] don't mask attributes used to create CSS selectors ([#1737](https://github.com/DataDog/browser-sdk/pull/1737))\n- ⚗ [RUMF-1379] heatmap: experiment improved selector regarding unicity ([#1741](https://github.com/DataDog/browser-sdk/pull/1741))\n\n## v4.22.0\n\n- ⚡️ Enable telemetry configuration ([#1780](https://github.com/DataDog/browser-sdk/pull/1780))\n- 🔊 [RUMF-1416] Use service distinguish log rum telemetry configuration ([#1774](https://github.com/DataDog/browser-sdk/pull/1774))\n- ✨ accept functions in allowedTracingOrigins/excludedActivityUrls arguments list ([#1775](https://github.com/DataDog/browser-sdk/pull/1775))\n- ⚗️ [RUMF-1405] remove mechanism to simulate intake issue ([#1768](https://github.com/DataDog/browser-sdk/pull/1768))\n- 🔊 Collect configuration telemetry event ([#1760](https://github.com/DataDog/browser-sdk/pull/1760))\n\n## v4.21.2\n\n- ⚗️ [RUMF-1405] add mechanism to simulate intake issue ([#1757](https://github.com/DataDog/browser-sdk/pull/1757))\n\n## v4.21.1\n\n- 🐛 npm publish: skip publish confirmation ([#1755](https://github.com/DataDog/browser-sdk/pull/1755))\n\n## v4.21.0\n\n- ✨ [RUMF-1353] Collect error causes ([#1740](https://github.com/DataDog/browser-sdk/pull/1740))\n- 🐛 [RUMF-1276] handle performance entry without `toJSON` ([#1751](https://github.com/DataDog/browser-sdk/pull/1751))\n- 🐛 handle undefined policy ([#1752](https://github.com/DataDog/browser-sdk/pull/1752))\n\n## v4.20.0\n\n- ✨ [RUMF-1391] Introduce trackResources, trackLongTasks and sessionReplaySampleRate ([#1744](https://github.com/DataDog/browser-sdk/pull/1744))\n- ♻️ [RUMF-1368] use the PointerDown event target for click actions ([#1731](https://github.com/DataDog/browser-sdk/pull/1731))\n- ⚗ [RUMF-1379] use experimented CSS selectors strategies by default ([#1738](https://github.com/DataDog/browser-sdk/pull/1738))\n\n## v4.19.1\n\n- 🐛 [RUMF-1369] Exclude error message from stacktrace parsing ([#1725](https://github.com/DataDog/browser-sdk/pull/1725))\n- 🐛 [RUMF-1384] Filter abnormal TTFB values ([#1729](https://github.com/DataDog/browser-sdk/pull/1729))\n- 🐛 [RUMF-1378] do not mask action name attributes ([#1721](https://github.com/DataDog/browser-sdk/pull/1721))\n- ⚗️ [RUMF-1378] use stable attributes when computing heatmap selector ([#1724](https://github.com/DataDog/browser-sdk/pull/1724))\n- ⚗️ [RUMF-1379] heatmaps: refine selectors pass 2 ([#1726](https://github.com/DataDog/browser-sdk/pull/1726))\n- ⚗️ [RUMF-1351] tweak retry strategy ([#1723](https://github.com/DataDog/browser-sdk/pull/1723))\n- ⚗️ [RUMF-1351] retry request on timeout ([#1728](https://github.com/DataDog/browser-sdk/pull/1728))\n\n## v4.19.0\n\n- ✨ [RUMF-1286] test for expected features before starting recording ([#1719](https://github.com/DataDog/browser-sdk/pull/1719))\n- ✨ [RUMF-1371] Collect view time to first byte ([#1717](https://github.com/DataDog/browser-sdk/pull/1717))\n- 📝 Fix `actionNameAttribute` broken link ([#1708](https://github.com/DataDog/browser-sdk/pull/1708))\n- ⚗️🔉 [RUMF-1351] add error when reaching max events size queued for upload ([#1716](https://github.com/DataDog/browser-sdk/pull/1716))\n- ⚗️🔉 [RUMF-1351] retry: add extra context to queue full log ([#1714](https://github.com/DataDog/browser-sdk/pull/1714))\n- ⚗️✨[RUMF-1351] experiment request retry strategy ([#1700](https://github.com/DataDog/browser-sdk/pull/1700))\n\n## v4.18.1\n\n- 🐛 [RUMF-1333] fix keepalive support check ([#1712](https://github.com/DataDog/browser-sdk/pull/1712))\n\n## v4.18.0\n\n- ✨ [RUMF-1306] Send the tracing sample rate in rule_psr for resources ([#1669](https://github.com/DataDog/browser-sdk/pull/1669)), ([#1705](https://github.com/DataDog/browser-sdk/pull/1705))\n- ✨ [RUMF-1333] Send request with fetch keepalive + fallback ([#1701](https://github.com/DataDog/browser-sdk/pull/1701)), ([#1682](https://github.com/DataDog/browser-sdk/pull/1682))\n- ✨ [RUMF-1309] Implement nested CSS support ([#1699](https://github.com/DataDog/browser-sdk/pull/1699))\n- 🐛 Fix instrumention of null function with 3rd party wrapper ([#1570](https://github.com/DataDog/browser-sdk/pull/1570)) ([#1697](https://github.com/DataDog/browser-sdk/pull/1697))\n\n## v4.17.2\n\n- 🐛 [RUMF-1344] scroll positions: remove fallback for null scrollingElement ([#1694](https://github.com/DataDog/browser-sdk/pull/1694))\n- ⚗️ [RUMF-1356] selectors using stable attributes and no class names ([#1689](https://github.com/DataDog/browser-sdk/pull/1689))\n- 👷 [RUMF-1357] Add a peer dependency between rum and logs packages ([#1668](https://github.com/DataDog/browser-sdk/pull/1668))\n\n## v4.17.1\n\n- 🐛 [RUMF-1344] try to improve document scrolling element handling ([#1688](https://github.com/DataDog/browser-sdk/pull/1688))\n- ✨⚗ [RUMF-1355] add selector with stable attributes ([#1684](https://github.com/DataDog/browser-sdk/pull/1684))\n\n## v4.17.0\n\n- ✨ [RUMF-1315] Extend user object methods ([#1641](https://github.com/DataDog/browser-sdk/pull/1641))\n- ⚡[RUMF-1344] Serialize scroll positions only for full snapshots ([#1670](https://github.com/DataDog/browser-sdk/pull/1670))\n- ⚡ [RUMF-1344] Access scroll attributes only on initial full snapshot ([#1680](https://github.com/DataDog/browser-sdk/pull/1680))\n- ⚗️ [RUMF-1346] heatmaps: move action event attributes ([#1667](https://github.com/DataDog/browser-sdk/pull/1667))\n- 🐛 [RUMF-1239] Hide placeholder value when privacy set to mask ([#1660](https://github.com/DataDog/browser-sdk/pull/1660))\n- 🐛 fix compatibility check ([#1685](https://github.com/DataDog/browser-sdk/pull/1685))\n\n## v4.16.1\n\n- 🐛 [RUMF-1274] track request to undefined/null URL ([#1665](https://github.com/DataDog/browser-sdk/pull/1665))\n\n## v4.16.0\n\n- ✨ [REPLAY-898] Recording Frustration signals (dead, error & rage clicks) for session replay ([#1632](https://github.com/DataDog/browser-sdk/pull/1632))\n- 🐛 [RUMF-1310] handle extra stacktrace parsing cases ([#1647](https://github.com/DataDog/browser-sdk/pull/1647))\n- 🐛 improve `jsonStringify` implementation ([#1653](https://github.com/DataDog/browser-sdk/pull/1653))\n- 🔒 [RUMF-1335] fix incorrect string escape ([#1651](https://github.com/DataDog/browser-sdk/pull/1651))\n\n## v4.15.0\n\n- 🐛 frustration signals: track window open ([#1631](https://github.com/DataDog/browser-sdk/pull/1631))\n- 🐛 [RUMF-1327] rum synthetics: fix logs session conflict ([#1629](https://github.com/DataDog/browser-sdk/pull/1629))\n- 🔊 Add feature flags to telemetry events ([#1625](https://github.com/DataDog/browser-sdk/pull/1625))\n- ✨[RUMF-1314] Expose a DD_LOGS.getInternalContext ([#1626](https://github.com/DataDog/browser-sdk/pull/1626))\n- 🐛 [RUMF-1273] fix BUILD_MODE scope ([#1627](https://github.com/DataDog/browser-sdk/pull/1627))\n\n## v4.14.0\n\n- ✨ [RUMF-1211] release Frustration Signals publicly ([#1617](https://github.com/DataDog/browser-sdk/pull/1617))\n- 🐛 [RUMF-1294] ignore dead clicks based on the click event target ([#1610](https://github.com/DataDog/browser-sdk/pull/1610))\n- 📝 Fixing intrapage broken links ([#1613](https://github.com/DataDog/browser-sdk/pull/1613))\n- 📝 Removes Extra Link ([#1612](https://github.com/DataDog/browser-sdk/pull/1612))\n- 🐛 [RUMF-1297] frustration signals: track input changes ([#1603](https://github.com/DataDog/browser-sdk/pull/1603))\n- 📝 DOCS-2277 Browser Monitoring Edits ([#1572](https://github.com/DataDog/browser-sdk/pull/1572))\n- 🐛 [RUMF-1209] frustration signals: track selection change ([#1596](https://github.com/DataDog/browser-sdk/pull/1596))\n\n## v4.13.0\n\n- ✨ Enable service and version update on startView ([#1601](https://github.com/DataDog/browser-sdk/pull/1601))\n\n## v4.12.0\n\n- 🐛 [RUMF-1305] forbid the usage of `Date.now` ([#1600](https://github.com/DataDog/browser-sdk/pull/1600))\n- 🔊 Clear batch before send to allow telemetry in httpRequest.send ([#1594](https://github.com/DataDog/browser-sdk/pull/1594))\n- ⚗✨ [RUMF-1288] Collect viewport size ([#1584](https://github.com/DataDog/browser-sdk/pull/1584))\n\n## v4.11.5\n\n- 🐛 [RUMF-1303] stop forwarding network errors when forwardErrorsToLogs is false ([#1591](https://github.com/DataDog/browser-sdk/pull/1591))\n- ♻️ Simplify RUM assembly ([#1588](https://github.com/DataDog/browser-sdk/pull/1588))\n\n## v4.11.4\n\n- 🏷️ adjust types to allow updating the SDK in Datadog app ([#1587](https://github.com/DataDog/browser-sdk/pull/1587))\n- [RUMF-1280] collect click position ([#1566](https://github.com/DataDog/browser-sdk/pull/1566))\n\n## v4.11.3\n\n- ✨ improve developer extension ([#1580](https://github.com/DataDog/browser-sdk/pull/1580))\n- 🐛 [RUMF-1267] remove last circular dependencies ([#1577](https://github.com/DataDog/browser-sdk/pull/1577))\n\n## v4.11.2\n\n- 🏷️ [RUMF-1256] adjust StyleSheetRule records to support index paths ([#1571](https://github.com/DataDog/browser-sdk/pull/1571))\n- 🐛 [RUMF-1267] resolve remaining cyclic dependencies related to telemetry ([#1567](https://github.com/DataDog/browser-sdk/pull/1567))\n- 📝 Browser Monitoring Edits ([#1563](https://github.com/DataDog/browser-sdk/pull/1563))\n\n## v4.11.1\n\n- ♻️ [RUMF-1190] cleanup telemetry ([#1560](https://github.com/DataDog/browser-sdk/pull/1560))\n- ♻️ [RUMF-1267] remove circular dependencies part 1 ([#1559](https://github.com/DataDog/browser-sdk/pull/1559))\n- ♻️ [RUMF-1277] rename frustration types ([#1557](https://github.com/DataDog/browser-sdk/pull/1557))\n\n## v4.11.0\n\n- ✨ [RUMF-1262] ignore some URLs when watching the page activity ([#1536](https://github.com/DataDog/browser-sdk/pull/1536))\n- ✨ [RUMF-1191] enable telemetry on us1 site ([#1554](https://github.com/DataDog/browser-sdk/pull/1554))\n\n## v4.10.4\n\n- ✨ [RUMF-1191] enable telemetry on eu site ([#1551](https://github.com/DataDog/browser-sdk/pull/1551))\n- ✨ [RUMF-1264] scrub customer frames from telemetry errors ([#1546](https://github.com/DataDog/browser-sdk/pull/1546))\n\n## v4.10.3\n\n- 🐛 Fix dependency issue ([#1549](https://github.com/DataDog/browser-sdk/pull/1549))\n\n## v4.10.2\n\n- ✨ rename Replay plan to Premium plan ([#1534](https://github.com/DataDog/browser-sdk/pull/1534))\n- ✨ enable telemetry on us3 site ([#1544](https://github.com/DataDog/browser-sdk/pull/1544))\n\n## v4.10.1\n\n- ✨ enable telemetry on us5 site ([#1540](https://github.com/DataDog/browser-sdk/pull/1540))\n\n## v4.10.0\n\n- ✨[RUMF-1253] add `tracingSampleRate` option ([#1526](https://github.com/DataDog/browser-sdk/pull/1526))\n- ⚗️✨ [RUMF-1258] stop ongoing action on view end ([#1528](https://github.com/DataDog/browser-sdk/pull/1528))\n- 🐛 [RUMF-1259] support Zone.js < 0.8.6 ([#1530](https://github.com/DataDog/browser-sdk/pull/1530))\n- ✨ add a button to clear events in the developer extension ([#1527](https://github.com/DataDog/browser-sdk/pull/1527))\n- ⚗✨ [RUMF-1210] add a `trackFrustrations` initialization parameter ([#1524](https://github.com/DataDog/browser-sdk/pull/1524))\n- ✨[RUMF-1257] prevent dual shipping of telemetry events ([#1523](https://github.com/DataDog/browser-sdk/pull/1523))\n- ✨ [RUMF-1251] allow to enable telemetry by site ([#1520](https://github.com/DataDog/browser-sdk/pull/1520))\n\n## v4.9.0\n\n- ✨ Upgraded console logger to log the proper levels ([#1501](https://github.com/DataDog/browser-sdk/pull/1501))\n- ♻️ [RUMF-1178] New logger assembly flow ([#1497](https://github.com/DataDog/browser-sdk/pull/1497))\n- ⚗✨ [RUMF-1209] introduce \"dead\" and \"error\" frustration types ([#1487](https://github.com/DataDog/browser-sdk/pull/1487))\n- ⚗✨ [RUMF-1209] collect rage clicks ([#1488](https://github.com/DataDog/browser-sdk/pull/1488))\n- ⚗✨ [RUMF-1214] implement frustration signals counters ([#1511](https://github.com/DataDog/browser-sdk/pull/1511))\n\n## v4.8.1\n\n- 🐛 [RUMF-1240] fix attribute mutating to an empty value ([#1512](https://github.com/DataDog/browser-sdk/pull/1512))\n- ⚗️ [RUMF-1182] add telemetry sample rate ([#1510](https://github.com/DataDog/browser-sdk/pull/1510))\n- 💡 Update links to api key docs ([#1508](https://github.com/DataDog/browser-sdk/pull/1508))\n\n## v4.8.0\n\n- ✨ [RUMF-1192] forward Reports to Datadog ([#1506](https://github.com/DataDog/browser-sdk/pull/1506))\n- ✨ [RUMF-1192] forward `console.*` logs to Datadog ([#1505](https://github.com/DataDog/browser-sdk/pull/1505))\n- 📝 fix documentation for `proxyUrl` documentation ([#1503](https://github.com/DataDog/browser-sdk/pull/1503))\n- ✨ [RUMF-1237] The event bridge allowed hosts should also match subdomains ([#1499](https://github.com/DataDog/browser-sdk/pull/1499))\n- 📝 add `replaySampleRate` to README examples ([#1370](https://github.com/DataDog/browser-sdk/pull/1370))\n\n## v4.7.1\n\n- 🐛 Adjust records generated during view change so their date matches the view date ([#1486](https://github.com/DataDog/browser-sdk/pull/1486))\n- ⚗✨ [RUMF-1224] remove console APIs prefix ([#1479](https://github.com/DataDog/browser-sdk/pull/1479))\n- ♻️ [RUMF-1178] improve logs assembly part 2 ([#1463](https://github.com/DataDog/browser-sdk/pull/1463))\n- ⚗✨ Allow update service version with start view ([#1448](https://github.com/DataDog/browser-sdk/pull/1448))\n- ⚗✨ [RUMF-1208] don't discard automatic action on view creation ([#1451](https://github.com/DataDog/browser-sdk/pull/1451))\n- ⚗✨ [RUMF-1207] collect concurrent actions ([#1434](https://github.com/DataDog/browser-sdk/pull/1434))\n- ♻️ [RUMF-1207] collect concurrent actions groundwork - move action history closer to action collection ([#1432](https://github.com/DataDog/browser-sdk/pull/1432))\n\n## v4.7.0\n\nNote: The Logs Browser SDK 3.10.1 (released on December 21th, 2021) unexpectedly changed the initialization parameter `forwardErrorsToLogs` default value from `true` to `false`. This release restores the default value to `true`, so Logs Browser SDK users who don't specify this parameter will have errors forwarded as logs.\n\n- 🐛 [RUMF-1217] restore forwardErrorsToLogs default value to `true` ([#1433](https://github.com/DataDog/browser-sdk/pull/1433))\n- 🐛 [RUMF-1203] fix `stopSessionReplayRecording` instrumentation cleanup ([#1442](https://github.com/DataDog/browser-sdk/pull/1442))\n- ♻️ 🐛 [RUMF-1178] fix logs displayed twice in the console ([#1425](https://github.com/DataDog/browser-sdk/pull/1425))\n- 📝 Update browser config to include SDK version ([#1380](https://github.com/DataDog/browser-sdk/pull/1380))\n\n## v4.6.1\n\n- 🐛 fix build-env replacement in npm packages ([#1389](https://github.com/DataDog/browser-sdk/pull/1389))\n\n## v4.6.0\n\n- 📦 [RUMF-1162] update developer-extension ([#1379](https://github.com/DataDog/browser-sdk/pull/1379))\n- 🔥 [RUMF-1198] remove problematic and useless code from the DeflateWorker ([#1378](https://github.com/DataDog/browser-sdk/pull/1378))\n- ⚗️✨ [RUMF-1175] collect reports and csp violation ([#1332](https://github.com/DataDog/browser-sdk/pull/1332))\n- ⚗️ [RUMF-1181] collect telemetry events ([#1374](https://github.com/DataDog/browser-sdk/pull/1374))\n- 📄 Update documentation ([#1362](https://github.com/DataDog/browser-sdk/pull/1362))\n- ♻️ [RUMF-1181] preliminary refactorings for telemetry events collection ([#1371](https://github.com/DataDog/browser-sdk/pull/1371))\n- 🎨 Avoid template syntax when not needed ([#1372](https://github.com/DataDog/browser-sdk/pull/1372))\n- 📦 [RUMF-1168] update typescript ([#1368](https://github.com/DataDog/browser-sdk/pull/1368))\n- ⚡️ [RUMF-1171] prefer const enums ([#1364](https://github.com/DataDog/browser-sdk/pull/1364))\n- 🔥 Clear remaining code of network error removal ([#1367](https://github.com/DataDog/browser-sdk/pull/1367))\n- ⚡️ Process buffered performance entries in an idle callback ([#1337](https://github.com/DataDog/browser-sdk/pull/1337))\n- ⚡️ [RUMF-1043] remove TSLib dependency ([#1347](https://github.com/DataDog/browser-sdk/pull/1347))\n- ⚗️✨[RUMF-1188] add telemetry event types ([#1353](https://github.com/DataDog/browser-sdk/pull/1353))\n\n## v4.5.0\n\n- ⚡️ [RUMF-1115] throttle view updates by addTiming ([#1355](https://github.com/DataDog/browser-sdk/pull/1355))\n- 📝 Update the configuration of the Browser Sessions ([#1322](https://github.com/DataDog/browser-sdk/pull/1322))\n- ✨ [RUMF-1177] add index_in_view to segment meta ([#1342](https://github.com/DataDog/browser-sdk/pull/1342))\n- ✨ [RUMF-1103] enable RUM tracking inside mobile webviews ([#1333](https://github.com/DataDog/browser-sdk/pull/1333))\n- ⚗ [RUMF-1176] collect other console logs new ([#1316](https://github.com/DataDog/browser-sdk/pull/1316))\n\n## v4.4.0\n\n- ✨ [RUMF-1180] add `error.source_type` attribute ([#1328](https://github.com/DataDog/browser-sdk/pull/1328))\n- ⚡️ [RUMF-1169] cleanup compute stack trace ([#1335](https://github.com/DataDog/browser-sdk/pull/1335))\n- 🐛 [RUMF-1079] limit session inconsistencies issue on chromium browsers ([#1327](https://github.com/DataDog/browser-sdk/pull/1327))\n\n## v4.3.0\n\n- ✨ [RUMF-1135] expose SDK version through global variable ([#1278](https://github.com/DataDog/browser-sdk/pull/1278))\n- ✨ [RUMF-1174] forward event to bridge with rum type ([#1309](https://github.com/DataDog/browser-sdk/pull/1309))\n- 🐛 [RUMF-1153] fix initial view loading time computation ([#1315](https://github.com/DataDog/browser-sdk/pull/1315))\n- ⚗ [RUMF-1079] restrict cookie-lock to chromium browsers ([#1283](https://github.com/DataDog/browser-sdk/pull/1283))\n\n## v4.2.0\n\n- ⚡️ [RUMF-1113] Notify performance entries by batch ([#1255](https://github.com/DataDog/browser-sdk/pull/1255))\n- 🐛 [RUMF-1147] Implement TextEncoder().encode fallback for replay encorder ([#1269](https://github.com/DataDog/browser-sdk/pull/1269))\n- ✨ [RUMF-1146] add 'source:browser' to all RUM events ([#1271](https://github.com/DataDog/browser-sdk/pull/1271))\n- ⚡️ [RUMF-1111] limit the number of bytes read from the response ([#1264](https://github.com/DataDog/browser-sdk/pull/1264))\n- ✨ [REPLAY-564] enable visual viewport recording ([#1247](https://github.com/DataDog/browser-sdk/pull/1247))\n- 📝 add clarification to config example ([#1268](https://github.com/DataDog/browser-sdk/pull/1268))\n- ⚡️ [RUMF-1111] compute response text in trackNetworkError ([#1263](https://github.com/DataDog/browser-sdk/pull/1263))\n- 📝 [RUMF-1137] replace major changes description by links to the upgrade guide ([#1265](https://github.com/DataDog/browser-sdk/pull/1265))\n- ⚗ [RUMF-1079] tweak max number of lock retries ([#1262](https://github.com/DataDog/browser-sdk/pull/1262))\n\n## v4.1.0\n\n- 🐛 [RUMF-1143] make sure to drop LCP timings if the page was previously hidden ([#1259](https://github.com/DataDog/browser-sdk/pull/1259))\n- ⚗🐛 [RUMF-1079] add lock mechanism for session cookie writes ([#1230](https://github.com/DataDog/browser-sdk/pull/1230))\n- ✨ [RUMF-1119] Implement dual ship for other orgs ([#1248](https://github.com/DataDog/browser-sdk/pull/1248))\n- ✨ [RUMF-1109] Add event rate limiters for loggers ([#1243](https://github.com/DataDog/browser-sdk/pull/1243))\n- ⚡️ [REPLAY-565] ♻️ Remove URL \"relative to absolute\" transformation ([#1244](https://github.com/DataDog/browser-sdk/pull/1244))\n\n## v4.0.1\n\n- 🐛 let the backend to most of the tags sanitization ([#1252](https://github.com/DataDog/browser-sdk/pull/1252))\n- 🐛 remove child with action-names innerText instead of replacing them ([#1251](https://github.com/DataDog/browser-sdk/pull/1251))\n- 📝 Add module convention to contributing ([#1240](https://github.com/DataDog/browser-sdk/pull/1240))\n- ⚡️ [RUMF-1030] Decrease BoundedBuffer limitation to 500 ([#1242](https://github.com/DataDog/browser-sdk/pull/1242))\n\n## v4.0.0\n\nSee our [upgrade guide](https://docs.datadoghq.com/real_user_monitoring/guide/browser-sdk-upgrade/#from-v3-to-v4) for a comprehensive list of breaking changes introduced by this major version.\n\n### Changes\n\n- 💥 improve privacy computation on a single node ([#1226](https://github.com/DataDog/browser-sdk/pull/1226))\n- 💥 [RUMF-1098] move init options into their related interfaces ([#1232](https://github.com/DataDog/browser-sdk/pull/1232))\n- 💥 [RUMF-1093] deprecated proxyhost option ([#1227](https://github.com/DataDog/browser-sdk/pull/1227))\n- 💥 [RUMF-1124] Use the programmatic action attribute instead of innertext ([#1200](https://github.com/DataDog/browser-sdk/pull/1200))\n- 💥 [RUMF-1094] remove deprecated privacy attributes ([#1224](https://github.com/DataDog/browser-sdk/pull/1224))\n- 💥 [RUMF-1092] use a WeakMap to store XHR context ([#1222](https://github.com/DataDog/browser-sdk/pull/1222))\n- 💥 [RUMF-1090] update minimal version to 3.8.2 ([#1219](https://github.com/DataDog/browser-sdk/pull/1219))\n- 💥 [RUMF-827] sanitize tags ([#1218](https://github.com/DataDog/browser-sdk/pull/1218))\n- 💥 [RUMF-1089] Cleanup legacy intake URLs ([#1214](https://github.com/DataDog/browser-sdk/pull/1214))\n\n## v3.11.0\n\n- ✨ [ci-visibility] Link CI Visibility and RUM ([#1192](https://github.com/DataDog/browser-sdk/pull/1192))\n\n## v3.10.1\n\n- ♻️ [RUMF-1097] revamp configuration - rum ([#1221](https://github.com/DataDog/browser-sdk/pull/1221))\n- 🐛 [RUMF-1122] fix view updates while session is expired ([#1228](https://github.com/DataDog/browser-sdk/pull/1228))\n- 🐛 Fix proxy url intake detection ([#1223](https://github.com/DataDog/browser-sdk/pull/1223))\n- ♻️ [RUMF-1097] revamp configuration - logs ([#1217](https://github.com/DataDog/browser-sdk/pull/1217))\n\n## v3.10.0\n\n- ♻ [RUMF-1097] revamp internal configuration - core ([#1216](https://github.com/DataDog/browser-sdk/pull/1216))\n- ♻️ [RUMF-1083] rework session management API ([#1197](https://github.com/DataDog/browser-sdk/pull/1197))\n- ♻️ [RUMF-1083] introduce session context history ([#1187](https://github.com/DataDog/browser-sdk/pull/1187))\n- ♻️ [RUMF-1083] rework session cookie cache ([#1180](https://github.com/DataDog/browser-sdk/pull/1180))\n\n## v3.9.0\n\n- 🐛 remove readonly from all LogsEvent properties ([#1198](https://github.com/DataDog/browser-sdk/pull/1198))\n- ⚗✨ [RUMF-1085] implement the `synthetics.injected` field ([#1194](https://github.com/DataDog/browser-sdk/pull/1194))\n- ⚗✨ [RUMF-1047] implement a RUM synthetics entry point ([#1188](https://github.com/DataDog/browser-sdk/pull/1188))\n- ✨ [RUMF-1082] enable record-at-dom-loaded ([#1182](https://github.com/DataDog/browser-sdk/pull/1182))\n- 📝 improve site parameter doc ([#1189](https://github.com/DataDog/browser-sdk/pull/1189))\n- ⚗✨ [RUMF-1071] forward internal monitoring to bridge ([#1177](https://github.com/DataDog/browser-sdk/pull/1177))\n- ⚗✨ [RUMF-1070] forward logs event to bridge ([#1155](https://github.com/DataDog/browser-sdk/pull/1155))\n- ⚗ [RUMF-1068] Forward browser_sdk_version to mobile ([#1162](https://github.com/DataDog/browser-sdk/pull/1162))\n- 📝 add details about sampling configuration ([#1186](https://github.com/DataDog/browser-sdk/pull/1186))\n- ⚗✨ [RUMF-1084] ignore init if a RUM instance is or will be injected by synthetics ([#1170](https://github.com/DataDog/browser-sdk/pull/1170))\n\n## v3.8.0\n\n- ⚗ [RUMF-1082] start recording when the DOM is ready ([#1164](https://github.com/DataDog/browser-sdk/pull/1164))\n- 🐛 [RUMF-1077] use cookies to get Synthetics context ([#1161](https://github.com/DataDog/browser-sdk/pull/1161))\n- ✨ [RUMF-1074] bridge host checking ([#1157](https://github.com/DataDog/browser-sdk/pull/1157))\n- ⚗[REPLAY-341] Add VisualViewport tracking (Pinch Zoom) ([#1118](https://github.com/DataDog/browser-sdk/pull/1118))\n\n## v3.7.0\n\n- ✨ [RUMF-1067] forward rum event to bridge ([#1148](https://github.com/DataDog/browser-sdk/pull/1148))\n- 🐛 [RUMF-1062] fix support for Safari 11.0 ([#1154](https://github.com/DataDog/browser-sdk/pull/1154))\n- 📄 [RUMF-1075] add missing initialization parameters ([#1152](https://github.com/DataDog/browser-sdk/pull/1152))\n- 🐛 [Internal monitoring] use monitoring api key for monitoring requests ([#1147](https://github.com/DataDog/browser-sdk/pull/1147))\n\n## v3.6.13\n\n- 🐛 [RUMF-1060] fix failing worker detection in Firefox ([#1139](https://github.com/DataDog/browser-sdk/pull/1139))\n\n## v3.6.12\n\n- 🐛 Do not trace requests when the session is not tracked ([#1131](https://github.com/DataDog/browser-sdk/pull/1131))\n- 🔊 [RUMF-1041] add lcp info on view events ([#1129](https://github.com/DataDog/browser-sdk/pull/1129))\n- 🔇 [RUMF-1021] remove monitoring on cookie ([#1132](https://github.com/DataDog/browser-sdk/pull/1132))\n- 🐛 Discard views and actions with negative loading time ([#1122](https://github.com/DataDog/browser-sdk/pull/1122))\n\n## v3.6.11\n\n- ♻️ [RUMF-1046] instrument method implementation ([#1117](https://github.com/DataDog/browser-sdk/pull/1117))\n- 🔊 [RUMF-1021] improve cookie monitoring ([#1120](https://github.com/DataDog/browser-sdk/pull/1120))\n\n## v3.6.10\n\n- Revert \"⚗[REPLAY-341] Add VisualViewport tracking (Pinch Zoom) ([#1089](https://github.com/DataDog/browser-sdk/pull/1089))\" ([#1115](https://github.com/DataDog/browser-sdk/pull/1115))\n\n## v3.6.9\n\n- [RUMF-1045] rely on browser detection to check for innerText support ([#1110](https://github.com/DataDog/browser-sdk/pull/1110))\n- ⚗[REPLAY-341] Add VisualViewport tracking (Pinch Zoom) ([#1089](https://github.com/DataDog/browser-sdk/pull/1089))\n\n## v3.6.8\n\n- 🐛 [RUMF-1040] Remove long task for lite plan ([#1103](https://github.com/DataDog/browser-sdk/pull/1103))\n- ⚗ [REPLAY-465] Base tag support (feature flagged): Remove URL transformation from relative to absolute ([#1106](https://github.com/DataDog/browser-sdk/pull/1106))\n\n## v3.6.7\n\n- 🔊 [RUMF-1036] Add negative loading time internal monitoring ([#1095](https://github.com/DataDog/browser-sdk/pull/1095))\n\n## v3.6.6\n\n- 🐛 [RUMF-1021] fix regression on renew session ([#1096](https://github.com/DataDog/browser-sdk/pull/1096))\n\n## v3.6.5\n\n- 🐛 [RUMF-1033] request parameters into proxy url ([#1087](https://github.com/DataDog/browser-sdk/pull/1087))\n- [RUMF-1034] allow passing `undefined` options to RUM and Logs init ([#1082](https://github.com/DataDog/browser-sdk/pull/1082))\n- 🔊 [RUMF-1021] add extra monitoring on session type change ([#1091](https://github.com/DataDog/browser-sdk/pull/1091))\n\n## v3.6.4\n\n- ✨ [RUMF-1000] add a custom time parameter to `addTiming` ([#1079](https://github.com/DataDog/browser-sdk/pull/1079))\n- 🐛 [RUMF-1021] clear cookie cache before expanding cookie ([#1080](https://github.com/DataDog/browser-sdk/pull/1080))\n\n## v3.6.3\n\n- [REPLAY-328][rumf-1035] gracefully handle recorder Worker initialisation crash ([#1068](https://github.com/DataDog/browser-sdk/pull/1068))\n- 🔊 Add monitoring on session type change ([#1075](https://github.com/DataDog/browser-sdk/pull/1075))\n\n## v3.6.2\n\n- 🔊 Add extra monitoring info on lite session with replay ([#1072](https://github.com/DataDog/browser-sdk/pull/1072))\n\n## v3.6.1\n\n- ⚡ [RUMF-1022] remove `__sn` property in nodes ([#1069](https://github.com/DataDog/browser-sdk/pull/1069))\n- ♻️ [RUMF-1015] use the url corresponding to the start of the event ([#1063](https://github.com/DataDog/browser-sdk/pull/1063))\n\n## v3.6.0\n\n- ✨ [RUMF-1028] enable privacy by default ([#1049](https://github.com/DataDog/browser-sdk/pull/1049))\n- ✨ [RUMF-1020] enable intake v2 ([#1048](https://github.com/DataDog/browser-sdk/pull/1048))\n\n## v3.5.0\n\n- ✨ Add rate limit on actions ([#1058](https://github.com/DataDog/browser-sdk/pull/1058))\n- ✨ Remove focus feature flag ([#1053](https://github.com/DataDog/browser-sdk/pull/1053))\n- ✨ [RUMF-1029] remove the limit on view.loading_time ([#1054](https://github.com/DataDog/browser-sdk/pull/1054))\n- ✨ Discard long FCP and LCP ([#1045](https://github.com/DataDog/browser-sdk/pull/1045))\n- 📝 Add proxyUrl option documentation ([#1050](https://github.com/DataDog/browser-sdk/pull/1050))\n- ⚡️Introducing new max for foreground periods ([#1032](https://github.com/DataDog/browser-sdk/pull/1032))\n\n## v3.4.1\n\n- 🔊 [RUMF-976] add info to monitor failing xhr fallback ([#1035](https://github.com/DataDog/browser-sdk/pull/1035))\n- 🐛 MutationObserver bug fix for privacy level ([#1038](https://github.com/DataDog/browser-sdk/pull/1038))\n\n## v3.4.0\n\n- ForegroundContext: Remove monitoring & ignore untrusted events ([#1029](https://github.com/DataDog/browser-sdk/pull/1029))\n- ✨ [RUMF-992] New CLS implementation ([#1026](https://github.com/DataDog/browser-sdk/pull/1026))\n\n## v3.3.1\n\n- 🐛 [RUMF-1005] Fix dd-request-id endpoint query param ([#1018](https://github.com/DataDog/browser-sdk/pull/1018))\n\n## v3.3.0\n\n- ✨ [RUMF-993] New proxy strategy ([#1016](https://github.com/DataDog/browser-sdk/pull/1016))\n- 🐛 [RUMF-1012] fix console.error loop on npm setup ([#1027](https://github.com/DataDog/browser-sdk/pull/1027))\n- 🐛 [REPLAY-371] Truncate long \"data:\" URIs ([#1021](https://github.com/DataDog/browser-sdk/pull/1021))\n\n## v3.2.0\n\n- ✨ [RUMF-994] support intake v2 ([#1013](https://github.com/DataDog/browser-sdk/pull/1013))\n- ✨ [RUMF-998] introduce the initialPrivacyLevel configuration option ([#1004](https://github.com/DataDog/browser-sdk/pull/1004))\n- 🐛 [RUMF-997] dont take a FullSnapshot on view creation during session renew ([#1011](https://github.com/DataDog/browser-sdk/pull/1011))\n- 🐛 prevent recording to start when session renewed before onload ([#1009](https://github.com/DataDog/browser-sdk/pull/1009))\n- ✨ [RUMF-996] set synthetics ids on RUM events ([#1007](https://github.com/DataDog/browser-sdk/pull/1007))\n\n## v3.1.3\n\n- ⚗✨[REPLAY-336] Privacy by Default ([#951](https://github.com/DataDog/browser-sdk/pull/951))\n- ⚗✨ [REPLAY-379] add replay stats on view (getter edition) ([#994](https://github.com/DataDog/browser-sdk/pull/994))\n- 📝 Update Readme for v3 cdn links ([#999](https://github.com/DataDog/browser-sdk/pull/999))\n- 🐛[RUMF-990] restore global check to detect synthetics sessions ([#997](https://github.com/DataDog/browser-sdk/pull/997))\n\n## v3.1.2\n\n- ✨[RUMF-970] enable buffered PerformanceObserver ([#995](https://github.com/DataDog/browser-sdk/pull/995))\n- Limit log monitoring + add more details ([#990](https://github.com/DataDog/browser-sdk/pull/990))\n- 🗑️ Remove deprecated trace endpoint ([#992](https://github.com/DataDog/browser-sdk/pull/992))\n\n## v3.1.1\n\n- ⚗ [RUMF-970] Buffered PerformanceObserver: add fallback for older browsers ([#978](https://github.com/DataDog/browser-sdk/pull/978))\n- ⚗ [RUMF-971] experiment to detect when the computer goes to sleep ([#976](https://github.com/DataDog/browser-sdk/pull/976))\n- 🔊 [RUMF-971] add some context on suspicious LCP and FCP monitoring ([#979](https://github.com/DataDog/browser-sdk/pull/979))\n\n## v3.1.0\n\nNote: this is the first 3.x release for the Logs SDK. See migration notes in [v3.0.0](#v300).\n\n- 📝🗑 deprecate the XHR context, to be removed in V4 ([#973](https://github.com/DataDog/browser-sdk/pull/973))\n- ⚗ [RUMF-970] experiment with buffered PerformanceObserver ([#972](https://github.com/DataDog/browser-sdk/pull/972))\n- 📝 [RUMF-984] update CHANGELOG for logs breaking changes ([#971](https://github.com/DataDog/browser-sdk/pull/971))\n- ✨ [RUMF-974] use user-agent to detect synthetics sessions ([#969](https://github.com/DataDog/browser-sdk/pull/969))\n- 💥 [RUMF-982] remove deprecated LogsUserConfiguration type ([#968](https://github.com/DataDog/browser-sdk/pull/968))\n- 💥 [RUMF-981] remove deprecated logs options ([#967](https://github.com/DataDog/browser-sdk/pull/967))\n- 📝 document `trackViewsManually` option ([#965](https://github.com/DataDog/browser-sdk/pull/965))\n\n## v3.0.2\n\n- [RUMF-972] Revert \"💥 always use alternative domains for RUM ([#944](https://github.com/DataDog/browser-sdk/pull/944))\" ([#963](https://github.com/DataDog/browser-sdk/pull/963))\n- 📝 update CDN URLs for V3 ([#962](https://github.com/DataDog/browser-sdk/pull/962))\n\n## v3.0.1\n\n- 🐛 fix recording session renewal ([#955](https://github.com/DataDog/browser-sdk/pull/955))\n\n## v3.0.0\n\nSee our [upgrade guide](https://docs.datadoghq.com/real_user_monitoring/guide/browser-sdk-upgrade/#from-v2-to-v3) for a comprehensive list of breaking changes introduced by this major version.\n\n### Changes\n\n- 💥 always use alternative domains for RUM ([#944](https://github.com/DataDog/browser-sdk/pull/944))\n- 💥 remove deprecated rum init options ([#940](https://github.com/DataDog/browser-sdk/pull/940))\n- 💥 remove deprecated types ([#942](https://github.com/DataDog/browser-sdk/pull/942))\n- 💥 [RUMF-951] merge rum-recorder into rum ([#941](https://github.com/DataDog/browser-sdk/pull/941))\n- 👷 [RUMF-937] create the rum-slim package ([#935](https://github.com/DataDog/browser-sdk/pull/935))\n- 💥 remove deprecated RUM.addUserAction ([#939](https://github.com/DataDog/browser-sdk/pull/939))\n- ✨ [RUMF-940] implement the replay sample rate option and remove resource sample rate option ([#931](https://github.com/DataDog/browser-sdk/pull/931))\n- 💥 Remove addError 'source' argument ([#936](https://github.com/DataDog/browser-sdk/pull/936))\n\n## v2.18.0\n\n- 👷 Versioned CDN files ([#932](https://github.com/DataDog/browser-sdk/pull/932))\n- 👷 Increase browser cache to 4 hours ([#933](https://github.com/DataDog/browser-sdk/pull/933))\n- 🐛 ensure that test cookie is correctly deleted after the test ([#927](https://github.com/DataDog/browser-sdk/pull/927))\n- 📝 add `actionNameAttribute` initialization parameter ([#923](https://github.com/DataDog/browser-sdk/pull/923))\n\n## v2.17.0\n\n- ✨ [RUMF-928] enable manual view tracking ([#924](https://github.com/DataDog/browser-sdk/pull/924))\n- ✨ [PROF-3535] expose init configuration via `getInitConfiguration()` API ([#897](https://github.com/DataDog/browser-sdk/pull/897))\n\n## v2.16.0\n\n- ✨ [RUMF-932] allow context edition in logs beforeSend ([#909](https://github.com/DataDog/browser-sdk/pull/909))\n- ✨ [RUMF-945] allow users to customize the attribute used to define the action name ([#919](https://github.com/DataDog/browser-sdk/pull/919))\n\n## v2.15.1\n\n- 🐛 fix new view segment starting with an IncrementalSnapshot ([#908](https://github.com/DataDog/browser-sdk/pull/908))\n- 🐛 [REPLAY-325] add verbose error details on XHR transport failure ([#902](https://github.com/DataDog/browser-sdk/pull/902))\n\n## v2.15.0\n\n- ✨ [RUMF-920] keep trace id on aborted requests ([#898](https://github.com/DataDog/browser-sdk/pull/898))\n- ✨ [RUMF-922] stack trace on handled calls ([#889](https://github.com/DataDog/browser-sdk/pull/889))\n\n## v2.14.0\n\n- 🐛 [RUMF-931] check if PerformanceEntry is defined before using it ([#891](https://github.com/DataDog/browser-sdk/pull/891))\n- ✨ [RUMF-921] differentiate handled and unhandled errors ([#886](https://github.com/DataDog/browser-sdk/pull/886))\n- 🐛 [RUMF-876] Improve proxy behavior for xhr reuse ([#865](https://github.com/DataDog/browser-sdk/pull/865))\n- ⚗ manual view mode: create new view on renew session ([#887](https://github.com/DataDog/browser-sdk/pull/887))\n\n## v2.13.0\n\n- ✨ [RUMF-909] add beforeSend context ([#883](https://github.com/DataDog/browser-sdk/pull/883))\n- ✨ [RUMF-909] allow event context edition in beforeSend ([#869](https://github.com/DataDog/browser-sdk/pull/869))\n- 🔊[RUMF-927] monitor timings with high values ([#884](https://github.com/DataDog/browser-sdk/pull/884))\n- ⚗ [RUMF-878] add trackViewsManually option (disabled) ([#867](https://github.com/DataDog/browser-sdk/pull/867))\n\n## v2.12.1\n\n- 🔊 monitor potential invalid date ([#880](https://github.com/DataDog/browser-sdk/pull/880))\n\n## v2.12.0\n\n- ⚡️ start mutation observer only when needed ([#858](https://github.com/DataDog/browser-sdk/pull/858))\n- 📦 bump ws from 7.4.2 to 7.4.6 ([#875](https://github.com/DataDog/browser-sdk/pull/875))\n- ✨ track foreground ([#854](https://github.com/DataDog/browser-sdk/pull/854))\n- ✨ add id on rum events ([#873](https://github.com/DataDog/browser-sdk/pull/873))\n\n## v2.11.1\n\n- 🐛 do not break the recorder when an URL fails to parse ([#871](https://github.com/DataDog/browser-sdk/pull/871))\n\n## v2.11.0\n\n- 🐛 [REPLAY-312] use unpatched MutationObserver object ([#866](https://github.com/DataDog/browser-sdk/pull/866))\n- 🐛 ignore full snapshots taken before \"load\" event ([#861](https://github.com/DataDog/browser-sdk/pull/861))\n- ⚗✨ [RUMF-878] add startView API ([#850](https://github.com/DataDog/browser-sdk/pull/850))\n- 🏷️ update events format ([#864](https://github.com/DataDog/browser-sdk/pull/864))\n- ✨ [RUMF-913] allow masking input values ([#860](https://github.com/DataDog/browser-sdk/pull/860))\n\n## v2.10.0\n\n- ✨[RUMF-889] enable system clock usages ([#845](https://github.com/DataDog/browser-sdk/pull/845))\n\n## v2.9.1\n\n- 🐛 [logs] Fix IE11 console.log issue ([#852](https://github.com/DataDog/browser-sdk/pull/852))\n\n## v2.9.0\n\n- ✨[RUMF-907] Use unaltered console functions when displaying console messages ([#847](https://github.com/DataDog/browser-sdk/pull/847))\n- ✨[RUMF-910] handle logs console and http simultaneously ([#844](https://github.com/DataDog/browser-sdk/pull/844))\n- ⚡️ [RUMF-902] enable new mutation observer ([#842](https://github.com/DataDog/browser-sdk/pull/842))\n- ✨[RUMF-908] attach current drift value to events ([#843](https://github.com/DataDog/browser-sdk/pull/843))\n- ✨ Clear previously set user context ([#840](https://github.com/DataDog/browser-sdk/pull/840))\n- 📝 add a warning in the RUM-recorder readme ([#838](https://github.com/DataDog/browser-sdk/pull/838))\n- 📝 Restructure tables in docs page for improved readability ([#835](https://github.com/DataDog/browser-sdk/pull/835))\n- 📦 [RUMF-905] update vulnerable dependencies ([#836](https://github.com/DataDog/browser-sdk/pull/836))\n- ⚡️ [RUMF-896] process mutations asynchronously ([#832](https://github.com/DataDog/browser-sdk/pull/832))\n\n## v2.8.1\n\n- 🐛 [RUMF-870] Max errors threshold should not take into account errors excluded by beforeSend ([#828](https://github.com/DataDog/browser-sdk/pull/828))\n- ✨ [RUMF-901] allow to run the 'performances' script with rum-recorder ([#818](https://github.com/DataDog/browser-sdk/pull/818))\n\n## v2.8.0\n\n- ⚗🐛 allow 1 ms error for matching request ([#824](https://github.com/DataDog/browser-sdk/pull/824))\n- ⚗🐛 [RUMF-889] apply correction only for positive drift ([#821](https://github.com/DataDog/browser-sdk/pull/821))\n- ⚗⚡️ [RUMF-902] implement a new mutation observer ([#810](https://github.com/DataDog/browser-sdk/pull/810))\n- 🐛 [RUMF-900] clear parent view context when view end ([#816](https://github.com/DataDog/browser-sdk/pull/816))\n- 🐛 [RUMF-900] prevent events to be sent from expired session ([#814](https://github.com/DataDog/browser-sdk/pull/814))\n- ⚗🐛 [RUMF-889] fix relative time rounding ([#817](https://github.com/DataDog/browser-sdk/pull/817))\n- ⚗ [RUMF-889] use preferred clock ([#809](https://github.com/DataDog/browser-sdk/pull/809))\n\n## v2.7.4\n\n- [RUMF-868] ignore paramaters stored in the hash ([#792](https://github.com/DataDog/browser-sdk/pull/792))\n- 🐛 fallback to xhr when sendBeacon throws ([#796](https://github.com/DataDog/browser-sdk/pull/796))\n\n## v2.7.3\n\n- 🐛 [RUMF-886] don't start recording when 'postpone_start_recording' is enabled ([#790](https://github.com/DataDog/browser-sdk/pull/790))\n- 🐛 [RUMF-882] Segments can be flushed because of the max_size limit even if the max_size isn't reached ([#787](https://github.com/DataDog/browser-sdk/pull/787))\n\n## v2.7.2\n\n- ✨ [RUMF-867] enable start/stop recording API ([#784](https://github.com/DataDog/browser-sdk/pull/784))\n- 🐛 fix developer extension popup ([#778](https://github.com/DataDog/browser-sdk/pull/778))\n\n## v2.7.1\n\n- ✨ [RUMF-863] Enable console error with stack traces ([#781](https://github.com/DataDog/browser-sdk/pull/781))\n- ⚗ [RUMF-869] Ensure the \"Focus\" records are emited in the same segment as the \"FullSnapshot\" ([#779](https://github.com/DataDog/browser-sdk/pull/779))\n\n## v2.7.0\n\n- ⚗ [RUMF-853] introduce a feature flag for aborted network errors ([#777](https://github.com/DataDog/browser-sdk/pull/777))\n- ⚗ [RUMF-853] don't emit error for requests aborted by the application ([#768](https://github.com/DataDog/browser-sdk/pull/768))\n- ⚗ [RUMF-867] implement stop recording ([#771](https://github.com/DataDog/browser-sdk/pull/771))\n- ⚗ [RUMF-857] round CLS to 4 decimals ([#773](https://github.com/DataDog/browser-sdk/pull/773))\n- 🐛 Revert negative FID monitoring and adjust to 0 ([#775](https://github.com/DataDog/browser-sdk/pull/775))\n- ⚗ [RUMF-866] adjust postpone start recording ([#769](https://github.com/DataDog/browser-sdk/pull/769))\n\n## v2.6.2\n\n- 🐛 [RUMF-862] fix export MediaInteractions enum ([#761](https://github.com/DataDog/browser-sdk/pull/761))\n- ⚗ [RUMF-863] rework console error calls containing error instances ([#762](https://github.com/DataDog/browser-sdk/pull/762))\n\n## v2.6.1\n\n- 🐛 [RUMF-855] discard negative first-input delays ([#758](https://github.com/DataDog/browser-sdk/pull/758))\n- ⚗ performance impact summary tool ([#755](https://github.com/DataDog/browser-sdk/pull/755))\n\n## v2.6.0\n\n- ⚗ [RUMF-858] add monotonic batch time ([#748](https://github.com/DataDog/browser-sdk/pull/748))\n- ✨ [RUM] Catch errors thrown by user callbacks ([#745](https://github.com/DataDog/browser-sdk/pull/745))\n- 📝 Doc: remove resourceSampleRate ([#747](https://github.com/DataDog/browser-sdk/pull/747))\n\n## v2.5.5\n\n- 🐛 [REPLAY-187] flush pending records before taking a fullsnapshot ([#742](https://github.com/DataDog/browser-sdk/pull/742))\n- ✨ [RUMF-854] Enable beforeSend to dismiss events ([#743](https://github.com/DataDog/browser-sdk/pull/743))\n- ✅ [RUMF-815] import RRWeb integration tests ([#738](https://github.com/DataDog/browser-sdk/pull/738))\n- ✨ [RUMF-847] Add onNewLocation to configuration ([#724](https://github.com/DataDog/browser-sdk/pull/724))\n\n## v2.5.4\n\n- 🔊 Add clock drift monitoring ([#736](https://github.com/DataDog/browser-sdk/pull/736))\n- ✨ Implement a developer extension ([#686](https://github.com/DataDog/browser-sdk/pull/686))\n\n## v2.5.3\n\n- ⚗ Remove mutation buffer global instance ([#728](https://github.com/DataDog/browser-sdk/pull/728))\n- ⚗ replay: set data-dd-privacy attribute on snapshot node if hidden ([#726](https://github.com/DataDog/browser-sdk/pull/726))\n- ⚗ replay: add dd-privacy attribute for obfuscation & ignoring input ([#715](https://github.com/DataDog/browser-sdk/pull/715))\n\n## v2.5.2\n\n- ⚗ [RUMF-843] monitor rrweb codebase ([#721](https://github.com/DataDog/browser-sdk/pull/721))\n- ⚡️ Remove unused parameters ([#723](https://github.com/DataDog/browser-sdk/pull/723))\n- ⚗ [RUMF-823] monitor deflate worker ([#722](https://github.com/DataDog/browser-sdk/pull/722))\n- 🐛 recorder: remove forEach polyfills ([#719](https://github.com/DataDog/browser-sdk/pull/719))\n\n## v2.5.1\n\n- ⚗ [RUMF-821] remove unused record types ([#717](https://github.com/DataDog/browser-sdk/pull/717))\n- ⚗🐛 [RUMF-834] fix loop direction ([#714](https://github.com/DataDog/browser-sdk/pull/714))\n- ⚗⚡️ [RUMF-841] remove session renew support in rum recorder ([#713](https://github.com/DataDog/browser-sdk/pull/713))\n- ⚗✨ [REPLAY-149] implement ViewEnd record ([#711](https://github.com/DataDog/browser-sdk/pull/711))\n\n## v2.5.0\n\n- ✨ Allow logs collection on file:// URL ([#709](https://github.com/DataDog/browser-sdk/pull/709))\n- 🐛[RUMF-836] sanitize unsupported characters in timing name ([#706](https://github.com/DataDog/browser-sdk/pull/706))\n- rum-recorder: import rrweb-snapshot code ([#700](https://github.com/DataDog/browser-sdk/pull/700))\n- [REPLAY-164] track Focus records ([#707](https://github.com/DataDog/browser-sdk/pull/707))\n\n## v2.4.0\n\n- ✨[RUMF-820] expose API to add custom timings to the current view ([#702](https://github.com/DataDog/browser-sdk/pull/702))\n- 👷[RUMF-324] Replace TSLint with ESLint ([#681](https://github.com/DataDog/browser-sdk/pull/681))\n- ♻️ Remove automatic snake case ([#699](https://github.com/DataDog/browser-sdk/pull/699))\n\n## v2.3.1\n\n- ✨ [RUMF-826] Allow classic intake only for us and eu ([#694](https://github.com/DataDog/browser-sdk/pull/694))\n- [recorder] set 'hasReplay' to undefined by defaultb ([#697](https://github.com/DataDog/browser-sdk/pull/697))\n- [RUMF-819] postpone start recording ([#688](https://github.com/DataDog/browser-sdk/pull/688))\n\n## v2.3.0\n\n- ✨[RUMF-802] add support for capacitor app stack traces ([#685](https://github.com/DataDog/browser-sdk/pull/685))\n- 🐛[RUMF-824] support Request instances in tracing ([#684](https://github.com/DataDog/browser-sdk/pull/684))\n- 🐛[RUMF-809] URL encode tags in intake requests ([#689](https://github.com/DataDog/browser-sdk/pull/689))\n- ⚗[RUMF-804] implement a minimal version of the recorder ([#670](https://github.com/DataDog/browser-sdk/pull/670))\n\n## v2.2.1\n\n- ⚗ Implement addTiming ([#668](https://github.com/DataDog/browser-sdk/pull/668))\n\n## v2.2.0\n\n- 🐛 [RUMF-810] force alternate intake for us3 ([#677](https://github.com/DataDog/browser-sdk/pull/677))\n- ✨ [RUMF-783] collect view.first_input_time ([#676](https://github.com/DataDog/browser-sdk/pull/676))\n- ⚗ Create a rum-core package ([#673](https://github.com/DataDog/browser-sdk/pull/673))\n- ⚗ [RUMF-803] import RRWeb ([#658](https://github.com/DataDog/browser-sdk/pull/658))\n- ⚗ [RUMF-801] create a new package for rum-recorder ([#657](https://github.com/DataDog/browser-sdk/pull/657))\n\n## v2.1.2\n\n- [RUMF-807] Broaden context types in APIs ([#663](https://github.com/DataDog/browser-sdk/pull/663))\n- [RUMF-807] Export types used in API ([#662](https://github.com/DataDog/browser-sdk/pull/662))\n\n## v2.1.1\n\n- 🐛 [CDN cache] remove stale-while-revalidate ([#665](https://github.com/DataDog/browser-sdk/pull/665))\n- ✨ [RUMF-794] Add isActive attribute to view events ([#648](https://github.com/DataDog/browser-sdk/pull/648))\n\n## v2.1.0\n\n- ✨ [RUMF-787] implement the User API ([#638](https://github.com/DataDog/browser-sdk/pull/638))\n- ✨ [RUMF-772] add beforeSend API ([#644](https://github.com/DataDog/browser-sdk/pull/644))\n\n## v2.0.3\n\n- 🐛 handle direct onerror calls with objects ([#659](https://github.com/DataDog/browser-sdk/pull/659))\n\n## v2.0.2\n\n- 🐛 sanitize error properties even when there is a valid stack ([#655](https://github.com/DataDog/browser-sdk/pull/655))\n\n## v2.0.1\n\n- 🐛 fix tracekit handling of exotic errors ([#651](https://github.com/DataDog/browser-sdk/pull/651))\n\n## v2.0.0\n\n- 💥 [RUMF-730] prefer object and type alias over enum in APIs ([#630](https://github.com/DataDog/browser-sdk/pull/630))\n- 💥 [RUMF-730] use v2 events format ([#627](https://github.com/DataDog/browser-sdk/pull/627))\n\n## v1.26.3\n\n- 🐛⚡️ [RUMF-793] tweak the cache-control header ([#642](https://github.com/DataDog/browser-sdk/pull/642))\n\n## v1.26.2\n\n- ✨ [RUMF-764] Use new intake domain for US ([#616](https://github.com/DataDog/browser-sdk/pull/616))\n- ✨ [RUMF-770] Disable tracing for cancelled requests ([#635](https://github.com/DataDog/browser-sdk/pull/635))\n\n## v1.26.1\n\n- 🐛 [RUMF-791] prevent IE11 performance entry error ([#633](https://github.com/DataDog/browser-sdk/pull/633))\n\n## v1.26.0\n\n- ✨ [RUMF-777] implement Cumulative Layout Shift ([#628](https://github.com/DataDog/browser-sdk/pull/628))\n- ✨ [RUMF-776] implement First Input Delay ([#626](https://github.com/DataDog/browser-sdk/pull/626))\n- ✨ [RUMF-775] implement Largest Contentful Paint ([#624](https://github.com/DataDog/browser-sdk/pull/624))\n- ✨ [RUMF-758] keep internal context in v1 format ([#625](https://github.com/DataDog/browser-sdk/pull/625))\n- ✨ [RUMF-780] implement track first hidden ([#621](https://github.com/DataDog/browser-sdk/pull/621))\n\n## v1.25.4\n\n- ✨ [RUMF-771] Add getLoggerGlobalContext and getRumGlobalContext ([#614](https://github.com/DataDog/browser-sdk/pull/614))\n- ✨ [RUMF-762] include the context when using console handler ([#613](https://github.com/DataDog/browser-sdk/pull/613))\n- Revert \"⚗️[RUMF-766] add match request timing debug infos (experimental) ([#609](https://github.com/DataDog/browser-sdk/pull/609))\" ([#612](https://github.com/DataDog/browser-sdk/pull/612))\n\n## v1.25.3\n\n- ⚗️[RUMF-766] add match request timing debug infos (experimental) ([#609](https://github.com/DataDog/browser-sdk/pull/609))\n\n## v1.25.2\n\n- [RUMF-766] prevent request duration override by wrong matching timing ([#604](https://github.com/DataDog/browser-sdk/pull/604))\n- ♻️ [RUMF-748] cleanup add user add action events ([#602](https://github.com/DataDog/browser-sdk/pull/602))\n- 🐛 Fix unit test format validation ([#598](https://github.com/DataDog/browser-sdk/pull/598))\n- [RUMF-748] use RAW_RUM_EVENT_COLLECTED to compute event counts ([#596](https://github.com/DataDog/browser-sdk/pull/596))\n- [RUMF-729] validate rum events in e2e ([#597](https://github.com/DataDog/browser-sdk/pull/597))\n\n## v1.25.1\n\n- [RUMF-756] cyclic reference support in Context ([#595](https://github.com/DataDog/browser-sdk/pull/595))\n- ✨[RUMF-518] migrate internal context to v2 format (experimental) ([#593](https://github.com/DataDog/browser-sdk/pull/593))\n- ✨[RUMF-740] migrate error to v2 format (experimental) ([#592](https://github.com/DataDog/browser-sdk/pull/592))\n- [logs] add choose the right installation method ([#594](https://github.com/DataDog/browser-sdk/pull/594))\n\n## v1.25.0\n\n- ✨ [RUMF-724] implement API to capture an error ([#585](https://github.com/DataDog/browser-sdk/pull/585))\n- ✨ [RUMF-739] migrate action to v2 format (experimental) ([#588](https://github.com/DataDog/browser-sdk/pull/588))\n- ✨ [RUMF-738] migrate view to v2 format (experimental) ([#586](https://github.com/DataDog/browser-sdk/pull/586))\n- ✨ [RUMF-737] migrate resource to v2 format (experimental) ([#584](https://github.com/DataDog/browser-sdk/pull/584))\n- 🐛 [RUMF-745] fix V2 context ([#579](https://github.com/DataDog/browser-sdk/pull/579))\n- 📝 Added async installation method ([#571](https://github.com/DataDog/browser-sdk/pull/571))\n- 📝 DOCS-1257 Browser Log Collection ([#575](https://github.com/DataDog/browser-sdk/pull/575))\n\n## v1.24.1\n\n- 🐛 [RUMF-742] fix cookie creation domain when trackSessionAcrossSubdomains: true ([#573](https://github.com/DataDog/browser-sdk/pull/573))\n- ✨ [RUMF-727] introduce v2 format (experimental) ([#570](https://github.com/DataDog/browser-sdk/pull/570))\n\n## v1.24.0\n\n- 🐛 Use the same options to test and set cookies ([#555](https://github.com/DataDog/browser-sdk/pull/555))\n- ✨ [RUMF-534] implement logs.onReady and rum.onReady ([#564](https://github.com/DataDog/browser-sdk/pull/564))\n\n## v1.23.0\n\n- 🐛 [Core] dereference `combine` sources recursively ([#560](https://github.com/DataDog/browser-sdk/pull/560))\n- ✨ [RUMF-530][rum] allow using RUM API before init ([#551](https://github.com/DataDog/browser-sdk/pull/551))\n\n## v1.22.1\n\n- 🐛[RUMF-716] fix invalid action name ([#557](https://github.com/DataDog/browser-sdk/pull/557))\n- 🐛 consider proxy host with custom path request as intake request ([#550](https://github.com/DataDog/browser-sdk/pull/550))\n\n## v1.22.0\n\n- ✨ [RUMF-530][logs] allow using logs API before init ([#545](https://github.com/DataDog/browser-sdk/pull/545))\n\n## v1.21.1\n\n- ✨ [RUMF-709][core] support 'null' as a context value ([#546](https://github.com/DataDog/browser-sdk/pull/546))\n\n## v1.21.0\n\n- 🐛 [RUMF-620]: Dual-ship \"service\" as tag and attribute ([#543](https://github.com/DataDog/browser-sdk/pull/543))\n\n## v1.20.1\n\n- 🐛 [RUMF-699] allow collecting requests with the same origin as the proxy ([#537](https://github.com/DataDog/browser-sdk/pull/537))\n- 🐛 include sources in NPM backage ([#535](https://github.com/DataDog/browser-sdk/pull/535))\n\n## v1.20.0\n\n- 🐛 fix issue when using proxy ([#530](https://github.com/DataDog/browser-sdk/pull/530))\n- 🐛 [RUMF-650] exclude intake request from performance/request collection ([#528](https://github.com/DataDog/browser-sdk/pull/528))\n- ✨ [RUM] add new functionality to remove global context to SDK ([#527](https://github.com/DataDog/browser-sdk/pull/527))\n\n## v1.19.0\n\n- 🐛 [RUMF-670] wait for the DOM to be ready before getting the trace id ([#525](https://github.com/DataDog/browser-sdk/pull/525))\n- ✨ [RUMF-648] add cookie configuration options ([#523](https://github.com/DataDog/browser-sdk/pull/523))\n- 🐛 [RUMF-684] fix error collection when Logs and RUM configuration diverge ([#522](https://github.com/DataDog/browser-sdk/pull/522))\n\n## v1.18.1\n\n- ✨ [RUMF-634] add resource id for traced request ([#515](https://github.com/DataDog/browser-sdk/pull/515))\n- 🐛 [RUMF-617] fix missing headers on traced requests ([#517](https://github.com/DataDog/browser-sdk/pull/517))\n\n## v1.18.0\n\n- ✨ [RUMF-617] integrate tracing from rum ([#511](https://github.com/DataDog/browser-sdk/pull/511))\n\n## v1.17.0\n\n- 🐛 [RUMF-645] do not track intake request errors ([#506](https://github.com/DataDog/browser-sdk/pull/506))\n- ✨ [RUMF-621] set view referrer to the previous view URL ([#507](https://github.com/DataDog/browser-sdk/pull/507))\n\n## v1.16.0\n\n- ✨ [RUMF-636] initial document trace id ([#492](https://github.com/DataDog/browser-sdk/pull/492))\n- 🐛 [RUM] do not return internal context if the session is untracked ([#498](https://github.com/DataDog/browser-sdk/pull/498))\n\n## v1.15.3\n\n- 🐛 [RUM] fix loading measures conversion to nanoseconds ([#490](https://github.com/DataDog/browser-sdk/pull/490))\n\n## v1.15.2\n\n- 🐛 [RUMF-622] attach loading measures to initial view ([#479](https://github.com/DataDog/browser-sdk/pull/479))\n\n## v1.15.1\n\n- 🐛 [RUMF-639] xhr proxy: do not instrument xhr already opened ([#484](https://github.com/DataDog/browser-sdk/pull/484))\n\n## v1.15.0\n\n- ✨ [RUMF-626] use site configuration and deprecate suffixed bundle ([#476](https://github.com/DataDog/browser-sdk/pull/476))\n- ✨ Update context api to include removeContext method ([#478](https://github.com/DataDog/browser-sdk/pull/478))\n\n## v1.14.1\n\n- [RUMF-617] Extract XHR and Fetch proxies ([#468](https://github.com/DataDog/browser-sdk/pull/468))\n\n## v1.14.0\n\n- ✨ [RUMF-592] support for hash navigation ([#467](https://github.com/DataDog/browser-sdk/pull/467))\n\n## v1.13.1\n\n- 🐛 [RUMF-625] make sure view url doesn't change ([#469](https://github.com/DataDog/browser-sdk/pull/469))\n\n## v1.13.0\n\n- ✨ [RUMF-605] enable event association to parent context by start date ([#460](https://github.com/DataDog/browser-sdk/pull/460))\n\n## v1.12.10\n\n- ✨ [RUMF-605] associate event to parent context by start date (behind flag) ([#445](https://github.com/DataDog/browser-sdk/pull/445))\n\n## v1.12.9\n\n- 🐛 fix current action context reset on custom action ([#444](https://github.com/DataDog/browser-sdk/pull/444))\n- ♻️ [RUMF-604] introduce parentContexts to return current contexts ([#440](https://github.com/DataDog/browser-sdk/pull/440))\n\n## v1.12.8\n\n- ✨[RUMF-603] Introduce and use new lifecycle events ([#438](https://github.com/DataDog/browser-sdk/pull/438))\n\n## v1.12.7\n\n- ✨[RUMF-609] export Datacenter enum from logs and rum ([#436](https://github.com/DataDog/browser-sdk/pull/436))\n- 🐛 use Datacenter enum in setup doc ([#435](https://github.com/DataDog/browser-sdk/pull/435))\n\n## v1.12.6\n\n- ✨[RUMF-594] specify same site attribute on cookies ([#431](https://github.com/DataDog/browser-sdk/pull/431))\n- ✨[resources] resolve .ico resources as kind:image ([#428](https://github.com/DataDog/browser-sdk/pull/428))\n\n## v1.12.5\n\n- 🐛[RUMF-559] prevent event without sessionId ([#425](https://github.com/DataDog/browser-sdk/pull/425))\n\n## v1.12.4\n\n- ✨[RUMF-513] enable keep alive mechanism ([#421](https://github.com/DataDog/browser-sdk/pull/421))\n\n## v1.12.3\n\n- 👷[build] improve core tree-shaking ([#417](https://github.com/DataDog/browser-sdk/pull/417))\n- ⚡️[RUMF-510] Improve sizeInByte calculation performance ([#413](https://github.com/DataDog/browser-sdk/pull/413))\n- ✨[RUMF-513] add a session keep alive mechanism ([#394](https://github.com/DataDog/browser-sdk/pull/394))\n\n## v1.12.2\n\n- ✨ [RUMF-549] add an option to enable the user interaction tracking ([#414](https://github.com/DataDog/browser-sdk/pull/414))\n- ✨ [RUMF-385] implement a declarative API to set the action names ([#412](https://github.com/DataDog/browser-sdk/pull/412))\n- ✨ [RUMF-385] improve click action naming ([#406](https://github.com/DataDog/browser-sdk/pull/406))\n\n## v1.12.1\n\n- 👷 [RUM] add application id as query parameter ([#405](https://github.com/DataDog/browser-sdk/pull/405))\n\n## v1.12.0\n\n- 👷 Removing lodash dependencies ([#396](https://github.com/DataDog/browser-sdk/pull/396))\n\n## v1.11.6\n\n- ✨[RUMF-473] collect view loading time in ns and integrate the load event timing in the loading time calculation ([#401](https://github.com/DataDog/browser-sdk/pull/401))\n- ✨[RUMF-373] Add View load duration and load type ([#388](https://github.com/DataDog/browser-sdk/pull/388))\n\n## v1.11.5\n\n- ✨[RUMF-465] collect client service, env and version ([#392](https://github.com/DataDog/browser-sdk/pull/392))\n\n## v1.11.4\n\n- ♻️[RUMF-471] rename version ([#382](https://github.com/DataDog/browser-sdk/pull/382))\n\n## v1.11.3\n\n- [RUMF-447]: Only collect first-contentful-paint if page is visible ([#361](https://github.com/DataDog/browser-sdk/pull/361))\n\n## v1.11.2\n\n- 🐛[RUMF-451] compute session type for each event ([#375](https://github.com/DataDog/browser-sdk/pull/375))\n- 🐛 [RUM] fix angular compatibility ([#376](https://github.com/DataDog/browser-sdk/pull/376))\n\n## v1.11.1\n\n- 🐛 [RUM] fix view update after its end ([#373](https://github.com/DataDog/browser-sdk/pull/373))\n\n## v1.11.0\n\n- Change view logic to emit LifeCycle events ([#366](https://github.com/DataDog/browser-sdk/pull/366))\n- [RUMF-441] Track event counts for user actions ([#358](https://github.com/DataDog/browser-sdk/pull/358))\n\n## v1.10.0\n\n- ✨[RUMF-430] enable new session strategy ([#360](https://github.com/DataDog/browser-sdk/pull/360))\n- 🐛[RUMF-383] fix custom user action type case ([#356](https://github.com/DataDog/browser-sdk/pull/356))\n\n## v1.9.4\n\n- ✨[RUMF-43] add proxyHost init option ([#354](https://github.com/DataDog/browser-sdk/pull/354))\n- ✨ [RUMF-438] add user action reference to the internal context ([#352](https://github.com/DataDog/browser-sdk/pull/352))\n\n## v1.9.3\n\n- ✨[RUMF-435] add session type on all events ([#347](https://github.com/DataDog/browser-sdk/pull/347))\n- 🐛[RUMF-431] fix CSP issue with global object strategy ([#345](https://github.com/DataDog/browser-sdk/pull/345))\n\n## v1.9.2\n\n- ✨[RUMF-430] new session strategy (disabled) ([#343](https://github.com/DataDog/browser-sdk/pull/343))\n- ✨[RUMF-383] automatic click user action collection (disabled) ([#338](https://github.com/DataDog/browser-sdk/pull/338))\n\n## v1.9.1\n\n- 🔥[RUMF-430] stop maintaining old cookies ([#342](https://github.com/DataDog/browser-sdk/pull/342))\n\n## v1.9.0\n\n- ✨[RUMF-430] new session cookie format ([#337](https://github.com/DataDog/browser-sdk/pull/337))\n\n## v1.8.3\n\n- 🐛 [RUMF-430] fix rollback ([#334](https://github.com/DataDog/browser-sdk/pull/334))\n\n## v1.8.2\n\n- 🥅[RUMF-430] handle potential session rollback ([#329](https://github.com/DataDog/browser-sdk/pull/329))\n\n## v1.8.1\n\n- 🐛fix feature check ([#320](https://github.com/DataDog/browser-sdk/pull/320))\n\n## v1.8.0\n\n- 🔊[RUMF-408] add new session check logs ([#318](https://github.com/DataDog/browser-sdk/pull/318))\n- [RUMF-407] improve resource timings collection ([#315](https://github.com/DataDog/browser-sdk/pull/315))\n- 🔧 improve CBT test names ([#314](https://github.com/DataDog/browser-sdk/pull/314))\n- [RUMF-382] prepare support for multiple feature flags ([#312](https://github.com/DataDog/browser-sdk/pull/312))\n- 🔧 update cbt chrome mobile ([#313](https://github.com/DataDog/browser-sdk/pull/313))\n\n## v1.7.5\n\n- ✨add an option to silent multiple Init errors ([#310](https://github.com/DataDog/browser-sdk/pull/310))\n\n## v1.7.4\n\n- 🐛 replace console.error by console.warn when cookies are not supported ([#307](https://github.com/DataDog/browser-sdk/pull/307))\n- 🔒 upgrade vulnerable packages ([#306](https://github.com/DataDog/browser-sdk/pull/306))\n\n## v1.7.3\n\n- 🐛[RUMF-403] fix checkURLSupported ([#302](https://github.com/DataDog/browser-sdk/pull/302))\n- ✅ add cbt error case ([#299](https://github.com/DataDog/browser-sdk/pull/299))\n- [RUM] enable request with batch time by default ([#297](https://github.com/DataDog/browser-sdk/pull/297))\n\n## v1.7.2\n\n- 🐛[RUMF-396] try to fix view date shift ([#295](https://github.com/DataDog/browser-sdk/pull/295))\n\n## v1.7.1\n\n- 🐛[RUMF-320] Remove url-polyfill dependency ([#294](https://github.com/DataDog/browser-sdk/pull/294))\n\n## v1.7.0\n\n- ✨[RUMF-375] do not collect irrelevant timings ([#292](https://github.com/DataDog/browser-sdk/pull/292))\n\n## v1.6.3\n\n- 🐛[RUMF-266] xhr tracker: add fallback on event listener ([#287](https://github.com/DataDog/browser-sdk/pull/287))\n\n## v1.6.2\n\n- ⚗️[RUMF-371] add batch time to rum intake requests ([#285](https://github.com/DataDog/browser-sdk/pull/285))\n- 🐛[RUMF-266] fix xhr incorrect status reported on late abortion ([#283](https://github.com/DataDog/browser-sdk/pull/283))\n\n## v1.6.1\n\n- 🐛[RUMF-330] fix intake requests exclusion ([#281](https://github.com/DataDog/browser-sdk/pull/281))\n\n## v1.6.0\n\n- ✨[RUMF-315] collect initial document timing ([#276](https://github.com/DataDog/browser-sdk/pull/276))\n- ⬆️ Bump codecov from 3.6.1 to 3.6.5 ([#277](https://github.com/DataDog/browser-sdk/pull/277))\n- ✨[RUMF-342] use startTime for events timestamp ([#275](https://github.com/DataDog/browser-sdk/pull/275))\n\n## v1.5.0\n\n- ✨[RUMF-264] add compatibility with server side rendering ([#273](https://github.com/DataDog/browser-sdk/pull/273))\n\n## v1.4.2\n\n- 🔧 add repository link for each package ([#271](https://github.com/DataDog/browser-sdk/pull/271))\n\n## v1.4.1\n\n- 🐛 [RUM] fix retrieving early timings ([#268](https://github.com/DataDog/browser-sdk/pull/268))\n\n## v1.4.0\n\n- 🔇[RUMF-257] remove logging ([#265](https://github.com/DataDog/browser-sdk/pull/265))\n- 🐛 [RUMF-71] do not report negative performance timing duration ([#264](https://github.com/DataDog/browser-sdk/pull/264))\n- [MRO] update Node version ([#263](https://github.com/DataDog/browser-sdk/pull/263))\n- ✨ [Browser SDK][rum-291] Allow logs when cookies are disabled ([#255](https://github.com/DataDog/browser-sdk/pull/255))\n\n## v1.3.3\n\n- 🔊[RUMF-257] rework logging ([#261](https://github.com/DataDog/browser-sdk/pull/261))\n- 🐛[RUMF-308] do not track session without id ([#260](https://github.com/DataDog/browser-sdk/pull/260))\n- 📄 add check-licenses script ([#258](https://github.com/DataDog/browser-sdk/pull/258))\n\n## v1.3.2\n\n- 🔊 [RUMF-71] add internal logs messages when an abnormal duration is spoted ([#251](https://github.com/DataDog/browser-sdk/pull/251))\n\n## v1.3.1\n\n- 🔊[RUMF-257] report abnormal performance.now() ([#254](https://github.com/DataDog/browser-sdk/pull/254))\n- ✅[e2e] wait for browser url loaded ([#253](https://github.com/DataDog/browser-sdk/pull/253))\n- 🐛[RUMF-293][fetch] handle fetch response text error ([#252](https://github.com/DataDog/browser-sdk/pull/252))\n\n## v1.3.0\n\n- ✨[internal monitoring] add RUM/Logs context ([#249](https://github.com/DataDog/browser-sdk/pull/249))\n- 🔊 [RUM-257] add more abnormal info ([#248](https://github.com/DataDog/browser-sdk/pull/248))\n\n## v1.2.11\n\n- 🔊 [RUMF-257] add extra abnormal load info ([#245](https://github.com/DataDog/browser-sdk/pull/245))\n- 🔧 lower maxErrorsByMinute threshold ([#244](https://github.com/DataDog/browser-sdk/pull/244))\n\n## v1.2.10\n\n- 🐛[jsonStringify] do not crash on serialization error ([#242](https://github.com/DataDog/browser-sdk/pull/242))\n\n## v1.2.9\n\n- 🐛[init] remove deprecate prerender check ([#240](https://github.com/DataDog/browser-sdk/pull/240))\n\n## v1.2.8\n\n- 🏷 [TypeScript] ensure 3.0 minimal support ([#237](https://github.com/DataDog/browser-sdk/pull/237))\n\n## v1.2.7\n\n- ✅[e2e] cleaner tests ([#233](https://github.com/DataDog/browser-sdk/pull/233))\n- 🔧[coverage] setup codecov ([#232](https://github.com/DataDog/browser-sdk/pull/232))\n- 🔊[e2e] add extra logging ([#231](https://github.com/DataDog/browser-sdk/pull/231))\n- 🔥[rum/logs] remove outdated attributes ([#230](https://github.com/DataDog/browser-sdk/pull/230))\n- ♻️[e2e] wait request to reach server before assertions ([#229](https://github.com/DataDog/browser-sdk/pull/229))\n- ⚡️[batch] limit view update events ([#228](https://github.com/DataDog/browser-sdk/pull/228))\n- 🔊[e2e] output server response in logs ([#226](https://github.com/DataDog/browser-sdk/pull/226))\n- 🔧[e2e cbt] add retry case ([#227](https://github.com/DataDog/browser-sdk/pull/227))\n- 🔊[e2e] output test server log ([#225](https://github.com/DataDog/browser-sdk/pull/225))\n- 🔧[e2e] fix local tests on chrome 79 ([#224](https://github.com/DataDog/browser-sdk/pull/224))\n\n## v1.2.6\n\n- [RUMF-188] add traceId to fetch calls ([#221](https://github.com/DataDog/browser-sdk/pull/221))\n- 🐛 [RUMF-201] use timing.navigationStart to compute fake timings ([#217](https://github.com/DataDog/browser-sdk/pull/217))\n- ✅ fix e2e cbt tests on Edge ([#222](https://github.com/DataDog/browser-sdk/pull/222))\n\n## v1.2.5\n\n- 🔊🐛 [RUMF-201] add internal logs for abnormal timeOrigin ([#219](https://github.com/DataDog/browser-sdk/pull/219))\n- 🔧[e2e cbt] setup retry ([#218](https://github.com/DataDog/browser-sdk/pull/218))\n\n## v1.2.4\n\n- 🐛[types] do not globally override ts types ([#215](https://github.com/DataDog/browser-sdk/pull/215))\n- [RUMF-201] add debug monitoring for navigation timing entries ([#214](https://github.com/DataDog/browser-sdk/pull/214))\n\n## v1.2.3\n\n- [RUMF-158] fix view id associated to different session id ([#211](https://github.com/DataDog/browser-sdk/pull/211))\n- 🔧[packages] add scripts to release & publish ([#212](https://github.com/DataDog/browser-sdk/pull/212))\n- :pencil:[packages] improve README.md ([#209](https://github.com/DataDog/browser-sdk/pull/209))\n- 🔧[packages] force exact version ([#208](https://github.com/DataDog/browser-sdk/pull/208))\n- 🚀[ci] publish npm packages on tag ([#207](https://github.com/DataDog/browser-sdk/pull/207))\n- ✨[packages] allow to publish publicly ([#206](https://github.com/DataDog/browser-sdk/pull/206))\n\n## v1.2.2\n\n- 🔊🐛 [RUMF-201] add internal logs for buggy load event measures ([#204](https://github.com/DataDog/browser-sdk/pull/204))\n- ✨[packages] use new names ([#203](https://github.com/DataDog/browser-sdk/pull/203))\n- ⬆️[security] fix alert by upgrading webpack ([#202](https://github.com/DataDog/browser-sdk/pull/202))\n\n## v1.2.1\n\n- [e2e cbt] add android browser ([#200](https://github.com/DataDog/browser-sdk/pull/200))\n- 💚[gitlab] use new project name ([#199](https://github.com/DataDog/browser-sdk/pull/199))\n- 🐛[request] do not consider opaque response as error ([#197](https://github.com/DataDog/browser-sdk/pull/197))\n- ✅[e2e cbt] add edge and firefox ([#196](https://github.com/DataDog/browser-sdk/pull/196))\n\n## v1.2.0\n\n- ✅[e2e cbt] make scenarios compatible with safari ([#195](https://github.com/DataDog/browser-sdk/pull/195))\n- ✅[karma cbt] add retry for UnhandledException ([#194](https://github.com/DataDog/browser-sdk/pull/194))\n- 🐛[request] do not monitor xhr.send monkey patch ([#193](https://github.com/DataDog/browser-sdk/pull/193))\n- 🔥[RUM] remove deprecated count ([#192](https://github.com/DataDog/browser-sdk/pull/192))\n- ✨[init] add extra checks ([#191](https://github.com/DataDog/browser-sdk/pull/191))\n- 🐛[core] ensure that document.cookie is not null ([#190](https://github.com/DataDog/browser-sdk/pull/190))\n- ✨[RUM] add view resource count ([#189](https://github.com/DataDog/browser-sdk/pull/189))\n- ✨[RUM] do not snake case user defined contexts ([#188](https://github.com/DataDog/browser-sdk/pull/188))\n- :pencil:[Readme] Remove deployment part ([#187](https://github.com/DataDog/browser-sdk/pull/187))\n- Rename repository ([#186](https://github.com/DataDog/browser-sdk/pull/186))\n- ✨[RUM] exclude trace intake requests ([#185](https://github.com/DataDog/browser-sdk/pull/185))\n- 🐛[RUM] fix wrong url on spa last view event ([#184](https://github.com/DataDog/browser-sdk/pull/184))\n- 📄[license] update third parties ([#183](https://github.com/DataDog/browser-sdk/pull/183))\n- 🔧[ci] fix cbt fail on release ([#182](https://github.com/DataDog/browser-sdk/pull/182))\n\n## v1.1.0\n\n- 🔥[RUM] remove screen performance events ([#180](https://github.com/DataDog/browser-sdk/pull/180))\n- 🐛[release] get version from lerna.json ([#179](https://github.com/DataDog/browser-sdk/pull/179))\n\n## v1.0.0\n"
  },
  {
    "path": "CLAUDE.md",
    "content": "# Datadog Browser SDK\n\nSee @./AGENTS.md for detailed documentation on working with this codebase.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nFirst of all, thanks for contributing!\n\nThis document provides some basic guidelines for contributing to this repository. To propose\nimprovements, feel free to submit a pull request.\n\n## Submitting issues\n\nGithub issues are welcome, feel free to submit error reports and feature requests! Make sure to add\nenough details to explain your use case. If you require further assistance, you can also contact\nour [support][1].\n\n## Pull Requests\n\nHave you fixed a bug or written a new feature and want to share it? Many thanks!\n\nIn order to ease/speed up our review, here are some items you can check/improve when submitting your\npull request:\n\n- Follow this repository [Documentation][2]\n- Keep commits small and focused, rebase your branch if needed.\n- Write unit and e2e tests for the code you wrote.\n- Write meaningful [Commit messages and Pull Request titles][3]\n- Sign your commits, see [Github's documentation][4]\n- Sign the CLA\n\nOur CI is not (yet) public, so it may be difficult to understand why your pull request status is\nfailing. Make sure that all tests pass locally, and we'll try to sort it out in our CI.\n\n[1]: https://docs.datadoghq.com/help/\n[2]: https://github.com/DataDog/browser-sdk/blob/main/docs/README.md\n[3]: https://github.com/DataDog/browser-sdk/blob/main/docs/DEVELOPMENT.md#commit-messages-and-pull-request-titles\n[4]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM node:25.9.0-bookworm-slim\n\nARG CHROME_PACKAGE_VERSION\n\nSHELL [\"/bin/bash\", \"-c\"]\nRUN test -n \"$CHROME_PACKAGE_VERSION\" || (echo \"\\nCHROME_PACKAGE_VERSION not set, you need to run:\\ndocker build --build-arg CHROME_PACKAGE_VERSION=xxx\\n\" && false)\n\n# Install Chrome deps\nRUN apt-get update && apt-get install -y -q --no-install-recommends \\\n  libgcc-s1 \\\n  libgtk-3-dev \\\n  libx11-xcb1  \\\n  libnss3 \\\n  libxss1 \\\n  libasound2 \\\n  libu2f-udev \\\n  libvulkan1 \\\n  fonts-liberation \\\n  libappindicator3-1 \\\n  lsb-release \\\n  xdg-utils \\\n  curl \\\n  ca-certificates \\\n  wget \\\n  zip\n\n# Download and install Chrome\n# Debian taken from https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable\nRUN curl --silent --show-error --fail http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_PACKAGE_VERSION}_amd64.deb --output google-chrome.deb \\\n  && dpkg -i google-chrome.deb \\\n  && rm google-chrome.deb\n\n\n# Install AWS cli\n# https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html\nRUN set -x \\\n  && apt-get install -y -q --no-install-recommends unzip \\\n  && cd /tmp \\\n  && curl \"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip\" -o \"awscliv2.zip\" \\\n  && unzip awscliv2.zip \\\n  && ./aws/install\n\n# Node fsevents deps\nRUN apt-get install -y -q --no-install-recommends g++ build-essential\n\n# Datadog CI cli\nRUN yarn global add @datadog/datadog-ci\n\n# Gihub cli\nRUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg -o /usr/share/keyrings/githubcli-archive-keyring.gpg \\\n  && echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main\" > /etc/apt/sources.list.d/github-cli.list \\\n  && apt-get update && apt-get install -y -q gh\n\n# DD Octo STS to get security token\nCOPY --from=registry.ddbuild.io/dd-octo-sts:v1.8.1@sha256:eb2895829cdcb1f41cc4fc9d1f3f329c7d8f6fa72b0e8bb915d8195717e02bfa /usr/local/bin/dd-octo-sts /usr/local/bin/dd-octo-sts\n\nRUN apt-get update && apt-get install -y jq\n\n# Webdriverio deps\nRUN mkdir -p /usr/share/man/man1\n\nRUN apt-get install -y -q --no-install-recommends default-jdk\n\nRUN apt-get -y install git\n\nRUN apt-get -y install procps\n\n# Woke\nRUN set -o pipefail \\\n  && curl -sSfL https://git.io/getwoke | bash -s -- -b /usr/local/bin v0.17.1\n\n# Install authanywhere for pull request commenter token\nRUN if [ $(uname -m) = x86_64 ]; then AAA=\"amd64\"; else AAA=\"arm64\"; fi; curl -OL \"binaries.ddbuild.io/dd-source/authanywhere/LATEST/authanywhere-linux-${AAA}\" && mv \"authanywhere-linux-${AAA}\" /bin/authanywhere && chmod +x /bin/authanywhere\n"
  },
  {
    "path": "LEGAL",
    "content": "# Legal\n\nYou must sign [our CLA](https://gist.github.com/bits-bot/55bdc97a4fdad52d97feb4d6c3d1d618) before we can accept your contributions. The first time you submit a PR, a bot will walk you through the automated process. On subsequent contributions you will not be prompted unless the content of the agreement has changed.\n\nWe sincerely appreciate your contribution and have worked hard to ensure the CLA wording is simple, clear, and concise. It does not require you to give up ownership of your contributions, or prevent you from using your contributions for other purposes. We've put the agreement in place to explicitly clarify your intellectual property license grant, for your protection as well as ours.\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "LICENSE-3rdparty.csv",
    "content": "Component,Origin,License,Copyright\nfile,pako,MIT,(C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\nfile,rrweb,MIT,Copyright (c) 2018 Contributors (https://github.com/rrweb-io/rrweb/graphs/contributors) and SmartX Inc.\nfile,rrweb-snapshot,MIT,Copyright (c) 2018 Contributors (https://github.com/rrweb-io/rrweb-snapshot/graphs/contributors) and SmartX Inc.\nfile,tracekit,MIT,Copyright 2013 Onur Can Cakmak and all TraceKit contributors\nfile,web-vitals,Apache-2.0,Copyright 2020 Google LLC\nprod,@mantine/core,MIT,Copyright (c) 2021 Vitaly Rtishchev\nprod,@mantine/hooks,MIT,Copyright (c) 2021 Vitaly Rtishchev\nprod,@tabler/icons-react,MIT,Copyright (c) 2020-2023 Paweł Kuna\nprod,clsx,MIT,Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\nprod,react,MIT,Copyright (c) Facebook, Inc. and its affiliates.\nprod,react-dom,MIT,Copyright (c) Facebook, Inc. and its affiliates.\ndev,typedoc,Apache-2.0,TypeStrong\ndev,@angular/common,MIT,Copyright (c) 2010-2024 Google LLC\ndev,@angular/compiler,MIT,Copyright (c) 2010-2024 Google LLC\ndev,@angular/compiler-cli,MIT,Copyright (c) 2010-2024 Google LLC\ndev,@angular/core,MIT,Copyright (c) 2010-2024 Google LLC\ndev,@angular/platform-browser,MIT,Copyright (c) 2010-2024 Google LLC\ndev,@angular/router,MIT,Copyright (c) 2010-2024 Google LLC\ndev,@eslint/js,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>\ndev,@jsdevtools/coverage-istanbul-loader,MIT,Copyright (c) 2015 James Messinger\ndev,@ngtools/webpack,MIT,Copyright (c) 2017 Google LLC\ndev,@playwright/test,Apache-2.0,Copyright Microsoft Corporation\ndev,@swc/core,Apache-2.0,Copyright (c) SWC Contributors\ndev,@tanstack/react-router,MIT,Copyright (c) 2021-present Tanner Linsley\ndev,@types/chrome,MIT,Copyright Microsoft Corporation\ndev,@types/busboy,MIT,Copyright Microsoft Corporation\ndev,@types/cors,MIT,Copyright Microsoft Corporation\ndev,@types/express,MIT,Copyright Microsoft Corporation\ndev,@types/jasmine,MIT,Copyright Microsoft Corporation\ndev,@types/node,MIT,Copyright Microsoft Corporation\ndev,@types/node-forge,MIT,Copyright Microsoft Corporation\ndev,@types/pako,MIT,Copyright Microsoft Corporation\ndev,@types/react,MIT,Copyright Microsoft Corporation\ndev,@types/react-dom,MIT,Copyright Microsoft Corporation\ndev,@wxt-dev/module-react,MIT,Copyright (c) 2023 Aaron\ndev,@vitejs/plugin-react,MIT,Copyright (c) 2019-present Evan You & Vite Contributors\ndev,@vitejs/plugin-vue,MIT,Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors\ndev,@module-federation/enhanced,MIT, Copyright (c) 2020 ScriptedAlchemy LLC (Zack Jackson) Zhou Shaw (zhouxiao)\ndev,@vue/test-utils,MIT,Copyright (c) 2021-present vuejs\ndev,ajv,MIT,Copyright 2015-2017 Evgeny Poberezkin\ndev,babel-loader,MIT,Copyright (c) 2014-2019 Luís Couto <hello@luiscouto.pt>\ndev,browserstack-local,MIT,Copyright 2016 BrowserStack\ndev,chrome-webstore-upload,MIT,Copyright Federico Brigante <me@fregante.com> (https://fregante.com), 2020 Andrew Levine\ndev,busboy,MIT,Copyright Brian White\ndev,cors,MIT,Copyright 2013 Troy Goode\ndev,emoji-name-map,MIT,Copyright 2016-19 Ionică Bizău <bizauionica@gmail.com> (https://ionicabizau.net)\ndev,eslint,MIT,Copyright JS Foundation and other contributors\ndev,eslint-module-utils,MIT,Copyright (c) 2015 Ben Mosher\ndev,eslint-plugin-import,MIT,Copyright (c) 2015 Ben Mosher\ndev,eslint-import-resolver-typescript,ISC,Copyright 2021 Alex Gorbatchev <alex.gorbatchev@gmail.com>\ndev,eslint-plugin-jasmine,MIT,Copyright (c) 2021 Tom Vincent\ndev,eslint-plugin-jsdoc,BSD-3-Clause,Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/)\ndev,eslint-plugin-unicorn,MIT,Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\ndev,express,MIT,Copyright 2009-2014 TJ Holowaychuk 2013-2014 Roman Shtylman 2014-2015 Douglas Christopher Wilson\ndev,globals,MIT,Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\ndev,html-webpack-plugin,MIT,Copyright JS Foundation and other contributors\ndev,http-server,MIT,Copyright http-party contributors\ndev,jasmine-core,MIT,Copyright 2008-2017 Pivotal Labs\ndev,json-schema-to-typescript,MIT,\ndev,karma,MIT,Copyright 2011-2019 Google Inc.\ndev,karma-browserstack-launcher,MIT,Copyright 2011-2013 Google, Inc.\ndev,karma-chrome-launcher,MIT,Copyright 2011-2013 Google Inc.\ndev,karma-coverage-istanbul-reporter,MIT,Copyright 2017 Matt Lewis\ndev,karma-jasmine,MIT,Copyright 2011-2013 Google Inc.\ndev,karma-junit-reporter,MIT,Copyright (C) 2011-2013 Google, Inc.\ndev,karma-sourcemap-loader,MIT,Copyright 2013 Sergey Todyshev\ndev,karma-spec-reporter,MIT,Copyright 2015 Michael Lex\ndev,karma-webpack,MIT,Copyright JS Foundation and other contributors\ndev,minimatch,ISC,Copyright (c) Isaac Z. Schlueter and Contributors\ndev,next,MIT,Copyright (c) 2025 Vercel, Inc.\ndev,node-forge,BSD,Copyright (c) 2010, Digital Bazaar, Inc.\ndev,pako,MIT,(C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\ndev,prettier,MIT,Copyright James Long and contributors\ndev,puppeteer,Apache-2.0,Copyright 2017 Google Inc.\ndev,react-is,MIT,Copyright (c) Meta Platforms, Inc. and affiliates\ndev,react-router,MIT,Copyright (c) React Training LLC 2015-2019 Copyright (c) Remix Software Inc. 2020-2021 Copyright (c) Shopify Inc. 2022-2023\ndev,react-router-dom,MIT,Copyright (c) React Training LLC 2015-2019 Copyright (c) Remix Software Inc. 2020-2021 Copyright (c) Shopify Inc. 2022-2023\ndev,react-window,MIT,Copyright (c) 2018 Brian Vaughn\ndev,recharts,MIT,Copyright (c) 2015-present recharts\ndev,rxjs,Apache-2.0,Copyright (c) 2015-2022 Google LLC Ben Lesh and contributors\ndev,swc-loader,MIT,Copyright (c) SWC Contributors\ndev,terser-webpack-plugin,MIT,Copyright JS Foundation and other contributors\ndev,ts-loader,MIT,Copyright 2015 TypeStrong\ndev,tsconfig-paths-webpack-plugin,MIT,Copyright 2016 Jonas Kello\ndev,typescript,Apache-2.0,Copyright Microsoft Corporation\ndev,typescript-eslint,MIT,Copyright (c) 2019 typescript-eslint and other contributors\ndev,undici,MIT,Copyright (c) Matteo Collina and Undici contributors\ndev,vite,MIT,Copyright (c) 2019-present, VoidZero Inc. and Vite contributors\ndev,vue,MIT,Copyright (c) 2018-present, Yuxi (Evan) You\ndev,nuxt,MIT,Copyright (c) 2016-present Nuxt Team\ndev,vue-router,MIT,Copyright (c) 2019-present Eduardo San Martin Morote\ndev,webpack,MIT,Copyright JS Foundation and other contributors\ndev,webpack-cli,MIT,Copyright JS Foundation and other contributors\ndev,webpack-dev-middleware,MIT,Copyright JS Foundation and other contributors\ndev,wxt,MIT,Copyright (c) 2023 Aaron\ndev,zone.js,MIT,Copyright (c) 2010-2024 Google LLC\n"
  },
  {
    "path": "NOTICE",
    "content": "Datadog browser-sdk\nCopyright 2019-Present Datadog, Inc.\n\nThis product includes software developed at Datadog (https://www.datadoghq.com/).\n"
  },
  {
    "path": "README.md",
    "content": "# Datadog Browser SDK\n\nCollect and send browser data to Datadog.\n\n## Getting Started\n\n### Log collection\n\nSee the dedicated [Datadog Browser Log Collection documentation][08] to learn how to forward logs from your browser application to Datadog.\n\n### Real User Monitoring\n\nSee the dedicated [Datadog Browser RUM Collection documentation][18] to learn how to send RUM data from your browser application to Datadog.\n\n### API Reference\n\nFor detailed API information, see the [Datadog Browser SDK API Reference][71].\n\n## npm packages\n\nThis repository contains several packages:\n\n| Package          | npm                      | size                     |\n| ---------------- | ------------------------ | ------------------------ |\n| browser-logs     | [![npm version][01]][02] | [![bundle size][03]][04] |\n| browser-rum      | [![npm version][11]][12] | [![bundle size][13]][14] |\n| browser-rum-slim | [![npm version][21]][22] | [![bundle size][23]][24] |\n| browser-rum-core | [![npm version][51]][52] | [![bundle size][53]][54] |\n| browser-worker   | [![npm version][61]][62] | [![bundle size][63]][64] |\n| browser-core     | [![npm version][41]][42] | [![bundle size][43]][44] |\n\n## CDN bundles\n\nDatadog provides one CDN bundle per [site][70]:\n\n| Site    | logs                                                           | rum                                                           | rum-slim                                                           |\n| ------- | -------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------ |\n| US1     | https://www.datadoghq-browser-agent.com/us1/v6/datadog-logs.js | https://www.datadoghq-browser-agent.com/us1/v6/datadog-rum.js | https://www.datadoghq-browser-agent.com/us1/v6/datadog-rum-slim.js |\n| US3     | https://www.datadoghq-browser-agent.com/us3/v6/datadog-logs.js | https://www.datadoghq-browser-agent.com/us3/v6/datadog-rum.js | https://www.datadoghq-browser-agent.com/us3/v6/datadog-rum-slim.js |\n| US5     | https://www.datadoghq-browser-agent.com/us5/v6/datadog-logs.js | https://www.datadoghq-browser-agent.com/us5/v6/datadog-rum.js | https://www.datadoghq-browser-agent.com/us5/v6/datadog-rum-slim.js |\n| EU1     | https://www.datadoghq-browser-agent.com/eu1/v6/datadog-logs.js | https://www.datadoghq-browser-agent.com/eu1/v6/datadog-rum.js | https://www.datadoghq-browser-agent.com/eu1/v6/datadog-rum-slim.js |\n| AP1     | https://www.datadoghq-browser-agent.com/ap1/v6/datadog-logs.js | https://www.datadoghq-browser-agent.com/ap1/v6/datadog-rum.js | https://www.datadoghq-browser-agent.com/ap1/v6/datadog-rum-slim.js |\n| US1-FED | https://www.datadoghq-browser-agent.com/datadog-logs-v6.js     | https://www.datadoghq-browser-agent.com/datadog-rum-v6.js     | https://www.datadoghq-browser-agent.com/datadog-rum-slim-v6.js     |\n\n[1]: https://github.githubassets.com/favicons/favicon.png\n[2]: https://imgix.datadoghq.com/img/favicons/favicon-32x32.png\n[01]: https://badge.fury.io/js/%40datadog%2Fbrowser-logs.svg\n[02]: https://badge.fury.io/js/%40datadog%2Fbrowser-logs\n\n[03]: https://deno.bundlejs.com/badge?q=@datadog/browser-logs&treeshake=[*]\n[04]: https://bundlejs.com/?q=@datadog/browser-logs&treeshake=[*]\n[08]: https://docs.datadoghq.com/logs/log_collection/javascript\n[11]: https://badge.fury.io/js/%40datadog%2Fbrowser-rum.svg\n[12]: https://badge.fury.io/js/%40datadog%2Fbrowser-rum\n[13]: https://deno.bundlejs.com/badge?q=@datadog/browser-rum&treeshake=[*]\n[14]: https://bundlejs.com/?q=@datadog/browser-rum&treeshake=[*]\n[18]: https://docs.datadoghq.com/real_user_monitoring/browser/\n[21]: https://badge.fury.io/js/%40datadog%2Fbrowser-rum-slim.svg\n[22]: https://badge.fury.io/js/%40datadog%2Fbrowser-rum-slim\n[23]: https://deno.bundlejs.com/badge?q=@datadog/browser-rum-slim&treeshake=[*]\n[24]: https://bundlejs.com/?q=@datadog/browser-rum-slim&treeshake=[*]\n[41]: https://badge.fury.io/js/%40datadog%2Fbrowser-core.svg\n[42]: https://badge.fury.io/js/%40datadog%2Fbrowser-core\n[43]: https://deno.bundlejs.com/badge?q=@datadog/browser-core&treeshake=[*]\n[44]: https://bundlejs.com/?q=@datadog/browser-core&treeshake=[*]\n[51]: https://badge.fury.io/js/%40datadog%2Fbrowser-rum-core.svg\n[52]: https://badge.fury.io/js/%40datadog%2Fbrowser-rum-core\n[53]: https://deno.bundlejs.com/badge?q=@datadog/browser-rum-core&treeshake=[*]\n[54]: https://bundlejs.com/?q=@datadog/browser-rum-core&treeshake=[*]\n[61]: https://badge.fury.io/js/%40datadog%2Fbrowser-worker.svg\n[62]: https://badge.fury.io/js/%40datadog%2Fbrowser-worker\n[63]: https://deno.bundlejs.com/badge?q=@datadog/browser-worker&treeshake=[*]\n[64]: https://bundlejs.com/?q=@datadog/browser-worker&treeshake=[*]\n[70]: https://docs.datadoghq.com/getting_started/site/\n[71]: https://datadoghq.dev/browser-sdk/\n"
  },
  {
    "path": "developer-extension/README.md",
    "content": "# Browser SDK developer extension\n\nBrowser extension to investigate your Browser SDK integration.\n\n## Installation\n\nThe extension is available on the [Chrome Web Store](https://chrome.google.com/webstore/detail/datadog-browser-sdk-devel/boceobohkgenpcpogecpjlnmnfbdigda).\n\n## Features\n\n- Log events sent by the SDK in the devtools console\n- Flush buffered events\n- End current session\n- Load the SDK development bundles instead of production ones\n- Switch between `rum` and `rum-slim` bundles\n- Retrieve Logs/RUM configuration\n\n## Browser compatibility\n\nFor now, only Google Chrome is supported.\n\n## Usage tips\n\n### Event Tab\n\nThe Event Tab contains a list of events sent by the SDK and a menu of event types for quick filtering.\n\n#### Search syntax\n\nWe support a basic `key:value` search syntax, which means you can search within the limits of [RUM event structures](https://docs.datadoghq.com/real_user_monitoring/explorer/search/), such as `action.target.name:action_name`.\n\nWe split each search key based on whitespace. To search with multiple conditions, simply add whitespace characters in between, such as:\n\n```\ntype:view application.id:2 action.target.name:my_action_name\n```\n\n#### Event columns\n\nThe Events List offers an interactive experience to visualize RUM events:\n\n- Drag and drop to reorder columns in the event list\n- Remove (by clicking on `x` in the column title) or add new columns:\n  - Add a new column from searching for a field by clicking on the `+column` icon at the right side of the header row.\n  - Add a new column from values in existing columns by right clicking on any attribute in the event json.\n- Copy queries and objects from the list by clicking on any cell\n\n### Info Tab\n\n**⚠️Don’t forget to reset everything in the Info Tab after experimenting.**\n\nInfo tab contains information about Session and RUM SDK configurations\n\n- **RUM/LOGS Configuration**: edit configuration files on the fly. When configuration changes apply, the extension will automatically reload the page. But for some configurations you might want to click on End Current Session to ensure that the changes kicked in.\n- **End current session**: manually end the current session within the extension. This will also end the current replay session.\n\n### Setting Tab\n\n> [!IMPORTANT]\n> Don’t forget to reset everything in the Setting Tab after experimenting.\n\n- **Request Interception**: override the current SDK bundle with local build, or ​​switch between `rum` and `rum-slim` bundles on any site that is using RUM SDK. (note: if the SDK is installed from NPM, this override might not work, as it is still in an experimental stage.)\n\n- **Debug Mode**: This option enables debug mode from the developer extension to display errors happening in RUM and LOGS in the developer console.\n\n## Contribution\n\nTo get up to speed with WebExtensions for devtools, read the [Extend the developer tools](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools) MDN guide. Pay special attention to the various entrypoints (`panel.html`, `devtools.html`) and the content script communication, as it's not straightforward.\n\n### Development setup\n\nFrom the `developer-extension` folder, run `yarn build` then `yarn dev`.\n\nThere are two ways to work with the extension:\n\n#### Option A: Use the auto-launched browser (recommended)\n\nA Chrome window opens automatically with the extension loaded, DevTools open, and the [Browser SDK test playground](https://datadoghq.dev/browser-sdk-test-playground/) ready to use.\n\n#### Option B: Load the extension into your own Chrome profile\n\n1. In Chrome, navigate to [chrome://extensions](chrome://extensions) and enable _Developer Mode_.\n2. Click _Load unpacked_ and select the `dist/chrome-mv3/` folder.\n3. Open DevTools — the extension is available in the **Browser SDK** panel.\n\n> **Tip:** You can also load the `dist/chrome-mv3-dev/` folder for a development build with hot reload.\n\nAfter making a change, right-click the extension UI and select **Reload frame** to see your updates.\n"
  },
  {
    "path": "developer-extension/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-sdk-developer-extension\",\n  \"version\": \"6.32.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"wxt build\",\n    \"dev\": \"wxt\"\n  },\n  \"devDependencies\": {\n    \"@types/chrome\": \"0.1.40\",\n    \"@types/react\": \"19.2.14\",\n    \"@types/react-dom\": \"19.2.3\",\n    \"@wxt-dev/module-react\": \"1.2.2\",\n    \"typescript\": \"6.0.2\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"workspace:*\",\n    \"@datadog/browser-logs\": \"workspace:*\",\n    \"@datadog/browser-rum\": \"workspace:*\",\n    \"@datadog/browser-rum-core\": \"workspace:*\",\n    \"@mantine/core\": \"9.0.2\",\n    \"@mantine/hooks\": \"9.0.2\",\n    \"@tabler/icons-react\": \"3.41.1\",\n    \"clsx\": \"2.1.1\",\n    \"react\": \"19.2.5\",\n    \"react-dom\": \"19.2.5\",\n    \"wxt\": \"0.20.22\"\n  },\n  \"volta\": {\n    \"extends\": \"../package.json\"\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/background/devtoolsPanelConnection.ts",
    "content": "import type { DevtoolsToBackgroundMessage } from '../common/extension.types'\nimport { EventListeners } from '../common/eventListeners'\nimport { createLogger } from '../common/logger'\n\nconst logger = createLogger('devtoolsPanelConnection')\n\ntype TabId = number\n\nconst devtoolsConnectionsByTabId = new Map<TabId, chrome.runtime.Port>()\n\nconst portNameRe = /^devtools-panel-for-tab-(\\d+)$/\n\nexport const onDevtoolsFirstConnection = new EventListeners<TabId>()\nexport const onDevtoolsLastDisconnection = new EventListeners<TabId>()\nexport const onDevtoolsConnection = new EventListeners<TabId>()\nexport const onDevtoolsDisconnection = new EventListeners<TabId>()\nexport const onDevtoolsMessage = new EventListeners<DevtoolsToBackgroundMessage>()\n\nexport function sendMessageToDevtools(tabId: TabId, message: any) {\n  const port = devtoolsConnectionsByTabId.get(tabId)\n\n  if (!port) {\n    // Extension not yet opened\n    return\n  }\n\n  port.postMessage(message)\n}\n\n// Listen for connection from the devtools-panel\nchrome.runtime.onConnect.addListener((port) => {\n  const match = portNameRe.exec(port.name)\n  if (!match) {\n    return\n  }\n\n  const tabId = Number(match[1])\n\n  logger.log(`New devtools connection for tab ${tabId}`)\n  devtoolsConnectionsByTabId.set(tabId, port)\n\n  if (devtoolsConnectionsByTabId.size === 1) {\n    onDevtoolsFirstConnection.notify(tabId)\n  }\n  onDevtoolsConnection.notify(tabId)\n\n  port.onMessage.addListener((message) => {\n    onDevtoolsMessage.notify(message)\n  })\n\n  port.onDisconnect.addListener(() => {\n    logger.log(`Remove devtools connection for tab ${tabId}`)\n    devtoolsConnectionsByTabId.delete(tabId)\n\n    onDevtoolsDisconnection.notify(tabId)\n    if (devtoolsConnectionsByTabId.size === 0) {\n      onDevtoolsLastDisconnection.notify(tabId)\n    }\n  })\n})\n"
  },
  {
    "path": "developer-extension/src/background/domain/messageRelay.ts",
    "content": "// This file implements a way to relay messages from the web page to the devtools script. Basically,\n// the devtools panel cannot simply listen for messages on the inspected page. Instead, messages\n// from the web page are relayed through a list of scripts:\n//\n// 1. web-page calls a global callback defined by a \"main\" content script\n// 2. the \"main\" content script relays the message to an \"isolated\" content script via a custom\n//    event\n// 3. the \"isolated\" content script relays the message to the background script via the\n//    chrome.runtime.sendMessage API\n// 4. the background script relays the message to the devtools panel via a persistent connection\n//    (chrome.runtime.Port)\n//\n// Steps 2, 3 and 4 are a solution advised in the documentation provided by Google Chrome:\n// https://developer.chrome.com/docs/extensions/mv3/devtools/#content-script-to-devtools\n\nimport { createLogger } from '../../common/logger'\nimport {\n  onDevtoolsFirstConnection,\n  onDevtoolsLastDisconnection,\n  sendMessageToDevtools,\n} from '../devtoolsPanelConnection'\n\nconst logger = createLogger('messageRelay')\n\nconst CONTENT_SCRIPTS: Array<{\n  id: string\n  file: string\n  world: chrome.scripting.ExecutionWorld\n}> = [\n  {\n    id: 'browser-sdk-content-script-main',\n    world: chrome.scripting.ExecutionWorld.MAIN,\n    file: './contentScriptMain.js',\n  },\n  {\n    id: 'browser-sdk-content-script-isolated',\n    world: chrome.scripting.ExecutionWorld.ISOLATED,\n    file: './contentScriptIsolated.js',\n  },\n]\n\nonDevtoolsFirstConnection.subscribe((tabId) => {\n  // Register content scripts when a first devtools panel is open\n  registerContentScripts(tabId).catch((error) => logger.error('Error while registering content scripts:', error))\n})\n\nonDevtoolsLastDisconnection.subscribe(() => {\n  // Unregister content scripts when the last devtools panel is open\n  unregisterContentScripts().catch((error) => logger.error('Error while unregistering content scripts:', error))\n})\n\n// Listen for messages coming from the \"isolated\" content-script and relay them to a potential\n// devtools panel connection.\nchrome.runtime.onMessage.addListener((message, sender) => {\n  if (sender.tab && sender.tab.id) {\n    sendMessageToDevtools(sender.tab.id, { type: 'sdk-message', message })\n  }\n})\n\nasync function unregisterContentScripts() {\n  logger.log('Unregistering content scripts')\n  try {\n    await chrome.scripting.unregisterContentScripts({ ids: CONTENT_SCRIPTS.map((script) => script.id) })\n  } catch {\n    // This will throw an error when scripts are not registered. Just ignore it.\n  }\n}\n\nasync function registerContentScripts(tabId: number) {\n  // We always refresh the content scripts, just in case they changed.\n  await unregisterContentScripts()\n\n  logger.log('Registering content scripts')\n  await chrome.scripting.registerContentScripts(\n    CONTENT_SCRIPTS.map((script) => ({\n      id: script.id,\n      allFrames: true,\n      js: [script.file],\n      matches: ['<all_urls>'],\n      world: script.world,\n      runAt: 'document_start',\n    }))\n  )\n\n  // Execute scripts in the tab where the devtools panel was first open, so we don't need to refresh\n  // the page to see events flowing.\n  await Promise.all(\n    CONTENT_SCRIPTS.map((script) =>\n      chrome.scripting.executeScript({\n        files: [script.file],\n        world: script.world,\n        target: {\n          tabId,\n          allFrames: true,\n        },\n      })\n    )\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/background/domain/syncRules.ts",
    "content": "import type { NetRequestRulesOptions } from '../../common/extension.types'\nimport { DEV_RUM_SLIM_URL, DEV_RUM_URL, DEV_SERVER_ORIGIN } from '../../common/packagesUrlConstants'\nimport { INTAKE_DOMAINS } from '../../common/intakeDomainConstants'\nimport { createLogger } from '../../common/logger'\nimport { onDevtoolsDisconnection, onDevtoolsMessage } from '../devtoolsPanelConnection'\n\nconst logger = createLogger('syncRules')\n\nonDevtoolsDisconnection.subscribe((tabId) => {\n  clearRules(tabId).catch((error) => logger.error('Error while clearing rules:', error))\n})\n\nonDevtoolsMessage.subscribe((message) => {\n  if (message.type === 'update-net-request-rules') {\n    updateRules(message.options).catch((error) => logger.error('Error while updating rules:', error))\n  }\n})\n\nasync function clearRules(tabId: number) {\n  logger.log(`Clearing rules for tab ${tabId}`)\n  const { tabRuleIds } = await getExistingRulesInfos(tabId)\n  await chrome.declarativeNetRequest.updateSessionRules({\n    removeRuleIds: tabRuleIds,\n  })\n  await chrome.browsingData.removeCache({})\n}\n\nasync function updateRules(options: NetRequestRulesOptions) {\n  logger.log(`Updating rules for tab ${options.tabId}`)\n  const { tabRuleIds, nextRuleId } = await getExistingRulesInfos(options.tabId)\n  await chrome.declarativeNetRequest.updateSessionRules({\n    removeRuleIds: tabRuleIds,\n    addRules: buildRules(options, nextRuleId),\n  })\n  await chrome.browsingData.removeCache({})\n}\n\nasync function getExistingRulesInfos(tabId: number) {\n  const rules = await chrome.declarativeNetRequest.getSessionRules()\n\n  let nextRuleId = 1\n  const tabRuleIds: number[] = []\n  for (const rule of rules) {\n    if (rule.condition.tabIds?.includes(tabId)) {\n      tabRuleIds.push(rule.id)\n    } else {\n      nextRuleId = rule.id + 1\n    }\n  }\n\n  return { tabRuleIds, nextRuleId }\n}\n\nfunction buildRules(\n  { tabId, useDevBundles, useRumSlim, blockIntakeRequests }: NetRequestRulesOptions,\n  nextRuleId: number\n) {\n  const rules: chrome.declarativeNetRequest.Rule[] = []\n  let id = nextRuleId\n\n  if (useDevBundles === 'cdn') {\n    const devRumUrl = useRumSlim ? DEV_RUM_SLIM_URL : DEV_RUM_URL\n    logger.log('add redirect to dev bundles rules')\n    rules.push(\n      createRedirectRule(/^https:\\/\\/.*\\/datadog-(rum|rum-slim|logs)(-[\\w-]+)?\\.js$/, {\n        regexSubstitution: `${DEV_SERVER_ORIGIN}/datadog-\\\\1.js`,\n      }),\n      createRedirectRule(/^https:\\/\\/.*\\/chunks\\/(\\w+)(-\\w+)?-datadog-rum.js$/, {\n        regexSubstitution: `${DEV_SERVER_ORIGIN}/chunks/\\\\1-datadog-rum.js`,\n      }),\n      createRedirectRule('https://localhost:8443/static/datadog-rum-hotdog.js', { url: devRumUrl })\n    )\n  } else if (useRumSlim) {\n    logger.log('add redirect to rum slim rule')\n    rules.push(createRedirectRule(/^(https:\\/\\/.*\\/datadog-rum)(-slim)?/, { regexSubstitution: '\\\\1-slim' }))\n  }\n\n  if (blockIntakeRequests) {\n    logger.log('add block intake rules')\n    for (const intakeDomain of INTAKE_DOMAINS) {\n      rules.push({\n        id: id++,\n        condition: { tabIds: [tabId], urlFilter: `||${intakeDomain}` },\n        action: {\n          type: chrome.declarativeNetRequest.RuleActionType.BLOCK,\n        },\n      })\n    }\n  }\n\n  function createRedirectRule(\n    filter: RegExp | string,\n    redirect: chrome.declarativeNetRequest.Redirect\n  ): chrome.declarativeNetRequest.Rule {\n    const tabIds = [tabId]\n    return {\n      id: id++,\n      action: {\n        type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,\n        redirect,\n      },\n      condition:\n        typeof filter === 'string' ? { tabIds, urlFilter: `|${filter}|` } : { tabIds, regexFilter: filter.source },\n    }\n  }\n\n  return rules\n}\n"
  },
  {
    "path": "developer-extension/src/background/index.ts",
    "content": "// Initialize Datadog logs for service worker - must be first\nimport './monitoring'\n\nimport './domain/messageRelay'\nimport './domain/syncRules'\n"
  },
  {
    "path": "developer-extension/src/background/monitoring.ts",
    "content": "import { datadogLogs } from '@datadog/browser-logs'\nimport { BASE_MONITORING_CONFIG } from '../common/monitoringConfig'\n\n// Initialize Datadog logs for service worker\ndatadogLogs.init(BASE_MONITORING_CONFIG)\n\n// Add context to distinguish background logs from panel logs\ndatadogLogs.setGlobalContext({\n  context: 'background',\n})\n"
  },
  {
    "path": "developer-extension/src/common/eventListeners.ts",
    "content": "export class EventListeners<Event = void> {\n  private listeners = new Set<(event: Event) => void>()\n\n  subscribe(listener: (event: Event) => void) {\n    this.listeners.add(listener)\n    return {\n      unsubscribe: () => {\n        this.listeners.delete(listener)\n      },\n    }\n  }\n\n  notify(event: Event) {\n    this.listeners.forEach((listener) => listener(event))\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/common/extension.types.ts",
    "content": "import type { TelemetryEvent } from '../../../packages/core/src/domain/telemetry'\nimport type { LogsEvent } from '../../../packages/logs/src/logsEvent.types'\nimport type { RumEvent } from '../../../packages/rum-core/src/rumEvent.types'\nimport type { BrowserRecord, BrowserSegmentMetadata } from '../../../packages/rum/src/types'\n\nexport interface BackgroundToDevtoolsMessage {\n  type: 'sdk-message'\n  message: SdkMessage\n}\n\nexport interface DevtoolsToBackgroundMessage {\n  type: 'update-net-request-rules'\n  options: NetRequestRulesOptions\n}\n\nexport type DevBundlesOverride = false | 'cdn' | 'npm'\n\nexport interface NetRequestRulesOptions {\n  tabId: number\n  useDevBundles: DevBundlesOverride\n  useRumSlim: boolean\n  blockIntakeRequests: boolean\n}\n\nexport type SdkMessage =\n  | {\n      type: 'logs'\n      payload: LogsEvent\n    }\n  | {\n      type: 'rum'\n      payload: RumEvent\n    }\n  | {\n      type: 'telemetry'\n      payload: TelemetryEvent\n    }\n  | {\n      type: 'record'\n      payload: {\n        record: BrowserRecord\n        segment: BrowserSegmentMetadata\n      }\n    }\n\nexport type EventCollectionStrategy = 'sdk' | 'requests'\n\nexport interface Settings {\n  useDevBundles: DevBundlesOverride\n  useDevReplaySandbox: boolean\n  useRumSlim: boolean\n  blockIntakeRequests: boolean\n  autoFlush: boolean\n  preserveEvents: boolean\n  eventCollectionStrategy: EventCollectionStrategy\n  rumConfigurationOverride: object | null\n  logsConfigurationOverride: object | null\n  debugMode: boolean\n  datadogMode: boolean\n}\n"
  },
  {
    "path": "developer-extension/src/common/intakeDomainConstants.ts",
    "content": "export const INTAKE_DOMAINS = [\n  'iam-rum-intake.datadoghq.com',\n  'browser-intake-datad0g.com',\n  'browser-intake-datadoghq.com',\n  'browser-intake-datadoghq.eu',\n  'browser-intake-ddog-gov.com',\n  'browser-intake-us3-datadoghq.com',\n  'browser-intake-us5-datadoghq.com',\n  ...['com', 'eu'].flatMap((tld) => [\n    `public-trace-http-intake.logs.datadoghq.${tld}`,\n    `rum-http-intake.logs.datadoghq.${tld}`,\n    `browser-http-intake.logs.datadoghq.${tld}`,\n  ]),\n]\n"
  },
  {
    "path": "developer-extension/src/common/isDisconnectError.ts",
    "content": "export function isDisconnectError(error: unknown) {\n  return (\n    typeof error === 'object' && error && (error as { message?: string }).message === 'Extension context invalidated.'\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/common/logger.ts",
    "content": "const DEVELOPER_EXTENSION_PREFIX = 'Datadog Browser SDK extension:'\n\nexport function createLogger(module: string) {\n  return {\n    log(...args: any[]) {\n      // eslint-disable-next-line no-console\n      console.log(DEVELOPER_EXTENSION_PREFIX, `[${module}]`, ...args)\n    },\n    error(...args: any[]) {\n      // eslint-disable-next-line no-console\n      console.error(DEVELOPER_EXTENSION_PREFIX, `[${module}]`, ...args)\n    },\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/common/monitoringConfig.ts",
    "content": "import packageJson from '../../package.json'\n\n// Base monitoring configuration shared by both panel and background\nexport const BASE_MONITORING_CONFIG = {\n  clientToken: 'pub74fd472504982beb427b647893758040',\n  site: 'datadoghq.com' as const,\n  service: 'browser-sdk-developer-extension',\n  env: 'prod' as const,\n  version: packageJson.version,\n  sessionSampleRate: 100,\n  telemetrySampleRate: 100,\n  sessionPersistence: 'local-storage' as const,\n  forwardErrorsToLogs: true,\n  forwardConsoleLogs: 'all' as const,\n}\n\nexport const RUM_CONFIG = {\n  ...BASE_MONITORING_CONFIG,\n  applicationId: '235202fa-3da1-4aeb-abc4-d01b10ca1539',\n  sessionReplaySampleRate: 100,\n  trackUserInteractions: true,\n  trackViewsManually: true,\n  trackResources: true,\n  trackLongTasks: true,\n  defaultPrivacyLevel: 'mask' as const,\n}\n"
  },
  {
    "path": "developer-extension/src/common/packagesUrlConstants.ts",
    "content": "export const DEV_SERVER_ORIGIN = 'http://localhost:8080'\nexport const DEV_LOGS_URL = `${DEV_SERVER_ORIGIN}/datadog-logs.js`\nexport const DEV_RUM_SLIM_URL = `${DEV_SERVER_ORIGIN}/datadog-rum-slim.js`\nexport const DEV_RUM_URL = `${DEV_SERVER_ORIGIN}/datadog-rum.js`\n\n// To follow web-ui development, this version will need to be manually updated from time to time.\n// When doing that, be sure to update types and implement any protocol changes.\nexport const PROD_REPLAY_SANDBOX_VERSION = '0.138.0'\nexport const PROD_REPLAY_SANDBOX_ORIGIN = 'https://session-replay-datadoghq.com'\nexport const PROD_REPLAY_SANDBOX_URL = `${PROD_REPLAY_SANDBOX_ORIGIN}/${PROD_REPLAY_SANDBOX_VERSION}/index.html`\n\nexport const DEV_REPLAY_SANDBOX_ORIGIN = 'https://localhost:8443'\nexport const DEV_REPLAY_SANDBOX_URL = `${DEV_REPLAY_SANDBOX_ORIGIN}/static-apps/replay-sandbox/public/index.html`\n"
  },
  {
    "path": "developer-extension/src/common/panelTabConstants.ts",
    "content": "export const enum PanelTabs {\n  Events = 'events',\n  Infos = 'infos',\n  Settings = 'settings',\n  Replay = 'replay',\n}\n\nexport const DEFAULT_PANEL_TAB = PanelTabs.Events\n"
  },
  {
    "path": "developer-extension/src/common/sessionKeyConstant.ts",
    "content": "export const SESSION_STORAGE_SETTINGS_KEY = '__ddBrowserSdkExtensionSettings'\n"
  },
  {
    "path": "developer-extension/src/content-scripts/isolated.ts",
    "content": "// This content script is executed in the \"isolated\" execution world. Thus, it has not access to\n// the webpage global variables, but can use webextension APIs.\nimport { isDisconnectError } from '../common/isDisconnectError'\nimport { createLogger } from '../common/logger'\n\nexport function main() {\n  const logger = createLogger('content-script-isolated')\n\n  interface IsolatedWindow {\n    unregisterIsolatedScript?(): void\n  }\n\n  const isolatedWindow = window as IsolatedWindow\n\n  // Unregister any callback from a previously injected isolated content script\n  if (isolatedWindow.unregisterIsolatedScript) {\n    isolatedWindow.unregisterIsolatedScript()\n  }\n  // Register the new callback\n  window.addEventListener('__ddBrowserSdkMessage', browserSdkMessageListener)\n\n  isolatedWindow.unregisterIsolatedScript = () => {\n    window.removeEventListener('__ddBrowserSdkMessage', browserSdkMessageListener)\n  }\n\n  // Listen to events from the \"main\" content script and relays them to the background script via the\n  // webextension API.\n  function browserSdkMessageListener(event: unknown) {\n    const detail = (event as CustomEvent).detail\n\n    try {\n      chrome.runtime.sendMessage(detail).catch((error) => logger.error('Failed to send message:', error))\n    } catch (error) {\n      // Ignore errors when the background script is unloaded, as this is expected to happen sometimes and we\n      // don't want to spam the console in this case.\n      if (!isDisconnectError(error)) {\n        logger.error('Failed to send message:', error)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/content-scripts/main.ts",
    "content": "import type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport type { RumInitConfiguration } from '@datadog/browser-rum'\nimport type { Settings } from '../common/extension.types'\nimport { EventListeners } from '../common/eventListeners'\nimport { DEV_LOGS_URL, DEV_RUM_SLIM_URL, DEV_RUM_URL } from '../common/packagesUrlConstants'\nimport { SESSION_STORAGE_SETTINGS_KEY } from '../common/sessionKeyConstant'\n\nconst windowWithSdkGlobals = window as Window & {\n  DD_RUM?: SdkPublicApi\n  DD_LOGS?: SdkPublicApi\n  __ddBrowserSdkExtensionCallback?: (message: unknown) => void\n}\n\ninterface SdkPublicApi {\n  [key: string]: (...args: any[]) => unknown\n}\n\nexport function main() {\n  // Prevent multiple executions when the devetools are reconnecting\n  if (windowWithSdkGlobals.__ddBrowserSdkExtensionCallback) {\n    return\n  }\n\n  sendEventsToExtension()\n\n  const settings = getSettings()\n\n  if (\n    settings &&\n    // Avoid instrumenting SDK global variables if the SDKs are already loaded.\n    // This happens when the page is loaded and then the devtools are opened.\n    noBrowserSdkLoaded()\n  ) {\n    const ddRumGlobal = instrumentGlobal('DD_RUM')\n    const ddLogsGlobal = instrumentGlobal('DD_LOGS')\n\n    if (settings.debugMode) {\n      setDebug(ddRumGlobal)\n      setDebug(ddLogsGlobal)\n    }\n\n    if (settings.rumConfigurationOverride) {\n      overrideInitConfiguration(ddRumGlobal, settings.rumConfigurationOverride)\n    }\n\n    if (settings.logsConfigurationOverride) {\n      overrideInitConfiguration(ddLogsGlobal, settings.logsConfigurationOverride)\n    }\n\n    if (settings.useDevBundles === 'npm') {\n      injectDevBundle(settings.useRumSlim ? DEV_RUM_SLIM_URL : DEV_RUM_URL, ddRumGlobal)\n      injectDevBundle(DEV_LOGS_URL, ddLogsGlobal)\n    }\n  }\n}\n\nfunction sendEventsToExtension() {\n  // This script is executed in the \"main\" execution world, the same world as the webpage. Thus, it\n  // can define a global callback variable to listen to SDK events.\n  windowWithSdkGlobals.__ddBrowserSdkExtensionCallback = (message: unknown) => {\n    // Relays any message to the \"isolated\" content-script via a custom event.\n    window.dispatchEvent(\n      new CustomEvent('__ddBrowserSdkMessage', {\n        detail: message,\n      })\n    )\n  }\n}\n\nfunction getSettings() {\n  try {\n    // sessionStorage access throws in sandboxed iframes\n    const stringSettings = sessionStorage.getItem(SESSION_STORAGE_SETTINGS_KEY)\n    // JSON.parse throws if the stringSettings is not a valid JSON\n    return JSON.parse(stringSettings || 'null') as Settings | null\n  } catch (error) {\n    // eslint-disable-next-line no-console\n    console.error('Error getting settings', error)\n  }\n}\n\nfunction noBrowserSdkLoaded() {\n  return !windowWithSdkGlobals.DD_RUM && !windowWithSdkGlobals.DD_LOGS\n}\n\nfunction injectDevBundle(url: string, global: GlobalInstrumentation) {\n  loadSdkScriptFromURL(url)\n  const devInstance = global.get() as SdkPublicApi\n\n  if (devInstance) {\n    global.onSet((sdkInstance) => proxySdk(sdkInstance, devInstance))\n    global.returnValue(devInstance)\n  }\n}\n\nfunction setDebug(global: GlobalInstrumentation) {\n  global.onSet((sdkInstance) => {\n    // Ensure the sdkInstance has a '_setDebug' method, excluding async stubs.\n    if ('_setDebug' in sdkInstance) {\n      sdkInstance._setDebug(true)\n    }\n  })\n}\n\nfunction overrideInitConfiguration(\n  global: GlobalInstrumentation,\n  configurationOverride: Partial<RumInitConfiguration | LogsInitConfiguration>\n) {\n  global.onSet((sdkInstance) => {\n    // Ensure the sdkInstance has an 'init' method, excluding async stubs.\n    if ('init' in sdkInstance) {\n      const originalInit = sdkInstance.init\n      sdkInstance.init = (config: RumInitConfiguration | LogsInitConfiguration) => {\n        originalInit({\n          ...config,\n          ...restoreFunctions(config, configurationOverride),\n          allowedTrackingOrigins: [location.origin],\n        })\n      }\n    }\n  })\n}\n\ntype SDKInitConfiguration = RumInitConfiguration | LogsInitConfiguration\nfunction restoreFunctions(\n  original: SDKInitConfiguration,\n  override: Partial<SDKInitConfiguration>\n): Partial<SDKInitConfiguration> {\n  // Clone the override to avoid mutating the input\n  const result = (Array.isArray(override) ? [...override] : { ...override }) as Record<string, unknown>\n\n  // Add back any missing functions from original\n  for (const key in original) {\n    if (!Object.prototype.hasOwnProperty.call(original, key)) {\n      continue\n    }\n\n    const originalValue = original[key as keyof typeof original]\n    const resultValue = result[key]\n\n    // If it's a function and missing in result, restore it\n    if (typeof originalValue === 'function' && !(key in result)) {\n      result[key] = originalValue\n    }\n    // If both are objects, recurse to restore functions at deeper levels\n    else if (\n      key in result &&\n      originalValue &&\n      typeof originalValue === 'object' &&\n      !Array.isArray(originalValue) &&\n      resultValue &&\n      typeof resultValue === 'object' &&\n      !Array.isArray(resultValue)\n    ) {\n      result[key] = restoreFunctions(\n        originalValue as SDKInitConfiguration,\n        resultValue as Partial<SDKInitConfiguration>\n      )\n    }\n  }\n\n  return result as Partial<SDKInitConfiguration>\n}\n\nfunction loadSdkScriptFromURL(url: string) {\n  const xhr = new XMLHttpRequest()\n  try {\n    xhr.open('GET', url, false) // `false` makes the request synchronous\n    xhr.send()\n  } catch (error) {\n    // eslint-disable-next-line no-console\n    console.error(`[DD Browser SDK extension] Error while loading ${url}:`, error)\n    return\n  }\n  if (xhr.status === 200) {\n    let sdkCode = xhr.responseText\n\n    // Webpack expects the script to be loaded with a `<script src=\"...\">` tag to get its URL to\n    // know where to load the relative chunks. By loading it with an XHR and evaluating it in an\n    // inline script tag, Webpack does not know where to load the chunks from.\n    //\n    // Let's replace Webpack logic that breaks with our own logic to define the URL. It's not\n    // pretty, but loading the script this way isn't either, so...\n    //\n    // We'll probably have to revisit when using actual `import()` expressions instead of relying on\n    // Webpack runtime to load the chunks.\n    sdkCode = sdkCode.replace(\n      'if (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");',\n      `if (!scriptUrl) scriptUrl = ${JSON.stringify(url)};`\n    )\n\n    const script = document.createElement('script')\n    script.type = 'text/javascript'\n    script.text = sdkCode\n\n    document.documentElement.prepend(script)\n  }\n}\n\ntype GlobalInstrumentation = ReturnType<typeof instrumentGlobal>\nfunction instrumentGlobal(global: 'DD_RUM' | 'DD_LOGS') {\n  const eventListeners = new EventListeners<SdkPublicApi>()\n  let returnedInstance: SdkPublicApi | undefined\n  let lastInstance: SdkPublicApi | undefined\n  Object.defineProperty(window, global, {\n    set(sdkInstance: SdkPublicApi) {\n      eventListeners.notify(sdkInstance)\n      lastInstance = sdkInstance\n    },\n    get(): SdkPublicApi | undefined {\n      return returnedInstance ?? lastInstance\n    },\n  })\n\n  return {\n    get: () => windowWithSdkGlobals[global],\n    onSet: (callback: (sdkInstance: SdkPublicApi) => void) => {\n      eventListeners.subscribe(callback)\n    },\n    returnValue: (sdkInstance: SdkPublicApi) => {\n      returnedInstance = sdkInstance\n    },\n  }\n}\n\nfunction proxySdk(target: SdkPublicApi, root: SdkPublicApi) {\n  Object.assign(target, root)\n}\n"
  },
  {
    "path": "developer-extension/src/devtools/index.ts",
    "content": "chrome.devtools.panels.create('Browser SDK', 'icon.png', 'panel.html')\n"
  },
  {
    "path": "developer-extension/src/entrypoints/background.ts",
    "content": "import { defineBackground } from 'wxt/utils/define-background'\n\n// eslint-disable-next-line import/no-default-export\nexport default defineBackground(() => {\n  void import('../background')\n})\n"
  },
  {
    "path": "developer-extension/src/entrypoints/contentScriptIsolated.ts",
    "content": "import { defineContentScript } from 'wxt/utils/define-content-script'\nimport { main } from '../content-scripts/isolated'\n\n// eslint-disable-next-line import/no-default-export\nexport default defineContentScript({\n  matches: ['<all_urls>'],\n  world: 'ISOLATED',\n  main,\n})\n"
  },
  {
    "path": "developer-extension/src/entrypoints/contentScriptMain.ts",
    "content": "import { defineContentScript } from 'wxt/utils/define-content-script'\nimport { main } from '../content-scripts/main'\n\n// eslint-disable-next-line import/no-default-export\nexport default defineContentScript({\n  matches: ['<all_urls>'],\n  world: 'MAIN',\n  main,\n})\n"
  },
  {
    "path": "developer-extension/src/entrypoints/devtools.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <script type=\"module\" src=\"../devtools\"></script>\n  </head>\n  <body></body>\n</html>\n"
  },
  {
    "path": "developer-extension/src/entrypoints/panel.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"../panel\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "developer-extension/src/panel/backgroundScriptConnection.ts",
    "content": "import type { BackgroundToDevtoolsMessage, DevtoolsToBackgroundMessage } from '../common/extension.types'\nimport { isDisconnectError } from '../common/isDisconnectError'\nimport { createLogger } from '../common/logger'\nimport { EventListeners } from '../common/eventListeners'\n\nconst logger = createLogger('backgroundScriptConnection')\n\nexport const onBackgroundMessage = new EventListeners<BackgroundToDevtoolsMessage>()\nexport const onBackgroundDisconnection = new EventListeners<void>()\n\nlet backgroundScriptConnection: chrome.runtime.Port | undefined\n\n// Buffer messages while the background script is not connected\nconst backgroundScriptMessageBuffer: DevtoolsToBackgroundMessage[] = []\n\nexport function connectToBackgroundScript() {\n  try {\n    backgroundScriptConnection = chrome.runtime.connect({\n      name: `devtools-panel-for-tab-${chrome.devtools.inspectedWindow.tabId}`,\n    })\n\n    backgroundScriptConnection.onDisconnect.addListener(() => {\n      backgroundScriptConnection = undefined\n      // The background script can be disconnected for (at least) two main reasons:\n      // * the extension is updated and its context is invalidated\n      // * the background script has been idle for too long\n      //\n      // We want to try to automatically reconnect, and notify only if the extension context is\n      // invalidated (in which case, calling `chrome.runtime.connect` should throw an exception).\n      //\n      // Somehow, if we try to reconnect right after the extension is updated, the connection\n      // unexpectedly succeeds (does not throw or notify onDisconnect). It turns out that we need to\n      // wait a few milliseconds to have the expected behavior.\n      setTimeout(() => {\n        connectToBackgroundScript()\n      }, 100)\n    })\n\n    backgroundScriptConnection.onMessage.addListener((backgroundMessage) =>\n      onBackgroundMessage.notify(backgroundMessage)\n    )\n\n    for (const message of backgroundScriptMessageBuffer.splice(0)) {\n      backgroundScriptConnection.postMessage(message)\n    }\n  } catch (error) {\n    backgroundScriptConnection = undefined\n    if (isDisconnectError(error)) {\n      onBackgroundDisconnection.notify()\n    } else {\n      logger.error('While creating connection:', error)\n    }\n  }\n}\n\nexport function sendMessageToBackground(message: DevtoolsToBackgroundMessage) {\n  if (backgroundScriptConnection) {\n    backgroundScriptConnection.postMessage(message)\n  } else {\n    backgroundScriptMessageBuffer.push(message)\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/alert.tsx",
    "content": "import type { ReactNode } from 'react'\nimport React from 'react'\nimport { Alert as MantineAlert, Center, Group, MantineProvider, Space } from '@mantine/core'\n\nexport function Alert({\n  level,\n  title,\n  message,\n  button,\n}: {\n  level: 'warning' | 'error'\n  title?: string\n  message: string\n  button?: ReactNode\n}) {\n  const color = level === 'warning' ? ('orange' as const) : ('red' as const)\n  return (\n    <Center mt=\"xl\" className=\"dd-privacy-allow\">\n      <MantineAlert color={color} title={title}>\n        {message}\n        {button && (\n          <>\n            <Space h=\"sm\" />\n            <MantineProvider defaultColorScheme=\"auto\" theme={{ components: { Button: { defaultProps: { color } } } }}>\n              <Group justify=\"flex-end\">{button}</Group>\n            </MantineProvider>\n          </>\n        )}\n      </MantineAlert>\n    </Center>\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/app.tsx",
    "content": "import { Button, MantineProvider } from '@mantine/core'\nimport type { ReactNode } from 'react'\nimport React, { Suspense, useEffect, useState } from 'react'\nimport { isDisconnectError } from '../../common/isDisconnectError'\nimport { onBackgroundDisconnection, connectToBackgroundScript } from '../backgroundScriptConnection'\nimport { Alert } from './alert'\nimport { Panel } from './panel'\n\nexport function App() {\n  const [isDisconnected, setIsDisconnected] = useState(false)\n\n  useEffect(() => {\n    connectToBackgroundScript()\n\n    const subscription = onBackgroundDisconnection.subscribe(() => setIsDisconnected(true))\n    return () => subscription.unsubscribe()\n  }, [])\n\n  return (\n    <MantineProvider\n      defaultColorScheme=\"auto\"\n      theme={{\n        cursorType: 'pointer',\n        // This is the default for devtools on mac\n        // https://github.com/ChromeDevTools/devtools-frontend/blob/92b3004cf9190eeb98a721ecb8c3931b45609031/front_end/ui/legacy/inspectorCommon.css#L86\n        // TODO: adjust for other OS\n        fontFamily: '\".SFNSDisplay-Regular\", \"Helvetica Neue\", \"Lucida Grande\", sans-serif',\n        fontSizes: {\n          xs: '11px',\n\n          // Mantine uses the 'md' font size as a default, but some of its components is using 'sm'.\n          // We want all font size to default to the same size, so let's use the same value for 'sm'\n          // and 'md'.\n          sm: '12px',\n          md: '12px',\n\n          lg: '16px',\n          xl: '22px',\n        },\n        fontFamilyMonospace: 'menlo, monospace',\n      }}\n    >\n      <ErrorBoundary>\n        <Suspense fallback={<></>}>{isDisconnected ? <DisconnectAlert /> : <Panel />}</Suspense>\n      </ErrorBoundary>\n    </MantineProvider>\n  )\n}\n\nfunction DisconnectAlert() {\n  return (\n    <Alert\n      level=\"error\"\n      title=\"Extension disconnected!\"\n      message=\"The extension has been disconnected. This can happen after an update.\"\n      button={<ReloadButton />}\n    />\n  )\n}\n\nfunction ReloadButton() {\n  return <Button onClick={() => location.reload()}>Reload extension</Button>\n}\n\nclass ErrorBoundary extends React.Component<{ children: ReactNode }, { error?: unknown }> {\n  state = {}\n\n  static getDerivedStateFromError(error: unknown) {\n    return { error }\n  }\n\n  render() {\n    if ('error' in this.state) {\n      const error = this.state.error\n\n      if (isDisconnectError(error)) {\n        return <DisconnectAlert />\n      }\n\n      return (\n        <Alert\n          level=\"error\"\n          title=\"Extension crashed!\"\n          message={error instanceof Error ? String(error) : `Error: ${String(error)}`}\n          button={<ReloadButton />}\n        />\n      )\n    }\n\n    return this.props.children\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/columns.tsx",
    "content": "import { Grid, Space, Title } from '@mantine/core'\nimport React from 'react'\n\nexport function Columns({ children }: { children: React.ReactNode }) {\n  return (\n    <Grid mt=\"sm\" mx=\"sm\">\n      {children}\n    </Grid>\n  )\n}\n\nfunction Column({ children, title }: { children: React.ReactNode; title: string }) {\n  return (\n    <Grid.Col span={{ md: 4, sm: 12 }}>\n      <Title order={3}>{title}</Title>\n      <Space h=\"sm\" />\n      {children || '(empty)'}\n      <Space h=\"sm\" />\n    </Grid.Col>\n  )\n}\n\nColumns.Column = Column\n"
  },
  {
    "path": "developer-extension/src/panel/components/json.module.css",
    "content": ".root {\n  /* --text-fz is used by mantine as a default font size for all <Text> components */\n  --text-fz: 11px;\n\n  --indent: 18px;\n  --line-height: 20px;\n\n  line-height: var(--line-height);\n  word-break: break-word;\n  -webkit-font-smoothing: auto;\n  font-family: var(--mantine-font-family-monospace);\n\n  /*\n    Use the same font size as the Chromium devtools for monospace fonts.\n    https://github.com/ChromeDevTools/devtools-frontend/blob/92b3004cf9190eeb98a721ecb8c3931b45609031/front_end/ui/legacy/inspectorCommon.css#L121\n  */\n  font-size: 11px;\n}\n\n.valueChildren {\n  position: relative;\n  min-height: var(--line-height);\n}\n\n.valueChildrenIndent {\n  position: absolute;\n  z-index: var(--dd-json-z-index);\n  left: 0px;\n  width: var(--indent);\n\n  /* Leaves a small space between indent bars. */\n  top: 1px;\n  bottom: 1px;\n\n  line-height: var(--indent);\n  text-align: center;\n  border-radius: var(--mantine-radius-sm);\n  user-select: none;\n}\n\n.valueChildrenIndent[data-collapsible] {\n  cursor: pointer;\n}\n\n.valueChildrenCollapsedEllipsis {\n  cursor: pointer;\n}\n\n.jsonTextTarget {\n  cursor: pointer;\n}\n\n.jsonLine:not([data-top-level]) {\n  margin-left: calc(var(--indent) * var(--depth) + 4px);\n\n  /*\n    This indents wrapping lines.\n    https://stackoverflow.com/questions/480567/what-is-the-best-way-to-indent-text-in-a-div-when-it-wraps\n  */\n  padding-left: var(--indent);\n  text-indent: calc(-1 * var(--indent));\n}\n\n.jsonLine[data-floating] {\n  position: absolute;\n  z-index: var(--dd-json-z-index);\n}\n\n.functionSource {\n  border-radius: 4px;\n  white-space: pre-wrap;\n  word-break: break-all;\n  text-indent: 0;\n}\n\n.functionSourceToggle {\n  cursor: pointer;\n}\n\n.functionSourceToggle svg {\n  vertical-align: middle;\n  margin-right: 4px;\n}\n\n.functionSource > .functionSourceToggle {\n  margin-bottom: 8px;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/json.tsx",
    "content": "import type { BoxProps, MantineColor } from '@mantine/core'\nimport { Box, Collapse, Menu, Text } from '@mantine/core'\nimport { useColorScheme } from '@mantine/hooks'\nimport { IconCopy, IconSearch } from '@tabler/icons-react'\nimport type { ForwardedRef, ReactNode } from 'react'\nimport React, { forwardRef, useContext, createContext, useState } from 'react'\nimport { copy } from '../copy'\nimport { formatNumber } from '../formatNumber'\n\nimport * as classes from './json.module.css'\n\ninterface JsonProps {\n  value: unknown\n  defaultCollapseLevel?: number\n  getMenuItemsForPath?: GetMenuItemsForPath\n  formatValue?: FormatValue\n  onRevealFunctionLocation?: (descriptor: JsonValueDescriptor) => void\n}\n\ntype GetMenuItemsForPath = (path: string, value: unknown) => ReactNode\ntype FormatValue = (path: string, value: unknown) => ReactNode\n\nconst COLORS = {\n  dark: {\n    null: 'gray',\n    // eslint-disable-next-line id-denylist\n    number: 'orange',\n    // eslint-disable-next-line id-denylist\n    string: 'yellow',\n    // eslint-disable-next-line id-denylist\n    boolean: 'violet.4',\n  },\n  light: {\n    null: 'gray',\n    // eslint-disable-next-line id-denylist\n    number: 'orange.7',\n    // eslint-disable-next-line id-denylist\n    string: 'yellow.9',\n    // eslint-disable-next-line id-denylist\n    boolean: 'violet.7',\n  },\n}\n\nconst JsonContext = createContext<{\n  defaultCollapseLevel: number\n  getMenuItemsForPath?: GetMenuItemsForPath\n  formatValue: FormatValue\n  onRevealFunctionLocation?: (descriptor: JsonValueDescriptor) => void\n} | null>(null)\n\nexport type JsonValueDescriptor =\n  | {\n      parentType: 'root'\n      value: unknown\n      depth: 0\n      path: ''\n      evaluationPath: ''\n    }\n  | {\n      parentType: 'array'\n      parentValue: unknown[]\n      value: unknown\n      path: string\n      evaluationPath: string\n      depth: number\n    }\n  | {\n      parentType: 'object'\n      parentValue: object\n      value: unknown\n      path: string\n      evaluationPath: string\n      depth: number\n      key: string\n    }\n\nexport const Json = forwardRef(\n  (\n    {\n      value,\n      defaultCollapseLevel = Infinity,\n      formatValue = defaultFormatValue,\n      getMenuItemsForPath,\n      onRevealFunctionLocation,\n      ...boxProps\n    }: JsonProps & BoxProps,\n    ref: ForwardedRef<HTMLDivElement | HTMLSpanElement>\n  ) => (\n    <Box\n      ref={\n        // setting a HTMLDivElement | HTMLSpanElement ref messes with TS types as the component prop is also div | span\n        ref as any\n      }\n      {...boxProps}\n      component={doesValueHasChildren(value) ? 'div' : 'span'}\n      className={classes.root}\n    >\n      <JsonContext.Provider\n        value={{ defaultCollapseLevel, getMenuItemsForPath, formatValue, onRevealFunctionLocation }}\n      >\n        <JsonValue\n          descriptor={{\n            parentType: 'root',\n            value,\n            depth: 0,\n            path: '',\n            evaluationPath: '',\n          }}\n        />\n      </JsonContext.Provider>\n    </Box>\n  )\n)\n\nexport function defaultFormatValue(_path: string, value: unknown) {\n  return typeof value === 'number' ? formatNumber(value) : JSON.stringify(value)\n}\n\ninterface FunctionMetadata {\n  __type: 'function'\n  __name: string\n  __source?: string\n}\n\nfunction isFunctionMetadata(value: unknown): value is FunctionMetadata {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    '__type' in value &&\n    (value as any).__type === 'function' &&\n    '__name' in value\n  )\n}\n\nfunction JsonFunctionValue({ descriptor, metadata }: { descriptor: JsonValueDescriptor; metadata: FunctionMetadata }) {\n  const [showSource, setShowSource] = useState(false)\n  const colorScheme = useColorScheme()\n  const { onRevealFunctionLocation } = useContext(JsonContext)!\n\n  return (\n    <JsonLine descriptor={descriptor}>\n      <JsonText color=\"grape\" descriptor={descriptor}>\n        <Text component=\"span\">{`<function: ${metadata.__name}>`}</Text>\n      </JsonText>\n      {metadata.__source && (\n        <>\n          <Text\n            component=\"span\"\n            size=\"xs\"\n            c=\"dimmed\"\n            ml=\"xs\"\n            className={classes.functionSourceToggle}\n            onClick={() => setShowSource(!showSource)}\n          >\n            {showSource ? '▾ hide source' : '▸ show source'}\n          </Text>\n          <Collapse expanded={showSource}>\n            <Box\n              p=\"xs\"\n              bg={`gray.${colorScheme === 'dark' ? 8 - descriptor.depth : descriptor.depth + 1}`}\n              className={classes.functionSource}\n            >\n              {onRevealFunctionLocation && (\n                <Text\n                  component=\"div\"\n                  size=\"xs\"\n                  c=\"blue\"\n                  className={classes.functionSourceToggle}\n                  onClick={() => onRevealFunctionLocation?.(descriptor)}\n                  title=\"Log function to console to reveal source location\"\n                >\n                  <IconSearch size={12} />\n                  Reveal in console\n                </Text>\n              )}\n              {metadata.__source}\n            </Box>\n          </Collapse>\n        </>\n      )}\n    </JsonLine>\n  )\n}\n\nfunction JsonValue({ descriptor }: { descriptor: JsonValueDescriptor }) {\n  const colorScheme = useColorScheme()\n  const { formatValue } = useContext(JsonContext)!\n\n  if (Array.isArray(descriptor.value)) {\n    if (descriptor.value.length === 0) {\n      return <JsonEmptyValue label=\"[empty array]\" descriptor={descriptor} />\n    }\n\n    return (\n      <JsonValueChildren descriptor={descriptor}>\n        {descriptor.value.map((child, i) => (\n          <JsonValue\n            key={i}\n            descriptor={{\n              parentType: 'array',\n              parentValue: descriptor.value as unknown[],\n              value: child,\n              path: descriptor.path,\n              evaluationPath: descriptor.evaluationPath ? `${descriptor.evaluationPath}.${i}` : String(i),\n              depth: descriptor.depth + 1,\n            }}\n          />\n        ))}\n      </JsonValueChildren>\n    )\n  }\n\n  if (typeof descriptor.value === 'object' && descriptor.value !== null) {\n    // Check if this is a serialized function object\n    if (isFunctionMetadata(descriptor.value)) {\n      return <JsonFunctionValue descriptor={descriptor} metadata={descriptor.value} />\n    }\n\n    const entries = Object.entries(descriptor.value)\n    if (entries.length === 0) {\n      return <JsonEmptyValue label=\"{empty object}\" descriptor={descriptor} />\n    }\n\n    return (\n      <JsonValueChildren descriptor={descriptor}>\n        {Object.entries(descriptor.value).map(([key, child]) => (\n          <JsonValue\n            key={key}\n            descriptor={{\n              parentType: 'object',\n              parentValue: descriptor.value as object,\n              value: child,\n              path: descriptor.path ? `${descriptor.path}.${key}` : key,\n              evaluationPath: descriptor.evaluationPath ? `${descriptor.evaluationPath}.${key}` : key,\n              depth: descriptor.depth + 1,\n              key,\n            }}\n          />\n        ))}\n      </JsonValueChildren>\n    )\n  }\n  const themeColors = COLORS[colorScheme]\n  const color =\n    descriptor.value === null\n      ? themeColors.null\n      : typeof descriptor.value === 'number'\n        ? themeColors.number\n        : typeof descriptor.value === 'string'\n          ? themeColors.string\n          : typeof descriptor.value === 'boolean'\n            ? themeColors.boolean\n            : undefined\n\n  return (\n    <JsonLine descriptor={descriptor}>\n      <JsonText color={color} descriptor={descriptor}>\n        {formatValue(descriptor.path, descriptor.value)}\n      </JsonText>\n    </JsonLine>\n  )\n}\n\nfunction JsonValueChildren({ children, descriptor }: { children: ReactNode; descriptor: JsonValueDescriptor }) {\n  const { defaultCollapseLevel } = useContext(JsonContext)!\n\n  // The root is not collapsible\n  const isCollapsible = descriptor.parentType !== 'root'\n\n  const [isCollapsed, setIsCollapsed] = useState(isCollapsible && descriptor.depth >= defaultCollapseLevel)\n  const colorScheme = useColorScheme()\n\n  function toggleIsCollapsed() {\n    setIsCollapsed((previous) => !previous)\n  }\n\n  return (\n    <div className={classes.valueChildren}>\n      <Box\n        bg={`gray.${colorScheme === 'dark' ? 8 - descriptor.depth : descriptor.depth + 1}`}\n        className={classes.valueChildrenIndent}\n        data-collapsible={isCollapsible}\n        onClick={isCollapsible ? toggleIsCollapsed : undefined}\n      >\n        {isCollapsible && (isCollapsed ? '▸' : '▾')}\n      </Box>\n      <JsonLine descriptor={descriptor} isFloating={descriptor.parentType === 'array'}>\n        {isCollapsed && (\n          <span className={classes.valueChildrenCollapsedEllipsis} onClick={toggleIsCollapsed}>\n            ...\n          </span>\n        )}\n      </JsonLine>\n      <Collapse expanded={!isCollapsed}>{children}</Collapse>\n    </div>\n  )\n}\n\nfunction JsonEmptyValue({ label, descriptor }: { label: string; descriptor: JsonValueDescriptor }) {\n  return (\n    <JsonLine descriptor={descriptor}>\n      <JsonText color=\"dimmed\" descriptor={descriptor}>\n        {label}\n      </JsonText>\n    </JsonLine>\n  )\n}\n\nfunction JsonText({\n  children,\n  color,\n  descriptor,\n}: {\n  children: ReactNode\n  color?: MantineColor | undefined\n  descriptor: JsonValueDescriptor\n}) {\n  const { getMenuItemsForPath } = useContext(JsonContext)!\n  const menuItemsForPath = getMenuItemsForPath?.(descriptor.path, descriptor.value)\n\n  let menuItems: ReactNode\n\n  if (descriptor.parentType === 'object') {\n    menuItems = (\n      <>\n        <CopyMenuItem value={descriptor.value}>Copy property value</CopyMenuItem>\n        <CopyMenuItem value={descriptor.parentValue}>Copy parent object</CopyMenuItem>\n      </>\n    )\n  } else if (descriptor.parentType === 'array') {\n    menuItems = (\n      <>\n        <CopyMenuItem value={descriptor.value}>Copy array item</CopyMenuItem>\n        <CopyMenuItem value={descriptor.parentValue}>Copy parent array</CopyMenuItem>\n      </>\n    )\n  } else {\n    menuItems = (\n      <>\n        <CopyMenuItem value={descriptor.value}>Copy value</CopyMenuItem>\n      </>\n    )\n  }\n\n  return (\n    <Menu shadow=\"md\" width={200}>\n      <Menu.Target>\n        <Text component=\"span\" c={color} className={classes.jsonTextTarget}>\n          {children}\n        </Text>\n      </Menu.Target>\n      <Menu.Dropdown>\n        {menuItems}\n        {menuItemsForPath}\n      </Menu.Dropdown>\n    </Menu>\n  )\n}\n\nfunction JsonLine({\n  children,\n  onClick,\n  descriptor,\n  isFloating,\n}: {\n  children: ReactNode\n  onClick?: () => void\n  descriptor: JsonValueDescriptor\n  isFloating?: boolean\n}) {\n  let prefix\n  if (descriptor.parentType === 'array') {\n    prefix = <JsonText descriptor={descriptor}>{'- '}</JsonText>\n  } else if (descriptor.parentType === 'object') {\n    prefix = <JsonText descriptor={descriptor}>{`${descriptor.key}: `}</JsonText>\n  }\n\n  const isTopLevel = descriptor.parentType === 'root'\n\n  return (\n    <Box\n      component={isTopLevel ? 'span' : 'div'}\n      className={classes.jsonLine}\n      data-top-level={isTopLevel || undefined}\n      data-floating={isFloating || undefined}\n      style={{ '--depth': descriptor.depth }}\n      onClick={onClick}\n    >\n      {prefix}\n      {children}\n    </Box>\n  )\n}\n\nexport function CopyMenuItem({ value, children }: { value: unknown; children: ReactNode }) {\n  return (\n    <Menu.Item\n      onClick={() => {\n        if (typeof value === 'object') {\n          copy(JSON.stringify(value, null, 2))\n        } else {\n          /* eslint-disable @typescript-eslint/no-base-to-string */\n          copy(String(value))\n        }\n      }}\n      leftSection={<IconCopy size={14} />}\n    >\n      {children}\n    </Menu.Item>\n  )\n}\n\nfunction doesValueHasChildren(value: unknown) {\n  if (Array.isArray(value)) {\n    return value.length > 0\n  }\n\n  if (typeof value === 'object' && value !== null) {\n    return Object.keys(value).length > 0\n  }\n\n  return false\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/lazyCollapse.tsx",
    "content": "import { Collapse as MantineCollapse } from '@mantine/core'\nimport type { CollapseProps } from '@mantine/core'\nimport React, { forwardRef, useRef, useState } from 'react'\n\n/**\n * Dropin replacement for mantine Collapse component but does not render children when collapsed.\n */\nexport const LazyCollapse = forwardRef<HTMLDivElement, CollapseProps>(\n  ({ children, expanded: expandedProp, onTransitionEnd, ...otherProps }, ref) => {\n    const [isTransitioning, setIsTransitioning] = useState(false)\n    const previousExpandedRef = useRef(expandedProp)\n\n    if (previousExpandedRef.current !== expandedProp) {\n      setIsTransitioning(true)\n      previousExpandedRef.current = expandedProp\n    }\n\n    return (\n      <MantineCollapse\n        ref={ref}\n        expanded={expandedProp}\n        {...otherProps}\n        onTransitionEnd={() => {\n          setIsTransitioning(false)\n          onTransitionEnd?.()\n        }}\n      >\n        {(expandedProp || isTransitioning) && children}\n      </MantineCollapse>\n    )\n  }\n)\n"
  },
  {
    "path": "developer-extension/src/panel/components/panel.module.css",
    "content": ".tabs {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n}\n\n.tab {\n  flex: 1;\n  min-height: 0;\n}\n\n.link {\n  align-self: center;\n  padding-right: 2%;\n  flex-shrink: 0;\n}\n\n.topBox {\n  justify-content: space-between;\n  flex-wrap: unset;\n}\n\n.tabBox {\n  display: flex;\n  flex: 1;\n  flex-direction: row;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/panel.tsx",
    "content": "import React, { useState } from 'react'\nimport { Tabs, Text, Anchor } from '@mantine/core'\nimport { datadogRum } from '@datadog/browser-rum'\n\nimport { useEvents } from '../hooks/useEvents'\nimport { useAutoFlushEvents } from '../hooks/useAutoFlushEvents'\nimport { useNetworkRules } from '../hooks/useNetworkRules'\nimport { useSettings } from '../hooks/useSettings'\nimport { DEFAULT_PANEL_TAB, PanelTabs } from '../../common/panelTabConstants'\nimport type { Settings } from '../../common/extension.types'\nimport { useDebugMode } from '../hooks/useDebugMode'\nimport { SettingsTab } from './tabs/settingsTab'\nimport { InfosTab } from './tabs/infosTab'\nimport { EventsTab, DEFAULT_COLUMNS } from './tabs/eventsTab'\nimport { ReplayTab } from './tabs/replayTab'\n\nimport * as classes from './panel.module.css'\n\nexport function Panel() {\n  const [settings] = useSettings()\n\n  useAutoFlushEvents(settings.autoFlush)\n  useNetworkRules(settings)\n  useDebugMode(settings.debugMode)\n\n  const { events, filters, setFilters, clear, facetRegistry } = useEvents(settings)\n\n  const [columns, setColumns] = useState(DEFAULT_COLUMNS)\n\n  const [activeTab, setActiveTab] = useState<string | null>(DEFAULT_PANEL_TAB)\n  function updateActiveTab(activeTab: string | null) {\n    setActiveTab(activeTab)\n    datadogRum.startView(activeTab!)\n  }\n\n  return (\n    <Tabs color=\"violet\" value={activeTab} className={classes.tabs} onChange={updateActiveTab}>\n      <Tabs.List className={classes.topBox} data-dd-privacy=\"allow\">\n        <div className={classes.tabBox}>\n          <Tabs.Tab value={PanelTabs.Events}>Events</Tabs.Tab>\n          <Tabs.Tab\n            value={PanelTabs.Infos}\n            rightSection={\n              isOverridingInitConfiguration(settings) && (\n                <Text c=\"orange\" fw=\"bold\" title=\"Overriding init configuration\">\n                  ⚠\n                </Text>\n              )\n            }\n          >\n            <Text>Infos</Text>\n          </Tabs.Tab>\n          <Tabs.Tab value={PanelTabs.Replay}>\n            <Text>Live replay</Text>\n          </Tabs.Tab>\n          <Tabs.Tab\n            value={PanelTabs.Settings}\n            rightSection={\n              isInterceptingNetworkRequests(settings) && (\n                <Text c=\"orange\" fw=\"bold\" title=\"Intercepting network requests\">\n                  ⚠\n                </Text>\n              )\n            }\n          >\n            Settings\n          </Tabs.Tab>\n        </div>\n        <Anchor\n          className={classes.link}\n          href=\"https://github.com/DataDog/browser-sdk/tree/main/developer-extension#browser-sdk-developer-extension\"\n          target=\"_blank\"\n        >\n          🔗 Documentation\n        </Anchor>\n      </Tabs.List>\n\n      <Tabs.Panel value={PanelTabs.Events} className={classes.tab}>\n        <EventsTab\n          events={events}\n          facetRegistry={facetRegistry}\n          filters={filters}\n          onFiltersChange={setFilters}\n          columns={columns}\n          onColumnsChange={setColumns}\n          clear={clear}\n        />\n      </Tabs.Panel>\n      <Tabs.Panel value={PanelTabs.Infos} className={classes.tab}>\n        <InfosTab />\n      </Tabs.Panel>\n      <Tabs.Panel value={PanelTabs.Replay} className={classes.tab}>\n        <ReplayTab />\n      </Tabs.Panel>\n      <Tabs.Panel value={PanelTabs.Settings} className={classes.tab}>\n        <SettingsTab />\n      </Tabs.Panel>\n    </Tabs>\n  )\n}\n\nfunction isInterceptingNetworkRequests(settings: Settings) {\n  return settings.blockIntakeRequests || settings.useDevBundles || settings.useRumSlim\n}\n\nfunction isOverridingInitConfiguration(settings: Settings) {\n  return settings.rumConfigurationOverride || settings.logsConfigurationOverride\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabBase.module.css",
    "content": ".root {\n  height: 100%;\n}\n\n.topContainer {\n  margin: 0;\n}\n\n.leftContainer {\n  width: 250px;\n}\n\n.contentContainer {\n  flex: 1;\n  overflow-y: auto;\n  overflow-x: hidden;\n  padding: 0;\n  margin: 0;\n\n  scroll-timeline:\n    --dd-tab-scroll-timeline,\n    --dd-tab-scroll-x-timeline x;\n}\n\n.horizontalContainer {\n  flex: 1;\n  /* This makes sure the row height fills its parent container and is not influenced by its inner content */\n  min-height: 0;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabBase.tsx",
    "content": "import { Container, Flex, ScrollArea, Space } from '@mantine/core'\nimport type { ReactNode } from 'react'\nimport React from 'react'\nimport * as classes from './tabBase.module.css'\n\ninterface TabBaseProps {\n  /**\n   * Content displayed at the top of the tab, does not scroll.\n   */\n  top?: ReactNode\n\n  /**\n   * Content displayed at the left side of the tab.\n   */\n  leftSide?: ReactNode\n\n  /**\n   * Content of the tab, scrolls\n   */\n  children: ReactNode\n}\n\nexport function TabBase({ top, leftSide, children }: TabBaseProps) {\n  return (\n    <Flex direction=\"column\" className={classes.root}>\n      {top && (\n        <Container fluid className={classes.topContainer}>\n          <Space h=\"sm\" />\n          {top}\n          <Space h=\"sm\" />\n        </Container>\n      )}\n      <Flex direction=\"row\" className={classes.horizontalContainer}>\n        {leftSide && (\n          <ScrollArea className={classes.leftContainer}>\n            {leftSide}\n            <Space h=\"sm\" />\n          </ScrollArea>\n        )}\n        <Container fluid className={classes.contentContainer}>\n          {children}\n        </Container>\n      </Flex>\n    </Flex>\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/addColumnPopover.module.css",
    "content": ".addFieldColumn {\n  display: flex;\n  align-items: flex-end;\n  gab: var(--mantine-spacing-md);\n}\n\n.addFieldAutocomplete {\n  flex: 1;\n}\n\n.addFilterAutocompleteHighlight {\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/addColumnPopover.tsx",
    "content": "import type { OptionsFilter } from '@mantine/core'\nimport { Autocomplete, Button, Flex, Popover, Text } from '@mantine/core'\nimport { IconColumnInsertRight } from '@tabler/icons-react'\nimport React, { useMemo, useState } from 'react'\nimport type { FacetRegistry } from '../../../hooks/useEvents'\nimport type { EventListColumn } from './columnUtils'\nimport { getColumnTitle, includesColumn, DEFAULT_COLUMNS } from './columnUtils'\nimport { RowButton } from './rowButton'\nimport * as classes from './addColumnPopover.module.css'\n\nexport function AddColumnPopover({\n  columns,\n  onColumnsChange,\n  facetRegistry,\n}: {\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n  facetRegistry: FacetRegistry\n}) {\n  return (\n    <Popover width={300} trapFocus position=\"bottom\" withArrow shadow=\"md\">\n      <Popover.Target>\n        <RowButton title=\"Add column\" icon={IconColumnInsertRight} />\n      </Popover.Target>\n      <Popover.Dropdown>\n        <Flex direction=\"column\" gap=\"sm\">\n          {DEFAULT_COLUMNS.map((column) => (\n            <AddDefaultColumnButton\n              key={column.type}\n              column={column}\n              columns={columns}\n              onColumnsChange={onColumnsChange}\n            />\n          ))}\n          <AddFieldColumn columns={columns} onColumnsChange={onColumnsChange} facetRegistry={facetRegistry} />\n        </Flex>\n      </Popover.Dropdown>\n    </Popover>\n  )\n}\n\nfunction AddDefaultColumnButton({\n  column,\n  columns,\n  onColumnsChange,\n}: {\n  column: EventListColumn\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n}) {\n  if (includesColumn(columns, column)) {\n    return null\n  }\n  return (\n    <Flex justify=\"space-between\" align=\"center\" gap=\"sm\">\n      <Text>{getColumnTitle(column)}</Text>\n      <Button\n        onClick={() => {\n          onColumnsChange(columns.concat(column))\n        }}\n      >\n        Add\n      </Button>\n    </Flex>\n  )\n}\n\nfunction AddFieldColumn({\n  columns,\n  onColumnsChange,\n  facetRegistry,\n}: {\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n  facetRegistry: FacetRegistry\n}) {\n  const [input, setInput] = useState('')\n\n  function addFieldColumn(path: string) {\n    const newColumn: EventListColumn = { path, type: 'field' }\n    if (!includesColumn(columns, newColumn)) {\n      onColumnsChange(columns.concat(newColumn))\n    }\n  }\n\n  const allPaths = useMemo(\n    () =>\n      Array.from(facetRegistry.getAllFieldPaths()).sort((a, b) => {\n        // Sort private fields last\n        if (a.startsWith('_dd') !== b.startsWith('_dd')) {\n          if (a.startsWith('_dd')) {\n            return 1\n          }\n          if (b.startsWith('_dd')) {\n            return -1\n          }\n        }\n        return a < b ? -1 : 1\n      }),\n    []\n  )\n\n  return (\n    <form\n      onSubmit={(event) => {\n        event.preventDefault()\n        addFieldColumn(input)\n      }}\n      className={classes.addFieldColumn}\n    >\n      <Autocomplete\n        className={classes.addFieldAutocomplete}\n        value={input}\n        label=\"Field\"\n        onChange={setInput}\n        data={allPaths}\n        filter={filterColumns}\n        placeholder=\"foo.bar\"\n        onOptionSubmit={addFieldColumn}\n      />\n      <Button type=\"submit\">Add</Button>\n    </form>\n  )\n}\n\nfunction filterColumns(filterOptions: Parameters<OptionsFilter>[0]): ReturnType<OptionsFilter> {\n  if (!filterOptions.search) {\n    return filterOptions.options\n  }\n  const filteredOptions = filterOptions.options.flatMap((option) => {\n    if (!('value' in option)) {\n      return []\n    }\n\n    const inputIndex = option.value.indexOf(filterOptions.search)\n    if (inputIndex < 0) {\n      return []\n    }\n\n    return [\n      {\n        value: option.value,\n        label: (\n          <span>\n            {option.value.slice(0, inputIndex)}\n            <span className={classes.addFilterAutocompleteHighlight}>\n              {option.value.slice(inputIndex, inputIndex + filterOptions.search.length)}\n            </span>\n            {option.value.slice(inputIndex + filterOptions.search.length)}\n          </span>\n        ) as unknown as string,\n        // Mantime types expect a string as label, but to support highlighting we need to return a\n        // ReactNode. This is the simplest way to achieve this, but it might break in the future\n      },\n    ]\n  })\n  return filteredOptions\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/columnDrag.module.css",
    "content": ".dragGhost {\n  /** Horizontal padding used by the Mantine Table in pixels */\n  --horizontal-padding: 10px;\n\n  /** Vertical padding used by the Mantine Table in pixels */\n  --vertical-padding: 7px;\n\n  position: fixed;\n\n  z-index: var(--dd-column-drag-ghost-z-index);\n\n  opacity: 0.5;\n  border-radius: var(--mantine-radius-sm);\n  top: var(--drag-target-top);\n  height: var(--drag-target-height);\n  transform: translateX(-50%);\n  left: var(--drag-x);\n  background: grey;\n  padding-top: var(--vertical-padding);\n  padding-bottom: var(--vertical-padding);\n  padding-left: var(--horizontal-padding);\n  padding-right: var(--horizontal-padding);\n  cursor: grabbing;\n}\n\n.dragGhost[data-action='insert'] {\n  width: 0;\n  left: var(--drag-insert-x);\n  background: green;\n  color: transparent;\n  padding-right: 3px;\n  padding-left: 3px;\n}\n\n.dragGhost[data-action='delete'] {\n  top: calc(var(--drag-target-y) + var(--drag-y) - var(--drag-start-y));\n  background: red;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/columnDrag.tsx",
    "content": "import type { RefObject } from 'react'\nimport React, { useState, useEffect } from 'react'\nimport { Text } from '@mantine/core'\nimport type { Coordinates } from './drag'\nimport { initDrag } from './drag'\nimport type { EventListColumn } from './columnUtils'\nimport { moveColumn, removeColumn, getColumnTitle } from './columnUtils'\nimport * as classes from './columnDrag.module.css'\n\n/** Number of pixel to determine if the cursor is close enough of a position to trigger an action */\nconst ACTION_DISTANCE_THRESHOLD = 20\n\nexport function ColumnDrag({\n  headerRowRef,\n  columns,\n  onColumnsChange,\n}: {\n  headerRowRef: RefObject<HTMLDivElement | null>\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n}) {\n  const [drag, setDrag] = useState<DragState | null>(null)\n\n  useEffect(() => {\n    if (columns.length > 1) {\n      const { stop } = initColumnDrag(headerRowRef.current!, setDrag, columns, onColumnsChange)\n      return stop\n    }\n  }, [columns])\n\n  return drag && <DragGhost drag={drag} />\n}\n\nfunction DragGhost({ drag }: { drag: DragState }) {\n  return (\n    <div\n      className={classes.dragGhost}\n      data-action={drag.action?.type}\n      style={\n        {\n          '--drag-x': `${drag.position.x}px`,\n          '--drag-y': `${drag.position.y}px`,\n          '--drag-start-y': `${drag.startPosition.y}px`,\n          '--drag-target-top': `${drag.targetRect.top}px`,\n          '--drag-target-height': `${drag.targetRect.height}px`,\n          '--drag-target-y': `${drag.targetRect.y}px`,\n          '--drag-insert-x': drag.action?.type === 'insert' ? `${drag.action.place.xPosition}px` : '0',\n        } as React.CSSProperties\n      }\n    >\n      <Text w=\"bold\">{getColumnTitle(drag.column)}</Text>\n    </div>\n  )\n}\n\nfunction getClosestCell(target: HTMLElement) {\n  if (target.closest('button, .mantine-Popover-dropdown')) {\n    return null\n  }\n  return target.closest('[data-header-cell]')\n}\n\ninterface DragState {\n  targetRect: DOMRect\n  startPosition: Coordinates\n  position: Coordinates\n  action?: DragAction\n  moved: boolean\n  insertPlaces: Place[]\n  column: EventListColumn\n}\n\ninterface Place {\n  index: number\n  xPosition: number\n}\n\ntype DragAction = { type: 'delete' } | { type: 'insert'; place: Place }\n\nfunction initColumnDrag(\n  target: HTMLElement,\n  onColumnDragStateChanges: (state: DragState | null) => void,\n  columns: EventListColumn[],\n  onColumnsChange: (columns: EventListColumn[]) => void\n) {\n  let state: DragState | null = null\n\n  return initDrag({\n    target,\n\n    onStart({ target, position }) {\n      const targetCell = getClosestCell(target)\n      if (!targetCell) {\n        return false\n      }\n      const siblings = Array.from(targetCell.parentElement!.querySelectorAll(':scope > [data-header-cell]'))\n      const columnIndex = siblings.indexOf(targetCell)\n\n      state = {\n        targetRect: targetCell.getBoundingClientRect(),\n        insertPlaces: siblings.flatMap((sibling, index) => {\n          if (sibling === targetCell) {\n            return []\n          }\n          return {\n            xPosition: sibling.getBoundingClientRect()[index < columnIndex ? 'left' : 'right'],\n            index,\n          }\n        }),\n        startPosition: position,\n        position,\n        moved: false,\n        action: undefined,\n        column: columns[columnIndex],\n      }\n      onColumnDragStateChanges(state)\n    },\n\n    onMove({ position }) {\n      if (!state) {\n        return\n      }\n      let action: DragAction | undefined\n      if (Math.abs(state.startPosition.y - position.y) > ACTION_DISTANCE_THRESHOLD) {\n        action = { type: 'delete' }\n      } else {\n        const insertPlace = state.insertPlaces.find(\n          ({ xPosition }) => Math.abs(position.x - xPosition) < ACTION_DISTANCE_THRESHOLD\n        )\n        if (insertPlace) {\n          action = { type: 'insert', place: insertPlace }\n        }\n      }\n\n      state = { ...state, action, position, moved: true }\n      onColumnDragStateChanges(state)\n    },\n\n    onDrop() {\n      if (!state) {\n        return\n      }\n\n      if (state.action) {\n        switch (state.action.type) {\n          case 'delete':\n            onColumnsChange(removeColumn(columns, state.column))\n            break\n          case 'insert':\n            onColumnsChange(moveColumn(columns, state.column, state.action.place.index))\n            break\n        }\n      }\n\n      state = null\n      onColumnDragStateChanges(state)\n    },\n\n    onAbort() {\n      state = null\n      onColumnDragStateChanges(state)\n    },\n  })\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/columnUtils.ts",
    "content": "export type EventListColumn =\n  | { type: 'date' }\n  | { type: 'description' }\n  | { type: 'type' }\n  | { type: 'field'; path: string }\n\nexport const DEFAULT_COLUMNS: EventListColumn[] = [{ type: 'date' }, { type: 'type' }, { type: 'description' }]\n\nexport function includesColumn(existingColumns: EventListColumn[], newColumn: EventListColumn) {\n  return existingColumns.some((column) => {\n    if (column.type === 'field' && newColumn.type === 'field') {\n      return column.path === newColumn.path\n    }\n    return column.type === newColumn.type\n  })\n}\n\nexport function addColumn(columns: EventListColumn[], columnToAdd: EventListColumn) {\n  return columns.concat(columnToAdd)\n}\n\nexport function removeColumn(columns: EventListColumn[], columnToRemove: EventListColumn) {\n  return columns.filter((column) => columnToRemove !== column)\n}\n\nexport function moveColumn(columns: EventListColumn[], columnToMove: EventListColumn, index: number) {\n  const newColumns = removeColumn(columns, columnToMove)\n  newColumns.splice(index, 0, columnToMove)\n  return newColumns\n}\n\nexport function getColumnTitle(column: EventListColumn) {\n  return column.type === 'date'\n    ? 'Date'\n    : column.type === 'description'\n      ? 'Description'\n      : column.type === 'type'\n        ? 'Type'\n        : column.path\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/computeFacetState.spec.ts",
    "content": "import type { RumActionEvent, RumResourceEvent } from '@datadog/browser-rum'\nimport { FacetRegistry } from '../../../hooks/useEvents'\nimport type { FacetValuesFilter } from '../../../hooks/useEvents'\nimport { FACET_ROOT } from '../../../facets.constants'\nimport type { Facet } from '../../../facets.constants'\nimport { computeSelectionState } from './computeFacetState'\n\nconst rumResourceXHREvent = {\n  type: 'resource',\n  resource: {\n    type: 'xhr',\n    url: 'http://example.com',\n  },\n} as RumResourceEvent\n\nconst rumResourceBeaconEvent = {\n  type: 'resource',\n  resource: {\n    type: 'beacon',\n    url: 'http://example.com',\n  },\n} as RumResourceEvent\n\nconst rumCustomActionEvent = {\n  type: 'action',\n  action: {\n    type: 'custom',\n  },\n} as RumActionEvent\n\n// test that computeSelectionState returns the correct state\ndescribe('computeSelectionState', () => {\n  describe('include mode', () => {\n    it('returns \"unselected\" when the filter is empty', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'include',\n        facetValues: {},\n      }\n      const facet = {\n        path: 'resource.type',\n        label: 'Resource Type',\n      }\n\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      const facetValue = 'xhr'\n      expect(\n        computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])\n      ).toBe('unselected')\n    })\n    it('returns \"selected\" when the facet is in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'include',\n        facetValues: {\n          'resource.type': ['xhr'],\n        },\n      }\n      const facet = {\n        path: 'resource.type',\n        label: 'Resource Type',\n      }\n\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      const facetValue = 'xhr'\n      expect(\n        computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])\n      ).toBe('selected')\n    })\n\n    it('returns \"partial-selected\" when some children are in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'include',\n        facetValues: {\n          'resource.type': ['xhr'],\n        },\n      }\n      const facet = FACET_ROOT.values!.rum?.facets![0] as Facet\n      const facetValue = 'resource'\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      facetRegistry.addEvent(rumResourceBeaconEvent)\n      expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(\n        'partial-selected'\n      )\n    })\n\n    it('returns \"selected\" when all children are in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'include',\n        facetValues: {\n          'resource.type': ['xhr', 'beacon'],\n        },\n      }\n      const facet = FACET_ROOT.values!.rum?.facets![0] as Facet\n      const facetValue = 'resource'\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      facetRegistry.addEvent(rumResourceBeaconEvent)\n      expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(\n        'selected'\n      )\n    })\n\n    it('returns \"unselected\" when the facet or children are not in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'include',\n        facetValues: {\n          'resource.type': ['xhr'],\n        },\n      }\n      const facet = {\n        path: 'action.type',\n        label: 'Action Type',\n      }\n\n      const facetValue = 'action'\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      facetRegistry.addEvent(rumCustomActionEvent)\n      expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'action'])).toBe(\n        'unselected'\n      )\n    })\n  })\n\n  describe('exclude mode', () => {\n    it('returns \"selected\" when the filter is empty', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'exclude',\n        facetValues: {},\n      }\n      const facet = {\n        path: 'resource.type',\n        label: 'Resource Type',\n      }\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      const facetValue = 'xhr'\n      expect(\n        computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])\n      ).toBe('selected')\n    })\n\n    it('returns \"unselected\" when the facet is in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'exclude',\n        facetValues: {\n          'resource.type': ['xhr'],\n        },\n      }\n      const facet = {\n        path: 'resource.type',\n        label: 'Resource Type',\n      }\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      const facetValue = 'xhr'\n      expect(\n        computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])\n      ).toBe('unselected')\n    })\n    it('returns \"partial-selected\" when some children are in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'exclude',\n        facetValues: {\n          'resource.type': ['xhr'],\n        },\n      }\n      const facet = FACET_ROOT.values!.rum?.facets![0] as Facet\n\n      const facetValue = 'resource'\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      facetRegistry.addEvent(rumResourceBeaconEvent)\n      expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(\n        'partial-selected'\n      )\n    })\n\n    it('returns \"unelected\" when all children are in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'exclude',\n        facetValues: {\n          'resource.type': ['xhr', 'beacon'],\n        },\n      }\n      const facet = FACET_ROOT.values!.rum?.facets![0] as Facet\n      const facetValue = 'resource'\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      facetRegistry.addEvent(rumResourceBeaconEvent)\n      expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(\n        'unselected'\n      )\n    })\n\n    it('returns \"selected\" when the facet or children are not in the filter', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'exclude',\n        facetValues: {\n          'resource.type': ['xhr'],\n        },\n      }\n      const facet = {\n        path: 'action.type',\n        label: 'Action Type',\n      }\n\n      const facetValue = 'action'\n      const facetRegistry = new FacetRegistry()\n      facetRegistry.addEvent(rumResourceXHREvent)\n      facetRegistry.addEvent(rumCustomActionEvent)\n      expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'action'])).toBe(\n        'selected'\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/computeFacetState.ts",
    "content": "import type { FacetRegistry, FacetValuesFilter } from '../../../hooks/useEvents'\nimport type { Facet, FacetValue } from '../../../facets.constants'\ntype SelectionState = 'selected' | 'unselected' | 'partial-selected'\n\nfunction isAllChildrenFiltered(children: string[], filteredFacetValues: string[]) {\n  return children.every((child: FacetValue) => filteredFacetValues.includes(child))\n}\n\nfunction isAnyChildrenFiltered(children: string[], filteredFacetValues: string[]) {\n  return children.some((child: FacetValue) => filteredFacetValues.includes(child))\n}\n\n// limitation: only populate direct parents\nexport function computeSelectionState(\n  facetValuesFilter: FacetValuesFilter,\n  facetRegistry: FacetRegistry,\n  facet: Facet,\n  facetValue: FacetValue,\n  parentList: string[]\n): SelectionState {\n  const childrenFacets = facet.values?.[facetValue]?.facets\n\n  // we cannot know how many children in total there are, so we need to have facetRegistry\n  const children =\n    childrenFacets && childrenFacets.flatMap((child: Facet) => facetRegistry.getFacetChildrenValues(child.path))\n  const filteredFacetValues = Object.values(facetValuesFilter.facetValues).flat()\n  const isFiltering = !!Object.keys(facetValuesFilter.facetValues)\n\n  if (facetValuesFilter.type === 'include') {\n    if (!isFiltering) {\n      return 'unselected'\n    }\n\n    for (const parent of parentList) {\n      if (filteredFacetValues.includes(parent)) {\n        return 'selected'\n      }\n    }\n\n    // if all children are in the filter, then it should be selected'\n    if (children && isAllChildrenFiltered(children, filteredFacetValues)) {\n      return 'selected'\n    }\n    // if any of the direct children of the facet is in the filter, then it should be partial-selected\n    if (children && isAnyChildrenFiltered(children, filteredFacetValues)) {\n      return 'partial-selected'\n    }\n  } else if (facetValuesFilter.type === 'exclude') {\n    if (!isFiltering) {\n      return 'selected'\n    }\n    // if facet.value is in facetValueFilter, then it should be unselected\n    if (filteredFacetValues.includes(facetValue)) {\n      return 'unselected'\n    }\n    // if all children are in the filter, then it should be unselected\n    if (children && isAllChildrenFiltered(children, filteredFacetValues)) {\n      return 'unselected'\n    }\n    // if any of the children of the facet is in the filter, then it should be partial-selected\n    if (children && isAnyChildrenFiltered(children, filteredFacetValues)) {\n      return 'partial-selected'\n    }\n    return 'selected'\n  }\n\n  return 'unselected'\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/copyEvent.spec.ts",
    "content": "import type { TelemetryEvent } from '../../../../../../packages/core/src/domain/telemetry'\nimport type { LogsEvent } from '../../../../../../packages/logs/src/logsEvent.types'\nimport type { RumEvent } from '../../../../../../packages/rum-core/src/rumEvent.types'\nimport { getIntakeUrlForEvent, escapeShellParameter } from './copyEvent'\n\nconst RUM_ERROR_EVENT = { type: 'error' } as RumEvent\nconst TELEMETRY_EVENT = {\n  type: 'telemetry',\n  telemetry: { type: 'log' },\n} as TelemetryEvent\nconst LOG_EVENT = {\n  status: 'info',\n} as LogsEvent\n\ndescribe('getIntakeUrlForEvent', () => {\n  it('should return undefined when RUM is not present', () => {\n    expect(getIntakeUrlForEvent({} as any, RUM_ERROR_EVENT)).toBeUndefined()\n  })\n\n  it('should return undefined when no RUM config', () => {\n    expect(getIntakeUrlForEvent({ rum: {} } as any, RUM_ERROR_EVENT)).toBeUndefined()\n  })\n\n  it('should return undefined when no RUM version', () => {\n    expect(getIntakeUrlForEvent({ rum: { config: {} } } as any, RUM_ERROR_EVENT)).toBeUndefined()\n  })\n\n  it('should return the URL with the right parameters', () => {\n    const url = new URL(\n      getIntakeUrlForEvent(\n        {\n          rum: {\n            config: {\n              clientToken: 'client-token',\n              source: 'browser',\n            },\n            version: '1.2.3',\n          },\n        } as any,\n        RUM_ERROR_EVENT\n      )!\n    )\n\n    expect(url.host).toBe('browser-intake-datadoghq.com')\n    expect(url.pathname).toBe('/api/v2/rum')\n    expect(url.searchParams.get('ddsource')).toBe('browser')\n    expect(url.searchParams.get('dd-api-key')).toBe('client-token')\n    expect(url.searchParams.get('dd-evp-origin-version')).toBe('1.2.3')\n    expect(url.searchParams.get('dd-evp-origin')).toBe('browser')\n    expect(url.searchParams.get('dd-request-id')).toMatch(/[a-f0-9-]+/)\n    expect(url.searchParams.get('batch_time')).toMatch(/[0-9]+/)\n  })\n\n  it('should escape the version URL parameter', () => {\n    const url = new URL(\n      getIntakeUrlForEvent(\n        {\n          rum: {\n            config: {\n              clientToken: 'client-token',\n              source: 'browser',\n            },\n            version: '1.2.3&4',\n          },\n        } as any,\n        RUM_ERROR_EVENT\n      )!\n    )\n\n    expect(url.searchParams.get('dd-evp-origin-version')).toBe('1.2.3&4')\n  })\n\n  it('should use the RUM intake for telemetry events', () => {\n    const url = new URL(\n      getIntakeUrlForEvent(\n        {\n          rum: {\n            config: {\n              clientToken: 'client-token',\n              source: 'browser',\n            },\n            version: '1.2.3',\n          },\n        } as any,\n        TELEMETRY_EVENT\n      )!\n    )\n\n    expect(url.pathname).toBe('/api/v2/rum')\n  })\n\n  it('should use the Logs intake for Log events', () => {\n    const url = new URL(\n      getIntakeUrlForEvent(\n        {\n          logs: {\n            config: {\n              clientToken: 'client-token',\n              source: 'browser',\n            },\n            version: '1.2.3',\n          },\n        } as any,\n        LOG_EVENT\n      )!\n    )\n\n    expect(url.pathname).toBe('/api/v2/logs')\n  })\n})\n\ndescribe('escapeShellParameter', () => {\n  it('should escape simple strings', () => {\n    expect(escapeShellParameter('foo bar')).toBe(\"$'foo bar'\")\n  })\n\n  it('should escape backslashes', () => {\n    expect(escapeShellParameter('foo\\\\bar')).toBe(\"$'foo\\\\\\\\bar'\")\n  })\n\n  it('should escape single quotes', () => {\n    expect(escapeShellParameter(\"foo'bar\")).toBe(\"$'foo\\\\'bar'\")\n  })\n})\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/copyEvent.ts",
    "content": "import type { EndpointBuilder, InitConfiguration } from '@datadog/browser-core'\nimport { computeTransportConfiguration } from '../../../../../../packages/core/src/domain/configuration'\nimport { copy } from '../../../copy'\nimport type { SdkInfos } from '../../../hooks/useSdkInfos'\nimport type { SdkEvent } from '../../../sdkEvent'\nimport { getEventSource, EventSource } from '../../../sdkEvent'\n\nexport function canCopyEvent(sdkInfos: SdkInfos | undefined, event: SdkEvent): sdkInfos is SdkInfos {\n  return Boolean(sdkInfos && getIntakeUrlForEvent(sdkInfos, event))\n}\n\n/**\n * Copy the event as a curl command to the clipboard.\n *\n * This function is \"naive\" in the sense that it does not reflect the actual request done by the\n * SDK:\n *\n * * Request payloads are sometimes compressed, and we don't compress them here.\n *\n * * The intake URL is computed using the a version of the SDK that might not match one used by the\n * website.\n *\n * * Various tags like \"api\", \"flush_reason\", \"retry_count\" and \"retry_after\" are not included or\n * hardcoded.\n *\n * * Various browser headers like \"User-Agent\" are not included.\n */\nexport function copyEventAsCurl(sdkInfos: SdkInfos, event: SdkEvent) {\n  const url = getIntakeUrlForEvent(sdkInfos, event)\n  copy(`curl '${url}' \\\\\n  -X POST \\\\\n  -H 'Content-Type: text/plain' \\\\\n  --data-raw ${escapeShellParameter(JSON.stringify(event))}`)\n}\n\n/**\n * Copy the event as a fetch API call to the clipboard.\n *\n * This function is \"naive\" in the sense that it does not reflect the actual request done by the\n * SDK:\n *\n * * Request payloads are sometimes compressed, and we don't compress them here.\n *\n * * The intake URL is computed using the a version of the SDK that might not match one used by the\n * website.\n *\n * * Various tags like \"api\", \"flush_reason\", \"retry_count\" and \"retry_after\" are not included or\n * hardcoded.\n *\n * * Various browser headers like \"User-Agent\" are not included.\n */\nexport function copyEventAsFetch(sdkInfos: SdkInfos, event: SdkEvent) {\n  const url = getIntakeUrlForEvent(sdkInfos, event)\n  copy(`fetch('${url}', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'text/plain'\n    },\n    body: JSON.stringify(${JSON.stringify(event, null, 2)})\n  })`)\n}\n\nexport function escapeShellParameter(value: string) {\n  return `$'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n}\n\nexport function getIntakeUrlForEvent(sdkInfos: SdkInfos, event: SdkEvent) {\n  let builder: EndpointBuilder\n  let version: string\n\n  switch (getEventSource(event)) {\n    case EventSource.RUM:\n    case EventSource.TELEMETRY: {\n      if (!sdkInfos.rum?.config || !sdkInfos.rum?.version) {\n        return\n      }\n      version = sdkInfos.rum.version\n      builder = computeTransportConfiguration(sdkInfos.rum.config as InitConfiguration).rumEndpointBuilder\n      break\n    }\n\n    case EventSource.LOGS:\n      if (!sdkInfos.logs?.config || !sdkInfos.logs?.version) {\n        return\n      }\n      version = sdkInfos.logs.version\n      builder = computeTransportConfiguration(sdkInfos.logs.config as InitConfiguration).logsEndpointBuilder\n      break\n  }\n\n  return builder\n    .build('manual', { data: 'a', bytesCount: 1 })\n    .replace(/dd-evp-origin-version=[^&]+/g, `dd-evp-origin-version=${encodeURIComponent(version)}`)\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/drag.ts",
    "content": "export interface Coordinates {\n  x: number\n  y: number\n}\n\n/**\n * This is a framework agnostic drag implementation that works as a state machine:\n *\n * ```\n *  (init)\n *    |\n *  [onStart]\n *    |   \\______________\n *    |                  \\\n *  <returns true>      <returns false>\n *    |     ____          |\n *    |    /    \\       (end)\n *  [onMove]     )\n *    |  \\ \\____/\n *    |   \\______________\n *    |                  \\\n *  <drop in the window>  |\n *    |                <stop() called or drop out of the window>\n *    |                   |\n *  [onDrop]           [onAbort]\n *    | _________________/\n *    |/\n *  (end)\n * ```\n */\nexport function initDrag({\n  target,\n  onStart,\n  onMove,\n  onAbort,\n  onDrop,\n}: {\n  target: HTMLElement\n  onStart: (event: { target: HTMLElement; position: Coordinates }) => boolean | void\n  onMove: (event: { position: Coordinates }) => void\n  onDrop: () => void\n  onAbort: () => void\n}) {\n  type DragState =\n    | { isDragging: false }\n    | {\n        isDragging: true\n        removeListeners: () => void\n      }\n\n  let state: DragState = {\n    isDragging: false,\n  }\n\n  target.addEventListener('pointerdown', onPointerDown, { capture: true })\n\n  return {\n    stop: () => {\n      endDrag(true)\n      target.removeEventListener('pointerdown', onPointerDown, { capture: true })\n    },\n  }\n\n  function onPointerDown(event: PointerEvent) {\n    if (\n      state.isDragging ||\n      event.buttons !== 1 ||\n      onStart({ target: event.target as HTMLElement, position: { x: event.clientX, y: event.clientY } }) === false\n    ) {\n      return\n    }\n\n    event.preventDefault()\n\n    state = {\n      isDragging: true,\n      removeListeners: () => {\n        removeEventListener('pointerup', onPointerUp, { capture: true })\n        removeEventListener('pointermove', onPointerMove, { capture: true })\n      },\n    }\n\n    addEventListener('pointerup', onPointerUp, { capture: true })\n    addEventListener('pointermove', onPointerMove, { capture: true })\n  }\n\n  function onPointerUp(_event: PointerEvent) {\n    endDrag(false)\n  }\n\n  function onPointerMove(event: PointerEvent) {\n    if (!state.isDragging) {\n      return\n    }\n\n    if (event.buttons !== 1) {\n      // The user might have released the click outside of the window\n      endDrag(true)\n      return\n    }\n\n    onMove({\n      position: {\n        x: event.clientX,\n        y: event.clientY,\n      },\n    })\n  }\n\n  function endDrag(abort: boolean) {\n    if (state.isDragging) {\n      if (abort) {\n        onAbort()\n      } else {\n        onDrop()\n      }\n      state.removeListeners()\n      state = { isDragging: false }\n    }\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventRow.module.css",
    "content": ".descriptionCell {\n  cursor: pointer;\n}\n\n.cell {\n  vertical-align: top;\n}\n\n.cell:not([data-no-wrap]) {\n  word-break: break-word;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventRow.tsx",
    "content": "import { Table, Badge, Menu } from '@mantine/core'\nimport { IconCopy, IconDotsVertical, IconColumnInsertRight } from '@tabler/icons-react'\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react'\nimport React, { useRef, useState } from 'react'\nimport { default as clsx } from 'clsx'\nimport type { TelemetryEvent } from '../../../../../../packages/core/src/domain/telemetry'\nimport type { LogsEvent } from '../../../../../../packages/logs/src/logsEvent.types'\nimport type {\n  RumActionEvent,\n  RumErrorEvent,\n  RumLongTaskEvent,\n  RumResourceEvent,\n  RumViewEvent,\n  RumVitalEvent,\n} from '../../../../../../packages/rum-core/src/rumEvent.types'\nimport type { SdkEvent } from '../../../sdkEvent'\nimport { isTelemetryEvent, isLogEvent, isRumEvent } from '../../../sdkEvent'\nimport { formatDate, formatDuration } from '../../../formatNumber'\nimport { CopyMenuItem, defaultFormatValue, Json } from '../../json'\nimport { LazyCollapse } from '../../lazyCollapse'\nimport type { FacetRegistry } from '../../../hooks/useEvents'\nimport { useSdkInfos } from '../../../hooks/useSdkInfos'\nimport type { EventListColumn } from './columnUtils'\nimport { addColumn, includesColumn } from './columnUtils'\nimport * as classes from './eventRow.module.css'\nimport { RowButton } from './rowButton'\nimport { canCopyEvent, copyEventAsCurl, copyEventAsFetch } from './copyEvent'\n\nconst RUM_EVENT_TYPE_COLOR = {\n  action: 'violet',\n  error: 'red',\n  long_task: 'yellow',\n  view: 'blue',\n  resource: 'cyan',\n  telemetry: 'teal',\n  vital: 'orange',\n  transition: 'green',\n  view_update: 'blue',\n}\n\nconst LOG_STATUS_COLOR = {\n  emerg: 'red',\n  alert: 'red',\n  critical: 'red',\n  error: 'red',\n  warn: 'yellow',\n  notice: 'blue',\n  info: 'blue',\n  debug: 'cyan',\n  ok: 'cyan',\n}\n\nconst RESOURCE_TYPE_LABELS: Record<string, string | undefined> = {\n  xhr: 'XHR',\n  fetch: 'Fetch',\n  document: 'Document',\n  beacon: 'Beacon',\n  css: 'CSS',\n  js: 'JS',\n  image: 'Image',\n  font: 'Font',\n  media: 'Media',\n  other: 'Other',\n}\n\nexport const EventRow = React.memo(\n  ({\n    event,\n    columns,\n    facetRegistry,\n    onColumnsChange,\n  }: {\n    event: SdkEvent\n    columns: EventListColumn[]\n    facetRegistry: FacetRegistry\n    onColumnsChange: (newColumn: EventListColumn[]) => void\n  }) => {\n    const [isCollapsed, setIsCollapsed] = useState(true)\n    const jsonRef = useRef<HTMLDivElement>(null)\n\n    function getMenuItemsForPath(path: string, value?: unknown) {\n      const menuItems: ReactNode[] = []\n\n      const newColumn: EventListColumn = { type: 'field', path }\n      if (path && !includesColumn(columns, newColumn)) {\n        menuItems.push(\n          <>\n            <Menu.Item\n              onClick={() => {\n                onColumnsChange(addColumn(columns, newColumn))\n              }}\n              leftSection={<IconColumnInsertRight size={14} />}\n            >\n              Add column\n            </Menu.Item>\n          </>\n        )\n      }\n      if (typeof value === 'string') {\n        const searchTerm = String(value).replace(/ /g, '\\\\ ')\n        menuItems.push(<CopyMenuItem value={`${path}:${searchTerm}`}>Copy search query</CopyMenuItem>)\n      }\n      return <>{menuItems}</>\n    }\n\n    return (\n      <Table.Tr>\n        {columns.map((column): React.ReactElement => {\n          switch (column.type) {\n            case 'date':\n              return (\n                <Cell key=\"date\" noWrap>\n                  {formatDate(event.date)}\n                </Cell>\n              )\n            case 'description':\n              return (\n                <Cell\n                  key=\"description\"\n                  className={classes.descriptionCell}\n                  onClick={(event) => {\n                    const target = event.target as Element\n\n                    // Ignore clicks on menus or the JSON contained in the collapsible area\n                    if (target.matches('[role=\"menu\"] *') || jsonRef.current?.contains(target)) {\n                      return\n                    }\n\n                    setIsCollapsed((previous) => !previous)\n                  }}\n                >\n                  <EventDescription event={event} />\n                  <LazyCollapse expanded={!isCollapsed}>\n                    <Json\n                      ref={jsonRef}\n                      value={event}\n                      defaultCollapseLevel={0}\n                      getMenuItemsForPath={getMenuItemsForPath}\n                      formatValue={formatValue}\n                      mt=\"xs\"\n                    />\n                  </LazyCollapse>\n                </Cell>\n              )\n            case 'type':\n              return (\n                <Cell key=\"type\">\n                  <EventTypeBadge event={event} />\n                </Cell>\n              )\n            case 'field': {\n              const value = facetRegistry.getFieldValueForEvent(event, column.path)\n              return (\n                <Cell key={`field-${column.path}`}>\n                  {value !== undefined && (\n                    <Json\n                      value={value}\n                      defaultCollapseLevel={0}\n                      getMenuItemsForPath={(path) =>\n                        getMenuItemsForPath(path ? `${column.path}.${path}` : column.path, value)\n                      }\n                      formatValue={(path, value) => formatValue(path ? `${column.path}.${path}` : column.path, value)}\n                    />\n                  )}\n                </Cell>\n              )\n            }\n          }\n        })}\n        <Cell>\n          <EventMenu event={event} />\n        </Cell>\n      </Table.Tr>\n    )\n  }\n)\n\nfunction EventTypeBadge({ event }: { event: SdkEvent }) {\n  let label: string\n  let variant: string\n  let color: string\n  if (isRumEvent(event) || isTelemetryEvent(event)) {\n    label = event.type\n    variant = 'outline'\n    color = RUM_EVENT_TYPE_COLOR[event.type]\n  } else {\n    label = `${event.origin} ${event.status}`\n    variant = 'dot'\n    color = LOG_STATUS_COLOR[event.status]\n  }\n\n  return (\n    <Badge\n      variant={variant}\n      color={color}\n      styles={{\n        label: { overflow: 'visible' },\n      }}\n    >\n      {label}\n    </Badge>\n  )\n}\n\nfunction EventMenu({ event }: { event: SdkEvent }) {\n  return (\n    <Menu shadow=\"md\" width={200}>\n      <Menu.Target>\n        <RowButton icon={IconDotsVertical} title=\"Actions\" />\n      </Menu.Target>\n\n      <Menu.Dropdown>\n        <EventMenuDropdown event={event} />\n      </Menu.Dropdown>\n    </Menu>\n  )\n}\n\nfunction EventMenuDropdown({ event }: { event: SdkEvent }) {\n  const infos = useSdkInfos()\n  if (!canCopyEvent(infos, event)) {\n    return (\n      <>\n        <Menu.Item disabled>Copy as cURL</Menu.Item>\n        <Menu.Item disabled>Copy as fetch</Menu.Item>\n      </>\n    )\n  }\n  return (\n    <>\n      <Menu.Item leftSection={<IconCopy size={14} />} onClick={() => copyEventAsCurl(infos, event)}>\n        Copy as cURL\n      </Menu.Item>\n      <Menu.Item leftSection={<IconCopy size={14} />} onClick={() => copyEventAsFetch(infos, event)}>\n        Copy as fetch\n      </Menu.Item>\n    </>\n  )\n}\n\nfunction Cell({\n  children,\n  className,\n  onClick,\n  noWrap,\n}: {\n  children: ReactNode\n  className?: string\n  onClick?: ComponentPropsWithoutRef<'td'>['onClick']\n  noWrap?: boolean\n}) {\n  return (\n    <Table.Td className={clsx(className, classes.cell)} data-no-wrap={noWrap || undefined} onClick={onClick}>\n      {children}\n    </Table.Td>\n  )\n}\n\nfunction formatValue(path: string, value: unknown) {\n  if (typeof value === 'number') {\n    if (path === 'date') {\n      return formatDate(value)\n    }\n    if (\n      path.endsWith('.first_byte') ||\n      path.endsWith('.dom_complete') ||\n      path.endsWith('.dom_content_loaded') ||\n      path.endsWith('.dom_interactive') ||\n      path.endsWith('.first_contentful_paint') ||\n      path.endsWith('.largest_contentful_paint') ||\n      path.endsWith('.load_event') ||\n      path.endsWith('.time_spent') ||\n      path.endsWith('_time') ||\n      path.endsWith('_delay') ||\n      path.endsWith('.duration') ||\n      path.endsWith('.start') ||\n      path.includes('.custom_timings.')\n    ) {\n      return formatDuration(value)\n    }\n  }\n\n  return defaultFormatValue(path, value)\n}\n\nexport const EventDescription = React.memo(({ event }: { event: SdkEvent }) => {\n  if (isRumEvent(event)) {\n    switch (event.type) {\n      case 'view':\n        return <ViewDescription event={event} />\n      case 'long_task':\n        return <LongTaskDescription event={event} />\n      case 'error':\n        return <ErrorDescription event={event} />\n      case 'resource':\n        return <ResourceDescription event={event} />\n      case 'action':\n        return <ActionDescription event={event} />\n      case 'vital':\n        return <VitalDescription event={event} />\n    }\n  } else if (isLogEvent(event)) {\n    return <LogDescription event={event} />\n  } else {\n    return <TelemetryDescription event={event} />\n  }\n})\n\nfunction LogDescription({ event }: { event: LogsEvent }) {\n  if (typeof event.message === 'string') {\n    return <>{event.message}</>\n  }\n\n  return <Json value={event.message} defaultCollapseLevel={0} />\n}\n\nfunction TelemetryDescription({ event }: { event: TelemetryEvent }) {\n  if (event.telemetry.type === 'configuration') {\n    return <Emphasis>Configuration</Emphasis>\n  }\n  if (event.telemetry.type === 'usage') {\n    return (\n      <>\n        <Emphasis>Usage</Emphasis> of <Emphasis>{event.telemetry.usage.feature}</Emphasis>\n      </>\n    )\n  }\n  return <>{event.telemetry.message}</>\n}\n\nfunction ViewDescription({ event }: { event: RumViewEvent }) {\n  const isRouteChange = event.view.loading_type === 'route_change'\n\n  return (\n    <>\n      {isRouteChange ? 'SPA Route Change' : 'Load Page'} <Emphasis>{getViewName(event.view)}</Emphasis>\n    </>\n  )\n}\n\nfunction ActionDescription({ event }: { event: RumActionEvent }) {\n  const actionName = event.action.target?.name\n  const frustrationTypes = event.action.frustration?.type\n\n  if (event.action.type === 'custom') {\n    return (\n      <>\n        Custom user action <Emphasis>{event.action.target?.name}</Emphasis>\n      </>\n    )\n  }\n\n  return (\n    <>\n      {frustrationTypes && frustrationTypes.length > 0 && '😡 '}\n      <Emphasis>{event.action.type}</Emphasis>\n      {actionName && (\n        <>\n          {' '}\n          on <Emphasis>{actionName}</Emphasis>\n        </>\n      )}\n    </>\n  )\n}\nfunction LongTaskDescription({ event }: { event: RumLongTaskEvent }) {\n  return (\n    <>\n      Long task of <Emphasis>{formatDuration(event.long_task.duration)}</Emphasis>\n    </>\n  )\n}\n\nfunction VitalDescription({ event }: { event: RumVitalEvent }) {\n  const vitalName = event.vital.name\n  const vitalValue = (event.vital as { duration?: number }).duration\n  const vitalDescription = event.vital.description\n  return (\n    <>\n      Custom <Emphasis>{event.vital.type}</Emphasis> vital:{' '}\n      <Emphasis>\n        {vitalName}\n        {vitalDescription && ` - ${vitalDescription}`}\n      </Emphasis>\n      {vitalValue !== undefined && (\n        <>\n          {' '}\n          of <Emphasis>{formatDuration(vitalValue)}</Emphasis>\n        </>\n      )}\n    </>\n  )\n}\n\nfunction ErrorDescription({ event }: { event: RumErrorEvent }) {\n  return (\n    <>\n      <Emphasis>{event.error.source}</Emphasis> error {event.error.type}: {event.error.message}\n    </>\n  )\n}\n\nfunction ResourceDescription({ event }: { event: RumResourceEvent }) {\n  const resourceType = event.resource.type\n  const isAsset = resourceType !== 'xhr' && resourceType !== 'fetch'\n\n  if (isAsset) {\n    return (\n      <>\n        Load <Emphasis>{RESOURCE_TYPE_LABELS[resourceType] || RESOURCE_TYPE_LABELS.other}</Emphasis> file{' '}\n        <Emphasis>{event.resource.url}</Emphasis>\n      </>\n    )\n  }\n\n  return (\n    <>\n      {RESOURCE_TYPE_LABELS[resourceType]} request <Emphasis>{event.resource.url}</Emphasis>\n    </>\n  )\n}\n\nfunction Emphasis({ children }: { children: ReactNode }) {\n  return <strong>{children}</strong>\n}\n\nfunction getViewName(view: { name?: string; url: string }) {\n  return `${view.name || new URL(view.url).pathname}`\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsList.module.css",
    "content": "/*\n  The event list is styled in a way that:\n\n  * when the table content would not fill the whole table width, the last column is stretched to\n    fill the remaining space:\n\n      | foo foo | bar bar                 |\n      |---------|-------------------------|\n      | foo foo | bar bar                 |\n\n  * when the table content would fill the table width, all columns are sized according to their\n    content, letting the text wrap:\n\n      | foo foo foo foo | bar bar bar bar |\n      | foo foo foo     | bar bar bar     |\n      |-----------------|-----------------|\n      | foo foo         | bar bar         |\n\n\n  To achieve this, first we bound the container width so it is either:\n\n  * 100% of the scrolling area when the content doesn't fill the whole table\n  * 100% + 1px of the scrolling area otherwise.\n\n  In the latter case, the scrolling container can theoretically scroll horizontally (in practice it\n  doesn't because the horizontal overflow is hidden).\n\n  We can detect this state by using a Scroll Driven Animation as described in\n  https://www.bram.us/2023/09/16/solved-by-css-scroll-driven-animations-detect-if-an-element-can-scroll-or-not/\n\n  Finally, we use a container query to stretch the last column to fill the remaining space only when\n  the table content doesn't fill the whole table.\n*/\n\n.root {\n  padding: 0 var(--mantine-spacing-md) var(--mantine-spacing-md) var(--mantine-spacing-md);\n\n  width: max-content;\n  min-width: 100%;\n  max-width: calc(100% + 1px);\n\n  --content-fills-the-table: no;\n  animation: detect-scroll;\n  animation-timeline: --dd-tab-scroll-x-timeline;\n}\n\n@keyframes detect-scroll {\n  from,\n  to {\n    --content-fills-the-table: yes;\n  }\n}\n\n@container style(--content-fills-the-table: no) {\n  .root table {\n    text-wrap: nowrap;\n  }\n\n  .root col[data-growable] {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsList.tsx",
    "content": "import { Table } from '@mantine/core'\nimport React, { useRef } from 'react'\nimport type { EventFilters, FacetRegistry } from '../../../hooks/useEvents'\nimport type { SdkEvent } from '../../../sdkEvent'\nimport { isRumViewEvent } from '../../../sdkEvent'\nimport type { EventListColumn } from './columnUtils'\nimport { EventRow } from './eventRow'\nimport { ColumnDrag } from './columnDrag'\nimport * as classes from './eventsList.module.css'\nimport { EventsListHeader } from './eventsListHeader'\n\nexport function EventsList({\n  events,\n  filters,\n  facetRegistry,\n  columns,\n  onColumnsChange,\n}: {\n  events: SdkEvent[]\n  filters: EventFilters\n  facetRegistry: FacetRegistry\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n}) {\n  const headerRowRef = useRef<HTMLTableRowElement>(null)\n\n  return (\n    <div className={classes.root}>\n      <Table stickyHeader>\n        <colgroup>\n          {columns.map((_, index) => (\n            <col\n              key={index}\n              data-growable={\n                // Only the last column is allowed to grow\n                index === columns.length - 1 || undefined\n              }\n            />\n          ))}\n        </colgroup>\n        <EventsListHeader\n          ref={headerRowRef}\n          columns={columns}\n          onColumnsChange={onColumnsChange}\n          facetRegistry={facetRegistry}\n        />\n\n        <Table.Tbody>\n          {events.map((event) => (\n            <EventRow\n              key={getEventRenderingKey(event, !filters.outdatedVersions)}\n              event={event}\n              columns={columns}\n              onColumnsChange={onColumnsChange}\n              facetRegistry={facetRegistry}\n            />\n          ))}\n        </Table.Tbody>\n      </Table>\n\n      <ColumnDrag columns={columns} onColumnsChange={onColumnsChange} headerRowRef={headerRowRef} />\n    </div>\n  )\n}\n\nconst eventRenderingKeys = new WeakMap<SdkEvent, number>()\nlet nextEventRenderingKey = 1\n\nfunction getEventRenderingKey(event: SdkEvent, excludeOutdatedVersions: boolean): number | string {\n  // If we are showing only the latest view updates, return the view.id as key so the component is\n  // simply updated and not recreated when a new update comes up.\n  if (isRumViewEvent(event) && excludeOutdatedVersions) {\n    return event.view.id\n  }\n\n  // Else return an ever-increasing id identifying each event instance.\n  let key = eventRenderingKeys.get(event)\n  if (key === undefined) {\n    key = nextEventRenderingKey\n    nextEventRenderingKey += 1\n    eventRenderingKeys.set(event, key)\n  }\n  return key\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsListHeader.module.css",
    "content": ".root {\n  z-index: var(--dd-events-list-header-z-index);\n}\n\n.columnHeader :global(.mantine-CloseButton-root) {\n  opacity: 0;\n}\n\n.columnHeader:hover :global(.mantine-CloseButton-root) {\n  opacity: 1;\n}\n\n.addColumnCell {\n  width: 0;\n}\n\n/*\n  The following style is used to draw a shadow at the bottom of the header.\n\n  We want to show the shadow only when the header is scrolled down. To do so, we use a Scroll Driven\n  Animation to display the shadow according to the scroll position.\n\n  When using a box-shadow directly on the header, the shadow is visible on the sides, which is a bit\n  weird aesthetically. To avoid this, we use a pseudo-element to draw the shadow and use the\n  container to \"clip\" the shadow on the sides.\n*/\n\n@keyframes table-header-shadow {\n  to {\n    box-shadow: 5px 0 var(--shadow-size) var(--shadow-color);\n  }\n}\n\n.headerRowShadow {\n  --shadow-size: 20px;\n\n  position: absolute;\n\n  /*\n    When the header is positioned as 'sticky', its bottom border disappears when scrolled down,\n    making difficult to differentiate the header from the rows. This pseudo-element is used to\n    draw a border at the bottom of the header, so that it is always visible.\n  */\n  border-top: 1px solid var(--dd-border-color);\n  margin-top: -1px;\n\n  width: 100%;\n\n  /*\n    The goal of this hidden overflow is to crop the shadow on the sides, to keep the shadow only on\n    the bottom.\n  */\n  overflow: hidden;\n\n  height: 100px; /* give the shadow some space */\n  pointer-events: none;\n}\n\n:root[data-mantine-color-scheme='light'] .headerRowShadow {\n  --shadow-color: rgba(0, 0, 0, 0.1);\n}\n\n:root[data-mantine-color-scheme='dark'] .headerRowShadow {\n  --shadow-color: rgba(0, 0, 0, 1);\n}\n\n.headerRowShadow::after {\n  content: '';\n\n  width: calc(100% - var(--shadow-size));\n\n  /* If the container has no height, the shadow is not quite visible. Set an arbitrary size */\n  height: 20px;\n  margin: -20px auto 0;\n\n  display: block;\n  animation: table-header-shadow linear forwards;\n  animation-timeline: --dd-tab-scroll-timeline;\n  animation-range: 0 35px; /* The header happens to be 35px tall. It doesn't need to be precise. */\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsListHeader.tsx",
    "content": "import React, { forwardRef } from 'react'\nimport { CloseButton, Flex, Table } from '@mantine/core'\nimport type { FacetRegistry } from '../../../hooks/useEvents'\nimport type { EventListColumn } from './columnUtils'\nimport { removeColumn, getColumnTitle } from './columnUtils'\nimport { AddColumnPopover } from './addColumnPopover'\nimport * as classes from './eventsListHeader.module.css'\n\ninterface Props {\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n  facetRegistry: FacetRegistry\n}\n\nexport const EventsListHeader = forwardRef<HTMLTableRowElement, Props>(\n  ({ columns, onColumnsChange, facetRegistry }, forwardedRef) => (\n    <Table.Thead className={classes.root}>\n      <Table.Tr ref={forwardedRef}>\n        {columns.map((column) => (\n          <ColumnHeader\n            key={column.type === 'field' ? `field-${column.path}` : column.type}\n            columns={columns}\n            column={column}\n            onColumnsChange={onColumnsChange}\n          ></ColumnHeader>\n        ))}\n        <Table.Td className={classes.addColumnCell}>\n          <AddColumnPopover columns={columns} onColumnsChange={onColumnsChange} facetRegistry={facetRegistry} />\n        </Table.Td>\n      </Table.Tr>\n      <div className={classes.headerRowShadow} />\n    </Table.Thead>\n  )\n)\n\nfunction ColumnHeader({\n  columns,\n  column,\n  onColumnsChange,\n}: {\n  columns: EventListColumn[]\n  column: EventListColumn\n  onColumnsChange: (columns: EventListColumn[]) => void\n}) {\n  return (\n    <Table.Th\n      key={column.type === 'field' ? `field-${column.path}` : column.type}\n      data-header-cell\n      className={classes.columnHeader}\n    >\n      <Flex justify=\"space-between\" gap=\"sm\" align=\"center\">\n        {getColumnTitle(column)}\n        <CloseButton size=\"xs\" variant=\"filled\" onClick={() => onColumnsChange(removeColumn(columns, column))} />\n      </Flex>\n    </Table.Th>\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsTab.tsx",
    "content": "import React from 'react'\nimport { Center, Text } from '@mantine/core'\nimport type { EventFilters, FacetRegistry } from '../../../hooks/useEvents'\nimport { TabBase } from '../../tabBase'\nimport type { SdkEvent } from '../../../sdkEvent'\nimport { EventsTabTop } from './eventsTabTop'\nimport { EventsList } from './eventsList'\nimport { EventsTabSide } from './eventsTabSide'\nimport type { EventListColumn } from './columnUtils'\n\ninterface EventsTabProps {\n  events: SdkEvent[]\n  facetRegistry: FacetRegistry | undefined\n  filters: EventFilters\n  onFiltersChange: (filters: EventFilters) => void\n  columns: EventListColumn[]\n  onColumnsChange: (columns: EventListColumn[]) => void\n  clear: () => void\n}\n\nexport function EventsTab({\n  events,\n  facetRegistry,\n  filters,\n  onFiltersChange,\n  columns,\n  onColumnsChange,\n  clear,\n}: EventsTabProps) {\n  return (\n    <TabBase\n      top={<EventsTabTop filters={filters} onFiltersChange={onFiltersChange} clear={clear} />}\n      leftSide={<EventsTabSide filters={filters} onFiltersChange={onFiltersChange} facetRegistry={facetRegistry} />}\n    >\n      {events.length === 0 || !facetRegistry ? (\n        <Center>\n          <Text size=\"xl\" c=\"dimmed\" fw=\"bold\">\n            No events\n          </Text>\n        </Center>\n      ) : (\n        <EventsList\n          events={events}\n          filters={filters}\n          facetRegistry={facetRegistry}\n          columns={columns}\n          onColumnsChange={onColumnsChange}\n        />\n      )}\n    </TabBase>\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsTabSide.tsx",
    "content": "import { Box, Checkbox } from '@mantine/core'\nimport React from 'react'\nimport type { EventFilters, FacetRegistry } from '../../../hooks/useEvents'\nimport { FacetList } from './facetList'\n\nexport function EventsTabSide({\n  facetRegistry,\n  filters,\n  onFiltersChange,\n}: {\n  facetRegistry?: FacetRegistry\n  filters: EventFilters\n  onFiltersChange: (filters: EventFilters) => void\n}) {\n  return (\n    <Box ml=\"md\">\n      <Checkbox\n        label={'Show only the latest View\\xa0event'}\n        checked={!filters.outdatedVersions}\n        onChange={(e) => onFiltersChange({ ...filters, outdatedVersions: !e.target.checked })}\n        mb=\"sm\"\n      />\n\n      {facetRegistry && (\n        <FacetList\n          facetRegistry={facetRegistry}\n          facetValuesFilter={filters.facetValuesFilter}\n          onExcludedFacetValuesChange={(newExcludedFacetValues) =>\n            onFiltersChange({ ...filters, facetValuesFilter: newExcludedFacetValues })\n          }\n        />\n      )}\n    </Box>\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsTabTop.module.css",
    "content": ".textInput {\n  flex-grow: 1;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/eventsTabTop.tsx",
    "content": "import { Button, Group, TextInput } from '@mantine/core'\nimport React from 'react'\nimport { flushEvents } from '../../../flushEvents'\nimport type { EventFilters } from '../../../hooks/useEvents'\nimport * as classes from './eventsTabTop.module.css'\n\nexport function EventsTabTop({\n  filters,\n  onFiltersChange,\n  clear,\n}: {\n  filters: EventFilters\n  onFiltersChange: (filters: EventFilters) => void\n  clear: () => void\n}) {\n  return (\n    <Group className=\"dd-privacy-allow\">\n      <TextInput\n        placeholder=\"Filter your events, syntax: 'type:view application.id:40d8ca4b'\"\n        value={filters.query}\n        className={classes.textInput}\n        onChange={(event) => onFiltersChange({ ...filters, query: event.currentTarget.value })}\n        data-dd-privacy=\"mask\"\n      />\n\n      <Button color=\"violet\" variant=\"light\" onClick={flushEvents}>\n        Flush\n      </Button>\n      <Button color=\"red\" variant=\"light\" onClick={clear}>\n        Clear\n      </Button>\n    </Group>\n  )\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/facetList.module.css",
    "content": ".facetChildren {\n  /* the Mantine checkbox component happen to be 20px wide */\n  --dd-checkbox-width: 20px;\n  /* the Mantine tabs list happen to have a 2px border */\n  --dd-tabs-list-border-width: 2px;\n\n  padding-bottom: var(--mantine-spacing-xs);\n}\n\n.facetChildren:not([data-top-level]) {\n  margin-left: calc((var(--dd-checkbox-width) - var(--dd-tabs-list-border-width)) / 2);\n  padding-left: calc((var(--dd-checkbox-width) - var(--dd-tabs-list-border-width)) / 2);\n  border-left: var(--dd-tabs-list-border-width) solid var(--dd-border-color);\n  border-bottom-left-radius: var(--mantine-radius-md);\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/facetList.tsx",
    "content": "import { Box, Button, Card, Checkbox, Collapse, Flex, Text } from '@mantine/core'\nimport React from 'react'\nimport type { FacetValuesFilter, FacetRegistry } from '../../../hooks/useEvents'\nimport type { Facet, FacetValue } from '../../../facets.constants'\nimport { FACET_ROOT } from '../../../facets.constants'\nimport * as classes from './facetList.module.css'\nimport { computeSelectionState } from './computeFacetState'\n\nexport function FacetList({\n  facetRegistry,\n  facetValuesFilter,\n  onExcludedFacetValuesChange,\n}: {\n  facetRegistry: FacetRegistry\n  facetValuesFilter: FacetValuesFilter\n  onExcludedFacetValuesChange: (newExcludedFacetValues: FacetValuesFilter) => void\n}) {\n  return (\n    <FacetField\n      facet={FACET_ROOT}\n      depth={0}\n      facetRegistry={facetRegistry}\n      facetValuesFilter={facetValuesFilter}\n      onExcludedFacetValuesChange={onExcludedFacetValuesChange}\n      parentList={[]}\n    />\n  )\n}\n\nfunction FacetField({\n  facet,\n  depth,\n  facetRegistry,\n  facetValuesFilter,\n  parentList,\n  onExcludedFacetValuesChange,\n}: {\n  facet: Facet\n  depth: number\n  facetRegistry: FacetRegistry\n  facetValuesFilter: FacetValuesFilter\n  parentList: string[]\n  onExcludedFacetValuesChange: (newExcludedFacetValues: FacetValuesFilter) => void\n}) {\n  const facetValueCounts = facetRegistry.getFacetValueCounts(facet.path)\n\n  return (\n    <Box>\n      {facet.label && (\n        <Text pt=\"xs\" c=\"dimmed\" fw=\"bold\">\n          {facet.label}\n        </Text>\n      )}\n\n      {Array.from(facetValueCounts.entries(), ([facetValue, facetValueCount]) => (\n        <FacetValue\n          key={facetValue}\n          facet={facet}\n          facetValue={facetValue}\n          facetValueCount={facetValueCount}\n          depth={depth}\n          facetRegistry={facetRegistry}\n          facetValuesFilter={facetValuesFilter}\n          parentList={parentList.includes(facetValue) ? parentList : [...parentList, facetValue]}\n          onExcludedFacetValuesChange={onExcludedFacetValuesChange}\n        />\n      ))}\n    </Box>\n  )\n}\n\nconst SPACE_BETWEEN_CHECKBOX = 4 // the smallest size defined by mantine (\"xs\") is 10px, which is a bit too much\n\nfunction FacetValue({\n  facet,\n  facetValue,\n  facetValueCount,\n  depth,\n  facetRegistry,\n  facetValuesFilter,\n  parentList,\n  onExcludedFacetValuesChange,\n}: {\n  facet: Facet\n  facetValue: FacetValue\n  facetValueCount: number\n  depth: number\n  facetRegistry: FacetRegistry\n  facetValuesFilter: FacetValuesFilter\n  parentList: string[]\n  onExcludedFacetValuesChange: (newExcludedFacetValues: FacetValuesFilter) => void\n}) {\n  const isTopLevel = depth === 0\n  const facetSelectState = computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, parentList)\n  const isCollapsed =\n    !facetValuesFilter.facetValues[facet.path] || !facetValuesFilter.facetValues[facet.path].includes(facetValue)\n  const isFiltered =\n    facetValuesFilter.facetValues[facet.path] && facetValuesFilter.facetValues[facet.path].includes(facetValue)\n  const isOnly = facetValuesFilter.type === 'include' && facetSelectState === 'selected'\n  const value = (\n    <Flex justify=\"space-between\" mt={isTopLevel ? 'xs' : SPACE_BETWEEN_CHECKBOX}>\n      <Checkbox\n        label={facet.values?.[facetValue]?.label ?? facetValue}\n        checked={facetSelectState === 'selected'}\n        indeterminate={facetSelectState === 'partial-selected'} // can only populate direct parents\n        onChange={() => {\n          const filterType = facetSelectState === 'selected' ? 'exclude' : 'include'\n          onExcludedFacetValuesChange(toggleFacetValue(filterType, facet, facetValuesFilter, facetValue))\n        }}\n      />\n      <Text>{facetValueCount}</Text>\n      <Button\n        variant={isOnly ? 'filled' : 'light'}\n        size=\"compact-xs\"\n        w=\"40px\"\n        onClick={() => {\n          const filterType = isOnly ? 'exclude' : 'include'\n          onExcludedFacetValuesChange(toggleFacetValue(filterType, facet, facetValuesFilter, facetValue))\n        }}\n      >\n        {isOnly ? 'all' : 'only'}\n      </Button>\n    </Flex>\n  )\n\n  const childFacets = facet.values?.[facetValue]?.facets\n  const children = childFacets && (\n    <Collapse expanded={isCollapsed || isOnly}>\n      <Box className={classes.facetChildren} data-top-level={isTopLevel ? true : undefined}>\n        {childFacets.map((facet) => (\n          <FacetField\n            key={facet.path}\n            facet={facet}\n            facetRegistry={facetRegistry}\n            depth={depth + 1}\n            facetValuesFilter={facetValuesFilter}\n            parentList={parentList.includes(facetValue) ? parentList : [...parentList, facetValue]}\n            onExcludedFacetValuesChange={onExcludedFacetValuesChange}\n          />\n        ))}\n      </Box>\n    </Collapse>\n  )\n\n  if (isTopLevel) {\n    return (\n      <Card shadow=\"sm\" padding=\"sm\" radius=\"md\" withBorder mb=\"md\">\n        <Card.Section withBorder={isFiltered} inheritPadding pb=\"xs\">\n          {value}\n        </Card.Section>\n        <Card.Section inheritPadding>{children}</Card.Section>\n      </Card>\n    )\n  }\n\n  return (\n    <>\n      {value}\n      {children}\n    </>\n  )\n}\n\nfunction toggleFacetValue(\n  type: 'include' | 'exclude',\n  facet: Facet,\n  facetValuesFilter: FacetValuesFilter,\n  value: FacetValue\n): FacetValuesFilter {\n  const currentValues = facetValuesFilter.facetValues[facet.path]\n  const newFacetValues = { ...facetValuesFilter.facetValues }\n\n  if (facetValuesFilter.type !== type) {\n    // handle mode changes\n    if (type === 'exclude') {\n      // reset when change from include to exclude\n      return {\n        type,\n        facetValues: {},\n      }\n    } else if (type === 'include' && currentValues) {\n      // should maintain one and only filter when change from exclude to include\n      return {\n        type,\n        facetValues: currentValues.includes(value) ? newFacetValues : { [facet.path]: [value] },\n      }\n    }\n  }\n\n  if (!currentValues) {\n    // Add exclusion or inclusion. Nothing was excluded yet, create a new list\n    newFacetValues[facet.path] = [value]\n  } else if (!currentValues.includes(value)) {\n    // Add exclusion or inclusion. Some other values are already added, add it to the list\n    newFacetValues[facet.path] = currentValues.concat(value)\n  } else if (currentValues.length === 1) {\n    // Remove exclusion or inclusion. If it's the only value, delete the list altogether.\n    delete newFacetValues[facet.path]\n  } else {\n    // Remove exclusion or inclusion. Filter out the the value from the existing list.\n    newFacetValues[facet.path] = currentValues.filter((other) => other !== value)\n  }\n\n  return { type, facetValues: newFacetValues }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/index.ts",
    "content": "export { EventsTab } from './eventsTab'\nexport { DEFAULT_COLUMNS } from './columnUtils'\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/rowButton.module.css",
    "content": ".root {\n  display: flex;\n  margin: -4px 0 -4px;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/eventsTab/rowButton.tsx",
    "content": "import type { ActionIconProps, PolymorphicComponentProps } from '@mantine/core'\nimport { ActionIcon } from '@mantine/core'\nimport { default as clsx } from 'clsx'\nimport type { JSXElementConstructor } from 'react'\nimport React, { forwardRef } from 'react'\nimport * as classes from './rowButton.module.css'\n\ntype RowButtonProps = Omit<PolymorphicComponentProps<'button', ActionIconProps>, 'children'> & {\n  icon: JSXElementConstructor<{ size: number; strokeWidth: number }>\n}\n\nexport const RowButton = forwardRef<HTMLButtonElement, RowButtonProps>((props, ref) => (\n  <ActionIcon ref={ref} {...props} variant=\"light\" size=\"md\" className={clsx(classes.root, props.className)}>\n    <props.icon size={20} strokeWidth={1.5} />\n  </ActionIcon>\n))\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/infosTab.tsx",
    "content": "import { Anchor, Button, Divider, Group, JsonInput, Space, Text } from '@mantine/core'\nimport type { ReactNode } from 'react'\nimport React, { useState } from 'react'\nimport { evalInWindow } from '../../evalInWindow'\nimport { useSdkInfos } from '../../hooks/useSdkInfos'\nimport { Columns } from '../columns'\nimport type { JsonValueDescriptor } from '../json'\nimport { Json } from '../json'\nimport { TabBase } from '../tabBase'\nimport { createLogger } from '../../../common/logger'\nimport { formatDate } from '../../formatNumber'\nimport { useSettings } from '../../hooks/useSettings'\n\nconst logger = createLogger('infosTab')\n\nfunction buildLogExpression(descriptor: JsonValueDescriptor, sdkType: 'rum' | 'logs'): string {\n  const evaluationPath = descriptor.evaluationPath\n  const sdkGlobal = sdkType === 'rum' ? 'DD_RUM' : 'DD_LOGS'\n  const sdkName = sdkType === 'rum' ? 'RUM' : 'Logs'\n\n  return `\n    (function() {\n      const config = window.${sdkGlobal}?.getInitConfiguration?.();\n      if (!config) {\n        console.warn('[${sdkName}] SDK not found');\n        return;\n      }\n      \n      // Navigate the path to get the value\n      let value = config;\n      const pathParts = '${evaluationPath}'.split('.');\n      \n      for (const key of pathParts) {\n        if (!value || typeof value !== 'object') {\n          console.warn('[${sdkName}] Property not found at path: ${evaluationPath}');\n          return;\n        }\n        \n        // Handle array indices (numeric keys)\n        if (Array.isArray(value)) {\n          const index = parseInt(key, 10);\n          if (isNaN(index) || index < 0 || index >= value.length) {\n            console.warn('[${sdkName}] Invalid array index at path: ${evaluationPath}');\n            return;\n          }\n          value = value[index];\n        } else {\n          if (!(key in value)) {\n            console.warn('[${sdkName}] Property not found at path: ${evaluationPath}');\n            return;\n          }\n          value = value[key];\n        }\n      }\n      \n      console.log('[${sdkName}] ${evaluationPath}:', value);\n    })()\n  `\n}\n\nfunction createRevealFunctionLocation(sdkType: 'rum' | 'logs') {\n  return (descriptor: JsonValueDescriptor) => {\n    const logExpression = buildLogExpression(descriptor, sdkType)\n\n    evalInWindow(logExpression).catch((error) => {\n      logger.error('Failed to log function:', error)\n    })\n  }\n}\n\nexport function InfosTab() {\n  const infos = useSdkInfos()\n  const [settings, setSetting] = useSettings()\n\n  if (!infos) {\n    return null\n  }\n\n  const sessionId = infos.cookie?.id\n  const { rumTrackingType, logsTrackingType } = infos\n\n  return (\n    <TabBase>\n      <Columns>\n        <Columns.Column title=\"Session\">\n          {infos.cookie && (\n            <>\n              <Entry name=\"Id\" value={infos.cookie.id} />\n              <Entry\n                name=\"Logs\"\n                value={logsTrackingType && formatSessionType(logsTrackingType, 'Not tracked', 'Tracked')}\n              />\n              <Entry\n                name=\"RUM\"\n                value={\n                  rumTrackingType &&\n                  formatSessionType(\n                    rumTrackingType,\n                    'Not tracked',\n                    'Tracked with Session Replay',\n                    'Tracked without Session Replay'\n                  )\n                }\n              />\n              {infos.cookie.forcedReplay && <Entry name=\"Is Replay Forced\" value={'True'} />}\n              <Entry name=\"Created\" value={infos.cookie.created && formatDate(Number(infos.cookie.created))} />\n              <Entry name=\"Expire\" value={infos.cookie.expire && formatDate(Number(infos.cookie.expire))} />\n              <Button color=\"violet\" variant=\"light\" onClick={endSession} className=\"dd-privacy-allow\">\n                End current session\n              </Button>\n            </>\n          )}\n        </Columns.Column>\n        <Columns.Column title=\"RUM\">\n          {infos.rum && (\n            <>\n              {sessionId && (\n                <Group className=\"dd-privacy-allow\">\n                  <AppLink\n                    config={infos.rum.config}\n                    path=\"rum/explorer\"\n                    params={{\n                      query: `@session.id:${sessionId}`,\n                      live: 'true',\n                    }}\n                  >\n                    Explorer\n                  </AppLink>\n                  <Divider orientation=\"vertical\" />\n                  <AppLink config={infos.rum.config} path={`rum/replay/sessions/${sessionId}`} params={{}}>\n                    Session Replay\n                  </AppLink>\n                </Group>\n              )}\n              <Entry name=\"Version\" value={infos.rum.version} />\n              <Entry\n                name=\"Configuration\"\n                value={infos.rum.config}\n                onChange={(value) => {\n                  setSetting('rumConfigurationOverride', value)\n                }}\n                isOverridden={!!settings.rumConfigurationOverride}\n                onRevealFunctionLocation={createRevealFunctionLocation('rum')}\n              />\n              <Entry name=\"Internal context\" value={infos.rum.internalContext} />\n              <Entry name=\"Global context\" value={infos.rum.globalContext} />\n              <Entry name=\"User\" value={infos.rum.user} />\n            </>\n          )}\n        </Columns.Column>\n        <Columns.Column title=\"Logs\">\n          {infos.logs && (\n            <>\n              {sessionId && (\n                <div className=\"dd-privacy-allow\">\n                  <AppLink\n                    config={infos.logs.config}\n                    path=\"logs\"\n                    params={{\n                      query: `source:browser @session_id:${sessionId}`,\n                    }}\n                  >\n                    Explorer\n                  </AppLink>\n                </div>\n              )}\n              <Entry name=\"Version\" value={infos.logs.version} />\n              <Entry\n                name=\"Configuration\"\n                value={infos.logs.config}\n                onChange={(value) => {\n                  setSetting('logsConfigurationOverride', value)\n                }}\n                isOverridden={!!settings.logsConfigurationOverride}\n                onRevealFunctionLocation={createRevealFunctionLocation('logs')}\n              />\n              <Entry name=\"Global context\" value={infos.logs.globalContext} />\n              <Entry name=\"User\" value={infos.logs.user} />\n            </>\n          )}\n        </Columns.Column>\n      </Columns>\n    </TabBase>\n  )\n}\n\nfunction AppLink({\n  config,\n  path,\n  params,\n  children,\n}: {\n  config?: { site?: string }\n  path: string\n  params: { [key: string]: string }\n  children: ReactNode\n}) {\n  const site = config?.site ?? 'datadoghq.com'\n  const hostname = site === 'datadoghq.com' ? 'app.datadoghq.com' : site === 'datad0g.com' ? 'dd.datad0g.com' : site\n  return (\n    <Anchor href={`https://${hostname}/${path}?${new URLSearchParams(params).toString()}`} target=\"_blank\">\n      {children}\n    </Anchor>\n  )\n}\n\nfunction Entry({\n  name,\n  value,\n  isOverridden = false,\n  onChange,\n  onRevealFunctionLocation,\n}: {\n  name: string\n  value: any\n  isOverridden?: boolean\n  onChange?: (value: object | null) => void\n  onRevealFunctionLocation?: (descriptor: JsonValueDescriptor) => void\n}) {\n  const [edited, setEdited] = useState(false)\n  const [newValue, setNewValue] = React.useState<string | null>()\n\n  const handleApplyClick = () => {\n    const valueJson = newValue ? tryParseJson(newValue) : null\n    if (onChange && valueJson !== false) {\n      onChange(valueJson)\n      setEdited(false)\n      reloadPage()\n    }\n  }\n\n  const handleClearClick = () => {\n    onChange?.(null)\n    reloadPage()\n  }\n\n  const handleEditClick = () => {\n    setEdited(true)\n    setNewValue(serializeJson(value))\n  }\n  return (\n    <Text component=\"div\">\n      {typeof value === 'string' ? (\n        <>\n          <EntryName>{name}: </EntryName> {value}\n        </>\n      ) : value ? (\n        <>\n          <div style={{ display: 'inline-flex', gap: '5px', alignItems: 'center' }}>\n            <EntryName>{name}: </EntryName>\n            {onChange && (\n              <>\n                {!edited ? (\n                  <>\n                    <Button variant=\"light\" size=\"compact-xs\" onClick={handleEditClick}>\n                      Edit\n                    </Button>\n                    {isOverridden && (\n                      <Button variant=\"light\" size=\"compact-xs\" onClick={handleClearClick}>\n                        Clear\n                      </Button>\n                    )}\n                  </>\n                ) : (\n                  <>\n                    <Button variant=\"light\" size=\"compact-xs\" onClick={handleApplyClick} className=\"dd-privacy-allow\">\n                      Apply\n                    </Button>\n                    <Button\n                      variant=\"light\"\n                      size=\"compact-xs\"\n                      color=\"gray\"\n                      onClick={() => setEdited(false)}\n                      className=\"dd-privacy-allow\"\n                    >\n                      Cancel\n                    </Button>\n                  </>\n                )}\n              </>\n            )}\n          </div>\n          {!edited ? (\n            <Json value={value} onRevealFunctionLocation={onRevealFunctionLocation} />\n          ) : (\n            <JsonInput\n              style={{ marginTop: '5px' }}\n              validationError=\"Invalid JSON\"\n              formatOnBlur\n              autosize\n              minRows={4}\n              value={newValue ?? ''}\n              onChange={setNewValue}\n              serialize={serializeJson}\n            />\n          )}\n        </>\n      ) : (\n        <>\n          <EntryName>{name}: </EntryName>(empty)\n        </>\n      )}\n      <Space h=\"xs\" />\n    </Text>\n  )\n}\n\nfunction EntryName({ children }: { children: ReactNode }) {\n  return (\n    <Text component=\"span\" size=\"md\" fw={500}>\n      {children}\n    </Text>\n  )\n}\n\nfunction formatSessionType(value: string, ...labels: string[]) {\n  const index = Number(value)\n  return !isNaN(index) && index >= 0 && index < labels.length ? labels[index] : value\n}\n\nfunction endSession() {\n  const fourHours = 1000 * 60 * 60 * 4\n  const expires = new Date(Date.now() + fourHours).toUTCString()\n\n  evalInWindow(\n    `\n      document.cookie = '_dd_s=isExpired=1; expires=${expires}; path=/'\n    `\n  ).catch((error) => logger.error('Error while ending session:', error))\n}\n\nfunction reloadPage() {\n  evalInWindow('window.location.reload()').catch((error) => logger.error('Error while reloading the page:', error))\n}\n\nfunction tryParseJson(value: string) {\n  try {\n    return JSON.parse(value) as { [key: string]: any }\n  } catch {\n    return false\n  }\n}\n\nfunction serializeJson(value: object) {\n  // replacer to remove function attributes that have been serialized with metadata by useSdkInfos() (ex: beforeSend)\n  const replacer = (key: string, val: unknown) => {\n    // Filter out function metadata objects\n    if (key !== '' && !Array.isArray(val) && typeof val === 'object' && val && (val as any).__type === 'function') {\n      return undefined\n    }\n    return val\n  }\n\n  return JSON.stringify(value, replacer, 2)\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/replayTab.module.css",
    "content": ".iframe {\n  height: 100%;\n  width: 100%;\n  border: none;\n  display: block;\n}\n\n.iframe:not([data-status='ready']) {\n  display: none;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/replayTab.tsx",
    "content": "import { Button, Flex, Checkbox, Badge } from '@mantine/core'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { TabBase } from '../tabBase'\nimport type { SessionReplayPlayerState } from '../../sessionReplayPlayer/startSessionReplayPlayer'\nimport { startSessionReplayPlayer } from '../../sessionReplayPlayer/startSessionReplayPlayer'\nimport { evalInWindow } from '../../evalInWindow'\nimport { createLogger } from '../../../common/logger'\nimport { Alert } from '../alert'\nimport { useSdkInfos } from '../../hooks/useSdkInfos'\nimport { useSettings } from '../../hooks/useSettings'\nimport * as classes from './replayTab.module.css'\n\nconst logger = createLogger('replayTab')\n\nexport function ReplayTab() {\n  const infos = useSdkInfos()\n  if (!infos) {\n    return <Alert level=\"error\" message=\"No RUM SDK present in the page.\" />\n  }\n\n  const { rumTrackingType } = infos\n\n  if (!rumTrackingType) {\n    return <Alert level=\"error\" message=\"No RUM session.\" />\n  }\n\n  if (rumTrackingType === '0') {\n    return <Alert level=\"error\" message=\"RUM session sampled out.\" />\n  }\n\n  if (rumTrackingType === '2' && infos.cookie?.forcedReplay !== '1') {\n    return <Alert level=\"error\" message=\"RUM session plan does not include replay.\" />\n  }\n\n  return <Player />\n}\n\nfunction Player() {\n  const [{ useDevReplaySandbox }] = useSettings()\n  const frameRef = useRef<HTMLIFrameElement | null>(null)\n  const [playerState, setPlayerState] = useState<SessionReplayPlayerState>({\n    status: 'loading',\n    recordCount: 0,\n    excludeMouseMovements: false,\n  })\n  const playerRef = useRef<ReturnType<typeof startSessionReplayPlayer>>(null)\n\n  useEffect(() => {\n    playerRef.current = startSessionReplayPlayer(frameRef.current!, setPlayerState, useDevReplaySandbox)\n    return () => playerRef.current?.stop()\n  }, [useDevReplaySandbox])\n\n  const downloadRecords = () => {\n    if (!playerRef.current?.getRecords) {\n      return\n    }\n\n    const records = playerRef.current.getRecords()\n    // Create a segment that contains enough information to be compatible with the Replay Playground Static App\n    const segment = { records, source: 'browser', records_count: records.length, view: { id: 'xxx' } }\n    const segmentStr = JSON.stringify(segment, null, 2)\n    const dataUri = `data:application/json;charset=utf-8,${encodeURIComponent(segmentStr)}`\n\n    const downloadLink = document.createElement('a')\n    downloadLink.setAttribute('href', dataUri)\n    downloadLink.setAttribute('download', `session-replay-records-${Date.now()}.json`)\n    document.body.appendChild(downloadLink)\n    downloadLink.click()\n    document.body.removeChild(downloadLink)\n  }\n\n  return (\n    <TabBase\n      top={\n        <Flex>\n          <Flex justify=\"space-between\" align=\"center\" flex=\"1\">\n            <Flex align=\"center\" gap=\"md\">\n              <Button onClick={generateFullSnapshot} color=\"orange\">\n                Force Full Snapshot\n              </Button>\n              <Checkbox\n                label=\"Exclude mouse movements\"\n                checked={playerState.excludeMouseMovements}\n                onChange={(event) => playerRef.current?.setExcludeMouseMovements(event.currentTarget.checked)}\n              />\n            </Flex>\n            <Flex align=\"center\" gap=\"xs\">\n              <div>Records applied: {playerState.recordCount}</div>\n              <Button\n                onClick={downloadRecords}\n                variant=\"subtle\"\n                disabled={playerState.recordCount === 0}\n                title=\"Download records as JSON\"\n                p=\"xs\"\n              >\n                📥\n              </Button>\n            </Flex>\n          </Flex>\n          <Flex align=\"center\">{useDevReplaySandbox ? <Badge color=\"blue\">Dev</Badge> : <></>}</Flex>\n        </Flex>\n      }\n    >\n      <iframe ref={frameRef} className={classes.iframe} data-status={playerState.status} />\n      {playerState.status === 'waiting-for-full-snapshot' && <WaitingForFullSnapshot />}\n    </TabBase>\n  )\n}\n\nfunction WaitingForFullSnapshot() {\n  return (\n    <Alert\n      level=\"warning\"\n      message=\"⚠️ Waiting for a full snapshot to be generated. Navigate to another view, or press the button above to force a full snapshot.\"\n    />\n  )\n}\n\nfunction generateFullSnapshot() {\n  // Restart to make sure we have a fresh Full Snapshot\n  evalInWindow(`\n    DD_RUM.stopSessionReplayRecording()\n    DD_RUM.startSessionReplayRecording({ force: true })\n  `).catch((error) => {\n    logger.error('While restarting recording:', error)\n  })\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/settingsTab.module.css",
    "content": ".select {\n  flex: 1;\n}\n"
  },
  {
    "path": "developer-extension/src/panel/components/tabs/settingsTab.tsx",
    "content": "import { Badge, Box, Checkbox, Code, Group, Space, Switch, Text, SegmentedControl, Accordion } from '@mantine/core'\nimport React from 'react'\nimport { DEV_LOGS_URL, DEV_REPLAY_SANDBOX_URL } from '../../../common/packagesUrlConstants'\nimport { DevServerStatus, useDevServerStatus } from '../../hooks/useDevServerStatus'\nimport { useSettings } from '../../hooks/useSettings'\nimport { Columns } from '../columns'\nimport { TabBase } from '../tabBase'\nimport type { DevBundlesOverride, EventCollectionStrategy } from '../../../common/extension.types'\n\nexport function SettingsTab() {\n  const sdkDevServerStatus = useDevServerStatus(DEV_LOGS_URL)\n  const replayDevServerStatus = useDevServerStatus(DEV_REPLAY_SANDBOX_URL)\n  const [\n    {\n      useDevBundles,\n      useDevReplaySandbox,\n      useRumSlim,\n      blockIntakeRequests,\n      preserveEvents,\n      eventCollectionStrategy,\n      autoFlush,\n      debugMode: debug,\n      datadogMode,\n    },\n    setSetting,\n  ] = useSettings()\n\n  return (\n    <TabBase>\n      <div className=\"dd-privacy-allow\">\n        <Columns>\n          <Columns.Column title=\"Overrides\">\n            <Accordion defaultValue=\"browser-sdk\">\n              <Accordion.Item key=\"browser-sdk\" value=\"browser-sdk\">\n                <Accordion.Control>\n                  <Group>\n                    <Text>Browser SDK</Text>\n                    <Box style={{ marginLeft: 'auto' }}>\n                      {sdkDevServerStatus === DevServerStatus.AVAILABLE && useDevBundles ? (\n                        <Badge color=\"blue\">Overridden</Badge>\n                      ) : sdkDevServerStatus === DevServerStatus.AVAILABLE ? (\n                        <Badge color=\"green\">Available</Badge>\n                      ) : sdkDevServerStatus === DevServerStatus.CHECKING ? (\n                        <Badge color=\"yellow\">Checking...</Badge>\n                      ) : (\n                        <Badge color=\"red\">Unavailable</Badge>\n                      )}\n                    </Box>\n                  </Group>\n                </Accordion.Control>\n                <Accordion.Panel>\n                  <Box>\n                    Use the local development version of the browser SDK. The development server must be running; to\n                    start it, run <Code>yarn dev</Code>.\n                  </Box>\n\n                  <Space h=\"md\" />\n\n                  <SettingItem\n                    input={\n                      <Group>\n                        <Text>Override strategy:</Text>\n                        <SegmentedControl\n                          color=\"violet\"\n                          value={useDevBundles || 'off'}\n                          size=\"xs\"\n                          data={[\n                            { value: 'off', label: 'Off' },\n                            { value: 'cdn', label: 'Redirect' },\n                            { value: 'npm', label: 'Inject' },\n                          ]}\n                          onChange={(value) =>\n                            setSetting('useDevBundles', value === 'off' ? false : (value as DevBundlesOverride))\n                          }\n                        />\n                      </Group>\n                    }\n                    description={\n                      <>\n                        Choose an override strategy. Network request redirection is reliable, but only works for CDN\n                        setups. Injecting the bundle into the page can work for both CDN and NPM setups, but it's not\n                        always reliable.\n                      </>\n                    }\n                  />\n\n                  <SettingItem\n                    input={\n                      <Group>\n                        <Text>SDK variant:</Text>\n                        <SegmentedControl\n                          color=\"violet\"\n                          value={useRumSlim ? 'rum-slim' : 'rum'}\n                          size=\"xs\"\n                          data={[\n                            { value: 'rum', label: 'RUM' },\n                            { value: 'rum-slim', label: 'RUM Slim' },\n                          ]}\n                          onChange={(value) => {\n                            setSetting('useRumSlim', value === 'rum-slim')\n                          }}\n                        />\n                      </Group>\n                    }\n                    description={<>Choose an SDK variant. Session replay features won't work with the slim version.</>}\n                  />\n                </Accordion.Panel>\n              </Accordion.Item>\n\n              {datadogMode && (\n                <Accordion.Item key=\"replay-sandbox\" value=\"replay-sandbox\">\n                  <Accordion.Control>\n                    <Group>\n                      <Text>Live replay</Text>\n                      <Box style={{ marginLeft: 'auto' }}>\n                        {replayDevServerStatus === DevServerStatus.AVAILABLE && useDevReplaySandbox ? (\n                          <Badge color=\"blue\">Overridden</Badge>\n                        ) : replayDevServerStatus === DevServerStatus.AVAILABLE ? (\n                          <Badge color=\"green\">Available</Badge>\n                        ) : replayDevServerStatus === DevServerStatus.CHECKING ? (\n                          <Badge color=\"yellow\">Checking...</Badge>\n                        ) : (\n                          <Badge color=\"red\">Unavailable</Badge>\n                        )}\n                      </Box>\n                    </Group>\n                  </Accordion.Control>\n                  <Accordion.Panel>\n                    <Box>\n                      Use the Datadog-internal local development version of the live replay sandbox. The development\n                      server must be running; to start it, run\n                      <Code>yarn dev</Code>.\n                    </Box>\n\n                    <Space h=\"md\" />\n\n                    <SettingItem\n                      input={\n                        <Switch\n                          label=\"Override the live replay sandbox\"\n                          checked={!!useDevReplaySandbox}\n                          onChange={(event) => setSetting('useDevReplaySandbox', event.currentTarget.checked)}\n                          color=\"violet\"\n                        />\n                      }\n                      description={<>Activate to use the local development version of the live replay sandbox.</>}\n                    />\n                  </Accordion.Panel>\n                </Accordion.Item>\n              )}\n\n              <Accordion.Item key=\"intake-requests\" value=\"intake-requests\">\n                <Accordion.Control>\n                  <Group>\n                    <Text>Intake requests</Text>\n                    <Box style={{ marginLeft: 'auto' }}>\n                      {blockIntakeRequests ? <Badge color=\"blue\">Blocked</Badge> : <Badge color=\"green\">Allowed</Badge>}\n                    </Box>\n                  </Group>\n                </Accordion.Control>\n                <Accordion.Panel>\n                  <SettingItem\n                    input={\n                      <Switch\n                        label=\"Block intake requests\"\n                        checked={blockIntakeRequests}\n                        onChange={(event) => setSetting('blockIntakeRequests', event.currentTarget.checked)}\n                        color=\"violet\"\n                      />\n                    }\n                    description={\n                      <>Block requests made to the intake, preventing any data from being sent to Datadog.</>\n                    }\n                  />\n                </Accordion.Panel>\n              </Accordion.Item>\n            </Accordion>\n          </Columns.Column>\n\n          <Columns.Column title=\"Events list\">\n            <SettingItem\n              input={\n                <Checkbox\n                  label=\"Preserve events\"\n                  checked={preserveEvents}\n                  onChange={(e) => setSetting('preserveEvents', isChecked(e.target))}\n                  color=\"violet\"\n                />\n              }\n              description={<>Don't clear events when reloading the page or navigating away.</>}\n            />\n\n            <SettingItem\n              input={\n                <Group>\n                  <Text>Event collection strategy:</Text>\n                  <SegmentedControl\n                    color=\"violet\"\n                    value={eventCollectionStrategy}\n                    size=\"xs\"\n                    data={[\n                      { label: 'SDK', value: 'sdk' },\n                      { label: 'Requests', value: 'requests' },\n                    ]}\n                    onChange={(value) => setSetting('eventCollectionStrategy', value as EventCollectionStrategy)}\n                  />\n                </Group>\n              }\n              description={\n                <>\n                  {eventCollectionStrategy === 'requests' && (\n                    <>\n                      Collect events by listening to intake HTTP requests: events need to be flushed to be collected.\n                      Any SDK setup is supported.\n                    </>\n                  )}\n                  {eventCollectionStrategy === 'sdk' && (\n                    <>\n                      Collect events by listening to messages sent from the SDK: events are available as soon as they\n                      happen. Only newer versions of the SDK are supported.\n                    </>\n                  )}\n                </>\n              }\n            />\n\n            <SettingItem\n              input={\n                <Checkbox\n                  label=\"Auto Flush\"\n                  checked={autoFlush}\n                  onChange={(e) => setSetting('autoFlush', isChecked(e.target))}\n                  color=\"violet\"\n                />\n              }\n              description={<>Force the SDK to flush events periodically.</>}\n            />\n          </Columns.Column>\n          <Columns.Column title=\"Other\">\n            <SettingItem\n              input={\n                <Checkbox\n                  label=\"Debug mode\"\n                  checked={debug}\n                  onChange={(e) => setSetting('debugMode', isChecked(e.target))}\n                  color=\"violet\"\n                />\n              }\n              description={<>Enable the SDK logs in the developer console</>}\n            />\n            <SettingItem\n              input={\n                <Checkbox\n                  label=\"Datadog employee mode\"\n                  checked={datadogMode}\n                  onChange={(e) => setSetting('datadogMode', isChecked(e.target))}\n                  color=\"violet\"\n                />\n              }\n              description={<>Enable Datadog-internal debugging features</>}\n            />\n          </Columns.Column>\n        </Columns>\n      </div>\n    </TabBase>\n  )\n}\n\nfunction SettingItem({ description, input }: { description?: React.ReactNode; input: React.ReactNode }) {\n  return (\n    <Box>\n      {input}\n      {description && <Text c=\"dimmed\">{description}</Text>}\n      <Space h=\"md\" />\n    </Box>\n  )\n}\n\nfunction isChecked(target: EventTarget) {\n  return target instanceof HTMLInputElement && target.checked\n}\n"
  },
  {
    "path": "developer-extension/src/panel/copy.ts",
    "content": "export function copy(text: string) {\n  // Unfortunately, navigator.clipboard.writeText does not seem to work in extensions\n  const container = document.createElement('textarea')\n  container.innerHTML = text\n  document.body.appendChild(container)\n  container.select()\n  document.execCommand('copy')\n  document.body.removeChild(container)\n}\n"
  },
  {
    "path": "developer-extension/src/panel/evalInWindow.ts",
    "content": "export function evalInWindow(code: string): Promise<unknown> {\n  return new Promise((resolve, reject) => {\n    chrome.devtools.inspectedWindow.eval(`(() => { ${code} })()`, (result, exceptionInfo) => {\n      if (exceptionInfo) {\n        if (exceptionInfo.isError) {\n          reject(\n            Object.assign(\n              new Error(`DevTools error while evaluating code: [${exceptionInfo.code}] ${exceptionInfo.description}`),\n              {\n                details: exceptionInfo.details,\n              }\n            )\n          )\n        } else if (exceptionInfo.isException) {\n          reject(new Error(`Failed to evaluate code: ${exceptionInfo.value}`))\n        }\n      } else {\n        resolve(result)\n      }\n    })\n  })\n}\n"
  },
  {
    "path": "developer-extension/src/panel/facets.constants.ts",
    "content": "// Represents the path of a field in an event object. The special value '$eventSource' represent the\n// event source (rum, logs, ...)\nexport type FieldPath = string\nexport type FieldValue = string | number | null | boolean | Record<string, unknown>\nexport type FieldMultiValue = FieldValue | FieldValue[]\n\n// For now, facet values are only strings (we don't support number pickers etc.)\nexport type FacetValue = string\n\nexport interface Facet {\n  path: string\n  label?: string\n  values?: {\n    [value: FacetValue]:\n      | {\n          label?: string\n          facets?: Facet[]\n        }\n      | undefined\n  }\n}\n\nexport const FACET_ROOT: Facet = {\n  path: '$eventSource',\n  values: {\n    rum: {\n      label: 'RUM',\n      facets: [\n        {\n          path: 'type',\n          label: 'Type',\n          values: {\n            action: {\n              facets: [\n                {\n                  path: 'action.type',\n                  label: 'Action Type',\n                },\n              ],\n            },\n            error: {\n              facets: [\n                {\n                  path: 'error.source',\n                  label: 'Error Source',\n                },\n              ],\n            },\n            resource: {\n              facets: [\n                {\n                  path: 'resource.type',\n                  label: 'Resource Type',\n                },\n              ],\n            },\n          },\n        },\n      ],\n    },\n    logs: {\n      label: 'Logs',\n      facets: [\n        {\n          path: 'status',\n          label: 'Status',\n        },\n\n        {\n          path: 'origin',\n          label: 'Origin',\n        },\n      ],\n    },\n    telemetry: {\n      label: 'Telemetry',\n      facets: [\n        {\n          path: 'telemetry.type',\n          label: 'Type',\n        },\n        {\n          path: 'telemetry.status',\n          label: 'Status',\n        },\n      ],\n    },\n  },\n}\n"
  },
  {
    "path": "developer-extension/src/panel/flushEvents.spec.ts",
    "content": "import type { Configuration } from '@datadog/browser-core'\nimport { registerCleanupTask } from '../../../packages/core/test'\nimport type { PageMayExitEvent } from '../../../packages/core/src/browser/pageMayExitObservable'\nimport { createPageMayExitObservable } from '../../../packages/core/src/browser/pageMayExitObservable'\nimport { flushScript } from './flushEvents'\n\ndescribe('flushEvents', () => {\n  let onExitSpy: jasmine.Spy<(event: PageMayExitEvent) => void>\n  let configuration: Configuration\n\n  beforeEach(() => {\n    onExitSpy = jasmine.createSpy()\n    configuration = {} as Configuration\n    registerCleanupTask(createPageMayExitObservable(configuration).subscribe(onExitSpy).unsubscribe)\n  })\n\n  it('flushes when the flush scripts evaluated', () => {\n    // evalInWindow() uses extension APIs that are not available in the test environment\n    // eslint-disable-next-line no-eval\n    eval(flushScript)\n    expect(onExitSpy).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "developer-extension/src/panel/flushEvents.ts",
    "content": "import { createLogger } from '../common/logger'\nimport { evalInWindow } from './evalInWindow'\n\nconst logger = createLogger('flushEvents')\nexport const flushScript = `\nconst descriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState');\nObject.defineProperty(Document.prototype, 'visibilityState', { value: 'hidden' });\nconst hiddenEvent = new Event('visibilitychange', { bubbles: true});\nhiddenEvent.__ddIsTrusted = true;\ndocument.dispatchEvent(hiddenEvent);\nObject.defineProperty(Document.prototype, 'visibilityState', descriptor);\ndocument.dispatchEvent(new Event('visibilitychange', { bubbles: true }));\n`\nexport function flushEvents() {\n  evalInWindow(flushScript).catch((error) => {\n    logger.error('Error while flushing events:', error)\n  })\n}\n"
  },
  {
    "path": "developer-extension/src/panel/formatNumber.ts",
    "content": "const LOCALE = 'en-US'\n\nexport function formatNumber(n: number): string {\n  if (isNaN(n)) {\n    return '(NaN)'\n  }\n  return new Intl.NumberFormat(LOCALE, {}).format(n)\n}\n\nexport function formatDuration(ns: number): string {\n  if (isNaN(ns)) {\n    return '(NaN)'\n  }\n  return new Intl.NumberFormat(LOCALE, { style: 'unit', unit: 'millisecond' }).format(ns / 1_000_000)\n}\n\nexport function formatDate(ms: number): string {\n  if (isNaN(ms)) {\n    return '(NaN)'\n  }\n  const date = new Date(ms)\n  const now = new Date()\n  const isSameDay =\n    now.getDate() === date.getDate() && now.getMonth() === date.getMonth() && now.getFullYear() === date.getFullYear()\n\n  return new Intl.DateTimeFormat(LOCALE, {\n    dateStyle: isSameDay ? undefined : 'medium',\n    timeStyle: 'medium',\n    hour12: false, // slightly more compact date\n  })\n    .formatToParts(date)\n    .map(({ type, value }) => {\n      if (type === 'second') {\n        // Add milliseconds to the formatted date\n        value += `.${new Intl.DateTimeFormat(LOCALE, {\n          fractionalSecondDigits: 3,\n        } as Intl.DateTimeFormatOptions).format(date)}`\n      }\n      return value\n    })\n    .join('')\n}\n"
  },
  {
    "path": "developer-extension/src/panel/global.css",
    "content": ":root {\n  /* To keep z-index management simple, define all z-index values here, in ascending order */\n  --dd-json-z-index: 0;\n  --dd-events-list-header-z-index: 1;\n  --dd-column-drag-ghost-z-index: 2;\n}\n\n/*\n * Define the main border color to be used across the extension. It should match the color used by\n * Mantine, for example in the tabs component:\n * https://github.com/mantinedev/mantine/blob/4b62fcc54bcacdf30c2795dc04034df1e999e51d/src/mantine-core/src/components/Tabs/Tabs.module.css#L72-L78\n */\n:root[data-mantine-color-scheme='dark'] {\n  --dd-border-color: var(--mantine-color-dark-4);\n}\n\n:root[data-mantine-color-scheme='light'] {\n  --dd-border-color: var(--mantine-color-gray-3);\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useAutoFlushEvents.ts",
    "content": "import { useEffect } from 'react'\nimport { flushEvents } from '../flushEvents'\n\nconst FLUSH_EVENTS_INTERVAL = 5000\n\nexport function useAutoFlushEvents(enabled: boolean) {\n  useEffect(() => {\n    if (enabled) {\n      flushEvents()\n      const id = setInterval(flushEvents, FLUSH_EVENTS_INTERVAL)\n      return () => clearInterval(id)\n    }\n  }, [enabled])\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useDebugMode.ts",
    "content": "import { useEffect } from 'react'\nimport { setDebugMode } from '../setDebugMode'\n\nexport function useDebugMode(enabled: boolean) {\n  useEffect(() => {\n    setDebugMode(enabled)\n  }, [enabled])\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useDevServerStatus.ts",
    "content": "import { useEffect, useState } from 'react'\n\nconst REFRESH_DELAY = 2000\nconst CHECKING_STATUS_DELAY = 500\n\nexport const enum DevServerStatus {\n  CHECKING,\n  AVAILABLE,\n  UNAVAILABLE,\n}\n\nexport function useDevServerStatus(url: string) {\n  const [status, setStatus] = useState<DevServerStatus>(DevServerStatus.CHECKING)\n\n  useEffect(() => {\n    const abortController = new AbortController()\n    let checkingTimeoutId: ReturnType<typeof setTimeout>\n\n    void refreshDevServerStatus(url, abortController.signal, (status) => {\n      // We don't want to show the CHECKING state to quickly to avoid UI flashing. Delay the actual\n      // `setStatus` a little bit.\n      if (status === DevServerStatus.CHECKING) {\n        checkingTimeoutId = setTimeout(() => setStatus(DevServerStatus.CHECKING), CHECKING_STATUS_DELAY)\n      } else {\n        clearTimeout(checkingTimeoutId)\n        setStatus(status)\n      }\n    })\n\n    return () => {\n      clearTimeout(checkingTimeoutId)\n      abortController.abort()\n    }\n  }, [])\n\n  return status\n}\n\nasync function refreshDevServerStatus(\n  url: string,\n  abortSignal: AbortSignal,\n  callback: (status: DevServerStatus) => void\n) {\n  if (abortSignal.aborted) {\n    return\n  }\n\n  callback(DevServerStatus.CHECKING)\n\n  const isAvailable = await isDevServerAvailable(url, abortSignal)\n\n  if (abortSignal.aborted) {\n    return\n  }\n\n  callback(isAvailable ? DevServerStatus.AVAILABLE : DevServerStatus.UNAVAILABLE)\n\n  setTimeout(() => {\n    void refreshDevServerStatus(url, abortSignal, callback)\n  }, REFRESH_DELAY)\n}\n\nasync function isDevServerAvailable(url: string, abortSignal: AbortSignal) {\n  try {\n    const response = await fetch(url, { method: 'HEAD', signal: abortSignal })\n    return response.status === 200\n  } catch {\n    // The request can fail if nothing is listening on the URL port. In this case, consider the dev\n    // server 'unavailable'.\n    return false\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/eventCollection.ts",
    "content": "import type { EventCollectionStrategy } from '../../../common/extension.types'\nimport { INTAKE_DOMAINS } from '../../../common/intakeDomainConstants'\nimport { onBackgroundMessage } from '../../backgroundScriptConnection'\nimport { isRumViewEvent, type SdkEvent } from '../../sdkEvent'\nimport { FacetRegistry } from './facetRegistry'\n\nconst MAXIMUM_LOGGED_EVENTS = 1000\n\nexport type EventCollection = ReturnType<typeof startEventCollection>\n\nexport function startEventCollection(strategy: EventCollectionStrategy, onEventsChanged: (events: SdkEvent[]) => void) {\n  let events: SdkEvent[] = []\n  const facetRegistry = new FacetRegistry()\n\n  const listenToEvents = strategy === 'requests' ? listenEventsFromRequests : listenEventsFromSdk\n  const { stop } = listenToEvents((newEvents) => {\n    for (const event of newEvents) {\n      facetRegistry.addEvent(event)\n    }\n\n    // TODO remove events from facet registry when they are out of retention\n    events = [...newEvents, ...events].sort(compareEvents).slice(0, MAXIMUM_LOGGED_EVENTS)\n    onEventsChanged(events)\n  })\n\n  return {\n    facetRegistry,\n    clear: () => {\n      events = []\n      facetRegistry.clear()\n      onEventsChanged(events)\n    },\n    stop,\n  }\n}\n\nfunction compareEvents(a: SdkEvent, b: SdkEvent) {\n  // Sort events chronologically\n  if (a.date !== b.date) {\n    return b.date - a.date\n  }\n\n  // If two events have the same date, make sure to display View events last. This ensures that View\n  // updates are collocated in the list (no other event are present between two updates)\n  //\n  // For example, we can receive an initial View event, then a 'document' Resource event, then a\n  // View event update. All of those events have the same date (navigationStart). If we only relied\n  // on the event date, events would be displayed in the order they are received, so the Resource\n  // event would be displayed between the two View events, which makes it a bit confusing. This\n  // ensures that all View updates are displayed before the Resource event.\n  return (isRumViewEvent(a) as any) - (isRumViewEvent(b) as any)\n}\n\nfunction listenEventsFromRequests(callback: (events: SdkEvent[]) => void) {\n  function beforeRequestHandler(request: chrome.devtools.network.Request) {\n    const url = new URL(request.request.url)\n\n    if (!INTAKE_DOMAINS.find((rootDomain) => url.hostname.endsWith(rootDomain))) {\n      return\n    }\n    // intake request path is /api/vX/track\n    if (!['rum', 'logs'].includes(url.pathname.split('/')[3])) {\n      return\n    }\n    if (!request.request.postData || !request.request.postData.text) {\n      return\n    }\n\n    const decodedBody = request.request.postData.text\n    const rawEvents = decodedBody.split('\\n')\n    const events = rawEvents.map((rawEvent) => JSON.parse(rawEvent) as SdkEvent)\n\n    callback(events)\n  }\n\n  chrome.devtools.network.onRequestFinished.addListener(beforeRequestHandler)\n\n  return { stop: () => chrome.devtools.network.onRequestFinished.removeListener(beforeRequestHandler) }\n}\n\nfunction listenEventsFromSdk(events: (events: SdkEvent[]) => void) {\n  const subscription = onBackgroundMessage.subscribe((backgroundMessage) => {\n    if (backgroundMessage.type !== 'sdk-message') {\n      return\n    }\n    const sdkMessage = backgroundMessage.message\n    if (sdkMessage.type === 'logs' || sdkMessage.type === 'rum' || sdkMessage.type === 'telemetry') {\n      events([sdkMessage.payload])\n    }\n  })\n  return { stop: () => subscription.unsubscribe() }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/eventFilters.spec.ts",
    "content": "import type { RumEvent } from '../../../../../packages/rum-core/src/rumEvent.types'\nimport type { LogsEvent } from '../../../../../packages/logs/src/logsEvent.types'\nimport { isSafari } from '../../../../../packages/core/src/tools/utils/browserDetection'\nimport { parseQuery, matchWithWildcard, filterFacets } from './eventFilters'\nimport type { FacetValuesFilter } from './eventFilters'\nimport { FacetRegistry } from './facetRegistry'\nconst RUM_ERROR_EVENT = { type: 'error' } as RumEvent\nconst RUM_ACTION_EVENT = { type: 'action' } as RumEvent\nconst LOGS_EVENT = { status: 'info', origin: 'logger' } as LogsEvent\nconst RUM_XHR_RESOURCE_EVENT = { type: 'resource', resource: { type: 'xhr' } } as RumEvent\n\nif (!isSafari()) {\n  describe('filterFacets', () => {\n    const facetRegistry = new FacetRegistry()\n    facetRegistry.addEvent(RUM_ACTION_EVENT)\n    facetRegistry.addEvent(RUM_ERROR_EVENT)\n    facetRegistry.addEvent(RUM_ERROR_EVENT)\n    facetRegistry.addEvent(RUM_XHR_RESOURCE_EVENT)\n    facetRegistry.addEvent(LOGS_EVENT)\n\n    it('should exclude selected facets when in exclusion mode', () => {\n      expect(\n        filterFacets(\n          [RUM_ACTION_EVENT, RUM_ERROR_EVENT, RUM_ERROR_EVENT],\n          { type: 'exclude', facetValues: { type: ['error'] } } as FacetValuesFilter,\n          facetRegistry\n        )\n      ).toEqual([RUM_ACTION_EVENT])\n    })\n    it('should exclude unselected facets when in inclusion mode', () => {\n      expect(\n        filterFacets(\n          [RUM_ACTION_EVENT, RUM_ERROR_EVENT, RUM_ERROR_EVENT],\n          { type: 'include', facetValues: { type: ['error'] } } as FacetValuesFilter,\n          facetRegistry\n        )\n      ).toEqual([RUM_ERROR_EVENT, RUM_ERROR_EVENT])\n    })\n    it('should include selected facets at different levels in inclusion mode', () => {\n      expect(\n        filterFacets(\n          [RUM_ACTION_EVENT, RUM_ERROR_EVENT, RUM_ERROR_EVENT, RUM_XHR_RESOURCE_EVENT],\n          {\n            type: 'include',\n            facetValues: {\n              type: ['action'],\n              'resource.type': ['xhr'],\n            },\n          } as FacetValuesFilter,\n          facetRegistry\n        )\n      ).toEqual([RUM_ACTION_EVENT, RUM_XHR_RESOURCE_EVENT])\n    })\n    it('should exclude facets at different levels in exclusion mode', () => {\n      const facetValuesFilter: FacetValuesFilter = {\n        type: 'exclude',\n        facetValues: {\n          type: ['action', 'resource', 'view'],\n          $eventSource: ['logs'],\n        },\n      }\n      expect(filterFacets([RUM_ACTION_EVENT, RUM_ERROR_EVENT, LOGS_EVENT], facetValuesFilter, facetRegistry)).toEqual([\n        RUM_ERROR_EVENT,\n      ])\n    })\n  })\n\n  describe('parseQuery', () => {\n    it('return a simple field', () => {\n      expect(parseQuery('foo:bar')).toEqual([['foo', 'bar']])\n    })\n    it('return intermediary fields', () => {\n      expect(parseQuery('foo.bar:baz')).toEqual([['foo.bar', 'baz']])\n    })\n    it('return multiple fields', () => {\n      expect(parseQuery('foo:bar baz:qux')).toEqual([\n        ['foo', 'bar'],\n        ['baz', 'qux'],\n      ])\n    })\n    it('parse escaped whitespace with backslashes in search terms', () => {\n      expect(parseQuery('foo:bar\\\\ baz')).toEqual([['foo', 'bar\\\\ baz']])\n    })\n    it('parse escaped whitespace with backslashes in keys', () => {\n      expect(parseQuery('foo\\\\ bar:baz')).toEqual([['foo\\\\ bar', 'baz']])\n    })\n    it('return multiple fields with escaped whitespace', () => {\n      expect(parseQuery('foo\\\\ bar:baz\\\\ qux')).toEqual([['foo\\\\ bar', 'baz\\\\ qux']])\n      expect(parseQuery('foo:bar\\\\ baz qux:quux\\\\ corge')).toEqual([\n        ['foo', 'bar\\\\ baz'],\n        ['qux', 'quux\\\\ corge'],\n      ])\n    })\n  })\n\n  describe('matchWithWildcard', () => {\n    it('matches exact strings', () => {\n      expect(matchWithWildcard('foo', 'foo')).toBe(true)\n    })\n    it('matches exact strings case-insensitively', () => {\n      expect(matchWithWildcard('foo', 'FOO')).toBe(true)\n    })\n    it('matches substrings', () => {\n      expect(matchWithWildcard('foo', 'oo')).toBe(true)\n    })\n    it('matches substrings case-insensitively', () => {\n      expect(matchWithWildcard('foo', 'OO')).toBe(true)\n    })\n    it('does not match missing substrings', () => {\n      expect(matchWithWildcard('foo', 'bar')).toBe(false)\n    })\n    it('does not match missing substrings case-insensitively', () => {\n      expect(matchWithWildcard('foo', 'BAR')).toBe(false)\n    })\n    it('matches with wildcard at the beginning', () => {\n      expect(matchWithWildcard('foo', '*oo')).toBe(true)\n    })\n    it('matches with wildcard at the end', () => {\n      expect(matchWithWildcard('foo', 'fo*')).toBe(true)\n    })\n    it('matches with wildcard at the beginning and the end', () => {\n      expect(matchWithWildcard('foo', '*o*')).toBe(true)\n    })\n    it('matches with wildcard at the beginning and the end case-insensitively', () => {\n      expect(matchWithWildcard('foo', '*O*')).toBe(true)\n    })\n    it('does not match missing substrings with wildcard at the beginning', () => {\n      expect(matchWithWildcard('foo', '*bar')).toBe(false)\n    })\n    it('does not match missing substrings with wildcard at the end', () => {\n      expect(matchWithWildcard('foo', 'bar*')).toBe(false)\n    })\n    it('does not match missing substrings with wildcard at the beginning and the end', () => {\n      expect(matchWithWildcard('foo', '*bar*')).toBe(false)\n    })\n    it('does not match missing substrings with wildcard at the beginning and the end case-insensitively', () => {\n      expect(matchWithWildcard('foo', '*BAR*')).toBe(false)\n    })\n  })\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/eventFilters.ts",
    "content": "import type { SdkEvent } from '../../sdkEvent'\nimport type { RumViewEvent } from '../../../../../packages/rum-core/src/rumEvent.types'\nimport { isRumViewEvent } from '../../sdkEvent'\nimport type { FacetRegistry } from './facetRegistry'\n\nexport interface EventFilters {\n  facetValuesFilter: FacetValuesFilter\n  query: string\n  outdatedVersions: boolean\n}\n\nexport interface FacetValuesFilter {\n  type: 'include' | 'exclude'\n  facetValues: FacetValues\n}\nexport interface FacetValues {\n  [facetPath: string]: string[]\n}\n\nexport const DEFAULT_FILTERS: EventFilters = {\n  facetValuesFilter: { type: 'exclude', facetValues: {} },\n  query: '',\n  outdatedVersions: false,\n}\n\nexport function applyEventFilters(filters: EventFilters, events: SdkEvent[], facetRegistry: FacetRegistry) {\n  let filteredEvents = events\n\n  filteredEvents = filterFacets(filteredEvents, filters.facetValuesFilter, facetRegistry)\n\n  if (filters.query) {\n    const queryParts: string[][] = parseQuery(filters.query)\n    const matchQuery = (event: SdkEvent) =>\n      queryParts.every((queryPart) => {\n        // Hack it to restore the whitespace\n        const searchTerm = queryPart.length > 1 ? queryPart[1].replaceAll(/\\\\\\s+/gm, ' ') : ''\n        return matchQueryPart(event, queryPart[0], searchTerm)\n      })\n    filteredEvents = filteredEvents.filter(matchQuery)\n  }\n\n  if (!filters.outdatedVersions) {\n    filteredEvents = filterOutdatedVersions(filteredEvents)\n  }\n\n  return filteredEvents\n}\n\nexport function filterFacets(\n  events: SdkEvent[],\n  facetValuesFilter: FacetValuesFilter,\n  facetRegistry: FacetRegistry\n): SdkEvent[] {\n  const filteredFacetValueEntries = Object.entries(facetValuesFilter.facetValues)\n  if (filteredFacetValueEntries.length === 0) {\n    return events\n  }\n  const isIncludeType = facetValuesFilter.type === 'include'\n  return events.filter((event) =>\n    filteredFacetValueEntries[isIncludeType ? 'some' : 'every'](([facetPath, filteredValues]) => {\n      const eventValue = facetRegistry.getFieldValueForEvent(event, facetPath)\n      return isIncludeType === filteredValues.includes(eventValue as string)\n    })\n  )\n}\n\nfunction filterOutdatedVersions(events: SdkEvent[]): SdkEvent[] {\n  const upToDateEvents = new Map<string, RumViewEvent>()\n  const outdatedEvents = new Set<SdkEvent>()\n\n  for (const event of events) {\n    if (isRumViewEvent(event)) {\n      const otherEvent = upToDateEvents.get(event.view.id)\n      if (!otherEvent) {\n        upToDateEvents.set(event.view.id, event)\n      } else if (otherEvent._dd.document_version < event._dd.document_version) {\n        upToDateEvents.set(event.view.id, event)\n        outdatedEvents.add(otherEvent)\n      } else {\n        outdatedEvents.add(event)\n      }\n    }\n  }\n\n  return events.filter((event) => !outdatedEvents.has(event))\n}\n\nexport function parseQuery(query: string) {\n  const queryParts = query\n    .split(new RegExp('(?<!\\\\\\\\)\\\\s', 'g')) // Hack it to escape whitespace with backslashes\n    .filter((queryPart) => queryPart)\n    .map((queryPart) => queryPart.split(':'))\n\n  return queryParts\n}\n\nexport function matchWithWildcard(value: string, searchTerm: string): boolean {\n  value = value.toLowerCase()\n  searchTerm = searchTerm.toLowerCase()\n  if (!searchTerm.includes('*')) {\n    return value.includes(searchTerm)\n  }\n  const searchTerms = searchTerm.toLowerCase().split('*')\n  let lastIndex = 0\n  for (const term of searchTerms) {\n    const index = value.indexOf(term, lastIndex)\n    if (index === -1) {\n      return false\n    }\n    lastIndex = index + term.length\n  }\n  return true\n}\n\nfunction matchQueryPart(json: unknown, searchKey: string, searchTerm: string, jsonPath = ''): boolean {\n  if (searchKey.toLowerCase() === 'description') {\n    return matchWithWildcard(JSON.stringify(json), searchTerm)\n  }\n  if (jsonPath.endsWith(searchKey) && matchWithWildcard(String(json), searchTerm)) {\n    return true\n  }\n\n  if (typeof json !== 'object') {\n    return false\n  }\n\n  for (const key in json) {\n    if (\n      Object.prototype.hasOwnProperty.call(json, key) &&\n      matchQueryPart((json as any)[key], searchKey, searchTerm, jsonPath ? `${jsonPath}.${key}` : key)\n    ) {\n      return true\n    }\n  }\n\n  return false\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/facetRegistry.spec.ts",
    "content": "import { isChromium } from '../../../../../packages/core/src/tools/utils/browserDetection'\nimport { getAllFields } from './facetRegistry'\n\ndescribe('getAllFields', () => {\n  beforeEach(() => {\n    if (!isChromium()) {\n      pending('Extension only supported in chromium')\n    }\n  })\n\n  it('return a simple field', () => {\n    expect(getAllFields({ foo: 'bar' })).toEqual(new Map([['foo', 'bar']]))\n  })\n\n  it('return a field with an array as value', () => {\n    expect(getAllFields({ foo: ['bar', 'baz'] })).toEqual(new Map([['foo', ['bar', 'baz']]]))\n  })\n\n  it('return intermediary fields', () => {\n    expect(getAllFields({ foo: { bar: 'baz' } })).toEqual(\n      new Map<string, unknown>([\n        ['foo', { bar: 'baz' }],\n        ['foo.bar', 'baz'],\n      ])\n    )\n  })\n\n  it('return fields nested in an array', () => {\n    expect(getAllFields({ foo: [{ bar: 'baz' }, { bar: 'biz' }] })).toEqual(\n      new Map([\n        ['foo', [{ bar: 'baz' }, { bar: 'biz' }]],\n        ['foo.bar', ['baz', 'biz']],\n      ])\n    )\n  })\n})\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/facetRegistry.ts",
    "content": "import { getEventSource, type SdkEvent } from '../../sdkEvent'\nimport { createLogger } from '../../../common/logger'\nimport type { FacetValue, FieldPath, FieldMultiValue, FieldValue } from '../../facets.constants'\nimport { FACET_ROOT } from '../../facets.constants'\n\nconst logger = createLogger('facetRegistry')\n\ntype FacetValueCounts = Map<FieldPath, Map<FacetValue, number>>\ntype EventFields = Map<FieldPath, FieldMultiValue>\n\nexport class FacetRegistry {\n  facetValueCounts: FacetValueCounts = new Map()\n  eventFieldsCache: WeakMap<SdkEvent, EventFields> = new WeakMap()\n  allEventFieldPaths: Set<FieldPath> = new Set()\n\n  addEvent(event: SdkEvent) {\n    const fields = getAllFields(event)\n    fields.set('$eventSource', getEventSource(event))\n    this.eventFieldsCache.set(event, fields)\n\n    incrementFacetValueCounts(fields, this.facetValueCounts)\n    fields.forEach((_value, fieldPath) => {\n      this.allEventFieldPaths.add(fieldPath)\n    })\n  }\n\n  getFieldValueForEvent(event: SdkEvent, fieldPath: FieldPath): FieldMultiValue | undefined {\n    return this.eventFieldsCache.get(event)?.get(fieldPath)\n  }\n\n  getFacetValueCounts(fieldPath: FieldPath): Map<FacetValue, number> {\n    return this.facetValueCounts.get(fieldPath) || new Map<FacetValue, number>()\n  }\n\n  getAllFieldPaths() {\n    return this.allEventFieldPaths\n  }\n\n  getFacetChildrenValues(fieldPath: FieldPath): FacetValue[] {\n    const facetValues = this.facetValueCounts.get(fieldPath)\n    if (!facetValues) {\n      return []\n    }\n    return Array.from(facetValues.keys())\n  }\n\n  clear() {\n    this.facetValueCounts.clear()\n  }\n}\n\n/**\n * Increment facet value counts by iterating over all defined facets matching the event fields.\n */\nfunction incrementFacetValueCounts(fields: EventFields, facetValueCounts: FacetValueCounts, facet = FACET_ROOT) {\n  const fieldValue = fields.get(facet.path)\n  if (typeof fieldValue !== 'string') {\n    return\n  }\n\n  let valueCounts = facetValueCounts.get(facet.path)\n  if (!valueCounts) {\n    valueCounts = new Map()\n    facetValueCounts.set(facet.path, valueCounts)\n  }\n  valueCounts.set(fieldValue, (valueCounts.get(fieldValue) ?? 0) + 1)\n\n  if (facet.values?.[fieldValue]?.facets) {\n    for (const childFacet of facet.values[fieldValue].facets) {\n      incrementFacetValueCounts(fields, facetValueCounts, childFacet)\n    }\n  }\n}\n\n/**\n * Get all event fields indexed by their path. Intermediary fields are also taken into account.\n *\n * @example\n *\n * Simple field:\n *\n *   getAllFields({ foo: 'bar' })\n *   => Map { 'foo' => 'bar' }\n *\n * Event with an intermediary field:\n *\n *   getAllFields({ foo: { bar: 'baz' } })\n *   => Map {\n *     'foo' => { bar: 'baz' },\n *     'foo.bar' => 'baz'\n *   }\n *\n * Event with an array containing plain values:\n *\n *   getAllFields({ foo: ['bar', 'baz'] })\n *   => Map { 'foo' => ['bar', 'baz'] }\n *\n * Event with an array containing nested values:\n *\n *   getAllFields({ foo: [ { bar: 1 }, { bar: 2 } ] })\n *   => Map {\n *     'foo' => [ { bar: 1 }, { bar: 2 } ],\n *     'foo.bar' => [1, 2]\n *   }\n */\nexport function getAllFields(event: object) {\n  const fields: EventFields = new Map()\n\n  getAllFieldsRecursively(event, undefined)\n\n  return fields\n\n  function getAllFieldsRecursively(value: unknown, path: string | undefined) {\n    if (Array.isArray(value)) {\n      // Recurse inside arrays. The path does not change for array items.\n      for (const item of value) {\n        getAllFieldsRecursively(item, path)\n      }\n    } else if (typeof value === 'object' && value !== null) {\n      const typedValue = value as Record<string, unknown>\n      if (path !== undefined) {\n        // Store the intermediary field\n        pushField(path, typedValue)\n      }\n      // Recurse inside objects, building the path on the way\n      for (const key in typedValue) {\n        if (Object.prototype.hasOwnProperty.call(typedValue, key)) {\n          const itemPath = path === undefined ? key : `${path}.${key}`\n          const itemValue = (typedValue as { [key: string]: unknown })[key]\n          getAllFieldsRecursively(itemValue, itemPath)\n        }\n      }\n    } else if (\n      path !== undefined &&\n      (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null)\n    ) {\n      // Store the field\n      pushField(path, value)\n    } else {\n      // Coherence check, it should not happen because events are JSON-encoded so value types are\n      // limited.\n      logger.error(`Unexpected value type at ${path || '<root>'}`, value)\n    }\n  }\n\n  /**\n   * Add the value to the fields map. If a value is already defined for the given path, store it as\n   * an array to reflect all possible values for that path.\n   */\n  function pushField(path: FieldPath, value: FieldValue) {\n    const previousValue = fields.get(path)\n    if (Array.isArray(previousValue)) {\n      previousValue.push(value)\n    } else if (previousValue !== undefined) {\n      fields.set(path, [previousValue, value])\n    } else {\n      fields.set(path, value)\n    }\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/index.ts",
    "content": "export { useEvents } from './useEvents'\nexport type { EventFilters, FacetValuesFilter } from './eventFilters'\nexport { FacetRegistry } from './facetRegistry'\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useEvents/useEvents.ts",
    "content": "import { useEffect, useRef, useState } from 'react'\nimport type { SdkEvent } from '../../sdkEvent'\nimport type { EventCollectionStrategy } from '../../../common/extension.types'\nimport type { EventFilters } from './eventFilters'\nimport { DEFAULT_FILTERS, applyEventFilters } from './eventFilters'\nimport type { EventCollection } from './eventCollection'\nimport { startEventCollection } from './eventCollection'\n\nconst MAXIMUM_DISPLAYED_EVENTS = 100\n\nexport function useEvents({\n  preserveEvents,\n  eventCollectionStrategy,\n}: {\n  preserveEvents: boolean\n  eventCollectionStrategy: EventCollectionStrategy\n}) {\n  const [events, setEvents] = useState<SdkEvent[]>([])\n  const [filters, setFilters] = useState<EventFilters>(DEFAULT_FILTERS)\n\n  const eventCollectionRef = useRef<EventCollection>(null)\n\n  function clearEvents() {\n    eventCollectionRef.current?.clear()\n  }\n\n  useEffect(() => {\n    const eventCollection = startEventCollection(eventCollectionStrategy, setEvents)\n    eventCollectionRef.current = eventCollection\n    return () => eventCollection.stop()\n  }, [eventCollectionStrategy])\n\n  useEffect(() => {\n    if (!preserveEvents) {\n      const clearCurrentEvents = (details: chrome.webNavigation.WebNavigationTransitionCallbackDetails) => {\n        if (details.transitionType === 'reload' && details.tabId === chrome.devtools.inspectedWindow.tabId) {\n          clearEvents()\n        }\n      }\n      chrome.webNavigation.onCommitted.addListener(clearCurrentEvents)\n      return () => {\n        chrome.webNavigation.onCommitted.removeListener(clearCurrentEvents)\n      }\n    }\n  }, [preserveEvents])\n\n  const facetRegistry = eventCollectionRef.current?.facetRegistry\n  return {\n    events: facetRegistry\n      ? applyEventFilters(filters, events, facetRegistry).slice(0, MAXIMUM_DISPLAYED_EVENTS)\n      : events,\n    filters,\n    setFilters,\n    clear: clearEvents,\n    facetRegistry,\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useNetworkRules.ts",
    "content": "import { useEffect } from 'react'\nimport type { NetRequestRulesOptions } from '../../common/extension.types'\nimport { sendMessageToBackground } from '../backgroundScriptConnection'\n\nexport function useNetworkRules({\n  blockIntakeRequests,\n  useDevBundles,\n  useRumSlim,\n}: Omit<NetRequestRulesOptions, 'tabId'>) {\n  useEffect(() => {\n    sendMessageToBackground({\n      type: 'update-net-request-rules',\n      options: {\n        blockIntakeRequests,\n        useDevBundles,\n        useRumSlim,\n        tabId: chrome.devtools.inspectedWindow.tabId,\n      },\n    })\n  }, [blockIntakeRequests, useDevBundles, useRumSlim])\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useSdkInfos.ts",
    "content": "import { useEffect, useState } from 'react'\nimport type { RumInternalContext, Context } from '@datadog/browser-core'\nimport type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport type { RumInitConfiguration } from '@datadog/browser-rum'\nimport { createLogger } from '../../common/logger'\nimport { evalInWindow } from '../evalInWindow'\nimport { computeLogsTrackingType, computeRumTrackingType } from '../sampler'\n\nconst logger = createLogger('useSdkInfos')\n\nconst REFRESH_INFOS_INTERVAL = 2000\n\nexport interface SdkInfos {\n  rum?: {\n    version?: string\n    config?: RumInitConfiguration\n    internalContext?: RumInternalContext\n    globalContext?: Context\n    user: Context\n  }\n  logs?: {\n    version?: string\n    config?: LogsInitConfiguration\n    globalContext?: Context\n    user: Context\n  }\n  cookie?: {\n    id?: string\n    created?: string\n    expire?: string\n    logs?: string\n    rum?: string\n    forcedReplay?: '1'\n  }\n  rumTrackingType?: string\n  logsTrackingType?: string\n}\n\nexport function useSdkInfos() {\n  const [infos, setInfos] = useState<SdkInfos | undefined>()\n\n  useEffect(() => {\n    function refreshInfos() {\n      void getInfos().then((newInfos) =>\n        setInfos((previousInfos) => (deepEqual(previousInfos, newInfos) ? previousInfos : newInfos))\n      )\n    }\n    refreshInfos()\n    const id = setInterval(refreshInfos, REFRESH_INFOS_INTERVAL)\n    return () => clearInterval(id)\n  }, [])\n\n  return infos\n}\n\nasync function getInfos(): Promise<SdkInfos> {\n  let raw: SdkInfos\n  try {\n    raw = (await evalInWindow(\n      `\n        // Helper to serialize objects while preserving function metadata\n        function serializeWithFunctions(obj) {\n          return JSON.parse(JSON.stringify(obj, function(key, value) {\n            if (typeof value === 'function') {\n              return {\n                __type: 'function',\n                __name: value.name || '(anonymous)',\n                __source: value.toString()\n              }\n            }\n            return value\n          }))\n        }\n\n        const cookieRawValue = document.cookie\n          .split(';')\n          .map(cookie => cookie.match(/(\\\\S*?)=(.*)/)?.slice(1) || [])\n          .find(([name, _]) => name === '_dd_s')\n          ?.[1]\n\n        const cookie = cookieRawValue && Object.fromEntries(\n          cookieRawValue.split('&').map(value => value.split('='))\n        )\n        const rum = window.DD_RUM && {\n          version: window.DD_RUM?.version,\n          config: serializeWithFunctions(window.DD_RUM?.getInitConfiguration?.()),\n          internalContext: window.DD_RUM?.getInternalContext?.(),\n          globalContext: window.DD_RUM?.getGlobalContext?.(),\n          user: window.DD_RUM?.getUser?.(),\n        }\n        const logs = window.DD_LOGS && {\n          version: window.DD_LOGS?.version,\n          config: serializeWithFunctions(window.DD_LOGS?.getInitConfiguration?.()),\n          globalContext: window.DD_LOGS?.getGlobalContext?.(),\n          user: window.DD_LOGS?.getUser?.(),\n        }\n        return { rum, logs, cookie }\n      `\n    )) as SdkInfos\n  } catch (error) {\n    logger.error('Error while getting SDK infos:', error)\n    return {}\n  }\n\n  const sessionId = raw.cookie?.id\n  return {\n    ...raw,\n    rumTrackingType:\n      (raw.cookie?.rum ?? (sessionId && raw.rum?.config && computeRumTrackingType(sessionId, raw.rum.config))) ||\n      undefined,\n    logsTrackingType:\n      (raw.cookie?.logs ?? (sessionId && raw.logs?.config && computeLogsTrackingType(sessionId, raw.logs.config))) ||\n      undefined,\n  }\n}\n\nfunction deepEqual(a: unknown, b: unknown) {\n  // Quick and dirty but does the job. We might want to include a cleaner helper if our needs are\n  // changing.\n  return JSON.stringify(a) === JSON.stringify(b)\n}\n"
  },
  {
    "path": "developer-extension/src/panel/hooks/useSettings.ts",
    "content": "import { useEffect, useReducer } from 'react'\nimport { SESSION_STORAGE_SETTINGS_KEY } from '../../common/sessionKeyConstant'\nimport { EventListeners } from '../../common/eventListeners'\nimport { createLogger } from '../../common/logger'\nimport { evalInWindow } from '../evalInWindow'\nimport type { Settings } from '../../common/extension.types'\n\nconst logger = createLogger('useSettings')\n\nconst DEFAULT_SETTINGS: Readonly<Settings> = {\n  useDevBundles: false,\n  useDevReplaySandbox: false,\n  useRumSlim: false,\n  blockIntakeRequests: false,\n  autoFlush: false,\n  preserveEvents: false,\n  eventCollectionStrategy: 'sdk',\n  rumConfigurationOverride: null,\n  logsConfigurationOverride: null,\n  debugMode: false,\n  datadogMode: false,\n}\n\nlet settings: Settings | undefined\nconst onSettingsChange = new EventListeners()\nconst storageLoadingPromise = loadSettingsFromStorage().catch((error) =>\n  logger.error('Error while loading extension storage', error)\n)\n\nfunction syncSettingsWithSessionStorage(settings: Settings) {\n  evalInWindow(`sessionStorage.setItem(\n    ${JSON.stringify(SESSION_STORAGE_SETTINGS_KEY)},\n    ${JSON.stringify(JSON.stringify(settings))})\n  `).catch((error) => logger.error('Error while synchronizing session storage with extension storage', error))\n}\n\nasync function loadSettingsFromStorage() {\n  const storage = await chrome.storage.local.get()\n  settings = Object.fromEntries(\n    Object.entries(DEFAULT_SETTINGS).map(([name, defaultValue]) => [name, storage[name] ?? defaultValue])\n  ) as unknown as Settings\n  if (settings) {\n    syncSettingsWithSessionStorage(settings)\n  }\n}\n\nfunction setSetting<Name extends keyof Settings>(name: Name, value: Settings[Name]) {\n  settings![name] = value\n  onSettingsChange.notify()\n  chrome.storage.local\n    .set({ [name]: value })\n    .catch((error) => logger.error('Error while storing setting to the storage', error))\n  if (settings) {\n    syncSettingsWithSessionStorage(settings)\n  }\n}\n\nexport function useSettings() {\n  // If we don't have settings yet, it means that we are still loading them from the storage. Throw\n  // the promise so it'll be caught by the Suspense boundary.\n  if (!settings) {\n    // eslint-disable-next-line @typescript-eslint/only-throw-error\n    throw storageLoadingPromise\n  }\n\n  // We want to have a single 'settings' object shared between all components (it's easier to have\n  // a single source of truth and simplifies persistence implementation). Usually, we would use\n  // something like redux or one of the many other alternatives. Since we have a single use-case in\n  // this project, let's implement a shared state manually by forcing an update when the 'settings'\n  // object changes.\n\n  // https://legacy.reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate\n  const [, forceUpdate] = useReducer((x: number) => x + 1, 0)\n\n  useEffect(() => {\n    const subscription = onSettingsChange.subscribe(forceUpdate)\n    return () => subscription.unsubscribe()\n  }, [])\n\n  return [settings, setSetting] as const\n}\n"
  },
  {
    "path": "developer-extension/src/panel/index.tsx",
    "content": "// The default eslint-plugin-import resolver does not support \"exports\" fields in package.json yet.\n// Ignore the error until the default resolver supports it, or we switch to a different resolver.\n// https://github.com/import-js/eslint-plugin-import/issues/1810\nimport '@mantine/core/styles.layer.css'\n\nimport './global.css'\n\nimport { createRoot } from 'react-dom/client'\nimport React from 'react'\n\nimport { App } from './components/app'\nimport { initMonitoring } from './monitoring'\n\nmockDevtoolsApiForTests()\n\nconst main = document.createElement('main')\ndocument.body.append(main)\nconst root = createRoot(main)\nroot.render(<App />)\ninitMonitoring()\n\n/**\n * Allow to display the extension panel outside of chrome devtools for testing\n */\nfunction mockDevtoolsApiForTests() {\n  if (!chrome.devtools) {\n    chrome.devtools = {\n      inspectedWindow: {\n        tabId: 0,\n      },\n    } as any\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/monitoring.ts",
    "content": "import { datadogRum } from '@datadog/browser-rum'\nimport { datadogLogs } from '@datadog/browser-logs'\nimport { DEFAULT_PANEL_TAB } from '../common/panelTabConstants'\nimport { BASE_MONITORING_CONFIG, RUM_CONFIG } from '../common/monitoringConfig'\n\nexport function initMonitoring() {\n  datadogRum.init(RUM_CONFIG)\n  datadogRum.startSessionReplayRecording()\n  datadogRum.startView(DEFAULT_PANEL_TAB)\n\n  datadogLogs.init(BASE_MONITORING_CONFIG)\n}\n"
  },
  {
    "path": "developer-extension/src/panel/overrides.d.ts",
    "content": "declare module '*.css'\n"
  },
  {
    "path": "developer-extension/src/panel/sampler.ts",
    "content": "import { isSampled } from '@datadog/browser-rum-core'\n\nexport function computeRumTrackingType(\n  sessionId: string,\n  config: { sessionSampleRate?: number; sessionReplaySampleRate?: number }\n): string {\n  const sessionSampleRate = config.sessionSampleRate ?? 100\n  const sessionReplaySampleRate = config.sessionReplaySampleRate ?? 0\n\n  if (!isSampled(sessionId, sessionSampleRate)) {\n    return '0' // NOT_TRACKED\n  }\n\n  if (isSampled(sessionId, (sessionSampleRate * sessionReplaySampleRate) / 100)) {\n    return '1' // TRACKED_WITH_SESSION_REPLAY\n  }\n\n  return '2' // TRACKED_WITHOUT_SESSION_REPLAY\n}\n\nexport function computeLogsTrackingType(sessionId: string, config: { sessionSampleRate?: number }): string {\n  const sessionSampleRate = config.sessionSampleRate ?? 100\n\n  if (!isSampled(sessionId, sessionSampleRate)) {\n    return '0' // NOT_TRACKED\n  }\n\n  return '1' // TRACKED\n}\n"
  },
  {
    "path": "developer-extension/src/panel/sdkEvent.ts",
    "content": "import type { TelemetryEvent } from '../../../packages/core/src/domain/telemetry'\nimport type { LogsEvent } from '../../../packages/logs/src/logsEvent.types'\nimport type { RumEvent, RumViewEvent } from '../../../packages/rum-core/src/rumEvent.types'\n\nexport enum EventSource {\n  TELEMETRY = 'telemetry',\n  RUM = 'rum',\n  LOGS = 'logs',\n}\n\nexport type SdkEvent = RumEvent | TelemetryEvent | LogsEvent\n\nexport function isLogEvent(event: SdkEvent): event is LogsEvent {\n  return getEventSource(event) === EventSource.LOGS\n}\n\nexport function isRumEvent(event: SdkEvent): event is RumEvent {\n  return getEventSource(event) === EventSource.RUM\n}\n\nexport function isRumViewEvent(event: SdkEvent): event is RumViewEvent {\n  return isRumEvent(event) && event.type === 'view'\n}\n\nexport function isTelemetryEvent(event: SdkEvent): event is TelemetryEvent {\n  return getEventSource(event) === EventSource.TELEMETRY\n}\n\nexport function getEventSource(event: SdkEvent): EventSource {\n  if (event.status) {\n    return EventSource.LOGS\n  }\n\n  if (event.type === 'telemetry') {\n    return EventSource.TELEMETRY\n  }\n\n  return EventSource.RUM\n}\n"
  },
  {
    "path": "developer-extension/src/panel/sessionReplayPlayer/sessionReplayPlayer.types.ts",
    "content": "// Those types are coming from the Web-UI Session Replay Player. Please keep them as close as\n// possible to the original types.\n\nimport type { BrowserRecord, RecordType } from '@datadog/browser-rum/src/types'\n\nexport enum MessageBridgeUpType {\n  READY = 'ready',\n  RECORD_APPLIED = 'record_applied',\n  LOG = 'log',\n  ERROR = 'error',\n  METRIC_TIMING = 'timing',\n  METRIC_INCREMENT = 'increment',\n  CAPABILITIES = 'capabilities',\n  SERVICE_WORKER_ACTIVATED = 'service_worker_activated',\n  RENDERER_DIMENSIONS = 'renderer_dimensions',\n  ELEMENT_POSITION = 'element_position',\n}\n\nexport enum MessageBridgeDownType {\n  RECORD = 'record',\n  RESET = 'reset',\n  ELEMENT_POSITION = 'element_position',\n}\n\nexport enum MessageBridgeUpLogLevel {\n  LOG = 'log',\n  DEBUG = 'debug',\n  WARN = 'warn',\n  ERROR = 'error',\n}\n\nexport interface Dimensions {\n  width: number\n  height: number\n}\n\nexport interface StaticFrameContext {\n  origin: string\n  featureFlags: { [flagName: string]: boolean }\n  tabId: string\n  // Optional params will only be true to avoid confusions with stringified 'false'\n  isHot?: true\n  /**\n   * If the HTMLRenderers should report the offset dimensions to the parent window or not\n   */\n  reportDimensions?: true\n\n  /**\n   * If the HTMLRenderers should be rendered to full height without cropping in the viewport\n   */\n  isFullHeight?: true\n\n  /**\n   * If animations and transitions should be disabled in the HTMLRenderers\n   */\n  areAnimationsDisabled?: true\n}\n\n/**\n * For message types that benefit from verbose context (RUM logs and errors), the\n * following properties are reserved so context can be added at each level of the message\n * bridges without worry of conflicts. For simplicity, this type is shared across message\n * bridges, even though, for example, the service worker will never implement other contexts.\n */\nexport type MessageBridgeVerboseContext = {\n  sessionReplayContext?: {\n    viewId?: string\n    sessionId?: string\n  }\n  isolationSandboxContext?: {\n    pageUrl?: string\n  }\n  serviceWorkerContext?: {\n    registrationUrl?: string\n    version?: string\n    fetchUrl?: string\n    destination?: string\n  }\n} & Record<string, any>\n\ntype RawMessageBridgeUp =\n  | MessageBridgeUpReady\n  | MessageBridgeUpRecordApplied\n  | MessageBridgeUpLog\n  | MessageBridgeUpError\n  | MessageBridgeUpTiming\n  | MessageBridgeUpIncrement\n  | MessageBridgeUpCapabilities\n  | MessageBridgeUpServiceWorkerActivated\n  | MessageBridgeUpRendererDimensions\n  | MessageBridgeUpElementPosition\n\nexport type MessageBridgeUp = {\n  sentAt: number\n  tabId: string\n  viewId?: string\n} & RawMessageBridgeUp\n\n/**\n * Message send by the sanboxing when iframe is ready\n */\nexport interface MessageBridgeUpReady {\n  type: MessageBridgeUpType.READY\n}\n\n/**\n * Message send by the sanboxing when a record has been applied\n */\nexport interface MessageBridgeUpRecordApplied {\n  type: MessageBridgeUpType.RECORD_APPLIED\n  /** OrderId of the Record applied */\n  orderId: number\n  /** Type of the Record applied */\n  recordType: RecordType\n}\n\n/**\n * Message send by the sanboxing when a log is sent\n */\nexport interface MessageBridgeUpLog {\n  type: MessageBridgeUpType.LOG\n  level: MessageBridgeUpLogLevel\n  message: string\n  context?: { [key: string]: any }\n}\n\n/**\n * Message send by the sanboxing iframe when there is an error\n */\nexport interface MessageBridgeUpError {\n  type: MessageBridgeUpType.ERROR\n  serialisedError: SerialisedError\n  context?: { [key: string]: any }\n}\n\n/**\n * Message send by the sanboxing iframe with a custom timing\n */\nexport interface MessageBridgeUpTiming {\n  type: MessageBridgeUpType.METRIC_TIMING\n  name: string\n  duration: number\n  context?: { [key: string]: any }\n}\n\n/**\n * Message send by the sanboxing iframe with a custom count\n */\nexport interface MessageBridgeUpIncrement {\n  type: MessageBridgeUpType.METRIC_INCREMENT\n  name: string\n  value: number\n  context?: { [key: string]: any }\n}\n\nexport interface MessageBridgeUpCapabilities {\n  type: MessageBridgeUpType.CAPABILITIES\n  capabilities: {\n    SERVICE_WORKER: boolean\n    THIRD_PARTY_STORAGE: boolean\n  }\n}\n\nexport interface MessageBridgeUpServiceWorkerActivated {\n  type: MessageBridgeUpType.SERVICE_WORKER_ACTIVATED\n}\n\nexport interface MessageBridgeUpRendererDimensions {\n  type: MessageBridgeUpType.RENDERER_DIMENSIONS\n  dimensions: Dimensions\n}\n\nexport interface ElementPositionResponse {\n  cssSelector: string\n  position: Omit<DOMRect, 'toJSON'>\n}\n\nexport interface MessageBridgeUpElementPosition {\n  type: MessageBridgeUpType.ELEMENT_POSITION\n  positions: ElementPositionResponse[]\n}\n\ninterface MessageBridgeMetadata {\n  sentAt: number\n}\n\nexport type MessageBridgeDown = MessageBridgeDownRecords | MessageBridgeDownReset | MessageBridgeDownElementPosition\n\nexport type MessageBridgeDownReset = {\n  type: MessageBridgeDownType.RESET\n} & MessageBridgeMetadata\n\nexport type MessageBridgeDownRecords = {\n  type: MessageBridgeDownType.RECORD\n  record: RecordWithMetadata\n} & MessageBridgeMetadata\n\nexport type MessageBridgeDownElementPosition = {\n  type: MessageBridgeDownType.ELEMENT_POSITION\n  cssSelectors: string[]\n} & MessageBridgeMetadata\n\nexport interface SerialisedError {\n  name: string\n  message: string\n  stack?: string\n}\n\nexport type RecordWithSegmentData<T extends BrowserRecord = BrowserRecord> = T & {\n  viewId: string\n  segmentSource: 'browser' | undefined\n}\n\nexport type RecordWithMetadata<T extends BrowserRecord = BrowserRecord> = RecordWithSegmentData<T> & {\n  /**\n   * index of the record inside the view\n   */\n  orderId: number\n  /**\n   * Is the player preparing a seek?\n   * when seeking we might have to apply record before actually\n   * showing the content to the user\n   * this flag inform us this behavior\n   */\n  isSeeking: boolean\n  /**\n   * Should we apply back pressure on the timer when applying this record\n   * This is used by the renderer of the sandbox\n   * By default, it's only true for FS\n   * (meta also block the timer but it's in the main app not in the sandbox)\n   */\n  shouldWaitForIt: boolean // 'DARY... LEGENDARY\n}\n"
  },
  {
    "path": "developer-extension/src/panel/sessionReplayPlayer/startSessionReplayPlayer.ts",
    "content": "import { IncrementalSource, RecordType } from '@datadog/browser-rum/src/types'\nimport type { BrowserRecord } from '@datadog/browser-rum/src/types'\nimport { createLogger } from '../../common/logger'\nimport { onBackgroundMessage } from '../backgroundScriptConnection'\nimport {\n  DEV_REPLAY_SANDBOX_ORIGIN,\n  DEV_REPLAY_SANDBOX_URL,\n  PROD_REPLAY_SANDBOX_ORIGIN,\n  PROD_REPLAY_SANDBOX_URL,\n} from '../../common/packagesUrlConstants'\nimport type { MessageBridgeUp } from './sessionReplayPlayer.types'\nimport { MessageBridgeDownType, MessageBridgeUpLogLevel, MessageBridgeUpType } from './sessionReplayPlayer.types'\n\nconst sandboxLogger = createLogger('sandbox')\n\nexport type SessionReplayPlayerStatus = 'loading' | 'waiting-for-full-snapshot' | 'ready'\nexport interface SessionReplayPlayerState {\n  status: SessionReplayPlayerStatus\n  recordCount: number\n  excludeMouseMovements: boolean\n}\n\nconst sandboxParams = new URLSearchParams({\n  staticContext: JSON.stringify({\n    tabId: 'xxx',\n    origin: location.origin,\n    featureFlags: {\n      // Allows to easily inspect the DOM in the sandbox\n      rum_session_replay_iframe_interactive: true,\n      rum_session_replay_service_worker_debug: false,\n      rum_session_replay_disregard_origin: true,\n    },\n  }),\n})\nconst devSandboxUrl = `${DEV_REPLAY_SANDBOX_URL}?${String(sandboxParams)}`\nconst prodSandboxUrl = `${PROD_REPLAY_SANDBOX_URL}?${String(sandboxParams)}`\n\nexport function startSessionReplayPlayer(\n  iframe: HTMLIFrameElement,\n  setPlayerState: (state: SessionReplayPlayerState) => void,\n  useDevReplaySandbox: boolean\n) {\n  let status: SessionReplayPlayerStatus = 'loading'\n  const bufferedRecords = createRecordBuffer()\n  let excludeMouseMovements = false\n\n  const sandboxOrigin = useDevReplaySandbox ? DEV_REPLAY_SANDBOX_ORIGIN : PROD_REPLAY_SANDBOX_ORIGIN\n\n  const messageBridge = createMessageBridge(iframe, sandboxOrigin, () => {\n    const records = bufferedRecords.getRecords()\n    if (records.length > 0) {\n      status = 'ready'\n      records.forEach((record) => messageBridge.sendRecord(record))\n    } else {\n      status = 'waiting-for-full-snapshot'\n    }\n    setPlayerState({\n      status,\n      recordCount: bufferedRecords.getCount(),\n      excludeMouseMovements,\n    })\n  })\n\n  const backgroundMessageSubscription = onBackgroundMessage.subscribe((backgroundMessage) => {\n    if (backgroundMessage.type !== 'sdk-message' || backgroundMessage.message.type !== 'record') {\n      return\n    }\n    const record = backgroundMessage.message.payload.record\n\n    // Check if this is a mouse movement that should be excluded\n    const isMouseMovement =\n      record.type === RecordType.IncrementalSnapshot && record.data.source === IncrementalSource.MouseMove\n\n    if (excludeMouseMovements && isMouseMovement) {\n      return // Skip adding this record entirely\n    }\n\n    // Add record to buffer\n    bufferedRecords.add(record)\n    if (status === 'ready') {\n      messageBridge.sendRecord(record)\n    } else if (status === 'waiting-for-full-snapshot' && isFullSnapshotStart(record)) {\n      status = 'ready'\n      messageBridge.sendRecord(record)\n    }\n    setPlayerState({\n      status,\n      recordCount: bufferedRecords.getCount(),\n      excludeMouseMovements,\n    })\n  })\n\n  iframe.src = useDevReplaySandbox ? devSandboxUrl : prodSandboxUrl\n\n  return {\n    stop() {\n      messageBridge.stop()\n      backgroundMessageSubscription.unsubscribe()\n    },\n    getRecords() {\n      return bufferedRecords.getRecords()\n    },\n    setExcludeMouseMovements(shouldExcludeMouseMovements: boolean) {\n      excludeMouseMovements = shouldExcludeMouseMovements\n      setPlayerState({\n        status,\n        recordCount: bufferedRecords.getCount(),\n        excludeMouseMovements,\n      })\n    },\n  }\n}\n\nfunction createRecordBuffer() {\n  const records: BrowserRecord[] = []\n\n  return {\n    add(record: BrowserRecord) {\n      // Make sure 'records' starts with a FullSnapshot\n      if (isFullSnapshotStart(record)) {\n        records.length = 0\n        records.push(record)\n      } else if (records.length > 0) {\n        records.push(record)\n      }\n    },\n    getRecords(): BrowserRecord[] {\n      return [...records]\n    },\n    getCount(): number {\n      return records.length\n    },\n  }\n}\n\nfunction isFullSnapshotStart(record: BrowserRecord) {\n  // All FullSnapshot start with a \"Meta\" record. The FullSnapshot record comes in third position\n  return record.type === RecordType.Meta\n}\n\nfunction normalizeRecord(record: BrowserRecord) {\n  if (record.type === RecordType.IncrementalSnapshot && record.data.source === IncrementalSource.MouseMove) {\n    return {\n      ...record,\n      data: {\n        ...record.data,\n        position: record.data.positions[0],\n      },\n    }\n  }\n  return record\n}\n\nfunction createMessageBridge(iframe: HTMLIFrameElement, sandboxOrigin: string, onReady: () => void) {\n  let nextMessageOrderId = 1\n\n  function globalMessageListener(event: MessageEvent<MessageBridgeUp>) {\n    if (event.origin === sandboxOrigin) {\n      const message = event.data\n      if (message.type === MessageBridgeUpType.LOG) {\n        if (message.level === MessageBridgeUpLogLevel.ERROR) {\n          sandboxLogger.error(message.message)\n        } else {\n          sandboxLogger.log(message.message)\n        }\n      } else if (message.type === MessageBridgeUpType.ERROR) {\n        sandboxLogger.error(\n          `${message.serialisedError.name}: ${message.serialisedError.message}`,\n          message.serialisedError.stack\n        )\n      } else if (message.type === MessageBridgeUpType.READY) {\n        onReady()\n      } else {\n        // Ignore other messages for now.\n      }\n    }\n  }\n\n  window.addEventListener('message', globalMessageListener)\n  return {\n    stop: () => {\n      window.removeEventListener('message', globalMessageListener)\n    },\n\n    sendRecord: (record: BrowserRecord) => {\n      iframe.contentWindow!.postMessage(\n        {\n          type: MessageBridgeDownType.RECORD,\n          record: {\n            ...normalizeRecord(record),\n            viewId: 'xxx',\n            orderId: nextMessageOrderId,\n            isSeeking: false,\n            shouldWaitForIt: false,\n            segmentSource: 'browser',\n          },\n          sentAt: Date.now(),\n        },\n        sandboxOrigin\n      )\n\n      nextMessageOrderId++\n    },\n  }\n}\n"
  },
  {
    "path": "developer-extension/src/panel/setDebugMode.ts",
    "content": "import { createLogger } from '../common/logger'\nimport { evalInWindow } from './evalInWindow'\n\nconst logger = createLogger('setDebug')\n\nexport function setDebugMode(enabled: boolean) {\n  evalInWindow(\n    `\n      DD_RUM?._setDebug(${enabled})\n      DD_LOGS?._setDebug(${enabled})\n    `\n  ).catch((error) => logger.error('Error while setting debug mode:', error))\n}\n"
  },
  {
    "path": "developer-extension/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n\n  \"compilerOptions\": {\n    \"module\": \"preserve\",\n    \"target\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"jsx\": \"react\",\n    \"lib\": [\"ES2022\", \"DOM\"],\n    \"types\": [\"chrome\", \"react\", \"react-dom\", \"jasmine\"],\n    \"skipLibCheck\": true,\n    \"allowImportingTsExtensions\": true,\n    \"noEmit\": true\n  },\n\n  \"include\": [\"src\", \"wxt.config.ts\"]\n}\n"
  },
  {
    "path": "developer-extension/wxt.config.ts",
    "content": "import { defineConfig } from 'wxt'\nimport { getBuildEnvValue } from '../scripts/lib/buildEnv'\n\n// eslint-disable-next-line import/no-default-export\nexport default defineConfig({\n  outDir: 'dist',\n  modules: ['@wxt-dev/module-react'],\n  entrypointsDir: 'src/entrypoints',\n  manifest: {\n    name: 'Datadog Browser SDK developer extension',\n    permissions: ['storage', 'browsingData', 'declarativeNetRequest', 'webNavigation', 'scripting'],\n    host_permissions: ['<all_urls>'],\n    icons: {\n      '256': 'icon.png',\n    },\n    background: {\n      service_worker: 'background.js',\n      type: 'module',\n    },\n    devtools_page: 'devtools.html',\n  },\n  webExt: {\n    chromiumArgs: ['--auto-open-devtools-for-tabs'],\n    openDevtools: true,\n    openConsole: true,\n    startUrls: ['https://datadoghq.dev/browser-sdk-test-playground/?application_id=xxx&client_token=xxx'],\n  },\n  vite: () => ({\n    build: {\n      chunkSizeWarningLimit: 1000,\n    },\n    resolve: {\n      extensions: ['.ts', '.tsx', '.js'],\n    },\n    css: {\n      modules: {\n        localsConvention: 'camelCase',\n        generateScopedName: '[name]_[local]_[hash:base64:5]',\n      },\n    },\n    define: {\n      __BUILD_ENV__SDK_VERSION__: JSON.stringify(getBuildEnvValue('SDK_VERSION')),\n    },\n  }),\n})\n"
  },
  {
    "path": "docs/ARCHITECTURE.md",
    "content": "# Architecture\n\nDescribes architecture patterns with examples — detailed component documentation lives as JSDoc on the files themselves.\n\n## Package dependencies\n\nThe [monorepo](https://github.com/DataDog/browser-sdk) contains several packages:\n\n```mermaid\ngraph TD\n  core[\"@datadog/browser-core\\n(shared utilities)\"]\n  rum-core[\"@datadog/browser-rum-core\\n(core RUM)\"]\n  rum[\"@datadog/browser-rum\\n(full RUM)\"]\n  rum-slim[\"@datadog/browser-rum-slim\\n(lightweight RUM)\"]\n  rum-react[\"@datadog/browser-rum-react\\n(React integration)\"]\n  logs[\"@datadog/browser-logs\"]\n  worker[\"@datadog/browser-worker\"]\n\n  core --> rum-core\n  core --> logs\n  rum-core --> rum\n  rum-core --> rum-slim\n  rum --> rum-react\n```\n\n## Data processing\n\nHigh-level view of RUM SDK data processing. Each box represents a module:\n\n```mermaid\nflowchart TD\n  startRum[\"startRum\\n(boot)\"]\n  collections[\"collections\\n(views, actions, resources, errors…)\"]\n  assembly[\"assembly\\n(adds common attributes)\"]\n  batch[\"batch\\n(in-memory buffer)\"]\n\n  startRum --> collections\n  collections -->|\"raw RUM events\"| assembly\n  assembly -->|\"enriched events\"| batch\n```\n\n### startRum [[code](https://github.com/DataDog/browser-sdk/blob/32ffe4bb7e50a37a43794773bbbc57aabb373468/packages/rum-core/src/boot/startRum.ts)]\n\nCalled at SDK initialization. Starts all event data collection.\n\n### collection [[code](https://github.com/DataDog/browser-sdk/blob/32ffe4bb7e50a37a43794773bbbc57aabb373468/packages/rum-core/src/domain/rumEventsCollection/error/errorCollection.ts)]\n\nCreates raw RUM events (`views`, `actions`, `resources`, …) by listening to or instrumenting various web APIs, then notifies the assembly.\n\n### assembly [[code](https://github.com/DataDog/browser-sdk/blob/32ffe4bb7e50a37a43794773bbbc57aabb373468/packages/rum-core/src/domain/assembly.ts)]\n\nEnriches each event with common attributes (`applicationId`, `service`, `version`, view context, customer context, …) then forwards it to the batch.\n\n## Data transfer\n\n```mermaid\nflowchart TD\n  batch[\"batch\\n(in-memory buffer)\"]\n  httpRetry[\"httpRetry\\n(retry & throttle)\"]\n  httpRequest[\"httpRequest\\n(fetch / XHR)\"]\n  intake[\"Datadog intake\"]\n\n  batch -->|\"flush\"| httpRetry\n  httpRetry -->|\"send\"| httpRequest\n  httpRequest --> intake\n```\n\n### batch [[code](https://github.com/DataDog/browser-sdk/blob/32ffe4bb7e50a37a43794773bbbc57aabb373468/packages/core/src/transport/batch.ts)]\n\nCollects events into an in-memory batch. Flushed:\n\n- Periodically, every `configuration.flushTimeout` (30s by default)\n- When the buffer size reaches `configuration.batchBytesLimit`\n- When the number of events reaches `configuration.maxBatchSize`\n- On `visibilitychange` when the document becomes hidden\n- On `beforeunload`\n\n### httpRetry\n\nBuffers and retries failed requests (`network failure`, `intake unavailable`, `no connectivity`, …). Also throttles requests when too many are in progress.\n\nThe SDK buffers at most 3MB of requests; older requests are dropped beyond that limit. The buffer is in-memory — requests are lost if the tab is closed.\n\n### httpRequest [[code](https://github.com/DataDog/browser-sdk/blob/32ffe4bb7e50a37a43794773bbbc57aabb373468/packages/core/src/transport/httpRequest.ts)]\n\nSends events using `fetch` with `keepAlive`, falling back to `XMLHttpRequest`.\n"
  },
  {
    "path": "docs/CONVENTIONS.md",
    "content": "# Conventions\n\n## Dependencies as parameters\n\nFavor passing a loosely coupled domain dependency as a parameter instead of statically importing it for:\n\n- **Readability**: Better see which external concepts are involved\n- **Testability**: Easily substitute a dependency by a mock to focus on test subject behaviors\n- **Extensibility**: Easily replace a dependency with another one with the same signature as needs change\n\n**Examples:**\n\n- **OK** to statically import generic utilities\n\n  ```typescript\n  import { find } from 'utils'\n  ```\n\n- **OK** to split a file for maintenance purpose and statically import the different parts\n\n  ```typescript\n  import { mySubBehavior } from './mySubBehavior'\n  import { myOtherSubBehavior } from './myOtherSubBehavior'\n\n  function startMyModule() {\n    mySubBehavior()\n    myOtherSubBehavior()\n  }\n  ```\n\n- For two different modules, with one depending on the other:\n  - **KO** to statically retrieve the dependency\n\n    ```typescript\n    import { getOrCreateMyDependency } from './myDependency'\n\n    function startMyModule() {\n      myDependency = getOrCreateMyDependency()\n      myDependency.interact()\n    }\n    ```\n\n  - **KO** to statically expose a part of the dependency\n\n    ```typescript\n    // boot\n    myDependency = startMyDependency()\n    myModule = startMyModule()\n\n    // myModule.ts\n    import { interactWithMyDependency } from './myDependency'\n\n    function startMyModule() {\n      interactWithMyDependency()\n    }\n    ```\n\n  - **OK**\n\n    ```typescript\n    // boot\n    myDependency = startMyDependency()\n    myOtherDependency = getOrCreateMyDependency()\n    myModule = startMyModule(myDependency, myOtherDependency)\n\n    // myModule.ts\n    function startMyModule(myDependency, myOtherDependency) {\n      myDependency.interact()\n      myOtherDependency.interact()\n    }\n    ```\n\n## Avoid global polyfill\n\nAvoid polluting browser context or conflicting with customer own polyfills.\n\n**Example:**\n\n- **KO** to overwrite global API\n\n  ```typescript\n  window.URL = window.URL || buildUrl(url: string, base?: string) {\n    ...\n  }\n  ```\n\n- **OK** to use our own utility internally\n\n  ```typescript\n  export function buildUrl(url: string, base?: string) {\n    ...\n  }\n  ```\n\n## File organization\n\nIn the different packages, we try to split code relative to different concerns to ease discoverability and reusability:\n\n- **Boot**: code related to API declaration and init phase of the SDK\n- **Domain**: code specific to our products: `configuration`, `action`, `views`, `assembly`, ...\n- **Tools**: utilities used across the code base without domain logic: `observable`, `timeUtils`, ...\n- **Browser**: code wrapping browser APIs without domain logic to use more convenient API, extend capabilities, handle edge cases: `performanceCollection`, `cookie`, ...\n- **Transport**: code related to final data transport (server/bridge): `batch`, `httpRequest`, `replicas`, ...\n\n## Index module usage\n\nUse index.ts files to expose a single, minimal API in directories where modules are used together.\nDo not use index.ts when a directory contains independent modules.\nAn index.ts file should not have exports only used for spec files.\n\n**Examples:**\n\n- Directory with similar but independent modules: `core/src/tools`\n- Directory with single domain split in several files: `core/src/transport`\n\n## Utility files\n\nIt is useful to extract reusable code in \"utils\" files.\n\nTo increase discoverability and limit the scope of those files, specialize them with a relevant prefix and keep them close to where they are used.\n\nExamples: `serializationUtils`, `resourceUtils`, ...\n\n## SpecHelper files\n\nIt is useful to extract tests shared code in \"specHelper\" files.\n\nTo increase discoverability and limit the scope of those files, specialize them with a relevant prefix and keep them close to where they are used.\n\nExamples: `htmlAst.specHelper.ts`, `location.specHelper.ts`, ...\n\n## Size control\n\n### Favor function over class\n\nClass syntax does not play well with minification, even without being transpiled as ES5 syntax:\n\n```javascript\nclass Batch {\n  pendingMessages = []\n  add(message) {\n    this.pendingMessages.push(message)\n  }\n}\n\n// bundled as (64 bytes):\nclass s {\n  pendingMessages = []\n  add(s) {\n    this.pendingMessages.push(s)\n  }\n}\n```\n\nInstead, prefer using closures (or plain functions when possible):\n\n```javascript\nfunction createBatch() {\n  const pendingMessages = []\n  return {\n    add(message) {\n      pendingMessages.push(message)\n    },\n  }\n}\n\n// bundled as (50 bytes):\nfunction n() {\n  const n = []\n  return {\n    add(t) {\n      n.push(t)\n    },\n  }\n}\n```\n\n(use `pbpaste | npx terser -m --toplevel` to get the minified version)\n\n### Favor const enum\n\nThey generally produce less code.\n\n## Public APIs\n\n### Don't use enum in public APIs or types\n\nWe want to give the user flexibility on how to specify constant options, to let them choose between hardcoded strings or importing some constant.\n\n### Use option parameter for customer-provided functions\n\n```javascript\nfunction customerFn({ foo, bar }) {} // OK\nfunction customerFn(foo, bar) {} // KO\n```\n\nFor functions API (startView, addAction), if we want to support new inputs, we can tweak the behavior to support both old and new inputs and avoid a breaking change.\n\nHowever, for customer-provided functions (beforeSend, allowTracingUrl), introducing a change in the input could be a breaking change because the customer implementation would not support it. To have more flexibility in those cases, favor an option input parameter over multiple parameters.\n\n_Note_: to avoid unnecessary customer migration, don't update existing APIs until it is needed.\n"
  },
  {
    "path": "docs/DEVELOPMENT.md",
    "content": "# Development\n\n## Commit messages and Pull Request titles\n\nMessages should be concise but explanatory. We are using a convention inspired by [gitmoji][1], to\nlabel our Commit messages and Pull Request titles:\n\n### User-facing changes\n\n- 💥 **Breaking change** - Breaking API changes\n- ✨ **New feature** - New public API, behavior, event, property\n- 🐛 **Bug fix** - Fix bugs, regressions, crashes\n- ⚡️ **Performance** - Improve performance, reduce bundle size\n- 📝 **Documentation** - User-facing documentation\n- ⚗️ **Experimental** - New public feature behind a feature flag\n\n### Internal changes\n\n- 👷 **Build/CI** - Dependencies, tooling, deployment, CI config\n- ♻️ **Refactor** - Code restructuring, architectural changes\n- 🎨 **Code structure** - Improve code structure, formatting\n- ✅ **Tests** - Add/fix/improve tests\n- 🔧 **Configuration** - Config files, project setup\n- 🔥 **Removal** - Remove code, features, deprecated items\n- 👌 **Code review** - Address code review feedback\n- 🚨 **Linting** - Add/fix linter rules\n- 🧹 **Cleanup** - Minor cleanup, housekeeping\n- 🔊 **Logging** - Add/modify debug logs, telemetry\n\n## Dependency Management\n\n### Adding Dependencies\n\nWhen adding a new dependency, you must update `LICENSE-3rdparty.csv`:\n\n1. Add entry with format: `Component,Origin,License,Copyright`\n2. Use `dev` prefix for all devDependencies (including playground)\n3. **Do not include version numbers** - list package name only\n4. Maintain alphabetical order by package name\n5. Fetch license info from GitHub raw LICENSE file\n\n**Example:**\n\n```csv\ndev,chokidar,MIT,Copyright (c) 2012 Paul Miller / Elan Shanker\n```\n\n### License Information Sources\n\n- Check package repository's LICENSE or package.json\n- GitHub: `https://raw.githubusercontent.com/{org}/{repo}/master/LICENSE`\n- Extract copyright holder from license file header\n\n### Updating Dependencies\n\nAlways use latest stable versions for new dependencies. Check with:\n\n```bash\nnpm view <package>@latest version\n```\n\n## RUM Events Schema Management\n\nTypes auto-generated from [rum-events-format](https://github.com/DataDog/rum-events-format) submodule → `src/rumEvent.types.ts` (committed).\n\n```bash\nyarn json-schemas:sync      # Update submodule + regenerate types\nyarn json-schemas:generate  # Regenerate types only\n```\n\n**Fork dependency**: Uses `bcaudan/json-schema-to-typescript#bcaudan/add-readonly-support` (v11.0.1) for `readonly` modifier support. Built lazily when generating types (not during `yarn install`) to avoid CI rate limiting.\n\n⚠️ Never edit generated types manually.\n\n## TypeScript 3.8.2 compatibility\n\nthe CI fails with an error like this:\n\n```\nScript exited with error: Error: TypeScript 3.8.2 compatibility compatibility broken\n    ...\n  node_modules/@datadog/browser-rum-core/cjs/index.d.ts(15,46): error TS1005: ',' expected.\n```\n\nReproduce locally with `yarn test:compat:tsc`.\n\nCheck the file mentioned in the error (e.g. `node_modules/@datadog/browser-rum-core/cjs/index.d.ts`). The likely cause is using TypeScript syntax too recent for 3.8.2. For example, combining type and non-type exports on a single line:\n\n```typescript\n// ❌ not supported in TS 3.8.2\nexport { createProfilingContextManager, type ProfilingContextManager } from './domain/contexts/profilingContext'\n```\n\nSplit into two separate lines:\n\n```typescript\n// ✅\nexport type { ProfilingContextManager } from './domain/contexts/profilingContext'\nexport { createProfilingContextManager } from './domain/contexts/profilingContext'\n```\n\n[1]: https://gitmoji.carloscuesta.me/\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Documentation\n\n## Policy\n\nWhen making changes that impact development workflows or architecture, update the relevant document (see reference below).\n\n**Keep it concise**: Document the essential information only. Prefer command examples and brief explanations over lengthy descriptions.\n\n## Reference\n\n| Document               | Purpose                                                         |\n| ---------------------- | --------------------------------------------------------------- |\n| `docs/DEVELOPMENT.md`  | Workflow, dependencies                                          |\n| `docs/CONVENTIONS.md`  | Coding conventions and style guidelines                         |\n| `docs/ARCHITECTURE.md` | SDK design patterns and event pipeline                          |\n| `docs/TESTING.md`      | Unit and E2E testing strategy and infrastructure                |\n| `scripts/AGENTS.md`    | Writing and organizing scripts                                  |\n| `test/e2e/AGENTS.md`   | E2E test writing guide (Playwright, createTest, IntakeRegistry) |\n"
  },
  {
    "path": "docs/TESTING.md",
    "content": "# Testing\n\n## Test my change on my local environment\n\n1. Run `yarn dev`\n2. Open [http://localhost:8080](http://localhost:8080/) in your browser. The [sandbox folder](https://github.com/DataDog/browser-sdk/tree/master/sandbox) is served, with a minimal browser SDK setup.\n3. You can use global API via the devtools (see below) or locally modify [index.html](https://github.com/DataDog/browser-sdk/blob/master/sandbox/index.html) to experiment things.\n\n## Test my change using Claude Code agent\n\nWe have a `/manual-testing` skill ([source](https://github.com/DataDog/browser-sdk/blob/main/.claude/skills/manual-testing/SKILL.md)) to help you test your changes using the dev-server sandbox and [agent-browser](https://agent-browser.dev/). This skill should be able to generate the test instructions for your PR.\n\n## Test my change on remote environments that use the Browser SDK bundles via CDN\n\nUse this strategy to test the integration on Real applications.\n\n1. Install the [developer extension](https://github.com/DataDog/browser-sdk/tree/master/developer-extension)\n2. Run `yarn dev`\n3. Open the Chrome DevTools browser SDK panel and check \"Use dev bundles\".\n\n## Work with unit tests\n\n1. Write a unit test.\n2. Run only your tests by temporarily replacing `describe(...)` with `fdescribe(...)` or `it(...)` with `fit(...)`.\n3. Run `yarn test` in the project root. It will launch the tests in watch mode, and also expose [a local URL](http://localhost:9876/) that you can open in any browser.\n4. Look at your terminal to see your test results.\n5. For deeper investigation, open [the \"debug\" page](http://localhost:9876/debug.html#) to inspect test execution via the devtools.\n\n## Debug flaky unit tests\n\nTop-level `describe` blocks are run in a random order. Sometimes, an issue can only be reproduced with a given order. To reproduce a test run order:\n\n1. Check the `Randomized with seed XXXX` message from the test output.\n2. Run `yarn test:unit --seed XXXX`.\n\n## Work with E2E tests\n\nSee `test/e2e/AGENTS.md` for the full E2E testing guide (setup, writing tests, createTest builder, IntakeRegistry, best practices).\n\nQuick commands:\n\n- `yarn test:e2e:init` — first-time setup\n- `yarn test:e2e` — run all E2E tests\n- `yarn test:e2e -g \"pattern\"` — filter by name\n- `yarn test:e2e --ui` — Playwright UI mode\n\n## Run tests in browserstack\n\n- `BS_USERNAME=<username> BS_ACCESS_KEY=<access_key> yarn test:unit:bs` - unit tests\n- `BS_USERNAME=<username> BS_ACCESS_KEY=<access_key> yarn test:e2e:bs` - e2e tests\n"
  },
  {
    "path": "eslint-local-rules/disallowEnumExports.js",
    "content": "import { SymbolFlags } from 'typescript'\n\n/**\n * This rule forbids exporting 'enums'.  It serves two purposes:\n *\n * # enums\n *\n * This SDK is used in a variety of ways. It can be used in JS, in TS, but also a mix between the\n * two, for example when including the bundle via the CDN and using it in a JS or TS app. We want to\n * give the user flexibility on how to specify constant options, to let them chose between hardcoded\n * strings or importing some constant. To allow this, we can't use enums publicly because it is not\n * flexible enough.\n *\n * # const enums\n *\n * 'const enums' are useful in TS to optimize the generated code, but they don't produce any JS code\n * on their own[0].  So, exporting them in public packages entry points should be avoided, because\n * we don't know how public packages are used: it could be used by other builders like babel which\n * don't have access to the type definition, so won't be able to access the enum value.\n *\n * Exporting 'const enums' from internal modules to be consumed by internal modules is fine, because\n * we know that everything will be handled by TypeScript.\n *\n * So, this rule should not be applied on all the source code, but only on entry points that will be\n * used in the wild.\n *\n * In the future, this rule could be removed and the 'isolatedModules' TS option[1] could be used\n * instead. This way, TS output 'const enum' the same way it does for standard 'enum'. But this\n * option adds a few more requirements, like exporting type with `export type` statements, which is\n * not possible before TS 3.8[2]. Since we support all TS 3.x versions, it is not currently possible\n * to enable this option.\n *\n * [0]: https://github.com/microsoft/TypeScript/issues/16671\n * [1]: https://www.typescriptlang.org/tsconfig#isolatedModules\n * [2]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export\n */\nexport default {\n  meta: {\n    docs: {\n      description: 'Disallow export of enums.',\n      recommended: false,\n    },\n    schema: [],\n  },\n  create(context) {\n    const parserServices = context.sourceCode.parserServices\n    const checker = parserServices.program.getTypeChecker()\n\n    return {\n      ExportNamedDeclaration(node) {\n        for (const specifier of node.specifiers) {\n          const originalNode = parserServices.esTreeNodeToTSNodeMap.get(specifier)\n          const type = checker.getTypeAtLocation(originalNode)\n          if (type.symbol && isEnum(type.symbol)) {\n            context.report(specifier, 'Cannot export enum')\n          }\n        }\n      },\n      ExportAllDeclaration(node) {\n        const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node)\n        const moduleSymbol = checker.getSymbolAtLocation(originalNode.moduleSpecifier)\n        const moduleExports = checker.getExportsOfModule(moduleSymbol)\n\n        for (const symbol of moduleExports) {\n          if (isEnum(symbol, checker)) {\n            context.report(node, `Cannot export enum ${symbol.getName()}`)\n          }\n        }\n      },\n    }\n\n    function isEnum(symbol) {\n      const flags = symbol.getFlags()\n\n      // eslint-disable-next-line no-bitwise\n      if (flags & SymbolFlags.Enum) {\n        return true\n      }\n\n      // eslint-disable-next-line no-bitwise\n      if (flags & SymbolFlags.Alias) {\n        return isEnum(checker.getAliasedSymbol(symbol))\n      }\n\n      return false\n    }\n  },\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowGenericUtils.js",
    "content": "import path from 'node:path'\n\nexport default {\n  meta: {\n    docs: {\n      description: 'Disallow the use of too generic utility file names',\n      recommended: false,\n    },\n    schema: [],\n  },\n  create: (context) => ({\n    Program: (node) => {\n      const filename = path.basename(context.getFilename())\n      if (isGenericUtilsFileName(filename)) {\n        context.report({\n          node,\n          message: 'Consider having a more specific file name to reflect the domain of this utility file',\n        })\n      }\n    },\n  }),\n}\n\nfunction isGenericUtilsFileName(filename) {\n  return /^(utils|specHelper)\\..*/.test(filename)\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowNonScripts.js",
    "content": "export default {\n  meta: {\n    docs: {\n      description: 'Disallow JS files that are not used as a \"script\"',\n    },\n    schema: [],\n  },\n  create: (context) => ({\n    Program: (node) => {\n      // Find if there is a `runMain()` expression at the top level\n      const hasRunMainAtTopLevel = node.body.some(\n        (n) =>\n          n.type === 'ExpressionStatement' &&\n          n.expression.type === 'CallExpression' &&\n          n.expression.callee.name === 'runMain'\n      )\n\n      // Check if the file has `if (!process.env.NODE_TEST_CONTEXT)` wrapping `runMain()`\n      const hasRequireMainCheck = node.body.some(\n        (n) =>\n          n.type === 'IfStatement' &&\n          n.test.type === 'UnaryExpression' &&\n          n.test.operator === '!' &&\n          n.test.argument.type === 'MemberExpression' &&\n          n.test.argument.object.type === 'MemberExpression' &&\n          n.test.argument.object.object.name === 'process' &&\n          n.test.argument.object.property.name === 'env' &&\n          n.test.argument.property.name === 'NODE_TEST_CONTEXT' &&\n          n.consequent.body.some(\n            (innerNode) =>\n              innerNode.type === 'ExpressionStatement' &&\n              innerNode.expression.type === 'CallExpression' &&\n              innerNode.expression.callee.name === 'runMain'\n          )\n      )\n\n      if (!hasRunMainAtTopLevel && !hasRequireMainCheck) {\n        context.report({\n          node,\n          message: 'This file should be a script and contain a `runMain()` expression',\n        })\n      }\n    },\n  }),\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowProtectedDirectoryImport.js",
    "content": "import path from 'node:path'\nimport { minimatch } from 'minimatch'\n\nimport resolvePackage from 'eslint-module-utils/resolve.js'\nimport moduleVisitorPackage from 'eslint-module-utils/moduleVisitor.js'\nimport importTypePackage from 'eslint-plugin-import/lib/core/importType.js'\n\nconst moduleVisitor = moduleVisitorPackage.default\nconst importType = importTypePackage.default\nconst resolve = resolvePackage.default\n\nexport default {\n  meta: {\n    docs: {\n      description:\n        'Consider directories containing an \"index\" file as protected, and disallow importing modules from them.',\n    },\n    schema: [\n      {\n        type: 'object',\n        properties: {\n          ignore: {\n            type: 'array',\n            items: {\n              type: 'string',\n            },\n          },\n        },\n        additionalProperties: false,\n      },\n    ],\n  },\n  /**\n   * Create an ESLint rule to disallow importing modules from protected directories.\n   *\n   * @returns {Record<string, Function>}\n   */\n  create(context) {\n    return moduleVisitor((source) => {\n      const protectedDirectory = getFirstProtectedDirectory(source.value, context)\n      if (protectedDirectory) {\n        context.report(source, `${protectedDirectory} is a protected directory, import from its index module instead`)\n      }\n    })\n  },\n}\n\nfunction getFirstProtectedDirectory(importedModule, context) {\n  // only consider relative and absolute paths, no package or builtin imports\n  if (!['absolute', 'sibling', 'index', 'parent'].includes(importType(importedModule, context))) {\n    return\n  }\n\n  // only consider imports that can be resolved\n  if (!resolve(importedModule, context)) {\n    return\n  }\n\n  return findProtectedDirectory(splitLast(importedModule)[0])\n\n  function findProtectedDirectory(potentialProtectedDirectory) {\n    const [parentPotentialProtectedDirectory, basename] = splitLast(potentialProtectedDirectory)\n    if (basename === '' || basename === '..' || basename === '.') {\n      return\n    }\n\n    // Look for a directory higher in the hierarchy first\n    const parentProtectedDirectory = findProtectedDirectory(parentPotentialProtectedDirectory)\n    if (parentProtectedDirectory) {\n      return parentProtectedDirectory\n    }\n\n    // If we can import an index file within the directory, consider it protected.\n    const resolvedPath = resolve(`${potentialProtectedDirectory}/index`, context)\n    if (!resolvedPath) {\n      return\n    }\n\n    // Make sure we shouldn't ignore it\n    const resolvedPathRelativeToCwd = path.relative(context.getCwd(), resolvedPath)\n    const shouldIgnore = context.options[0]?.ignore?.some((glob) => minimatch(resolvedPathRelativeToCwd, glob))\n    if (shouldIgnore) {\n      return\n    }\n\n    return potentialProtectedDirectory\n  }\n}\n\nfunction splitLast(importSource) {\n  const lastIndex = importSource.lastIndexOf('/')\n  if (lastIndex < 0) {\n    return ['', importSource]\n  }\n  return [importSource.slice(0, lastIndex), importSource.slice(lastIndex + 1)]\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowSideEffects.js",
    "content": "import path from 'node:path'\n\nexport default {\n  meta: {\n    docs: {\n      description:\n        'Disallow potential side effects when evaluating modules, to ensure modules content are tree-shakable.',\n      recommended: false,\n    },\n    schema: [],\n  },\n  create(context) {\n    const filename = context.getFilename()\n    if (pathsWithSideEffect.has(filename)) {\n      return {}\n    }\n    return {\n      Program(node) {\n        reportPotentialSideEffect(context, node)\n      },\n    }\n  },\n}\n\nconst packagesRoot = path.resolve(import.meta.dirname, '..', 'packages')\n\n// Those modules are known to have side effects when evaluated\nconst pathsWithSideEffect = new Set([\n  `${packagesRoot}/logs/src/entries/main.ts`,\n  `${packagesRoot}/rum/src/entries/main.ts`,\n  `${packagesRoot}/rum-slim/src/entries/main.ts`,\n])\n\n// Those packages are known to have no side effects when evaluated\nconst packagesWithoutSideEffect = new Set([\n  '@datadog/browser-core',\n  '@datadog/browser-rum-core',\n  '@datadog/browser-rum-react/internal',\n  'react',\n  'react-router-dom',\n  'vue',\n  'vue-router',\n  '@angular/core',\n  '@angular/router',\n  'rxjs',\n])\n\n/**\n * Iterate over the given node and its children, and report any node that may have a side effect\n * when evaluated.\n *\n * @example\n * const foo = 1     // OK, this statement can't have any side effect\n * foo()             // KO, we don't know what 'foo' does, report this\n * function bar() {  // OK, a function declaration doesn't have side effects\n *    foo()          // OK, this statement won't be executed when evaluating the module code\n * }\n */\nfunction reportPotentialSideEffect(context, node) {\n  // This acts like an authorized list of syntax nodes to use directly in the body of a module.  All\n  // those nodes should not have a side effect when evaluated.\n  //\n  // This list is probably not complete, feel free to add more cases if you encounter an unhandled\n  // node.\n  switch (node.type) {\n    case 'Program':\n      node.body.forEach((child) => reportPotentialSideEffect(context, child))\n      return\n    case 'TemplateLiteral':\n      node.expressions.forEach((child) => reportPotentialSideEffect(context, child))\n      return\n    case 'ExportNamedDeclaration':\n    case 'ExportAllDeclaration':\n    case 'ImportDeclaration':\n      if (node.declaration) {\n        reportPotentialSideEffect(context, node.declaration)\n      } else if (\n        node.source &&\n        node.importKind !== 'type' &&\n        !isAllowedImport(context.getFilename(), node.source.value)\n      ) {\n        context.report({\n          node: node.source,\n          message: 'This file cannot import modules with side-effects',\n        })\n      }\n      return\n    case 'VariableDeclaration':\n      node.declarations.forEach((child) => reportPotentialSideEffect(context, child))\n      return\n    case 'VariableDeclarator':\n      if (node.init) {\n        reportPotentialSideEffect(context, node.init)\n      }\n      return\n    case 'ArrayExpression':\n      node.elements.forEach((child) => reportPotentialSideEffect(context, child))\n      return\n    case 'UnaryExpression':\n      reportPotentialSideEffect(context, node.argument)\n      return\n    case 'ObjectExpression':\n      node.properties.forEach((child) => reportPotentialSideEffect(context, child))\n      return\n    case 'SpreadElement':\n      reportPotentialSideEffect(context, node.argument)\n      return\n    case 'Property':\n      reportPotentialSideEffect(context, node.key)\n      reportPotentialSideEffect(context, node.value)\n      return\n    case 'BinaryExpression':\n    case 'LogicalExpression':\n      reportPotentialSideEffect(context, node.left)\n      reportPotentialSideEffect(context, node.right)\n      return\n    case 'TSAsExpression':\n    case 'ExpressionStatement':\n      reportPotentialSideEffect(context, node.expression)\n      return\n    case 'MemberExpression':\n      reportPotentialSideEffect(context, node.object)\n      reportPotentialSideEffect(context, node.property)\n      return\n    case 'ConditionalExpression':\n    case 'FunctionExpression':\n    case 'ArrowFunctionExpression':\n    case 'FunctionDeclaration':\n    case 'ClassDeclaration':\n    case 'TSEnumDeclaration':\n    case 'TSInterfaceDeclaration':\n    case 'TSTypeAliasDeclaration':\n    case 'TSModuleDeclaration':\n    case 'TSDeclareFunction':\n    case 'TSInstantiationExpression':\n    case 'Literal':\n    case 'Identifier':\n      return\n    case 'CallExpression':\n      if (isAllowedCallExpression(node)) {\n        return\n      }\n      break\n    case 'NewExpression':\n      if (isAllowedNewExpression(node)) {\n        return\n      }\n      break\n  }\n\n  // If the node doesn't match any of the condition above, report it\n  context.report({\n    node,\n    message: `${node.type} can have side effects when the module is evaluated. \\\nMaybe move it in a function declaration?`,\n  })\n}\n\n/**\n * Make sure an 'import' statement does not pull a module or package with side effects.\n */\nfunction isAllowedImport(basePath, source) {\n  if (source.startsWith('.')) {\n    const resolvedPath = `${path.resolve(path.dirname(basePath), source)}.ts`\n    return !pathsWithSideEffect.has(resolvedPath)\n  }\n  return packagesWithoutSideEffect.has(source)\n}\n\n/**\n * Authorize some call expressions. Feel free to add more exceptions here. Good candidates would\n * be functions that are known to be ECMAScript functions without side effects, that are likely to\n * be considered as pure functions by the bundler.\n *\n * You can experiment with Rollup tree-shaking strategy to ensure your function is known to be pure.\n * https://rollupjs.org/repl/?version=2.38.5&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMiUyRiUyRiUyMFB1cmUlMjBmdW5jdGlvbnMlNUNubmV3JTIwV2Vha01hcCgpJTVDbk9iamVjdC5rZXlzKCklNUNuJTVDbiUyRiUyRiUyMFNpZGUlMjBlZmZlY3QlMjBmdW5jdGlvbnMlNUNuZm9vKCklMjAlMkYlMkYlMjB1bmtub3duJTIwZnVuY3Rpb25zJTIwYXJlJTIwY29uc2lkZXJlZCUyMHRvJTIwaGF2ZSUyMHNpZGUlMjBlZmZlY3RzJTVDbmFsZXJ0KCdhYWEnKSU1Q25uZXclMjBNdXRhdGlvbk9ic2VydmVyKCgpJTIwJTNEJTNFJTIwJTdCJTdEKSUyMiUyQyUyMmlzRW50cnklMjIlM0F0cnVlJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmVzJTIyJTJDJTIybmFtZSUyMiUzQSUyMm15QnVuZGxlJTIyJTJDJTIyYW1kJTIyJTNBJTdCJTIyaWQlMjIlM0ElMjIlMjIlN0QlMkMlMjJnbG9iYWxzJTIyJTNBJTdCJTdEJTdEJTJDJTIyZXhhbXBsZSUyMiUzQW51bGwlN0Q=\n *\n * Webpack is not as smart as Rollup, and it usually treat all call expressions as impure, but it\n * could be fine to allow it nonetheless at it pulls very little code.\n */\nfunction isAllowedCallExpression({ callee }) {\n  // Allow \"Object.keys()\"\n  if (callee.type === 'MemberExpression' && callee.object.name === 'Object' && callee.property.name === 'keys') {\n    return true\n  }\n\n  // Allow \".concat()\"\n  if (callee.type === 'MemberExpression' && callee.property.name === 'concat') {\n    return true\n  }\n\n  return false\n}\n\n/**\n * Authorize some 'new' expressions. Feel free to add more exceptions here. Good candidates would\n * be functions that are known to be ECMAScript functions without side effects, that are likely to\n * be considered as pure functions by the bundler.\n *\n * You can experiment with Rollup tree-shaking strategy to ensure your function is known to be pure.\n * https://rollupjs.org/repl/?version=2.38.5&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMiUyRiUyRiUyMFB1cmUlMjBmdW5jdGlvbnMlNUNubmV3JTIwV2Vha01hcCgpJTVDbk9iamVjdC5rZXlzKCklNUNuJTVDbiUyRiUyRiUyMFNpZGUlMjBlZmZlY3QlMjBmdW5jdGlvbnMlNUNuZm9vKCklMjAlMkYlMkYlMjB1bmtub3duJTIwZnVuY3Rpb25zJTIwYXJlJTIwY29uc2lkZXJlZCUyMHRvJTIwaGF2ZSUyMHNpZGUlMjBlZmZlY3RzJTVDbmFsZXJ0KCdhYWEnKSU1Q25uZXclMjBNdXRhdGlvbk9ic2VydmVyKCgpJTIwJTNEJTNFJTIwJTdCJTdEKSUyMiUyQyUyMmlzRW50cnklMjIlM0F0cnVlJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmVzJTIyJTJDJTIybmFtZSUyMiUzQSUyMm15QnVuZGxlJTIyJTJDJTIyYW1kJTIyJTNBJTdCJTIyaWQlMjIlM0ElMjIlMjIlN0QlMkMlMjJnbG9iYWxzJTIyJTNBJTdCJTdEJTdEJTJDJTIyZXhhbXBsZSUyMiUzQW51bGwlN0Q=\n *\n * Webpack is not as smart as Rollup, and it usually treat all 'new' expressions as impure, but it\n * could be fine to allow it nonetheless at it pulls very little code.\n */\nfunction isAllowedNewExpression({ callee }) {\n  switch (callee.name) {\n    // Allow some native constructors\n    case 'RegExp':\n    case 'WeakMap':\n    case 'WeakSet':\n    case 'Set':\n    case 'Map':\n      return true\n\n    default:\n      return false\n  }\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowSpecImport.js",
    "content": "export default {\n  meta: {\n    docs: {\n      description: 'Disallow importing spec file code to avoid to execute the tests from the imported spec file twice',\n      recommended: false,\n    },\n    schema: [],\n  },\n  create(context) {\n    return {\n      ImportDeclaration(node) {\n        if (isSpecFile(node.source.value)) {\n          context.report({\n            node: node.source,\n            message: 'Members of a spec file must not be imported',\n          })\n        }\n      },\n    }\n  },\n}\n\nfunction isSpecFile(filename) {\n  return /\\.spec(\\.ts)?$/.test(filename)\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowTestImportExportFromSrc.js",
    "content": "export default {\n  meta: {\n    docs: {\n      description:\n        'Disallow importing or exporting test code in src code to avoid bloating customer package with test code',\n      recommended: false,\n    },\n    schema: [],\n  },\n  create(context) {\n    return {\n      ImportDeclaration(node) {\n        checkTestImportExportFromSrc(context, node)\n      },\n      ExportNamedDeclaration(node) {\n        checkTestImportExportFromSrc(context, node)\n      },\n      ExportAllDeclaration(node) {\n        checkTestImportExportFromSrc(context, node)\n      },\n    }\n  },\n}\n\nfunction checkTestImportExportFromSrc(context, node) {\n  if (!isTestCode(context.getFilename()) && node.source && isTestCode(node.source.value)) {\n    context.report({\n      node: node.source,\n      message: 'Test code import or export is not allowed in src code',\n    })\n  }\n}\n\nfunction isTestCode(filename) {\n  return /(\\/test|\\.specHelper|\\.spec)/.test(filename)\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowUrlConstructorPatchValues.js",
    "content": "export default {\n  meta: {\n    docs: {\n      description: 'Disallow problematic URL constructor patched values.',\n      recommended: false,\n    },\n    schema: [],\n  },\n\n  create(context) {\n    return {\n      'Program:exit'(node) {\n        const globalScope = context.sourceCode.getScope(node)\n        const variable = globalScope.set.get('URL')\n\n        if (variable && variable.defs.length === 0) {\n          variable.references.forEach((ref) => {\n            const idNode = ref.identifier\n            const parent = idNode.parent\n\n            if (parent && parent.type === 'NewExpression' && parent.callee === idNode) {\n              context.report(idNode, 'This value might be patched. Use `buildUrl` from @datadog/browser-core instead')\n            }\n          })\n        }\n      },\n    }\n  },\n}\n"
  },
  {
    "path": "eslint-local-rules/disallowZoneJsPatchedValues.js",
    "content": "const PROBLEMATIC_IDENTIFIERS = {\n  // Using the patched `MutationObserver` from Zone.js triggers an infinite callback loop on some\n  // occasion, see PRs #376 #866 #1530\n  MutationObserver: 'Use `getMutationObserverConstructor` from @datadog/browser-rum-core instead',\n\n  // Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular\n  // component, see issue PR #2030\n  setTimeout: 'Use `setTimeout` from @datadog/browser-core instead',\n  clearTimeout: 'Use `clearTimeout` from @datadog/browser-core instead',\n\n  // We didn't stumble on cases where using the patched `setInterval` from Zone.js is problematic\n  // yet, but still consider it problematic in prevention and to unify its usages with `setTimeout`.\n  setInterval: 'Use `setInterval` from @datadog/browser-core instead',\n  clearInterval: 'Use `clearInterval` from @datadog/browser-core instead',\n\n  // Using the patched `addEventListener` from Zone.js might trigger a memory leak in Firefox, see\n  // PR #1860\n  addEventListener: 'Use `addEventListener` from @datadog/browser-core instead',\n  removeEventListener: 'Use `addEventListener().stop` from @datadog/browser-core instead',\n\n  // Using the patched `fetch` from Zone.js triggers unnecessary Angular change detection cycles,\n  // see PR #4117.\n  fetch: 'Use `fetch` from @datadog/browser-core instead',\n}\n\nexport default {\n  meta: {\n    docs: {\n      description: 'Disallow problematic ZoneJs patched values.',\n      recommended: false,\n    },\n    schema: [],\n  },\n  create(context) {\n    const parserServices = context.sourceCode.parserServices\n    const checker = parserServices.program.getTypeChecker()\n\n    return {\n      Identifier(node) {\n        if (\n          Object.hasOwn(PROBLEMATIC_IDENTIFIERS, node.name) &&\n          // Using those identifiers inside type definition is not problematic\n          !isInTypeDefinition(node)\n        ) {\n          const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node)\n          const symbol = checker.getSymbolAtLocation(originalNode)\n          if (symbol && isDeclaredInTsDomLib(symbol.declarations[0])) {\n            context.report(node, `This value might be patched by Zone.js. ${PROBLEMATIC_IDENTIFIERS[node.name]}`)\n          }\n        }\n      },\n    }\n  },\n}\n\n/**\n * Wether the declaration is inside the TypeScript DOM declaration file (i.e. lib.dom.d.ts),\n * indicating that it's a \"native\" browser API and not a function that we declare ourselves.\n */\nfunction isDeclaredInTsDomLib(declaration) {\n  if (declaration.parent) {\n    return isDeclaredInTsDomLib(declaration.parent)\n  }\n  return declaration.isDeclarationFile && declaration.path.endsWith('/lib.dom.d.ts')\n}\n\n/**\n * Whether the symbol is a concrete value and not a type\n */\n\nfunction isInTypeDefinition(node) {\n  let types = new Set()\n  while (node) {\n    types.add(node.type)\n    if (isTypeDefinition(node)) {\n      return true\n    }\n    node = node.parent\n  }\n  return false\n}\n\nconst typeDefinitionNodeTypes = new Set(['TSAsExpression', 'TSTypeAliasDeclaration', 'TSInterfaceDeclaration'])\nfunction isTypeDefinition(node) {\n  return typeDefinitionNodeTypes.has(node.type)\n}\n"
  },
  {
    "path": "eslint-local-rules/enforceProdDepsImports.js",
    "content": "import fs from 'node:fs'\n\nimport moduleVisitorPackage from 'eslint-module-utils/moduleVisitor.js'\nimport importTypePackage from 'eslint-plugin-import/lib/core/importType.js'\nimport pkgUpPackage from 'eslint-module-utils/pkgUp.js'\n\nconst moduleVisitor = moduleVisitorPackage.default\nconst pkgUp = pkgUpPackage.default\nconst importType = importTypePackage.default\n\n// The import/no-extraneous-dependencies rule cannot catch this issue[1] where we imported an\n// aliased package in production code, because it resolves[2] the alias to the real package name, and\n// the real package name is a peer dependency, so it is allowed.\n//\n// This custom rule is more straightforward than the import/no-extraneous-dependencies rule, and\n// should better suit our needs.\n//\n// [1]: https://github.com/DataDog/browser-sdk/pull/3405\n// [2]: https://github.com/import-js/eslint-plugin-import/blob/4f145a2c64af4931f4bf3ae951c8b719b544718f/src/rules/no-extraneous-dependencies.js#L221-L223\n\nconst packageJsonCache = new Map()\n\nexport default {\n  meta: {\n    docs: {\n      description: 'Forbids importing non-prod dependencies in prod files',\n    },\n    schema: [],\n  },\n  /**\n   * Create an ESLint rule to enforce that only prod dependencies are imported in prod files.\n   *\n   * @returns {Record<string, Function>}\n   */\n  create(context) {\n    const packageJson = readPackageJson(pkgUp({ cwd: context.getFilename() }))\n\n    return moduleVisitor((source) => {\n      const importTypeResult = importType(source.value, context)\n      // Use an allow list instead of a deny list to make the rule more future-proof.\n      if (importTypeResult === 'parent' || importTypeResult === 'sibling') {\n        return\n      }\n\n      const packageName = parsePackageName(source.value)\n      if (!packageJson.dependencies?.[packageName] && !packageJson.peerDependencies?.[packageName]) {\n        context.report(source, `${packageName} in not a prod or peer dependency`)\n      }\n    })\n  },\n}\n\n/**\n * Parses the package name from an import source, in particular removes a potential entry path.\n *\n * @example\n * ```ts\n * parsePackageName('foo/bar') // 'foo'\n * parsePackageName('@foo/bar/baz') // '@foo/bar'\n * ```\n */\nfunction parsePackageName(importSource) {\n  return importSource.split('/', importSource.startsWith('@') ? 2 : 1).join('/')\n}\n\nfunction readPackageJson(packageJsonPath) {\n  if (!packageJsonCache.has(packageJsonPath)) {\n    packageJsonCache.set(packageJsonPath, JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')))\n  }\n  return packageJsonCache.get(packageJsonPath)\n}\n"
  },
  {
    "path": "eslint-local-rules/index.js",
    "content": "import disallowSideEffects from './disallowSideEffects.js'\nimport disallowEnumExports from './disallowEnumExports.js'\nimport disallowSpecImport from './disallowSpecImport.js'\nimport disallowProtectedDirectoryImport from './disallowProtectedDirectoryImport.js'\nimport disallowTestImportExportFromSrc from './disallowTestImportExportFromSrc.js'\nimport disallowZoneJsPatchedValues from './disallowZoneJsPatchedValues.js'\nimport disallowUrlConstructorPatchValues from './disallowUrlConstructorPatchValues.js'\nimport disallowGenericUtils from './disallowGenericUtils.js'\nimport disallowNonScripts from './disallowNonScripts.js'\nimport enforceProdDepsImports from './enforceProdDepsImports.js'\nimport secureCommandExecution from './secureCommandExecution.js'\nimport monitorUntilCommentRules from './monitorUntilCommentRules.js'\n\n// Declare the local rules used by the Browser SDK\n//\n// See https://eslint.org/docs/developer-guide/working-with-rules for documentation on how to write\n// rules.\n//\n// You can use https://astexplorer.net/ to explore the parsed data structure of a code snippet.\n// Choose '@typescript-eslint/parser' as a parser to have the exact same structure as our ESLint\n// parser.\nexport default {\n  'disallow-side-effects': disallowSideEffects,\n  'disallow-enum-exports': disallowEnumExports,\n  'disallow-spec-import': disallowSpecImport,\n  'disallow-protected-directory-import': disallowProtectedDirectoryImport,\n  'disallow-test-import-export-from-src': disallowTestImportExportFromSrc,\n  'disallow-zone-js-patched-values': disallowZoneJsPatchedValues,\n  'disallow-url-constructor-patched-values': disallowUrlConstructorPatchValues,\n  'disallow-generic-utils': disallowGenericUtils,\n  'disallow-non-scripts': disallowNonScripts,\n  'enforce-prod-deps-imports': enforceProdDepsImports,\n  'secure-command-execution': secureCommandExecution,\n  ...monitorUntilCommentRules,\n}\n"
  },
  {
    "path": "eslint-local-rules/monitorUntilCommentRules.js",
    "content": "const METHODS_TO_CHECK = ['addTelemetryDebug', 'addTelemetryMetrics']\nconst MONITOR_COMMENT_FORMAT = /^\\s*monitor-until: (\\d{4}-\\d{2}-\\d{2}|forever)/\n\nexport default {\n  'enforce-monitor-until-comment': {\n    meta: {\n      docs: {\n        description:\n          'Force to specify an expiration date to telemetry debug and metrics events in order to clean them regularly',\n        recommended: false,\n      },\n      schema: [],\n    },\n    create(context) {\n      const sourceCode = context.getSourceCode()\n\n      return {\n        CallExpression(node) {\n          const methodName = node.callee.name\n          if (!METHODS_TO_CHECK.includes(methodName)) {\n            return\n          }\n\n          const monitorComment = sourceCode\n            .getCommentsBefore(node)\n            .find((comment) => MONITOR_COMMENT_FORMAT.test(comment.value))\n\n          if (!monitorComment) {\n            context.report(node, 'Missing `// monitor-until: YYYY-MM-DD` or `// monitor-until: forever` comment')\n          }\n        },\n      }\n    },\n  },\n  'monitor-until-comment-expired': {\n    meta: {\n      docs: {\n        description: 'Report expired monitor-until comments',\n        recommended: false,\n      },\n      schema: [],\n    },\n    create(context) {\n      return {\n        Program() {\n          const now = new Date()\n          const comments = context.getSourceCode().getAllComments()\n          comments.forEach((comment) => {\n            const monitorCommentMatch = comment.value.match(MONITOR_COMMENT_FORMAT)\n            if (!monitorCommentMatch || monitorCommentMatch[1] === 'forever') {\n              return\n            }\n\n            if (new Date(monitorCommentMatch[1]) < now) {\n              context.report(comment, `Expired: ${comment.value}`)\n            }\n          })\n        },\n      }\n    },\n  },\n}\n"
  },
  {
    "path": "eslint-local-rules/secureCommandExecution.js",
    "content": "export default {\n  meta: {\n    docs: {\n      description: 'Check command execution within nodejs scripts',\n    },\n    schema: [],\n  },\n  create(context) {\n    return {\n      'TaggedTemplateExpression[tag.name=\"command\"]'(node) {\n        if (!isCommandExecuted(node)) {\n          context.report({\n            node,\n            message: 'Command is missing a `run()` call',\n          })\n        }\n\n        if (isCommandContainsShellCharacters(node)) {\n          context.report({\n            node,\n            message: \"Command is containing shell characters. This is probably a mistake as it won't run in a shell.\",\n          })\n        }\n      },\n    }\n  },\n}\n\nfunction isCommandExecuted(node) {\n  let methodCallNames = []\n  let currentMethodCall = node.parent\n\n  // Iterate over the builder pattern method calls. For the expression \"`foo`.bar().baz()\" AST looks\n  // like this:\n  //\n  //                         CallExpression\n  //                          | callee\n  //                         MemberExpression\n  //                         / object      \\ property\n  //                       CallExpression  Identifier (baz)\n  //                        | callee\n  //                       MemberExpression\n  //                       / object     \\ property\n  // TaggedTemplateExpression (`foo`)   Identifier (bar)\n  //\n  // From the TaggedTemplateExpression node, we need to recurse on parents, getting method call\n  // names stored in member expression property identifiers.\n  while (currentMethodCall.type === 'MemberExpression' && currentMethodCall.parent.type === 'CallExpression') {\n    methodCallNames.push(currentMethodCall.property.name)\n    currentMethodCall = currentMethodCall.parent.parent\n  }\n\n  return methodCallNames.includes('run')\n}\n\nfunction isCommandContainsShellCharacters(node) {\n  return node.quasi.quasis.some((quasi) => /[~\\\\$\"'><(){}[\\]]/.test(quasi.value.raw))\n}\n"
  },
  {
    "path": "eslint.config.mjs",
    "content": "// @ts-check .ts config files are still experimental: https://github.com/eslint/eslint/discussions/17726\n\nimport eslint from '@eslint/js'\nimport * as tseslint from 'typescript-eslint'\nimport importPlugin from 'eslint-plugin-import'\nimport unicornPlugin from 'eslint-plugin-unicorn'\nimport jsdocPlugin from 'eslint-plugin-jsdoc'\nimport jasmine from 'eslint-plugin-jasmine'\nimport globals from 'globals'\n// eslint-disable-next-line local-rules/disallow-protected-directory-import\nimport eslintLocalRules from './eslint-local-rules/index.js'\nimport { SCHEMAS } from './scripts/lib/generatedSchemaTypes.ts'\n\nconst SPEC_FILES = '**/*.{spec,specHelper}.{ts,tsx,js}'\nconst MONITOR_UNTIL_COMMENT_EXPIRED_LEVEL = process.env.MONITOR_UNTIL_COMMENT_EXPIRED_LEVEL || 'warn'\n\n// eslint-disable-next-line import/no-default-export\nexport default tseslint.config(\n  eslint.configs.recommended,\n  tseslint.configs.recommendedTypeChecked,\n  importPlugin.flatConfigs.recommended,\n  importPlugin.flatConfigs.typescript,\n  {\n    ignores: [\n      ...SCHEMAS.map((schema) => schema.typesPath),\n      'packages/*/bundle',\n      'packages/*/cjs',\n      'packages/*/esm',\n      'test/**/dist',\n      'test/**/.next',\n      'test/apps/react-heavy-spa',\n      'test/apps/react-shopist-like',\n      'test/apps/microfrontend',\n      'test/apps/nextjs',\n      'test/apps/angular-app',\n      'test/apps/vue-router-app',\n      'test/apps/nuxt-app',\n      'sandbox',\n      'coverage',\n      'rum-events-format',\n      '.yarn',\n      '**/playwright-report',\n      'generated-docs',\n      'developer-extension/.wxt',\n      'developer-extension/dist',\n    ],\n  },\n\n  {\n    linterOptions: {\n      reportUnusedDisableDirectives: 'error',\n    },\n  },\n\n  {\n    plugins: {\n      unicorn: unicornPlugin,\n      'local-rules': { rules: eslintLocalRules },\n      jsdoc: jsdocPlugin,\n      jasmine,\n    },\n\n    settings: {\n      'import/resolver': {\n        typescript: true,\n      },\n    },\n\n    languageOptions: {\n      parserOptions: {\n        project: [\n          './tsconfig.default.json',\n          './tsconfig.scripts.json',\n          './developer-extension/tsconfig.json',\n          './packages/rum-nextjs/tsconfig.json',\n          './test/e2e/tsconfig.json',\n          './test/performance/tsconfig.json',\n          './test/apps/**/tsconfig.json',\n        ],\n        sourceType: 'module',\n\n        // Without this option, typescript-eslint fails to lint .js files because we don't use\n        // `allowJs: true` in the TypeScript configuration. Same issue as\n        // https://github.com/typescript-eslint/typescript-eslint/issues/9749.\n        //\n        // Enabling `allowJs` would be a better solution, but right now it's not possible because of a\n        // pretty small reason with big implications: `webpack.base.js` includes\n        // `tsconfig-paths-webpack-plugin`, and this file includes Node.js types via a <reference>\n        // directive (see https://unpkg.com/browse/tsconfig-paths-webpack-plugin@4.2.0/lib/plugin.d.ts).\n        //\n        // Because of this, Node.js types are included in the whole project, and because some of them\n        // are slightly different from the DOM/Browser types, some annoying typecheck errors are raised.\n        //\n        // So, ideally, we should:\n        // * add `allowJs: true` in the TypeScript configuration\n        // * have different tsconfig.json configurations for packages and scripts\n        // * when typechecking, run `tsc` multiple time with each configuration (like we do for the\n        //   developer-extension)\n        // * then remove this option\n        disallowAutomaticSingleRunInference: true,\n      },\n    },\n\n    rules: {\n      'arrow-body-style': 'error',\n      camelcase: ['error', { properties: 'never', allow: ['_dd_temp_'] }],\n      curly: 'error',\n      eqeqeq: ['error', 'smart'],\n      'guard-for-in': 'error',\n      'id-denylist': [\n        'error',\n        'any',\n        'Number',\n        'number',\n        'String',\n        'string',\n        'Boolean',\n        'boolean',\n        'Undefined',\n        'undefined',\n      ],\n      'id-match': 'error',\n      'no-bitwise': 'error',\n      'no-caller': 'error',\n      'no-else-return': 'error',\n      'no-eq-null': 'error',\n      'no-eval': 'error',\n      'no-extra-bind': 'error',\n      'no-inner-declarations': 'error',\n      'no-new-func': 'error',\n      'no-new-wrappers': 'error',\n      'no-sequences': 'error',\n      'no-template-curly-in-string': 'error',\n      'no-undef-init': 'error',\n      'no-unreachable': 'error',\n      'no-useless-concat': 'error',\n      'object-shorthand': 'error',\n      'one-var': ['error', 'never'],\n      'prefer-rest-params': 'off',\n      'prefer-template': 'error',\n      'prefer-object-spread': 'error',\n      quotes: ['error', 'single', { avoidEscape: true }],\n      radix: 'error',\n      'require-await': 'error',\n      'spaced-comment': [\n        'error',\n        'always',\n        {\n          line: {\n            markers: ['/'],\n          },\n          block: {\n            balanced: true,\n          },\n        },\n      ],\n\n      '@typescript-eslint/array-type': ['error', { default: 'array-simple' }],\n      '@typescript-eslint/ban-ts-comment': [\n        'error',\n        {\n          'ts-expect-error': 'allow-with-description',\n          'ts-ignore': 'allow-with-description',\n          'ts-nocheck': 'allow-with-description',\n          'ts-check': false,\n        },\n      ],\n      '@typescript-eslint/no-restricted-types': [\n        'error',\n        {\n          types: {\n            /* eslint-disable id-denylist */\n            Object: { message: 'Avoid using the `Object` type. Did you mean `object`?' },\n            Boolean: { message: 'Avoid using the `Boolean` type. Did you mean `boolean`?' },\n            Number: { message: 'Avoid using the `Number` type. Did you mean `number`?' },\n            String: { message: 'Avoid using the `String` type. Did you mean `string`?' },\n            Symbol: { message: 'Avoid using the `Symbol` type. Did you mean `symbol`?' },\n            /* eslint-enable id-denylist */\n          },\n        },\n      ],\n      '@typescript-eslint/consistent-type-imports': ['error'],\n      '@typescript-eslint/consistent-type-exports': 'error',\n      '@typescript-eslint/consistent-type-definitions': ['error', 'interface'],\n      '@typescript-eslint/member-ordering': [\n        'error',\n        {\n          default: {\n            memberTypes: [\n              'signature',\n              'public-static-field',\n              'protected-static-field',\n              'private-static-field',\n              'public-decorated-field',\n              'public-instance-field',\n              'public-abstract-field',\n              'protected-decorated-field',\n              'protected-instance-field',\n              'protected-abstract-field',\n              'private-decorated-field',\n              'private-instance-field',\n              'public-constructor',\n              'protected-constructor',\n              'private-constructor',\n              'public-static-method',\n              'protected-static-method',\n              'private-static-method',\n              'public-decorated-method',\n              'public-instance-method',\n              'public-abstract-method',\n              'protected-decorated-method',\n              'protected-instance-method',\n              'protected-abstract-method',\n              'private-decorated-method',\n              'private-instance-method',\n            ],\n            order: 'as-written',\n          },\n        },\n      ],\n      '@typescript-eslint/no-empty-function': 'error',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/no-unsafe-argument': 'off',\n      '@typescript-eslint/no-unsafe-assignment': 'off',\n      '@typescript-eslint/no-unsafe-member-access': 'off',\n      '@typescript-eslint/no-unused-vars': ['error', { args: 'all', argsIgnorePattern: '^_', vars: 'all' }],\n      '@typescript-eslint/triple-slash-reference': ['error', { path: 'always', types: 'prefer-import', lib: 'always' }],\n      '@typescript-eslint/no-floating-promises': [\n        'error',\n        { allowForKnownSafeCalls: [{ from: 'package', name: ['describe', 'it', 'test'], package: 'node:test' }] },\n      ],\n\n      'import/no-cycle': 'error',\n      'import/no-default-export': 'error',\n      'import/no-duplicates': 'error',\n      'import/no-extraneous-dependencies': 'error',\n      'import/no-unresolved': [\n        'error',\n        {\n          commonjs: true,\n          ignore: [\n            // The json-schema-to-typescript is built on demand (see scripts/cli build_json2type)\n            // and is not always available in the node_modules. Skip the import check.\n            'json-schema-to-typescript',\n          ],\n        },\n      ],\n      'import/no-useless-path-segments': 'error',\n      'import/order': [\n        'error',\n        {\n          // This is the default order plus 'internal', which is imports like\n          // @datadog/browser-core/test (references a file/folder within a local package)\n          // https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups\n          groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],\n        },\n      ],\n\n      'jasmine/no-focused-tests': 'error',\n      'jsdoc/check-alignment': 'error',\n      'jsdoc/check-indentation': 'error',\n      'jsdoc/no-blank-blocks': 'error',\n      'jsdoc/sort-tags': [\n        'error',\n        {\n          linesBetween: 0,\n          tagSequence: [\n            {\n              tags: [\n                'category',\n                'packageDocumentation',\n                'internal',\n                'deprecated',\n                'experimental',\n                'defaultValue',\n                'param',\n                'return',\n                'returns',\n                'see',\n                'example',\n              ],\n            },\n          ],\n        },\n      ],\n      'jsdoc/require-description': 'error',\n      'jsdoc/require-param-description': 'error',\n      'jsdoc/require-hyphen-before-param-description': 'error',\n      'jsdoc/tag-lines': ['error', 'any', { startLines: 1 }],\n      'jsdoc/require-property-description': 'error',\n      'jsdoc/require-property-name': 'error',\n      'jsdoc/check-param-names': 'error',\n      'jsdoc/multiline-blocks': 'error',\n\n      'local-rules/disallow-test-import-export-from-src': 'error',\n      'local-rules/disallow-generic-utils': 'error',\n      'local-rules/disallow-protected-directory-import': [\n        'error',\n        {\n          ignore: [\n            // ignore packages index files so `[...]/test/*` can import from the `[...]/src/*`\n            'packages/*/src/index.ts',\n          ],\n        },\n      ],\n\n      'unicorn/filename-case': ['error', { case: 'camelCase' }],\n      'unicorn/no-empty-file': 'error',\n    },\n  },\n\n  {\n    files: ['**/*Event.types.ts'],\n    rules: {\n      '@typescript-eslint/naming-convention': [\n        'error',\n        {\n          leadingUnderscore: 'allow',\n          selector: 'property',\n          format: ['snake_case'],\n        },\n        {\n          leadingUnderscore: 'allow',\n          selector: 'objectLiteralProperty',\n          format: ['UPPER_CASE'],\n        },\n      ],\n    },\n  },\n\n  {\n    files: ['scripts/**'],\n    rules: {\n      'import/extensions': ['error', 'ignorePackages'],\n    },\n  },\n\n  {\n    files: ['scripts/**', 'packages/*/scripts/**'],\n    ignores: ['**/lib/**'],\n    rules: {\n      'unicorn/filename-case': ['error', { case: 'kebabCase' }],\n    },\n  },\n\n  {\n    files: ['scripts/**', 'packages/*/scripts/**'],\n    ignores: ['**/lib/**', SPEC_FILES],\n    rules: {\n      'local-rules/secure-command-execution': 'error',\n      'local-rules/disallow-non-scripts': 'error',\n    },\n  },\n\n  {\n    // JS files. Allow weaker typings since TS can't infer types as accurately as TS files.\n    files: ['**/*.{js,mjs}'],\n    rules: {\n      '@typescript-eslint/no-unsafe-call': 'off',\n      '@typescript-eslint/no-unsafe-return': 'off',\n      '@typescript-eslint/restrict-plus-operands': 'off',\n      '@typescript-eslint/restrict-template-expressions': 'off',\n    },\n  },\n\n  // All \"production files\" = files that are used by Browser SDK users\n  {\n    files: ['packages/*/src/**/*', 'developer-extension/src/**/*'],\n    ignores: [SPEC_FILES],\n    rules: {\n      'local-rules/enforce-prod-deps-imports': ['error'],\n    },\n  },\n\n  {\n    files: ['packages/*/src/**/*.ts', 'developer-extension/src/**/*.{tsx,ts}'],\n    rules: {\n      'no-console': 'error',\n    },\n  },\n\n  {\n    files: ['packages/*/src/**/*.ts'],\n    ignores: [SPEC_FILES],\n    rules: {\n      'local-rules/enforce-monitor-until-comment': 'error',\n      // @ts-expect-error - MONITOR_UNTIL_COMMENT_EXPIRED_LEVEL is either 'warn' or 'error'\n      'local-rules/monitor-until-comment-expired': MONITOR_UNTIL_COMMENT_EXPIRED_LEVEL,\n      'local-rules/disallow-side-effects': 'error',\n      'local-rules/disallow-zone-js-patched-values': 'error',\n      'local-rules/disallow-url-constructor-patched-values': 'error',\n      'no-restricted-syntax': [\n        'error',\n        {\n          selector: 'ClassDeclaration',\n          message: 'Classes are not allowed. Use functions instead.',\n        },\n        {\n          selector: 'ArrayExpression > SpreadElement',\n          message: 'Array spread is not authorized. Please use .concat instead.',\n        },\n        {\n          selector: 'MemberExpression[object.name=\"Date\"][property.name=\"now\"]',\n          message: '`Date.now()` is not authorized. Please use `dateNow()` instead',\n        },\n        {\n          selector: 'TSEnumDeclaration:not([const=true])',\n          message: 'When possible, use `const enum` as it produces less code when transpiled.',\n        },\n\n        {\n          selector: 'TSModuleDeclaration[kind=global]',\n          message: 'Never declare global types as it will leak to the user app global scope.',\n        },\n      ],\n    },\n  },\n\n  {\n    files: ['packages/**/*.ts'],\n    rules: {\n      'local-rules/disallow-spec-import': 'error',\n      'jsdoc/no-types': 'error',\n    },\n  },\n\n  {\n    files: ['packages/*/src/**/*.ts'],\n    ignores: [SPEC_FILES],\n    rules: {\n      'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],\n    },\n  },\n\n  {\n    files: ['packages/{rum,logs,rum-slim}/src/entries/*.ts'],\n    rules: {\n      'local-rules/disallow-enum-exports': 'error',\n    },\n  },\n\n  {\n    // Files executed by nodejs\n    files: [\n      'scripts/**',\n      'test/**/*.js',\n      'eslint-local-rules/**/*.js',\n      'eslint.config.mjs',\n      'packages/*/scripts/**/*.js',\n    ],\n    languageOptions: {\n      globals: globals.node,\n    },\n    rules: {\n      '@typescript-eslint/no-require-imports': 'off',\n      'import/enforce-node-protocol-usage': ['error', 'always'],\n      'no-restricted-imports': [\n        'error',\n        {\n          paths: [\n            {\n              name: 'glob',\n              message: 'Use node:fs or node:fs/promises (fs.glob) instead.',\n            },\n          ],\n        },\n      ],\n    },\n  },\n\n  {\n    files: ['**/webpack.*.{ts,mts}', 'eslint-local-rules/**/*.js'],\n    rules: {\n      // Webpack configuration files and eslint rules files are expected to use a default export.\n      'import/no-default-export': 'off',\n    },\n  },\n\n  {\n    files: ['test/e2e/**/*.ts', 'test/performance/**/*.ts'],\n    rules: {\n      // E2E codebase is importing @datadog/browser-* packages referenced by tsconfig.\n      'import/no-extraneous-dependencies': 'off',\n    },\n  },\n\n  {\n    files: ['packages/core/src/tools/**/*.ts'],\n    ignores: [SPEC_FILES],\n    rules: {\n      'no-restricted-imports': [\n        'error',\n        {\n          patterns: [\n            {\n              group: ['../**/boot/*', '../**/browser/*', '../**/domain/*', '../**/transport/*'],\n              message: 'tools components should not import from other directories',\n            },\n          ],\n        },\n      ],\n    },\n  }\n)\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"browser-sdk\",\n  \"version\": \"6.32.0\",\n  \"description\": \"browser SDK\",\n  \"private\": true,\n  \"workspaces\": [\n    \"packages/*\",\n    \"developer-extension\",\n    \"test/e2e\",\n    \"test/performance\"\n  ],\n  \"type\": \"module\",\n  \"scripts\": {\n    \"postinstall\": \"scripts/cli init_submodule\",\n    \"build\": \"yarn workspaces foreach --all --parallel --topological run build\",\n    \"build:bundle\": \"yarn workspaces foreach --all --parallel run build:bundle\",\n    \"build:apps\": \"node scripts/build/build-test-apps.ts\",\n    \"build:docs:json\": \"typedoc --logLevel Verbose --json ./generated-docs.json\",\n    \"build:docs:html\": \"typedoc --out ./generated-docs\",\n    \"serve:docs\": \"yarn build:docs:html && npx http-server ./generated-docs -p 8080 -o\",\n    \"pack\": \"yarn workspaces foreach --all --parallel --topological --include '@datadog/*' exec yarn pack\",\n    \"format\": \"prettier --check .\",\n    \"lint\": \"NODE_OPTIONS='--max-old-space-size=4096' eslint .\",\n    \"typecheck\": \"tsc -b --noEmit true\",\n    \"dev\": \"yarn dev-server start\",\n    \"dev-server\": \"node scripts/dev-server/index.ts\",\n    \"release\": \"node ./scripts/release/prepare-release.ts --push\",\n    \"test\": \"yarn test:unit:watch\",\n    \"test:unit\": \"karma start ./test/unit/karma.local.conf.js\",\n    \"test:script\": \"node --test --experimental-test-module-mocks './scripts/**/*.spec.*'\",\n    \"test:unit:watch\": \"yarn test:unit --no-single-run\",\n    \"test:unit:bs\": \"node --env-file-if-exists=.env ./scripts/test/bs-wrapper.ts karma start test/unit/karma.bs.conf.js\",\n    \"test:e2e:init\": \"yarn build && yarn build:apps && yarn playwright install chromium --with-deps\",\n    \"test:e2e\": \"playwright test --config test/e2e/playwright.local.config.ts --project chromium\",\n    \"test:e2e:bs\": \"node --env-file-if-exists=.env ./scripts/test/bs-wrapper.ts playwright test --config test/e2e/playwright.bs.config.ts\",\n    \"test:e2e:ci\": \"yarn test:e2e:init && yarn test:e2e\",\n    \"test:e2e:ci:bs\": \"yarn build && yarn build:apps && yarn test:e2e:bs\",\n    \"test:compat:tsc\": \"node scripts/check-typescript-compatibility.ts\",\n    \"test:compat:ssr\": \"scripts/cli check_server_side_rendering_compatibility\",\n    \"test:performance\": \"yarn test:e2e:init && playwright test --config test/performance/playwright.config.ts\",\n    \"test:performance:debug\": \"playwright test --config test/performance/playwright.config.ts --debug\",\n    \"test:performance:ui\": \"playwright test --config test/performance/playwright.config.ts --ui\",\n    \"json-schemas:sync\": \"scripts/cli update_submodule && yarn json-schemas:generate\",\n    \"json-schemas:generate\": \"scripts/cli build_json2type && node scripts/generate-schema-types.ts\",\n    \"size\": \"node scripts/show-bundle-size.ts\",\n    \"woke\": \"scripts/cli woke\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"9.39.4\",\n    \"@jsdevtools/coverage-istanbul-loader\": \"3.0.5\",\n    \"@playwright/test\": \"1.58.2\",\n    \"@swc/core\": \"1.15.26\",\n    \"@types/busboy\": \"1.5.4\",\n    \"@types/chrome\": \"0.1.40\",\n    \"@types/cors\": \"2.8.19\",\n    \"@types/express\": \"5.0.6\",\n    \"@types/jasmine\": \"3.10.19\",\n    \"@types/node\": \"25.6.0\",\n    \"@types/node-forge\": \"1.3.14\",\n    \"ajv\": \"8.18.0\",\n    \"browserstack-local\": \"1.5.13\",\n    \"busboy\": \"1.6.0\",\n    \"chrome-webstore-upload\": \"4.0.3\",\n    \"cors\": \"2.8.6\",\n    \"emoji-name-map\": \"2.0.3\",\n    \"eslint\": \"9.39.4\",\n    \"eslint-import-resolver-typescript\": \"4.4.4\",\n    \"eslint-module-utils\": \"2.12.1\",\n    \"eslint-plugin-import\": \"2.32.0\",\n    \"eslint-plugin-jasmine\": \"4.2.2\",\n    \"eslint-plugin-jsdoc\": \"62.9.0\",\n    \"eslint-plugin-unicorn\": \"63.0.0\",\n    \"express\": \"5.2.1\",\n    \"globals\": \"17.5.0\",\n    \"html-webpack-plugin\": \"5.6.6\",\n    \"http-server\": \"14.1.1\",\n    \"jasmine-core\": \"3.99.1\",\n    \"json-schema-to-typescript\": \"bcaudan/json-schema-to-typescript#bcaudan/add-readonly-support\",\n    \"karma\": \"6.4.4\",\n    \"karma-browserstack-launcher\": \"1.6.0\",\n    \"karma-chrome-launcher\": \"3.2.0\",\n    \"karma-coverage-istanbul-reporter\": \"3.0.3\",\n    \"karma-jasmine\": \"4.0.2\",\n    \"karma-junit-reporter\": \"2.0.1\",\n    \"karma-sourcemap-loader\": \"0.4.0\",\n    \"karma-spec-reporter\": \"0.0.36\",\n    \"karma-webpack\": \"5.0.0\",\n    \"minimatch\": \"10.2.5\",\n    \"node-forge\": \"1.4.0\",\n    \"prettier\": \"3.8.3\",\n    \"puppeteer\": \"24.40.0\",\n    \"swc-loader\": \"0.2.7\",\n    \"terser-webpack-plugin\": \"5.4.0\",\n    \"ts-loader\": \"9.5.7\",\n    \"tsconfig-paths-webpack-plugin\": \"4.2.0\",\n    \"typedoc\": \"0.28.19\",\n    \"typescript\": \"6.0.2\",\n    \"typescript-eslint\": \"8.58.2\",\n    \"undici\": \"8.1.0\",\n    \"webpack\": \"5.106.2\",\n    \"webpack-cli\": \"7.0.2\",\n    \"webpack-dev-middleware\": \"8.0.3\"\n  },\n  \"resolutions\": {\n    \"puppeteer-core@npm:21.11.0/ws\": \"8.17.1\"\n  },\n  \"volta\": {\n    \"node\": \"25.9.0\",\n    \"yarn\": \"4.13.0\"\n  },\n  \"packageManager\": \"yarn@4.13.0\"\n}\n"
  },
  {
    "path": "packages/core/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/core/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/core/README.md",
    "content": "# `core`\n\nDatadog browser core utilities.\n"
  },
  {
    "path": "packages/core/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-core\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/index.js\",\n  \"module\": \"esm/index.js\",\n  \"types\": \"cjs/index.d.ts\",\n  \"sideEffects\": false,\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"yarn build\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/core\"\n  },\n  \"devDependencies\": {\n    \"@types/pako\": \"2.0.4\",\n    \"pako\": \"2.1.0\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/core/src/boot/displayAlreadyInitializedError.spec.ts",
    "content": "import type { InitConfiguration } from '../domain/configuration'\nimport { display } from '../tools/display'\nimport { displayAlreadyInitializedError } from './displayAlreadyInitializedError'\n\ndescribe('displayAlreadyInitializedError', () => {\n  it('should display an error', () => {\n    const displayErrorSpy = spyOn(display, 'error')\n    displayAlreadyInitializedError('DD_RUM', {} as InitConfiguration)\n    expect(displayErrorSpy).toHaveBeenCalledTimes(1)\n    expect(displayErrorSpy).toHaveBeenCalledWith('DD_RUM is already initialized.')\n  })\n\n  it('should not display an error if the \"silentMultipleInit\" option is used', () => {\n    const displayErrorSpy = spyOn(display, 'error')\n    displayAlreadyInitializedError('DD_RUM', { silentMultipleInit: true } as InitConfiguration)\n    expect(displayErrorSpy).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/boot/displayAlreadyInitializedError.ts",
    "content": "import type { InitConfiguration } from '../domain/configuration'\nimport { display } from '../tools/display'\n\nexport function displayAlreadyInitializedError(sdkName: 'DD_RUM' | 'DD_LOGS', initConfiguration: InitConfiguration) {\n  if (!initConfiguration.silentMultipleInit) {\n    display.error(`${sdkName} is already initialized.`)\n  }\n}\n"
  },
  {
    "path": "packages/core/src/boot/init.spec.ts",
    "content": "import { display } from '../tools/display'\nimport { defineGlobal } from './init'\n\ndescribe('defineGlobal', () => {\n  it('adds new property to the global object', () => {\n    const myGlobal = {} as any\n    const value = 'my value'\n    defineGlobal(myGlobal, 'foo', value)\n    expect(myGlobal.foo).toBe(value)\n  })\n\n  it('overrides property if exists on the global object', () => {\n    const myGlobal = { foo: 'old value' }\n    const value = 'my value'\n    defineGlobal(myGlobal, 'foo', value)\n    expect(myGlobal.foo).toBe(value)\n  })\n\n  it('run the queued callbacks on the old value', () => {\n    const fn1 = jasmine.createSpy()\n    const fn2 = jasmine.createSpy()\n    const myGlobal: any = {\n      foo: {\n        q: [fn1, fn2],\n      },\n    }\n    const value = 'my value'\n    defineGlobal(myGlobal, 'foo', value)\n    expect(myGlobal.foo).toBe(value)\n    expect(fn1).toHaveBeenCalled()\n    expect(fn2).toHaveBeenCalled()\n  })\n\n  it('catches the errors thrown by the queued callbacks', () => {\n    const myError = 'Ooops!'\n    const onReady = () => {\n      // eslint-disable-next-line @typescript-eslint/only-throw-error\n      throw myError\n    }\n    const myGlobal: any = {\n      foo: {\n        q: [onReady],\n      },\n    }\n    const displaySpy = spyOn(display, 'error')\n\n    defineGlobal(myGlobal, 'foo', {})\n    expect(displaySpy).toHaveBeenCalledWith('onReady callback threw an error:', myError)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/boot/init.ts",
    "content": "import { catchUserErrors } from '../tools/catchUserErrors'\nimport { setDebugMode } from '../tools/monitor'\nimport { display } from '../tools/display'\n\n// replaced at build time\ndeclare const __BUILD_ENV__SDK_VERSION__: string\n\nexport interface PublicApi {\n  /**\n   * Version of the Logs browser SDK\n   */\n  version: string\n\n  /**\n   * For CDN async setup: Early RUM API calls must be wrapped in the `window.DD_RUM.onReady()` callback. This ensures the code only gets executed once the SDK is properly loaded.\n   *\n   * See [CDN async setup](https://docs.datadoghq.com/real_user_monitoring/browser/#cdn-async) for further information.\n   */\n  onReady: (callback: () => void) => void\n}\n\nexport function makePublicApi<T extends PublicApi>(stub: Omit<T, keyof PublicApi>): T {\n  const publicApi = {\n    version: __BUILD_ENV__SDK_VERSION__,\n    // This API method is intentionally not monitored, since the only thing executed is the\n    // user-provided 'callback'.  All SDK usages executed in the callback should be monitored, and\n    // we don't want to interfere with the user uncaught exceptions.\n    onReady(callback: () => void) {\n      callback()\n    },\n    ...stub,\n  }\n\n  // Add a \"hidden\" property to set debug mode. We define it that way to hide it\n  // as much as possible but of course it's not a real protection.\n  Object.defineProperty(publicApi, '_setDebug', {\n    get() {\n      return setDebugMode\n    },\n    enumerable: false,\n  })\n\n  return publicApi as T\n}\n\nexport function defineGlobal<Global, Name extends keyof Global>(global: Global, name: Name, api: Global[Name]) {\n  const existingGlobalVariable = global[name] as { q?: Array<() => void>; version?: string } | undefined\n  if (existingGlobalVariable && !existingGlobalVariable.q && existingGlobalVariable.version) {\n    display.warn('SDK is loaded more than once. This is unsupported and might have unexpected behavior.')\n  }\n  global[name] = api\n  if (existingGlobalVariable && existingGlobalVariable.q) {\n    existingGlobalVariable.q.forEach((fn) => catchUserErrors(fn, 'onReady callback threw an error:')())\n  }\n}\n"
  },
  {
    "path": "packages/core/src/browser/addEventListener.spec.ts",
    "content": "import type { Configuration } from '../domain/configuration'\nimport { createNewEvent, mockZoneJs, registerCleanupTask } from '../../test'\nimport type { MockZoneJs } from '../../test'\nimport { noop } from '../tools/utils/functionUtils'\nimport { addEventListener, DOM_EVENT } from './addEventListener'\n\ndescribe('addEventListener', () => {\n  let configuration: Configuration\n\n  describe('Zone.js support', () => {\n    let zoneJs: MockZoneJs\n\n    beforeEach(() => {\n      configuration = { allowUntrustedEvents: false } as Configuration\n      zoneJs = mockZoneJs()\n    })\n\n    it('uses the original addEventListener method instead of the method patched by Zone.js', () => {\n      const zoneJsPatchedAddEventListener = jasmine.createSpy()\n      const eventTarget = document.createElement('div')\n      zoneJs.replaceProperty(eventTarget, 'addEventListener', zoneJsPatchedAddEventListener)\n\n      addEventListener(configuration, eventTarget, DOM_EVENT.CLICK, noop)\n      expect(zoneJsPatchedAddEventListener).not.toHaveBeenCalled()\n    })\n\n    it('uses the original removeEventListener method instead of the method patched by Zone.js', () => {\n      const zoneJsPatchedRemoveEventListener = jasmine.createSpy()\n      const eventTarget = document.createElement('div')\n      zoneJs.replaceProperty(eventTarget, 'removeEventListener', zoneJsPatchedRemoveEventListener)\n\n      const { stop } = addEventListener(configuration, eventTarget, DOM_EVENT.CLICK, noop)\n      stop()\n      expect(zoneJsPatchedRemoveEventListener).not.toHaveBeenCalled()\n    })\n  })\n\n  it('Use the EventTarget.prototype.addEventListener when the eventTarget is an instance of EventTarget', () => {\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    const originalAddEventListener = EventTarget.prototype.addEventListener\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    const originalRemoveEventListener = EventTarget.prototype.removeEventListener\n\n    EventTarget.prototype.addEventListener = jasmine.createSpy()\n    EventTarget.prototype.removeEventListener = jasmine.createSpy()\n\n    registerCleanupTask(() => {\n      EventTarget.prototype.addEventListener = originalAddEventListener\n      EventTarget.prototype.removeEventListener = originalRemoveEventListener\n    })\n\n    const htmlDivElement = document.createElement('div')\n    htmlDivElement.addEventListener = jasmine.createSpy()\n    htmlDivElement.removeEventListener = jasmine.createSpy()\n\n    const { stop } = addEventListener({ allowUntrustedEvents: false }, htmlDivElement, DOM_EVENT.CLICK, noop)\n\n    const event = createNewEvent(DOM_EVENT.CLICK)\n    htmlDivElement.dispatchEvent(event)\n    stop()\n\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(htmlDivElement.addEventListener).not.toHaveBeenCalled()\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(htmlDivElement.removeEventListener).not.toHaveBeenCalled()\n\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(EventTarget.prototype.addEventListener).toHaveBeenCalled()\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(EventTarget.prototype.removeEventListener).toHaveBeenCalled()\n  })\n\n  it('Use the addEventListener method when the eventTarget is not an instance of EventTarget', () => {\n    const listener = jasmine.createSpy()\n\n    const customEventTarget = {\n      addEventListener: jasmine.createSpy(),\n      removeEventListener: jasmine.createSpy(),\n    } as unknown as HTMLElement\n\n    const { stop } = addEventListener({ allowUntrustedEvents: false }, customEventTarget, 'change', listener)\n    stop()\n\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(customEventTarget.addEventListener).toHaveBeenCalled()\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(customEventTarget.removeEventListener).toHaveBeenCalled()\n  })\n\n  describe('Untrusted event', () => {\n    beforeEach(() => {\n      configuration = { allowUntrustedEvents: false } as Configuration\n    })\n\n    it('should be ignored if __ddIsTrusted is absent', () => {\n      const listener = jasmine.createSpy()\n      const eventTarget = document.createElement('div')\n      addEventListener(configuration, eventTarget, DOM_EVENT.CLICK, listener)\n\n      const event = createNewEvent(DOM_EVENT.CLICK, { __ddIsTrusted: undefined })\n      eventTarget.dispatchEvent(event)\n      expect(listener).not.toHaveBeenCalled()\n    })\n\n    it('should be ignored if __ddIsTrusted is false', () => {\n      const listener = jasmine.createSpy()\n      const eventTarget = document.createElement('div')\n      addEventListener(configuration, eventTarget, DOM_EVENT.CLICK, listener)\n\n      const event = createNewEvent(DOM_EVENT.CLICK, { __ddIsTrusted: false })\n      eventTarget.dispatchEvent(event)\n      expect(listener).not.toHaveBeenCalled()\n    })\n\n    it('should not be ignored if __ddIsTrusted is true', () => {\n      const listener = jasmine.createSpy()\n      const eventTarget = document.createElement('div')\n      addEventListener(configuration, eventTarget, DOM_EVENT.CLICK, listener)\n\n      const event = createNewEvent(DOM_EVENT.CLICK, { __ddIsTrusted: true })\n      eventTarget.dispatchEvent(event)\n\n      expect(listener).toHaveBeenCalled()\n    })\n\n    it('should not be ignored if allowUntrustedEvents is true', () => {\n      const listener = jasmine.createSpy()\n      const eventTarget = document.createElement('div')\n      configuration = { allowUntrustedEvents: true } as Configuration\n\n      addEventListener(configuration, eventTarget, DOM_EVENT.CLICK, listener)\n\n      const event = createNewEvent(DOM_EVENT.CLICK, { __ddIsTrusted: undefined })\n      eventTarget.dispatchEvent(event)\n\n      expect(listener).toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/browser/addEventListener.ts",
    "content": "import { monitor } from '../tools/monitor'\nimport { getZoneJsOriginalValue } from '../tools/getZoneJsOriginalValue'\nimport type { CookieStore, CookieStoreEventMap, VisualViewport, VisualViewportEventMap } from './browser.types'\n\nexport type TrustableEvent<E extends Event = Event> = E & { __ddIsTrusted?: boolean }\n\nexport const enum DOM_EVENT {\n  BEFORE_UNLOAD = 'beforeunload',\n  CLICK = 'click',\n  DBL_CLICK = 'dblclick',\n  KEY_DOWN = 'keydown',\n  LOAD = 'load',\n  POP_STATE = 'popstate',\n  SCROLL = 'scroll',\n  TOUCH_START = 'touchstart',\n  TOUCH_END = 'touchend',\n  TOUCH_MOVE = 'touchmove',\n  VISIBILITY_CHANGE = 'visibilitychange',\n  PAGE_SHOW = 'pageshow',\n  FREEZE = 'freeze',\n  RESUME = 'resume',\n  DOM_CONTENT_LOADED = 'DOMContentLoaded',\n  POINTER_DOWN = 'pointerdown',\n  POINTER_UP = 'pointerup',\n  POINTER_CANCEL = 'pointercancel',\n  HASH_CHANGE = 'hashchange',\n  PAGE_HIDE = 'pagehide',\n  MOUSE_DOWN = 'mousedown',\n  MOUSE_UP = 'mouseup',\n  MOUSE_MOVE = 'mousemove',\n  FOCUS = 'focus',\n  BLUR = 'blur',\n  CONTEXT_MENU = 'contextmenu',\n  RESIZE = 'resize',\n  CHANGE = 'change',\n  INPUT = 'input',\n  PLAY = 'play',\n  PAUSE = 'pause',\n  SECURITY_POLICY_VIOLATION = 'securitypolicyviolation',\n  SELECTION_CHANGE = 'selectionchange',\n  STORAGE = 'storage',\n}\n\ninterface AddEventListenerOptions {\n  once?: boolean\n  capture?: boolean\n  passive?: boolean\n}\n\ntype EventMapFor<T> = T extends Window\n  ? WindowEventMap & {\n      // TS 4.9.5 does not support `freeze` and `resume` events yet\n      freeze: Event\n      resume: Event\n      // TS 4.9.5 does not define `visibilitychange` on Window (only Document)\n      visibilitychange: Event\n    }\n  : T extends Document\n    ? DocumentEventMap\n    : T extends HTMLElement\n      ? HTMLElementEventMap\n      : T extends VisualViewport\n        ? VisualViewportEventMap\n        : T extends ShadowRoot\n          ? // ShadowRootEventMap is not yet defined in our supported TS version. Instead, use\n            // GlobalEventHandlersEventMap which is more than enough as we only need to listen for events bubbling\n            // through the ShadowRoot like \"change\" or \"input\"\n            GlobalEventHandlersEventMap\n          : T extends XMLHttpRequest\n            ? XMLHttpRequestEventMap\n            : T extends Performance\n              ? PerformanceEventMap\n              : T extends Worker\n                ? WorkerEventMap\n                : T extends CookieStore\n                  ? CookieStoreEventMap\n                  : Record<never, never>\n\n/**\n * Add an event listener to an event target object (Window, Element, mock object...).  This provides\n * a few conveniences compared to using `element.addEventListener` directly:\n *\n * * supports IE11 by: using an option object only if needed and emulating the `once` option\n *\n * * wraps the listener with a `monitor` function\n *\n * * returns a `stop` function to remove the listener\n */\nexport function addEventListener<Target extends EventTarget, EventName extends keyof EventMapFor<Target> & string>(\n  configuration: { allowUntrustedEvents?: boolean | undefined },\n  eventTarget: Target,\n  eventName: EventName,\n  listener: (event: EventMapFor<Target>[EventName] & { type: EventName }) => void,\n  options?: AddEventListenerOptions\n) {\n  return addEventListeners(configuration, eventTarget, [eventName], listener, options)\n}\n\n/**\n * Add event listeners to an event target object (Window, Element, mock object...).  This provides\n * a few conveniences compared to using `element.addEventListener` directly:\n *\n * * supports IE11 by: using an option object only if needed and emulating the `once` option\n *\n * * wraps the listener with a `monitor` function\n *\n * * returns a `stop` function to remove the listener\n *\n * * with `once: true`, the listener will be called at most once, even if different events are listened\n */\nexport function addEventListeners<Target extends EventTarget, EventName extends keyof EventMapFor<Target> & string>(\n  configuration: { allowUntrustedEvents?: boolean | undefined },\n  eventTarget: Target,\n  eventNames: EventName[],\n  listener: (event: EventMapFor<Target>[EventName] & { type: EventName }) => void,\n  { once, capture, passive }: AddEventListenerOptions = {}\n) {\n  const listenerWithMonitor = monitor((event: TrustableEvent) => {\n    if (!event.isTrusted && !event.__ddIsTrusted && !configuration.allowUntrustedEvents) {\n      return\n    }\n    if (once) {\n      stop()\n    }\n    listener(event as unknown as EventMapFor<Target>[EventName] & { type: EventName })\n  })\n\n  const options = passive ? { capture, passive } : capture\n\n  // Use the window.EventTarget.prototype when possible to avoid wrong overrides (e.g: https://github.com/salesforce/lwc/issues/1824)\n  const listenerTarget =\n    window.EventTarget && eventTarget instanceof EventTarget ? window.EventTarget.prototype : eventTarget\n\n  const add = getZoneJsOriginalValue(listenerTarget, 'addEventListener')\n  eventNames.forEach((eventName) => add.call(eventTarget, eventName, listenerWithMonitor, options))\n\n  function stop() {\n    const remove = getZoneJsOriginalValue(listenerTarget, 'removeEventListener')\n    eventNames.forEach((eventName) => remove.call(eventTarget, eventName, listenerWithMonitor, options))\n  }\n\n  return {\n    stop,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/browser/browser.types.ts",
    "content": "// Those types come from the official TypeScript DOM library, but are not included in our minimal\n// supported TS version.\n// https://github.com/microsoft/TypeScript/blob/13c374a868c926f6a907666a5599992c1351b773/src/lib/dom.generated.d.ts#L15399-L15418\n\nexport interface VisualViewportEventMap {\n  resize: Event\n  scroll: Event\n}\n\nexport interface VisualViewport extends EventTarget {\n  readonly height: number\n  readonly offsetLeft: number\n  readonly offsetTop: number\n  onresize: ((this: VisualViewport, ev: Event) => any) | null\n  onscroll: ((this: VisualViewport, ev: Event) => any) | null\n  readonly pageLeft: number\n  readonly pageTop: number\n  readonly scale: number\n  readonly width: number\n  addEventListener<K extends keyof VisualViewportEventMap>(\n    type: K,\n    listener: (this: VisualViewport, ev: VisualViewportEventMap[K]) => any,\n    options?: boolean | AddEventListenerOptions\n  ): void\n  addEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions\n  ): void\n  removeEventListener<K extends keyof VisualViewportEventMap>(\n    type: K,\n    listener: (this: VisualViewport, ev: VisualViewportEventMap[K]) => any,\n    options?: boolean | EventListenerOptions\n  ): void\n  removeEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | EventListenerOptions\n  ): void\n}\n\nexport interface WeakRef<T extends object> {\n  readonly [Symbol.toStringTag]: 'WeakRef'\n\n  deref(): T | undefined\n}\n\nexport interface WeakRefConstructor {\n  readonly prototype: WeakRef<any>\n\n  new <T extends object>(target: T): WeakRef<T>\n}\n\nexport interface CookieStore extends EventTarget {\n  get(name: string): Promise<unknown>\n  getAll(name?: string): Promise<\n    Array<{\n      name: string\n      value: string\n      domain?: string\n      path?: string\n      expires?: number\n      secure?: boolean\n      sameSite?: 'strict' | 'lax' | 'none'\n      partitioned?: boolean\n    }>\n  >\n}\n\nexport interface CookieStoreEventMap {\n  change: CookieChangeEvent\n}\n\nexport interface CookieChangeItem {\n  name: string\n  value: string | undefined\n}\n\nexport type CookieChangeEvent = Event & {\n  changed: CookieChangeItem[]\n  deleted: CookieChangeItem[]\n}\n"
  },
  {
    "path": "packages/core/src/browser/cookie.spec.ts",
    "content": "import { mockCookies } from '../../test'\nimport { getCurrentSite } from './cookie'\n\ndescribe('cookie', () => {\n  describe('getCurrentSite', () => {\n    it('returns the eTLD+1 for example.com', () => {\n      mockCookies()\n      expect(getCurrentSite('example.com')).toBe('example.com')\n    })\n\n    it('returns the eTLD+1 for example.co.uk', () => {\n      mockCookies({\n        filter: (cookie) => cookie.domain !== '.co.uk',\n      })\n      expect(getCurrentSite('example.co.uk')).toBe('example.co.uk')\n    })\n\n    it('returns the eTLD+1 for foo.bar.baz.example.com', () => {\n      mockCookies()\n      expect(getCurrentSite('foo.bar.baz.example.com')).toBe('example.com')\n    })\n\n    it('does not left any cookies', () => {\n      const { getCookies } = mockCookies()\n      expect(getCurrentSite('example.com')).toBe('example.com')\n      expect(getCookies()).toEqual([])\n    })\n\n    it('falls back to the referrer when the hostname is empty', () => {\n      mockCookies()\n      expect(getCurrentSite('', 'https://example.com')).toBe('example.com')\n    })\n\n    it('returns undefined when the referrer is empty', () => {\n      mockCookies()\n      expect(getCurrentSite('', '')).toBeUndefined()\n    })\n\n    it('caches the result', () => {\n      const { setter } = mockCookies()\n\n      expect(getCurrentSite('example.com')).toBe('example.com')\n      expect(setter).toHaveBeenCalledTimes(2)\n\n      expect(getCurrentSite('example.com')).toBe('example.com')\n      expect(setter).toHaveBeenCalledTimes(2)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/browser/cookie.ts",
    "content": "import { display } from '../tools/display'\nimport { ONE_MINUTE, ONE_SECOND } from '../tools/utils/timeUtils'\nimport {\n  findAllCommaSeparatedValues,\n  findCommaSeparatedValue,\n  findCommaSeparatedValues,\n  generateUUID,\n} from '../tools/utils/stringUtils'\nimport { buildUrl } from '../tools/utils/urlPolyfill'\n\nexport interface CookieOptions {\n  secure?: boolean\n  crossSite?: boolean\n  partitioned?: boolean\n  domain?: string\n}\n\nexport function setCookie(name: string, value: string, expireDelay: number = 0, options?: CookieOptions) {\n  const date = new Date()\n  date.setTime(date.getTime() + expireDelay)\n  const expires = `expires=${date.toUTCString()}`\n  const sameSite = options && options.crossSite ? 'none' : 'strict'\n  const domain = options && options.domain ? `;domain=${options.domain}` : ''\n  const secure = options && options.secure ? ';secure' : ''\n  const partitioned = options && options.partitioned ? ';partitioned' : ''\n  document.cookie = `${name}=${value};${expires};path=/;samesite=${sameSite}${domain}${secure}${partitioned}`\n}\n\n/**\n * Returns the value of the cookie with the given name\n * If there are multiple cookies with the same name, returns the first one\n */\nexport function getCookie(name: string) {\n  return findCommaSeparatedValue(document.cookie, name)\n}\n\n/**\n * Returns all the values of the cookies with the given name\n */\nexport function getCookies(name: string): string[] {\n  return findAllCommaSeparatedValues(document.cookie).get(name) || []\n}\n\nlet initCookieParsed: Map<string, string> | undefined\n\n/**\n * Returns a cached value of the cookie. Use this during SDK initialization (and whenever possible)\n * to avoid accessing document.cookie multiple times.\n *\n * ⚠️ If there are multiple cookies with the same name, returns the LAST one (unlike `getCookie()`)\n */\nexport function getInitCookie(name: string) {\n  if (!initCookieParsed) {\n    initCookieParsed = findCommaSeparatedValues(document.cookie)\n  }\n  return initCookieParsed.get(name)\n}\n\nexport function resetInitCookies() {\n  initCookieParsed = undefined\n}\n\nexport function deleteCookie(name: string, options?: CookieOptions) {\n  setCookie(name, '', 0, options)\n}\n\nexport function areCookiesAuthorized(options: CookieOptions): boolean {\n  if (document.cookie === undefined || document.cookie === null) {\n    return false\n  }\n  try {\n    // Use a unique cookie name to avoid issues when the SDK is initialized multiple times during\n    // the test cookie lifetime\n    const testCookieName = `dd_cookie_test_${generateUUID()}`\n    const testCookieValue = 'test'\n    setCookie(testCookieName, testCookieValue, ONE_MINUTE, options)\n    const isCookieCorrectlySet = getCookie(testCookieName) === testCookieValue\n    deleteCookie(testCookieName, options)\n    return isCookieCorrectlySet\n  } catch (error) {\n    display.error(error)\n    return false\n  }\n}\n\n/**\n * No API to retrieve it, number of levels for subdomain and suffix are unknown\n * strategy: find the minimal domain on which cookies are allowed to be set\n * https://web.dev/same-site-same-origin/#site\n */\nlet getCurrentSiteCache: string | undefined\nexport function getCurrentSite(hostname = location.hostname, referrer = document.referrer): string | undefined {\n  if (getCurrentSiteCache === undefined) {\n    const defaultHostName = getCookieDefaultHostName(hostname, referrer)\n    if (defaultHostName) {\n      // Use a unique cookie name to avoid issues when the SDK is initialized multiple times during\n      // the test cookie lifetime\n      const testCookieName = `dd_site_test_${generateUUID()}`\n      const testCookieValue = 'test'\n\n      const domainLevels = defaultHostName.split('.')\n      let candidateDomain = domainLevels.pop()!\n      while (domainLevels.length && !getCookie(testCookieName)) {\n        candidateDomain = `${domainLevels.pop()!}.${candidateDomain}`\n        setCookie(testCookieName, testCookieValue, ONE_SECOND, { domain: candidateDomain })\n      }\n      deleteCookie(testCookieName, { domain: candidateDomain })\n      getCurrentSiteCache = candidateDomain\n    }\n  }\n\n  return getCurrentSiteCache\n}\n\nfunction getCookieDefaultHostName(hostname: string, referrer: string) {\n  try {\n    return hostname || buildUrl(referrer).hostname\n  } catch {\n    // Ignore\n  }\n}\n\nexport function resetGetCurrentSite() {\n  getCurrentSiteCache = undefined\n}\n"
  },
  {
    "path": "packages/core/src/browser/fetch.spec.ts",
    "content": "import { type MockZoneJs, mockZoneJs } from '../../test'\nimport { fetch } from './fetch'\n\ndescribe('fetch', () => {\n  let zoneJs: MockZoneJs\n\n  beforeEach(() => {\n    zoneJs = mockZoneJs()\n  })\n\n  it('does not use the Zone.js function', async () => {\n    const nativeFetchSpy = spyOn(window, 'fetch')\n    const zoneJsFetchSpy = jasmine.createSpy('zoneJsFetch')\n\n    zoneJs.replaceProperty(window, 'fetch', zoneJsFetchSpy)\n\n    await fetch('https://example.com')\n\n    expect(zoneJsFetchSpy).not.toHaveBeenCalled()\n    expect(nativeFetchSpy).toHaveBeenCalled()\n  })\n\n  it('calls the native fetch function with correct arguments', async () => {\n    const nativeFetchSpy = spyOn(window, 'fetch')\n    const zoneJsFetchSpy = jasmine.createSpy('zoneJsFetch')\n\n    zoneJs.replaceProperty(window, 'fetch', zoneJsFetchSpy)\n\n    await fetch('https://example.com', { method: 'POST' })\n\n    expect(nativeFetchSpy).toHaveBeenCalledWith('https://example.com', { method: 'POST' })\n  })\n\n  it('returns the response from native fetch', async () => {\n    const mockResponse = new Response('test response', { status: 200 })\n    spyOn(window, 'fetch').and.returnValue(Promise.resolve(mockResponse))\n    const zoneJsFetchSpy = jasmine.createSpy('zoneJsFetch').and.returnValue(Promise.resolve(new Response()))\n\n    zoneJs.replaceProperty(window, 'fetch', zoneJsFetchSpy)\n\n    const response = await fetch('https://example.com')\n\n    expect(response).toBe(mockResponse)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/browser/fetch.ts",
    "content": "import { getZoneJsOriginalValue } from '../tools/getZoneJsOriginalValue'\nimport { getGlobalObject } from '../tools/globalObject'\n\n/**\n * Make a fetch request using the native implementation, bypassing Zone.js patching.\n * This prevents unnecessary Angular change detection cycles.\n *\n * @param input - The resource to fetch (URL or Request object)\n * @param init - Optional fetch options\n * @returns A Promise that resolves to the Response\n */\nexport function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n  return getZoneJsOriginalValue(getGlobalObject(), 'fetch')(input, init)\n}\n"
  },
  {
    "path": "packages/core/src/browser/fetchObservable.spec.ts",
    "content": "import type { MockFetch, MockFetchManager } from '../../test'\nimport { registerCleanupTask, mockFetch } from '../../test'\nimport type { Subscription } from '../tools/observable'\nimport type { FetchResolveContext, FetchContext } from './fetchObservable'\nimport { initFetchObservable, resetFetchObservable, ResponseBodyAction } from './fetchObservable'\n\ndescribe('fetch proxy', () => {\n  const FAKE_URL = 'http://fake-url/'\n  const FAKE_RELATIVE_URL = '/fake-path'\n  const NORMALIZED_FAKE_RELATIVE_URL = `${location.origin}/fake-path`\n  let mockFetchManager: MockFetchManager\n  let requestsTrackingSubscription: Subscription\n  let contextEditionSubscription: Subscription | undefined\n  let requests: FetchResolveContext[]\n  let originalMockFetch: typeof window.fetch\n  let fetch: MockFetch\n\n  beforeEach(() => {\n    mockFetchManager = mockFetch()\n    originalMockFetch = window.fetch\n\n    requests = []\n    requestsTrackingSubscription = initFetchObservable().subscribe((context) => {\n      if (context.state === 'resolve') {\n        requests.push(context)\n      }\n    })\n    fetch = window.fetch as MockFetch\n\n    registerCleanupTask(() => {\n      requestsTrackingSubscription.unsubscribe()\n      contextEditionSubscription?.unsubscribe()\n      resetFetchObservable()\n    })\n  })\n\n  it('should track server error', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 500, responseText: 'fetch error' })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = requests[0]\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(500)\n      expect(request.isAborted).toBe(false)\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should track refused fetch', (done) => {\n    fetch(FAKE_URL).rejectWith(new Error('fetch error'))\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = requests[0]\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(0)\n      expect(request.isAborted).toBe(false)\n      expect(request.error).toEqual(new Error('fetch error'))\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should track aborted fetch', (done) => {\n    fetch(FAKE_URL).abort()\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = requests[0]\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(0)\n      expect(request.isAborted).toBe(true)\n      expect(request.error).toEqual(new DOMException('The user aborted a request', 'AbortError'))\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should track fetch aborted by AbortController', (done) => {\n    if (!window.AbortController) {\n      pending('AbortController is not supported')\n    }\n\n    const controller = new AbortController()\n    void fetch(FAKE_URL, { signal: controller.signal })\n    controller.abort('AbortError')\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = requests[0]\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(0)\n      expect(request.isAborted).toBe(true)\n      expect(request.error).toEqual(controller.signal.reason)\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should track opaque fetch', (done) => {\n    // https://fetch.spec.whatwg.org/#concept-filtered-response-opaque\n    fetch(FAKE_URL).resolveWith({ status: 0, type: 'opaque' })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = requests[0]\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(0)\n      expect(request.isAborted).toBe(false)\n      done()\n    })\n  })\n\n  it('should track client error', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 400, responseText: 'Not found' })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = requests[0]\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(400)\n      expect(request.isAborted).toBe(false)\n      done()\n    })\n  })\n\n  it('should get method from input', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 500 })\n    fetch(new Request(FAKE_URL)).resolveWith({ status: 500 })\n    fetch(new Request(FAKE_URL, { method: 'PUT' })).resolveWith({ status: 500 })\n    fetch(new Request(FAKE_URL, { method: 'PUT' }), { method: 'POST' }).resolveWith({ status: 500 })\n    fetch(new Request(FAKE_URL), { method: 'POST' }).resolveWith({ status: 500 })\n    fetch(FAKE_URL, { method: 'POST' }).resolveWith({ status: 500 })\n    fetch(FAKE_URL, { method: 'post' }).resolveWith({ status: 500 })\n    fetch(null as any).resolveWith({ status: 500 })\n    fetch({ method: 'POST' } as any).resolveWith({ status: 500 })\n    fetch(FAKE_URL, { method: null as any }).resolveWith({ status: 500 })\n    fetch(FAKE_URL, { method: undefined }).resolveWith({ status: 500 })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(requests[0].method).toEqual('GET')\n      expect(requests[1].method).toEqual('GET')\n      expect(requests[2].method).toEqual('PUT')\n      expect(requests[3].method).toEqual('POST')\n      expect(requests[4].method).toEqual('POST')\n      expect(requests[5].method).toEqual('POST')\n      expect(requests[6].method).toEqual('POST')\n      expect(requests[7].method).toEqual('GET')\n      expect(requests[8].method).toEqual('GET')\n      expect(requests[9].method).toEqual('NULL')\n      expect(requests[10].method).toEqual('GET')\n\n      done()\n    })\n  })\n\n  it('should get the normalized url from input', (done) => {\n    fetch(FAKE_URL).rejectWith(new Error('fetch error'))\n    fetch(new Request(FAKE_URL)).rejectWith(new Error('fetch error'))\n    fetch(null as any).rejectWith(new Error('fetch error'))\n    fetch({\n      toString() {\n        return FAKE_RELATIVE_URL\n      },\n    } as any).rejectWith(new Error('fetch error'))\n    fetch(FAKE_RELATIVE_URL).rejectWith(new Error('fetch error'))\n    fetch(new Request(FAKE_RELATIVE_URL)).rejectWith(new Error('fetch error'))\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(requests[0].url).toEqual(FAKE_URL)\n      expect(requests[1].url).toEqual(FAKE_URL)\n      expect(requests[2].url).toMatch(/\\/null$/)\n      expect(requests[3].url).toEqual(NORMALIZED_FAKE_RELATIVE_URL)\n      expect(requests[4].url).toEqual(NORMALIZED_FAKE_RELATIVE_URL)\n      expect(requests[5].url).toEqual(NORMALIZED_FAKE_RELATIVE_URL)\n      done()\n    })\n  })\n\n  it('should keep promise resolved behavior for Response', (done) => {\n    const mockFetchPromise = fetch(FAKE_URL)\n    const spy = jasmine.createSpy()\n    mockFetchPromise.then(spy).catch(() => {\n      fail('Should not have thrown an error!')\n    })\n    mockFetchPromise.resolveWith({ status: 500 })\n\n    setTimeout(() => {\n      expect(spy).toHaveBeenCalled()\n      done()\n    })\n  })\n\n  it('should keep promise resolved behavior for any other type', (done) => {\n    const mockFetchPromise = fetch(FAKE_URL)\n    const spy = jasmine.createSpy()\n    mockFetchPromise.then(spy).catch(() => {\n      fail('Should not have thrown an error!')\n    })\n    mockFetchPromise.resolveWith('response' as any)\n\n    setTimeout(() => {\n      expect(spy).toHaveBeenCalled()\n      done()\n    })\n  })\n\n  it('should keep promise rejected behavior for Error', (done) => {\n    const mockFetchPromise = fetch(FAKE_URL)\n    const spy = jasmine.createSpy()\n    mockFetchPromise.catch(spy)\n    mockFetchPromise.rejectWith(new Error('fetch error'))\n\n    setTimeout(() => {\n      expect(spy).toHaveBeenCalled()\n      done()\n    })\n  })\n\n  it('should keep promise rejected behavior for any other type', (done) => {\n    const mockFetchPromise = fetch(FAKE_URL)\n    const spy = jasmine.createSpy()\n    mockFetchPromise.catch(spy)\n    mockFetchPromise.rejectWith('fetch error' as any)\n\n    setTimeout(() => {\n      expect(spy).toHaveBeenCalled()\n      done()\n    })\n  })\n\n  it('should allow to enhance the context', (done) => {\n    type CustomContext = FetchContext & { foo: string }\n    contextEditionSubscription = initFetchObservable().subscribe((rawContext) => {\n      const context = rawContext as CustomContext\n      if (context.state === 'start') {\n        context.foo = 'bar'\n      }\n    })\n    fetch(FAKE_URL).resolveWith({ status: 500, responseText: 'fetch error' })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect((requests[0] as CustomContext).foo).toBe('bar')\n      done()\n    })\n  })\n\n  describe('when unsubscribing', () => {\n    it('should stop tracking requests', (done) => {\n      requestsTrackingSubscription.unsubscribe()\n\n      fetch(FAKE_URL).resolveWith({ status: 200, responseText: 'ok' })\n\n      mockFetchManager.whenAllComplete(() => {\n        expect(requests).toEqual([])\n        done()\n      })\n    })\n\n    it('should restore original window.fetch', () => {\n      requestsTrackingSubscription.unsubscribe()\n\n      expect(window.fetch).toBe(originalMockFetch)\n    })\n  })\n})\n\ndescribe('fetch proxy with ResponseBodyAction', () => {\n  const FAKE_URL = 'http://fake-url/'\n  let mockFetchManager: MockFetchManager\n  let requestsTrackingSubscription: Subscription\n  let requests: FetchResolveContext[]\n  let fetch: MockFetch\n\n  function setupFetchTracking(responseBodyAction: () => ResponseBodyAction) {\n    mockFetchManager = mockFetch()\n    requests = []\n    requestsTrackingSubscription = initFetchObservable({ responseBodyAction }).subscribe((context) => {\n      if (context.state === 'resolve') {\n        requests.push(context)\n      }\n    })\n    fetch = window.fetch as MockFetch\n  }\n\n  afterEach(() => {\n    requestsTrackingSubscription?.unsubscribe()\n    resetFetchObservable()\n  })\n\n  it('should collect response body with COLLECT action', (done) => {\n    setupFetchTracking(() => ResponseBodyAction.COLLECT)\n\n    fetch(FAKE_URL).resolveWith({ status: 200, responseText: 'response body content' })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(requests[0].responseBody).toBe('response body content')\n      done()\n    })\n  })\n\n  it('should not collect response body with WAIT or IGNORE action', (done) => {\n    setupFetchTracking(() => ResponseBodyAction.WAIT)\n\n    fetch(FAKE_URL).resolveWith({ status: 200, responseText: 'response body content' })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(requests[0].responseBody).toBeUndefined()\n      done()\n    })\n  })\n\n  it('should use the highest priority action when multiple getters are registered', (done) => {\n    setupFetchTracking(() => ResponseBodyAction.WAIT)\n\n    initFetchObservable({\n      responseBodyAction: () => ResponseBodyAction.COLLECT,\n    })\n\n    registerCleanupTask(() => {\n      requestsTrackingSubscription.unsubscribe()\n    })\n\n    fetch = window.fetch as MockFetch\n    fetch(FAKE_URL).resolveWith({ status: 200, responseText: 'response body content' })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(requests[0].responseBody).toBe('response body content')\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/browser/fetchObservable.ts",
    "content": "import type { InstrumentedMethodCall } from '../tools/instrumentMethod'\nimport { instrumentMethod } from '../tools/instrumentMethod'\nimport { monitorError } from '../tools/monitor'\nimport { Observable } from '../tools/observable'\nimport type { ClocksState } from '../tools/utils/timeUtils'\nimport { clocksNow } from '../tools/utils/timeUtils'\nimport { normalizeUrl } from '../tools/utils/urlPolyfill'\nimport type { GlobalObject } from '../tools/globalObject'\nimport { globalObject } from '../tools/globalObject'\nimport { readBytesFromStream } from '../tools/readBytesFromStream'\nimport { tryToClone } from '../tools/utils/responseUtils'\n\ninterface FetchContextBase {\n  method: string\n  startClocks: ClocksState\n  input: unknown\n  init?: RequestInit\n  url: string\n  handlingStack?: string\n  isAbortedOnStart: boolean\n}\n\nexport interface FetchStartContext extends FetchContextBase {\n  state: 'start'\n}\n\nexport interface FetchResolveContext extends FetchContextBase {\n  state: 'resolve'\n  status: number\n  response?: Response\n  responseBody?: string\n  responseType?: string\n  isAborted: boolean\n  error?: Error\n}\n\nexport type FetchContext = FetchStartContext | FetchResolveContext\n\ntype ResponseBodyActionGetter = (context: FetchResolveContext) => ResponseBodyAction\n\n/**\n * Action to take with the response body of a fetch request.\n * Values are ordered by priority: higher values take precedence when multiple actions are requested.\n */\nexport const enum ResponseBodyAction {\n  IGNORE = 0,\n  // TODO(next-major): Remove the \"WAIT\" action when `trackEarlyRequests` is removed, as the\n  // duration of fetch requests will always come from PerformanceResourceTiming\n  WAIT = 1,\n  COLLECT = 2,\n}\n\nlet fetchObservable: Observable<FetchContext> | undefined\nconst responseBodyActionGetters: ResponseBodyActionGetter[] = []\n\nexport function initFetchObservable({ responseBodyAction }: { responseBodyAction?: ResponseBodyActionGetter } = {}) {\n  if (responseBodyAction) {\n    responseBodyActionGetters.push(responseBodyAction)\n  }\n  if (!fetchObservable) {\n    fetchObservable = createFetchObservable()\n  }\n  return fetchObservable\n}\n\nexport function resetFetchObservable() {\n  fetchObservable = undefined\n  responseBodyActionGetters.length = 0\n}\n\nfunction createFetchObservable() {\n  return new Observable<FetchContext>((observable) => {\n    // eslint-disable-next-line local-rules/disallow-zone-js-patched-values\n    if (!globalObject.fetch) {\n      return\n    }\n\n    const { stop } = instrumentMethod(globalObject, 'fetch', (call) => beforeSend(call, observable), {\n      computeHandlingStack: true,\n    })\n\n    return stop\n  })\n}\n\nfunction beforeSend(\n  { parameters, onPostCall, handlingStack }: InstrumentedMethodCall<GlobalObject, 'fetch'>,\n  observable: Observable<FetchContext>\n) {\n  const [input, init] = parameters\n  let methodFromParams = init && init.method\n\n  if (methodFromParams === undefined && input instanceof Request) {\n    methodFromParams = input.method\n  }\n\n  const method = methodFromParams !== undefined ? String(methodFromParams).toUpperCase() : 'GET'\n  const url = input instanceof Request ? input.url : normalizeUrl(String(input))\n  const startClocks = clocksNow()\n\n  const context: FetchStartContext = {\n    state: 'start',\n    init,\n    input,\n    method,\n    startClocks,\n    url,\n    handlingStack,\n    isAbortedOnStart: (input instanceof Request && input.signal?.aborted) || init?.signal?.aborted || false,\n  }\n\n  observable.notify(context)\n\n  // Those properties can be changed by observable subscribers\n  parameters[0] = context.input as RequestInfo | URL\n  parameters[1] = context.init\n\n  onPostCall((responsePromise) => {\n    afterSend(observable, responsePromise, context).catch(monitorError)\n  })\n}\n\nasync function afterSend(\n  observable: Observable<FetchContext>,\n  responsePromise: Promise<Response>,\n  startContext: FetchStartContext\n) {\n  const context = startContext as unknown as FetchResolveContext\n  context.state = 'resolve'\n\n  let response: Response\n\n  try {\n    response = await responsePromise\n  } catch (error) {\n    context.status = 0\n    context.isAborted =\n      context.init?.signal?.aborted || (error instanceof DOMException && error.code === DOMException.ABORT_ERR)\n    context.error = error as Error\n    observable.notify(context)\n    return\n  }\n\n  context.response = response\n  context.status = response.status\n  context.responseType = response.type\n  context.isAborted = false\n\n  const responseBodyCondition = responseBodyActionGetters.reduce(\n    (action, getter) => Math.max(action, getter(context)),\n    ResponseBodyAction.IGNORE\n  ) as ResponseBodyAction\n\n  if (responseBodyCondition !== ResponseBodyAction.IGNORE) {\n    const clonedResponse = tryToClone(response)\n    if (clonedResponse && clonedResponse.body) {\n      try {\n        const bytes = await readBytesFromStream(clonedResponse.body, {\n          collectStreamBody: responseBodyCondition === ResponseBodyAction.COLLECT,\n        })\n        context.responseBody = bytes && new TextDecoder().decode(bytes)\n      } catch {\n        // Ignore errors when reading the response body (e.g., stream aborted, network errors)\n        // This is not critical and should not be reported as an SDK error\n      }\n    }\n  }\n\n  observable.notify(context)\n}\n"
  },
  {
    "path": "packages/core/src/browser/pageMayExitObservable.spec.ts",
    "content": "import type { Configuration } from '../domain/configuration'\nimport { createNewEvent, restorePageVisibility, setPageVisibility, registerCleanupTask } from '../../test'\nimport type { PageMayExitEvent } from './pageMayExitObservable'\nimport { PageExitReason, createPageMayExitObservable } from './pageMayExitObservable'\n\ndescribe('createPageMayExitObservable', () => {\n  let onExitSpy: jasmine.Spy<(event: PageMayExitEvent) => void>\n  let configuration: Configuration\n\n  beforeEach(() => {\n    onExitSpy = jasmine.createSpy()\n    configuration = {} as Configuration\n    registerCleanupTask(createPageMayExitObservable(configuration).subscribe(onExitSpy).unsubscribe)\n  })\n\n  afterEach(() => {\n    restorePageVisibility()\n  })\n\n  it('notifies when the page fires beforeunload', () => {\n    window.dispatchEvent(createNewEvent('beforeunload'))\n\n    expect(onExitSpy).toHaveBeenCalledOnceWith({ reason: PageExitReason.UNLOADING })\n  })\n\n  it('notifies when the page becomes hidden', () => {\n    emulatePageVisibilityChange('hidden')\n\n    expect(onExitSpy).toHaveBeenCalledOnceWith({ reason: PageExitReason.HIDDEN })\n  })\n\n  it('notifies when the page becomes frozen', () => {\n    window.dispatchEvent(createNewEvent('freeze'))\n\n    expect(onExitSpy).toHaveBeenCalledOnceWith({ reason: PageExitReason.FROZEN })\n  })\n\n  it('notifies multiple times', () => {\n    window.dispatchEvent(createNewEvent('beforeunload'))\n    window.dispatchEvent(createNewEvent('beforeunload'))\n    emulatePageVisibilityChange('hidden')\n\n    expect(onExitSpy).toHaveBeenCalledTimes(3)\n  })\n\n  it('does not notify when the page becomes visible', () => {\n    emulatePageVisibilityChange('visible')\n\n    expect(onExitSpy).not.toHaveBeenCalled()\n  })\n\n  function emulatePageVisibilityChange(visibility: 'visible' | 'hidden') {\n    setPageVisibility(visibility)\n    document.dispatchEvent(createNewEvent('visibilitychange'))\n  }\n})\n"
  },
  {
    "path": "packages/core/src/browser/pageMayExitObservable.ts",
    "content": "import { Observable } from '../tools/observable'\nimport { objectValues } from '../tools/utils/polyfills'\nimport type { Configuration } from '../domain/configuration'\nimport { isWorkerEnvironment } from '../tools/globalObject'\nimport { addEventListeners, addEventListener, DOM_EVENT } from './addEventListener'\n\nexport const PageExitReason = {\n  HIDDEN: 'visibility_hidden',\n  UNLOADING: 'before_unload',\n  PAGEHIDE: 'page_hide',\n  FROZEN: 'page_frozen',\n} as const\n\nexport type PageExitReason = (typeof PageExitReason)[keyof typeof PageExitReason]\n\nexport interface PageMayExitEvent {\n  reason: PageExitReason\n}\n\nexport function createPageMayExitObservable(configuration: Configuration): Observable<PageMayExitEvent> {\n  return new Observable<PageMayExitEvent>((observable) => {\n    if (isWorkerEnvironment) {\n      // Page exit is not observable in worker environments (no window/document events)\n      return\n    }\n    const { stop: stopListeners } = addEventListeners(\n      configuration,\n      window,\n      [DOM_EVENT.VISIBILITY_CHANGE, DOM_EVENT.FREEZE],\n      (event) => {\n        if (event.type === DOM_EVENT.VISIBILITY_CHANGE && document.visibilityState === 'hidden') {\n          /**\n           * Only event that guarantee to fire on mobile devices when the page transitions to background state\n           * (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.\n           */\n          observable.notify({ reason: PageExitReason.HIDDEN })\n        } else if (event.type === DOM_EVENT.FREEZE) {\n          /**\n           * After transitioning in background a tab can be freezed to preserve resources. (cf: https://developer.chrome.com/blog/page-lifecycle-api)\n           * Allow to collect events happening between hidden and frozen state.\n           */\n          observable.notify({ reason: PageExitReason.FROZEN })\n        }\n      },\n      { capture: true }\n    )\n\n    const stopBeforeUnloadListener = addEventListener(configuration, window, DOM_EVENT.BEFORE_UNLOAD, () => {\n      observable.notify({ reason: PageExitReason.UNLOADING })\n    }).stop\n\n    return () => {\n      stopListeners()\n      stopBeforeUnloadListener()\n    }\n  })\n}\n\nexport function isPageExitReason(reason: string): reason is PageExitReason {\n  return objectValues(PageExitReason).includes(reason as PageExitReason)\n}\n"
  },
  {
    "path": "packages/core/src/browser/runOnReadyState.ts",
    "content": "import type { Configuration } from '../domain/configuration'\nimport { noop } from '../tools/utils/functionUtils'\nimport { DOM_EVENT, addEventListener } from './addEventListener'\n\nexport function runOnReadyState(\n  configuration: Configuration,\n  expectedReadyState: 'complete' | 'interactive',\n  callback: () => void\n): { stop: () => void } {\n  if (document.readyState === expectedReadyState || document.readyState === 'complete') {\n    callback()\n    return { stop: noop }\n  }\n  const eventName = expectedReadyState === 'complete' ? DOM_EVENT.LOAD : DOM_EVENT.DOM_CONTENT_LOADED\n  return addEventListener(configuration, window, eventName, callback, { once: true })\n}\n\nexport function asyncRunOnReadyState(\n  configuration: Configuration,\n  expectedReadyState: 'complete' | 'interactive'\n): Promise<void> {\n  return new Promise((resolve) => {\n    runOnReadyState(configuration, expectedReadyState, resolve)\n  })\n}\n"
  },
  {
    "path": "packages/core/src/browser/xhrObservable.spec.ts",
    "content": "import type { Configuration } from '../domain/configuration'\nimport { withXhr, mockXhr } from '../../test'\nimport type { Subscription } from '../tools/observable'\nimport type { XhrCompleteContext, XhrContext } from './xhrObservable'\nimport { initXhrObservable } from './xhrObservable'\n\ndescribe('xhr observable', () => {\n  let requestsTrackingSubscription: Subscription\n  let contextEditionSubscription: Subscription | undefined\n  let requests: XhrCompleteContext[]\n  let originalMockXhrSend: XMLHttpRequest['send']\n  let configuration: Configuration\n\n  beforeEach(() => {\n    mockXhr()\n    configuration = {} as Configuration\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    originalMockXhrSend = XMLHttpRequest.prototype.send\n\n    requests = []\n    startTrackingRequests()\n  })\n\n  afterEach(() => {\n    requestsTrackingSubscription.unsubscribe()\n    contextEditionSubscription?.unsubscribe()\n  })\n\n  function startTrackingRequests() {\n    requestsTrackingSubscription = initXhrObservable(configuration).subscribe((context) => {\n      if (context.state === 'complete') {\n        requests.push(context)\n      }\n    })\n  }\n\n  it('should track successful request', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200, 'ok')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/ok')\n        expect(request.status).toBe(200)\n        expect(request.isAborted).toBe(false)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should sanitize request method', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('get', '/ok')\n        xhr.send()\n        xhr.complete(200, 'ok')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track client error', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/expected-404')\n        xhr.send()\n        xhr.complete(404, 'NOT FOUND')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/expected-404')\n        expect(request.status).toBe(404)\n        expect(request.isAborted).toBe(false)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track server error', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/throw')\n        xhr.send()\n        xhr.complete(500, 'expected server error')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/throw')\n        expect(request.status).toBe(500)\n        expect(request.isAborted).toBe(false)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track network error', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', 'http://foo.bar/qux')\n        xhr.send()\n        xhr.complete(0, '')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toBe('http://foo.bar/qux')\n        expect(request.status).toBe(0)\n        expect(request.isAborted).toBe(false)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track successful request aborted', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.onreadystatechange = () => {\n          if (xhr.readyState === XMLHttpRequest.DONE) {\n            xhr.abort()\n          }\n        }\n        spyOn(xhr, 'onreadystatechange').and.callThrough()\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200, 'ok')\n      },\n      onComplete(xhr) {\n        const request = requests[0]\n        expect(requests.length).toBe(1)\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/ok')\n        expect(request.status).toBe(200)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(request.isAborted).toBe(false)\n        expect(xhr.status).toBe(0)\n        expect(xhr.onreadystatechange).toHaveBeenCalledTimes(1)\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track aborted requests', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.abort()\n      },\n      onComplete(xhr) {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/ok')\n        expect(request.status).toBe(0)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(request.isAborted).toBe(true)\n        expect(xhr.status).toBe(0)\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track request with onreadystatechange overridden before open', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.onreadystatechange = jasmine.createSpy()\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200, 'ok')\n      },\n      onComplete(xhr) {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/ok')\n        expect(request.status).toBe(200)\n        expect(request.isAborted).toBe(false)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(xhr.onreadystatechange).toHaveBeenCalled()\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should track request with onreadystatechange overridden after open', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.onreadystatechange = jasmine.createSpy()\n        xhr.complete(200, 'ok')\n      },\n      onComplete(xhr) {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/ok')\n        expect(request.status).toBe(200)\n        expect(request.isAborted).toBe(false)\n        expect(request.duration).toEqual(jasmine.any(Number))\n        expect(xhr.onreadystatechange).toHaveBeenCalled()\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should allow to enhance the context', (done) => {\n    type CustomContext = XhrContext & { foo: string }\n    contextEditionSubscription = initXhrObservable(configuration).subscribe((rawContext) => {\n      const context = rawContext as CustomContext\n      if (context.state === 'start') {\n        context.foo = 'bar'\n      }\n    })\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200)\n      },\n      onComplete() {\n        const request = requests[0]\n        expect((request as CustomContext).foo).toBe('bar')\n        done()\n      },\n    })\n  })\n\n  it('should not break xhr opened before the instrumentation', (done) => {\n    requestsTrackingSubscription.unsubscribe()\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        startTrackingRequests()\n        xhr.send()\n        xhr.complete(200)\n      },\n      onComplete() {\n        expect(requests.length).toBe(0)\n        done()\n      },\n    })\n  })\n\n  it('should track multiple requests with the same xhr instance', (done) => {\n    let listeners: { [k: string]: Array<(event: Event) => void> }\n    withXhr({\n      setup(xhr) {\n        const secondOnload = () => {\n          xhr.removeEventListener('load', secondOnload)\n        }\n        const onLoad = () => {\n          xhr.removeEventListener('load', onLoad)\n          xhr.addEventListener('load', secondOnload)\n          xhr.open('GET', '/ok?request=2')\n          xhr.send()\n          xhr.complete(400, 'ok')\n        }\n        xhr.onreadystatechange = jasmine.createSpy()\n        xhr.addEventListener('load', onLoad)\n        xhr.open('GET', '/ok?request=1')\n        xhr.send()\n        xhr.complete(200, 'ok')\n        listeners = xhr.listeners\n      },\n      onComplete(xhr) {\n        const firstRequest = requests[0]\n        expect(firstRequest.method).toBe('GET')\n        expect(firstRequest.url).toContain('/ok?request=1')\n        expect(firstRequest.status).toBe(200)\n        expect(firstRequest.isAborted).toBe(false)\n        expect(firstRequest.duration).toEqual(jasmine.any(Number))\n        expect(firstRequest.handlingStack).toBeDefined()\n\n        const secondRequest = requests[1]\n        expect(secondRequest.method).toBe('GET')\n        expect(secondRequest.url).toContain('/ok?request=2')\n        expect(secondRequest.status).toBe(400)\n        expect(secondRequest.isAborted).toBe(false)\n        expect(secondRequest.duration).toEqual(jasmine.any(Number))\n        expect(secondRequest.handlingStack).toBeDefined()\n\n        expect(xhr.onreadystatechange).toHaveBeenCalledTimes(2)\n        expect(listeners.load.length).toBe(0)\n        expect(listeners.loadend.length).toBe(0)\n        done()\n      },\n    })\n  })\n\n  it('should track request to undefined url', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', undefined)\n        xhr.send()\n        xhr.complete(404, 'NOT FOUND')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/undefined')\n        expect(request.status).toBe(404)\n        done()\n      },\n    })\n  })\n\n  it('should track request to null url', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', null)\n        xhr.send()\n        xhr.complete(404, 'NOT FOUND')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toContain('/null')\n        expect(request.status).toBe(404)\n        done()\n      },\n    })\n  })\n\n  it('should track request to URL object', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', new URL('http://example.com/path'))\n        xhr.send()\n        xhr.complete(200, 'ok')\n      },\n      onComplete() {\n        const request = requests[0]\n        expect(request.method).toBe('GET')\n        expect(request.url).toBe('http://example.com/path')\n        done()\n      },\n    })\n  })\n\n  describe('when unsubscribing', () => {\n    it('should stop tracking requests', (done) => {\n      requestsTrackingSubscription.unsubscribe()\n\n      withXhr({\n        setup(xhr) {\n          xhr.open('GET', '/ok')\n          xhr.send()\n          xhr.complete(200)\n        },\n        onComplete() {\n          expect(requests.length).toBe(0)\n          done()\n        },\n      })\n    })\n\n    it('should restore original XMLHttpRequest methods', () => {\n      requestsTrackingSubscription.unsubscribe()\n\n      // eslint-disable-next-line @typescript-eslint/unbound-method\n      expect(XMLHttpRequest.prototype.send).toBe(originalMockXhrSend)\n    })\n  })\n\n  it('should track request with undefined or null methods', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open(null, '/ok')\n        xhr.send()\n        xhr.onreadystatechange = jasmine.createSpy()\n        xhr.complete(200, 'ok')\n        xhr.open(undefined, '/ok')\n        xhr.send()\n        xhr.onreadystatechange = jasmine.createSpy()\n        xhr.complete(200, 'ok')\n      },\n      onComplete() {\n        expect(requests[0].method).toBe('NULL')\n        expect(requests[1].method).toBe('UNDEFINED')\n        done()\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/browser/xhrObservable.ts",
    "content": "import type { InstrumentedMethodCall } from '../tools/instrumentMethod'\nimport { instrumentMethod } from '../tools/instrumentMethod'\nimport { Observable } from '../tools/observable'\nimport type { Duration, ClocksState } from '../tools/utils/timeUtils'\nimport { elapsed, clocksNow, timeStampNow } from '../tools/utils/timeUtils'\nimport { normalizeUrl } from '../tools/utils/urlPolyfill'\nimport { shallowClone } from '../tools/utils/objectUtils'\nimport type { Configuration } from '../domain/configuration'\nimport { addEventListener } from './addEventListener'\n\nexport interface XhrOpenContext {\n  state: 'open'\n  method: string\n  url: string\n}\n\nexport interface XhrStartContext extends Omit<XhrOpenContext, 'state'> {\n  state: 'start'\n  startClocks: ClocksState\n  isAborted: boolean\n  xhr: XMLHttpRequest\n  handlingStack?: string\n  requestBody?: unknown\n}\n\nexport interface XhrCompleteContext extends Omit<XhrStartContext, 'state'> {\n  state: 'complete'\n  duration: Duration\n  status: number\n  responseBody?: string\n}\n\nexport type XhrContext = XhrOpenContext | XhrStartContext | XhrCompleteContext\n\nlet xhrObservable: Observable<XhrContext> | undefined\nconst xhrContexts = new WeakMap<XMLHttpRequest, XhrContext>()\n\nexport function initXhrObservable(configuration: Configuration) {\n  if (!xhrObservable) {\n    xhrObservable = createXhrObservable(configuration)\n  }\n  return xhrObservable\n}\n\nfunction createXhrObservable(configuration: Configuration) {\n  return new Observable<XhrContext>((observable) => {\n    const { stop: stopInstrumentingStart } = instrumentMethod(XMLHttpRequest.prototype, 'open', openXhr)\n\n    const { stop: stopInstrumentingSend } = instrumentMethod(\n      XMLHttpRequest.prototype,\n      'send',\n      (call) => {\n        sendXhr(call, configuration, observable)\n      },\n      { computeHandlingStack: true }\n    )\n\n    const { stop: stopInstrumentingAbort } = instrumentMethod(XMLHttpRequest.prototype, 'abort', abortXhr)\n\n    return () => {\n      stopInstrumentingStart()\n      stopInstrumentingSend()\n      stopInstrumentingAbort()\n    }\n  })\n}\n\nfunction openXhr({ target: xhr, parameters: [method, url] }: InstrumentedMethodCall<XMLHttpRequest, 'open'>) {\n  xhrContexts.set(xhr, {\n    state: 'open',\n    method: String(method).toUpperCase(),\n    url: normalizeUrl(String(url)),\n  })\n}\n\nfunction sendXhr(\n  { target: xhr, parameters: [body], handlingStack }: InstrumentedMethodCall<XMLHttpRequest, 'send'>,\n  configuration: Configuration,\n  observable: Observable<XhrContext>\n) {\n  const context = xhrContexts.get(xhr)\n  if (!context) {\n    return\n  }\n\n  const startContext = context as XhrStartContext\n  startContext.state = 'start'\n  startContext.startClocks = clocksNow()\n  startContext.isAborted = false\n  startContext.xhr = xhr\n  startContext.handlingStack = handlingStack\n  startContext.requestBody = body\n\n  let hasBeenReported = false\n\n  const { stop: stopInstrumentingOnReadyStateChange } = instrumentMethod(xhr, 'onreadystatechange', () => {\n    if (xhr.readyState === XMLHttpRequest.DONE) {\n      // Try to report the XHR as soon as possible, because the XHR may be mutated by the\n      // application during a future event. For example, Angular is calling .abort() on\n      // completed requests during an onreadystatechange event, so the status becomes '0'\n      // before the request is collected.\n      onEnd()\n    }\n  })\n\n  const onEnd = () => {\n    unsubscribeLoadEndListener()\n    stopInstrumentingOnReadyStateChange()\n    if (hasBeenReported) {\n      return\n    }\n    hasBeenReported = true\n\n    const completeContext = context as XhrCompleteContext\n    completeContext.state = 'complete'\n    completeContext.duration = elapsed(startContext.startClocks.timeStamp, timeStampNow())\n    completeContext.status = xhr.status\n    if (typeof xhr.response === 'string') {\n      completeContext.responseBody = xhr.response\n    }\n    observable.notify(shallowClone(completeContext))\n  }\n\n  const { stop: unsubscribeLoadEndListener } = addEventListener(configuration, xhr, 'loadend', onEnd)\n\n  observable.notify(startContext)\n}\n\nfunction abortXhr({ target: xhr }: InstrumentedMethodCall<XMLHttpRequest, 'abort'>) {\n  const context = xhrContexts.get(xhr) as XhrStartContext | undefined\n  if (context) {\n    context.isAborted = true\n  }\n}\n\n/**\n * Reset the XHR observable global state. This is useful for testing to ensure clean state between tests.\n *\n * @internal\n */\nexport function resetXhrObservable() {\n  xhrObservable = undefined\n}\n"
  },
  {
    "path": "packages/core/src/domain/allowedTrackingOrigins.spec.ts",
    "content": "import { replaceMockable, STACK_WITH_INIT_IN_EXTENSION, STACK_WITH_INIT_IN_PAGE } from '../../test'\nimport { display } from '../tools/display'\nimport {\n  isAllowedTrackingOrigins,\n  ERROR_NOT_ALLOWED_TRACKING_ORIGIN,\n  ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN,\n} from './allowedTrackingOrigins'\n\nconst DEFAULT_CONFIG = {\n  applicationId: 'xxx',\n  clientToken: 'xxx',\n  allowedTrackingOrigins: undefined as any,\n}\n\ndescribe('checkForAllowedTrackingOrigins', () => {\n  let displayErrorSpy: jasmine.Spy\n\n  function mockOrigin(origin: string) {\n    replaceMockable(location, { origin } as Location)\n  }\n\n  beforeEach(() => {\n    displayErrorSpy = spyOn(display, 'error')\n  })\n\n  it('should not warn if not in extension environment', () => {\n    mockOrigin('https://app.example.com')\n    const result = isAllowedTrackingOrigins(DEFAULT_CONFIG, STACK_WITH_INIT_IN_PAGE)\n    expect(displayErrorSpy).not.toHaveBeenCalled()\n    expect(result).toBe(true)\n  })\n\n  describe('when configuration has allowedTrackingOrigins and origin is allowed', () => {\n    it('should not warn if origin matches exactly', () => {\n      mockOrigin('https://app.example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: ['https://app.example.com'],\n        },\n        STACK_WITH_INIT_IN_PAGE\n      )\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(result).toBe(true)\n    })\n\n    it('should not warn if origin matches regex pattern', () => {\n      mockOrigin('https://app.example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [/^https:\\/\\/.*\\.example\\.com$/],\n        },\n        STACK_WITH_INIT_IN_PAGE\n      )\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(result).toBe(true)\n    })\n\n    it('should not warn if origin matches predicate function', () => {\n      mockOrigin('https://app.example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [(origin: string) => origin.includes('example.com')],\n        },\n        STACK_WITH_INIT_IN_PAGE\n      )\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(result).toBe(true)\n    })\n\n    it('should handle multiple patterns', () => {\n      mockOrigin('https://app.example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [\n            'https://exact-match.com',\n            /^https:\\/\\/.*\\.example\\.com$/,\n            (origin: string) => origin.startsWith('https://app.'),\n          ],\n        },\n        STACK_WITH_INIT_IN_PAGE\n      )\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(result).toBe(true)\n    })\n  })\n\n  describe('when configuration has allowedTrackingOrigins but origin is not allowed in extension context', () => {\n    it('should error when origin does not match any allowed pattern', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: ['https://different.com'],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should error when origin does not match regex pattern', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [/^https:\\/\\/specific-[a-z]+\\.com$/],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should error when origin does not match predicate function', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [(origin: string) => origin.includes('specific-id')],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should error when origin does not match any of multiple patterns', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [\n            'https://specific.com',\n            /^https:\\/\\/.*\\.specific\\.com$/,\n            (origin: string) => origin.includes('specific-id'),\n          ],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should error when origin is a partial match', () => {\n      mockOrigin('https://example.com.extra.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: ['https://example.com'],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should not error when in extension and origin matches', () => {\n      mockOrigin('chrome-extension://abcdefghijklmno')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [/^chrome-extension:\\/\\//],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(result).toBe(true)\n    })\n  })\n\n  describe('when configuration does not have allowedTrackingOrigins', () => {\n    it('should log an error when in extension environment and allowedTrackingOrigins is undefined', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: undefined,\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should error when in extension environment and allowedTrackingOrigins is an empty array', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: [],\n        },\n        STACK_WITH_INIT_IN_EXTENSION\n      )\n      expect(displayErrorSpy).toHaveBeenCalledWith(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n      expect(result).toBe(false)\n    })\n\n    it('should not warn when not in extension environment and allowedTrackingOrigins is undefined', () => {\n      mockOrigin('https://example.com')\n      const result = isAllowedTrackingOrigins(\n        {\n          ...DEFAULT_CONFIG,\n          allowedTrackingOrigins: undefined,\n        },\n        STACK_WITH_INIT_IN_PAGE\n      )\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(result).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/allowedTrackingOrigins.ts",
    "content": "import { display } from '../tools/display'\nimport { getGlobalObject } from '../tools/globalObject'\nimport { matchList } from '../tools/matchOption'\nimport { mockable } from '../tools/mockable'\nimport type { InitConfiguration } from './configuration'\nimport { isUnsupportedExtensionEnvironment } from './extension/extensionUtils'\n\nexport const ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN =\n  'Running the Browser SDK in a Web extension content script is forbidden unless the `allowedTrackingOrigins` option is provided.'\nexport const ERROR_NOT_ALLOWED_TRACKING_ORIGIN = 'SDK initialized on a non-allowed domain.'\n\nexport function isAllowedTrackingOrigins(configuration: InitConfiguration, errorStack: string): boolean {\n  const location = mockable(getGlobalObject().location)\n  const windowOrigin = location ? location.origin : ''\n  const allowedTrackingOrigins = configuration.allowedTrackingOrigins\n  if (!allowedTrackingOrigins) {\n    if (isUnsupportedExtensionEnvironment(windowOrigin, errorStack)) {\n      display.error(ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN)\n\n      return false\n    }\n    return true\n  }\n\n  const isAllowed = matchList(allowedTrackingOrigins, windowOrigin)\n  if (!isAllowed) {\n    display.error(ERROR_NOT_ALLOWED_TRACKING_ORIGIN)\n  }\n  return isAllowed\n}\n"
  },
  {
    "path": "packages/core/src/domain/bufferedData.spec.ts",
    "content": "import { replaceMockable, registerCleanupTask } from '../../test'\nimport { Observable } from '../tools/observable'\nimport { clocksNow } from '../tools/utils/timeUtils'\nimport { BufferedDataType, startBufferingData } from './bufferedData'\nimport { ErrorHandling, ErrorSource, type RawError } from './error/error.types'\nimport { trackRuntimeError } from './error/trackRuntimeError'\n\ndescribe('startBufferingData', () => {\n  it('collects runtime errors', (done) => {\n    const runtimeErrorObservable = new Observable<RawError>()\n    replaceMockable(trackRuntimeError, () => runtimeErrorObservable)\n    const { observable, stop } = startBufferingData()\n    registerCleanupTask(stop)\n\n    const rawError = {\n      startClocks: clocksNow(),\n      source: ErrorSource.SOURCE,\n      type: 'Error',\n      stack: 'Error: error!',\n      handling: ErrorHandling.UNHANDLED,\n      causes: undefined,\n      fingerprint: undefined,\n      message: 'error!',\n    }\n\n    runtimeErrorObservable.notify(rawError)\n\n    observable.subscribe((data) => {\n      expect(data).toEqual({\n        type: BufferedDataType.RUNTIME_ERROR,\n        error: rawError,\n      })\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/bufferedData.ts",
    "content": "import { BufferedObservable } from '../tools/observable'\nimport { mockable } from '../tools/mockable'\nimport type { RawError } from './error/error.types'\nimport { trackRuntimeError } from './error/trackRuntimeError'\n\nconst BUFFER_LIMIT = 500\n\nexport const enum BufferedDataType {\n  RUNTIME_ERROR,\n}\n\nexport interface BufferedData {\n  type: BufferedDataType.RUNTIME_ERROR\n  error: RawError\n}\n\nexport function startBufferingData() {\n  const observable = new BufferedObservable<BufferedData>(BUFFER_LIMIT)\n\n  const runtimeErrorSubscription = mockable(trackRuntimeError)().subscribe((error) => {\n    observable.notify({\n      type: BufferedDataType.RUNTIME_ERROR,\n      error,\n    })\n  })\n\n  return {\n    observable,\n    stop: () => {\n      runtimeErrorSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/configuration/configuration.spec.ts",
    "content": "import type { RumEvent } from '../../../../rum-core/src'\nimport { EXHAUSTIVE_INIT_CONFIGURATION, SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION } from '../../../test'\nimport type { ExtractTelemetryConfiguration, MapInitConfigurationKey } from '../../../test'\nimport { DOCS_ORIGIN, MORE_DETAILS, display } from '../../tools/display'\nimport { ExperimentalFeature, isExperimentalFeatureEnabled } from '../../tools/experimentalFeatures'\nimport { SessionPersistence } from '../session/sessionConstants'\nimport { TrackingConsent } from '../trackingConsent'\nimport type { InitConfiguration } from './configuration'\nimport { serializeConfiguration, validateAndBuildConfiguration } from './configuration'\n\ndescribe('validateAndBuildConfiguration', () => {\n  const clientToken = 'some_client_token'\n\n  let displaySpy: jasmine.Spy<typeof display.error>\n\n  beforeEach(() => {\n    displaySpy = spyOn(display, 'error')\n  })\n\n  describe('experimentalFeatures', () => {\n    const TEST_FEATURE_FLAG = 'foo' as ExperimentalFeature\n\n    beforeEach(() => {\n      ;(ExperimentalFeature as any).FOO = TEST_FEATURE_FLAG\n    })\n\n    afterEach(() => {\n      delete (ExperimentalFeature as any).FOO\n    })\n\n    it('ignores unknown experimental features', () => {\n      validateAndBuildConfiguration({\n        clientToken,\n        enableExperimentalFeatures: ['bar', undefined as any, null as any, 11 as any],\n      })\n      expect(isExperimentalFeatureEnabled('bar' as any)).toBeFalse()\n      expect(isExperimentalFeatureEnabled(undefined as any)).toBeFalse()\n      expect(isExperimentalFeatureEnabled(null as any)).toBeFalse()\n      expect(isExperimentalFeatureEnabled(11 as any)).toBeFalse()\n    })\n  })\n\n  describe('validate init configuration', () => {\n    it('requires the InitConfiguration to be defined', () => {\n      expect(validateAndBuildConfiguration(undefined as unknown as InitConfiguration)).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Client Token is not configured, we will not send any data.')\n    })\n\n    it('requires clientToken to be defined', () => {\n      expect(validateAndBuildConfiguration({} as unknown as InitConfiguration)).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Client Token is not configured, we will not send any data.')\n    })\n\n    it(\"shouldn't display any error if the configuration is correct\", () => {\n      validateAndBuildConfiguration({ clientToken: 'yes' })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('requires sessionSampleRate to be a percentage', () => {\n      expect(\n        validateAndBuildConfiguration({ clientToken, sessionSampleRate: 'foo' } as unknown as InitConfiguration)\n      ).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Session Sample Rate should be a number between 0 and 100')\n\n      displaySpy.calls.reset()\n      expect(\n        validateAndBuildConfiguration({ clientToken, sessionSampleRate: 200 } as unknown as InitConfiguration)\n      ).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Session Sample Rate should be a number between 0 and 100')\n\n      displaySpy.calls.reset()\n      validateAndBuildConfiguration({ clientToken: 'yes', sessionSampleRate: 1 })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('requires telemetrySampleRate to be a percentage', () => {\n      expect(\n        validateAndBuildConfiguration({ clientToken, telemetrySampleRate: 'foo' } as unknown as InitConfiguration)\n      ).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Telemetry Sample Rate should be a number between 0 and 100')\n\n      displaySpy.calls.reset()\n      expect(\n        validateAndBuildConfiguration({ clientToken, telemetrySampleRate: 200 } as unknown as InitConfiguration)\n      ).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Telemetry Sample Rate should be a number between 0 and 100')\n\n      displaySpy.calls.reset()\n      validateAndBuildConfiguration({ clientToken: 'yes', telemetrySampleRate: 1 })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('sessionStoreStrategyType', () => {\n    it('allowFallbackToLocalStorage should not be enabled by default', () => {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('')\n      const configuration = validateAndBuildConfiguration({ clientToken })\n      expect(configuration?.sessionStoreStrategyType).toBeUndefined()\n    })\n\n    it('should contain cookie strategy in the configuration by default', () => {\n      const configuration = validateAndBuildConfiguration({ clientToken, allowFallbackToLocalStorage: false })\n      expect(configuration?.sessionStoreStrategyType).toEqual({\n        type: SessionPersistence.COOKIE,\n        cookieOptions: { secure: false, crossSite: false, partitioned: false },\n      })\n    })\n\n    it('should contain cookie strategy in the configuration when fallback is enabled and cookies are available', () => {\n      const configuration = validateAndBuildConfiguration({ clientToken, allowFallbackToLocalStorage: true })\n      expect(configuration?.sessionStoreStrategyType).toEqual({\n        type: SessionPersistence.COOKIE,\n        cookieOptions: { secure: false, crossSite: false, partitioned: false },\n      })\n    })\n\n    it('should contain localStorage strategy in the configuration when localStorage fallback is enabled and cookies are not available', () => {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('')\n      const configuration = validateAndBuildConfiguration({ clientToken, allowFallbackToLocalStorage: true })\n      expect(configuration?.sessionStoreStrategyType).toEqual({ type: SessionPersistence.LOCAL_STORAGE })\n    })\n\n    it('should not contain any strategy if both cookies and local storage are unavailable', () => {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('')\n      spyOn(Storage.prototype, 'getItem').and.throwError('unavailable')\n      const configuration = validateAndBuildConfiguration({ clientToken, allowFallbackToLocalStorage: true })\n      expect(configuration?.sessionStoreStrategyType).toBeUndefined()\n    })\n  })\n\n  describe('beforeSend', () => {\n    it('should be undefined when beforeSend is missing on user configuration', () => {\n      const configuration = validateAndBuildConfiguration({ clientToken })!\n      expect(configuration.beforeSend).toBeUndefined()\n    })\n\n    it('should return the same result as the original', () => {\n      const beforeSend = (event: RumEvent) => {\n        if (event.view.url === '/foo') {\n          return false\n        }\n      }\n      const configuration = validateAndBuildConfiguration({ clientToken, beforeSend })!\n      expect(configuration.beforeSend!({ view: { url: '/foo' } }, {})).toBeFalse()\n      expect(configuration.beforeSend!({ view: { url: '/bar' } }, {})).toBeUndefined()\n    })\n\n    it('should catch errors and log them', () => {\n      const myError = 'Ooops!'\n      const beforeSend = () => {\n        // eslint-disable-next-line @typescript-eslint/only-throw-error\n        throw myError\n      }\n      const configuration = validateAndBuildConfiguration({ clientToken, beforeSend })!\n      expect(configuration.beforeSend!(null, {})).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledWith('beforeSend threw an error:', myError)\n    })\n  })\n\n  describe('allowUntrustedEvents', () => {\n    it('defaults to false', () => {\n      expect(validateAndBuildConfiguration({ clientToken: 'yes' })!.allowUntrustedEvents).toBeFalse()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildConfiguration({ clientToken: 'yes', allowUntrustedEvents: true })!.allowUntrustedEvents\n      ).toBeTrue()\n      expect(\n        validateAndBuildConfiguration({ clientToken: 'yes', allowUntrustedEvents: false })!.allowUntrustedEvents\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildConfiguration({ clientToken: 'yes', allowUntrustedEvents: 'foo' as any })!.allowUntrustedEvents\n      ).toBeTrue()\n    })\n  })\n\n  describe('trackingConsent', () => {\n    it('defaults to \"granted\"', () => {\n      expect(validateAndBuildConfiguration({ clientToken: 'yes' })!.trackingConsent).toBe(TrackingConsent.GRANTED)\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildConfiguration({ clientToken: 'yes', trackingConsent: TrackingConsent.NOT_GRANTED })!\n          .trackingConsent\n      ).toBe(TrackingConsent.NOT_GRANTED)\n      expect(\n        validateAndBuildConfiguration({ clientToken: 'yes', trackingConsent: TrackingConsent.GRANTED })!.trackingConsent\n      ).toBe(TrackingConsent.GRANTED)\n    })\n\n    it('rejects invalid values', () => {\n      expect(validateAndBuildConfiguration({ clientToken: 'yes', trackingConsent: 'foo' as any })).toBeUndefined()\n      expect(displaySpy).toHaveBeenCalledOnceWith('Tracking Consent should be either \"granted\" or \"not-granted\"')\n    })\n  })\n\n  describe('site parameter validation', () => {\n    it('should validate the site parameter', () => {\n      validateAndBuildConfiguration({ clientToken, site: 'foo.com' as any })\n      expect(displaySpy).toHaveBeenCalledOnceWith(\n        `Site should be a valid Datadog site. ${MORE_DETAILS} ${DOCS_ORIGIN}/getting_started/site/.`\n      )\n    })\n  })\n\n  describe('env parameter validation', () => {\n    it('should validate the env parameter', () => {\n      validateAndBuildConfiguration({ clientToken, env: false as any })\n      expect(displaySpy).toHaveBeenCalledOnceWith('Env must be defined as a string')\n    })\n  })\n\n  describe('service parameter validation', () => {\n    it('should validate the service parameter', () => {\n      validateAndBuildConfiguration({ clientToken, service: 1 as any })\n      expect(displaySpy).toHaveBeenCalledOnceWith('Service must be defined as a string')\n    })\n\n    it('should not reject null', () => {\n      const configuration = validateAndBuildConfiguration({ clientToken, service: null })\n      expect(displaySpy).not.toHaveBeenCalled()\n      expect(configuration!.service).toBeUndefined()\n    })\n  })\n\n  describe('version parameter validation', () => {\n    it('should validate the version parameter', () => {\n      validateAndBuildConfiguration({ clientToken, version: 0 as any })\n      expect(displaySpy).toHaveBeenCalledOnceWith('Version must be defined as a string')\n    })\n  })\n\n  describe('allowedTrackingOrigins parameter validation', () => {\n    it('should validate the allowedTrackingOrigins parameter', () => {\n      validateAndBuildConfiguration({ clientToken, allowedTrackingOrigins: 'foo' as any })\n      expect(displaySpy).toHaveBeenCalledOnceWith('Allowed Tracking Origins must be an array')\n    })\n  })\n\n  describe('serializeConfiguration', () => {\n    it('should serialize the configuration', () => {\n      // By specifying the type here, we can ensure that serializeConfiguration is returning an\n      // object containing all expected properties.\n      const serializedConfiguration: ExtractTelemetryConfiguration<MapInitConfigurationKey<keyof InitConfiguration>> =\n        serializeConfiguration(EXHAUSTIVE_INIT_CONFIGURATION)\n\n      expect(serializedConfiguration).toEqual(SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/configuration/configuration.ts",
    "content": "import { catchUserErrors } from '../../tools/catchUserErrors'\nimport { DOCS_ORIGIN, MORE_DETAILS, display } from '../../tools/display'\nimport type { RawTelemetryConfiguration } from '../telemetry'\nimport { isPercentage } from '../../tools/utils/numberUtils'\nimport { objectHasValue } from '../../tools/utils/objectUtils'\nimport { selectSessionStoreStrategyType } from '../session/sessionStore'\nimport type { SessionStoreStrategyType } from '../session/storeStrategies/sessionStoreStrategy'\nimport { TrackingConsent } from '../trackingConsent'\nimport type { SessionPersistence } from '../session/sessionConstants'\nimport type { MatchOption } from '../../tools/matchOption'\nimport { isAllowedTrackingOrigins } from '../allowedTrackingOrigins'\nimport type { Site } from '../intakeSites'\nimport { isWorkerEnvironment } from '../../tools/globalObject'\nimport type { TransportConfiguration } from './transportConfiguration'\nimport { computeTransportConfiguration } from './transportConfiguration'\n\n/**\n * Default privacy level for the browser SDK.\n *\n * [Replay Privacy Options](https://docs.datadoghq.com/real_user_monitoring/session_replay/browser/privacy_options) for further information.\n */\nexport const DefaultPrivacyLevel = {\n  ALLOW: 'allow',\n  MASK: 'mask',\n  MASK_USER_INPUT: 'mask-user-input',\n  MASK_UNLESS_ALLOWLISTED: 'mask-unless-allowlisted',\n} as const\nexport type DefaultPrivacyLevel = (typeof DefaultPrivacyLevel)[keyof typeof DefaultPrivacyLevel]\n\n/**\n * Trace context injection option.\n *\n * See [Connect RUM and Traces](https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum) for further information.\n */\nexport const TraceContextInjection = {\n  ALL: 'all',\n  SAMPLED: 'sampled',\n} as const\n\n/**\n * Trace context injection option.\n *\n * See [Connect RUM and Traces](https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum) for further information.\n *\n */\nexport type TraceContextInjection = (typeof TraceContextInjection)[keyof typeof TraceContextInjection]\n\nexport interface InitConfiguration {\n  /**\n   * The client token for Datadog. Required for authenticating your application with Datadog.\n   *\n   * @category Authentication\n   */\n  clientToken: string\n\n  /**\n   * A callback function that can be used to modify events before they are sent to Datadog.\n   *\n   * @category Data Collection\n   */\n  beforeSend?: GenericBeforeSendCallback | undefined\n\n  /**\n   * The percentage of sessions tracked. A value between 0 and 100.\n   *\n   * @category Data Collection\n   * @defaultValue 100\n   */\n  sessionSampleRate?: number | undefined\n\n  /**\n   * The percentage of telemetry events sent. A value between 0 and 100.\n   *\n   * @category Data Collection\n   * @defaultValue 20\n   */\n  telemetrySampleRate?: number | undefined\n\n  /**\n   * Initialization fails silently if the RUM Browser SDK is already initialized on the page.\n   *\n   * @defaultValue false\n   */\n  silentMultipleInit?: boolean | undefined\n\n  /**\n   * Which storage strategy to use for persisting sessions. Can be 'cookie', 'local-storage', or 'memory'.\n   * When an array is provided, the SDK will attempt each persistence type in the order specified.\n   *\n   * Important: If you are using the RUM and Logs Browser SDKs, this option must be configured with identical values\n   *\n   * Note: 'memory' option is only for use with single-page applications. All page loads will start a new session, likely resulting in an increase in total number of RUM sessions\n   *\n   * @category Session Persistence\n   * @defaultValue \"cookie\"\n   */\n  sessionPersistence?: SessionPersistence | SessionPersistence[] | undefined\n\n  /**\n   * Allows the use of localStorage when cookies cannot be set. This enables the RUM Browser SDK to run in environments that do not provide cookie support.\n   *\n   * Important: If you are using the RUM and Logs Browser SDKs, this option must be configured with identical values\n   * See [Monitor Electron Applications Using the Browser SDK](https://docs.datadoghq.com/real_user_monitoring/guide/monitor-electron-applications-using-browser-sdk) for further information.\n   *\n   * @category Session Persistence\n   * @deprecated use `sessionPersistence: local-storage` where you want to use localStorage instead\n   */\n  allowFallbackToLocalStorage?: boolean | undefined\n\n  /**\n   * Allow listening to DOM events dispatched programmatically ([untrusted events](https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted)). Enabling this option can be useful if you heavily rely on programmatic events, such as in an automated UI test environment.\n   *\n   * @defaultValue false\n   */\n  allowUntrustedEvents?: boolean | undefined\n\n  /**\n   * Store global context and user context in localStorage to preserve them along the user navigation.\n   * See [Contexts life cycle](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/?tab=npm#contexts-life-cycle) for further information.\n   *\n   * @defaultValue false\n   */\n  storeContextsAcrossPages?: boolean | undefined\n\n  /**\n   * Set the initial user tracking consent state.\n   * See [User tracking consent](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/?tab=npm#user-tracking-consent) for further information.\n   *\n   * @category Privacy\n   * @defaultValue granted\n   */\n  trackingConsent?: TrackingConsent | undefined\n\n  /**\n   * List of origins where the SDK is allowed to run when used in a browser extension context.\n   * Matches urls against the extensions origin.\n   * If not provided and the SDK is running in a browser extension, the SDK will not run.\n   */\n  allowedTrackingOrigins?: MatchOption[] | undefined\n\n  // transport options\n  /**\n   * Optional proxy URL, for example: https://www.proxy.com/path.\n   * See [Proxy Your Browser RUM Data](https://docs.datadoghq.com/real_user_monitoring/guide/proxy-rum-data) for further information.\n   *\n   * @category Transport\n   */\n  proxy?: string | ProxyFn | undefined\n\n  /**\n   * The Datadog [site](https://docs.datadoghq.com/getting_started/site) parameter of your organization.\n   *\n   * @category Transport\n   * @defaultValue datadoghq.com\n   */\n  site?: Site | undefined\n\n  // tag and context options\n  /**\n   * The service name for your application. Follows the [tag syntax requirements](https://docs.datadoghq.com/getting_started/tagging/#define-tags).\n   *\n   * @category Data Collection\n   */\n  service?: string | undefined | null\n\n  /**\n   * The application’s environment, for example: prod, pre-prod, and staging. Follows the [tag syntax requirements](https://docs.datadoghq.com/getting_started/tagging/#define-tags).\n   *\n   * @category Data Collection\n   */\n  env?: string | undefined | null\n\n  /**\n   * The application’s version, for example: 1.2.3, 6c44da20, and 2020.02.13. Follows the [tag syntax requirements](https://docs.datadoghq.com/getting_started/tagging/#define-tags).\n   *\n   * @category Data Collection\n   */\n  version?: string | undefined | null\n\n  // cookie options\n  /**\n   * Use a partitioned secure cross-site session cookie. This allows the RUM Browser SDK to run when the site is loaded from another one (iframe). Implies `useSecureSessionCookie`.\n   *\n   * Important: If you are using the RUM and Logs Browser SDKs, this option must be configured with identical values\n   *\n   * @category Session Persistence\n   * @defaultValue false\n   */\n  usePartitionedCrossSiteSessionCookie?: boolean | undefined\n\n  /**\n   * Use a secure session cookie. This disables RUM events sent on insecure (non-HTTPS) connections.\n   *\n   * Important: If you are using the RUM and Logs Browser SDKs, this option must be configured with identical values\n   *\n   * @category Session Persistence\n   * @defaultValue false\n   */\n  useSecureSessionCookie?: boolean | undefined\n\n  /**\n   * Preserve the session across subdomains for the same site.\n   *\n   * Important: If you are using the RUM and Logs Browser SDKs, this option must be configured with identical values\n   *\n   * @category Session Persistence\n   * @defaultValue false\n   */\n  trackSessionAcrossSubdomains?: boolean | undefined\n\n  /**\n   * Track anonymous user for the same site and extend cookie expiration date\n   *\n   * @category Data Collection\n   * @defaultValue true\n   */\n  trackAnonymousUser?: boolean | undefined\n\n  /**\n   * Encode cookie options in the cookie value. This can be used as a mitigation for microssession issues.\n   * ⚠️ This is a beta feature and may be changed or removed in the future.\n   *\n   * @category Beta\n   * @defaultValue false\n   */\n  betaEncodeCookieOptions?: boolean | undefined\n\n  // internal options\n  /**\n   * [Internal option] Enable experimental features\n   *\n   * @internal\n   */\n  enableExperimentalFeatures?: string[] | undefined\n\n  /**\n   * [Internal option] Configure the dual shipping to another datacenter\n   *\n   * @internal\n   */\n  replica?: ReplicaUserConfiguration | undefined\n\n  /**\n   * [Internal option] Set the datacenter from where the data is dual shipped\n   *\n   * @internal\n   */\n  datacenter?: string\n\n  /**\n   * [Internal option] Datadog internal analytics subdomain\n   *\n   * @internal\n   */\n  // TODO next major: remove this option and replace usages by proxyFn\n  internalAnalyticsSubdomain?: string\n\n  /**\n   * [Internal option] The percentage of telemetry configuration sent. A value between 0 and 100.\n   *\n   * @internal\n   * @defaultValue 5\n   */\n  telemetryConfigurationSampleRate?: number\n\n  /**\n   * [Internal option] The percentage of telemetry usage sent. A value between 0 and 100.\n   *\n   * @internal\n   * @defaultValue 5\n   */\n  telemetryUsageSampleRate?: number\n\n  /**\n   * [Internal option] Additional configuration for the SDK.\n   *\n   * @internal\n   */\n  source?: 'browser' | 'flutter' | 'unity' | undefined\n\n  /**\n   * [Internal option] Additional configuration for the SDK.\n   *\n   * @internal\n   */\n  sdkVersion?: string | undefined\n\n  /**\n   * [Internal option] Additional configuration for the SDK.\n   *\n   * @internal\n   */\n  variant?: string | undefined\n}\n\n// This type is only used to build the core configuration. Logs and RUM SDKs are using a proper type\n// for this option.\ntype GenericBeforeSendCallback = (event: any, context?: any) => unknown\n\n/**\n * path: /api/vX/product\n * parameters: xxx=yyy&zzz=aaa\n */\nexport type ProxyFn = (options: { path: string; parameters: string }) => string\n\n/**\n * @internal\n */\nexport interface ReplicaUserConfiguration {\n  applicationId?: string\n  clientToken: string\n}\n\nexport interface Configuration extends TransportConfiguration {\n  // Built from init configuration\n  beforeSend: GenericBeforeSendCallback | undefined\n  sessionStoreStrategyType: SessionStoreStrategyType | undefined\n  sessionSampleRate: number\n  telemetrySampleRate: number\n  telemetryConfigurationSampleRate: number\n  telemetryUsageSampleRate: number\n  service?: string | undefined\n  version?: string | undefined\n  env?: string | undefined\n  silentMultipleInit: boolean\n  allowUntrustedEvents: boolean\n  trackingConsent: TrackingConsent\n  storeContextsAcrossPages: boolean\n  trackAnonymousUser?: boolean\n  betaEncodeCookieOptions: boolean\n\n  // internal\n  sdkVersion: string | undefined\n  source: 'browser' | 'flutter' | 'unity'\n  variant: string | undefined\n}\n\nfunction isString(tag: unknown, tagName: string): tag is string | undefined | null {\n  if (tag !== undefined && tag !== null && typeof tag !== 'string') {\n    display.error(`${tagName} must be defined as a string`)\n    return false\n  }\n  return true\n}\n\nfunction isDatadogSite(site: unknown) {\n  if (site && typeof site === 'string' && !/(datadog|ddog|datad0g|dd0g)/.test(site)) {\n    display.error(`Site should be a valid Datadog site. ${MORE_DETAILS} ${DOCS_ORIGIN}/getting_started/site/.`)\n    return false\n  }\n  return true\n}\n\nexport function isSampleRate(sampleRate: unknown, name: string) {\n  if (sampleRate !== undefined && !isPercentage(sampleRate)) {\n    display.error(`${name} Sample Rate should be a number between 0 and 100`)\n    return false\n  }\n  return true\n}\n\nexport function validateAndBuildConfiguration(\n  initConfiguration: InitConfiguration,\n  errorStack?: string\n): Configuration | undefined {\n  if (!initConfiguration || !initConfiguration.clientToken) {\n    display.error('Client Token is not configured, we will not send any data.')\n    return\n  }\n\n  if (\n    initConfiguration.allowedTrackingOrigins !== undefined &&\n    !Array.isArray(initConfiguration.allowedTrackingOrigins)\n  ) {\n    display.error('Allowed Tracking Origins must be an array')\n    return\n  }\n\n  if (\n    !isDatadogSite(initConfiguration.site) ||\n    !isSampleRate(initConfiguration.sessionSampleRate, 'Session') ||\n    !isSampleRate(initConfiguration.telemetrySampleRate, 'Telemetry') ||\n    !isSampleRate(initConfiguration.telemetryConfigurationSampleRate, 'Telemetry Configuration') ||\n    !isSampleRate(initConfiguration.telemetryUsageSampleRate, 'Telemetry Usage') ||\n    !isString(initConfiguration.version, 'Version') ||\n    !isString(initConfiguration.env, 'Env') ||\n    !isString(initConfiguration.service, 'Service') ||\n    !isAllowedTrackingOrigins(initConfiguration, errorStack ?? '')\n  ) {\n    return\n  }\n\n  if (\n    initConfiguration.trackingConsent !== undefined &&\n    !objectHasValue(TrackingConsent, initConfiguration.trackingConsent)\n  ) {\n    display.error('Tracking Consent should be either \"granted\" or \"not-granted\"')\n    return\n  }\n\n  return {\n    beforeSend:\n      initConfiguration.beforeSend && catchUserErrors(initConfiguration.beforeSend, 'beforeSend threw an error:'),\n    sessionStoreStrategyType: isWorkerEnvironment ? undefined : selectSessionStoreStrategyType(initConfiguration),\n    sessionSampleRate: initConfiguration.sessionSampleRate ?? 100,\n    telemetrySampleRate: initConfiguration.telemetrySampleRate ?? 20,\n    telemetryConfigurationSampleRate: initConfiguration.telemetryConfigurationSampleRate ?? 5,\n    telemetryUsageSampleRate: initConfiguration.telemetryUsageSampleRate ?? 5,\n    service: initConfiguration.service ?? undefined,\n    env: initConfiguration.env ?? undefined,\n    version: initConfiguration.version ?? undefined,\n    datacenter: initConfiguration.datacenter ?? undefined,\n    silentMultipleInit: !!initConfiguration.silentMultipleInit,\n    allowUntrustedEvents: !!initConfiguration.allowUntrustedEvents,\n    trackingConsent: initConfiguration.trackingConsent ?? TrackingConsent.GRANTED,\n    trackAnonymousUser: initConfiguration.trackAnonymousUser ?? true,\n    storeContextsAcrossPages: !!initConfiguration.storeContextsAcrossPages,\n    betaEncodeCookieOptions: !!initConfiguration.betaEncodeCookieOptions,\n\n    /**\n     * The source of the SDK, used for support plugins purposes.\n     */\n    variant: initConfiguration.variant,\n    sdkVersion: initConfiguration.sdkVersion,\n\n    ...computeTransportConfiguration(initConfiguration),\n  }\n}\n\nexport function serializeConfiguration(initConfiguration: InitConfiguration) {\n  return {\n    session_sample_rate: initConfiguration.sessionSampleRate,\n    telemetry_sample_rate: initConfiguration.telemetrySampleRate,\n    telemetry_configuration_sample_rate: initConfiguration.telemetryConfigurationSampleRate,\n    telemetry_usage_sample_rate: initConfiguration.telemetryUsageSampleRate,\n    use_before_send: !!initConfiguration.beforeSend,\n    use_partitioned_cross_site_session_cookie: initConfiguration.usePartitionedCrossSiteSessionCookie,\n    use_secure_session_cookie: initConfiguration.useSecureSessionCookie,\n    use_proxy: !!initConfiguration.proxy,\n    silent_multiple_init: initConfiguration.silentMultipleInit,\n    track_session_across_subdomains: initConfiguration.trackSessionAcrossSubdomains,\n    track_anonymous_user: initConfiguration.trackAnonymousUser,\n    session_persistence: Array.isArray(initConfiguration.sessionPersistence)\n      ? initConfiguration.sessionPersistence[0]\n      : initConfiguration.sessionPersistence,\n    allow_fallback_to_local_storage: !!initConfiguration.allowFallbackToLocalStorage,\n    store_contexts_across_pages: !!initConfiguration.storeContextsAcrossPages,\n    allow_untrusted_events: !!initConfiguration.allowUntrustedEvents,\n    tracking_consent: initConfiguration.trackingConsent,\n    use_allowed_tracking_origins: Array.isArray(initConfiguration.allowedTrackingOrigins),\n    beta_encode_cookie_options: initConfiguration.betaEncodeCookieOptions,\n    source: initConfiguration.source,\n    sdk_version: initConfiguration.sdkVersion,\n    variant: initConfiguration.variant,\n  } satisfies RawTelemetryConfiguration\n}\n"
  },
  {
    "path": "packages/core/src/domain/configuration/endpointBuilder.spec.ts",
    "content": "import type { Payload } from '../../transport'\nimport type { InitConfiguration } from './configuration'\nimport { createEndpointBuilder } from './endpointBuilder'\n\nconst DEFAULT_PAYLOAD = {} as Payload\n\ndescribe('endpointBuilder', () => {\n  const clientToken = 'some_client_token'\n  let initConfiguration: InitConfiguration\n\n  beforeEach(() => {\n    initConfiguration = { clientToken }\n  })\n\n  describe('query parameters', () => {\n    it('should add intake query parameters', () => {\n      expect(createEndpointBuilder(initConfiguration, 'rum').build('fetch', DEFAULT_PAYLOAD)).toMatch(\n        `&dd-api-key=${clientToken}&dd-evp-origin-version=(.*)&dd-evp-origin=browser&dd-request-id=(.*)`\n      )\n    })\n\n    it('should add batch_time for rum endpoint', () => {\n      expect(createEndpointBuilder(initConfiguration, 'rum').build('fetch', DEFAULT_PAYLOAD)).toContain('&batch_time=')\n    })\n\n    it('should not add batch_time for logs and replay endpoints', () => {\n      expect(createEndpointBuilder(initConfiguration, 'logs').build('fetch', DEFAULT_PAYLOAD)).not.toContain(\n        '&batch_time='\n      )\n      expect(createEndpointBuilder(initConfiguration, 'replay').build('fetch', DEFAULT_PAYLOAD)).not.toContain(\n        '&batch_time='\n      )\n    })\n\n    it('should add the provided encoding', () => {\n      expect(\n        createEndpointBuilder(initConfiguration, 'rum').build('fetch', { ...DEFAULT_PAYLOAD, encoding: 'deflate' })\n      ).toContain('&dd-evp-encoding=deflate')\n    })\n\n    it('should not start with ddsource for internal analytics mode', () => {\n      const url = createEndpointBuilder({ ...initConfiguration, internalAnalyticsSubdomain: 'foo' }, 'rum').build(\n        'fetch',\n        DEFAULT_PAYLOAD\n      )\n      expect(url).not.toContain('/rum?ddsource')\n      expect(url).toContain('ddsource=browser')\n    })\n\n    it('accepts extra parameters', () => {\n      const extraParameters = ['application.id=1234', 'application.version=1.0.0']\n      const url = createEndpointBuilder(initConfiguration, 'rum', extraParameters).build('fetch', DEFAULT_PAYLOAD)\n      expect(url).toContain('application.id=1234')\n      expect(url).toContain('application.version=1.0.0')\n    })\n  })\n\n  describe('proxy configuration', () => {\n    it('should replace the intake endpoint by the proxy and set the intake path and parameters in the attribute ddforward', () => {\n      expect(\n        createEndpointBuilder({ ...initConfiguration, proxy: 'https://proxy.io/path' }, 'rum').build(\n          'fetch',\n          DEFAULT_PAYLOAD\n        )\n      ).toMatch(\n        `https://proxy.io/path\\\\?ddforward=${encodeURIComponent(\n          `/api/v2/rum?ddsource=(.*)&dd-api-key=${clientToken}` +\n            '&dd-evp-origin-version=(.*)&dd-evp-origin=browser&dd-request-id=(.*)&batch_time=(.*)'\n        )}`\n      )\n    })\n\n    it('normalizes the proxy url', () => {\n      const endpoint = createEndpointBuilder({ ...initConfiguration, proxy: '/path' }, 'rum').build(\n        'fetch',\n        DEFAULT_PAYLOAD\n      )\n      expect(endpoint.startsWith(`${location.origin}/path?ddforward`)).toBeTrue()\n    })\n\n    it('should allow to fully control the proxy url', () => {\n      const proxyFn = (options: { path: string; parameters: string }) =>\n        `https://proxy.io/prefix${options.path}/suffix?${options.parameters}`\n      expect(\n        createEndpointBuilder({ ...initConfiguration, proxy: proxyFn }, 'rum').build('fetch', DEFAULT_PAYLOAD)\n      ).toMatch(\n        `https://proxy.io/prefix/api/v2/rum/suffix\\\\?ddsource=(.*)&dd-api-key=${clientToken}&dd-evp-origin-version=(.*)&dd-evp-origin=browser&dd-request-id=(.*)&batch_time=(.*)`\n      )\n    })\n  })\n\n  describe('_dd attributes', () => {\n    it('should contain api', () => {\n      expect(createEndpointBuilder(initConfiguration, 'rum').build('fetch', DEFAULT_PAYLOAD)).toContain('_dd.api=fetch')\n    })\n\n    it('should contain retry infos', () => {\n      expect(\n        createEndpointBuilder(initConfiguration, 'rum').build('fetch', {\n          ...DEFAULT_PAYLOAD,\n          retry: {\n            count: 5,\n            lastFailureStatus: 408,\n          },\n        })\n      ).toContain('_dd.retry_count=5&_dd.retry_after=408')\n    })\n\n    it('should not contain any _dd attributes for non rum endpoints', () => {\n      expect(\n        createEndpointBuilder(initConfiguration, 'logs').build('fetch', {\n          ...DEFAULT_PAYLOAD,\n          retry: {\n            count: 5,\n            lastFailureStatus: 408,\n          },\n        })\n      ).not.toContain('_dd.api=fetch&_dd.retry_count=5&_dd.retry_after=408')\n    })\n  })\n\n  describe('PCI compliance intake with option', () => {\n    it('should return PCI compliance intake endpoint if site is us1', () => {\n      const config: InitConfiguration & { usePciIntake?: boolean } = {\n        clientToken,\n        usePciIntake: true,\n        site: 'datadoghq.com',\n      }\n      expect(createEndpointBuilder(config, 'logs').build('fetch', DEFAULT_PAYLOAD)).toContain(\n        'https://pci.browser-intake-datadoghq.com'\n      )\n    })\n    it('should not return PCI compliance intake endpoint if site is not us1', () => {\n      const config: InitConfiguration & { usePciIntake?: boolean } = {\n        clientToken,\n        usePciIntake: true,\n        site: 'ap1.datadoghq.com',\n      }\n      expect(createEndpointBuilder(config, 'logs').build('fetch', DEFAULT_PAYLOAD)).not.toContain(\n        'https://pci.browser-intake-datadoghq.com'\n      )\n    })\n    it('should not return PCI compliance intake endpoint if and site is us1 and track is not logs', () => {\n      const config: InitConfiguration & { usePciIntake?: boolean } = {\n        clientToken,\n        usePciIntake: true,\n        site: 'datadoghq.com',\n      }\n      expect(createEndpointBuilder(config, 'rum').build('fetch', DEFAULT_PAYLOAD)).not.toContain(\n        'https://pci.browser-intake-datadoghq.com'\n      )\n    })\n  })\n\n  describe('source configuration', () => {\n    it('should use the default source when no configuration is provided', () => {\n      const endpoint = createEndpointBuilder(initConfiguration, 'rum').build('fetch', DEFAULT_PAYLOAD)\n      expect(endpoint).toContain('ddsource=browser')\n    })\n\n    it('should use flutter source when provided', () => {\n      const config = { ...initConfiguration, source: 'flutter' as const }\n      const endpoint = createEndpointBuilder(config, 'rum').build('fetch', DEFAULT_PAYLOAD)\n      expect(endpoint).toContain('ddsource=flutter')\n    })\n\n    it('should use unity source when provided', () => {\n      const config = { ...initConfiguration, source: 'unity' as const }\n      const endpoint = createEndpointBuilder(config, 'rum').build('fetch', DEFAULT_PAYLOAD)\n      expect(endpoint).toContain('ddsource=unity')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/configuration/endpointBuilder.ts",
    "content": "import type { Payload } from '../../transport'\nimport { timeStampNow } from '../../tools/utils/timeUtils'\nimport { normalizeUrl } from '../../tools/utils/urlPolyfill'\nimport { generateUUID } from '../../tools/utils/stringUtils'\nimport { INTAKE_SITE_FED_STAGING, INTAKE_SITE_US1, PCI_INTAKE_HOST_US1 } from '../intakeSites'\nimport type { InitConfiguration } from './configuration'\n\n// replaced at build time\ndeclare const __BUILD_ENV__SDK_VERSION__: string\n\nexport type TrackType = 'logs' | 'rum' | 'replay' | 'profile' | 'exposures' | 'flagevaluation'\nexport type ApiType =\n  | 'fetch'\n  | 'beacon'\n  // 'manual' reflects that the request have been sent manually, outside of the SDK (ex: via curl or\n  // a Node.js script).\n  | 'manual'\n\nexport type EndpointBuilder = ReturnType<typeof createEndpointBuilder>\n\nexport function createEndpointBuilder(\n  initConfiguration: InitConfiguration,\n  trackType: TrackType,\n  extraParameters?: string[]\n) {\n  const buildUrlWithParameters = createEndpointUrlWithParametersBuilder(initConfiguration, trackType)\n\n  return {\n    build(api: ApiType, payload: Payload) {\n      const parameters = buildEndpointParameters(initConfiguration, trackType, api, payload, extraParameters)\n      return buildUrlWithParameters(parameters)\n    },\n    trackType,\n  }\n}\n\n/**\n * Create a function used to build a full endpoint url from provided parameters. The goal of this\n * function is to pre-compute some parts of the URL to avoid re-computing everything on every\n * request, as only parameters are changing.\n */\nfunction createEndpointUrlWithParametersBuilder(\n  initConfiguration: InitConfiguration,\n  trackType: TrackType\n): (parameters: string) => string {\n  const path = `/api/v2/${trackType}`\n  const proxy = initConfiguration.proxy\n  if (typeof proxy === 'string') {\n    const normalizedProxyUrl = normalizeUrl(proxy)\n    return (parameters) => `${normalizedProxyUrl}?ddforward=${encodeURIComponent(`${path}?${parameters}`)}`\n  }\n  if (typeof proxy === 'function') {\n    return (parameters) => proxy({ path, parameters })\n  }\n  const host = buildEndpointHost(trackType, initConfiguration)\n  return (parameters) => `https://${host}${path}?${parameters}`\n}\n\nexport function buildEndpointHost(\n  trackType: TrackType,\n  initConfiguration: InitConfiguration & { usePciIntake?: boolean }\n) {\n  const { site = INTAKE_SITE_US1, internalAnalyticsSubdomain } = initConfiguration\n\n  if (trackType === 'logs' && initConfiguration.usePciIntake && site === INTAKE_SITE_US1) {\n    return PCI_INTAKE_HOST_US1\n  }\n\n  if (internalAnalyticsSubdomain && site === INTAKE_SITE_US1) {\n    return `${internalAnalyticsSubdomain}.${INTAKE_SITE_US1}`\n  }\n\n  if (site === INTAKE_SITE_FED_STAGING) {\n    return `http-intake.logs.${site}`\n  }\n\n  const domainParts = site.split('.')\n  const extension = domainParts.pop()\n  return `browser-intake-${domainParts.join('-')}.${extension!}`\n}\n\n/**\n * Build parameters to be used for an intake request. Parameters should be re-built for each\n * request, as they change randomly.\n */\nfunction buildEndpointParameters(\n  { clientToken, internalAnalyticsSubdomain, source = 'browser' }: InitConfiguration,\n  trackType: TrackType,\n  api: ApiType,\n  { retry, encoding }: Payload,\n  extraParameters: string[] = []\n) {\n  const parameters = [\n    `ddsource=${source}`,\n    `dd-api-key=${clientToken}`,\n    `dd-evp-origin-version=${encodeURIComponent(__BUILD_ENV__SDK_VERSION__)}`,\n    'dd-evp-origin=browser',\n    `dd-request-id=${generateUUID()}`,\n  ].concat(extraParameters)\n\n  if (encoding) {\n    parameters.push(`dd-evp-encoding=${encoding}`)\n  }\n\n  if (trackType === 'rum') {\n    parameters.push(`batch_time=${timeStampNow()}`, `_dd.api=${api}`)\n\n    if (retry) {\n      parameters.push(`_dd.retry_count=${retry.count}`, `_dd.retry_after=${retry.lastFailureStatus}`)\n    }\n  }\n\n  if (internalAnalyticsSubdomain) {\n    parameters.reverse()\n  }\n\n  return parameters.join('&')\n}\n"
  },
  {
    "path": "packages/core/src/domain/configuration/index.ts",
    "content": "export type { Configuration, InitConfiguration, ProxyFn } from './configuration'\nexport {\n  DefaultPrivacyLevel,\n  TraceContextInjection,\n  isSampleRate,\n  validateAndBuildConfiguration,\n  serializeConfiguration,\n} from './configuration'\nexport type { EndpointBuilder, TrackType } from './endpointBuilder'\nexport { createEndpointBuilder, buildEndpointHost } from './endpointBuilder'\nexport { computeTransportConfiguration, isIntakeUrl } from './transportConfiguration'\n"
  },
  {
    "path": "packages/core/src/domain/configuration/transportConfiguration.spec.ts",
    "content": "import { INTAKE_SITE_FED_STAGING } from '../intakeSites'\nimport type { Payload } from '../../transport'\nimport { computeTransportConfiguration, isIntakeUrl } from './transportConfiguration'\n\nconst DEFAULT_PAYLOAD = {} as Payload\n\ndescribe('transportConfiguration', () => {\n  const clientToken = 'some_client_token'\n  const internalAnalyticsSubdomain = 'ia-rum-intake'\n  const intakeParameters = 'ddsource=browser&dd-api-key=xxxx&dd-request-id=1234567890'\n\n  describe('site', () => {\n    it('should use US site by default', () => {\n      const configuration = computeTransportConfiguration({ clientToken })\n      expect(configuration.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).toContain('datadoghq.com')\n      expect(configuration.site).toBe('datadoghq.com')\n    })\n\n    it('should use logs intake domain for fed staging', () => {\n      const configuration = computeTransportConfiguration({ clientToken, site: INTAKE_SITE_FED_STAGING })\n      expect(configuration.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).toContain(\n        'http-intake.logs.dd0g-gov.com'\n      )\n      expect(configuration.site).toBe(INTAKE_SITE_FED_STAGING)\n    })\n\n    it('should use site value when set', () => {\n      const configuration = computeTransportConfiguration({ clientToken, site: 'datadoghq.com' })\n      expect(configuration.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).toContain('datadoghq.com')\n      expect(configuration.site).toBe('datadoghq.com')\n    })\n  })\n\n  describe('internalAnalyticsSubdomain', () => {\n    it('should use internal analytics subdomain value when set for datadoghq.com site', () => {\n      const configuration = computeTransportConfiguration({\n        clientToken,\n        internalAnalyticsSubdomain,\n      })\n      expect(configuration.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).toContain(internalAnalyticsSubdomain)\n    })\n\n    it('should not use internal analytics subdomain value when set for other sites', () => {\n      const configuration = computeTransportConfiguration({\n        clientToken,\n        site: 'us3.datadoghq.com',\n        internalAnalyticsSubdomain,\n      })\n      expect(configuration.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).not.toContain(internalAnalyticsSubdomain)\n    })\n  })\n\n  it('adds the replica application id to the rum replica endpoint', () => {\n    const replicaApplicationId = 'replica-application-id'\n    const configuration = computeTransportConfiguration({\n      clientToken,\n      replica: {\n        clientToken: 'replica-client-token',\n        applicationId: replicaApplicationId,\n      },\n    })\n    expect(configuration.replica!.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).toContain(\n      `application.id=${replicaApplicationId}`\n    )\n  })\n\n  describe('isIntakeUrl', () => {\n    const v1IntakePath = `/v1/input/${clientToken}`\n    ;[\n      { site: 'datadoghq.eu', intakeDomain: 'browser-intake-datadoghq.eu' },\n      { site: 'datadoghq.com', intakeDomain: 'browser-intake-datadoghq.com' },\n      { site: 'datadoghq.com', intakeDomain: 'pci.browser-intake-datadoghq.com' },\n      { site: 'us3.datadoghq.com', intakeDomain: 'browser-intake-us3-datadoghq.com' },\n      { site: 'us5.datadoghq.com', intakeDomain: 'browser-intake-us5-datadoghq.com' },\n      { site: 'ap1.datadoghq.com', intakeDomain: 'browser-intake-ap1-datadoghq.com' },\n      { site: 'ddog-gov.com', intakeDomain: 'browser-intake-ddog-gov.com' },\n      { site: 'datad0g.com', intakeDomain: 'browser-intake-datad0g.com' },\n      { site: 'dd0g-gov.com', intakeDomain: 'http-intake.logs.dd0g-gov.com' },\n    ].forEach(({ site, intakeDomain }) => {\n      it(`should detect intake request to ${intakeDomain} for site ${site}`, () => {\n        expect(isIntakeUrl(`https://${intakeDomain}/api/v2/rum?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://${intakeDomain}/api/v2/logs?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://${intakeDomain}/api/v2/replay?${intakeParameters}`)).toBe(true)\n      })\n\n      it(`should detect older versions of the ${site} site for intake domain ${intakeDomain}`, () => {\n        // v4 intake endpoints\n        expect(isIntakeUrl(`https://rum.${intakeDomain}/api/v2/rum?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://logs.${intakeDomain}/api/v2/logs?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://replay.${intakeDomain}/api/v2/replay?${intakeParameters}`)).toBe(true)\n\n        // pre-v4 intake endpoints\n        expect(isIntakeUrl(`https://rum.${intakeDomain}${v1IntakePath}?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://logs.${intakeDomain}${v1IntakePath}?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://rum-http-intake.logs.${site}${v1IntakePath}?${intakeParameters}`)).toBe(true)\n        expect(isIntakeUrl(`https://browser-http-intake.logs.${site}${v1IntakePath}?${intakeParameters}`)).toBe(true)\n      })\n    })\n\n    it('should detect internal analytics intake request for datadoghq.com site', () => {\n      expect(isIntakeUrl(`https://${internalAnalyticsSubdomain}.datadoghq.com/api/v2/rum?${intakeParameters}`)).toBe(\n        true\n      )\n    })\n\n    it('should not detect non intake request', () => {\n      expect(isIntakeUrl('https://www.foo.com')).toBe(false)\n    })\n\n    describe('proxy configuration', () => {\n      it('should detect proxy intake request', () => {\n        expect(\n          isIntakeUrl(`https://www.proxy.com/?ddforward=${encodeURIComponent(`/api/v2/rum?${intakeParameters}`)}`)\n        ).toBe(true)\n        expect(\n          isIntakeUrl(\n            `https://www.proxy.com/custom/path?ddforward=${encodeURIComponent(`/api/v2/rum?${intakeParameters}`)}`\n          )\n        ).toBe(true)\n      })\n\n      it('should not detect request done on the same host as the proxy', () => {\n        expect(isIntakeUrl('https://www.proxy.com/foo')).toBe(false)\n      })\n    })\n    ;[\n      { site: 'datadoghq.eu' },\n      { site: 'us3.datadoghq.com' },\n      { site: 'us5.datadoghq.com' },\n      { site: 'ap1.datadoghq.com' },\n    ].forEach(({ site }) => {\n      it(`should detect replica intake request for site ${site}`, () => {\n        expect(isIntakeUrl(`https://${internalAnalyticsSubdomain}.datadoghq.com/api/v2/rum?${intakeParameters}`)).toBe(\n          true\n        )\n        expect(isIntakeUrl(`https://${internalAnalyticsSubdomain}.datadoghq.com/api/v2/logs?${intakeParameters}`)).toBe(\n          true\n        )\n        expect(\n          isIntakeUrl(`https://${internalAnalyticsSubdomain}.datadoghq.com/api/v2/replay?${intakeParameters}`)\n        ).toBe(true)\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/configuration/transportConfiguration.ts",
    "content": "import type { Site } from '../intakeSites'\nimport { INTAKE_SITE_US1, INTAKE_URL_PARAMETERS } from '../intakeSites'\nimport type { InitConfiguration } from './configuration'\nimport type { EndpointBuilder } from './endpointBuilder'\nimport { createEndpointBuilder } from './endpointBuilder'\n\nexport interface TransportConfiguration {\n  logsEndpointBuilder: EndpointBuilder\n  rumEndpointBuilder: EndpointBuilder\n  sessionReplayEndpointBuilder: EndpointBuilder\n  profilingEndpointBuilder: EndpointBuilder\n  exposuresEndpointBuilder: EndpointBuilder\n  flagEvaluationEndpointBuilder: EndpointBuilder\n  datacenter?: string | undefined\n  replica?: ReplicaConfiguration\n  site: Site\n  source: 'browser' | 'flutter' | 'unity'\n}\n\nexport interface ReplicaConfiguration {\n  logsEndpointBuilder: EndpointBuilder\n  rumEndpointBuilder: EndpointBuilder\n}\n\nexport function computeTransportConfiguration(initConfiguration: InitConfiguration): TransportConfiguration {\n  const site = initConfiguration.site || INTAKE_SITE_US1\n  const source = validateSource(initConfiguration.source)\n\n  const endpointBuilders = computeEndpointBuilders({ ...initConfiguration, site, source })\n  const replicaConfiguration = computeReplicaConfiguration({ ...initConfiguration, site, source })\n\n  return {\n    replica: replicaConfiguration,\n    site,\n    source,\n    ...endpointBuilders,\n  }\n}\n\nfunction validateSource(source: string | undefined) {\n  if (source === 'flutter' || source === 'unity') {\n    return source\n  }\n  return 'browser'\n}\n\nfunction computeEndpointBuilders(initConfiguration: InitConfiguration) {\n  return {\n    logsEndpointBuilder: createEndpointBuilder(initConfiguration, 'logs'),\n    rumEndpointBuilder: createEndpointBuilder(initConfiguration, 'rum'),\n    profilingEndpointBuilder: createEndpointBuilder(initConfiguration, 'profile'),\n    sessionReplayEndpointBuilder: createEndpointBuilder(initConfiguration, 'replay'),\n    exposuresEndpointBuilder: createEndpointBuilder(initConfiguration, 'exposures'),\n    flagEvaluationEndpointBuilder: createEndpointBuilder(initConfiguration, 'flagevaluation'),\n  }\n}\n\nfunction computeReplicaConfiguration(initConfiguration: InitConfiguration): ReplicaConfiguration | undefined {\n  if (!initConfiguration.replica) {\n    return\n  }\n\n  const replicaConfiguration: InitConfiguration = {\n    ...initConfiguration,\n    site: INTAKE_SITE_US1,\n    clientToken: initConfiguration.replica.clientToken,\n  }\n\n  return {\n    logsEndpointBuilder: createEndpointBuilder(replicaConfiguration, 'logs'),\n    rumEndpointBuilder: createEndpointBuilder(replicaConfiguration, 'rum', [\n      `application.id=${initConfiguration.replica.applicationId}`,\n    ]),\n  }\n}\n\nexport function isIntakeUrl(url: string): boolean {\n  // check if tags is present in the query string\n  return INTAKE_URL_PARAMETERS.every((param) => url.includes(param))\n}\n"
  },
  {
    "path": "packages/core/src/domain/connectivity/connectivity.spec.ts",
    "content": "import { setNavigatorOnLine, setNavigatorConnection } from '../../../test'\nimport { getConnectivity } from './connectivity'\n\ndescribe('connectivity', () => {\n  describe('status', () => {\n    it('should return `connected` when navigator.onLine is true', () => {\n      setNavigatorOnLine(true)\n      expect(getConnectivity().status).toEqual('connected')\n    })\n\n    it('should return `not_connected` when navigator.onLine is false', () => {\n      setNavigatorOnLine(false)\n      expect(getConnectivity().status).toEqual('not_connected')\n    })\n  })\n\n  describe('interfaces', () => {\n    it('should not be defined if navigator.connection is not available', () => {\n      setNavigatorConnection(undefined)\n      expect(getConnectivity().interfaces).toBeUndefined()\n    })\n\n    it('should not be defined if navigator.connection.type is not available', () => {\n      setNavigatorConnection({})\n      expect(getConnectivity().interfaces).toBeUndefined()\n    })\n\n    it('should return navigator.connection.type value', () => {\n      setNavigatorConnection({ type: 'bluetooth' })\n      expect(getConnectivity().interfaces).toEqual(['bluetooth'])\n    })\n  })\n\n  describe('effective_type', () => {\n    it('should not be defined if navigator.connection is not available', () => {\n      setNavigatorConnection(undefined)\n      expect(getConnectivity().effective_type).toBeUndefined()\n    })\n\n    it('should not be defined if navigator.connection.effective_type is not available', () => {\n      setNavigatorConnection({})\n      expect(getConnectivity().effective_type).toBeUndefined()\n    })\n\n    it('should return navigator.connection.effective_type value', () => {\n      setNavigatorConnection({ effectiveType: '4g' })\n      expect(getConnectivity().effective_type).toBe('4g')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/connectivity/connectivity.ts",
    "content": "import { globalObject } from '../../tools/globalObject'\n\nexport type NetworkInterface = 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi' | 'wimax' | 'other' | 'unknown'\nexport type EffectiveType = 'slow-2g' | '2g' | '3g' | '4g'\n\ninterface BrowserNavigator extends Navigator {\n  connection?: NetworkInformation\n}\n\nexport interface NetworkInformation {\n  type?: NetworkInterface\n  effectiveType?: EffectiveType\n  saveData: boolean\n}\n\nexport interface Connectivity {\n  status: 'connected' | 'not_connected'\n  interfaces?: NetworkInterface[]\n  effective_type?: EffectiveType\n  [key: string]: unknown\n}\n\nexport function getConnectivity(): Connectivity {\n  const navigator = globalObject.navigator as BrowserNavigator\n\n  return {\n    status: navigator.onLine ? 'connected' : 'not_connected',\n    interfaces: navigator.connection && navigator.connection.type ? [navigator.connection.type] : undefined,\n    effective_type: navigator.connection?.effectiveType,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/connectivity/index.ts",
    "content": "export * from './connectivity'\n"
  },
  {
    "path": "packages/core/src/domain/console/consoleObservable.spec.ts",
    "content": "/* eslint-disable no-console */\nimport { ignoreConsoleLogs } from '../../../test'\nimport { ConsoleApiName } from '../../tools/display'\nimport type { Subscription } from '../../tools/observable'\nimport type { ErrorConsoleLog } from './consoleObservable'\nimport { initConsoleObservable } from './consoleObservable'\n\n// prettier: avoid formatting issue\n// cf https://github.com/prettier/prettier/issues/12211\n;[\n  { api: ConsoleApiName.log },\n  { api: ConsoleApiName.info },\n  { api: ConsoleApiName.warn },\n  { api: ConsoleApiName.debug },\n  { api: ConsoleApiName.error },\n].forEach(({ api }) => {\n  describe(`console ${api} observable`, () => {\n    let consoleSpy: jasmine.Spy\n    let consoleSubscription: Subscription\n    let notifyLog: jasmine.Spy\n\n    beforeEach(() => {\n      consoleSpy = spyOn(console, api)\n      notifyLog = jasmine.createSpy('notifyLog')\n\n      consoleSubscription = initConsoleObservable([api]).subscribe(notifyLog)\n    })\n\n    afterEach(() => {\n      consoleSubscription.unsubscribe()\n    })\n\n    it(`should notify ${api}`, () => {\n      console[api]('foo', 'bar')\n\n      const consoleLog = notifyLog.calls.mostRecent().args[0]\n\n      expect(consoleLog).toEqual(\n        jasmine.objectContaining({\n          message: 'foo bar',\n          api,\n        })\n      )\n    })\n\n    it('should keep original behavior', () => {\n      console[api]('foo', 'bar')\n\n      expect(consoleSpy).toHaveBeenCalledWith('foo', 'bar')\n    })\n\n    it('should format error instance', () => {\n      console[api](new TypeError('hello'))\n      const consoleLog = notifyLog.calls.mostRecent().args[0]\n      expect(consoleLog.message).toBe('TypeError: hello')\n    })\n\n    it('should stringify object parameters', () => {\n      console[api]('Hello', { foo: 'bar' })\n      const consoleLog = notifyLog.calls.mostRecent().args[0]\n      expect(consoleLog.message).toBe('Hello {\\n  \"foo\": \"bar\"\\n}')\n    })\n\n    it('should allow multiple callers', () => {\n      const notifyOtherCaller = jasmine.createSpy('notifyOtherCaller')\n      const instrumentedConsoleApi = console[api]\n      const otherConsoleSubscription = initConsoleObservable([api]).subscribe(notifyOtherCaller)\n\n      console[api]('foo', 'bar')\n\n      expect(instrumentedConsoleApi).toEqual(console[api])\n      expect(notifyLog).toHaveBeenCalledTimes(1)\n      expect(notifyOtherCaller).toHaveBeenCalledTimes(1)\n\n      otherConsoleSubscription.unsubscribe()\n    })\n  })\n})\n\ndescribe('console error observable', () => {\n  let consoleSubscription: Subscription\n  let notifyLog: jasmine.Spy<(consoleLog: ErrorConsoleLog) => void>\n\n  beforeEach(() => {\n    ignoreConsoleLogs('error', 'Error: foo')\n    ignoreConsoleLogs('error', 'foo bar')\n    notifyLog = jasmine.createSpy('notifyLog')\n\n    consoleSubscription = initConsoleObservable([ConsoleApiName.error]).subscribe(notifyLog)\n  })\n\n  afterEach(() => {\n    consoleSubscription.unsubscribe()\n  })\n\n  it('should generate a handling stack', () => {\n    function triggerError() {\n      console.error('foo', 'bar')\n    }\n    triggerError()\n    const consoleLog = notifyLog.calls.mostRecent().args[0]\n    expect(consoleLog.handlingStack).toMatch(/^HandlingStack: console error\\s+at triggerError (.|\\n)*$/)\n  })\n\n  it('should extract stack from first error', () => {\n    console.error(new TypeError('foo'), new TypeError('bar'))\n    const stack = notifyLog.calls.mostRecent().args[0].error.stack\n    expect(stack).toContain('TypeError: foo')\n  })\n\n  it('should retrieve fingerprint from error', () => {\n    interface DatadogError extends Error {\n      dd_fingerprint?: string\n    }\n    const error = new Error('foo')\n    ;(error as DatadogError).dd_fingerprint = 'my-fingerprint'\n\n    console.error(error)\n\n    const consoleLog = notifyLog.calls.mostRecent().args[0]\n    expect(consoleLog.error.fingerprint).toBe('my-fingerprint')\n  })\n\n  it('should sanitize error fingerprint', () => {\n    const error = new Error('foo')\n    ;(error as any).dd_fingerprint = 2\n\n    console.error(error)\n\n    const consoleLog = notifyLog.calls.mostRecent().args[0]\n    expect(consoleLog.error.fingerprint).toBe('2')\n  })\n\n  it('should retrieve context from error', () => {\n    interface DatadogError extends Error {\n      dd_context?: Record<string, unknown>\n    }\n    const error = new Error('foo')\n    ;(error as DatadogError).dd_context = { foo: 'bar' }\n    console.error(error)\n    const consoleLog = notifyLog.calls.mostRecent().args[0]\n    expect(consoleLog.error.context).toEqual({ foo: 'bar' })\n  })\n\n  it('should report original error', () => {\n    const error = new Error('foo')\n    console.error(error)\n    const consoleLog = notifyLog.calls.mostRecent().args[0]\n    expect(consoleLog.error.originalError).toBe(error)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/console/consoleObservable.ts",
    "content": "import { isError, computeRawError } from '../error/error'\nimport { mergeObservables, Observable } from '../../tools/observable'\nimport { ConsoleApiName, globalConsole } from '../../tools/display'\nimport { callMonitored } from '../../tools/monitor'\nimport { sanitize } from '../../tools/serialisation/sanitize'\nimport { jsonStringify } from '../../tools/serialisation/jsonStringify'\nimport type { RawError } from '../error/error.types'\nimport { ErrorHandling, ErrorSource, NonErrorPrefix } from '../error/error.types'\nimport { computeStackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { createHandlingStack, formatErrorMessage } from '../../tools/stackTrace/handlingStack'\nimport { clocksNow } from '../../tools/utils/timeUtils'\n\nexport type ConsoleLog = NonErrorConsoleLog | ErrorConsoleLog\n\ninterface NonErrorConsoleLog extends ConsoleLogBase {\n  api: Exclude<ConsoleApiName, typeof ConsoleApiName.error>\n  error: undefined\n}\n\nexport interface ErrorConsoleLog extends ConsoleLogBase {\n  api: typeof ConsoleApiName.error\n  error: RawError\n}\n\ninterface ConsoleLogBase {\n  message: string\n  api: ConsoleApiName\n  handlingStack: string\n}\n\ntype ConsoleLogForApi<T extends ConsoleApiName> = T extends typeof ConsoleApiName.error\n  ? ErrorConsoleLog\n  : NonErrorConsoleLog\n\nlet consoleObservablesByApi: { [K in ConsoleApiName]?: Observable<ConsoleLogForApi<K>> } = {}\n\nexport function initConsoleObservable<T extends ConsoleApiName[]>(apis: T): Observable<ConsoleLogForApi<T[number]>> {\n  const consoleObservables = apis.map((api) => {\n    if (!consoleObservablesByApi[api]) {\n      consoleObservablesByApi[api] = createConsoleObservable(api) as any // we are sure that the observable created for this api will yield the expected ConsoleLog type\n    }\n    return consoleObservablesByApi[api] as unknown as Observable<ConsoleLogForApi<T[number]>>\n  })\n\n  return mergeObservables(...consoleObservables)\n}\n\nexport function resetConsoleObservable() {\n  consoleObservablesByApi = {}\n}\n\nfunction createConsoleObservable(api: ConsoleApiName) {\n  return new Observable<ConsoleLog>((observable) => {\n    const originalConsoleApi = globalConsole[api]\n\n    globalConsole[api] = (...params: unknown[]) => {\n      originalConsoleApi.apply(console, params)\n      const handlingStack = createHandlingStack('console error')\n\n      callMonitored(() => {\n        observable.notify(buildConsoleLog(params, api, handlingStack))\n      })\n    }\n\n    return () => {\n      globalConsole[api] = originalConsoleApi\n    }\n  })\n}\n\nfunction buildConsoleLog(params: unknown[], api: ConsoleApiName, handlingStack: string): ConsoleLog {\n  const message = params.map((param) => formatConsoleParameters(param)).join(' ')\n\n  if (api === ConsoleApiName.error) {\n    const firstErrorParam = params.find(isError)\n\n    const rawError = computeRawError({\n      originalError: firstErrorParam,\n      handlingStack,\n      startClocks: clocksNow(),\n      source: ErrorSource.CONSOLE,\n      handling: ErrorHandling.HANDLED,\n      nonErrorPrefix: NonErrorPrefix.PROVIDED,\n\n      // if no good stack is computed from the error, let's not use the fallback stack message\n      // advising the user to use an instance of Error, as console.error is commonly used without an\n      // Error instance.\n      useFallbackStack: false,\n    })\n\n    // Use the full log message as the error message instead of just the error instance message.\n    rawError.message = message\n\n    return {\n      api,\n      message,\n      handlingStack,\n      error: rawError,\n    }\n  }\n\n  return {\n    api,\n    message,\n    error: undefined,\n    handlingStack,\n  }\n}\n\nfunction formatConsoleParameters(param: unknown) {\n  if (typeof param === 'string') {\n    return sanitize(param)\n  }\n  if (isError(param)) {\n    return formatErrorMessage(computeStackTrace(param))\n  }\n  return jsonStringify(sanitize(param), undefined, 2)\n}\n"
  },
  {
    "path": "packages/core/src/domain/context/contextConstants.ts",
    "content": "export const enum CustomerDataType {\n  FeatureFlag,\n  User,\n  GlobalContext,\n  View,\n  Account,\n}\n\n// Use a const instead of const enum to avoid inlining the enum values in the bundle and save bytes\nexport const CustomerContextKey = {\n  userContext: 'userContext',\n  globalContext: 'globalContext',\n  accountContext: 'accountContext',\n} as const\n\nexport type CustomerContextKey = (typeof CustomerContextKey)[keyof typeof CustomerContextKey]\n\n// Use a const instead of const enum to avoid inlining the enum values in the bundle and save bytes\nexport const ContextManagerMethod = {\n  getContext: 'getContext',\n  setContext: 'setContext',\n  setContextProperty: 'setContextProperty',\n  removeContextProperty: 'removeContextProperty',\n  clearContext: 'clearContext',\n} as const\n\nexport type ContextManagerMethod = (typeof ContextManagerMethod)[keyof typeof ContextManagerMethod]\n"
  },
  {
    "path": "packages/core/src/domain/context/contextManager.spec.ts",
    "content": "import { display } from '../../tools/display'\nimport type { PropertiesConfig } from './contextManager'\nimport { createContextManager } from './contextManager'\n\nfunction createContextManagerWithDefaults(propertiesConfig?: PropertiesConfig) {\n  return createContextManager('test', { propertiesConfig })\n}\n\ndescribe('createContextManager', () => {\n  it('starts with an empty context', () => {\n    const manager = createContextManagerWithDefaults()\n    expect(manager.getContext()).toEqual({})\n  })\n\n  it('updates the context', () => {\n    const manager = createContextManagerWithDefaults()\n    manager.setContext({ bar: 'foo' })\n\n    expect(manager.getContext()).toEqual({ bar: 'foo' })\n  })\n\n  it('completely replaces the context', () => {\n    const manager = createContextManagerWithDefaults()\n    manager.setContext({ a: 'foo' })\n    expect(manager.getContext()).toEqual({ a: 'foo' })\n    manager.setContext({ b: 'foo' })\n    expect(manager.getContext()).toEqual({ b: 'foo' })\n  })\n\n  it('sets a context value', () => {\n    const manager = createContextManagerWithDefaults()\n    manager.setContextProperty('foo', 'bar')\n    expect(manager.getContext()).toEqual({ foo: 'bar' })\n  })\n\n  it('removes a context value', () => {\n    const manager = createContextManagerWithDefaults()\n    manager.setContext({ a: 'foo', b: 'bar' })\n    manager.removeContextProperty('a')\n    expect(manager.getContext()).toEqual({ b: 'bar' })\n    manager.removeContextProperty('b')\n    expect(manager.getContext()).toEqual({})\n  })\n\n  it('should get a clone of the context from getContext', () => {\n    const manager = createContextManagerWithDefaults()\n    expect(manager.getContext()).toEqual(manager.getContext())\n    expect(manager.getContext()).not.toBe(manager.getContext())\n  })\n\n  it('should set a clone of context via setContext', () => {\n    const nestedObject = { foo: 'bar' }\n    const context = { nested: nestedObject }\n    const manager = createContextManagerWithDefaults()\n    manager.setContext(context)\n    expect(manager.getContext().nested).toEqual(nestedObject)\n    expect(manager.getContext().nested).not.toBe(nestedObject)\n  })\n\n  it('should set a clone of the property via setContextProperty', () => {\n    const nestedObject = { foo: 'bar' }\n    const manager = createContextManagerWithDefaults()\n    manager.setContextProperty('nested', nestedObject)\n    expect(manager.getContext().nested).toEqual(nestedObject)\n    expect(manager.getContext().nested).not.toBe(nestedObject)\n  })\n\n  it('should clear context object via clearContext', () => {\n    const context = { foo: 'bar' }\n    const manager = createContextManagerWithDefaults()\n    manager.setContext(context)\n    expect(manager.getContext()).toEqual(context)\n    manager.clearContext()\n    expect(manager.getContext()).toEqual({})\n  })\n\n  it('should prevent setting non object values', () => {\n    spyOn(display, 'error')\n    const manager = createContextManagerWithDefaults()\n    manager.setContext(null as any)\n    expect(manager.getContext()).toEqual({})\n    manager.setContext(undefined as any)\n    expect(manager.getContext()).toEqual({})\n    manager.setContext(2 as any)\n    expect(manager.getContext()).toEqual({})\n  })\n\n  describe('type enforcement', () => {\n    const NULLISH_VALUES = [undefined, null, '']\n\n    it('should enforce specified type on properties', () => {\n      const manager = createContextManagerWithDefaults({\n        id: { type: 'string' },\n        name: { type: 'string' },\n        email: { type: 'string' },\n      })\n\n      manager.setContext({ id: 42, name: true, email: {} })\n\n      expect(manager.getContext()).toEqual({ id: '42', name: 'true', email: '[object Object]' })\n    })\n\n    it('should not enforce specified type on null or undefined properties', () => {\n      const manager = createContextManagerWithDefaults({\n        id: { type: 'string' },\n        name: { type: 'string' },\n      })\n\n      manager.setContext({ id: undefined, name: null })\n      expect(manager.getContext()).toEqual({ id: undefined, name: null })\n    })\n\n    NULLISH_VALUES.forEach((value) => {\n      it(`should warn when required property is  ${value}`, () => {\n        const displaySpy = spyOn(display, 'warn')\n\n        const manager = createContextManagerWithDefaults({\n          id: { required: true },\n        })\n\n        manager.setContext({ id: value })\n\n        expect(displaySpy).toHaveBeenCalledOnceWith(\n          'The property id of test is required; context will not be sent to the intake.'\n        )\n      })\n    })\n  })\n\n  describe('changeObservable', () => {\n    it('should notify on context changes', () => {\n      const changeSpy = jasmine.createSpy('change')\n      const manager = createContextManagerWithDefaults()\n      manager.changeObservable.subscribe(changeSpy)\n\n      manager.getContext()\n      expect(changeSpy).not.toHaveBeenCalled()\n\n      manager.setContext({ foo: 'bar' })\n      expect(changeSpy).toHaveBeenCalledTimes(1)\n\n      manager.setContextProperty('qux', 'qix')\n      expect(changeSpy).toHaveBeenCalledTimes(2)\n\n      manager.removeContextProperty('qux')\n      expect(changeSpy).toHaveBeenCalledTimes(3)\n\n      manager.clearContext()\n      expect(changeSpy).toHaveBeenCalledTimes(4)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/context/contextManager.ts",
    "content": "import { deepClone } from '../../tools/mergeInto'\nimport { sanitize } from '../../tools/serialisation/sanitize'\nimport type { Context } from '../../tools/serialisation/context'\nimport { Observable } from '../../tools/observable'\nimport { display } from '../../tools/display'\nimport { checkContext } from './contextUtils'\n\nexport type ContextManager = ReturnType<typeof createContextManager>\n\nexport interface PropertiesConfig {\n  [key: string]: {\n    required?: boolean\n    type?: 'string'\n  }\n}\n\nfunction ensureProperties(context: Context, propertiesConfig: PropertiesConfig, name: string) {\n  const newContext = { ...context }\n\n  for (const [key, { required, type }] of Object.entries(propertiesConfig)) {\n    /**\n     * Ensure specified properties are strings as defined here:\n     * https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#user-related-attributes\n     */\n\n    if (type === 'string' && !isDefined(newContext[key])) {\n      /* eslint-disable @typescript-eslint/no-base-to-string */\n      newContext[key] = String(newContext[key])\n    }\n\n    if (required && isDefined(newContext[key])) {\n      display.warn(`The property ${key} of ${name} is required; context will not be sent to the intake.`)\n    }\n  }\n\n  return newContext\n}\n\nfunction isDefined(value: unknown) {\n  return value === undefined || value === null || value === ''\n}\n\nexport function createContextManager(\n  name: string = '',\n  {\n    propertiesConfig = {},\n  }: {\n    propertiesConfig?: PropertiesConfig\n  } = {}\n) {\n  let context: Context = {}\n  const changeObservable = new Observable<void>()\n\n  const contextManager = {\n    getContext: () => deepClone(context),\n\n    setContext: (newContext: unknown) => {\n      if (checkContext(newContext)) {\n        context = sanitize(ensureProperties(newContext, propertiesConfig, name))\n      } else {\n        contextManager.clearContext()\n      }\n      changeObservable.notify()\n    },\n\n    setContextProperty: (key: string, property: any) => {\n      context = sanitize(ensureProperties({ ...context, [key]: property }, propertiesConfig, name))\n      changeObservable.notify()\n    },\n\n    removeContextProperty: (key: string) => {\n      delete context[key]\n      ensureProperties(context, propertiesConfig, name)\n      changeObservable.notify()\n    },\n\n    clearContext: () => {\n      context = {}\n      changeObservable.notify()\n    },\n\n    changeObservable,\n  }\n  return contextManager\n}\n"
  },
  {
    "path": "packages/core/src/domain/context/contextUtils.spec.ts",
    "content": "import { display } from '../../tools/display'\nimport type { Context } from '../../tools/serialisation/context'\nimport type { Account } from '../contexts/accountContext'\nimport type { User } from '../contexts/userContext'\nimport { checkContext } from './contextUtils'\n\ndescribe('checkContext function', () => {\n  it('should only accept valid objects', () => {\n    spyOn(display, 'error')\n\n    const obj: any = { id: 42, name: true, email: null } // Valid, even though not sanitized\n    const user: User = { id: '42', name: 'John', email: 'john@doe.com' }\n    const account: Account = { id: '42', name: 'Groupe' }\n    const undefUser: any = undefined\n    const nullUser: any = null\n    const invalidUser: any = 42\n\n    expect(checkContext(obj)).toBe(true)\n    expect(checkContext(user as Context)).toBe(true)\n    expect(checkContext(account as Context)).toBe(true)\n    expect(checkContext(undefUser)).toBe(false)\n    expect(checkContext(nullUser)).toBe(false)\n    expect(checkContext(invalidUser)).toBe(false)\n    expect(display.error).toHaveBeenCalledTimes(3)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/context/contextUtils.ts",
    "content": "import type { Context } from '../../tools/serialisation/context'\nimport { display } from '../../tools/display'\nimport { getType } from '../../tools/utils/typeUtils'\n\n/**\n * Simple check to ensure an object is a valid context\n */\nexport function checkContext(maybeContext: unknown): maybeContext is Context {\n  const isValid = getType(maybeContext) === 'object'\n  if (!isValid) {\n    display.error('Unsupported context:', maybeContext)\n  }\n  return isValid\n}\n"
  },
  {
    "path": "packages/core/src/domain/context/defineContextMethod.ts",
    "content": "import type { RawTelemetryUsage, RawTelemetryUsageFeature } from '../telemetry'\nimport { addTelemetryUsage } from '../telemetry'\nimport { monitor } from '../../tools/monitor'\nimport type { BoundedBuffer } from '../../tools/boundedBuffer'\nimport type { ContextManager } from './contextManager'\nimport type { ContextManagerMethod, CustomerContextKey } from './contextConstants'\n\nexport function defineContextMethod<MethodName extends ContextManagerMethod, Key extends CustomerContextKey>(\n  getStrategy: () => Record<Key, ContextManager>,\n  contextName: Key,\n  methodName: MethodName,\n  usage?: RawTelemetryUsageFeature\n): ContextManager[MethodName] {\n  return monitor((...args: any[]) => {\n    if (usage) {\n      addTelemetryUsage({ feature: usage } as RawTelemetryUsage)\n    }\n    return (getStrategy()[contextName][methodName] as (...args: unknown[]) => unknown)(...args)\n  }) as ContextManager[MethodName]\n}\n\nexport function bufferContextCalls<Key extends string, StartResult extends Record<Key, ContextManager>>(\n  preStartContextManager: ContextManager,\n  name: Key,\n  bufferApiCalls: BoundedBuffer<StartResult>\n) {\n  preStartContextManager.changeObservable.subscribe(() => {\n    const context = preStartContextManager.getContext()\n    bufferApiCalls.add((startResult) => startResult[name].setContext(context))\n  })\n}\n"
  },
  {
    "path": "packages/core/src/domain/context/storeContextManager.spec.ts",
    "content": "import type { Configuration } from '../configuration'\nimport { createNewEvent } from '../../../test'\nimport { DOM_EVENT } from '../../browser/addEventListener'\nimport type { Context } from '../../tools/serialisation/context'\nimport { storeContextManager, buildStorageKey, removeStorageListeners } from './storeContextManager'\nimport { CustomerDataType } from './contextConstants'\nimport { createContextManager } from './contextManager'\n\ndescribe('storeContextManager', () => {\n  const PRODUCT_KEY = 'fake'\n  const CUSTOMER_DATA_TYPE = CustomerDataType.User\n  const STORAGE_KEY = buildStorageKey(PRODUCT_KEY, CUSTOMER_DATA_TYPE)\n\n  let configuration: Configuration\n\n  beforeEach(() => {\n    configuration = {} as Configuration\n  })\n\n  afterEach(() => {\n    localStorage.clear()\n    removeStorageListeners()\n  })\n\n  it('should synchronize with local storage at start', () => {\n    localStorage.setItem(STORAGE_KEY, '{\"bar\":\"foo\"}')\n\n    const manager = createStoredContextManager()\n\n    expect(manager.getContext()).toEqual({ bar: 'foo' })\n  })\n\n  it('should synchronize with local storage on storage events', () => {\n    const manager = createStoredContextManager()\n\n    localStorage.setItem(STORAGE_KEY, '{\"bar\":\"foo\"}')\n    expect(manager.getContext()).toEqual({})\n\n    window.dispatchEvent(createNewEvent(DOM_EVENT.STORAGE, { key: 'unknown' }))\n    expect(manager.getContext()).toEqual({})\n\n    window.dispatchEvent(createNewEvent(DOM_EVENT.STORAGE, { key: STORAGE_KEY }))\n    expect(manager.getContext()).toEqual({ bar: 'foo' })\n  })\n\n  it('should update local storage on context updates', () => {\n    const manager = createStoredContextManager()\n    expect(localStorage.getItem(STORAGE_KEY)).toBe(null)\n\n    manager.setContext({ bar: 'foo' })\n    expect(localStorage.getItem(STORAGE_KEY)).toBe('{\"bar\":\"foo\"}')\n\n    manager.setContextProperty('qux', 'qix')\n    expect(localStorage.getItem(STORAGE_KEY)).toBe('{\"bar\":\"foo\",\"qux\":\"qix\"}')\n\n    manager.removeContextProperty('qux')\n    expect(localStorage.getItem(STORAGE_KEY)).toBe('{\"bar\":\"foo\"}')\n\n    manager.clearContext()\n    expect(localStorage.getItem(STORAGE_KEY)).toBe('{}')\n  })\n\n  it('merges local storage data with initial context', () => {\n    localStorage.setItem(STORAGE_KEY, '{\"bar\":\"foo\"}')\n    const manager = createStoredContextManager({ initialContext: { qux: 'qix' } })\n\n    expect(manager.getContext()).toEqual({ bar: 'foo', qux: 'qix' })\n    expect(localStorage.getItem(STORAGE_KEY)).toBe('{\"bar\":\"foo\",\"qux\":\"qix\"}')\n  })\n\n  it('should store different product data in different storage key', () => {\n    createStoredContextManager({ initialContext: { bar: 'foo' }, productKey: 'p1' })\n    createStoredContextManager({ initialContext: { qux: 'qix' }, productKey: 'p2' })\n\n    expect(localStorage.getItem(buildStorageKey('p1', CUSTOMER_DATA_TYPE))).toBe('{\"bar\":\"foo\"}')\n    expect(localStorage.getItem(buildStorageKey('p2', CUSTOMER_DATA_TYPE))).toBe('{\"qux\":\"qix\"}')\n  })\n\n  it('should store different data type in different storage key', () => {\n    createStoredContextManager({ initialContext: { bar: 'foo' }, customerDataType: CustomerDataType.User })\n    createStoredContextManager({ initialContext: { qux: 'qix' }, customerDataType: CustomerDataType.GlobalContext })\n\n    expect(localStorage.getItem(buildStorageKey(PRODUCT_KEY, CustomerDataType.User))).toBe('{\"bar\":\"foo\"}')\n    expect(localStorage.getItem(buildStorageKey(PRODUCT_KEY, CustomerDataType.GlobalContext))).toBe('{\"qux\":\"qix\"}')\n  })\n\n  function createStoredContextManager({\n    initialContext,\n    productKey = PRODUCT_KEY,\n    customerDataType = CUSTOMER_DATA_TYPE,\n  }: {\n    initialContext?: Context\n    productKey?: string\n    customerDataType?: CustomerDataType\n  } = {}) {\n    const manager = createContextManager('test')\n    if (initialContext) {\n      manager.setContext(initialContext)\n    }\n    storeContextManager(configuration, manager, productKey, customerDataType)\n    return manager\n  }\n})\n"
  },
  {
    "path": "packages/core/src/domain/context/storeContextManager.ts",
    "content": "import { addEventListener, DOM_EVENT } from '../../browser/addEventListener'\nimport type { Context } from '../../tools/serialisation/context'\nimport type { Configuration } from '../configuration'\nimport { combine } from '../../tools/mergeInto'\nimport { isEmptyObject } from '../../tools/utils/objectUtils'\nimport type { ContextManager } from './contextManager'\nimport type { CustomerDataType } from './contextConstants'\n\nconst CONTEXT_STORE_KEY_PREFIX = '_dd_c'\n\nconst storageListeners: Array<{ stop: () => void }> = []\n\nexport function storeContextManager(\n  configuration: Configuration,\n  contextManager: ContextManager,\n  productKey: string,\n  customerDataType: CustomerDataType\n) {\n  const storageKey = buildStorageKey(productKey, customerDataType)\n\n  storageListeners.push(\n    addEventListener(configuration, window, DOM_EVENT.STORAGE, ({ key }) => {\n      if (storageKey === key) {\n        synchronizeWithStorage()\n      }\n    })\n  )\n  contextManager.changeObservable.subscribe(dumpToStorage)\n\n  const contextFromStorage = combine(getFromStorage(), contextManager.getContext())\n  if (!isEmptyObject(contextFromStorage)) {\n    contextManager.setContext(contextFromStorage)\n  }\n\n  function synchronizeWithStorage() {\n    contextManager.setContext(getFromStorage())\n  }\n\n  function dumpToStorage() {\n    localStorage.setItem(storageKey, JSON.stringify(contextManager.getContext()))\n  }\n\n  function getFromStorage() {\n    const rawContext = localStorage.getItem(storageKey)\n    return rawContext ? (JSON.parse(rawContext) as Context) : {}\n  }\n}\n\nexport function buildStorageKey(productKey: string, customerDataType: CustomerDataType) {\n  return `${CONTEXT_STORE_KEY_PREFIX}_${productKey}_${customerDataType}`\n}\n\nexport function removeStorageListeners() {\n  storageListeners.map((listener) => listener.stop())\n}\n"
  },
  {
    "path": "packages/core/src/domain/contexts/accountContext.spec.ts",
    "content": "import type { Hooks } from '../../../test'\nimport { createHooks, registerCleanupTask } from '../../../test'\nimport { mockRumConfiguration } from '../../../../rum-core/test'\nimport type { ContextManager } from '../context/contextManager'\nimport { display } from '../../tools/display'\nimport type { RelativeTime } from '../../tools/utils/timeUtils'\nimport { HookNames } from '../../tools/abstractHooks'\nimport { removeStorageListeners } from '../context/storeContextManager'\nimport { startAccountContext } from './accountContext'\n\ndescribe('account context', () => {\n  let accountContext: ContextManager\n  let displaySpy: jasmine.Spy\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n    displaySpy = spyOn(display, 'warn')\n\n    accountContext = startAccountContext(hooks, mockRumConfiguration(), 'some_product_key')\n  })\n\n  it('should warn when the account.id is missing', () => {\n    accountContext.setContext({ foo: 'bar' })\n    expect(displaySpy).toHaveBeenCalled()\n  })\n\n  it('should sanitize predefined properties', () => {\n    accountContext.setContext({ id: false, name: 2 })\n    expect(accountContext.getContext()).toEqual({\n      id: 'false',\n      name: '2',\n    })\n  })\n\n  describe('assemble hook', () => {\n    it('should set the account', () => {\n      accountContext.setContext({ id: '123', foo: 'bar' })\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        account: {\n          id: '123',\n          foo: 'bar',\n        },\n      })\n    })\n\n    it('should not set the account when account.id is undefined', () => {\n      accountContext.setContext({ foo: 'bar' })\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n  })\n})\n\ndescribe('account context across pages', () => {\n  let accountContext: ContextManager\n  let hooks: Hooks\n  beforeEach(() => {\n    hooks = createHooks()\n\n    registerCleanupTask(() => {\n      localStorage.clear()\n      removeStorageListeners()\n    })\n  })\n\n  it('when disabled, should store contexts only in memory', () => {\n    accountContext = startAccountContext(\n      hooks,\n      mockRumConfiguration({ storeContextsAcrossPages: false }),\n      'some_product_key'\n    )\n    accountContext.setContext({ id: '123' })\n\n    expect(accountContext.getContext()).toEqual({ id: '123' })\n    expect(localStorage.getItem('_dd_c_rum_4')).toBeNull()\n  })\n\n  it('when enabled, should maintain the account in local storage', () => {\n    accountContext = startAccountContext(\n      hooks,\n      mockRumConfiguration({ storeContextsAcrossPages: true }),\n      'some_product_key'\n    )\n\n    accountContext.setContext({ id: 'foo', qux: 'qix' })\n    expect(accountContext.getContext()).toEqual({ id: 'foo', qux: 'qix' })\n    expect(localStorage.getItem('_dd_c_some_product_key_4')).toBe('{\"id\":\"foo\",\"qux\":\"qix\"}')\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/contexts/accountContext.ts",
    "content": "import type { Configuration } from '../configuration'\nimport { CustomerDataType } from '../context/contextConstants'\nimport { storeContextManager } from '../context/storeContextManager'\nimport { HookNames, SKIPPED } from '../../tools/abstractHooks'\nimport type { AbstractHooks } from '../../tools/abstractHooks'\nimport { isEmptyObject } from '../../tools/utils/objectUtils'\nimport { createContextManager } from '../context/contextManager'\n\n/**\n * Account information for the browser SDK.\n */\nexport interface Account {\n  id: string\n  name?: string | undefined\n  [key: string]: unknown\n}\n\nexport function startAccountContext(hooks: AbstractHooks, configuration: Configuration, productKey: string) {\n  const accountContextManager = buildAccountContextManager()\n\n  if (configuration.storeContextsAcrossPages) {\n    storeContextManager(configuration, accountContextManager, productKey, CustomerDataType.Account)\n  }\n\n  hooks.register(HookNames.Assemble, () => {\n    const account = accountContextManager.getContext() as Account\n\n    if (isEmptyObject(account) || !account.id) {\n      return SKIPPED\n    }\n\n    return {\n      account,\n    }\n  })\n\n  return accountContextManager\n}\n\nexport function buildAccountContextManager() {\n  return createContextManager('account', {\n    propertiesConfig: {\n      id: { type: 'string', required: true },\n      name: { type: 'string' },\n    },\n  })\n}\n"
  },
  {
    "path": "packages/core/src/domain/contexts/globalContext.spec.ts",
    "content": "import type { Hooks } from '../../../test'\nimport type { LogsConfiguration } from '../../../../logs/src/domain/configuration'\nimport type { ContextManager } from '../context/contextManager'\nimport { HookNames } from '../../tools/abstractHooks'\nimport type { RelativeTime } from '../../tools/utils/timeUtils'\nimport { createHooks, registerCleanupTask } from '../../../test'\nimport { removeStorageListeners } from '../context/storeContextManager'\nimport type { Configuration } from '../configuration'\nimport { startGlobalContext } from './globalContext'\n\ndescribe('logs global context', () => {\n  let globalContext: ContextManager\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n  })\n\n  describe('assemble hook', () => {\n    it('should set the context in context in `context` namespace when specified', () => {\n      const contextNamespace = true\n      globalContext = startGlobalContext(hooks, {} as LogsConfiguration, 'some_product_key', contextNamespace)\n\n      globalContext.setContext({ id: '123', foo: 'bar' })\n      const event = hooks.triggerHook(HookNames.Assemble, { startTime: 0 as RelativeTime })\n\n      expect(event).toEqual({\n        context: {\n          id: '123',\n          foo: 'bar',\n        },\n      })\n    })\n\n    it('should set the context in root namespace when specified', () => {\n      const contextNamespace = false\n      globalContext = startGlobalContext(hooks, {} as LogsConfiguration, 'some_product_key', contextNamespace)\n\n      globalContext.setContext({ id: '123', foo: 'bar' })\n      const event = hooks.triggerHook(HookNames.Assemble, { startTime: 0 as RelativeTime })\n\n      expect(event).toEqual({\n        id: '123',\n        foo: 'bar',\n      })\n    })\n  })\n})\n\ndescribe('global context across pages', () => {\n  let globalContext: ContextManager\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n\n    registerCleanupTask(() => {\n      localStorage.clear()\n      removeStorageListeners()\n    })\n  })\n\n  it('when disabled, should store contexts only in memory', () => {\n    globalContext = startGlobalContext(\n      hooks,\n      { storeContextsAcrossPages: false } as Configuration,\n      'some_product_key',\n      false\n    )\n    globalContext.setContext({ id: '123' })\n\n    expect(globalContext.getContext()).toEqual({ id: '123' })\n    expect(localStorage.getItem('_dd_c_some_product_key_2')).toBeNull()\n  })\n\n  it('when enabled, should maintain the global context in local storage', () => {\n    globalContext = startGlobalContext(\n      hooks,\n      { storeContextsAcrossPages: true } as Configuration,\n      'some_product_key',\n      false\n    )\n\n    globalContext.setContext({ id: 'foo', qux: 'qix' })\n    expect(globalContext.getContext()).toEqual({ id: 'foo', qux: 'qix' })\n    expect(localStorage.getItem('_dd_c_some_product_key_2')).toBe('{\"id\":\"foo\",\"qux\":\"qix\"}')\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/contexts/globalContext.ts",
    "content": "import type { AbstractHooks } from '../../tools/abstractHooks'\nimport { CustomerDataType } from '../context/contextConstants'\nimport { storeContextManager } from '../context/storeContextManager'\nimport { HookNames } from '../../tools/abstractHooks'\nimport { createContextManager } from '../context/contextManager'\nimport type { Configuration } from '../configuration'\n\nexport function startGlobalContext(\n  hooks: AbstractHooks,\n  configuration: Configuration,\n  productKey: string,\n  useContextNamespace: boolean\n) {\n  const globalContextManager = buildGlobalContextManager()\n\n  if (configuration.storeContextsAcrossPages) {\n    storeContextManager(configuration, globalContextManager, productKey, CustomerDataType.GlobalContext)\n  }\n\n  hooks.register(HookNames.Assemble, () => {\n    const context = globalContextManager.getContext()\n    return useContextNamespace ? { context } : context\n  })\n\n  return globalContextManager\n}\n\nexport function buildGlobalContextManager() {\n  return createContextManager('global context')\n}\n"
  },
  {
    "path": "packages/core/src/domain/contexts/rumInternalContext.type.ts",
    "content": "import type { Context } from '../../tools/serialisation/context'\n\nexport interface RumInternalContext extends Context {\n  application_id: string\n  session_id: string | undefined\n  view?: {\n    id: string\n    url: string\n    referrer: string\n    name?: string\n  }\n  user_action?: {\n    id: string | string[]\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/contexts/tabContext.spec.ts",
    "content": "import type { Hooks } from '../../../test'\nimport { createHooks, registerCleanupTask } from '../../../test'\nimport { HookNames } from '../../tools/abstractHooks'\nimport type { RelativeTime } from '../../tools/utils/timeUtils'\nimport { TAB_ID_STORAGE_KEY, resetCachedTabId, startTabContext } from './tabContext'\n\nconst UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/\n\ndescribe('tabContext', () => {\n  let hooks: Hooks\n\n  beforeEach(() => {\n    resetCachedTabId()\n    hooks = createHooks()\n    registerCleanupTask(() => {\n      sessionStorage.removeItem(TAB_ID_STORAGE_KEY)\n      resetCachedTabId()\n    })\n  })\n\n  it('should return a tab ID via the assemble hook', () => {\n    startTabContext(hooks)\n\n    const event = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(event).toEqual(\n      jasmine.objectContaining({\n        tab: jasmine.objectContaining({\n          id: jasmine.stringMatching(UUID_PATTERN),\n        }),\n      })\n    )\n  })\n\n  it('should return a consistent tab ID across multiple hook triggers', () => {\n    startTabContext(hooks)\n\n    const event1 = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n    const event2 = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(event1.tab.id).toBe(event2.tab.id)\n  })\n\n  it('should persist the tab ID to sessionStorage', () => {\n    startTabContext(hooks)\n\n    const event = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(sessionStorage.getItem(TAB_ID_STORAGE_KEY)).toBe(event.tab.id)\n  })\n\n  it('should reuse an existing tab ID from sessionStorage', () => {\n    sessionStorage.setItem(TAB_ID_STORAGE_KEY, 'existing-tab-id')\n    startTabContext(hooks)\n\n    const event = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(event.tab.id).toBe('existing-tab-id')\n  })\n\n  it('should generate a tab ID when sessionStorage.getItem throws', () => {\n    spyOn(sessionStorage, 'getItem').and.throwError('SecurityError')\n    startTabContext(hooks)\n\n    const event = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(event.tab.id).toMatch(UUID_PATTERN)\n  })\n\n  it('should generate a tab ID when sessionStorage.setItem throws', () => {\n    spyOn(sessionStorage, 'getItem').and.returnValue(null)\n    spyOn(sessionStorage, 'setItem').and.throwError('QuotaExceededError')\n    startTabContext(hooks)\n\n    const event = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(event.tab.id).toMatch(UUID_PATTERN)\n  })\n\n  it('should return the same tab ID across multiple startTabContext calls when sessionStorage is unavailable', () => {\n    spyOn(sessionStorage, 'getItem').and.throwError('SecurityError')\n\n    const hooks1 = createHooks()\n    startTabContext(hooks1)\n    const hooks2 = createHooks()\n    startTabContext(hooks2)\n\n    const event1 = hooks1.triggerHook(HookNames.Assemble, { startTime: 0 as RelativeTime })\n    const event2 = hooks2.triggerHook(HookNames.Assemble, { startTime: 0 as RelativeTime })\n\n    expect(event1.tab.id).toBe(event2.tab.id)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/contexts/tabContext.ts",
    "content": "import { HookNames } from '../../tools/abstractHooks'\nimport type { AbstractHooks } from '../../tools/abstractHooks'\nimport { generateUUID } from '../../tools/utils/stringUtils'\n\nexport const TAB_ID_STORAGE_KEY = '_dd_tab_id'\n\nlet cachedTabId: string | undefined\n\n// Exported for test cleanup only — allows specs to reset the in-memory cache between tests.\nexport function resetCachedTabId(): void {\n  cachedTabId = undefined\n}\n\nexport function startTabContext(hooks: AbstractHooks) {\n  const tabId = retrieveOrCreateTabId()\n\n  hooks.register(HookNames.Assemble, () => ({\n    tab: {\n      id: tabId,\n    },\n  }))\n}\n\nfunction retrieveOrCreateTabId(): string {\n  if (!cachedTabId) {\n    cachedTabId = getOrCreateIdInSessionStorage() ?? generateUUID()\n  }\n  return cachedTabId\n}\n\nfunction getOrCreateIdInSessionStorage(): string | undefined {\n  try {\n    const existingId = sessionStorage.getItem(TAB_ID_STORAGE_KEY)\n    if (existingId) {\n      return existingId\n    }\n    const newId = generateUUID()\n    sessionStorage.setItem(TAB_ID_STORAGE_KEY, newId)\n    return newId\n  } catch {\n    // sessionStorage unavailable (e.g. Web Worker, sandboxed iframe, quota exceeded)\n    return undefined\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/contexts/userContext.spec.ts",
    "content": "import type { Hooks } from '../../../test'\nimport { createHooks, registerCleanupTask } from '../../../test'\nimport { mockRumConfiguration } from '../../../../rum-core/test'\nimport type { ContextManager } from '../context/contextManager'\nimport type { RelativeTime } from '../../tools/utils/timeUtils'\nimport { HookNames } from '../../tools/abstractHooks'\nimport { removeStorageListeners } from '../context/storeContextManager'\nimport type { Configuration } from '../configuration'\nimport type { SessionContext } from '../session/sessionManager'\nimport { startUserContext } from './userContext'\n\ndescribe('user context', () => {\n  let userContext: ContextManager\n  let hooks: Hooks\n  const mockSessionManager = {\n    findTrackedSession: () =>\n      ({\n        anonymousId: 'device-123',\n      }) as SessionContext<string>,\n  }\n\n  beforeEach(() => {\n    hooks = createHooks()\n    userContext = startUserContext(\n      hooks,\n      mockRumConfiguration({ trackAnonymousUser: false }),\n      mockSessionManager,\n      'some_product_key'\n    )\n  })\n\n  it('should sanitize predefined properties', () => {\n    userContext.setContext({ id: false, name: 2, email: { bar: 'qux' } })\n\n    expect(userContext.getContext()).toEqual({\n      email: '[object Object]',\n      id: 'false',\n      name: '2',\n    })\n  })\n\n  describe('assemble hook', () => {\n    it('should set the user', () => {\n      userContext.setContext({ id: '123', foo: 'bar' })\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        usr: {\n          id: '123',\n          foo: 'bar',\n        },\n      })\n    })\n\n    it('should set anonymous_id when trackAnonymousUser is true', () => {\n      userContext = startUserContext(\n        hooks,\n        { trackAnonymousUser: true } as Configuration,\n        mockSessionManager,\n        'some_product_key'\n      )\n      userContext.setContext({ id: '123' })\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        usr: {\n          id: '123',\n          anonymous_id: 'device-123',\n        },\n      })\n    })\n\n    it('should not override customer provided anonymous_id when trackAnonymousUser is true', () => {\n      userContext = startUserContext(\n        hooks,\n        { trackAnonymousUser: true } as Configuration,\n        mockSessionManager,\n        'some_product_key'\n      )\n      userContext.setContext({ id: '123', anonymous_id: 'foo' })\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        usr: {\n          id: '123',\n          anonymous_id: 'foo',\n        },\n      })\n    })\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should set the anonymous_id', () => {\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        anonymous_id: 'device-123',\n      })\n    })\n  })\n})\n\ndescribe('user context across pages', () => {\n  let userContext: ContextManager\n  let hooks: Hooks\n  const mockSessionManager = { findTrackedSession: () => undefined }\n\n  beforeEach(() => {\n    hooks = createHooks()\n\n    registerCleanupTask(() => {\n      localStorage.clear()\n      removeStorageListeners()\n    })\n  })\n\n  it('when disabled, should store contexts only in memory', () => {\n    userContext = startUserContext(\n      hooks,\n      { storeContextsAcrossPages: false } as Configuration,\n      mockSessionManager,\n      'some_product_key'\n    )\n    userContext.setContext({ id: '123' })\n\n    expect(userContext.getContext()).toEqual({ id: '123' })\n    expect(localStorage.getItem('_dd_c_some_product_key_1')).toBeNull()\n  })\n\n  it('when enabled, should maintain the user in local storage', () => {\n    userContext = startUserContext(\n      hooks,\n      { storeContextsAcrossPages: true } as Configuration,\n      mockSessionManager,\n      'some_product_key'\n    )\n\n    userContext.setContext({ id: 'foo', qux: 'qix' })\n    expect(userContext.getContext()).toEqual({ id: 'foo', qux: 'qix' })\n    expect(localStorage.getItem('_dd_c_some_product_key_1')).toBe('{\"id\":\"foo\",\"qux\":\"qix\"}')\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/contexts/userContext.ts",
    "content": "import type { AbstractHooks } from '../../tools/abstractHooks'\nimport { CustomerDataType } from '../context/contextConstants'\nimport { storeContextManager } from '../context/storeContextManager'\nimport { HookNames, SKIPPED } from '../../tools/abstractHooks'\nimport { createContextManager } from '../context/contextManager'\nimport type { Configuration } from '../configuration'\nimport { isEmptyObject } from '../../tools/utils/objectUtils'\nimport type { RelativeTime } from '../../tools/utils/timeUtils'\n\nexport interface User {\n  id?: string | undefined\n  email?: string | undefined\n  name?: string | undefined\n  [key: string]: unknown\n}\n\nexport function startUserContext(\n  hooks: AbstractHooks,\n  configuration: Configuration,\n  sessionManager: {\n    findTrackedSession: (startTime?: RelativeTime) => { anonymousId?: string } | undefined\n  },\n  productKey: string\n) {\n  const userContextManager = buildUserContextManager()\n\n  if (configuration.storeContextsAcrossPages) {\n    storeContextManager(configuration, userContextManager, productKey, CustomerDataType.User)\n  }\n\n  hooks.register(HookNames.Assemble, ({ eventType, startTime }) => {\n    const user = userContextManager.getContext()\n    const session = sessionManager.findTrackedSession(startTime)\n\n    if (session && session.anonymousId && !user.anonymous_id && !!configuration.trackAnonymousUser) {\n      user.anonymous_id = session.anonymousId\n    }\n\n    if (isEmptyObject(user)) {\n      return SKIPPED\n    }\n\n    return {\n      type: eventType,\n      usr: user,\n    }\n  })\n\n  hooks.register(HookNames.AssembleTelemetry, ({ startTime }) => ({\n    anonymous_id: sessionManager.findTrackedSession(startTime)?.anonymousId,\n  }))\n\n  return userContextManager\n}\n\nexport function buildUserContextManager() {\n  return createContextManager('user', {\n    propertiesConfig: {\n      id: { type: 'string' },\n      name: { type: 'string' },\n      email: { type: 'string' },\n    },\n  })\n}\n"
  },
  {
    "path": "packages/core/src/domain/deflate/deflate.types.ts",
    "content": "import type { Encoder } from '../../tools/encoder'\nimport type { Uint8ArrayBuffer } from '../../tools/utils/byteUtils'\n\nexport type DeflateWorkerAction =\n  // Action to send when creating the worker to check if the communication is working correctly.\n  // The worker should respond with a 'initialized' response.\n  | {\n      action: 'init'\n    }\n  // Action to send when writing some unfinished data. The worker will respond with a 'wrote'\n  // response, with the same id and measurements of the wrote data bytes count.\n  | {\n      action: 'write'\n      id: number\n      streamId: number\n      data: string\n    }\n  // Action to send when all data has been written and the state of the stream needs to be reset.\n  | {\n      action: 'reset'\n      streamId: number\n    }\n\nexport type DeflateWorkerResponse =\n  // Response to 'init' action\n  | {\n      type: 'initialized'\n      version: string\n    }\n  // Response to 'write' action\n  | {\n      type: 'wrote'\n      id: number\n      streamId: number\n      result: Uint8ArrayBuffer\n      trailer: Uint8ArrayBuffer\n      additionalBytesCount: number\n    }\n  // Could happen at any time when something goes wrong in the worker\n  | {\n      type: 'errored'\n      streamId?: number\n      error: Error | string\n    }\n\nexport interface DeflateWorker extends Worker {\n  postMessage(message: DeflateWorkerAction): void\n}\n\nexport type DeflateEncoder = Encoder<Uint8ArrayBuffer> & { stop: () => void }\n\nexport const enum DeflateEncoderStreamId {\n  REPLAY = 1,\n  RUM = 2,\n  TELEMETRY = 4,\n  PROFILING = 6,\n}\n"
  },
  {
    "path": "packages/core/src/domain/deflate/index.ts",
    "content": "export * from './deflate.types'\n"
  },
  {
    "path": "packages/core/src/domain/error/error.spec.ts",
    "content": "import { clocksNow } from '../../tools/utils/timeUtils'\nimport type { StackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { registerCleanupTask } from '../../../test'\nimport {\n  computeRawError,\n  getFileFromStackTraceString,\n  flattenErrorCauses,\n  isError,\n  NO_ERROR_STACK_PRESENT_MESSAGE,\n} from './error'\nimport type { RawErrorCause, ErrorWithCause } from './error.types'\nimport { ErrorHandling, ErrorSource, NonErrorPrefix } from './error.types'\n\ndescribe('computeRawError', () => {\n  const DEFAULT_RAW_ERROR_PARAMS = {\n    startClocks: clocksNow(),\n    nonErrorPrefix: NonErrorPrefix.UNCAUGHT,\n    source: ErrorSource.CUSTOM,\n  }\n\n  it('should format an error instance', () => {\n    const error = new TypeError('oh snap!')\n    // This stack was generated in Chrome.\n    error.stack = `TypeError: Oh snap!\n  at foo (http://path/to/file.js:52:15)\n  at <anonymous>:3:1`\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    expect(formatted.message).toEqual('oh snap!')\n    expect(formatted.type).toEqual('TypeError')\n    expect(formatted.stack).toEqual(`TypeError: oh snap!\n  at foo @ http://path/to/file.js:52:15\n  at <anonymous> @ <anonymous>:3:1`)\n  })\n\n  it('should format an error instance with an empty message', () => {\n    const error = new TypeError('oh snap!')\n    error.message = ''\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    expect(formatted.message).toEqual('Empty message')\n  })\n\n  it('should format a string error', () => {\n    const error = 'oh snap!'\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    expect(formatted.message).toEqual('Uncaught \"oh snap!\"')\n    expect(formatted.stack).toEqual(NO_ERROR_STACK_PRESENT_MESSAGE)\n  })\n\n  it('should format an object error', () => {\n    const error = { foo: 'bar' }\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    expect(formatted.message).toEqual('Uncaught {\"foo\":\"bar\"}')\n    expect(formatted.stack).toEqual(NO_ERROR_STACK_PRESENT_MESSAGE)\n  })\n\n  it('does not define the stack if useFallbackStack is false', () => {\n    const error = 'foo is undefined'\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n      useFallbackStack: false,\n    })\n\n    expect(formatted.stack).toEqual(undefined)\n  })\n\n  it('uses the provided stack trace object', () => {\n    const stackTrace: StackTrace = {\n      message: 'oh snap!',\n      name: 'TypeError',\n      stack: [\n        {\n          args: ['1', 'bar'],\n          column: 15,\n          func: 'foo',\n          line: 52,\n          url: 'http://path/to/file.js',\n        },\n        {\n          args: [],\n          column: undefined,\n          func: '?',\n          line: 12,\n          url: 'http://path/to/file.js',\n        },\n        {\n          args: ['baz'],\n          column: undefined,\n          func: '?',\n          line: undefined,\n          url: 'http://path/to/file.js',\n        },\n      ],\n    }\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: 'toto',\n      handling: ErrorHandling.HANDLED,\n      stackTrace,\n    })\n\n    expect(formatted.message).toEqual('oh snap!')\n    expect(formatted.stack).toEqual(`TypeError: oh snap!\n  at foo(1, bar) @ http://path/to/file.js:52:15\n  at <anonymous> @ http://path/to/file.js:12\n  at <anonymous>(baz) @ http://path/to/file.js`)\n    expect(formatted.type).toEqual('TypeError')\n  })\n\n  it('should set handling according to given parameter', () => {\n    const error = { foo: 'bar' }\n\n    expect(\n      computeRawError({\n        ...DEFAULT_RAW_ERROR_PARAMS,\n        originalError: error,\n        handling: ErrorHandling.HANDLED,\n      }).handling\n    ).toEqual(ErrorHandling.HANDLED)\n\n    expect(\n      computeRawError({\n        ...DEFAULT_RAW_ERROR_PARAMS,\n        originalError: error,\n        handling: ErrorHandling.UNHANDLED,\n      }).handling\n    ).toEqual(ErrorHandling.UNHANDLED)\n  })\n\n  it('should compute an object error with causes', () => {\n    const error = new Error('foo: bar') as ErrorWithCause\n    error.stack = 'Error: foo: bar\\n    at <anonymous>:1:15'\n\n    const nestedError = new Error('biz: buz') as ErrorWithCause\n    nestedError.stack = 'NestedError: biz: buz\\n    at <anonymous>:2:15'\n\n    const deepNestedError = new TypeError('fiz: buz') as ErrorWithCause\n    deepNestedError.stack = 'NestedError: fiz: buz\\n    at <anonymous>:3:15'\n\n    error.cause = nestedError\n    nestedError.cause = deepNestedError\n\n    const formatted = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n      source: ErrorSource.SOURCE,\n    })\n\n    expect(formatted.type).toEqual('Error')\n    expect(formatted.message).toEqual('foo: bar')\n    expect(formatted.causes!.length).toBe(2)\n    expect(formatted.stack).toContain('Error: foo: bar')\n\n    const causes = formatted.causes as RawErrorCause[]\n\n    expect(causes[0].message).toContain(nestedError.message)\n    expect(causes[0].source).toContain(ErrorSource.SOURCE)\n    expect(causes[0].type).toEqual(nestedError.name)\n    expect(causes[0].stack).toContain('Error: biz: buz')\n\n    expect(causes[1].message).toContain(deepNestedError.message)\n    expect(causes[1].source).toContain(ErrorSource.SOURCE)\n    expect(causes[1].type).toEqual(deepNestedError.name)\n    expect(causes[1].stack).toContain('Error: fiz: buz')\n  })\n\n  it('should propagate the original error without modifications', () => {\n    const error = { description: 'syntax error' }\n\n    const formattedWithoutStackTrace = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    const formattedWithStackTrace = computeRawError({\n      ...DEFAULT_RAW_ERROR_PARAMS,\n      originalError: error,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    expect(formattedWithStackTrace.originalError).toBe(error)\n    expect(formattedWithoutStackTrace.originalError).toBe(error)\n  })\n})\n\ndescribe('getFileFromStackTraceString', () => {\n  it('should get the first source file of the stack', () => {\n    expect(\n      getFileFromStackTraceString(`TypeError: oh snap!\n  at foo(1, bar) @ http://path/to/file.js:52:15\n  at <anonymous> @ http://path/to/file.js:12\n  at <anonymous>(baz) @ http://path/to/file.js`)\n    ).toEqual('http://path/to/file.js:52:15')\n  })\n\n  it('should get undefined if no source file is in the stack', () => {\n    expect(getFileFromStackTraceString('TypeError: oh snap!')).not.toBeDefined()\n  })\n})\n\ndescribe('flattenErrorCauses', () => {\n  it('should return undefined if no cause found', () => {\n    const error = new Error('foo') as ErrorWithCause\n    const errorCauses = flattenErrorCauses(error, ErrorSource.LOGGER)\n    expect(errorCauses).toEqual(undefined)\n  })\n\n  it('should use error to extract stack trace', () => {\n    const error = new Error('foo') as ErrorWithCause\n\n    error.cause = new Error('bar')\n\n    const errorCauses = flattenErrorCauses(error, ErrorSource.LOGGER)\n    expect(errorCauses?.[0].type).toEqual('Error')\n  })\n\n  it('should only return the first 10 errors if nested chain is longer', () => {\n    const error = new Error('foo') as ErrorWithCause\n    error.cause = error\n    const errorCauses = flattenErrorCauses(error, ErrorSource.LOGGER)\n    expect(errorCauses?.length).toEqual(10)\n  })\n\n  describe('with non-Error values', () => {\n    it('should handle string cause with consistent structure', () => {\n      const error = new Error('main') as ErrorWithCause\n      error.cause = 'string cause'\n\n      const causes = flattenErrorCauses(error, ErrorSource.CUSTOM)\n      expect(causes?.length).toBe(1)\n      expect(causes?.[0]).toEqual({\n        message: '\"string cause\"', // JSON stringified\n        source: ErrorSource.CUSTOM,\n        type: undefined,\n        stack: undefined,\n      })\n    })\n\n    it('should handle object cause with consistent structure', () => {\n      const error = new Error('main') as ErrorWithCause\n      error.cause = { code: 'ERR_001', details: 'Invalid input' }\n\n      const causes = flattenErrorCauses(error, ErrorSource.CUSTOM)\n      expect(causes?.length).toBe(1)\n      expect(causes?.[0]).toEqual({\n        message: '{\"code\":\"ERR_001\",\"details\":\"Invalid input\"}',\n        source: ErrorSource.CUSTOM,\n        type: undefined,\n        stack: undefined,\n      })\n    })\n\n    it('should handle number cause with consistent structure', () => {\n      const error = new Error('main') as ErrorWithCause\n      error.cause = 42\n\n      const causes = flattenErrorCauses(error, ErrorSource.CUSTOM)\n      expect(causes?.length).toBe(1)\n      expect(causes?.[0]).toEqual({\n        message: '42',\n        source: ErrorSource.CUSTOM,\n        type: undefined,\n        stack: undefined,\n      })\n    })\n\n    it('should handle mixed Error and non-Error chain', () => {\n      const error1 = new Error('first') as ErrorWithCause\n      const error2 = new Error('second') as ErrorWithCause\n      error1.cause = error2\n      error2.cause = { code: 'ERR_ROOT' }\n\n      const causes = flattenErrorCauses(error1, ErrorSource.CUSTOM)\n      expect(causes?.length).toBe(2)\n\n      // First cause: Error with full structure\n      expect(causes?.[0].message).toBe('second')\n      expect(causes?.[0].type).toBe('Error')\n      expect(causes?.[0].stack).toContain('Error')\n\n      // Second cause: Object with normalized structure\n      expect(causes?.[1]).toEqual({\n        message: '{\"code\":\"ERR_ROOT\"}',\n        source: ErrorSource.CUSTOM,\n        type: undefined,\n        stack: undefined,\n      })\n    })\n\n    it('should stop chain after non-Error cause', () => {\n      const error = new Error('main') as ErrorWithCause\n      error.cause = { value: 'data', cause: new Error('ignored') }\n\n      const causes = flattenErrorCauses(error, ErrorSource.CUSTOM)\n      expect(causes?.length).toBe(1)\n      // The entire object is captured, nested cause is sanitized\n      expect(causes?.[0].message).toContain('\"value\":\"data\"')\n      expect(causes?.[0].type).toBeUndefined()\n    })\n\n    it('should handle null cause', () => {\n      const error = new Error('main') as ErrorWithCause\n      error.cause = null\n      expect(flattenErrorCauses(error, ErrorSource.CUSTOM)).toBeUndefined()\n    })\n\n    it('should handle undefined cause', () => {\n      const error = new Error('main') as ErrorWithCause\n      error.cause = undefined\n      expect(flattenErrorCauses(error, ErrorSource.CUSTOM)).toBeUndefined()\n    })\n  })\n})\n\ndescribe('isError', () => {\n  it('should correctly identify an error object from a different window context', () => {\n    const iframe = document.createElement('iframe')\n    document.body.appendChild(iframe)\n    registerCleanupTask(() => document.body.removeChild(iframe))\n\n    const iframeWindow = iframe.contentWindow as Window & { Error: ErrorConstructor }\n\n    expect(isError(new iframeWindow.Error())).toBe(true)\n  })\n})\n\ndescribe('tryToGetContext', () => {\n  it('should extract dd_context from an error object', () => {\n    const context = { key: 'value' }\n    const error = new Error('Test error') as any\n    error.dd_context = context\n\n    const rawError = computeRawError({\n      originalError: error,\n      handlingStack: undefined,\n      componentStack: undefined,\n      startClocks: clocksNow(),\n      nonErrorPrefix: NonErrorPrefix.UNCAUGHT,\n      source: ErrorSource.CUSTOM,\n      handling: ErrorHandling.HANDLED,\n    })\n\n    expect(rawError.context).toEqual(context)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/error/error.ts",
    "content": "import { sanitize } from '../../tools/serialisation/sanitize'\nimport type { ClocksState } from '../../tools/utils/timeUtils'\nimport type { Context } from '../../tools/serialisation/context'\nimport { jsonStringify } from '../../tools/serialisation/jsonStringify'\nimport type { StackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { computeStackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { toStackTraceString } from '../../tools/stackTrace/handlingStack'\nimport { isIndexableObject } from '../../tools/utils/typeUtils'\nimport type { ErrorSource, ErrorHandling, RawError, RawErrorCause, ErrorWithCause, NonErrorPrefix } from './error.types'\n\nexport const NO_ERROR_STACK_PRESENT_MESSAGE = 'No stack, consider using an instance of Error'\n\ninterface RawErrorParams {\n  stackTrace?: StackTrace\n  originalError: unknown\n  handlingStack?: string\n  componentStack?: string\n  startClocks: ClocksState\n  nonErrorPrefix: NonErrorPrefix\n  useFallbackStack?: boolean\n  source: ErrorSource\n  handling: ErrorHandling\n}\n\nfunction computeErrorBase({\n  originalError,\n  stackTrace,\n  source,\n  useFallbackStack = true,\n  nonErrorPrefix,\n}: {\n  originalError: unknown\n  stackTrace?: StackTrace\n  source: ErrorSource\n  useFallbackStack?: boolean\n  nonErrorPrefix?: NonErrorPrefix\n}) {\n  const isErrorInstance = isError(originalError)\n  if (!stackTrace && isErrorInstance) {\n    stackTrace = computeStackTrace(originalError)\n  }\n\n  return {\n    source,\n    type: stackTrace ? stackTrace.name : undefined,\n    message: computeMessage(stackTrace, isErrorInstance, nonErrorPrefix, originalError),\n    stack: stackTrace ? toStackTraceString(stackTrace) : useFallbackStack ? NO_ERROR_STACK_PRESENT_MESSAGE : undefined,\n  }\n}\n\nexport function computeRawError({\n  stackTrace,\n  originalError,\n  handlingStack,\n  componentStack,\n  startClocks,\n  nonErrorPrefix,\n  useFallbackStack = true,\n  source,\n  handling,\n}: RawErrorParams): RawError {\n  const errorBase = computeErrorBase({ originalError, stackTrace, source, useFallbackStack, nonErrorPrefix })\n\n  return {\n    startClocks,\n    handling,\n    handlingStack,\n    componentStack,\n    originalError,\n    ...errorBase,\n    causes: isError(originalError) ? flattenErrorCauses(originalError as ErrorWithCause, source) : undefined,\n    fingerprint: tryToGetFingerprint(originalError),\n    context: tryToGetErrorContext(originalError),\n  }\n}\n\nfunction computeMessage(\n  stackTrace: StackTrace | undefined,\n  isErrorInstance: boolean,\n  nonErrorPrefix: NonErrorPrefix | undefined,\n  originalError: unknown\n) {\n  // Favor stackTrace message only if tracekit has really been able to extract something meaningful (message + name)\n  // TODO rework tracekit integration to avoid scattering error building logic\n  return stackTrace?.message && stackTrace?.name\n    ? stackTrace.message\n    : !isErrorInstance\n      ? nonErrorPrefix\n        ? `${nonErrorPrefix} ${jsonStringify(sanitize(originalError))!}`\n        : jsonStringify(sanitize(originalError))!\n      : 'Empty message'\n}\n\nexport function tryToGetFingerprint(originalError: unknown) {\n  return isError(originalError) && 'dd_fingerprint' in originalError ? String(originalError.dd_fingerprint) : undefined\n}\n\nexport function tryToGetErrorContext(originalError: unknown) {\n  if (isIndexableObject(originalError)) {\n    return originalError.dd_context as Context | undefined\n  }\n}\n\nexport function getFileFromStackTraceString(stack: string) {\n  return /@ (.+)/.exec(stack)?.[1]\n}\n\nexport function isError(error: unknown): error is Error {\n  return error instanceof Error || Object.prototype.toString.call(error) === '[object Error]'\n}\n\nexport function flattenErrorCauses(error: ErrorWithCause, parentSource: ErrorSource): RawErrorCause[] | undefined {\n  const causes: RawErrorCause[] = []\n  let currentCause = error.cause\n\n  while (currentCause !== undefined && currentCause !== null && causes.length < 10) {\n    const causeBase = computeErrorBase({\n      originalError: currentCause,\n      source: parentSource,\n      useFallbackStack: false,\n    })\n\n    causes.push(causeBase)\n\n    currentCause = isError(currentCause) ? (currentCause as ErrorWithCause).cause : undefined\n  }\n\n  return causes.length ? causes : undefined\n}\n"
  },
  {
    "path": "packages/core/src/domain/error/error.types.ts",
    "content": "import type { Context } from '../../tools/serialisation/context'\nimport type { ClocksState } from '../../tools/utils/timeUtils'\n\n// TS v4.6 introduced Error.cause[1] typed as `Error`. TS v4.8 changed Error.cause to be\n// `unknown`[2].\n//\n// Because we still support TS 3.8, we need to declare our own type. We can remove it once we drop\n// support for TS v4.7 and before. The 'cause' property defined by TS needs to be omitted because\n// we define it with a type `unknown` which is incompatible with TS 4.6 and 4.7.\n//\n// [1]: https://devblogs.microsoft.com/typescript/announcing-typescript-4-6/#target-es2022\n// [2]: https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#lib-d-ts-updates\nexport interface ErrorWithCause extends Omit<Error, 'cause'> {\n  cause?: unknown\n}\n\nexport interface RawErrorCause {\n  message: string\n  source: ErrorSource\n  type?: string\n  stack?: string\n}\n\nexport interface Csp {\n  disposition: 'enforce' | 'report'\n}\n\nexport interface RawError {\n  startClocks: ClocksState\n  message: string\n  type?: string\n  stack?: string\n  source: ErrorSource\n  originalError?: unknown\n  handling?: ErrorHandling\n  handlingStack?: string\n  componentStack?: string\n  causes?: RawErrorCause[]\n  fingerprint?: string\n  csp?: Csp\n  context?: Context\n}\n\nexport const ErrorSource = {\n  AGENT: 'agent',\n  CONSOLE: 'console',\n  CUSTOM: 'custom',\n  LOGGER: 'logger',\n  NETWORK: 'network',\n  SOURCE: 'source',\n  REPORT: 'report',\n} as const\n\nexport const enum NonErrorPrefix {\n  UNCAUGHT = 'Uncaught',\n  PROVIDED = 'Provided',\n}\n\nexport const enum ErrorHandling {\n  HANDLED = 'handled',\n  UNHANDLED = 'unhandled',\n}\n\nexport type ErrorSource = (typeof ErrorSource)[keyof typeof ErrorSource]\n"
  },
  {
    "path": "packages/core/src/domain/error/trackRuntimeError.spec.ts",
    "content": "import { disableJasmineUncaughtExceptionTracking, wait } from '../../../test'\nimport type { UnhandledErrorCallback } from './trackRuntimeError'\nimport { instrumentOnError, instrumentUnhandledRejection, trackRuntimeError } from './trackRuntimeError'\nimport type { RawError } from './error.types'\n\ndescribe('trackRuntimeError', () => {\n  const ERROR_MESSAGE = 'foo'\n\n  const errorViaTrackRuntimeError = async (callback: () => void): Promise<RawError> => {\n    disableJasmineUncaughtExceptionTracking()\n\n    const errorObservable = trackRuntimeError()\n    const errorNotification = new Promise<RawError>((resolve) => {\n      errorObservable.subscribe((e: RawError) => resolve(e))\n    })\n\n    try {\n      await invokeAndWaitForErrorHandlers(callback)\n      return await errorNotification\n    } finally {\n      stop()\n    }\n  }\n\n  it('should collect unhandled error', async () => {\n    const error = await errorViaTrackRuntimeError(() => {\n      throw new Error(ERROR_MESSAGE)\n    })\n    expect(error.message).toEqual(ERROR_MESSAGE)\n  })\n\n  it('should collect unhandled rejection', async () => {\n    if (!('onunhandledrejection' in window)) {\n      pending('onunhandledrejection not supported')\n    }\n\n    const error = await errorViaTrackRuntimeError(() => {\n      // Reject with a string instead of an Error here because Jasmine forwards the\n      // unhandled rejection to the onerror handler with the wrong argument structure if\n      // you use an Error. (It uses the argument structure you'd use for\n      // addEventListener('error'). We could make our error processing code robust to\n      // that, but since it's a Jasmine-specific issue with a simple workaround, it makes\n      // sense to just work around it here.\n      // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n      void Promise.reject(ERROR_MESSAGE)\n    })\n    expect(error.message).toEqual(jasmine.stringContaining(ERROR_MESSAGE))\n  })\n})\n\ndescribe('instrumentOnError', () => {\n  const testLineNo = 1337\n  const testColNo = 42\n  const ERROR_MESSAGE = 'foo'\n\n  const spyViaInstrumentOnError = async (callback: () => void) => {\n    const onErrorSpy = spyOn(window as any, 'onerror')\n    const callbackSpy = jasmine.createSpy<UnhandledErrorCallback>()\n    const { stop } = instrumentOnError(callbackSpy)\n\n    try {\n      await invokeAndWaitForErrorHandlers(callback)\n      expect(onErrorSpy).toHaveBeenCalled()\n      return callbackSpy\n    } finally {\n      stop()\n    }\n  }\n\n  it('should call original error handler', async () => {\n    // withInstrumentOnError() asserts that the original error handler has been called for\n    // every test, so we don't need an explicit expectation here.\n    await spyViaInstrumentOnError(() => {\n      throw new Error(ERROR_MESSAGE)\n    })\n  })\n\n  it('should notify unhandled error instance', async () => {\n    const error = new Error(ERROR_MESSAGE)\n    const spy = await spyViaInstrumentOnError(() => {\n      throw error\n    })\n\n    const [originalError, stack] = spy.calls.mostRecent().args\n    expect(originalError).toBe(error)\n    expect(stack).toBeUndefined()\n  })\n\n  it('should notify unhandled string', async () => {\n    const error = 'foo' as any\n    const spy = await spyViaInstrumentOnError(() => {\n      throw error\n    })\n\n    const [originalError, stack] = spy.calls.mostRecent().args\n    expect(originalError).toBe(error)\n    expect(stack).toBeDefined()\n  })\n\n  it('should notify unhandled object', async () => {\n    const error = { a: 'foo' } as any\n    const spy = await spyViaInstrumentOnError(() => {\n      throw error\n    })\n\n    const [originalError, stack] = spy.calls.mostRecent().args\n    expect(originalError).toBe(error)\n    expect(stack).toBeDefined()\n  })\n\n  describe('uncaught exception handling', () => {\n    it('should not go into an infinite loop', async () => {\n      const spy = await spyViaInstrumentOnError(() => {\n        throw new Error('expected error')\n      })\n\n      expect(spy).toHaveBeenCalledTimes(1)\n      await wait(1000)\n      expect(spy).toHaveBeenCalledTimes(1)\n    })\n\n    it('should get extra arguments (isWindowError and exception)', async () => {\n      const exception = new Error('expected error')\n      const spy = await spyViaInstrumentOnError(() => {\n        throw exception\n      })\n\n      expect(spy).toHaveBeenCalledTimes(1)\n      await wait(1000)\n      expect(spy).toHaveBeenCalledTimes(1)\n      const [reportedError] = spy.calls.mostRecent().args\n      expect(reportedError).toEqual(exception)\n    })\n  })\n\n  describe('should handle direct onerror calls', () => {\n    it('with objects', async () => {\n      const error = { foo: 'bar' } as any\n      const spy = await spyViaInstrumentOnError(() => {\n        window.onerror!(error, 'http://example.com', testLineNo, testColNo)\n      })\n\n      const [originalError, stack] = spy.calls.mostRecent().args\n      expect(originalError).toBe(error)\n      expect(stack).toBeDefined()\n    })\n\n    describe('with undefined arguments', () => {\n      it('discards the stack', async () => {\n        // this is probably not good behavior;  just writing this test to verify\n        // that it doesn't change unintentionally\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!(undefined!, undefined, testLineNo)\n        })\n\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack).toBeUndefined()\n      })\n    })\n\n    describe('when no 5th argument (error object)', () => {\n      it('should separate name, message for default error types (e.g. ReferenceError)', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!('ReferenceError: foo is undefined', 'http://example.com', testLineNo)\n        })\n\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack!.name).toEqual('ReferenceError')\n        expect(stack!.message).toEqual('foo is undefined')\n      })\n\n      it('should separate name, message for default error types (e.g. Uncaught ReferenceError)', async () => {\n        // should work with/without 'Uncaught'\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!('Uncaught ReferenceError: foo is undefined', 'http://example.com', testLineNo)\n        })\n\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack!.name).toEqual('ReferenceError')\n        expect(stack!.message).toEqual('foo is undefined')\n      })\n\n      it('should separate name, message for default error types on Opera Mini', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!(\n            'Uncaught exception: ReferenceError: Undefined variable: foo',\n            'http://example.com',\n            testLineNo\n          )\n        })\n\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack!.name).toEqual('ReferenceError')\n        expect(stack!.message).toEqual('Undefined variable: foo')\n      })\n\n      it('should separate name, message for error with multiline message', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!(\n            \"TypeError: foo is not a function. (In 'my.function(\\n foo)\",\n            'http://example.com',\n            testLineNo\n          )\n        })\n\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack!.message).toEqual(\"foo is not a function. (In 'my.function(\\n foo)\")\n        expect(stack!.name).toEqual('TypeError')\n      })\n\n      it('should ignore unknown error types', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!('CustomError: woo scary', 'http://example.com', testLineNo)\n        })\n\n        // TODO: should we attempt to parse this?\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack!.name).toEqual(undefined)\n        expect(stack!.message).toEqual('CustomError: woo scary')\n      })\n\n      it('should ignore arbitrary messages passed through onerror', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!('all work and no play makes homer: something something', 'http://example.com', testLineNo)\n        })\n\n        const [, stack] = spy.calls.mostRecent().args\n        expect(stack!.name).toEqual(undefined)\n        expect(stack!.message).toEqual('all work and no play makes homer: something something')\n      })\n\n      it('should handle object message passed through onerror', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!({ foo: 'bar' } as any, 'http://example.com', testLineNo, testColNo)\n        })\n\n        const [error, stack] = spy.calls.mostRecent().args\n        expect(stack!.message).toBeUndefined()\n        expect(error).toEqual({ foo: 'bar' }) // consider the message as initial error\n      })\n    })\n\n    describe('when 5th argument (errorObj) is not of type Error', () => {\n      it('should handle strings', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!(\n            'Any error message',\n            'https://example.com',\n            testLineNo,\n            testColNo,\n            'Actual Error Message' as any\n          )\n        })\n\n        const [error, stack] = spy.calls.mostRecent().args\n        expect(stack!.message).toBe('Any error message')\n        expect(stack!.stack).toEqual([{ url: 'https://example.com', column: testColNo, line: testLineNo }])\n        expect(error).toEqual('Actual Error Message')\n      })\n\n      it('should handle objects', async () => {\n        const spy = await spyViaInstrumentOnError(() => {\n          window.onerror!('Any error message', 'https://example.com', testLineNo, testColNo, {\n            message: 'SyntaxError',\n            data: 'foo',\n          } as any)\n        })\n\n        const [error, stack] = spy.calls.mostRecent().args\n        expect(stack!.message).toBe('Any error message')\n        expect(stack!.stack).toEqual([{ url: 'https://example.com', column: testColNo, line: testLineNo }])\n        expect(error).toEqual({ message: 'SyntaxError', data: 'foo' })\n      })\n    })\n  })\n})\n\ndescribe('instrumentUnhandledRejection', () => {\n  const ERROR_MESSAGE = 'foo'\n\n  const spyViaInstrumentOnUnhandledRejection = async (callback: () => void) => {\n    if (!('onunhandledrejection' in window)) {\n      pending('onunhandledrejection not supported')\n    }\n\n    const onUnhandledRejectionSpy = spyOn(window as any, 'onunhandledrejection')\n    const callbackSpy = jasmine.createSpy<UnhandledErrorCallback>()\n    const { stop } = instrumentUnhandledRejection(callbackSpy)\n\n    try {\n      await invokeAndWaitForErrorHandlers(callback)\n      expect(onUnhandledRejectionSpy).toHaveBeenCalled()\n      return callbackSpy\n    } finally {\n      stop()\n    }\n  }\n\n  it('should call original unhandled rejection handler', async () => {\n    // withInstrumentOnUnhandledRejection() asserts that the original unhandled\n    // rejection handler has been called for every test, so we don't need an\n    // explicit expectation here.\n    await spyViaInstrumentOnUnhandledRejection(() => {\n      window.onunhandledrejection!({\n        reason: new Error(ERROR_MESSAGE),\n      } as PromiseRejectionEvent)\n    })\n  })\n\n  it('should notify unhandled rejection', async () => {\n    const reason = new Error(ERROR_MESSAGE)\n    const spy = await spyViaInstrumentOnUnhandledRejection(() => {\n      window.onunhandledrejection!({ reason } as PromiseRejectionEvent)\n    })\n\n    const [originalError, stack] = spy.calls.mostRecent().args\n    expect(originalError).toBe(reason)\n    expect(stack).toBeUndefined()\n  })\n})\n\n/**\n * Invokes the given callback, which is expected to be a function that throws or generates\n * an unhandled promise rejection, and returns a promise that resolves after the callback\n * has finished running and any global error handlers that run as a result are complete.\n */\nfunction invokeAndWaitForErrorHandlers(callback: () => void): Promise<void> {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      try {\n        // Invoke the callback.\n        callback()\n      } finally {\n        // The callback has generated an error here, but global error handlers\n        // have not yet run. The global unhandledrejection handler will run at\n        // the end of the next microtask checkpoint; the global error handler\n        // will run in a later macrotask. So, schedule a new task to resolve\n        // the promise after both of those things have happened.\n        setTimeout(resolve)\n      }\n    })\n  })\n}\n"
  },
  {
    "path": "packages/core/src/domain/error/trackRuntimeError.ts",
    "content": "import { instrumentMethod } from '../../tools/instrumentMethod'\nimport { Observable } from '../../tools/observable'\nimport { clocksNow } from '../../tools/utils/timeUtils'\nimport type { StackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { computeStackTraceFromOnErrorMessage } from '../../tools/stackTrace/computeStackTrace'\nimport { getGlobalObject } from '../../tools/globalObject'\nimport { computeRawError, isError } from './error'\nimport type { RawError } from './error.types'\nimport { ErrorHandling, ErrorSource, NonErrorPrefix } from './error.types'\n\nexport type UnhandledErrorCallback = (originalError: unknown, stackTrace?: StackTrace) => any\n\nexport function trackRuntimeError() {\n  return new Observable<RawError>((observer) => {\n    const handleRuntimeError = (originalError: unknown, stackTrace?: StackTrace) => {\n      const rawError = computeRawError({\n        stackTrace,\n        originalError,\n        startClocks: clocksNow(),\n        nonErrorPrefix: NonErrorPrefix.UNCAUGHT,\n        source: ErrorSource.SOURCE,\n        handling: ErrorHandling.UNHANDLED,\n      })\n      observer.notify(rawError)\n    }\n    const { stop: stopInstrumentingOnError } = instrumentOnError(handleRuntimeError)\n    const { stop: stopInstrumentingOnUnhandledRejection } = instrumentUnhandledRejection(handleRuntimeError)\n\n    return () => {\n      stopInstrumentingOnError()\n      stopInstrumentingOnUnhandledRejection()\n    }\n  })\n}\n\nexport function instrumentOnError(callback: UnhandledErrorCallback) {\n  return instrumentMethod(getGlobalObject(), 'onerror', ({ parameters: [messageObj, url, line, column, errorObj] }) => {\n    let stackTrace\n    if (!isError(errorObj)) {\n      stackTrace = computeStackTraceFromOnErrorMessage(messageObj, url, line, column)\n    }\n    callback(errorObj ?? messageObj, stackTrace)\n  })\n}\n\nexport function instrumentUnhandledRejection(callback: UnhandledErrorCallback) {\n  return instrumentMethod(getGlobalObject(), 'onunhandledrejection', ({ parameters: [e] }) => {\n    callback(e.reason || 'Empty reason')\n  })\n}\n"
  },
  {
    "path": "packages/core/src/domain/eventRateLimiter/createEventRateLimiter.spec.ts",
    "content": "import type { Clock } from '../../../test'\nimport { mockClock } from '../../../test'\nimport { relativeToClocks, ONE_MINUTE } from '../../tools/utils/timeUtils'\nimport { noop } from '../../tools/utils/functionUtils'\nimport type { RawError } from '../error/error.types'\nimport { createEventRateLimiter } from './createEventRateLimiter'\nimport type { EventRateLimiter } from './createEventRateLimiter'\n\ndescribe('createEventRateLimiter', () => {\n  let eventLimiter: EventRateLimiter | undefined\n  let clock: Clock\n  const limit = 1\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  it('returns false if the limit is not reached', () => {\n    eventLimiter = createEventRateLimiter('error', noop, limit)\n\n    expect(eventLimiter.isLimitReached()).toBe(false)\n  })\n\n  it('returns true if the limit is reached', () => {\n    eventLimiter = createEventRateLimiter('error', noop, limit)\n\n    eventLimiter.isLimitReached()\n    expect(eventLimiter.isLimitReached()).toBe(true)\n  })\n\n  it('returns false again when one minute is passed after the first counted error', () => {\n    eventLimiter = createEventRateLimiter('error', noop, limit)\n\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    clock.tick(ONE_MINUTE)\n    expect(eventLimiter.isLimitReached()).toBe(false)\n  })\n\n  it('calls the \"onLimitReached\" callback with the raw \"limit reached\" error when the limit is reached', () => {\n    const onLimitReachedSpy = jasmine.createSpy<(rawError: RawError) => void>()\n    eventLimiter = createEventRateLimiter('error', onLimitReachedSpy, limit)\n\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    expect(onLimitReachedSpy).toHaveBeenCalledOnceWith({\n      message: 'Reached max number of errors by minute: 1',\n      source: 'agent',\n      startClocks: relativeToClocks(clock.relative(0)),\n    })\n  })\n\n  it('returns false when called from the \"onLimitReached\" callback to bypass the limit for the \"limit reached\" error', () => {\n    eventLimiter = createEventRateLimiter(\n      'error',\n      () => {\n        expect(eventLimiter!.isLimitReached()).toBe(false)\n      },\n      limit\n    )\n\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n  })\n\n  it('does not call the \"onLimitReached\" callback more than once when the limit is reached', () => {\n    const onLimitReachedSpy = jasmine.createSpy<(rawError: RawError) => void>()\n    eventLimiter = createEventRateLimiter('error', onLimitReachedSpy, limit)\n\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    expect(onLimitReachedSpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('returns true after reaching the limit even if the \"onLimitReached\" callback throws', () => {\n    eventLimiter = createEventRateLimiter(\n      'error',\n      () => {\n        throw new Error('oops')\n      },\n      limit\n    )\n\n    eventLimiter.isLimitReached()\n    expect(() => eventLimiter!.isLimitReached()).toThrow()\n    expect(eventLimiter.isLimitReached()).toBe(true)\n    expect(eventLimiter.isLimitReached()).toBe(true)\n  })\n\n  it('returns true when the limit is reached and the \"onLimitReached\" callback does not call \"isLimitReached\" (ex: excluded by beforeSend)', () => {\n    eventLimiter = createEventRateLimiter(\n      'error',\n      () => {\n        // do not call isLimitReached\n      },\n      limit\n    )\n\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n    expect(eventLimiter.isLimitReached()).toBe(true)\n  })\n\n  it('returns false only once when called from the \"onLimitReached\" callback (edge case)', () => {\n    eventLimiter = createEventRateLimiter(\n      'error',\n      () => {\n        expect(eventLimiter!.isLimitReached()).toBe(false)\n        expect(eventLimiter!.isLimitReached()).toBe(true)\n      },\n      limit\n    )\n\n    eventLimiter.isLimitReached()\n    eventLimiter.isLimitReached()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/eventRateLimiter/createEventRateLimiter.ts",
    "content": "import { setTimeout } from '../../tools/timer'\nimport { clocksNow, ONE_MINUTE } from '../../tools/utils/timeUtils'\nimport type { RawError } from '../error/error.types'\nimport { ErrorSource } from '../error/error.types'\n\nexport type EventRateLimiter = ReturnType<typeof createEventRateLimiter>\n\n// Limit the maximum number of actions, errors and logs per minutes\nconst EVENT_RATE_LIMIT = 3000\n\nexport function createEventRateLimiter(\n  eventType: string,\n  onLimitReached: (limitError: RawError) => void,\n  limit = EVENT_RATE_LIMIT\n) {\n  let eventCount = 0\n  let allowNextEvent = false\n\n  return {\n    isLimitReached() {\n      if (eventCount === 0) {\n        setTimeout(() => {\n          eventCount = 0\n        }, ONE_MINUTE)\n      }\n\n      eventCount += 1\n      if (eventCount <= limit || allowNextEvent) {\n        allowNextEvent = false\n        return false\n      }\n\n      if (eventCount === limit + 1) {\n        allowNextEvent = true\n        try {\n          onLimitReached({\n            message: `Reached max number of ${eventType}s by minute: ${limit}`,\n            source: ErrorSource.AGENT,\n            startClocks: clocksNow(),\n          })\n        } finally {\n          allowNextEvent = false\n        }\n      }\n\n      return true\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/extension/extensionUtils.spec.ts",
    "content": "import {\n  STACK_WITH_INIT_IN_EXTENSION,\n  STACK_WITH_INIT_IN_EXTENSION_FIREFOX,\n  STACK_WITH_INIT_IN_PAGE,\n} from '../../../test'\nimport { containsExtensionUrl, EXTENSION_PREFIXES, isUnsupportedExtensionEnvironment } from './extensionUtils'\n\ndescribe('extensionUtils', () => {\n  describe('containsExtensionUrl', () => {\n    it('should return true if string contains an extension URL', () => {\n      EXTENSION_PREFIXES.forEach((prefix) => {\n        expect(containsExtensionUrl(`${prefix}some/path`)).toBe(true)\n      })\n    })\n\n    it('should return false if string does not contain extension URL', () => {\n      expect(containsExtensionUrl('https://example.com')).toBe(false)\n      expect(containsExtensionUrl('')).toBe(false)\n    })\n  })\n\n  describe('isUnsupportedExtensionEnvironment', () => {\n    it('should return true when window location is a regular URL and error stack init is in an extension', () => {\n      expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_EXTENSION)).toBe(true)\n    })\n\n    it('should return false when both window location and error stack init are regular URLs', () => {\n      expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_PAGE)).toBe(false)\n    })\n\n    it('should return false when error stack is empty', () => {\n      expect(isUnsupportedExtensionEnvironment('https://example.com', '')).toBe(false)\n    })\n\n    it('should handle each extension prefix in firefox', () => {\n      expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_EXTENSION_FIREFOX)).toBe(true)\n    })\n\n    it('should handle case when stack trace is undefined', () => {\n      expect(isUnsupportedExtensionEnvironment('https://example.com')).toBe(false)\n    })\n\n    it('should handle extension stack trace', () => {\n      expect(isUnsupportedExtensionEnvironment('https://example.com', STACK_WITH_INIT_IN_EXTENSION)).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/extension/extensionUtils.ts",
    "content": "export const EXTENSION_PREFIXES = ['chrome-extension://', 'moz-extension://']\n\nexport function containsExtensionUrl(str: string): boolean {\n  return EXTENSION_PREFIXES.some((prefix) => str.includes(prefix))\n}\n\n/**\n * Utility function to detect if the SDK is being initialized in an unsupported browser extension environment.\n *\n * @param windowLocation - The current window location to check\n * @param stack - The error stack to check for extension URLs\n * @returns true if running in an unsupported browser extension environment\n */\nexport function isUnsupportedExtensionEnvironment(windowLocation: string, stack: string = '') {\n  // If the page itself is an extension page.\n  if (containsExtensionUrl(windowLocation)) {\n    return false\n  }\n\n  // Since we generate the error on the init, we check the 2nd frame line.\n  const frameLines = stack.split('\\n').filter((line) => {\n    const trimmedLine = line.trim()\n    return trimmedLine.length && /^at\\s+|@/.test(trimmedLine)\n  })\n  const target = frameLines[1] || ''\n\n  return containsExtensionUrl(target)\n}\n"
  },
  {
    "path": "packages/core/src/domain/intakeSites.ts",
    "content": "export type Site =\n  | 'datadoghq.com'\n  | 'us3.datadoghq.com'\n  | 'us5.datadoghq.com'\n  | 'datadoghq.eu'\n  | 'ddog-gov.com'\n  | 'us2.ddog-gov.com'\n  | 'ap1.datadoghq.com'\n  | 'ap2.datadoghq.com'\n  | (string & {})\n\nexport const INTAKE_SITE_STAGING: Site = 'datad0g.com'\nexport const INTAKE_SITE_FED_STAGING: Site = 'dd0g-gov.com'\nexport const INTAKE_SITE_US1: Site = 'datadoghq.com'\nexport const INTAKE_SITE_EU1: Site = 'datadoghq.eu'\nexport const INTAKE_SITE_US1_FED: Site = 'ddog-gov.com'\nexport const INTAKE_SITE_US2_FED: Site = 'us2.ddog-gov.com'\n\nexport const PCI_INTAKE_HOST_US1 = 'pci.browser-intake-datadoghq.com'\nexport const INTAKE_URL_PARAMETERS = ['ddsource', 'dd-api-key', 'dd-request-id']\n"
  },
  {
    "path": "packages/core/src/domain/report/browser.types.ts",
    "content": "export type ReportType = DeprecationReport['type'] | InterventionReport['type']\n\ninterface Report {\n  type: ReportType\n  url: string\n  body: DeprecationReportBody | InterventionReportBody\n  toJSON(): any\n}\n\ninterface ReportBody {\n  toJSON(): any\n}\n\nexport interface DeprecationReport extends Report {\n  type: 'deprecation'\n  body: DeprecationReportBody\n}\nexport interface DeprecationReportBody extends ReportBody {\n  id: string\n  message: string\n  lineNumber: number | null\n  columnNumber: number | null\n  sourceFile: string | null\n  anticipatedRemoval: Date | null\n}\n\nexport interface InterventionReport extends Report {\n  type: 'intervention'\n  body: InterventionReportBody\n}\n\nexport interface InterventionReportBody extends ReportBody {\n  id: string\n  message: string\n  lineNumber: number | null\n  columnNumber: number | null\n  sourceFile: string | null\n}\n"
  },
  {
    "path": "packages/core/src/domain/report/reportObservable.spec.ts",
    "content": "import type { MockCspEventListener, MockReportingObserver } from '../../../test'\nimport { mockReportingObserver, mockCspEventListener, FAKE_CSP_VIOLATION_EVENT } from '../../../test'\nimport type { Subscription } from '../../tools/observable'\nimport type { Configuration } from '../configuration'\nimport { ErrorHandling, ErrorSource } from '../error/error.types'\nimport type { RawReportError } from './reportObservable'\nimport { initReportObservable, RawReportType } from './reportObservable'\n\ndescribe('report observable', () => {\n  let reportingObserver: MockReportingObserver\n  let cspEventListener: MockCspEventListener\n  let consoleSubscription: Subscription\n  let notifyReport: jasmine.Spy<(reportError: RawReportError) => void>\n  let configuration: Configuration\n\n  beforeEach(() => {\n    if (!window.ReportingObserver) {\n      pending('ReportingObserver not supported')\n    }\n    configuration = {} as Configuration\n    reportingObserver = mockReportingObserver()\n    cspEventListener = mockCspEventListener()\n    notifyReport = jasmine.createSpy('notifyReport')\n  })\n\n  afterEach(() => {\n    consoleSubscription?.unsubscribe()\n  })\n  ;[RawReportType.deprecation, RawReportType.intervention].forEach((type) => {\n    it(`should notify ${type} reports`, () => {\n      consoleSubscription = initReportObservable(configuration, [type]).subscribe(notifyReport)\n      reportingObserver.raiseReport(type)\n\n      const [report] = notifyReport.calls.mostRecent().args\n\n      expect(report).toEqual(\n        jasmine.objectContaining({\n          message: `${type}: foo bar`,\n          type: 'NavigatorVibrate',\n        })\n      )\n    })\n  })\n\n  it(`should compute stack for ${RawReportType.intervention}`, () => {\n    consoleSubscription = initReportObservable(configuration, [RawReportType.intervention]).subscribe(notifyReport)\n    reportingObserver.raiseReport(RawReportType.intervention)\n\n    const [report] = notifyReport.calls.mostRecent().args\n\n    expect(report.stack).toEqual(`NavigatorVibrate: foo bar\n  at <anonymous> @ http://foo.bar/index.js:20:10`)\n  })\n\n  it(`should notify ${RawReportType.cspViolation}`, () => {\n    consoleSubscription = initReportObservable(configuration, [RawReportType.cspViolation]).subscribe(notifyReport)\n    cspEventListener.dispatchEvent()\n\n    expect(notifyReport).toHaveBeenCalledOnceWith({\n      startClocks: jasmine.any(Object),\n      source: ErrorSource.REPORT,\n      message: \"csp_violation: 'blob' blocked by 'worker-src' directive\",\n      type: 'worker-src',\n      originalError: FAKE_CSP_VIOLATION_EVENT,\n      stack: `worker-src: 'blob' blocked by 'worker-src' directive of the policy \"worker-src 'none'\"\n  at <anonymous> @ http://foo.bar/index.js:17:8`,\n      handling: ErrorHandling.UNHANDLED,\n      csp: { disposition: 'enforce' },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/report/reportObservable.ts",
    "content": "import { toStackTraceString } from '../../tools/stackTrace/handlingStack'\nimport { monitor } from '../../tools/monitor'\nimport { mergeObservables, Observable } from '../../tools/observable'\nimport { addEventListener, DOM_EVENT } from '../../browser/addEventListener'\nimport { safeTruncate } from '../../tools/utils/stringUtils'\nimport type { Configuration } from '../configuration'\nimport type { RawError } from '../error/error.types'\nimport { ErrorHandling, ErrorSource } from '../error/error.types'\nimport { clocksNow } from '../../tools/utils/timeUtils'\nimport type { ReportType, InterventionReport, DeprecationReport } from './browser.types'\n\nexport const RawReportType = {\n  intervention: 'intervention',\n  deprecation: 'deprecation',\n  cspViolation: 'csp_violation',\n} as const\n\nexport type RawReportType = (typeof RawReportType)[keyof typeof RawReportType]\n\nexport type RawReportError = RawError & {\n  originalError: SecurityPolicyViolationEvent | DeprecationReport | InterventionReport\n}\n\nexport function initReportObservable(configuration: Configuration, apis: RawReportType[]) {\n  const observables: Array<Observable<RawReportError>> = []\n\n  if (apis.includes(RawReportType.cspViolation)) {\n    observables.push(createCspViolationReportObservable(configuration))\n  }\n\n  const reportTypes = apis.filter((api: RawReportType): api is ReportType => api !== RawReportType.cspViolation)\n  if (reportTypes.length) {\n    observables.push(createReportObservable(reportTypes))\n  }\n\n  return mergeObservables(...observables)\n}\n\nfunction createReportObservable(reportTypes: ReportType[]) {\n  return new Observable<RawReportError>((observable) => {\n    if (!window.ReportingObserver) {\n      return\n    }\n\n    const handleReports = monitor((reports: Array<DeprecationReport | InterventionReport>, _: ReportingObserver) =>\n      reports.forEach((report) => observable.notify(buildRawReportErrorFromReport(report)))\n    ) as ReportingObserverCallback\n\n    const observer = new window.ReportingObserver(handleReports, {\n      types: reportTypes,\n      buffered: true,\n    })\n\n    observer.observe()\n    return () => {\n      observer.disconnect()\n    }\n  })\n}\n\nfunction createCspViolationReportObservable(configuration: Configuration) {\n  return new Observable<RawReportError>((observable) => {\n    const { stop } = addEventListener(configuration, document, DOM_EVENT.SECURITY_POLICY_VIOLATION, (event) => {\n      observable.notify(buildRawReportErrorFromCspViolation(event))\n    })\n\n    return stop\n  })\n}\n\nfunction buildRawReportErrorFromReport(report: DeprecationReport | InterventionReport): RawReportError {\n  const { type, body } = report\n\n  return buildRawReportError({\n    type: body.id,\n    message: `${type}: ${body.message}`,\n    originalError: report,\n    stack: buildStack(body.id, body.message, body.sourceFile, body.lineNumber, body.columnNumber),\n  })\n}\n\nfunction buildRawReportErrorFromCspViolation(event: SecurityPolicyViolationEvent): RawReportError {\n  const message = `'${event.blockedURI}' blocked by '${event.effectiveDirective}' directive`\n  return buildRawReportError({\n    type: event.effectiveDirective,\n    message: `${RawReportType.cspViolation}: ${message}`,\n    originalError: event,\n    csp: {\n      disposition: event.disposition,\n    },\n    stack: buildStack(\n      event.effectiveDirective,\n      event.originalPolicy\n        ? `${message} of the policy \"${safeTruncate(event.originalPolicy, 100, '...')}\"`\n        : 'no policy',\n      event.sourceFile,\n      event.lineNumber,\n      event.columnNumber\n    ),\n  })\n}\n\nfunction buildRawReportError(partial: Omit<RawReportError, 'startClocks' | 'source' | 'handling'>): RawReportError {\n  return {\n    startClocks: clocksNow(),\n    source: ErrorSource.REPORT,\n    handling: ErrorHandling.UNHANDLED,\n    ...partial,\n  }\n}\n\nfunction buildStack(\n  name: string,\n  message: string,\n  sourceFile: string | null,\n  lineNumber: number | null,\n  columnNumber: number | null\n): string | undefined {\n  return sourceFile\n    ? toStackTraceString({\n        name,\n        message,\n        stack: [\n          {\n            func: '?',\n            url: sourceFile,\n            line: lineNumber ?? undefined,\n            column: columnNumber ?? undefined,\n          },\n        ],\n      })\n    : undefined\n}\n"
  },
  {
    "path": "packages/core/src/domain/resourceUtils.ts",
    "content": "export const ResourceType = {\n  DOCUMENT: 'document',\n  XHR: 'xhr',\n  BEACON: 'beacon',\n  FETCH: 'fetch',\n  CSS: 'css',\n  JS: 'js',\n  IMAGE: 'image',\n  FONT: 'font',\n  MEDIA: 'media',\n  OTHER: 'other',\n} as const\n\nexport type ResourceType = (typeof ResourceType)[keyof typeof ResourceType]\n\nexport const RequestType = {\n  FETCH: ResourceType.FETCH,\n  XHR: ResourceType.XHR,\n} as const\n\nexport type RequestType = (typeof RequestType)[keyof typeof RequestType]\n"
  },
  {
    "path": "packages/core/src/domain/session/README.md",
    "content": "## possible states:\n\n| state                   | value                                                        |\n| ----------------------- | ------------------------------------------------------------ |\n| NotStarted<sup>\\*</sup> | `{}`                                                         |\n| Expired                 | `{expired: '1'}` or `expire >  15 minutes` or `created > 4H` |\n| Tracked                 | `{id: 'xxxx-xx-xx}`                                          |\n| NotTracked              | `{rum: 0}` or `{logs: 0}`                                    |\n\n(<sup>\\*</sup>) `NotStarted` is a state that can happen in a few different ways:\n\n- First load of the page if there is no cookie present already\n- After the cookie has been deleted by a 3rd party (user, ad blocker, ...)\n- After the cookie has expired (it is deleted by the browser)\n\nOther terminology:\n\n- A _started_ session is a session that is either `Expired`, `Tracked`, or `NotTracked`.\n- An _active_ session is a session that is either `Tracked` or `NotTracked`.\n\n## start session\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\nstate fork_state2 <<fork>>\n\n[*] --> fork_state\n\nfork_state --> NotStarted\nfork_state --> Expired\nfork_state --> Tracked\nfork_state --> NotTracked\nNotStarted --> Expired: startSession()\n\nExpired --> fork_state2\nTracked --> fork_state2\nNotTracked --> fork_state2\nfork_state2 --> [*]: expandOrRenew()\n```\n\n## On User Activity\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\n\n[*] --> fork_state\n\nfork_state --> [*]: expandOrRenew()\n```\n\n## On Visibility Change\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\nstate visibility <<choice>>\n\n[*] --> visibility: VisibilityChange\n\nvisibility --> [*]: hidden\nvisibility --> fork_state : visible\n\nfork_state --> [*]: extendOrExpire()\n```\n\n## On resume from frozen state\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\nstate fork_state2 <<fork>>\n\n[*] --> fork_state: Resume\n\nfork_state --> NotStarted\nfork_state --> Expired\nfork_state --> Tracked\nfork_state --> NotTracked\n\nNotStarted --> Expired: restartSession()\nExpired --> fork_state2\nTracked --> fork_state2\nNotTracked --> fork_state2\n\nfork_state2 --> [*]: extendOrExpire()\n```\n\n## Watch (every second)\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\n\n\n[*] --> fork_state\nfork_state --> [*]: extendOrExpire()\n```\n\n## 3rd party cookie clearing\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\nstate join_state <<join>>\nNotStarted2: NotStarted\n\n[*] --> fork_state\n\nfork_state --> NotStarted\nfork_state --> Expired\nfork_state --> Tracked\nfork_state --> NotTracked\n\nExpired --> join_state\nTracked --> join_state\nNotTracked --> join_state\nNotStarted --> join_state\n\njoin_state --> NotStarted2 : clearCookies()\n\nNotStarted2 --> [*]\n```\n\n## Expand Or Renew\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\nstate fork_state2 <<fork>>\nstate fork_state3 <<fork>>\n\n\nstate expandOrRenew() {\n  [*] --> fork_state: expandOrRenew()\n  Tracked2: Tracked\n  NotTracked2: NotTracked\n\n  fork_state --> NotStarted\n  fork_state --> Expired\n  fork_state --> Tracked\n  fork_state --> NotTracked\n\n  NotStarted --> [*]\n\n  Expired --> fork_state2: renew()\n  Tracked --> fork_state2: extend()\n  NotTracked --> fork_state2: extend()\n\n  fork_state2 --> fork_state3: computeTrackingType()\n\n  fork_state3 --> Tracked2\n  fork_state3 --> NotTracked2\n\n  Tracked2 --> [*]\n  NotTracked2 --> [*]\n}\n```\n\n> [!NOTE]  \n> Because `computeTrackingType()` happens at every `expandOrRenew()`, it is in theory possible to switch from `Tracked` to `NotTracked` and vice versa within an active session. However, this is not expected to happen in practice at this time.\n\n## Extend Or Expire\n\n```mermaid\nstateDiagram-v2\nstate fork_state <<fork>>\n\nstate extendOrExpire() {\n  [*] --> fork_state : extendOrExpire()\n  Tracked2: Tracked\n  NotTracked2: NotTracked\n  Expired2: Expired\n\n  fork_state --> NotStarted\n  fork_state --> Expired\n  fork_state --> Tracked\n  fork_state --> NotTracked\n\n  Tracked --> Tracked2: extend()\n  NotTracked --> NotTracked2: extend()\n  Expired --> Expired2: expire()\n\n  NotStarted --> [*]\n  Tracked2 --> [*]\n  NotTracked2 --> [*]\n  Expired2 --> [*]\n}\n```\n\n> [!NOTE]  \n> Because a session time out can result in an `Expired` state, `expire()` explicitly normalizes the state to `isExpired=1`\n"
  },
  {
    "path": "packages/core/src/domain/session/oldCookiesMigration.spec.ts",
    "content": "import { getCookie, resetInitCookies, setCookie } from '../../browser/cookie'\nimport { getSessionState } from '../../../test'\nimport type { Configuration } from '../configuration'\nimport {\n  OLD_LOGS_COOKIE_NAME,\n  OLD_RUM_COOKIE_NAME,\n  OLD_SESSION_COOKIE_NAME,\n  tryOldCookiesMigration,\n} from './oldCookiesMigration'\nimport { SESSION_EXPIRATION_DELAY } from './sessionConstants'\nimport { initCookieStrategy } from './storeStrategies/sessionInCookie'\nimport type { SessionStoreStrategy } from './storeStrategies/sessionStoreStrategy'\nimport { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'\nconst DEFAULT_INIT_CONFIGURATION = { trackAnonymousUser: true } as Configuration\n\ndescribe('old cookies migration', () => {\n  let sessionStoreStrategy: SessionStoreStrategy\n\n  beforeEach(() => {\n    sessionStoreStrategy = initCookieStrategy(DEFAULT_INIT_CONFIGURATION, {})\n    resetInitCookies()\n  })\n\n  afterEach(() => {\n    resetInitCookies()\n  })\n\n  it('should not touch current cookie', () => {\n    setCookie(SESSION_STORE_KEY, 'id=abcde&rum=0&logs=1&expire=1234567890', SESSION_EXPIRATION_DELAY)\n\n    tryOldCookiesMigration(sessionStoreStrategy)\n\n    expect(getCookie(SESSION_STORE_KEY)).toBe('id=abcde&rum=0&logs=1&expire=1234567890')\n  })\n\n  it('should create new cookie from old cookie values', () => {\n    setCookie(OLD_SESSION_COOKIE_NAME, 'abcde', SESSION_EXPIRATION_DELAY)\n    setCookie(OLD_LOGS_COOKIE_NAME, '1', SESSION_EXPIRATION_DELAY)\n    setCookie(OLD_RUM_COOKIE_NAME, '0', SESSION_EXPIRATION_DELAY)\n\n    tryOldCookiesMigration(sessionStoreStrategy)\n\n    expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde')\n    expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0')\n    expect(getSessionState(SESSION_STORE_KEY).logs).toBe('1')\n    expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\\d+/)\n  })\n\n  it('should create new cookie from a single old cookie', () => {\n    setCookie(OLD_RUM_COOKIE_NAME, '0', SESSION_EXPIRATION_DELAY)\n\n    tryOldCookiesMigration(sessionStoreStrategy)\n    expect(getSessionState(SESSION_STORE_KEY).id).not.toBeDefined()\n    expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0')\n    expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\\d+/)\n  })\n\n  it('should not create a new cookie if no old cookie is present', () => {\n    tryOldCookiesMigration(sessionStoreStrategy)\n    expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n  })\n\n  it('should behave correctly when performing the migration multiple times', () => {\n    setCookie(OLD_SESSION_COOKIE_NAME, 'abcde', SESSION_EXPIRATION_DELAY)\n    setCookie(OLD_LOGS_COOKIE_NAME, '1', SESSION_EXPIRATION_DELAY)\n    setCookie(OLD_RUM_COOKIE_NAME, '0', SESSION_EXPIRATION_DELAY)\n\n    tryOldCookiesMigration(sessionStoreStrategy)\n    tryOldCookiesMigration(sessionStoreStrategy)\n\n    expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcde')\n    expect(getSessionState(SESSION_STORE_KEY).rum).toBe('0')\n    expect(getSessionState(SESSION_STORE_KEY).logs).toBe('1')\n    expect(getSessionState(SESSION_STORE_KEY).expire).toMatch(/\\d+/)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/oldCookiesMigration.ts",
    "content": "import { getInitCookie } from '../../browser/cookie'\nimport type { SessionStoreStrategy } from './storeStrategies/sessionStoreStrategy'\nimport { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'\nimport type { SessionState } from './sessionState'\nimport { expandSessionState, isSessionStarted } from './sessionState'\n\nexport const OLD_SESSION_COOKIE_NAME = '_dd'\nexport const OLD_RUM_COOKIE_NAME = '_dd_r'\nexport const OLD_LOGS_COOKIE_NAME = '_dd_l'\n\n// duplicate values to avoid dependency issues\nexport const RUM_SESSION_KEY = 'rum'\nexport const LOGS_SESSION_KEY = 'logs'\n\n/**\n * This migration should remain in the codebase as long as older versions are available/live\n * to allow older sdk versions to be upgraded to newer versions without compatibility issues.\n */\nexport function tryOldCookiesMigration(cookieStoreStrategy: SessionStoreStrategy) {\n  const sessionString = getInitCookie(SESSION_STORE_KEY)\n  if (!sessionString) {\n    const oldSessionId = getInitCookie(OLD_SESSION_COOKIE_NAME)\n    const oldRumType = getInitCookie(OLD_RUM_COOKIE_NAME)\n    const oldLogsType = getInitCookie(OLD_LOGS_COOKIE_NAME)\n    const session: SessionState = {}\n\n    if (oldSessionId) {\n      session.id = oldSessionId\n    }\n    if (oldLogsType && /^[01]$/.test(oldLogsType)) {\n      session[LOGS_SESSION_KEY] = oldLogsType\n    }\n    if (oldRumType && /^[012]$/.test(oldRumType)) {\n      session[RUM_SESSION_KEY] = oldRumType\n    }\n\n    if (isSessionStarted(session)) {\n      expandSessionState(session)\n      cookieStoreStrategy.persistSession(session)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionConstants.ts",
    "content": "import { ONE_HOUR, ONE_MINUTE, ONE_YEAR } from '../../tools/utils/timeUtils'\n\nexport const SESSION_TIME_OUT_DELAY = 4 * ONE_HOUR\nexport const SESSION_EXPIRATION_DELAY = 15 * ONE_MINUTE\nexport const SESSION_COOKIE_EXPIRATION_DELAY = ONE_YEAR\nexport const SESSION_NOT_TRACKED = '0'\n\n/**\n * @internal\n */\nexport const SessionPersistence = {\n  COOKIE: 'cookie',\n  MEMORY: 'memory',\n  LOCAL_STORAGE: 'local-storage',\n} as const\n\n/**\n * @inline\n */\nexport type SessionPersistence = (typeof SessionPersistence)[keyof typeof SessionPersistence]\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionManager.spec.ts",
    "content": "import {\n  createNewEvent,\n  expireCookie,\n  getSessionState,\n  mockClock,\n  registerCleanupTask,\n  restorePageVisibility,\n  setPageVisibility,\n} from '../../../test'\nimport type { Clock } from '../../../test'\nimport { getCookie, setCookie } from '../../browser/cookie'\nimport { DOM_EVENT } from '../../browser/addEventListener'\nimport { ONE_HOUR, ONE_SECOND } from '../../tools/utils/timeUtils'\nimport type { Configuration } from '../configuration'\nimport type { TrackingConsentState } from '../trackingConsent'\nimport { TrackingConsent, createTrackingConsentState } from '../trackingConsent'\nimport type { SessionManager } from './sessionManager'\nimport { startSessionManager, stopSessionManager, VISIBILITY_CHECK_DELAY } from './sessionManager'\nimport {\n  SESSION_EXPIRATION_DELAY,\n  SESSION_NOT_TRACKED,\n  SESSION_TIME_OUT_DELAY,\n  SessionPersistence,\n} from './sessionConstants'\nimport type { SessionStoreStrategyType } from './storeStrategies/sessionStoreStrategy'\nimport { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'\nimport { STORAGE_POLL_DELAY } from './sessionStore'\n\nconst enum FakeTrackingType {\n  NOT_TRACKED = SESSION_NOT_TRACKED,\n  TRACKED = 'tracked',\n}\n\ndescribe('startSessionManager', () => {\n  const DURATION = 123456\n  const FIRST_PRODUCT_KEY = 'first'\n  const SECOND_PRODUCT_KEY = 'second'\n  const STORE_TYPE: SessionStoreStrategyType = { type: SessionPersistence.COOKIE, cookieOptions: {} }\n  let clock: Clock\n\n  function expireSessionCookie() {\n    expireCookie()\n    clock.tick(STORAGE_POLL_DELAY)\n  }\n\n  function deleteSessionCookie() {\n    setCookie(SESSION_STORE_KEY, '', DURATION)\n    clock.tick(STORAGE_POLL_DELAY)\n  }\n\n  function expectSessionIdToBe(sessionManager: SessionManager<FakeTrackingType>, sessionId: string) {\n    expect(sessionManager.findSession()!.id).toBe(sessionId)\n    expect(getSessionState(SESSION_STORE_KEY).id).toBe(sessionId)\n  }\n\n  function expectSessionIdToBeDefined(sessionManager: SessionManager<FakeTrackingType>) {\n    expect(sessionManager.findSession()!.id).toMatch(/^[a-f0-9-]+$/)\n    expect(sessionManager.findSession()?.isExpired).toBeUndefined()\n\n    expect(getSessionState(SESSION_STORE_KEY).id).toMatch(/^[a-f0-9-]+$/)\n    expect(getSessionState(SESSION_STORE_KEY).isExpired).toBeUndefined()\n  }\n\n  function expectSessionToBeExpired(sessionManager: SessionManager<FakeTrackingType>) {\n    expect(sessionManager.findSession()).toBeUndefined()\n    expect(getSessionState(SESSION_STORE_KEY).isExpired).toBe('1')\n  }\n\n  function expectSessionIdToNotBeDefined(sessionManager: SessionManager<FakeTrackingType>) {\n    expect(sessionManager.findSession()!.id).toBeUndefined()\n    expect(getSessionState(SESSION_STORE_KEY).id).toBeUndefined()\n  }\n\n  function expectTrackingTypeToBe(\n    sessionManager: SessionManager<FakeTrackingType>,\n    productKey: string,\n    trackingType: FakeTrackingType\n  ) {\n    expect(sessionManager.findSession()!.trackingType).toEqual(trackingType)\n    expect(getSessionState(SESSION_STORE_KEY)[productKey]).toEqual(trackingType)\n  }\n\n  function expectTrackingTypeToNotBeDefined(sessionManager: SessionManager<FakeTrackingType>, productKey: string) {\n    expect(sessionManager.findSession()?.trackingType).toBeUndefined()\n    expect(getSessionState(SESSION_STORE_KEY)[productKey]).toBeUndefined()\n  }\n\n  beforeEach(() => {\n    clock = mockClock()\n\n    registerCleanupTask(() => {\n      // remove intervals first\n      stopSessionManager()\n      // flush pending callbacks to avoid random failures\n      clock.tick(ONE_HOUR)\n    })\n  })\n\n  describe('resume from a frozen tab ', () => {\n    it('when session in store, do nothing', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&first=tracked', DURATION)\n      const sessionManager = startSessionManagerWithDefaults()\n\n      window.dispatchEvent(createNewEvent(DOM_EVENT.RESUME))\n\n      expectSessionIdToBe(sessionManager, 'abcdef')\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.TRACKED)\n    })\n\n    it('when session not in store, reinitialize a session in store', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n\n      deleteSessionCookie()\n\n      expect(sessionManager.findSession()).toBeUndefined()\n      expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n\n      window.dispatchEvent(createNewEvent(DOM_EVENT.RESUME))\n\n      expectSessionToBeExpired(sessionManager)\n    })\n  })\n\n  describe('cookie management', () => {\n    it('when tracked, should store tracking type and session id', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n\n      expectSessionIdToBeDefined(sessionManager)\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.TRACKED)\n    })\n\n    it('when not tracked should store tracking type', () => {\n      const sessionManager = startSessionManagerWithDefaults({\n        computeTrackingType: () => FakeTrackingType.NOT_TRACKED,\n      })\n\n      expectSessionIdToNotBeDefined(sessionManager)\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.NOT_TRACKED)\n    })\n\n    it('when tracked should keep existing tracking type and session id', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&first=tracked', DURATION)\n\n      const sessionManager = startSessionManagerWithDefaults()\n\n      expectSessionIdToBe(sessionManager, 'abcdef')\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.TRACKED)\n    })\n\n    it('when not tracked should keep existing tracking type', () => {\n      setCookie(SESSION_STORE_KEY, `first=${SESSION_NOT_TRACKED}`, DURATION)\n\n      const sessionManager = startSessionManagerWithDefaults({\n        computeTrackingType: () => FakeTrackingType.NOT_TRACKED,\n      })\n\n      expectSessionIdToNotBeDefined(sessionManager)\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.NOT_TRACKED)\n    })\n  })\n\n  describe('computeTrackingType', () => {\n    let spy: (rawTrackingType?: string) => FakeTrackingType\n\n    beforeEach(() => {\n      spy = jasmine.createSpy().and.returnValue(FakeTrackingType.TRACKED)\n    })\n\n    it('should be called with an empty value if the cookie is not defined', () => {\n      startSessionManagerWithDefaults({ computeTrackingType: spy })\n      expect(spy).toHaveBeenCalledWith(undefined)\n    })\n\n    it('should be called with an invalid value if the cookie has an invalid value', () => {\n      setCookie(SESSION_STORE_KEY, 'first=invalid', DURATION)\n      startSessionManagerWithDefaults({ computeTrackingType: spy })\n      expect(spy).toHaveBeenCalledWith('invalid')\n    })\n\n    it('should be called with TRACKED', () => {\n      setCookie(SESSION_STORE_KEY, 'first=tracked', DURATION)\n      startSessionManagerWithDefaults({ computeTrackingType: spy })\n      expect(spy).toHaveBeenCalledWith(FakeTrackingType.TRACKED)\n    })\n\n    it('should be called with NOT_TRACKED', () => {\n      setCookie(SESSION_STORE_KEY, `first=${SESSION_NOT_TRACKED}`, DURATION)\n      startSessionManagerWithDefaults({ computeTrackingType: spy })\n      expect(spy).toHaveBeenCalledWith(FakeTrackingType.NOT_TRACKED)\n    })\n  })\n\n  describe('session renewal', () => {\n    it('should renew on activity after expiration', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const renewSessionSpy = jasmine.createSpy()\n      sessionManager.renewObservable.subscribe(renewSessionSpy)\n\n      expireSessionCookie()\n\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n\n      expectSessionToBeExpired(sessionManager)\n      expectTrackingTypeToNotBeDefined(sessionManager, FIRST_PRODUCT_KEY)\n\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      expect(renewSessionSpy).toHaveBeenCalled()\n      expectSessionIdToBeDefined(sessionManager)\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.TRACKED)\n    })\n\n    it('should not renew on visibility after expiration', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const renewSessionSpy = jasmine.createSpy()\n      sessionManager.renewObservable.subscribe(renewSessionSpy)\n\n      expireSessionCookie()\n\n      clock.tick(VISIBILITY_CHECK_DELAY)\n\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      expectSessionToBeExpired(sessionManager)\n    })\n\n    it('should not renew on activity if cookie is deleted by a 3rd party', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const renewSessionSpy = jasmine.createSpy('renewSessionSpy')\n      sessionManager.renewObservable.subscribe(renewSessionSpy)\n\n      deleteSessionCookie()\n\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n\n      expect(sessionManager.findSession()).toBeUndefined()\n      expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      expect(sessionManager.findSession()).toBeUndefined()\n      expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n    })\n  })\n\n  describe('multiple startSessionManager calls', () => {\n    it('should re-use the same session id', () => {\n      const firstSessionManager = startSessionManagerWithDefaults({ productKey: FIRST_PRODUCT_KEY })\n      const idA = firstSessionManager.findSession()!.id\n\n      const secondSessionManager = startSessionManagerWithDefaults({ productKey: SECOND_PRODUCT_KEY })\n      const idB = secondSessionManager.findSession()!.id\n\n      expect(idA).toBe(idB)\n    })\n\n    it('should not erase other session type', () => {\n      startSessionManagerWithDefaults({ productKey: FIRST_PRODUCT_KEY })\n\n      // schedule an expandOrRenewSession\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      clock.tick(STORAGE_POLL_DELAY / 2)\n\n      // expand first session cookie cache\n      document.dispatchEvent(createNewEvent(DOM_EVENT.VISIBILITY_CHANGE))\n\n      startSessionManagerWithDefaults({ productKey: SECOND_PRODUCT_KEY })\n\n      // cookie correctly set\n      expect(getSessionState(SESSION_STORE_KEY).first).toBeDefined()\n      expect(getSessionState(SESSION_STORE_KEY).second).toBeDefined()\n\n      clock.tick(STORAGE_POLL_DELAY / 2)\n\n      // scheduled expandOrRenewSession should not use cached value\n      expect(getSessionState(SESSION_STORE_KEY).first).toBeDefined()\n      expect(getSessionState(SESSION_STORE_KEY).second).toBeDefined()\n    })\n\n    it('should have independent tracking types', () => {\n      const firstSessionManager = startSessionManagerWithDefaults({\n        productKey: FIRST_PRODUCT_KEY,\n        computeTrackingType: () => FakeTrackingType.TRACKED,\n      })\n      const secondSessionManager = startSessionManagerWithDefaults({\n        productKey: SECOND_PRODUCT_KEY,\n        computeTrackingType: () => FakeTrackingType.NOT_TRACKED,\n      })\n\n      expect(firstSessionManager.findSession()!.trackingType).toEqual(FakeTrackingType.TRACKED)\n      expect(secondSessionManager.findSession()!.trackingType).toEqual(FakeTrackingType.NOT_TRACKED)\n    })\n\n    it('should notify each expire and renew observables', () => {\n      const firstSessionManager = startSessionManagerWithDefaults({ productKey: FIRST_PRODUCT_KEY })\n      const expireSessionASpy = jasmine.createSpy()\n      firstSessionManager.expireObservable.subscribe(expireSessionASpy)\n      const renewSessionASpy = jasmine.createSpy()\n      firstSessionManager.renewObservable.subscribe(renewSessionASpy)\n\n      const secondSessionManager = startSessionManagerWithDefaults({ productKey: SECOND_PRODUCT_KEY })\n      const expireSessionBSpy = jasmine.createSpy()\n      secondSessionManager.expireObservable.subscribe(expireSessionBSpy)\n      const renewSessionBSpy = jasmine.createSpy()\n      secondSessionManager.renewObservable.subscribe(renewSessionBSpy)\n\n      expireSessionCookie()\n\n      expect(expireSessionASpy).toHaveBeenCalled()\n      expect(expireSessionBSpy).toHaveBeenCalled()\n      expect(renewSessionASpy).not.toHaveBeenCalled()\n      expect(renewSessionBSpy).not.toHaveBeenCalled()\n\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      expect(renewSessionASpy).toHaveBeenCalled()\n      expect(renewSessionBSpy).toHaveBeenCalled()\n    })\n  })\n\n  describe('session timeout', () => {\n    it('should expire the session when the time out delay is reached', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      expect(sessionManager.findSession()).toBeDefined()\n      expect(getCookie(SESSION_STORE_KEY)).toBeDefined()\n\n      clock.tick(SESSION_TIME_OUT_DELAY)\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n\n    it('should renew an existing timed out session', () => {\n      setCookie(SESSION_STORE_KEY, `id=abcde&first=tracked&created=${Date.now() - SESSION_TIME_OUT_DELAY}`, DURATION)\n\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      expect(sessionManager.findSession()!.id).not.toBe('abcde')\n      expect(getSessionState(SESSION_STORE_KEY).created).toEqual(Date.now().toString())\n      expect(expireSessionSpy).not.toHaveBeenCalled() // the session has not been active from the start\n    })\n\n    it('should not add created date to an existing session from an older versions', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcde&first=tracked', DURATION)\n\n      const sessionManager = startSessionManagerWithDefaults()\n\n      expect(sessionManager.findSession()!.id).toBe('abcde')\n      expect(getSessionState(SESSION_STORE_KEY).created).toBeUndefined()\n    })\n  })\n\n  describe('automatic session expiration', () => {\n    beforeEach(() => {\n      setPageVisibility('hidden')\n    })\n\n    afterEach(() => {\n      restorePageVisibility()\n    })\n\n    it('should expire the session after expiration delay', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      expectSessionIdToBeDefined(sessionManager)\n\n      clock.tick(SESSION_EXPIRATION_DELAY)\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n\n    it('should expand duration on activity', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      expectSessionIdToBeDefined(sessionManager)\n\n      clock.tick(SESSION_EXPIRATION_DELAY - 10)\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      clock.tick(10)\n      expectSessionIdToBeDefined(sessionManager)\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n\n      clock.tick(SESSION_EXPIRATION_DELAY)\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n\n    it('should expand not tracked session duration on activity', () => {\n      const sessionManager = startSessionManagerWithDefaults({\n        computeTrackingType: () => FakeTrackingType.NOT_TRACKED,\n      })\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.NOT_TRACKED)\n\n      clock.tick(SESSION_EXPIRATION_DELAY - 10)\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      clock.tick(10)\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.NOT_TRACKED)\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n\n      clock.tick(SESSION_EXPIRATION_DELAY)\n      expectTrackingTypeToNotBeDefined(sessionManager, FIRST_PRODUCT_KEY)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n\n    it('should expand session on visibility', () => {\n      setPageVisibility('visible')\n\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      clock.tick(3 * VISIBILITY_CHECK_DELAY)\n      setPageVisibility('hidden')\n      expectSessionIdToBeDefined(sessionManager)\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n\n      clock.tick(SESSION_EXPIRATION_DELAY - 10)\n      expectSessionIdToBeDefined(sessionManager)\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n\n      clock.tick(10)\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n\n    it('should expand not tracked session on visibility', () => {\n      setPageVisibility('visible')\n\n      const sessionManager = startSessionManagerWithDefaults({\n        computeTrackingType: () => FakeTrackingType.NOT_TRACKED,\n      })\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      clock.tick(3 * VISIBILITY_CHECK_DELAY)\n      setPageVisibility('hidden')\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.NOT_TRACKED)\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n\n      clock.tick(SESSION_EXPIRATION_DELAY - 10)\n      expectTrackingTypeToBe(sessionManager, FIRST_PRODUCT_KEY, FakeTrackingType.NOT_TRACKED)\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n\n      clock.tick(10)\n      expectTrackingTypeToNotBeDefined(sessionManager, FIRST_PRODUCT_KEY)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n  })\n\n  describe('manual session expiration', () => {\n    it('expires the session when calling expire()', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      sessionManager.expire()\n\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalled()\n    })\n\n    it('notifies expired session only once when calling expire() multiple times', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      sessionManager.expire()\n      sessionManager.expire()\n\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('notifies expired session only once when calling expire() after the session has been expired', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      const expireSessionSpy = jasmine.createSpy()\n      sessionManager.expireObservable.subscribe(expireSessionSpy)\n\n      clock.tick(SESSION_EXPIRATION_DELAY)\n      sessionManager.expire()\n\n      expectSessionToBeExpired(sessionManager)\n      expect(expireSessionSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('renew the session on user activity', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      clock.tick(STORAGE_POLL_DELAY)\n\n      sessionManager.expire()\n\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      expectSessionIdToBeDefined(sessionManager)\n    })\n  })\n\n  describe('session history', () => {\n    it('should return undefined when there is no current session and no startTime', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      expireSessionCookie()\n\n      expect(sessionManager.findSession()).toBeUndefined()\n    })\n\n    it('should return the current session context when there is no start time', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n\n      expect(sessionManager.findSession()!.id).toBeDefined()\n      expect(sessionManager.findSession()!.trackingType).toBeDefined()\n    })\n\n    it('should return the session context corresponding to startTime', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n\n      // 0s to 10s: first session\n      clock.tick(10 * ONE_SECOND - STORAGE_POLL_DELAY)\n      const firstSessionId = sessionManager.findSession()!.id\n      const firstSessionTrackingType = sessionManager.findSession()!.trackingType\n      expireSessionCookie()\n\n      // 10s to 20s: no session\n      clock.tick(10 * ONE_SECOND)\n\n      // 20s to end: second session\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n      clock.tick(10 * ONE_SECOND)\n      const secondSessionId = sessionManager.findSession()!.id\n      const secondSessionTrackingType = sessionManager.findSession()!.trackingType\n\n      expect(sessionManager.findSession(clock.relative(5 * ONE_SECOND))!.id).toBe(firstSessionId)\n      expect(sessionManager.findSession(clock.relative(5 * ONE_SECOND))!.trackingType).toBe(firstSessionTrackingType)\n      expect(sessionManager.findSession(clock.relative(15 * ONE_SECOND))).toBeUndefined()\n      expect(sessionManager.findSession(clock.relative(25 * ONE_SECOND))!.id).toBe(secondSessionId)\n      expect(sessionManager.findSession(clock.relative(25 * ONE_SECOND))!.trackingType).toBe(secondSessionTrackingType)\n    })\n\n    describe('option `returnInactive` is true', () => {\n      it('should return the session context even when the session is expired', () => {\n        const sessionManager = startSessionManagerWithDefaults()\n\n        // 0s to 10s: first session\n        clock.tick(10 * ONE_SECOND - STORAGE_POLL_DELAY)\n\n        expireSessionCookie()\n\n        // 10s to 20s: no session\n        clock.tick(10 * ONE_SECOND)\n\n        expect(sessionManager.findSession(clock.relative(15 * ONE_SECOND), { returnInactive: true })).toBeDefined()\n\n        expect(sessionManager.findSession(clock.relative(15 * ONE_SECOND), { returnInactive: false })).toBeUndefined()\n      })\n    })\n\n    it('should return the current session context in the renewObservable callback', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      let currentSession\n      sessionManager.renewObservable.subscribe(() => (currentSession = sessionManager.findSession()))\n\n      // new session\n      expireSessionCookie()\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n      clock.tick(STORAGE_POLL_DELAY)\n\n      expect(currentSession).toBeDefined()\n    })\n\n    it('should return the current session context in the expireObservable callback', () => {\n      const sessionManager = startSessionManagerWithDefaults()\n      let currentSession\n      sessionManager.expireObservable.subscribe(() => (currentSession = sessionManager.findSession()))\n\n      // new session\n      expireSessionCookie()\n      clock.tick(STORAGE_POLL_DELAY)\n\n      expect(currentSession).toBeDefined()\n    })\n  })\n\n  describe('tracking consent', () => {\n    it('expires the session when tracking consent is withdrawn', () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n      const sessionManager = startSessionManagerWithDefaults({ trackingConsentState })\n\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n\n      expectSessionToBeExpired(sessionManager)\n      expect(getSessionState(SESSION_STORE_KEY).isExpired).toBe('1')\n    })\n\n    it('does not renew the session when tracking consent is withdrawn', () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n      const sessionManager = startSessionManagerWithDefaults({ trackingConsentState })\n\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      expectSessionToBeExpired(sessionManager)\n    })\n\n    it('renews the session when tracking consent is granted', () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n      const sessionManager = startSessionManagerWithDefaults({ trackingConsentState })\n      const initialSessionId = sessionManager.findSession()!.id\n\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n\n      expectSessionToBeExpired(sessionManager)\n\n      trackingConsentState.update(TrackingConsent.GRANTED)\n\n      clock.tick(STORAGE_POLL_DELAY)\n\n      expectSessionIdToBeDefined(sessionManager)\n      expect(sessionManager.findSession()!.id).not.toBe(initialSessionId)\n    })\n\n    it('Remove anonymousId when tracking consent is withdrawn', () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n      const sessionManager = startSessionManagerWithDefaults({ trackingConsentState })\n      const session = sessionManager.findSession()!\n\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n\n      expect(session.anonymousId).toBeUndefined()\n    })\n  })\n\n  describe('session state update', () => {\n    it('should notify session manager update observable', () => {\n      const sessionStateUpdateSpy = jasmine.createSpy()\n      const sessionManager = startSessionManagerWithDefaults()\n      sessionManager.sessionStateUpdateObservable.subscribe(sessionStateUpdateSpy)\n\n      sessionManager.updateSessionState({ extra: 'extra' })\n\n      expectSessionIdToBeDefined(sessionManager)\n      expect(sessionStateUpdateSpy).toHaveBeenCalledTimes(1)\n\n      const callArgs = sessionStateUpdateSpy.calls.argsFor(0)[0]\n      expect(callArgs.previousState.extra).toBeUndefined()\n      expect(callArgs.newState.extra).toBe('extra')\n    })\n  })\n\n  function startSessionManagerWithDefaults({\n    configuration,\n    productKey = FIRST_PRODUCT_KEY,\n    computeTrackingType = () => FakeTrackingType.TRACKED,\n    trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED),\n  }: {\n    configuration?: Partial<Configuration>\n    productKey?: string\n    computeTrackingType?: () => FakeTrackingType\n    trackingConsentState?: TrackingConsentState\n  } = {}) {\n    return startSessionManager(\n      {\n        sessionStoreStrategyType: STORE_TYPE,\n        ...configuration,\n      } as Configuration,\n      productKey,\n      computeTrackingType,\n      trackingConsentState\n    )\n  }\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionManager.ts",
    "content": "import { Observable } from '../../tools/observable'\nimport type { Context } from '../../tools/serialisation/context'\nimport { createValueHistory } from '../../tools/valueHistory'\nimport type { RelativeTime } from '../../tools/utils/timeUtils'\nimport { clocksOrigin, ONE_MINUTE, relativeNow } from '../../tools/utils/timeUtils'\nimport { addEventListener, addEventListeners, DOM_EVENT } from '../../browser/addEventListener'\nimport { clearInterval, setInterval } from '../../tools/timer'\nimport type { Configuration } from '../configuration'\nimport type { TrackingConsentState } from '../trackingConsent'\nimport { addTelemetryDebug } from '../telemetry'\nimport { isSyntheticsTest } from '../synthetics/syntheticsWorkerValues'\nimport type { CookieStore } from '../../browser/browser.types'\nimport { getCurrentSite } from '../../browser/cookie'\nimport { SESSION_NOT_TRACKED, SESSION_TIME_OUT_DELAY, SessionPersistence } from './sessionConstants'\nimport { startSessionStore } from './sessionStore'\nimport type { SessionState } from './sessionState'\nimport { retrieveSessionCookie } from './storeStrategies/sessionInCookie'\nimport { SESSION_STORE_KEY } from './storeStrategies/sessionStoreStrategy'\nimport { retrieveSessionFromLocalStorage } from './storeStrategies/sessionInLocalStorage'\n\nexport interface SessionManager<TrackingType extends string> {\n  findSession: (\n    startTime?: RelativeTime,\n    options?: { returnInactive: boolean }\n  ) => SessionContext<TrackingType> | undefined\n  renewObservable: Observable<void>\n  expireObservable: Observable<void>\n  sessionStateUpdateObservable: Observable<{ previousState: SessionState; newState: SessionState }>\n  expire: () => void\n  updateSessionState: (state: Partial<SessionState>) => void\n}\n\nexport interface SessionContext<TrackingType extends string> extends Context {\n  id: string\n  trackingType: TrackingType\n  isReplayForced: boolean\n  anonymousId: string | undefined\n}\n\nexport const VISIBILITY_CHECK_DELAY = ONE_MINUTE\nconst SESSION_CONTEXT_TIMEOUT_DELAY = SESSION_TIME_OUT_DELAY\nlet stopCallbacks: Array<() => void> = []\n\nexport function startSessionManager<TrackingType extends string>(\n  configuration: Configuration,\n  productKey: string,\n  computeTrackingType: (rawTrackingType?: string) => TrackingType,\n  trackingConsentState: TrackingConsentState\n): SessionManager<TrackingType> {\n  const renewObservable = new Observable<void>()\n  const expireObservable = new Observable<void>()\n\n  // TODO - Improve configuration type and remove assertion\n  const sessionStore = startSessionStore(\n    configuration.sessionStoreStrategyType!,\n    configuration,\n    productKey,\n    computeTrackingType\n  )\n  stopCallbacks.push(() => sessionStore.stop())\n\n  const sessionContextHistory = createValueHistory<SessionContext<TrackingType>>({\n    expireDelay: SESSION_CONTEXT_TIMEOUT_DELAY,\n  })\n  stopCallbacks.push(() => sessionContextHistory.stop())\n\n  sessionStore.renewObservable.subscribe(() => {\n    sessionContextHistory.add(buildSessionContext(), relativeNow())\n    renewObservable.notify()\n  })\n  sessionStore.expireObservable.subscribe(() => {\n    expireObservable.notify()\n    sessionContextHistory.closeActive(relativeNow())\n  })\n\n  // We expand/renew session unconditionally as tracking consent is always granted when the session\n  // manager is started.\n  sessionStore.expandOrRenewSession()\n  sessionContextHistory.add(buildSessionContext(), clocksOrigin().relative)\n\n  trackingConsentState.observable.subscribe(() => {\n    if (trackingConsentState.isGranted()) {\n      sessionStore.expandOrRenewSession()\n    } else {\n      sessionStore.expire(false)\n    }\n  })\n\n  trackActivity(configuration, () => {\n    if (trackingConsentState.isGranted()) {\n      sessionStore.expandOrRenewSession()\n    }\n  })\n  trackVisibility(configuration, () => sessionStore.expandSession())\n  trackResume(configuration, () => sessionStore.restartSession())\n\n  function buildSessionContext() {\n    const session = sessionStore.getSession()\n\n    if (!session) {\n      reportUnexpectedSessionState(configuration).catch(() => void 0) // Ignore errors\n\n      return {\n        id: 'invalid',\n        trackingType: SESSION_NOT_TRACKED as TrackingType,\n        isReplayForced: false,\n        anonymousId: undefined,\n      }\n    }\n\n    return {\n      id: session.id!,\n      trackingType: session[productKey] as TrackingType,\n      isReplayForced: !!session.forcedReplay,\n      anonymousId: session.anonymousId,\n    }\n  }\n\n  return {\n    findSession: (startTime, options) => sessionContextHistory.find(startTime, options),\n    renewObservable,\n    expireObservable,\n    sessionStateUpdateObservable: sessionStore.sessionStateUpdateObservable,\n    expire: sessionStore.expire,\n    updateSessionState: sessionStore.updateSessionState,\n  }\n}\n\nexport function stopSessionManager() {\n  stopCallbacks.forEach((e) => e())\n  stopCallbacks = []\n}\n\nfunction trackActivity(configuration: Configuration, expandOrRenewSession: () => void) {\n  const { stop } = addEventListeners(\n    configuration,\n    window,\n    [DOM_EVENT.CLICK, DOM_EVENT.TOUCH_START, DOM_EVENT.KEY_DOWN, DOM_EVENT.SCROLL],\n    expandOrRenewSession,\n    { capture: true, passive: true }\n  )\n  stopCallbacks.push(stop)\n}\n\nfunction trackVisibility(configuration: Configuration, expandSession: () => void) {\n  const expandSessionWhenVisible = () => {\n    if (document.visibilityState === 'visible') {\n      expandSession()\n    }\n  }\n\n  const { stop } = addEventListener(configuration, document, DOM_EVENT.VISIBILITY_CHANGE, expandSessionWhenVisible)\n  stopCallbacks.push(stop)\n\n  const visibilityCheckInterval = setInterval(expandSessionWhenVisible, VISIBILITY_CHECK_DELAY)\n  stopCallbacks.push(() => {\n    clearInterval(visibilityCheckInterval)\n  })\n}\n\nfunction trackResume(configuration: Configuration, cb: () => void) {\n  const { stop } = addEventListener(configuration, window, DOM_EVENT.RESUME, cb, { capture: true })\n  stopCallbacks.push(stop)\n}\n\nasync function reportUnexpectedSessionState(configuration: Configuration) {\n  const sessionStoreStrategyType = configuration.sessionStoreStrategyType\n  if (!sessionStoreStrategyType) {\n    return\n  }\n\n  let rawSession\n  let cookieContext\n\n  if (sessionStoreStrategyType.type === SessionPersistence.COOKIE) {\n    rawSession = retrieveSessionCookie(sessionStoreStrategyType.cookieOptions, configuration)\n\n    cookieContext = {\n      cookie: await getSessionCookies(),\n      currentDomain: `${window.location.protocol}//${window.location.hostname}`,\n    }\n  } else {\n    rawSession = retrieveSessionFromLocalStorage()\n  }\n  // monitor-until: forever, could be handy to troubleshoot issues until session manager rework\n  addTelemetryDebug('Unexpected session state', {\n    sessionStoreStrategyType: sessionStoreStrategyType.type,\n    session: rawSession,\n    isSyntheticsTest: isSyntheticsTest(),\n    createdTimestamp: rawSession?.created,\n    expireTimestamp: rawSession?.expire,\n    ...cookieContext,\n  })\n}\n\nasync function getSessionCookies(): Promise<{ count: number; domain: string }> {\n  let sessionCookies: string[] | Awaited<ReturnType<CookieStore['getAll']>>\n  if ('cookieStore' in window) {\n    sessionCookies = await (window as { cookieStore: CookieStore }).cookieStore.getAll(SESSION_STORE_KEY)\n  } else {\n    sessionCookies = document.cookie.split(/\\s*;\\s*/).filter((cookie) => cookie.startsWith(SESSION_STORE_KEY))\n  }\n\n  return {\n    count: sessionCookies.length,\n    domain: getCurrentSite() || 'undefined',\n    ...sessionCookies,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionState.spec.ts",
    "content": "import { dateNow } from '../../tools/utils/timeUtils'\nimport { SESSION_EXPIRATION_DELAY, SESSION_NOT_TRACKED } from './sessionConstants'\nimport type { SessionState } from './sessionState'\nimport {\n  expandSessionState,\n  isSessionInExpiredState,\n  toSessionString,\n  toSessionState,\n  isSessionInNotStartedState,\n} from './sessionState'\n\ndescribe('session state utilities', () => {\n  const NOT_STARTED_SESSION: SessionState = {}\n  const SERIALIZED_NOT_STARTED_SESSION = ''\n  const EXPIRED_SESSION: SessionState = { isExpired: '1' }\n  const SERIALIZED_EXPIRED_SESSION = 'isExpired=1'\n  const LIVE_SESSION: SessionState = { id: '123', first: 'tracked' }\n  const SERIALIZED_LIVE_SESSION = 'id=123&first=tracked'\n\n  describe('isSessionStarted', () => {\n    it('should correctly identify a session in a started state', () => {\n      expect(isSessionInNotStartedState(LIVE_SESSION)).toBe(false)\n      expect(isSessionInNotStartedState(EXPIRED_SESSION)).toBe(false)\n    })\n\n    it('should correctly identify a session in a not started state', () => {\n      expect(isSessionInNotStartedState(NOT_STARTED_SESSION)).toBe(true)\n    })\n  })\n\n  describe('isSessionInExpiredState', () => {\n    function dateNowWithOffset(offset = 0) {\n      return String(dateNow() + offset)\n    }\n\n    it('should correctly identify a session in expired state', () => {\n      expect(isSessionInExpiredState(EXPIRED_SESSION)).toBe(true)\n      expect(isSessionInExpiredState({ created: dateNowWithOffset(-1000 * 60 * 60 * 4) })).toBe(true)\n      expect(isSessionInExpiredState({ expire: dateNowWithOffset(-100) })).toBe(true)\n    })\n\n    it('should correctly identify a session in live state', () => {\n      expect(isSessionInExpiredState({ created: dateNowWithOffset(-1000), expire: dateNowWithOffset(1000) })).toBe(\n        false\n      )\n      expect(isSessionInExpiredState({ first: SESSION_NOT_TRACKED })).toBe(false)\n      expect(isSessionInExpiredState({ first: 'tracked' })).toBe(false)\n    })\n  })\n\n  describe('toSessionString', () => {\n    it('should serialize a sessionState to a string', () => {\n      expect(toSessionString(LIVE_SESSION)).toEqual(SERIALIZED_LIVE_SESSION)\n    })\n\n    it('should handle empty sessionStates', () => {\n      expect(toSessionString(EXPIRED_SESSION)).toEqual(SERIALIZED_EXPIRED_SESSION)\n    })\n  })\n\n  describe('sessionStringToSessionState', () => {\n    it('should deserialize a session string to a sessionState', () => {\n      expect(toSessionState(SERIALIZED_LIVE_SESSION)).toEqual(LIVE_SESSION)\n    })\n\n    it('should handle empty session strings', () => {\n      expect(toSessionState(SERIALIZED_NOT_STARTED_SESSION)).toEqual(NOT_STARTED_SESSION)\n    })\n\n    it('should handle expired session', () => {\n      expect(toSessionState(SERIALIZED_EXPIRED_SESSION)).toEqual(EXPIRED_SESSION)\n    })\n\n    it('should handle invalid session strings', () => {\n      const sessionString = '{invalid: true}'\n      expect(toSessionState(sessionString)).toEqual(NOT_STARTED_SESSION)\n    })\n  })\n\n  describe('expandSessionState', () => {\n    it('should modify the expire property of the session', () => {\n      const session = { ...LIVE_SESSION }\n      const now = dateNow()\n      expandSessionState(session)\n      expect(session.expire).toBeGreaterThanOrEqual(now + SESSION_EXPIRATION_DELAY)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionState.ts",
    "content": "import { isEmptyObject } from '../../tools/utils/objectUtils'\nimport { objectEntries } from '../../tools/utils/polyfills'\nimport { dateNow } from '../../tools/utils/timeUtils'\nimport type { Configuration } from '../configuration'\nimport { SESSION_EXPIRATION_DELAY, SESSION_TIME_OUT_DELAY } from './sessionConstants'\nimport { isValidSessionString, SESSION_ENTRY_REGEXP, SESSION_ENTRY_SEPARATOR } from './sessionStateValidation'\nexport const EXPIRED = '1'\n\nexport interface SessionState {\n  id?: string\n  created?: string\n  expire?: string\n  isExpired?: typeof EXPIRED\n\n  [key: string]: string | undefined\n}\n\nexport function getExpiredSessionState(\n  previousSessionState: SessionState | undefined,\n  configuration: Configuration\n): SessionState {\n  const expiredSessionState: SessionState = {\n    isExpired: EXPIRED,\n  }\n  if (configuration.trackAnonymousUser && previousSessionState?.anonymousId) {\n    expiredSessionState.anonymousId = previousSessionState?.anonymousId\n  }\n  return expiredSessionState\n}\n\nexport function isSessionInNotStartedState(session: SessionState) {\n  return isEmptyObject(session)\n}\n\nexport function isSessionStarted(session: SessionState) {\n  return !isSessionInNotStartedState(session)\n}\n\nexport function isSessionInExpiredState(session: SessionState) {\n  return session.isExpired !== undefined || !isActiveSession(session)\n}\n\n// An active session is a session in either `Tracked` or `NotTracked` state\nfunction isActiveSession(sessionState: SessionState) {\n  // created and expire can be undefined for versions which was not storing them\n  // these checks could be removed when older versions will not be available/live anymore\n  return (\n    (sessionState.created === undefined || dateNow() - Number(sessionState.created) < SESSION_TIME_OUT_DELAY) &&\n    (sessionState.expire === undefined || dateNow() < Number(sessionState.expire))\n  )\n}\n\nexport function expandSessionState(session: SessionState) {\n  session.expire = String(dateNow() + SESSION_EXPIRATION_DELAY)\n}\n\nexport function toSessionString(session: SessionState) {\n  return (\n    objectEntries(session)\n      // we use `aid` as a key for anonymousId\n      .map(([key, value]) => (key === 'anonymousId' ? `aid=${value}` : `${key}=${value}`))\n      .join(SESSION_ENTRY_SEPARATOR)\n  )\n}\n\nexport function toSessionState(sessionString: string | undefined | null) {\n  const session: SessionState = {}\n  if (isValidSessionString(sessionString)) {\n    sessionString.split(SESSION_ENTRY_SEPARATOR).forEach((entry) => {\n      const matches = SESSION_ENTRY_REGEXP.exec(entry)\n      if (matches !== null) {\n        const [, key, value] = matches\n        if (key === 'aid') {\n          // we use `aid` as a key for anonymousId\n          session.anonymousId = value\n        } else {\n          session[key] = value\n        }\n      }\n    })\n  }\n  return session\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionStateValidation.ts",
    "content": "export const SESSION_ENTRY_REGEXP = /^([a-zA-Z]+)=([a-z0-9-]+)$/\nexport const SESSION_ENTRY_SEPARATOR = '&'\n\nexport function isValidSessionString(sessionString: string | undefined | null): sessionString is string {\n  return (\n    !!sessionString &&\n    (sessionString.indexOf(SESSION_ENTRY_SEPARATOR) !== -1 || SESSION_ENTRY_REGEXP.test(sessionString))\n  )\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionStore.spec.ts",
    "content": "import type { Clock } from '../../../test'\nimport { mockClock, createFakeSessionStoreStrategy } from '../../../test'\nimport type { InitConfiguration, Configuration } from '../configuration'\nimport { display } from '../../tools/display'\nimport type { SessionStore } from './sessionStore'\nimport { STORAGE_POLL_DELAY, startSessionStore, selectSessionStoreStrategyType } from './sessionStore'\nimport {\n  SESSION_EXPIRATION_DELAY,\n  SESSION_NOT_TRACKED,\n  SESSION_TIME_OUT_DELAY,\n  SessionPersistence,\n} from './sessionConstants'\nimport type { SessionState } from './sessionState'\n\nconst enum FakeTrackingType {\n  TRACKED = 'tracked',\n  NOT_TRACKED = SESSION_NOT_TRACKED,\n}\n\nconst PRODUCT_KEY = 'product'\nconst FIRST_ID = 'first'\nconst SECOND_ID = 'second'\nconst IS_EXPIRED = '1'\nconst DEFAULT_INIT_CONFIGURATION: InitConfiguration = { clientToken: 'abc' }\nconst DEFAULT_CONFIGURATION = { trackAnonymousUser: true } as Configuration\n\nconst EMPTY_SESSION_STATE: SessionState = {}\n\nfunction createSessionState(\n  trackingType: FakeTrackingType = FakeTrackingType.TRACKED,\n  id?: string,\n  expire?: number\n): SessionState {\n  return {\n    [PRODUCT_KEY]: trackingType,\n    created: `${Date.now()}`,\n    expire: `${expire || Date.now() + SESSION_EXPIRATION_DELAY}`,\n    ...(id ? { id } : {}),\n  }\n}\n\nlet sessionStoreStrategy: ReturnType<typeof createFakeSessionStoreStrategy>\n\nfunction getSessionStoreState(): SessionState {\n  return sessionStoreStrategy.retrieveSession()\n}\n\nfunction expectTrackedSessionToBeInStore(id?: string) {\n  expect(getSessionStoreState().id).toEqual(id ? id : jasmine.any(String))\n  expect(getSessionStoreState().isExpired).toBeUndefined()\n  expect(getSessionStoreState()[PRODUCT_KEY]).toEqual(FakeTrackingType.TRACKED)\n}\n\nfunction expectNotTrackedSessionToBeInStore() {\n  expect(getSessionStoreState().id).toBeUndefined()\n  expect(getSessionStoreState().isExpired).toBeUndefined()\n  expect(getSessionStoreState()[PRODUCT_KEY]).toEqual(FakeTrackingType.NOT_TRACKED)\n}\n\nfunction expectSessionToBeExpiredInStore() {\n  expect(getSessionStoreState().isExpired).toEqual(IS_EXPIRED)\n  expect(getSessionStoreState().id).toBeUndefined()\n  expect(getSessionStoreState()[PRODUCT_KEY]).toBeUndefined()\n}\n\nfunction getStoreExpiration() {\n  return getSessionStoreState().expire\n}\n\nfunction resetSessionInStore() {\n  sessionStoreStrategy.expireSession()\n  sessionStoreStrategy.expireSession.calls.reset()\n}\n\nfunction setSessionInStore(sessionState: SessionState) {\n  sessionStoreStrategy.persistSession(sessionState)\n  sessionStoreStrategy.persistSession.calls.reset()\n}\n\ndescribe('session store', () => {\n  describe('selectSessionStoreStrategyType', () => {\n    describe('sessionPersistence: cookie (default)', () => {\n      it('returns cookie strategy when cookies are available', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType(DEFAULT_INIT_CONFIGURATION)\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.COOKIE }))\n      })\n\n      it('returns undefined when cookies are not available', () => {\n        disableCookies()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType(DEFAULT_INIT_CONFIGURATION)\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n\n      it('returns cookie strategy when sessionPersistence is cookie', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: SessionPersistence.COOKIE,\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.COOKIE }))\n      })\n    })\n\n    describe('sessionPersistence: local-storage', () => {\n      it('returns local storage strategy when sessionPersistence is local storage', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: SessionPersistence.LOCAL_STORAGE,\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.LOCAL_STORAGE }))\n      })\n\n      it('returns undefined when local storage is not available', () => {\n        disableLocalStorage()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: SessionPersistence.LOCAL_STORAGE,\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n    })\n\n    describe('sessionPersistence: memory', () => {\n      it('returns memory strategy when sessionPersistence is memory', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: SessionPersistence.MEMORY,\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.MEMORY }))\n      })\n    })\n\n    it('returns undefined when sessionPersistence is invalid', () => {\n      const displayErrorSpy = spyOn(display, 'error')\n\n      const sessionStoreStrategyType = selectSessionStoreStrategyType({\n        ...DEFAULT_INIT_CONFIGURATION,\n        sessionPersistence: 'invalid' as SessionPersistence,\n      })\n      expect(sessionStoreStrategyType).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith(\"Invalid session persistence 'invalid'\")\n    })\n\n    describe('sessionPersistence as array', () => {\n      it('returns the first available strategy from the array', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [SessionPersistence.COOKIE, SessionPersistence.LOCAL_STORAGE],\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.COOKIE }))\n      })\n\n      it('falls back to next strategy when first is unavailable', () => {\n        disableCookies()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [SessionPersistence.COOKIE, SessionPersistence.LOCAL_STORAGE],\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.LOCAL_STORAGE }))\n      })\n\n      it('falls back to memory when cookie and local storage are unavailable', () => {\n        disableCookies()\n        disableLocalStorage()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [SessionPersistence.COOKIE, SessionPersistence.LOCAL_STORAGE, SessionPersistence.MEMORY],\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.MEMORY }))\n      })\n\n      it('returns undefined when no strategy in array is available', () => {\n        disableCookies()\n        disableLocalStorage()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [SessionPersistence.COOKIE, SessionPersistence.LOCAL_STORAGE],\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n\n      it('handles empty array', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [],\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n\n      it('handles array with single element', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [SessionPersistence.LOCAL_STORAGE],\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.LOCAL_STORAGE }))\n      })\n\n      it('stops at first available strategy and does not try subsequent ones', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: [SessionPersistence.LOCAL_STORAGE, SessionPersistence.COOKIE],\n        })\n        // Should return local storage (first available), not cookie\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.LOCAL_STORAGE }))\n      })\n\n      it('returns undefined and logs error if array contains invalid persistence type', () => {\n        const displayErrorSpy = spyOn(display, 'error')\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: ['invalid' as SessionPersistence],\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n        expect(displayErrorSpy).toHaveBeenCalledOnceWith(\"Invalid session persistence 'invalid'\")\n      })\n    })\n\n    describe('allowFallbackToLocalStorage (deprecated)', () => {\n      it('should return a type cookie when cookies are available', () => {\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowFallbackToLocalStorage: true,\n        })\n        expect(sessionStoreStrategyType).toEqual(jasmine.objectContaining({ type: SessionPersistence.COOKIE }))\n      })\n\n      it('should report undefined when cookies are not available, and fallback is not allowed', () => {\n        disableCookies()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowFallbackToLocalStorage: false,\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n\n      it('should fallback to localStorage when cookies are not available', () => {\n        disableCookies()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowFallbackToLocalStorage: true,\n        })\n        expect(sessionStoreStrategyType).toEqual({ type: SessionPersistence.LOCAL_STORAGE })\n      })\n\n      it('should report undefined when no storage is available', () => {\n        disableLocalStorage()\n        disableCookies()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowFallbackToLocalStorage: true,\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n\n      it('does not fallback to localStorage when sessionPersistence is set to cookie', () => {\n        disableCookies()\n        const sessionStoreStrategyType = selectSessionStoreStrategyType({\n          ...DEFAULT_INIT_CONFIGURATION,\n          sessionPersistence: SessionPersistence.COOKIE,\n          allowFallbackToLocalStorage: true,\n        })\n        expect(sessionStoreStrategyType).toBeUndefined()\n      })\n    })\n\n    function disableCookies() {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('')\n    }\n    function disableLocalStorage() {\n      spyOn(Storage.prototype, 'getItem').and.throwError('unavailable')\n    }\n  })\n\n  describe('session lifecyle mechanism', () => {\n    let expireSpy: () => void\n    let renewSpy: () => void\n    let sessionStoreManager: SessionStore\n    let clock: Clock\n\n    function setupSessionStore(\n      initialState: SessionState = {},\n      computeTrackingType: (rawTrackingType?: string) => FakeTrackingType = () => FakeTrackingType.TRACKED\n    ) {\n      const sessionStoreStrategyType = selectSessionStoreStrategyType(DEFAULT_INIT_CONFIGURATION)\n      if (sessionStoreStrategyType?.type !== SessionPersistence.COOKIE) {\n        fail('Unable to initialize cookie storage')\n        return\n      }\n\n      sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: true, initialSession: initialState })\n\n      sessionStoreManager = startSessionStore(\n        sessionStoreStrategyType,\n        DEFAULT_CONFIGURATION,\n        PRODUCT_KEY,\n        computeTrackingType,\n        sessionStoreStrategy\n      )\n      sessionStoreStrategy.persistSession.calls.reset()\n      sessionStoreManager.expireObservable.subscribe(expireSpy)\n      sessionStoreManager.renewObservable.subscribe(renewSpy)\n    }\n\n    beforeEach(() => {\n      expireSpy = jasmine.createSpy('expire session')\n      renewSpy = jasmine.createSpy('renew session')\n      clock = mockClock()\n    })\n\n    afterEach(() => {\n      resetSessionInStore()\n      sessionStoreManager.stop()\n    })\n\n    describe('initialize session', () => {\n      it('when session not in store, should initialize a new session', () => {\n        setupSessionStore()\n        expect(sessionStoreManager.getSession().isExpired).toEqual(IS_EXPIRED)\n        expect(sessionStoreManager.getSession().anonymousId).toEqual(jasmine.any(String))\n      })\n\n      it('when tracked session in store, should do nothing ', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        expect(sessionStoreManager.getSession().id).toBe(FIRST_ID)\n        expect(sessionStoreManager.getSession().isExpired).toBeUndefined()\n        expect(sessionStoreManager.getSession()[PRODUCT_KEY]).toBeDefined()\n      })\n\n      it('when not tracked session in store, should do nothing ', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.NOT_TRACKED))\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(sessionStoreManager.getSession().isExpired).toBeUndefined()\n        expect(sessionStoreManager.getSession()[PRODUCT_KEY]).toBeDefined()\n      })\n\n      it('should generate an anonymousId if not present', () => {\n        setupSessionStore()\n        expect(sessionStoreManager.getSession().anonymousId).toBeDefined()\n      })\n    })\n\n    describe('expand or renew session', () => {\n      it(\n        'when session not in cache, session not in store and new session tracked, ' +\n          'should create new session and trigger renew session ',\n        () => {\n          setupSessionStore()\n\n          sessionStoreManager.expandOrRenewSession()\n\n          expect(sessionStoreManager.getSession().id).toBeDefined()\n          expectTrackedSessionToBeInStore()\n          expect(expireSpy).not.toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it(\n        'when session not in cache, session not in store and new session not tracked, ' +\n          'should store not tracked session and trigger renew session',\n        () => {\n          setupSessionStore(EMPTY_SESSION_STATE, () => FakeTrackingType.NOT_TRACKED)\n\n          sessionStoreManager.expandOrRenewSession()\n\n          expect(sessionStoreManager.getSession().id).toBeUndefined()\n          expectNotTrackedSessionToBeInStore()\n          expect(expireSpy).not.toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it('when session not in cache and session in store, should expand session and trigger renew session', () => {\n        setupSessionStore()\n        setSessionInStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        sessionStoreManager.expandOrRenewSession()\n\n        expect(sessionStoreManager.getSession().id).toBe(FIRST_ID)\n        expectTrackedSessionToBeInStore(FIRST_ID)\n        expect(expireSpy).not.toHaveBeenCalled()\n        expect(renewSpy).toHaveBeenCalledTimes(1)\n      })\n\n      it(\n        'when session in cache, session not in store and new session tracked, ' +\n          'should expire session, create a new one and trigger renew session',\n        () => {\n          setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n          resetSessionInStore()\n\n          sessionStoreManager.expandOrRenewSession()\n\n          const sessionId = sessionStoreManager.getSession().id\n          expect(sessionId).toBeDefined()\n          expect(sessionId).not.toBe(FIRST_ID)\n          expectTrackedSessionToBeInStore(sessionId)\n          expect(expireSpy).toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it(\n        'when session in cache, session not in store and new session not tracked, ' +\n          'should expire session, store not tracked session and trigger renew session',\n        () => {\n          setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID), () => FakeTrackingType.NOT_TRACKED)\n          resetSessionInStore()\n\n          sessionStoreManager.expandOrRenewSession()\n\n          expect(sessionStoreManager.getSession().id).toBeUndefined()\n          expect(sessionStoreManager.getSession()[PRODUCT_KEY]).toBeDefined()\n          expectNotTrackedSessionToBeInStore()\n          expect(expireSpy).toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it(\n        'when session not tracked in cache, session not in store and new session not tracked, ' +\n          'should expire session, store not tracked session and trigger renew session',\n        () => {\n          setupSessionStore(createSessionState(FakeTrackingType.NOT_TRACKED), () => FakeTrackingType.NOT_TRACKED)\n          resetSessionInStore()\n\n          sessionStoreManager.expandOrRenewSession()\n\n          expect(sessionStoreManager.getSession().id).toBeUndefined()\n          expect(sessionStoreManager.getSession()[PRODUCT_KEY]).toBeDefined()\n          expectNotTrackedSessionToBeInStore()\n          expect(expireSpy).toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it('when session in cache is same session than in store, should expand session', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        clock.tick(10)\n        sessionStoreManager.expandOrRenewSession()\n\n        expect(sessionStoreManager.getSession().id).toBe(FIRST_ID)\n        expect(sessionStoreManager.getSession().expire).toBe(getStoreExpiration())\n        expectTrackedSessionToBeInStore(FIRST_ID)\n        expect(expireSpy).not.toHaveBeenCalled()\n        expect(renewSpy).not.toHaveBeenCalled()\n      })\n\n      it(\n        'when session in cache is different session than in store and store session is tracked, ' +\n          'should expire session, expand store session and trigger renew',\n        () => {\n          setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n          setSessionInStore(createSessionState(FakeTrackingType.TRACKED, SECOND_ID))\n\n          sessionStoreManager.expandOrRenewSession()\n\n          expect(sessionStoreManager.getSession().id).toBe(SECOND_ID)\n          expectTrackedSessionToBeInStore(SECOND_ID)\n          expect(expireSpy).toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it(\n        'when session in cache is different session than in store and store session is not tracked, ' +\n          'should expire session, store not tracked session and trigger renew',\n        () => {\n          setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID), (rawTrackingType) =>\n            rawTrackingType === FakeTrackingType.TRACKED ? FakeTrackingType.TRACKED : FakeTrackingType.NOT_TRACKED\n          )\n          setSessionInStore(createSessionState(FakeTrackingType.NOT_TRACKED, ''))\n\n          sessionStoreManager.expandOrRenewSession()\n\n          expect(sessionStoreManager.getSession().id).toBeUndefined()\n          expectNotTrackedSessionToBeInStore()\n          expect(expireSpy).toHaveBeenCalled()\n          expect(renewSpy).toHaveBeenCalledTimes(1)\n        }\n      )\n\n      it('when throttled, expandOrRenewSession() should not renew the session if expire() is called right after', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        // The first call is not throttled (leading execution)\n        sessionStoreManager.expandOrRenewSession()\n\n        sessionStoreManager.expandOrRenewSession()\n        sessionStoreManager.expire()\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expectSessionToBeExpiredInStore()\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(renewSpy).not.toHaveBeenCalled()\n      })\n    })\n\n    describe('expand session', () => {\n      it('when session not in cache and session not in store, should do nothing', () => {\n        setupSessionStore()\n\n        sessionStoreManager.expandSession()\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).not.toHaveBeenCalled()\n      })\n\n      it('when session not in cache and session in store, should do nothing', () => {\n        setupSessionStore()\n        setSessionInStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        sessionStoreManager.expandSession()\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).not.toHaveBeenCalled()\n      })\n\n      it('when session in cache and session not in store, should expire session', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n        resetSessionInStore()\n\n        sessionStoreManager.expandSession()\n\n        expectSessionToBeExpiredInStore()\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).toHaveBeenCalled()\n      })\n\n      it('when session in cache is same session than in store, should expand session', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        clock.tick(10)\n        sessionStoreManager.expandSession()\n\n        expect(sessionStoreManager.getSession().id).toBe(FIRST_ID)\n        expect(sessionStoreManager.getSession().expire).toBe(getStoreExpiration())\n        expect(expireSpy).not.toHaveBeenCalled()\n      })\n\n      it('when session in cache is different session than in store, should expire session', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n        setSessionInStore(createSessionState(FakeTrackingType.TRACKED, SECOND_ID))\n\n        sessionStoreManager.expandSession()\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expectTrackedSessionToBeInStore(SECOND_ID)\n        expect(expireSpy).toHaveBeenCalled()\n      })\n    })\n\n    describe('regular watch', () => {\n      it('when session not in cache and session not in store, should store the expired session', () => {\n        setupSessionStore()\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expectSessionToBeExpiredInStore()\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).not.toHaveBeenCalled()\n        expect(sessionStoreStrategy.persistSession).toHaveBeenCalled()\n      })\n\n      it('when session in cache and session not in store, should expire session', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n        resetSessionInStore()\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expectSessionToBeExpiredInStore()\n        expect(expireSpy).toHaveBeenCalled()\n        expect(sessionStoreStrategy.persistSession).toHaveBeenCalled()\n      })\n\n      it('when session not in cache and session in store, should do nothing', () => {\n        setupSessionStore()\n        setSessionInStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).not.toHaveBeenCalled()\n        expect(sessionStoreStrategy.persistSession).not.toHaveBeenCalled()\n      })\n\n      it('when session in cache is same session than in store, should synchronize session', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n        setSessionInStore(\n          createSessionState(FakeTrackingType.TRACKED, FIRST_ID, Date.now() + SESSION_TIME_OUT_DELAY + 10)\n        )\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expect(sessionStoreManager.getSession().id).toBe(FIRST_ID)\n        expect(sessionStoreManager.getSession().expire).toBe(getStoreExpiration())\n        expect(expireSpy).not.toHaveBeenCalled()\n        expect(sessionStoreStrategy.persistSession).not.toHaveBeenCalled()\n      })\n\n      it('when session id in cache is different than session id in store, should expire session and not touch the store', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n        setSessionInStore(createSessionState(FakeTrackingType.TRACKED, SECOND_ID))\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).toHaveBeenCalled()\n        expect(sessionStoreStrategy.persistSession).not.toHaveBeenCalled()\n      })\n\n      it('when session in store is expired first and then get updated by another tab, should expire session in cache and not touch the store', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n        resetSessionInStore()\n\n        // Simulate a new session being written to the store by another tab during the watch.\n        // Watch is reading the cookie twice so we need to plan the write of the cookie at the right index\n        sessionStoreStrategy.planRetrieveSession(1, createSessionState(FakeTrackingType.TRACKED, SECOND_ID))\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        // expires session in cache\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).toHaveBeenCalled()\n\n        // Does not touch the store\n        // The two calls to persist session are for the lock management, these can be ignored\n        expect(sessionStoreStrategy.persistSession).toHaveBeenCalledTimes(2)\n        expect(sessionStoreStrategy.expireSession).not.toHaveBeenCalled()\n      })\n\n      it('when session type in cache is different than session type in store, should expire session and not touch the store', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.NOT_TRACKED, FIRST_ID))\n        setSessionInStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        clock.tick(STORAGE_POLL_DELAY)\n\n        expect(sessionStoreManager.getSession().id).toBeUndefined()\n        expect(expireSpy).toHaveBeenCalled()\n        expect(sessionStoreStrategy.persistSession).not.toHaveBeenCalled()\n      })\n    })\n\n    describe('reinitialize session', () => {\n      it('when session not in store, should reinitialize the store', () => {\n        setupSessionStore()\n\n        sessionStoreManager.restartSession()\n\n        expect(sessionStoreManager.getSession().isExpired).toEqual(IS_EXPIRED)\n        expect(sessionStoreManager.getSession().anonymousId).toEqual(jasmine.any(String))\n      })\n\n      it('when session in store, should do nothing', () => {\n        setupSessionStore(createSessionState(FakeTrackingType.TRACKED, FIRST_ID))\n\n        sessionStoreManager.restartSession()\n\n        expect(sessionStoreManager.getSession().id).toBe(FIRST_ID)\n        expect(sessionStoreManager.getSession().isExpired).toBeUndefined()\n      })\n\n      it('restart session should generate an anonymousId if not present', () => {\n        setupSessionStore()\n        sessionStoreManager.restartSession()\n        expect(sessionStoreManager.getSession().anonymousId).toBeDefined()\n      })\n    })\n  })\n\n  describe('session update and synchronisation', () => {\n    let updateSpy: jasmine.Spy<jasmine.Func>\n    let otherUpdateSpy: jasmine.Spy<jasmine.Func>\n    let clock: Clock\n\n    function setupSessionStore(initialState: SessionState = {}, updateSpy: () => void) {\n      const computeTrackingType: (rawTrackingType?: string) => FakeTrackingType = () => FakeTrackingType.TRACKED\n      const sessionStoreStrategyType = selectSessionStoreStrategyType(DEFAULT_INIT_CONFIGURATION)\n\n      sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: true, initialSession: initialState })\n\n      const sessionStoreManager = startSessionStore(\n        sessionStoreStrategyType!,\n        DEFAULT_CONFIGURATION,\n        PRODUCT_KEY,\n        computeTrackingType,\n        sessionStoreStrategy\n      )\n      sessionStoreManager.sessionStateUpdateObservable.subscribe(updateSpy)\n\n      return sessionStoreManager\n    }\n\n    let sessionStoreManager: SessionStore\n    let otherSessionStoreManager: SessionStore\n\n    beforeEach(() => {\n      updateSpy = jasmine.createSpy()\n      otherUpdateSpy = jasmine.createSpy()\n      clock = mockClock()\n    })\n\n    afterEach(() => {\n      resetSessionInStore()\n      sessionStoreManager.stop()\n      otherSessionStoreManager.stop()\n    })\n\n    it('should synchronise all stores and notify update observables of all stores', () => {\n      const initialState = createSessionState(FakeTrackingType.TRACKED, FIRST_ID)\n      sessionStoreManager = setupSessionStore(initialState, updateSpy)\n      otherSessionStoreManager = setupSessionStore(initialState, otherUpdateSpy)\n\n      sessionStoreManager.updateSessionState({ extra: 'extra' })\n\n      expect(updateSpy).toHaveBeenCalledTimes(1)\n\n      const callArgs = updateSpy.calls.argsFor(0)[0]\n      expect(callArgs!.previousState.extra).toBeUndefined()\n      expect(callArgs.newState.extra).toBe('extra')\n\n      // Need to wait until watch is triggered\n      clock.tick(STORAGE_POLL_DELAY)\n      expect(otherUpdateSpy).toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionStore.ts",
    "content": "import { clearInterval, setInterval } from '../../tools/timer'\nimport { Observable } from '../../tools/observable'\nimport { ONE_SECOND, dateNow } from '../../tools/utils/timeUtils'\nimport { throttle } from '../../tools/utils/functionUtils'\nimport { generateUUID } from '../../tools/utils/stringUtils'\nimport type { InitConfiguration, Configuration } from '../configuration'\nimport { display } from '../../tools/display'\nimport { selectCookieStrategy, initCookieStrategy } from './storeStrategies/sessionInCookie'\nimport type { SessionStoreStrategy, SessionStoreStrategyType } from './storeStrategies/sessionStoreStrategy'\nimport type { SessionState } from './sessionState'\nimport {\n  getExpiredSessionState,\n  isSessionInExpiredState,\n  isSessionInNotStartedState,\n  isSessionStarted,\n} from './sessionState'\nimport { initLocalStorageStrategy, selectLocalStorageStrategy } from './storeStrategies/sessionInLocalStorage'\nimport { processSessionStoreOperations } from './sessionStoreOperations'\nimport { SESSION_NOT_TRACKED, SessionPersistence } from './sessionConstants'\nimport { initMemorySessionStoreStrategy, selectMemorySessionStoreStrategy } from './storeStrategies/sessionInMemory'\n\nexport interface SessionStore {\n  expandOrRenewSession: () => void\n  expandSession: () => void\n  getSession: () => SessionState\n  restartSession: () => void\n  renewObservable: Observable<void>\n  expireObservable: Observable<void>\n  sessionStateUpdateObservable: Observable<{ previousState: SessionState; newState: SessionState }>\n  expire: (hasConsent?: boolean) => void\n  stop: () => void\n  updateSessionState: (state: Partial<SessionState>) => void\n}\n\n/**\n * Every second, the storage will be polled to check for any change that can occur\n * to the session state in another browser tab, or another window.\n * This value has been determined from our previous cookie-only implementation.\n */\nexport const STORAGE_POLL_DELAY = ONE_SECOND\n\n/**\n * Selects the correct session store strategy type based on the configuration and storage\n * availability. When an array is provided, tries each persistence type in order until one\n * successfully initializes.\n */\nexport function selectSessionStoreStrategyType(\n  initConfiguration: InitConfiguration\n): SessionStoreStrategyType | undefined {\n  const { sessionPersistence } = initConfiguration\n\n  const persistenceList = normalizePersistenceList(sessionPersistence, initConfiguration)\n\n  for (const persistence of persistenceList) {\n    const strategyType = selectStrategyForPersistence(persistence, initConfiguration)\n    if (strategyType !== undefined) {\n      return strategyType\n    }\n  }\n\n  return undefined\n}\n\nfunction normalizePersistenceList(\n  sessionPersistence: SessionPersistence | SessionPersistence[] | undefined,\n  initConfiguration: InitConfiguration\n): SessionPersistence[] {\n  if (Array.isArray(sessionPersistence)) {\n    return sessionPersistence\n  }\n\n  if (sessionPersistence !== undefined) {\n    return [sessionPersistence]\n  }\n\n  // Legacy default behavior: cookie first, with optional localStorage fallback\n  return initConfiguration.allowFallbackToLocalStorage\n    ? [SessionPersistence.COOKIE, SessionPersistence.LOCAL_STORAGE]\n    : [SessionPersistence.COOKIE]\n}\n\nfunction selectStrategyForPersistence(\n  persistence: SessionPersistence,\n  initConfiguration: InitConfiguration\n): SessionStoreStrategyType | undefined {\n  switch (persistence) {\n    case SessionPersistence.COOKIE:\n      return selectCookieStrategy(initConfiguration)\n\n    case SessionPersistence.LOCAL_STORAGE:\n      return selectLocalStorageStrategy()\n\n    case SessionPersistence.MEMORY:\n      return selectMemorySessionStoreStrategy()\n\n    default:\n      display.error(`Invalid session persistence '${String(persistence)}'`)\n      return undefined\n  }\n}\n\nexport function getSessionStoreStrategy(\n  sessionStoreStrategyType: SessionStoreStrategyType,\n  configuration: Configuration\n) {\n  return sessionStoreStrategyType.type === SessionPersistence.COOKIE\n    ? initCookieStrategy(configuration, sessionStoreStrategyType.cookieOptions)\n    : sessionStoreStrategyType.type === SessionPersistence.LOCAL_STORAGE\n      ? initLocalStorageStrategy(configuration)\n      : initMemorySessionStoreStrategy(configuration)\n}\n\n/**\n * Different session concepts:\n * - tracked, the session has an id and is updated along the user navigation\n * - not tracked, the session does not have an id but it is updated along the user navigation\n * - inactive, no session in store or session expired, waiting for a renew session\n */\nexport function startSessionStore<TrackingType extends string>(\n  sessionStoreStrategyType: SessionStoreStrategyType,\n  configuration: Configuration,\n  productKey: string,\n  computeTrackingType: (rawTrackingType?: string) => TrackingType,\n  sessionStoreStrategy: SessionStoreStrategy = getSessionStoreStrategy(sessionStoreStrategyType, configuration)\n): SessionStore {\n  const renewObservable = new Observable<void>()\n  const expireObservable = new Observable<void>()\n  const sessionStateUpdateObservable = new Observable<{ previousState: SessionState; newState: SessionState }>()\n\n  const watchSessionTimeoutId = setInterval(watchSession, STORAGE_POLL_DELAY)\n  let sessionCache: SessionState\n\n  startSession()\n\n  const { throttled: throttledExpandOrRenewSession, cancel: cancelExpandOrRenewSession } = throttle(() => {\n    processSessionStoreOperations(\n      {\n        process: (sessionState) => {\n          if (isSessionInNotStartedState(sessionState)) {\n            return\n          }\n\n          const synchronizedSession = synchronizeSession(sessionState)\n          expandOrRenewSessionState(synchronizedSession)\n          return synchronizedSession\n        },\n        after: (sessionState) => {\n          if (isSessionStarted(sessionState) && !hasSessionInCache()) {\n            renewSessionInCache(sessionState)\n          }\n          sessionCache = sessionState\n        },\n      },\n      sessionStoreStrategy\n    )\n  }, STORAGE_POLL_DELAY)\n\n  function expandSession() {\n    processSessionStoreOperations(\n      {\n        process: (sessionState) => (hasSessionInCache() ? synchronizeSession(sessionState) : undefined),\n      },\n      sessionStoreStrategy\n    )\n  }\n\n  /**\n   * allows two behaviors:\n   * - if the session is active, synchronize the session cache without updating the session store\n   * - if the session is not active, clear the session store and expire the session cache\n   */\n  function watchSession() {\n    const sessionState = sessionStoreStrategy.retrieveSession()\n\n    if (isSessionInExpiredState(sessionState)) {\n      processSessionStoreOperations(\n        {\n          process: (sessionState: SessionState) =>\n            isSessionInExpiredState(sessionState) ? getExpiredSessionState(sessionState, configuration) : undefined,\n          after: synchronizeSession,\n        },\n        sessionStoreStrategy\n      )\n    } else {\n      synchronizeSession(sessionState)\n    }\n  }\n\n  function synchronizeSession(sessionState: SessionState) {\n    if (isSessionInExpiredState(sessionState)) {\n      sessionState = getExpiredSessionState(sessionState, configuration)\n    }\n    if (hasSessionInCache()) {\n      if (isSessionInCacheOutdated(sessionState)) {\n        expireSessionInCache()\n      } else {\n        sessionStateUpdateObservable.notify({ previousState: sessionCache, newState: sessionState })\n        sessionCache = sessionState\n      }\n    }\n    return sessionState\n  }\n\n  function startSession() {\n    processSessionStoreOperations(\n      {\n        process: (sessionState) => {\n          if (isSessionInNotStartedState(sessionState)) {\n            sessionState.anonymousId = generateUUID()\n            return getExpiredSessionState(sessionState, configuration)\n          }\n        },\n        after: (sessionState) => {\n          sessionCache = sessionState\n        },\n      },\n      sessionStoreStrategy\n    )\n  }\n\n  function expandOrRenewSessionState(sessionState: SessionState) {\n    if (isSessionInNotStartedState(sessionState)) {\n      return false\n    }\n\n    const trackingType = computeTrackingType(sessionState[productKey])\n    sessionState[productKey] = trackingType\n    delete sessionState.isExpired\n    if (trackingType !== SESSION_NOT_TRACKED && !sessionState.id) {\n      sessionState.id = generateUUID()\n      sessionState.created = String(dateNow())\n    }\n    if (configuration.trackAnonymousUser && !sessionState.anonymousId) {\n      sessionState.anonymousId = generateUUID()\n    }\n  }\n\n  function hasSessionInCache() {\n    return sessionCache?.[productKey] !== undefined\n  }\n\n  function isSessionInCacheOutdated(sessionState: SessionState) {\n    return sessionCache.id !== sessionState.id || sessionCache[productKey] !== sessionState[productKey]\n  }\n\n  function expireSessionInCache() {\n    sessionCache = getExpiredSessionState(sessionCache, configuration)\n    expireObservable.notify()\n  }\n\n  function renewSessionInCache(sessionState: SessionState) {\n    sessionCache = sessionState\n    renewObservable.notify()\n  }\n\n  function updateSessionState(partialSessionState: Partial<SessionState>) {\n    processSessionStoreOperations(\n      {\n        process: (sessionState) => ({ ...sessionState, ...partialSessionState }),\n        after: synchronizeSession,\n      },\n      sessionStoreStrategy\n    )\n  }\n\n  return {\n    expandOrRenewSession: throttledExpandOrRenewSession,\n    expandSession,\n    getSession: () => sessionCache,\n    renewObservable,\n    expireObservable,\n    sessionStateUpdateObservable,\n    restartSession: startSession,\n    expire: (hasConsent?: boolean) => {\n      cancelExpandOrRenewSession()\n      if (hasConsent === false && sessionCache) {\n        delete sessionCache.anonymousId\n      }\n      sessionStoreStrategy.expireSession(sessionCache)\n      synchronizeSession(getExpiredSessionState(sessionCache, configuration))\n    },\n    stop: () => {\n      clearInterval(watchSessionTimeoutId)\n    },\n    updateSessionState,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionStoreOperations.spec.ts",
    "content": "import { createFakeSessionStoreStrategy, mockClock } from '../../../test'\nimport type { SessionState } from './sessionState'\nimport { expandSessionState } from './sessionState'\nimport {\n  processSessionStoreOperations,\n  LOCK_MAX_TRIES,\n  LOCK_RETRY_DELAY,\n  createLock,\n  LOCK_EXPIRATION_DELAY,\n} from './sessionStoreOperations'\n\nconst EXPIRED_SESSION: SessionState = { isExpired: '1', anonymousId: '0' }\n\ndescribe('sessionStoreOperations', () => {\n  let initialSession: SessionState\n  let otherSession: SessionState\n  let processSpy: jasmine.Spy<jasmine.Func>\n  let afterSpy: jasmine.Spy<jasmine.Func>\n  const now = Date.now()\n\n  beforeEach(() => {\n    initialSession = { id: '123', created: String(now) }\n    otherSession = { id: '456', created: String(now + 100) }\n    processSpy = jasmine.createSpy('process')\n    afterSpy = jasmine.createSpy('after')\n  })\n\n  describe('with lock access disabled', () => {\n    it('should persist session when process returns a value', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: false, initialSession })\n      processSpy.and.returnValue({ ...otherSession })\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n      const expectedSession = { ...otherSession, expire: jasmine.any(String) }\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(expectedSession)\n      expect(afterSpy).toHaveBeenCalledWith(expectedSession)\n    })\n\n    it('should clear session when process returns an expired session', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: false, initialSession })\n      processSpy.and.returnValue(EXPIRED_SESSION)\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(EXPIRED_SESSION)\n      expect(afterSpy).toHaveBeenCalledWith(EXPIRED_SESSION)\n    })\n\n    it('should not persist session when process returns undefined', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: false, initialSession })\n      processSpy.and.returnValue(undefined)\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(initialSession)\n      expect(afterSpy).toHaveBeenCalledWith(initialSession)\n    })\n\n    it('LOCK_MAX_TRIES value should not influence the behavior when lock mechanism is not enabled', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: false, initialSession })\n      processSpy.and.returnValue({ ...otherSession })\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy, LOCK_MAX_TRIES)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n      const expectedSession = { ...otherSession, expire: jasmine.any(String) }\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(expectedSession)\n      expect(afterSpy).toHaveBeenCalledWith(expectedSession)\n    })\n  })\n\n  describe('with lock access enabled', () => {\n    it('should persist session when process returns a value', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: true, initialSession })\n      processSpy.and.returnValue({ ...otherSession })\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n      const expectedSession = { ...otherSession, expire: jasmine.any(String) }\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(expectedSession)\n      expect(afterSpy).toHaveBeenCalledWith(expectedSession)\n    })\n\n    it('should clear session when process returns an expired session', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: true, initialSession })\n      processSpy.and.returnValue(EXPIRED_SESSION)\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(EXPIRED_SESSION)\n      expect(afterSpy).toHaveBeenCalledWith(EXPIRED_SESSION)\n    })\n\n    it('should not persist session when process returns undefined', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: true, initialSession })\n      processSpy.and.returnValue(undefined)\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      expect(processSpy).toHaveBeenCalledWith(initialSession)\n      expect(sessionStoreStrategy.retrieveSession()).toEqual(initialSession)\n      expect(afterSpy).toHaveBeenCalledWith(initialSession)\n    })\n    ;[\n      {\n        description: 'should wait for lock to be free',\n        lockConflictOnRetrievedSessionIndex: 0,\n      },\n      {\n        description: 'should retry if lock was acquired before process',\n        lockConflictOnRetrievedSessionIndex: 1,\n      },\n      {\n        description: 'should retry if lock was acquired after process',\n        lockConflictOnRetrievedSessionIndex: 2,\n      },\n      {\n        description: 'should retry if lock was acquired after persist',\n        lockConflictOnRetrievedSessionIndex: 3,\n      },\n    ].forEach(({ description, lockConflictOnRetrievedSessionIndex }) => {\n      it(description, (done) => {\n        expandSessionState(initialSession)\n        const sessionStoreStrategy = createFakeSessionStoreStrategy({ isLockEnabled: true, initialSession })\n        sessionStoreStrategy.planRetrieveSession(lockConflictOnRetrievedSessionIndex, {\n          ...initialSession,\n          lock: createLock(),\n        })\n        sessionStoreStrategy.planRetrieveSession(lockConflictOnRetrievedSessionIndex + 1, {\n          ...initialSession,\n          other: 'other',\n        })\n        processSpy.and.callFake((session) => ({ ...session, processed: 'processed' }) as SessionState)\n\n        processSessionStoreOperations(\n          {\n            process: processSpy,\n            after: (afterSession) => {\n              // session with 'other' value on process\n              expect(processSpy).toHaveBeenCalledWith({\n                ...initialSession,\n                other: 'other',\n                expire: jasmine.any(String),\n              })\n\n              // end state with session 'other' and 'processed' value\n              const expectedSession = {\n                ...initialSession,\n                other: 'other',\n                processed: 'processed',\n                expire: jasmine.any(String),\n              }\n              expect(sessionStoreStrategy.retrieveSession()).toEqual(expectedSession)\n              expect(afterSession).toEqual(expectedSession)\n              done()\n            },\n          },\n          sessionStoreStrategy\n        )\n      })\n    })\n\n    it('should abort after a max number of retry', () => {\n      const clock = mockClock()\n\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({\n        isLockEnabled: true,\n        initialSession: { ...initialSession, lock: createLock() },\n      })\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n\n      clock.tick(LOCK_MAX_TRIES * LOCK_RETRY_DELAY)\n      expect(processSpy).not.toHaveBeenCalled()\n      expect(afterSpy).not.toHaveBeenCalled()\n      expect(sessionStoreStrategy.persistSession).not.toHaveBeenCalled()\n    })\n\n    it('should execute cookie accesses in order', (done) => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({\n        isLockEnabled: true,\n        initialSession: { ...initialSession, lock: createLock() },\n      })\n      sessionStoreStrategy.planRetrieveSession(1, initialSession)\n\n      processSessionStoreOperations(\n        {\n          process: (session) => ({ ...session, value: 'foo' }),\n          after: afterSpy,\n        },\n        sessionStoreStrategy\n      )\n      processSessionStoreOperations(\n        {\n          process: (session) => ({ ...session, value: `${session.value || ''}bar` }),\n          after: (session) => {\n            expect(session.value).toBe('foobar')\n            expect(afterSpy).toHaveBeenCalled()\n            done()\n          },\n        },\n        sessionStoreStrategy\n      )\n    })\n\n    it('ignores locks set by an older version of the SDK (without creation date)', () => {\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({\n        isLockEnabled: true,\n        initialSession: { ...initialSession, lock: 'locked' },\n      })\n\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n      expect(processSpy).toHaveBeenCalled()\n    })\n\n    it('ignores expired locks', () => {\n      const clock = mockClock()\n      const sessionStoreStrategy = createFakeSessionStoreStrategy({\n        isLockEnabled: true,\n        initialSession: { ...initialSession, lock: createLock() },\n      })\n      clock.tick(LOCK_EXPIRATION_DELAY + 1)\n      processSessionStoreOperations({ process: processSpy, after: afterSpy }, sessionStoreStrategy)\n      expect(processSpy).toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/sessionStoreOperations.ts",
    "content": "import { setTimeout } from '../../tools/timer'\nimport { generateUUID } from '../../tools/utils/stringUtils'\nimport type { TimeStamp } from '../../tools/utils/timeUtils'\nimport { elapsed, ONE_SECOND, timeStampNow } from '../../tools/utils/timeUtils'\nimport type { SessionStoreStrategy } from './storeStrategies/sessionStoreStrategy'\nimport type { SessionState } from './sessionState'\nimport { expandSessionState, isSessionInExpiredState } from './sessionState'\n\ninterface Operations {\n  process: (sessionState: SessionState) => SessionState | undefined\n  after?: (sessionState: SessionState) => void\n}\n\nexport const LOCK_RETRY_DELAY = 10\nexport const LOCK_MAX_TRIES = 100\n\n// Locks should be hold for a few milliseconds top, just the time it takes to read and write a\n// cookie. Using one second should be enough in most situations.\nexport const LOCK_EXPIRATION_DELAY = ONE_SECOND\nconst LOCK_SEPARATOR = '--'\n\nconst bufferedOperations: Operations[] = []\nlet ongoingOperations: Operations | undefined\n\nexport function processSessionStoreOperations(\n  operations: Operations,\n  sessionStoreStrategy: SessionStoreStrategy,\n  numberOfRetries = 0\n) {\n  const { isLockEnabled, persistSession, expireSession } = sessionStoreStrategy\n  const persistWithLock = (session: SessionState) => persistSession({ ...session, lock: currentLock })\n  const retrieveStore = () => {\n    const { lock, ...session } = sessionStoreStrategy.retrieveSession()\n    return {\n      session,\n      lock: lock && !isLockExpired(lock) ? lock : undefined,\n    }\n  }\n\n  if (!ongoingOperations) {\n    ongoingOperations = operations\n  }\n  if (operations !== ongoingOperations) {\n    bufferedOperations.push(operations)\n    return\n  }\n  if (isLockEnabled && numberOfRetries >= LOCK_MAX_TRIES) {\n    next(sessionStoreStrategy)\n    return\n  }\n  let currentLock: string\n  let currentStore = retrieveStore()\n  if (isLockEnabled) {\n    // if someone has lock, retry later\n    if (currentStore.lock) {\n      retryLater(operations, sessionStoreStrategy, numberOfRetries)\n      return\n    }\n    // acquire lock\n    currentLock = createLock()\n    persistWithLock(currentStore.session)\n    // if lock is not acquired, retry later\n    currentStore = retrieveStore()\n    if (currentStore.lock !== currentLock) {\n      retryLater(operations, sessionStoreStrategy, numberOfRetries)\n      return\n    }\n  }\n  let processedSession = operations.process(currentStore.session)\n  if (isLockEnabled) {\n    // if lock corrupted after process, retry later\n    currentStore = retrieveStore()\n    if (currentStore.lock !== currentLock!) {\n      retryLater(operations, sessionStoreStrategy, numberOfRetries)\n      return\n    }\n  }\n  if (processedSession) {\n    if (isSessionInExpiredState(processedSession)) {\n      expireSession(processedSession)\n    } else {\n      expandSessionState(processedSession)\n      if (isLockEnabled) {\n        persistWithLock(processedSession)\n      } else {\n        persistSession(processedSession)\n      }\n    }\n  }\n  if (isLockEnabled) {\n    // correctly handle lock around expiration would require to handle this case properly at several levels\n    // since we don't have evidence of lock issues around expiration, let's just not do the corruption check for it\n    if (!(processedSession && isSessionInExpiredState(processedSession))) {\n      // if lock corrupted after persist, retry later\n      currentStore = retrieveStore()\n      if (currentStore.lock !== currentLock!) {\n        retryLater(operations, sessionStoreStrategy, numberOfRetries)\n        return\n      }\n      persistSession(currentStore.session)\n      processedSession = currentStore.session\n    }\n  }\n  // call after even if session is not persisted in order to perform operations on\n  // up-to-date session state value => the value could have been modified by another tab\n  operations.after?.(processedSession || currentStore.session)\n  next(sessionStoreStrategy)\n}\n\nfunction retryLater(operations: Operations, sessionStore: SessionStoreStrategy, currentNumberOfRetries: number) {\n  setTimeout(() => {\n    processSessionStoreOperations(operations, sessionStore, currentNumberOfRetries + 1)\n  }, LOCK_RETRY_DELAY)\n}\n\nfunction next(sessionStore: SessionStoreStrategy) {\n  ongoingOperations = undefined\n  const nextOperations = bufferedOperations.shift()\n  if (nextOperations) {\n    processSessionStoreOperations(nextOperations, sessionStore)\n  }\n}\n\nexport function createLock(): string {\n  return generateUUID() + LOCK_SEPARATOR + timeStampNow()\n}\n\nfunction isLockExpired(lock: string) {\n  const [, timeStamp] = lock.split(LOCK_SEPARATOR)\n  return !timeStamp || elapsed(Number(timeStamp) as TimeStamp, timeStampNow()) > LOCK_EXPIRATION_DELAY\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionInCookie.spec.ts",
    "content": "import { mockClock, getSessionState, registerCleanupTask } from '../../../../test'\nimport { setCookie, deleteCookie, getCookie } from '../../../browser/cookie'\nimport type { SessionState } from '../sessionState'\nimport { validateAndBuildConfiguration } from '../../configuration'\nimport type { InitConfiguration } from '../../configuration'\nimport { SESSION_COOKIE_EXPIRATION_DELAY, SESSION_EXPIRATION_DELAY, SESSION_TIME_OUT_DELAY } from '../sessionConstants'\nimport { buildCookieOptions, selectCookieStrategy, initCookieStrategy } from './sessionInCookie'\nimport { SESSION_STORE_KEY } from './sessionStoreStrategy'\n\nconst DEFAULT_INIT_CONFIGURATION = { clientToken: 'abc', trackAnonymousUser: true }\n\nfunction setupCookieStrategy(partialInitConfiguration: Partial<InitConfiguration> = {}) {\n  const initConfiguration = {\n    ...DEFAULT_INIT_CONFIGURATION,\n    ...partialInitConfiguration,\n  } as InitConfiguration\n\n  const configuration = validateAndBuildConfiguration(initConfiguration)!\n  const cookieOptions = buildCookieOptions(initConfiguration)!\n\n  registerCleanupTask(() => deleteCookie(SESSION_STORE_KEY, cookieOptions))\n\n  return initCookieStrategy(configuration, cookieOptions)\n}\n\ndescribe('session in cookie strategy', () => {\n  const sessionState: SessionState = { id: '123', created: '0' }\n\n  it('should persist a session in a cookie', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    cookieStorageStrategy.persistSession(sessionState)\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({ ...sessionState })\n    expect(getCookie(SESSION_STORE_KEY)).toBe('id=123&created=0')\n  })\n\n  it('should set `isExpired=1` to the cookie holding the session', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    spyOn(Math, 'random').and.callFake(() => 0)\n    cookieStorageStrategy.persistSession(sessionState)\n    cookieStorageStrategy.expireSession(sessionState)\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({ isExpired: '1' })\n    expect(getSessionState(SESSION_STORE_KEY)).toEqual({ isExpired: '1' })\n  })\n\n  it('should not generate an anonymousId if not present', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    cookieStorageStrategy.persistSession(sessionState)\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({ id: '123', created: '0' })\n    expect(getSessionState(SESSION_STORE_KEY)).toEqual({ id: '123', created: '0' })\n  })\n\n  it('should return an empty object if session string is invalid', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    setCookie(SESSION_STORE_KEY, '{test:42}', 1000)\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({})\n  })\n\n  describe('build cookie options', () => {\n    const clientToken = 'abc'\n\n    it('should not be secure nor crossSite by default', () => {\n      const cookieOptions = buildCookieOptions({ clientToken })\n      expect(cookieOptions).toEqual({ secure: false, crossSite: false, partitioned: false })\n    })\n\n    it('should be secure when `useSecureSessionCookie` is truthy', () => {\n      const cookieOptions = buildCookieOptions({ clientToken, useSecureSessionCookie: true })\n      expect(cookieOptions).toEqual({ secure: true, crossSite: false, partitioned: false })\n    })\n\n    it('should be secure, crossSite and partitioned when `usePartitionedCrossSiteSessionCookie` is truthy', () => {\n      const cookieOptions = buildCookieOptions({ clientToken, usePartitionedCrossSiteSessionCookie: true })\n      expect(cookieOptions).toEqual({ secure: true, crossSite: true, partitioned: true })\n    })\n\n    it('should have domain when `trackSessionAcrossSubdomains` is truthy', () => {\n      const cookieOptions = buildCookieOptions({ clientToken, trackSessionAcrossSubdomains: true })\n      expect(cookieOptions).toEqual({\n        secure: false,\n        crossSite: false,\n        partitioned: false,\n        domain: jasmine.any(String),\n      })\n    })\n  })\n\n  describe('cookie options', () => {\n    ;[\n      {\n        initConfiguration: { clientToken: 'abc' },\n        cookieOptions: {},\n        cookieString: /^dd_[\\w_-]+=[^;]*;expires=[^;]+;path=\\/;samesite=strict$/,\n        description: 'should set samesite to strict by default',\n      },\n      {\n        initConfiguration: { clientToken: 'abc', useSecureSessionCookie: true },\n        cookieOptions: { secure: true },\n        cookieString: /^dd_[\\w_-]+=[^;]*;expires=[^;]+;path=\\/;samesite=strict;secure$/,\n        description: 'should add secure attribute when defined',\n      },\n      {\n        initConfiguration: { clientToken: 'abc', trackSessionAcrossSubdomains: true },\n        cookieOptions: { domain: 'foo.bar' },\n        cookieString: new RegExp('^dd_[\\\\w_-]+=[^;]*;expires=[^;]+;path=\\\\/;samesite=strict;domain='),\n        description: 'should set cookie domain when tracking accross subdomains',\n      },\n    ].forEach(({ description, initConfiguration, cookieString }) => {\n      it(description, () => {\n        const cookieSetSpy = spyOnProperty(document, 'cookie', 'set')\n        selectCookieStrategy(initConfiguration)\n        expect(cookieSetSpy).toHaveBeenCalled()\n        for (const call of cookieSetSpy.calls.all()) {\n          expect(call.args[0]).toMatch(cookieString)\n        }\n      })\n    })\n  })\n\n  describe('encode cookie options', () => {\n    const config: Partial<InitConfiguration> = { betaEncodeCookieOptions: true }\n\n    it('should encode cookie options in the cookie value', () => {\n      // Some older browsers don't support partitioned cross-site session cookies\n      // so instead of testing the cookie value, we test the call to the cookie setter\n      const cookieSetSpy = spyOnProperty(document, 'cookie', 'set')\n      const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config })\n      cookieStorageStrategy.persistSession({ id: '123' })\n\n      const calls = cookieSetSpy.calls.all()\n      const lastCall = calls[calls.length - 1]\n      expect(lastCall.args[0]).toMatch(/^_dd_s=id=123&c=1/)\n    })\n\n    it('should not encode cookie options in the cookie value if the session is empty (deleting the cookie)', () => {\n      const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config })\n      cookieStorageStrategy.persistSession({})\n\n      expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n    })\n\n    it('should return the correct session state from the cookies', () => {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('_dd_s=id=123&c=0;_dd_s=id=456&c=1;_dd_s=id=789&c=2')\n      const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config })\n\n      expect(cookieStorageStrategy.retrieveSession()).toEqual({ id: '456' })\n    })\n\n    it('should return the session state from the first cookie if there is no match', () => {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('_dd_s=id=123&c=0;_dd_s=id=789&c=2')\n      const cookieStorageStrategy = setupCookieStrategy({ usePartitionedCrossSiteSessionCookie: true, ...config })\n\n      expect(cookieStorageStrategy.retrieveSession()).toEqual({ id: '123' })\n    })\n  })\n})\n\ndescribe('session in cookie strategy when opt-in anonymous user tracking', () => {\n  const anonymousId = 'device-123'\n  const sessionState: SessionState = { id: '123', created: '0' }\n\n  it('should persist with anonymous id', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    cookieStorageStrategy.persistSession({ ...sessionState, anonymousId })\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({ ...sessionState, anonymousId })\n    expect(getCookie(SESSION_STORE_KEY)).toBe('id=123&created=0&aid=device-123')\n  })\n\n  it('should expire with anonymous id', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    cookieStorageStrategy.expireSession({ ...sessionState, anonymousId })\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({ isExpired: '1', anonymousId })\n    expect(getCookie(SESSION_STORE_KEY)).toBe('isExpired=1&aid=device-123')\n  })\n\n  it('should persist for one year when opt-in', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    const cookieSetSpy = spyOnProperty(document, 'cookie', 'set')\n    const clock = mockClock()\n    cookieStorageStrategy.persistSession({ ...sessionState, anonymousId })\n    expect(cookieSetSpy.calls.argsFor(0)[0]).toContain(\n      new Date(clock.timeStamp(SESSION_COOKIE_EXPIRATION_DELAY)).toUTCString()\n    )\n  })\n\n  it('should expire in one year when opt-in', () => {\n    const cookieStorageStrategy = setupCookieStrategy()\n    const cookieSetSpy = spyOnProperty(document, 'cookie', 'set')\n    const clock = mockClock()\n    cookieStorageStrategy.expireSession({ ...sessionState, anonymousId })\n    expect(cookieSetSpy.calls.argsFor(0)[0]).toContain(\n      new Date(clock.timeStamp(SESSION_COOKIE_EXPIRATION_DELAY)).toUTCString()\n    )\n  })\n})\n\ndescribe('session in cookie strategy when opt-out anonymous user tracking', () => {\n  const anonymousId = 'device-123'\n  const sessionState: SessionState = { id: '123', created: '0' }\n\n  it('should not extend cookie expiration time when opt-out', () => {\n    const cookieStorageStrategy = setupCookieStrategy({ trackAnonymousUser: false })\n    const cookieSetSpy = spyOnProperty(document, 'cookie', 'set')\n    const clock = mockClock()\n    cookieStorageStrategy.expireSession({ ...sessionState, anonymousId })\n    expect(cookieSetSpy.calls.argsFor(0)[0]).toContain(new Date(clock.timeStamp(SESSION_TIME_OUT_DELAY)).toUTCString())\n  })\n\n  it('should not persist with one year when opt-out', () => {\n    const cookieStorageStrategy = setupCookieStrategy({ trackAnonymousUser: false })\n    const cookieSetSpy = spyOnProperty(document, 'cookie', 'set')\n    cookieStorageStrategy.persistSession({ ...sessionState, anonymousId })\n    expect(cookieSetSpy.calls.argsFor(0)[0]).toContain(new Date(Date.now() + SESSION_EXPIRATION_DELAY).toUTCString())\n  })\n\n  it('should not persist or expire a session with anonymous id when opt-out', () => {\n    const cookieStorageStrategy = setupCookieStrategy({ trackAnonymousUser: false })\n    cookieStorageStrategy.persistSession({ ...sessionState, anonymousId })\n    cookieStorageStrategy.expireSession({ ...sessionState, anonymousId })\n    const session = cookieStorageStrategy.retrieveSession()\n    expect(session).toEqual({ isExpired: '1' })\n    expect(getCookie(SESSION_STORE_KEY)).toBe('isExpired=1')\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionInCookie.ts",
    "content": "import { isEmptyObject } from '../../../tools/utils/objectUtils'\nimport { isChromium } from '../../../tools/utils/browserDetection'\nimport type { CookieOptions } from '../../../browser/cookie'\nimport { getCurrentSite, areCookiesAuthorized, getCookies, setCookie, getCookie } from '../../../browser/cookie'\nimport type { InitConfiguration, Configuration } from '../../configuration'\nimport { tryOldCookiesMigration } from '../oldCookiesMigration'\nimport {\n  SESSION_COOKIE_EXPIRATION_DELAY,\n  SESSION_EXPIRATION_DELAY,\n  SESSION_TIME_OUT_DELAY,\n  SessionPersistence,\n} from '../sessionConstants'\nimport type { SessionState } from '../sessionState'\nimport { toSessionString, toSessionState, getExpiredSessionState } from '../sessionState'\nimport type { SessionStoreStrategy, SessionStoreStrategyType } from './sessionStoreStrategy'\nimport { SESSION_STORE_KEY } from './sessionStoreStrategy'\n\nconst SESSION_COOKIE_VERSION = 0\n\nexport function selectCookieStrategy(initConfiguration: InitConfiguration): SessionStoreStrategyType | undefined {\n  const cookieOptions = buildCookieOptions(initConfiguration)\n  return cookieOptions && areCookiesAuthorized(cookieOptions)\n    ? { type: SessionPersistence.COOKIE, cookieOptions }\n    : undefined\n}\n\nexport function initCookieStrategy(configuration: Configuration, cookieOptions: CookieOptions): SessionStoreStrategy {\n  const cookieStore = {\n    /**\n     * Lock strategy allows mitigating issues due to concurrent access to cookie.\n     * This issue concerns only chromium browsers and enabling this on firefox increases cookie write failures.\n     */\n    isLockEnabled: isChromium(),\n    persistSession: (sessionState: SessionState) =>\n      storeSessionCookie(cookieOptions, configuration, sessionState, SESSION_EXPIRATION_DELAY),\n    retrieveSession: () => retrieveSessionCookie(cookieOptions, configuration),\n    expireSession: (sessionState: SessionState) =>\n      storeSessionCookie(\n        cookieOptions,\n        configuration,\n        getExpiredSessionState(sessionState, configuration),\n        SESSION_TIME_OUT_DELAY\n      ),\n  }\n\n  tryOldCookiesMigration(cookieStore)\n\n  return cookieStore\n}\n\nfunction storeSessionCookie(\n  options: CookieOptions,\n  configuration: Configuration,\n  sessionState: SessionState,\n  defaultTimeout: number\n) {\n  let sessionStateString = toSessionString(sessionState)\n\n  if (configuration.betaEncodeCookieOptions) {\n    sessionStateString = toSessionString({\n      ...sessionState,\n      // deleting a cookie is writing a new cookie with an empty value\n      // we don't want to store the cookie options in this case otherwise the cookie will not be deleted\n      ...(!isEmptyObject(sessionState) ? { c: encodeCookieOptions(options) } : {}),\n    })\n  }\n\n  setCookie(\n    SESSION_STORE_KEY,\n    sessionStateString,\n    configuration.trackAnonymousUser ? SESSION_COOKIE_EXPIRATION_DELAY : defaultTimeout,\n    options\n  )\n}\n\n/**\n * Retrieve the session state from the cookie that was set with the same cookie options\n * If there is no match, return the first cookie, because that's how `getCookie()` works\n */\nexport function retrieveSessionCookie(cookieOptions: CookieOptions, configuration: Configuration): SessionState {\n  if (configuration.betaEncodeCookieOptions) {\n    return retrieveSessionCookieFromEncodedCookie(cookieOptions)\n  }\n\n  const sessionString = getCookie(SESSION_STORE_KEY)\n  const sessionState = toSessionState(sessionString)\n  return sessionState\n}\n\nexport function buildCookieOptions(initConfiguration: InitConfiguration): CookieOptions | undefined {\n  const cookieOptions: CookieOptions = {}\n\n  cookieOptions.secure =\n    !!initConfiguration.useSecureSessionCookie || !!initConfiguration.usePartitionedCrossSiteSessionCookie\n  cookieOptions.crossSite = !!initConfiguration.usePartitionedCrossSiteSessionCookie\n  cookieOptions.partitioned = !!initConfiguration.usePartitionedCrossSiteSessionCookie\n\n  if (initConfiguration.trackSessionAcrossSubdomains) {\n    const currentSite = getCurrentSite()\n    if (!currentSite) {\n      return\n    }\n    cookieOptions.domain = currentSite\n  }\n\n  return cookieOptions\n}\n\nfunction encodeCookieOptions(cookieOptions: CookieOptions): string {\n  const domainCount = cookieOptions.domain ? cookieOptions.domain.split('.').length - 1 : 0\n\n  /* eslint-disable no-bitwise */\n  let byte = 0\n  byte |= SESSION_COOKIE_VERSION << 5 // Store version in upper 3 bits\n  byte |= domainCount << 1 // Store domain count in next 4 bits\n  byte |= cookieOptions.crossSite ? 1 : 0 // Store useCrossSiteScripting in next bit\n  /* eslint-enable no-bitwise */\n\n  return byte.toString(16) // Convert to hex string\n}\n\n/**\n * Retrieve the session state from the cookie that was set with the same cookie options.\n * If there is no match, fallback to the first cookie, (because that's how `getCookie()` works)\n * and this allows to keep the current session id when we release this feature.\n */\nfunction retrieveSessionCookieFromEncodedCookie(cookieOptions: CookieOptions): SessionState {\n  const cookies = getCookies(SESSION_STORE_KEY)\n  const opts = encodeCookieOptions(cookieOptions)\n\n  let sessionState: SessionState | undefined\n\n  // reverse the cookies so that if there is no match, the cookie returned is the first one\n  for (const cookie of cookies.reverse()) {\n    sessionState = toSessionState(cookie)\n\n    if (sessionState.c === opts) {\n      break\n    }\n  }\n\n  // remove the cookie options from the session state as this is not part of the session state\n  delete sessionState?.c\n\n  return sessionState ?? {}\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionInLocalStorage.spec.ts",
    "content": "import type { Configuration } from '../../configuration'\nimport { SessionPersistence } from '../sessionConstants'\nimport { toSessionState } from '../sessionState'\nimport type { SessionState } from '../sessionState'\nimport { selectLocalStorageStrategy, initLocalStorageStrategy } from './sessionInLocalStorage'\nimport { SESSION_STORE_KEY } from './sessionStoreStrategy'\nconst DEFAULT_INIT_CONFIGURATION = { trackAnonymousUser: true } as Configuration\n\nfunction getSessionStateFromLocalStorage(SESSION_STORE_KEY: string): SessionState {\n  return toSessionState(window.localStorage.getItem(SESSION_STORE_KEY))\n}\ndescribe('session in local storage strategy', () => {\n  const sessionState: SessionState = { id: '123', created: '0' }\n  beforeEach(() => {\n    spyOn(Math, 'random').and.returnValue(0)\n  })\n\n  afterEach(() => {\n    window.localStorage.clear()\n  })\n\n  it('should report local storage as available', () => {\n    const available = selectLocalStorageStrategy()\n    expect(available).toEqual({ type: SessionPersistence.LOCAL_STORAGE })\n  })\n\n  it('should report local storage as not available', () => {\n    spyOn(Storage.prototype, 'getItem').and.throwError('Unavailable')\n    const available = selectLocalStorageStrategy()\n    expect(available).toBeUndefined()\n  })\n\n  it('should persist a session in local storage', () => {\n    const localStorageStrategy = initLocalStorageStrategy(DEFAULT_INIT_CONFIGURATION)\n    localStorageStrategy.persistSession(sessionState)\n    const session = localStorageStrategy.retrieveSession()\n    expect(session).toEqual({ ...sessionState })\n    expect(getSessionStateFromLocalStorage(SESSION_STORE_KEY)).toEqual(sessionState)\n  })\n\n  it('should set `isExpired=1` to the local storage item holding the session', () => {\n    const localStorageStrategy = initLocalStorageStrategy(DEFAULT_INIT_CONFIGURATION)\n    localStorageStrategy.persistSession(sessionState)\n    localStorageStrategy.expireSession(sessionState)\n    const session = localStorageStrategy?.retrieveSession()\n    expect(session).toEqual({ isExpired: '1' })\n    expect(getSessionStateFromLocalStorage(SESSION_STORE_KEY)).toEqual({\n      isExpired: '1',\n    })\n  })\n\n  it('should not generate an anonymousId if not present', () => {\n    const localStorageStrategy = initLocalStorageStrategy(DEFAULT_INIT_CONFIGURATION)\n    localStorageStrategy.persistSession(sessionState)\n    const session = localStorageStrategy.retrieveSession()\n    expect(session).toEqual({ id: '123', created: '0' })\n    expect(getSessionStateFromLocalStorage(SESSION_STORE_KEY)).toEqual({ id: '123', created: '0' })\n  })\n\n  it('should return an empty object if session string is invalid', () => {\n    const localStorageStrategy = initLocalStorageStrategy(DEFAULT_INIT_CONFIGURATION)\n    window.localStorage.setItem(SESSION_STORE_KEY, '{test:42}')\n    const session = localStorageStrategy.retrieveSession()\n    expect(session).toEqual({})\n  })\n\n  it('should not interfere with other keys present in local storage', () => {\n    window.localStorage.setItem('test', 'hello')\n    const localStorageStrategy = initLocalStorageStrategy(DEFAULT_INIT_CONFIGURATION)\n    localStorageStrategy.persistSession(sessionState)\n    localStorageStrategy.retrieveSession()\n    localStorageStrategy.expireSession(sessionState)\n    expect(window.localStorage.getItem('test')).toEqual('hello')\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionInLocalStorage.ts",
    "content": "import { generateUUID } from '../../../tools/utils/stringUtils'\nimport type { Configuration } from '../../configuration'\nimport { SessionPersistence } from '../sessionConstants'\nimport type { SessionState } from '../sessionState'\nimport { toSessionString, toSessionState, getExpiredSessionState } from '../sessionState'\nimport type { SessionStoreStrategy, SessionStoreStrategyType } from './sessionStoreStrategy'\nimport { SESSION_STORE_KEY } from './sessionStoreStrategy'\n\nconst LOCAL_STORAGE_TEST_KEY = '_dd_test_'\n\nexport function selectLocalStorageStrategy(): SessionStoreStrategyType | undefined {\n  try {\n    const id = generateUUID()\n    const testKey = `${LOCAL_STORAGE_TEST_KEY}${id}`\n    localStorage.setItem(testKey, id)\n    const retrievedId = localStorage.getItem(testKey)\n    localStorage.removeItem(testKey)\n    return id === retrievedId ? { type: SessionPersistence.LOCAL_STORAGE } : undefined\n  } catch {\n    return undefined\n  }\n}\n\nexport function initLocalStorageStrategy(configuration: Configuration): SessionStoreStrategy {\n  return {\n    isLockEnabled: false,\n    persistSession: persistInLocalStorage,\n    retrieveSession: retrieveSessionFromLocalStorage,\n    expireSession: (sessionState: SessionState) => expireSessionFromLocalStorage(sessionState, configuration),\n  }\n}\n\nfunction persistInLocalStorage(sessionState: SessionState) {\n  localStorage.setItem(SESSION_STORE_KEY, toSessionString(sessionState))\n}\n\nexport function retrieveSessionFromLocalStorage(): SessionState {\n  const sessionString = localStorage.getItem(SESSION_STORE_KEY)\n  return toSessionState(sessionString)\n}\n\nfunction expireSessionFromLocalStorage(previousSessionState: SessionState, configuration: Configuration) {\n  persistInLocalStorage(getExpiredSessionState(previousSessionState, configuration))\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionInMemory.spec.ts",
    "content": "import { registerCleanupTask } from '../../../../test'\nimport { getGlobalObject } from '../../../tools/globalObject'\nimport type { Configuration } from '../../configuration'\nimport type { SessionState } from '../sessionState'\nimport { initMemorySessionStoreStrategy, MEMORY_SESSION_STORE_KEY } from './sessionInMemory'\n\ndescribe('session in memory strategy', () => {\n  const DEFAULT_INIT_CONFIGURATION = { trackAnonymousUser: true } as Configuration\n  const sessionState: SessionState = { id: '123', created: '0' }\n\n  beforeEach(() => {\n    registerCleanupTask(() => {\n      const globalObject = getGlobalObject<Record<string, unknown>>()\n      delete globalObject[MEMORY_SESSION_STORE_KEY]\n    })\n  })\n\n  it('should persist a session in memory', () => {\n    const memoryStorageStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    memoryStorageStrategy.persistSession(sessionState)\n    const session = memoryStorageStrategy.retrieveSession()\n    expect(session).toEqual(sessionState)\n    expect(session).not.toBe(sessionState)\n  })\n\n  it('should set `isExpired=1` on session', () => {\n    const memoryStorageStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    memoryStorageStrategy.persistSession(sessionState)\n    memoryStorageStrategy.expireSession(sessionState)\n    const session = memoryStorageStrategy.retrieveSession()\n    expect(session).toEqual({ isExpired: '1' })\n    expect(session).not.toBe(sessionState)\n  })\n\n  it('should return an empty object when no state persisted', () => {\n    const memoryStorageStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    const session = memoryStorageStrategy.retrieveSession()\n    expect(session).toEqual({})\n  })\n\n  it('should not mutate stored session if source state mutates', () => {\n    const sessionStateToMutate: SessionState = {}\n    const memoryStorageStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    memoryStorageStrategy.persistSession(sessionStateToMutate)\n    sessionStateToMutate.id = '123'\n    const session = memoryStorageStrategy.retrieveSession()\n    expect(session).toEqual({})\n    expect(session).not.toBe(sessionStateToMutate)\n  })\n\n  it('should share session state between multiple strategy instances (RUM and Logs)', () => {\n    const rumStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    const logsStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n\n    rumStrategy.persistSession(sessionState)\n\n    const logsSession = logsStrategy.retrieveSession()\n    expect(logsSession).toEqual(sessionState)\n  })\n\n  it('should reflect updates from one SDK instance in another', () => {\n    const rumStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    const logsStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n\n    rumStrategy.persistSession({ id: '123', created: '0' })\n    logsStrategy.persistSession({ id: '123', created: '0', rum: '1' })\n\n    const rumSession = rumStrategy.retrieveSession()\n    expect(rumSession.rum).toEqual('1')\n  })\n\n  it('should store session in global object', () => {\n    const memoryStorageStrategy = initMemorySessionStoreStrategy(DEFAULT_INIT_CONFIGURATION)\n    memoryStorageStrategy.persistSession(sessionState)\n\n    const globalObject = getGlobalObject<Record<string, unknown>>()\n    expect(globalObject[MEMORY_SESSION_STORE_KEY]).toEqual(sessionState)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionInMemory.ts",
    "content": "import { getGlobalObject } from '../../../tools/globalObject'\nimport type { Configuration } from '../../configuration'\nimport { SessionPersistence } from '../sessionConstants'\nimport type { SessionState } from '../sessionState'\nimport { getExpiredSessionState } from '../sessionState'\nimport { shallowClone } from '../../../tools/utils/objectUtils'\nimport type { SessionStoreStrategy, SessionStoreStrategyType } from './sessionStoreStrategy'\n\n/**\n * Key used to store session state in the global object.\n * This allows RUM and Logs SDKs to share the same session when using memory storage.\n */\nexport const MEMORY_SESSION_STORE_KEY = '_DD_SESSION'\n\ninterface GlobalObjectWithSession {\n  [MEMORY_SESSION_STORE_KEY]?: SessionState\n}\n\nexport function selectMemorySessionStoreStrategy(): SessionStoreStrategyType {\n  return { type: SessionPersistence.MEMORY }\n}\n\nexport function initMemorySessionStoreStrategy(configuration: Configuration): SessionStoreStrategy {\n  return {\n    expireSession: (sessionState: SessionState) => expireSessionFromMemory(sessionState, configuration),\n    isLockEnabled: false,\n    persistSession: persistInMemory,\n    retrieveSession: retrieveFromMemory,\n  }\n}\n\nfunction retrieveFromMemory(): SessionState {\n  const globalObject = getGlobalObject<GlobalObjectWithSession>()\n  if (!globalObject[MEMORY_SESSION_STORE_KEY]) {\n    globalObject[MEMORY_SESSION_STORE_KEY] = {}\n  }\n  return shallowClone(globalObject[MEMORY_SESSION_STORE_KEY])\n}\n\nfunction persistInMemory(state: SessionState): void {\n  const globalObject = getGlobalObject<GlobalObjectWithSession>()\n  globalObject[MEMORY_SESSION_STORE_KEY] = shallowClone(state)\n}\n\nfunction expireSessionFromMemory(previousSessionState: SessionState, configuration: Configuration) {\n  persistInMemory(getExpiredSessionState(previousSessionState, configuration))\n}\n"
  },
  {
    "path": "packages/core/src/domain/session/storeStrategies/sessionStoreStrategy.ts",
    "content": "import type { CookieOptions } from '../../../browser/cookie'\nimport type { SessionPersistence } from '../sessionConstants'\nimport type { SessionState } from '../sessionState'\n\nexport const SESSION_STORE_KEY = '_dd_s'\n\nexport type SessionStoreStrategyType =\n  | { type: typeof SessionPersistence.COOKIE; cookieOptions: CookieOptions }\n  | { type: typeof SessionPersistence.LOCAL_STORAGE }\n  | { type: typeof SessionPersistence.MEMORY }\n\nexport interface SessionStoreStrategy {\n  isLockEnabled: boolean\n  persistSession: (session: SessionState) => void\n  retrieveSession: () => SessionState\n  expireSession: (previousSessionState: SessionState) => void\n}\n"
  },
  {
    "path": "packages/core/src/domain/synthetics/syntheticsWorkerValues.spec.ts",
    "content": "import { mockSyntheticsWorkerValues } from '../../../test'\nimport { getSyntheticsContext, willSyntheticsInjectRum } from './syntheticsWorkerValues'\n\ndescribe('syntheticsWorkerValues', () => {\n  describe('willSyntheticsInjectRum', () => {\n    it('returns false if nothing is defined', () => {\n      mockSyntheticsWorkerValues({}, 'globals')\n\n      expect(willSyntheticsInjectRum()).toBeFalse()\n    })\n\n    it('returns false if the INJECTS_RUM global variable is false', () => {\n      mockSyntheticsWorkerValues({ injectsRum: false }, 'globals')\n\n      expect(willSyntheticsInjectRum()).toBeFalse()\n    })\n\n    it('returns true if the INJECTS_RUM global variable is truthy', () => {\n      mockSyntheticsWorkerValues({ injectsRum: true }, 'globals')\n\n      expect(willSyntheticsInjectRum()).toBeTrue()\n    })\n\n    it('returns true if the INJECTS_RUM cookie is truthy', () => {\n      mockSyntheticsWorkerValues({ injectsRum: true }, 'cookies')\n\n      expect(willSyntheticsInjectRum()).toBeTrue()\n    })\n  })\n\n  describe('getSyntheticsContext', () => {\n    it('returns undefined if nothing is defined', () => {\n      mockSyntheticsWorkerValues({}, 'globals')\n\n      expect(getSyntheticsContext()).toBeUndefined()\n    })\n\n    it('returns the context from the global variable', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo', result_id: 'bar' } }, 'globals')\n\n      expect(getSyntheticsContext()).toEqual({ test_id: 'foo', result_id: 'bar' })\n    })\n\n    it('returns undefined if the global variable is missing test_id or result_id', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo' } as any }, 'globals')\n\n      expect(getSyntheticsContext()).toBeUndefined()\n    })\n\n    it('returns undefined if test_id or result_id are not strings', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 1, result_id: 2 } as any }, 'globals')\n\n      expect(getSyntheticsContext()).toBeUndefined()\n    })\n\n    it('includes extra properties from the context', () => {\n      mockSyntheticsWorkerValues(\n        { context: { test_id: 'foo', result_id: 'bar', run_type: 'scheduled', suite_ids: ['abc'] as any } },\n        'globals'\n      )\n\n      expect(getSyntheticsContext()).toEqual({\n        test_id: 'foo',\n        result_id: 'bar',\n        run_type: 'scheduled',\n        suite_ids: ['abc'],\n      })\n    })\n\n    it('returns the context from the cookie', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo', result_id: 'bar' } }, 'cookies')\n\n      expect(getSyntheticsContext()).toEqual({ test_id: 'foo', result_id: 'bar' })\n    })\n\n    it('returns undefined if the cookie context is missing required fields', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo' } as any }, 'cookies')\n\n      expect(getSyntheticsContext()).toBeUndefined()\n    })\n\n    it('falls back to legacy globals when the new context is absent', () => {\n      mockSyntheticsWorkerValues({ publicId: 'foo', resultId: 'bar' }, 'globals')\n\n      expect(getSyntheticsContext()).toEqual({ test_id: 'foo', result_id: 'bar' })\n    })\n\n    it('falls back to legacy cookies when the new context is absent', () => {\n      mockSyntheticsWorkerValues({ publicId: 'foo', resultId: 'bar' }, 'cookies')\n\n      expect(getSyntheticsContext()).toEqual({ test_id: 'foo', result_id: 'bar' })\n    })\n\n    it('returns undefined from legacy fallback if one of the two values is missing', () => {\n      mockSyntheticsWorkerValues({ publicId: 'foo' }, 'globals')\n\n      expect(getSyntheticsContext()).toBeUndefined()\n    })\n\n    it('prefers the new context over legacy globals when both are present', () => {\n      mockSyntheticsWorkerValues(\n        { context: { test_id: 'new-id', result_id: 'new-result' }, publicId: 'old-id', resultId: 'old-result' },\n        'globals'\n      )\n\n      expect(getSyntheticsContext()).toEqual({ test_id: 'new-id', result_id: 'new-result' })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/synthetics/syntheticsWorkerValues.ts",
    "content": "import { getInitCookie } from '../../browser/cookie'\nimport { globalObject, isWorkerEnvironment } from '../../tools/globalObject'\nimport { tryJsonParse } from '../../tools/utils/objectUtils'\n\nconst cookieNamePrefix = 'datadog-synthetics-'\nexport const SYNTHETICS_TEST_ID_COOKIE_NAME = `${cookieNamePrefix}public-id`\nexport const SYNTHETICS_RESULT_ID_COOKIE_NAME = `${cookieNamePrefix}result-id`\nexport const SYNTHETICS_INJECTS_RUM_COOKIE_NAME = `${cookieNamePrefix}injects-rum`\nexport const SYNTHETICS_CONTEXT_COOKIE_NAME = `${cookieNamePrefix}rum-context`\n\nexport interface BrowserWindow extends Window {\n  _DATADOG_SYNTHETICS_PUBLIC_ID?: unknown\n  _DATADOG_SYNTHETICS_RESULT_ID?: unknown\n  _DATADOG_SYNTHETICS_INJECTS_RUM?: unknown\n  _DATADOG_SYNTHETICS_RUM_CONTEXT?: unknown\n}\n\nexport interface SyntheticsContext {\n  test_id: string\n  result_id: string\n  [key: string]: unknown\n}\n\nexport function willSyntheticsInjectRum(): boolean {\n  if (isWorkerEnvironment) {\n    // We don't expect to run synthetics tests in a worker environment\n    return false\n  }\n\n  return Boolean(\n    (globalObject as BrowserWindow)._DATADOG_SYNTHETICS_INJECTS_RUM || getInitCookie(SYNTHETICS_INJECTS_RUM_COOKIE_NAME)\n  )\n}\n\nexport function getSyntheticsContext(): SyntheticsContext | undefined {\n  const raw = getRawSyntheticsContext()\n  return isValidSyntheticsContext(raw) ? raw : undefined\n}\n\nexport function isSyntheticsTest(): boolean {\n  return Boolean(getSyntheticsContext())\n}\n\nfunction getRawSyntheticsContext(): unknown {\n  const rawGlobal = (globalObject as BrowserWindow)._DATADOG_SYNTHETICS_RUM_CONTEXT\n  if (rawGlobal) {\n    return rawGlobal\n  }\n\n  const rawCookie = getInitCookie(SYNTHETICS_CONTEXT_COOKIE_NAME)\n  if (rawCookie) {\n    return tryJsonParse(decodeURIComponent(rawCookie))\n  }\n\n  return {\n    test_id: (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID || getInitCookie(SYNTHETICS_TEST_ID_COOKIE_NAME),\n    result_id:\n      (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID || getInitCookie(SYNTHETICS_RESULT_ID_COOKIE_NAME),\n  }\n}\n\nfunction isValidSyntheticsContext(value: unknown): value is SyntheticsContext {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    typeof (value as Record<string, unknown>).test_id === 'string' &&\n    typeof (value as Record<string, unknown>).result_id === 'string'\n  )\n}\n"
  },
  {
    "path": "packages/core/src/domain/tags.spec.ts",
    "content": "import { display } from '../tools/display'\nimport type { Configuration } from './configuration'\nimport { buildTag, buildTags, supportUnicodePropertyEscapes, TAG_SIZE_LIMIT } from './tags'\n\nconst LARGE_VALUE = Array(TAG_SIZE_LIMIT + 10).join('a')\n\ndescribe('buildTags', () => {\n  it('build tags from init configuration', () => {\n    expect(\n      buildTags({\n        service: 'foo',\n        env: 'bar',\n        version: 'baz',\n        datacenter: 'us1.prod.dog',\n      } as Configuration)\n    ).toEqual(['sdk_version:test', 'env:bar', 'service:foo', 'version:baz', 'datacenter:us1.prod.dog'])\n  })\n})\n\ndescribe('buildTag warning', () => {\n  let displaySpy: jasmine.Spy<typeof display.warn>\n  beforeEach(() => {\n    if (!supportUnicodePropertyEscapes()) {\n      pending('Unicode property escapes are not supported')\n    }\n\n    displaySpy = spyOn(display, 'warn')\n  })\n  ;(\n    [\n      [(s: string) => buildTag(s), 'key only'],\n      [(s: string) => buildTag(s, 'value'), 'tag key'],\n      [(s: string) => buildTag('env', s), 'tag value'],\n    ] as const\n  ).forEach(([tagBuilder, description]) => {\n    describe(description, () => {\n      it('shows a warning when the tag contains uppercase letters', () => {\n        tagBuilder('BaR')\n        expectWarning()\n      })\n\n      it('shows a warning when the tag is too large', () => {\n        tagBuilder(LARGE_VALUE)\n        expectWarning()\n      })\n\n      it('shows a warning when the tag contains forbidden characters', () => {\n        tagBuilder('b#r')\n        expectWarning()\n      })\n\n      it('shows a warning when using non latin uppercase letters like in Greek', () => {\n        tagBuilder('Δοκιμή')\n        expectWarning()\n      })\n\n      it('do not shows a warning when non latin characters are neither uppercase or lowercase (p{Lo}) like Japanese', () => {\n        tagBuilder('てすと')\n        expect(displaySpy).not.toHaveBeenCalled()\n      })\n\n      it('forbids to craft multiple tags by passing a value with a comma', () => {\n        expect(tagBuilder('foo,bar')).toContain('foo_bar')\n        expectWarning()\n      })\n    })\n  })\n\n  function expectWarning() {\n    expect(displaySpy).toHaveBeenCalledOnceWith(\n      jasmine.stringMatching(\"Tag .* doesn't meet tag requirements and will be sanitized\")\n    )\n  }\n})\n"
  },
  {
    "path": "packages/core/src/domain/tags.ts",
    "content": "import { DOCS_ORIGIN, MORE_DETAILS, display } from '../tools/display'\nimport type { Configuration } from './configuration'\n\nexport const TAG_SIZE_LIMIT = 200\n\n// replaced at build time\ndeclare const __BUILD_ENV__SDK_VERSION__: string\n\nexport function buildTags(configuration: Configuration): string[] {\n  const { env, service, version, datacenter, sdkVersion, variant } = configuration\n  const tags = [buildTag('sdk_version', sdkVersion ?? __BUILD_ENV__SDK_VERSION__)]\n\n  if (env) {\n    tags.push(buildTag('env', env))\n  }\n  if (service) {\n    tags.push(buildTag('service', service))\n  }\n  if (version) {\n    tags.push(buildTag('version', version))\n  }\n  if (datacenter) {\n    tags.push(buildTag('datacenter', datacenter))\n  }\n\n  if (variant) {\n    tags.push(buildTag('variant', variant))\n  }\n\n  return tags\n}\n\nexport function buildTag(key: string, rawValue?: string) {\n  // See https://docs.datadoghq.com/getting_started/tagging/#defining-tags for tags syntax. Note\n  // that the backend may not follow the exact same rules, so we only want to display an informal\n  // warning.\n  const tag = rawValue ? `${key}:${rawValue}` : key\n\n  if (tag.length > TAG_SIZE_LIMIT || hasForbiddenCharacters(tag)) {\n    display.warn(\n      `Tag ${tag} doesn't meet tag requirements and will be sanitized. ${MORE_DETAILS} ${DOCS_ORIGIN}/getting_started/tagging/#defining-tags`\n    )\n  }\n\n  // Let the backend do most of the sanitization, but still make sure multiple tags can't be crafted\n  // by forging a value containing commas.\n  return sanitizeTag(tag)\n}\n\nexport function sanitizeTag(tag: string) {\n  return tag.replace(/,/g, '_')\n}\n\nfunction hasForbiddenCharacters(rawValue: string) {\n  // Unicode property escapes is not supported in all browsers, so we use a try/catch.\n  // Todo: Remove the try/catch when dropping support for Chrome 63 and Firefox 67\n  // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Unicode_character_class_escape#browser_compatibility\n  if (!supportUnicodePropertyEscapes()) {\n    return false\n  }\n\n  // We use the Unicode property escapes to match any character that is a letter including other languages like Chinese, Japanese, etc.\n  // p{Ll} matches a lowercase letter.\n  // p{Lo} matches a letter that is neither uppercase nor lowercase (ex: Japanese characters).\n  // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Unicode_character_class_escape#unicode_property_escapes_vs._character_classes\n  return new RegExp('[^\\\\p{Ll}\\\\p{Lo}0-9_:./-]', 'u').test(rawValue)\n}\n\nexport function supportUnicodePropertyEscapes() {\n  try {\n    new RegExp('[\\\\p{Ll}]', 'u')\n    return true\n  } catch {\n    return false\n  }\n}\n"
  },
  {
    "path": "packages/core/src/domain/telemetry/index.ts",
    "content": "export type { Telemetry } from './telemetry'\nexport {\n  TelemetryService,\n  TelemetryMetrics,\n  addTelemetryDebug,\n  addTelemetryError,\n  resetTelemetry,\n  startTelemetry,\n  addTelemetryConfiguration,\n  addTelemetryUsage,\n  addTelemetryMetrics,\n  getTelemetryObservable,\n} from './telemetry'\n\nexport * from './rawTelemetryEvent.types'\nexport type {\n  TelemetryEvent,\n  TelemetryErrorEvent,\n  TelemetryDebugEvent,\n  TelemetryConfigurationEvent,\n  TelemetryUsageEvent,\n} from './telemetryEvent.types'\n"
  },
  {
    "path": "packages/core/src/domain/telemetry/rawTelemetryEvent.types.ts",
    "content": "import type { TelemetryEvent, TelemetryConfigurationEvent, TelemetryUsageEvent } from './telemetryEvent.types'\n\nexport const TelemetryType = {\n  LOG: 'log',\n  CONFIGURATION: 'configuration',\n  USAGE: 'usage',\n} as const\n\nexport const enum StatusType {\n  debug = 'debug',\n  error = 'error',\n}\n\nexport interface RuntimeEnvInfo {\n  is_local_file: boolean\n  is_worker: boolean\n}\n\nexport type RawTelemetryEvent = TelemetryEvent['telemetry']\nexport type RawTelemetryConfiguration = TelemetryConfigurationEvent['telemetry']['configuration']\nexport type RawTelemetryUsage = TelemetryUsageEvent['telemetry']['usage']\nexport type RawTelemetryUsageFeature = TelemetryUsageEvent['telemetry']['usage']['feature']\n"
  },
  {
    "path": "packages/core/src/domain/telemetry/telemetry.spec.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-rum/internal'\nimport { NO_ERROR_STACK_PRESENT_MESSAGE } from '../error/error'\nimport { callMonitored } from '../../tools/monitor'\nimport type { ExperimentalFeature } from '../../tools/experimentalFeatures'\nimport { addExperimentalFeatures } from '../../tools/experimentalFeatures'\nimport { validateAndBuildConfiguration, type Configuration } from '../configuration'\nimport { INTAKE_SITE_US1_FED, INTAKE_SITE_US2_FED, INTAKE_SITE_US1 } from '../intakeSites'\nimport {\n  setNavigatorOnLine,\n  setNavigatorConnection,\n  createHooks,\n  waitNextMicrotask,\n  interceptRequests,\n  registerCleanupTask,\n  createNewEvent,\n} from '../../../test'\nimport type { Context } from '../../tools/serialisation/context'\nimport { Observable } from '../../tools/observable'\nimport type { StackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { HookNames } from '../../tools/abstractHooks'\nimport {\n  addTelemetryError,\n  scrubCustomerFrames,\n  formatError,\n  addTelemetryConfiguration,\n  addTelemetryUsage,\n  TelemetryService,\n  startTelemetryCollection,\n  addTelemetryMetrics,\n  addTelemetryDebug,\n  TelemetryMetrics,\n  startTelemetryTransport,\n} from './telemetry'\nimport type { TelemetryEvent } from './telemetryEvent.types'\nimport { StatusType, TelemetryType } from './rawTelemetryEvent.types'\n\nfunction startAndSpyTelemetry(\n  configuration?: Partial<Configuration>,\n  {\n    metricSampleRate,\n    maxTelemetryEventsPerPage,\n  }: { metricSampleRate?: number; maxTelemetryEventsPerPage?: number } = {}\n) {\n  const observable = new Observable<TelemetryEvent & Context>()\n\n  const events: TelemetryEvent[] = []\n  observable.subscribe((event) => events.push(event))\n  const hooks = createHooks()\n  const telemetry = startTelemetryCollection(\n    TelemetryService.RUM,\n    {\n      telemetrySampleRate: 100,\n      telemetryUsageSampleRate: 100,\n      ...configuration,\n    } as Configuration,\n    hooks,\n    observable,\n    metricSampleRate,\n    maxTelemetryEventsPerPage\n  )\n\n  return {\n    getTelemetryEvents: async () => {\n      await waitNextMicrotask()\n      return events\n    },\n    telemetry,\n    hooks,\n  }\n}\n\ndescribe('telemetry', () => {\n  it('collects \"monitor\" errors', async () => {\n    const { getTelemetryEvents } = startAndSpyTelemetry()\n    callMonitored(() => {\n      throw new Error('message')\n    })\n\n    expect(await getTelemetryEvents()).toEqual([\n      jasmine.objectContaining({\n        telemetry: jasmine.objectContaining({\n          type: TelemetryType.LOG,\n          status: StatusType.error,\n        }),\n      }),\n    ])\n  })\n\n  describe('addTelemetryConfiguration', () => {\n    it('should collects configuration when sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({\n        telemetrySampleRate: 100,\n        telemetryConfigurationSampleRate: 100,\n      })\n\n      addTelemetryConfiguration({})\n\n      expect(await getTelemetryEvents()).toEqual([\n        jasmine.objectContaining({\n          telemetry: jasmine.objectContaining({\n            type: TelemetryType.CONFIGURATION,\n            configuration: jasmine.anything(),\n          }),\n        }),\n      ])\n    })\n\n    it('should not notify configuration when not sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({\n        telemetrySampleRate: 100,\n        telemetryConfigurationSampleRate: 0,\n      })\n\n      addTelemetryConfiguration({})\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n\n    it('should not notify configuration when telemetrySampleRate is 0', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({\n        telemetrySampleRate: 0,\n        telemetryConfigurationSampleRate: 100,\n      })\n\n      addTelemetryConfiguration({})\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n  })\n\n  describe('addTelemetryUsage', () => {\n    it('should collects usage when sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 100, telemetryUsageSampleRate: 100 })\n\n      addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: 'granted' })\n\n      expect(await getTelemetryEvents()).toEqual([\n        jasmine.objectContaining({\n          telemetry: jasmine.objectContaining({\n            type: TelemetryType.USAGE,\n            usage: jasmine.anything(),\n          }),\n        }),\n      ])\n    })\n\n    it('should not notify usage when not sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 100, telemetryUsageSampleRate: 0 })\n\n      addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: 'granted' })\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n\n    it('should not notify usage when telemetrySampleRate is 0', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 0, telemetryUsageSampleRate: 100 })\n\n      addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: 'granted' })\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n  })\n\n  describe('addTelemetryMetrics', () => {\n    it('should collect metrics when sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 100 }, { metricSampleRate: 100 })\n\n      addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, { speed: 1000 })\n\n      expect(await getTelemetryEvents()).toEqual([\n        jasmine.objectContaining({\n          telemetry: jasmine.objectContaining({\n            type: TelemetryType.LOG,\n            message: TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME,\n            status: StatusType.debug,\n          }),\n        }),\n      ])\n    })\n\n    it('should not notify metrics when telemetry not sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 0 }, { metricSampleRate: 100 })\n\n      addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, { speed: 1000 })\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n\n    it('should not notify metrics when metric not sampled', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 100 }, { metricSampleRate: 0 })\n\n      addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, { speed: 1000 })\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n  })\n\n  it('should contains feature flags', async () => {\n    addExperimentalFeatures(['foo' as ExperimentalFeature])\n    const { getTelemetryEvents } = startAndSpyTelemetry()\n    callMonitored(() => {\n      throw new Error('message')\n    })\n\n    expect((await getTelemetryEvents())[0].experimental_features).toEqual(['foo'])\n  })\n\n  it('should contains runtime env', async () => {\n    const { getTelemetryEvents } = startAndSpyTelemetry()\n    callMonitored(() => {\n      throw new Error('message')\n    })\n\n    expect((await getTelemetryEvents())[0].telemetry.runtime_env).toEqual({\n      is_local_file: jasmine.any(Boolean),\n      is_worker: jasmine.any(Boolean),\n    })\n  })\n\n  it('should contain connectivity information', async () => {\n    setNavigatorOnLine(false)\n    setNavigatorConnection({ type: 'wifi', effectiveType: '4g' })\n\n    const { getTelemetryEvents } = startAndSpyTelemetry()\n    callMonitored(() => {\n      throw new Error('message')\n    })\n\n    expect((await getTelemetryEvents())[0].telemetry.connectivity).toEqual({\n      status: 'not_connected',\n      interfaces: ['wifi'],\n      effective_type: '4g',\n    })\n  })\n\n  it('should collect pre start events', async () => {\n    addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: 'granted' })\n\n    const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 100, telemetryUsageSampleRate: 100 })\n\n    expect((await getTelemetryEvents()).length).toBe(1)\n  })\n\n  it('should collect ddtags', async () => {\n    const { getTelemetryEvents } = startAndSpyTelemetry({\n      service: 'foo',\n      env: 'bar',\n      version: '123',\n    })\n\n    addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: 'granted' })\n\n    expect((await getTelemetryEvents())[0].ddtags).toEqual('sdk_version:test,env:bar,service:foo,version:123')\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should add default telemetry event attributes', async () => {\n      const { getTelemetryEvents, hooks } = startAndSpyTelemetry()\n\n      hooks.register(HookNames.AssembleTelemetry, () => ({ foo: 'bar' }))\n\n      callMonitored(() => {\n        throw new Error('foo')\n      })\n\n      expect((await getTelemetryEvents())[0].foo).toEqual('bar')\n    })\n\n    it('should add context progressively', async () => {\n      const { hooks, getTelemetryEvents } = startAndSpyTelemetry()\n      hooks.register(HookNames.AssembleTelemetry, () => ({\n        application: {\n          id: 'bar',\n        },\n      }))\n      callMonitored(() => {\n        throw new Error('foo')\n      })\n      hooks.register(HookNames.AssembleTelemetry, () => ({\n        session: {\n          id: '123',\n        },\n      }))\n      callMonitored(() => {\n        throw new Error('bar')\n      })\n\n      const events = await getTelemetryEvents()\n      expect(events[0].application!.id).toEqual('bar')\n      expect(events[1].application!.id).toEqual('bar')\n      expect(events[1].session!.id).toEqual('123')\n    })\n\n    it('should apply telemetry hook on events collected before telemetry is started', async () => {\n      addTelemetryDebug('debug 1')\n\n      const { hooks, getTelemetryEvents } = startAndSpyTelemetry()\n\n      hooks.register(HookNames.AssembleTelemetry, () => ({\n        application: {\n          id: 'bar',\n        },\n      }))\n\n      const events = await getTelemetryEvents()\n      expect(events[0].application!.id).toEqual('bar')\n    })\n  })\n\n  describe('sampling', () => {\n    it('should notify when sampled', async () => {\n      spyOn(Math, 'random').and.callFake(() => 0)\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 50 })\n\n      callMonitored(() => {\n        throw new Error('message')\n      })\n\n      expect((await getTelemetryEvents()).length).toBe(1)\n    })\n\n    it('should not notify when not sampled', async () => {\n      spyOn(Math, 'random').and.callFake(() => 1)\n      const { getTelemetryEvents } = startAndSpyTelemetry({ telemetrySampleRate: 50 })\n\n      callMonitored(() => {\n        throw new Error('message')\n      })\n\n      expect(await getTelemetryEvents()).toEqual([])\n    })\n  })\n\n  describe('deduplicating', () => {\n    it('should discard already sent telemetry', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry()\n      const fooError = new Error('foo')\n      const barError = new Error('bar')\n\n      addTelemetryError(fooError)\n      addTelemetryError(fooError)\n      addTelemetryError(barError)\n\n      const events = await getTelemetryEvents()\n      expect(events.length).toBe(2)\n      expect(events[0].telemetry.message).toEqual('foo')\n      expect(events[1].telemetry.message).toEqual('bar')\n    })\n\n    it('should not consider a discarded event for the maxTelemetryEventsPerPage', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry(undefined, { maxTelemetryEventsPerPage: 2 })\n\n      addTelemetryUsage({ feature: 'stop-session' })\n      addTelemetryUsage({ feature: 'stop-session' })\n      addTelemetryUsage({ feature: 'start-session-replay-recording' })\n\n      const events = await getTelemetryEvents()\n      expect(events.length).toBe(2)\n      expect((events[0].telemetry.usage as any).feature).toEqual('stop-session')\n      expect((events[1].telemetry.usage as any).feature).toEqual('start-session-replay-recording')\n    })\n  })\n\n  describe('maxTelemetryEventsPerPage', () => {\n    it('should be enforced', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry(undefined, { maxTelemetryEventsPerPage: 2 })\n\n      addTelemetryUsage({ feature: 'stop-session' })\n      addTelemetryUsage({ feature: 'start-session-replay-recording' })\n      addTelemetryUsage({ feature: 'start-view' })\n\n      const events = await getTelemetryEvents()\n      expect(events.length).toBe(2)\n      expect((events[0].telemetry.usage as any).feature).toEqual('stop-session')\n      expect((events[1].telemetry.usage as any).feature).toEqual('start-session-replay-recording')\n    })\n\n    it('should be enforced separately for different kinds of telemetry', async () => {\n      const { getTelemetryEvents } = startAndSpyTelemetry(undefined, {\n        metricSampleRate: 100,\n        maxTelemetryEventsPerPage: 2,\n      })\n\n      // Group 1. These are all distinct kinds of telemetry, so these should all be sent.\n      addTelemetryDebug('debug 1')\n      addTelemetryError(new Error('error 1'))\n      addTelemetryMetrics(TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, { bandwidth: 500 })\n      addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, { speed: 1000 })\n      addTelemetryUsage({ feature: 'stop-session' })\n\n      // Group 2. Again, these should all be sent.\n      addTelemetryDebug('debug 2')\n      addTelemetryError(new Error('error 2'))\n      addTelemetryMetrics(TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, { latency: 50 })\n      addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, { jank: 50 })\n      addTelemetryUsage({ feature: 'start-session-replay-recording' })\n\n      // Group 3. Each of these events should hit the limit for their respective kind of\n      // telemetry, so none of them should be sent.\n      addTelemetryDebug('debug 3')\n      addTelemetryError(new Error('error 3'))\n      addTelemetryMetrics(TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, { packet_loss: 99 })\n      addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, { latency: 500 })\n      addTelemetryUsage({ feature: 'start-view' })\n\n      expect((await getTelemetryEvents()).map((event) => event.telemetry)).toEqual([\n        // Group 1.\n        jasmine.objectContaining({ message: 'debug 1' }),\n        jasmine.objectContaining({ message: 'error 1' }),\n        jasmine.objectContaining({ message: TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, bandwidth: 500 }),\n        jasmine.objectContaining({ message: TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, speed: 1000 }),\n        jasmine.objectContaining({ usage: jasmine.objectContaining({ feature: 'stop-session' }) }),\n\n        // Group 2.\n        jasmine.objectContaining({ message: 'debug 2' }),\n        jasmine.objectContaining({ message: 'error 2' }),\n        jasmine.objectContaining({ message: TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, latency: 50 }),\n        jasmine.objectContaining({ message: TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, jank: 50 }),\n        jasmine.objectContaining({ usage: jasmine.objectContaining({ feature: 'start-session-replay-recording' }) }),\n      ])\n    })\n  })\n\n  describe('excluded sites', () => {\n    ;[\n      { site: INTAKE_SITE_US1_FED, enabled: false },\n      { site: INTAKE_SITE_US2_FED, enabled: false },\n      { site: INTAKE_SITE_US1, enabled: true },\n    ].forEach(({ site, enabled }) => {\n      it(`should be ${enabled ? 'enabled' : 'disabled'} on ${site}`, async () => {\n        const { getTelemetryEvents } = startAndSpyTelemetry({ site })\n\n        callMonitored(() => {\n          throw new Error('message')\n        })\n\n        const events = await getTelemetryEvents()\n        if (enabled) {\n          expect(events.length).toBe(1)\n        } else {\n          expect(events.length).toBe(0)\n        }\n      })\n    })\n  })\n})\n\ndescribe('startTelemetryTransport', () => {\n  it('should send telemetry events through transport', () => {\n    const interceptor = interceptRequests()\n    const telemetryObservable = new Observable<TelemetryEvent & Context>()\n\n    const { stop } = startTelemetryTransport(\n      validateAndBuildConfiguration({ clientToken: 'xxx' })!,\n      telemetryObservable\n    )\n\n    registerCleanupTask(stop)\n\n    // Trigger a telemetry event by notifying the observable\n    telemetryObservable.notify({\n      type: 'telemetry',\n      date: 123 as TimeStamp,\n      service: TelemetryService.RUM,\n      version: '0.0.0',\n      source: 'browser',\n      telemetry: {\n        type: TelemetryType.LOG,\n        status: StatusType.error,\n        message: 'test error',\n      },\n      _dd: {\n        format_version: 2,\n      },\n    })\n\n    // Force the batch to flush by emulating a beforeunload event\n    window.dispatchEvent(createNewEvent('beforeunload'))\n\n    expect(interceptor.requests.length).toBe(1)\n    const telemetryEvent = JSON.parse(interceptor.requests[0].body)\n    expect(telemetryEvent.type).toBe('telemetry')\n    expect(telemetryEvent.telemetry.type).toBe(TelemetryType.LOG)\n    expect(telemetryEvent.telemetry.status).toBe(StatusType.error)\n  })\n})\n\ndescribe('formatError', () => {\n  it('formats error instances', () => {\n    expect(formatError(new Error('message'))).toEqual({\n      message: 'message',\n      error: {\n        kind: 'Error',\n        stack: jasmine.stringMatching(/^Error: message(\\n|$)/) as unknown as string,\n      },\n    })\n  })\n\n  it('formats strings', () => {\n    expect(formatError('message')).toEqual({\n      message: 'Uncaught \"message\"',\n      error: {\n        stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n      },\n    })\n  })\n\n  it('formats objects', () => {\n    expect(formatError({ foo: 'bar' })).toEqual({\n      message: 'Uncaught {\"foo\":\"bar\"}',\n      error: {\n        stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n      },\n    })\n  })\n})\n\ndescribe('scrubCustomerFrames', () => {\n  it('should remove stack trace frames that are related to customer files', () => {\n    ;[\n      { scrub: false, url: 'https://www.datadoghq-browser-agent.com/datadog-rum-v4.js' },\n      { scrub: false, url: 'https://www.datad0g-browser-agent.com/datadog-rum-v5.js' },\n      { scrub: false, url: 'https://d3uc069fcn7uxw.cloudfront.net/datadog-logs-staging.js' },\n      { scrub: false, url: 'https://d20xtzwzcl0ceb.cloudfront.net/datadog-rum-canary.js' },\n      { scrub: false, url: 'http://localhost/index.html' },\n      { scrub: false, url: undefined },\n      { scrub: false, url: '<anonymous>' },\n      { scrub: true, url: 'https://foo.bar/path?qux=qix' },\n    ].forEach(({ url, scrub }) => {\n      const candidate: Partial<StackTrace> = {\n        stack: [{ url }],\n      }\n      expect(scrubCustomerFrames(candidate as StackTrace).stack.length).toBe(scrub ? 0 : 1, `for url: ${url!}`)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/telemetry/telemetry.ts",
    "content": "import type { Context } from '../../tools/serialisation/context'\nimport { ConsoleApiName } from '../../tools/display'\nimport { NO_ERROR_STACK_PRESENT_MESSAGE, isError } from '../error/error'\nimport { toStackTraceString } from '../../tools/stackTrace/handlingStack'\nimport { getExperimentalFeatures } from '../../tools/experimentalFeatures'\nimport type { Configuration } from '../configuration'\nimport { buildTags } from '../tags'\nimport { INTAKE_SITE_STAGING, INTAKE_SITE_US1_FED, INTAKE_SITE_US2_FED } from '../intakeSites'\nimport { BufferedObservable, Observable } from '../../tools/observable'\nimport { clocksNow } from '../../tools/utils/timeUtils'\nimport { displayIfDebugEnabled, startMonitorErrorCollection } from '../../tools/monitor'\nimport { sendToExtension } from '../../tools/sendToExtension'\nimport { performDraw } from '../../tools/utils/numberUtils'\nimport { jsonStringify } from '../../tools/serialisation/jsonStringify'\nimport { combine } from '../../tools/mergeInto'\nimport { NonErrorPrefix } from '../error/error.types'\nimport type { StackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { computeStackTrace } from '../../tools/stackTrace/computeStackTrace'\nimport { getConnectivity } from '../connectivity'\nimport {\n  canUseEventBridge,\n  createFlushController,\n  createHttpRequest,\n  getEventBridge,\n  createBatch,\n} from '../../transport'\nimport { createIdentityEncoder } from '../../tools/encoder'\nimport { createPageMayExitObservable } from '../../browser/pageMayExitObservable'\nimport type { AbstractHooks, RecursivePartial } from '../../tools/abstractHooks'\nimport { HookNames, DISCARDED } from '../../tools/abstractHooks'\nimport { globalObject, isWorkerEnvironment } from '../../tools/globalObject'\nimport { noop } from '../../tools/utils/functionUtils'\nimport type { TelemetryEvent } from './telemetryEvent.types'\nimport type {\n  RawTelemetryConfiguration,\n  RawTelemetryEvent,\n  RuntimeEnvInfo,\n  RawTelemetryUsage,\n} from './rawTelemetryEvent.types'\nimport { StatusType, TelemetryType } from './rawTelemetryEvent.types'\n\n// replaced at build time\ndeclare const __BUILD_ENV__SDK_VERSION__: string\ndeclare const __BUILD_ENV__SDK_SETUP__: string\n\nconst ALLOWED_FRAME_URLS = [\n  'https://www.datadoghq-browser-agent.com',\n  'https://www.datad0g-browser-agent.com',\n  'https://d3uc069fcn7uxw.cloudfront.net',\n  'https://d20xtzwzcl0ceb.cloudfront.net',\n  'http://localhost',\n  '<anonymous>',\n]\n\nexport const enum TelemetryService {\n  LOGS = 'browser-logs-sdk',\n  RUM = 'browser-rum-sdk',\n}\n\nexport interface Telemetry {\n  stop: () => void\n  enabled: boolean\n  metricsEnabled: boolean\n}\n\nexport const enum TelemetryMetrics {\n  CUSTOMER_DATA_METRIC_NAME = 'Customer data measures',\n  REMOTE_CONFIGURATION_METRIC_NAME = 'remote configuration metrics',\n  RECORDER_INIT_METRICS_TELEMETRY_NAME = 'Recorder init metrics',\n  SEGMENT_METRICS_TELEMETRY_NAME = 'Segment network request metrics',\n  INITIAL_VIEW_METRICS_TELEMETRY_NAME = 'Initial view metrics',\n}\n\nconst METRIC_SAMPLE_RATE = 1\n\nconst TELEMETRY_EXCLUDED_SITES: string[] = [INTAKE_SITE_US1_FED, INTAKE_SITE_US2_FED]\nconst MAX_TELEMETRY_EVENTS_PER_PAGE = 15\n\nlet telemetryObservable: BufferedObservable<{ rawEvent: RawTelemetryEvent; metricName?: string }> | undefined\n\nexport function getTelemetryObservable() {\n  if (!telemetryObservable) {\n    telemetryObservable = new BufferedObservable(100)\n  }\n  return telemetryObservable\n}\n\nexport function startTelemetry(\n  telemetryService: TelemetryService,\n  configuration: Configuration,\n  hooks: AbstractHooks\n): Telemetry {\n  const observable = new Observable<TelemetryEvent & Context>()\n  const { enabled, metricsEnabled } = startTelemetryCollection(telemetryService, configuration, hooks, observable)\n  const { stop } = startTelemetryTransport(configuration, observable)\n  return {\n    stop,\n    enabled,\n    metricsEnabled,\n  }\n}\n\nexport function startTelemetryCollection(\n  telemetryService: TelemetryService,\n  configuration: Configuration,\n  hooks: AbstractHooks,\n  observable: Observable<TelemetryEvent & Context>,\n  metricSampleRate = METRIC_SAMPLE_RATE,\n  maxTelemetryEventsPerPage = MAX_TELEMETRY_EVENTS_PER_PAGE\n) {\n  const alreadySentEventsByKind: Record<string, Set<string>> = {}\n\n  const telemetryEnabled =\n    !TELEMETRY_EXCLUDED_SITES.includes(configuration.site) && performDraw(configuration.telemetrySampleRate)\n\n  const telemetryEnabledPerType = {\n    [TelemetryType.LOG]: telemetryEnabled,\n    [TelemetryType.CONFIGURATION]: telemetryEnabled && performDraw(configuration.telemetryConfigurationSampleRate),\n    [TelemetryType.USAGE]: telemetryEnabled && performDraw(configuration.telemetryUsageSampleRate),\n    // not an actual \"type\" but using a single draw for all metrics\n    metric: telemetryEnabled && performDraw(metricSampleRate),\n  }\n\n  const runtimeEnvInfo = getRuntimeEnvInfo()\n  const telemetryObservable = getTelemetryObservable()\n  telemetryObservable.subscribe(({ rawEvent, metricName }) => {\n    if ((metricName && !telemetryEnabledPerType['metric']) || !telemetryEnabledPerType[rawEvent.type!]) {\n      return\n    }\n\n    const kind = metricName || (rawEvent.status as string | undefined) || rawEvent.type!\n    let alreadySentEvents = alreadySentEventsByKind[kind]\n    if (!alreadySentEvents) {\n      alreadySentEvents = alreadySentEventsByKind[kind] = new Set()\n    }\n\n    if (alreadySentEvents.size >= maxTelemetryEventsPerPage) {\n      return\n    }\n\n    const stringifiedEvent = jsonStringify(rawEvent)!\n    if (alreadySentEvents.has(stringifiedEvent)) {\n      return\n    }\n\n    const defaultTelemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n      startTime: clocksNow().relative,\n    })\n\n    if (defaultTelemetryEventAttributes === DISCARDED) {\n      return\n    }\n    const event = toTelemetryEvent(\n      defaultTelemetryEventAttributes as RecursivePartial<TelemetryEvent>,\n      telemetryService,\n      rawEvent,\n      runtimeEnvInfo\n    )\n    observable.notify(event)\n    sendToExtension('telemetry', event)\n    alreadySentEvents.add(stringifiedEvent)\n  })\n  telemetryObservable.unbuffer()\n\n  startMonitorErrorCollection(addTelemetryError)\n\n  return {\n    enabled: telemetryEnabled,\n    metricsEnabled: telemetryEnabledPerType['metric'],\n  }\n\n  function toTelemetryEvent(\n    defaultTelemetryEventAttributes: RecursivePartial<TelemetryEvent>,\n    telemetryService: TelemetryService,\n    rawEvent: RawTelemetryEvent,\n    runtimeEnvInfo: RuntimeEnvInfo\n  ): TelemetryEvent & Context {\n    const clockNow = clocksNow()\n\n    const event = {\n      type: 'telemetry' as const,\n      date: clockNow.timeStamp,\n      service: telemetryService,\n      version: __BUILD_ENV__SDK_VERSION__,\n      source: 'browser' as const,\n      _dd: {\n        format_version: 2 as const,\n      },\n      telemetry: combine(rawEvent, {\n        runtime_env: runtimeEnvInfo,\n        connectivity: getConnectivity(),\n        sdk_setup: __BUILD_ENV__SDK_SETUP__,\n      }) as TelemetryEvent['telemetry'],\n      ddtags: buildTags(configuration).join(','),\n      experimental_features: Array.from(getExperimentalFeatures()),\n    }\n\n    return combine(event, defaultTelemetryEventAttributes) as TelemetryEvent & Context\n  }\n}\n\nexport function startTelemetryTransport(\n  configuration: Configuration,\n  telemetryObservable: Observable<TelemetryEvent & Context>\n) {\n  const cleanupTasks: Array<() => void> = []\n  if (canUseEventBridge()) {\n    const bridge = getEventBridge<'internal_telemetry', TelemetryEvent>()!\n    const telemetrySubscription = telemetryObservable.subscribe((event) => bridge.send('internal_telemetry', event))\n    cleanupTasks.push(telemetrySubscription.unsubscribe)\n  } else {\n    const endpoints = [configuration.rumEndpointBuilder]\n    if (configuration.replica && isTelemetryReplicationAllowed(configuration)) {\n      endpoints.push(configuration.replica.rumEndpointBuilder)\n    }\n    const telemetryBatch = createBatch({\n      encoder: createIdentityEncoder(),\n      request: createHttpRequest(\n        endpoints,\n        // Ignore transport errors for telemetry\n        noop\n      ),\n      flushController: createFlushController({\n        pageMayExitObservable: createPageMayExitObservable(configuration),\n\n        // We don't use an actual session expire observable here, to make telemetry collection\n        // independent of the session. This allows to start and send telemetry events earlier.\n        sessionExpireObservable: new Observable(),\n      }),\n    })\n    cleanupTasks.push(telemetryBatch.stop)\n    const telemetrySubscription = telemetryObservable.subscribe(telemetryBatch.add)\n    cleanupTasks.push(telemetrySubscription.unsubscribe)\n  }\n\n  return {\n    stop: () => cleanupTasks.forEach((task) => task()),\n  }\n}\n\nfunction getRuntimeEnvInfo(): RuntimeEnvInfo {\n  return {\n    is_local_file: globalObject.location?.protocol === 'file:',\n    is_worker: isWorkerEnvironment,\n  }\n}\n\nexport function resetTelemetry() {\n  telemetryObservable = undefined\n}\n\n/**\n * Avoid mixing telemetry events from different data centers\n * but keep replicating staging events for reliability\n */\nfunction isTelemetryReplicationAllowed(configuration: Configuration) {\n  return configuration.site === INTAKE_SITE_STAGING\n}\n\nexport function addTelemetryDebug(message: string, context?: Context) {\n  displayIfDebugEnabled(ConsoleApiName.debug, message, context)\n  getTelemetryObservable().notify({\n    rawEvent: {\n      type: TelemetryType.LOG,\n      message,\n      status: StatusType.debug,\n      ...context,\n    },\n  })\n}\n\nexport function addTelemetryError(e: unknown, context?: Context) {\n  getTelemetryObservable().notify({\n    rawEvent: {\n      type: TelemetryType.LOG,\n      status: StatusType.error,\n      ...formatError(e),\n      ...context,\n    },\n  })\n}\n\nexport function addTelemetryConfiguration(configuration: RawTelemetryConfiguration) {\n  getTelemetryObservable().notify({\n    rawEvent: {\n      type: TelemetryType.CONFIGURATION,\n      configuration,\n    },\n  })\n}\n\nexport function addTelemetryMetrics(metricName: TelemetryMetrics, context?: Context) {\n  getTelemetryObservable().notify({\n    rawEvent: {\n      type: TelemetryType.LOG,\n      message: metricName,\n      status: StatusType.debug,\n      ...context,\n    },\n    metricName,\n  })\n}\n\nexport function addTelemetryUsage(usage: RawTelemetryUsage) {\n  getTelemetryObservable().notify({\n    rawEvent: {\n      type: TelemetryType.USAGE,\n      usage,\n    },\n  })\n}\n\nexport function formatError(e: unknown) {\n  if (isError(e)) {\n    const stackTrace = computeStackTrace(e)\n    return {\n      error: {\n        kind: stackTrace.name,\n        stack: toStackTraceString(scrubCustomerFrames(stackTrace)),\n      },\n      message: stackTrace.message!,\n    }\n  }\n  return {\n    error: {\n      stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n    },\n    message: `${NonErrorPrefix.UNCAUGHT} ${jsonStringify(e)!}`,\n  }\n}\n\nexport function scrubCustomerFrames(stackTrace: StackTrace) {\n  stackTrace.stack = stackTrace.stack.filter(\n    (frame) => !frame.url || ALLOWED_FRAME_URLS.some((allowedFrameUrl) => frame.url!.startsWith(allowedFrameUrl))\n  )\n  return stackTrace\n}\n"
  },
  {
    "path": "packages/core/src/domain/telemetry/telemetryEvent.types.ts",
    "content": "/**\n * DO NOT MODIFY IT BY HAND. Run `yarn json-schemas:sync` instead.\n */\n\n/**\n * Schema of all properties of a telemetry event\n */\nexport type TelemetryEvent =\n  | TelemetryErrorEvent\n  | TelemetryDebugEvent\n  | TelemetryConfigurationEvent\n  | TelemetryUsageEvent\n/**\n * Schema of all properties of a telemetry error event\n */\nexport type TelemetryErrorEvent = CommonTelemetryProperties & {\n  /**\n   * The telemetry log information\n   */\n  telemetry: {\n    /**\n     * Telemetry type\n     */\n    type?: 'log'\n    /**\n     * Level/severity of the log\n     */\n    status: 'error'\n    /**\n     * Body of the log\n     */\n    message: string\n    /**\n     * Error properties\n     */\n    error?: {\n      /**\n       * The stack trace or the complementary information about the error\n       */\n      stack?: string\n      /**\n       * The error type or kind (or code in some cases)\n       */\n      kind?: string\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of all properties of a telemetry debug event\n */\nexport type TelemetryDebugEvent = CommonTelemetryProperties & {\n  /**\n   * The telemetry log information\n   */\n  telemetry: {\n    /**\n     * Telemetry type\n     */\n    type?: 'log'\n    /**\n     * Level/severity of the log\n     */\n    status: 'debug'\n    /**\n     * Body of the log\n     */\n    message: string\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of all properties of a telemetry configuration event\n */\nexport type TelemetryConfigurationEvent = CommonTelemetryProperties & {\n  /**\n   * The telemetry configuration information\n   */\n  telemetry: {\n    /**\n     * Telemetry type\n     */\n    type: 'configuration'\n    /**\n     * Configuration properties\n     */\n    configuration: {\n      /**\n       * The percentage of sessions tracked\n       */\n      session_sample_rate?: number\n      /**\n       * The percentage of telemetry events sent\n       */\n      telemetry_sample_rate?: number\n      /**\n       * The percentage of telemetry configuration events sent after being sampled by telemetry_sample_rate\n       */\n      telemetry_configuration_sample_rate?: number\n      /**\n       * The percentage of telemetry usage events sent after being sampled by telemetry_sample_rate\n       */\n      telemetry_usage_sample_rate?: number\n      /**\n       * The percentage of requests traced\n       */\n      trace_sample_rate?: number\n      /**\n       * The opt-in configuration to add trace context\n       */\n      trace_context_injection?: 'all' | 'sampled'\n      /**\n       * The percentage of sessions with Browser RUM & Session Replay pricing tracked (deprecated in favor of session_replay_sample_rate)\n       */\n      premium_sample_rate?: number\n      /**\n       * The percentage of sessions with Browser RUM & Session Replay pricing tracked (deprecated in favor of session_replay_sample_rate)\n       */\n      replay_sample_rate?: number\n      /**\n       * The percentage of sessions with RUM & Session Replay pricing tracked\n       */\n      session_replay_sample_rate?: number\n      /**\n       * The initial tracking consent value\n       */\n      tracking_consent?: 'granted' | 'not-granted' | 'pending'\n      /**\n       * Whether the session replay start is handled manually\n       */\n      start_session_replay_recording_manually?: boolean\n      /**\n       * Whether Session Replay should automatically start a recording when enabled\n       */\n      start_recording_immediately?: boolean\n      /**\n       * Whether a proxy is used\n       */\n      use_proxy?: boolean\n      /**\n       * Whether beforeSend callback function is used\n       */\n      use_before_send?: boolean\n      /**\n       * Whether initialization fails silently if the SDK is already initialized\n       */\n      silent_multiple_init?: boolean\n      /**\n       * Whether sessions across subdomains for the same site are tracked\n       */\n      track_session_across_subdomains?: boolean\n      /**\n       * Whether resources are tracked\n       */\n      track_resources?: boolean\n      /**\n       * Whether early requests are tracked\n       */\n      track_early_requests?: boolean\n      /**\n       * Whether long tasks are tracked\n       */\n      track_long_task?: boolean\n      /**\n       * Whether views loaded from the bfcache are tracked\n       */\n      track_bfcache_views?: boolean\n      /**\n       * Whether a secure cross-site session cookie is used (deprecated)\n       */\n      use_cross_site_session_cookie?: boolean\n      /**\n       * Whether a partitioned secure cross-site session cookie is used\n       */\n      use_partitioned_cross_site_session_cookie?: boolean\n      /**\n       * Whether a secure session cookie is used\n       */\n      use_secure_session_cookie?: boolean\n      /**\n       * Whether it is allowed to use LocalStorage when cookies are not available (deprecated in favor of session_persistence)\n       */\n      allow_fallback_to_local_storage?: boolean\n      /**\n       * Configure the storage strategy for persisting sessions\n       */\n      session_persistence?: 'local-storage' | 'cookie' | 'memory'\n      /**\n       * Whether contexts are stored in local storage\n       */\n      store_contexts_across_pages?: boolean\n      /**\n       * Whether untrusted events are allowed\n       */\n      allow_untrusted_events?: boolean\n      /**\n       * Attribute to be used to name actions\n       */\n      action_name_attribute?: string\n      /**\n       * Whether the allowed tracing origins list is used (deprecated in favor of use_allowed_tracing_urls)\n       */\n      use_allowed_tracing_origins?: boolean\n      /**\n       * Whether the allowed tracing urls list is used\n       */\n      use_allowed_tracing_urls?: boolean\n      /**\n       * Whether the allowed GraphQL urls list is used\n       */\n      use_allowed_graph_ql_urls?: boolean\n      /**\n       * Whether GraphQL payload tracking is used for at least one GraphQL endpoint\n       */\n      use_track_graph_ql_payload?: boolean\n      /**\n       * Whether GraphQL response errors tracking is used for at least one GraphQL endpoint\n       */\n      use_track_graph_ql_response_errors?: boolean\n      /**\n       * A list of selected tracing propagators\n       */\n      selected_tracing_propagators?: ('datadog' | 'b3' | 'b3multi' | 'tracecontext')[]\n      /**\n       * Session replay default privacy level\n       */\n      default_privacy_level?: string\n      /**\n       * Session replay text and input privacy level\n       */\n      text_and_input_privacy_level?: string\n      /**\n       * Session replay image privacy level\n       */\n      image_privacy_level?: string\n      /**\n       * Session replay touch privacy level\n       */\n      touch_privacy_level?: string\n      /**\n       * Privacy control for action name\n       */\n      enable_privacy_for_action_name?: boolean\n      /**\n       * Whether the request origins list to ignore when computing the page activity is used\n       */\n      use_excluded_activity_urls?: boolean\n      /**\n       * Whether the Worker is loaded from an external URL\n       */\n      use_worker_url?: boolean\n      /**\n       * Whether intake requests are compressed\n       */\n      compress_intake_requests?: boolean\n      /**\n       * Whether user frustrations are tracked\n       */\n      track_frustrations?: boolean\n      /**\n       * Whether the RUM views creation is handled manually\n       */\n      track_views_manually?: boolean\n      /**\n       * Whether user actions are tracked (deprecated in favor of track_user_interactions)\n       */\n      track_interactions?: boolean\n      /**\n       * Whether user actions are tracked\n       */\n      track_user_interactions?: boolean\n      /**\n       * Whether console.error logs, uncaught exceptions and network errors are tracked\n       */\n      forward_errors_to_logs?: boolean\n      /**\n       * The number of displays available to the device\n       */\n      number_of_displays?: number\n      /**\n       * The console.* tracked\n       */\n      forward_console_logs?: string[] | 'all'\n      /**\n       * The reports from the Reporting API tracked\n       */\n      forward_reports?: string[] | 'all'\n      /**\n       * Whether local encryption is used\n       */\n      use_local_encryption?: boolean\n      /**\n       * View tracking strategy\n       */\n      view_tracking_strategy?:\n        | 'ActivityViewTrackingStrategy'\n        | 'FragmentViewTrackingStrategy'\n        | 'MixedViewTrackingStrategy'\n        | 'NavigationViewTrackingStrategy'\n      /**\n       * Whether SwiftUI view instrumentation is enabled\n       */\n      swiftui_view_tracking_enabled?: boolean\n      /**\n       * Whether SwiftUI action instrumentation is enabled\n       */\n      swiftui_action_tracking_enabled?: boolean\n      /**\n       * Whether RUM events are tracked when the application is in Background\n       */\n      track_background_events?: boolean\n      /**\n       * The period between each Mobile Vital sample (in milliseconds)\n       */\n      mobile_vitals_update_period?: number\n      /**\n       * Whether error monitoring & crash reporting is enabled for the source platform\n       */\n      track_errors?: boolean\n      /**\n       * Whether automatic collection of network requests is enabled\n       */\n      track_network_requests?: boolean\n      /**\n       * Whether tracing features are enabled\n       */\n      use_tracing?: boolean\n      /**\n       * Whether native views are tracked (for cross platform SDKs)\n       */\n      track_native_views?: boolean\n      /**\n       * Whether native error monitoring & crash reporting is enabled (for cross platform SDKs)\n       */\n      track_native_errors?: boolean\n      /**\n       * Whether long task tracking is performed automatically\n       */\n      track_native_long_tasks?: boolean\n      /**\n       * Whether long task tracking is performed automatically for cross platform SDKs\n       */\n      track_cross_platform_long_tasks?: boolean\n      /**\n       * Whether the client has provided a list of first party hosts\n       */\n      use_first_party_hosts?: boolean\n      /**\n       * The type of initialization the SDK used, in case multiple are supported\n       */\n      initialization_type?: string\n      /**\n       * Whether Flutter build and raster time tracking is enabled\n       */\n      track_flutter_performance?: boolean\n      /**\n       * The window duration for batches sent by the SDK (in milliseconds)\n       */\n      batch_size?: number\n      /**\n       * The upload frequency of batches (in milliseconds)\n       */\n      batch_upload_frequency?: number\n      /**\n       * Maximum number of batches processed sequentially without a delay\n       */\n      batch_processing_level?: number\n      /**\n       * Whether UIApplication background tasks are enabled\n       */\n      background_tasks_enabled?: boolean\n      /**\n       * The version of React used in a ReactNative application\n       */\n      react_version?: string\n      /**\n       * The version of ReactNative used in a ReactNative application\n       */\n      react_native_version?: string\n      /**\n       * The version of Dart used in a Flutter application\n       */\n      dart_version?: string\n      /**\n       * The version of Unity used in a Unity application\n       */\n      unity_version?: string\n      /**\n       * The threshold used for iOS App Hangs monitoring (in milliseconds)\n       */\n      app_hang_threshold?: number\n      /**\n       * Whether logs are sent to the PCI-compliant intake\n       */\n      use_pci_intake?: boolean\n      /**\n       * The tracer API used by the SDK. Possible values: 'Datadog', 'OpenTelemetry', 'OpenTracing'\n       */\n      tracer_api?: string\n      /**\n       * The version of the tracer API used by the SDK. Eg. '0.1.0'\n       */\n      tracer_api_version?: string\n      /**\n       * Whether logs are sent after the session expiration\n       */\n      send_logs_after_session_expiration?: boolean\n      /**\n       * The list of plugins enabled\n       */\n      plugins?: {\n        /**\n         * The name of the plugin\n         */\n        name: string\n        [k: string]: unknown\n      }[]\n      /**\n       * Whether the SDK is initialised on the application's main or a secondary process\n       */\n      is_main_process?: boolean\n      /**\n       * Interval in milliseconds when the last action is considered as the action that created the next view. Only sent if a time based strategy has been used\n       */\n      inv_time_threshold_ms?: number\n      /**\n       * The interval in milliseconds during which all network requests will be considered as initial, i.e. caused by the creation of this view. Only sent if a time based strategy has been used\n       */\n      tns_time_threshold_ms?: number\n      /**\n       * The list of events that include feature flags collection. The tracking is always enabled for views and errors.\n       */\n      track_feature_flags_for_events?: ('vital' | 'resource' | 'action' | 'long_task')[]\n      /**\n       * Whether the anonymous users are tracked\n       */\n      track_anonymous_user?: boolean\n      /**\n       * Whether a list of allowed origins is used to control SDK execution in browser extension contexts. When enabled, the SDK will check if the current origin matches the allowed origins list before running.\n       */\n      use_allowed_tracking_origins?: boolean\n      /**\n       * The version of the SDK that is running.\n       */\n      sdk_version?: string\n      /**\n       * The source of the SDK, e.g., 'browser', 'ios', 'android', 'flutter', 'react-native', 'unity', 'kotlin-multiplatform'.\n       */\n      source?: string\n      /**\n       * The variant of the SDK build (e.g., standard, lite, etc.).\n       */\n      variant?: string\n      /**\n       * The id of the remote configuration\n       */\n      remote_configuration_id?: string\n      /**\n       * Whether a proxy is used for remote configuration\n       */\n      use_remote_configuration_proxy?: boolean\n      /**\n       * The percentage of sessions with Profiling enabled\n       */\n      profiling_sample_rate?: number\n      /**\n       * Whether trace baggage is propagated to child spans\n       */\n      propagate_trace_baggage?: boolean\n      /**\n       * Whether the beta encode cookie options is enabled\n       */\n      beta_encode_cookie_options?: boolean\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of all properties of a telemetry usage event\n */\nexport type TelemetryUsageEvent = CommonTelemetryProperties & {\n  /**\n   * The telemetry usage information\n   */\n  telemetry: {\n    /**\n     * Telemetry type\n     */\n    type: 'usage'\n    usage: TelemetryCommonFeaturesUsage | TelemetryBrowserFeaturesUsage | TelemetryMobileFeaturesUsage\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of features usage common across SDKs\n */\nexport type TelemetryCommonFeaturesUsage =\n  | SetTrackingConsent\n  | StopSession\n  | StartView\n  | SetViewContext\n  | SetViewContextProperty\n  | SetViewName\n  | GetViewContext\n  | AddAction\n  | AddError\n  | GetGlobalContext\n  | SetGlobalContext\n  | SetGlobalContextProperty\n  | RemoveGlobalContextProperty\n  | ClearGlobalContext\n  | GetUser\n  | SetUser\n  | SetUserProperty\n  | RemoveUserProperty\n  | ClearUser\n  | GetAccount\n  | SetAccount\n  | SetAccountProperty\n  | RemoveAccountProperty\n  | ClearAccount\n  | AddFeatureFlagEvaluation\n  | AddOperationStepVital\n  | GraphQLRequest\n  | AddViewLoadingTime\n/**\n * Schema of browser specific features usage\n */\nexport type TelemetryBrowserFeaturesUsage =\n  | StartSessionReplayRecording\n  | StartDurationVital\n  | StopDurationVital\n  | AddDurationVital\n  | StartAction\n  | StopAction\n  | StartResource\n  | StopResource\n/**\n * Schema of mobile specific features usage\n */\nexport type TelemetryMobileFeaturesUsage = TrackWebView | AndroidNetworkInstrumentation\n\n/**\n * Schema of common properties of Telemetry events\n */\nexport interface CommonTelemetryProperties {\n  /**\n   * Internal properties\n   */\n  _dd: {\n    /**\n     * Version of the RUM event format\n     */\n    readonly format_version: 2\n    [k: string]: unknown\n  }\n  /**\n   * Telemetry event type. Should specify telemetry only.\n   */\n  readonly type: 'telemetry'\n  /**\n   * Start of the event in ms from epoch\n   */\n  date: number\n  /**\n   * The SDK generating the telemetry event\n   */\n  service: string\n  /**\n   * The source of this event\n   */\n  readonly source:\n    | 'android'\n    | 'ios'\n    | 'browser'\n    | 'flutter'\n    | 'react-native'\n    | 'unity'\n    | 'kotlin-multiplatform'\n    | 'electron'\n    | 'rum-cpp'\n  /**\n   * The version of the SDK generating the telemetry event\n   */\n  version: string\n  /**\n   * Application properties\n   */\n  readonly application?: {\n    /**\n     * UUID of the application\n     */\n    id: string\n    [k: string]: unknown\n  }\n  /**\n   * Session properties\n   */\n  session?: {\n    /**\n     * UUID of the session\n     */\n    id: string\n    [k: string]: unknown\n  }\n  /**\n   * View properties\n   */\n  view?: {\n    /**\n     * UUID of the view\n     */\n    id: string\n    [k: string]: unknown\n  }\n  /**\n   * Action properties\n   */\n  action?: {\n    /**\n     * UUID of the action\n     */\n    id: string\n    [k: string]: unknown\n  }\n  /**\n   * The actual percentage of telemetry usage per event\n   */\n  effective_sample_rate?: number\n  /**\n   * Enabled experimental features\n   */\n  readonly experimental_features?: string[]\n  telemetry?: {\n    /**\n     * Device properties\n     */\n    device?: {\n      /**\n       * Architecture of the device\n       */\n      architecture?: string\n      /**\n       * Brand of the device\n       */\n      brand?: string\n      /**\n       * Model of the device\n       */\n      model?: string\n      /**\n       * Number of logical CPU cores available for scheduling on the device at runtime, as reported by the operating system.\n       */\n      readonly logical_cpu_count?: number\n      /**\n       * Total RAM in megabytes\n       */\n      readonly total_ram?: number\n      /**\n       * Whether the device is considered a low RAM device (Android)\n       */\n      readonly is_low_ram?: boolean\n      [k: string]: unknown\n    }\n    /**\n     * OS properties\n     */\n    os?: {\n      /**\n       * Build of the OS\n       */\n      build?: string\n      /**\n       * Name of the OS\n       */\n      name?: string\n      /**\n       * Version of the OS\n       */\n      version?: string\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\nexport interface SetTrackingConsent {\n  /**\n   * setTrackingConsent API\n   */\n  feature: 'set-tracking-consent'\n  /**\n   * The tracking consent value set by the user\n   */\n  tracking_consent: 'granted' | 'not-granted' | 'pending'\n  [k: string]: unknown\n}\nexport interface StopSession {\n  /**\n   * stopSession API\n   */\n  feature: 'stop-session'\n  [k: string]: unknown\n}\nexport interface StartView {\n  /**\n   * startView API\n   */\n  feature: 'start-view'\n  [k: string]: unknown\n}\nexport interface SetViewContext {\n  /**\n   * setViewContext API\n   */\n  feature: 'set-view-context'\n  [k: string]: unknown\n}\nexport interface SetViewContextProperty {\n  /**\n   * setViewContextProperty API\n   */\n  feature: 'set-view-context-property'\n  [k: string]: unknown\n}\nexport interface SetViewName {\n  /**\n   * setViewName API\n   */\n  feature: 'set-view-name'\n  [k: string]: unknown\n}\nexport interface GetViewContext {\n  /**\n   * getViewContext API\n   */\n  feature: 'get-view-context'\n  [k: string]: unknown\n}\nexport interface AddAction {\n  /**\n   * addAction API\n   */\n  feature: 'add-action'\n  [k: string]: unknown\n}\nexport interface AddError {\n  /**\n   * addError API\n   */\n  feature: 'add-error'\n  [k: string]: unknown\n}\nexport interface GetGlobalContext {\n  /**\n   * getGlobalContext API\n   */\n  feature: 'get-global-context'\n  [k: string]: unknown\n}\nexport interface SetGlobalContext {\n  /**\n   * setGlobalContext, addAttribute APIs\n   */\n  feature: 'set-global-context'\n  [k: string]: unknown\n}\nexport interface SetGlobalContextProperty {\n  /**\n   * setGlobalContextProperty API\n   */\n  feature: 'set-global-context-property'\n  [k: string]: unknown\n}\nexport interface RemoveGlobalContextProperty {\n  /**\n   * removeGlobalContextProperty API\n   */\n  feature: 'remove-global-context-property'\n  [k: string]: unknown\n}\nexport interface ClearGlobalContext {\n  /**\n   * clearGlobalContext API\n   */\n  feature: 'clear-global-context'\n  [k: string]: unknown\n}\nexport interface GetUser {\n  /**\n   * getUser API\n   */\n  feature: 'get-user'\n  [k: string]: unknown\n}\nexport interface SetUser {\n  /**\n   * setUser, setUserInfo APIs\n   */\n  feature: 'set-user'\n  [k: string]: unknown\n}\nexport interface SetUserProperty {\n  /**\n   * setUserProperty API\n   */\n  feature: 'set-user-property'\n  [k: string]: unknown\n}\nexport interface RemoveUserProperty {\n  /**\n   * removeUserProperty API\n   */\n  feature: 'remove-user-property'\n  [k: string]: unknown\n}\nexport interface ClearUser {\n  /**\n   * clearUser API\n   */\n  feature: 'clear-user'\n  [k: string]: unknown\n}\nexport interface GetAccount {\n  /**\n   * getAccount API\n   */\n  feature: 'get-account'\n  [k: string]: unknown\n}\nexport interface SetAccount {\n  /**\n   * setAccount, setAccountProperty APIs\n   */\n  feature: 'set-account'\n  [k: string]: unknown\n}\nexport interface SetAccountProperty {\n  /**\n   * setAccountProperty API\n   */\n  feature: 'set-account-property'\n  [k: string]: unknown\n}\nexport interface RemoveAccountProperty {\n  /**\n   * removeAccountProperty API\n   */\n  feature: 'remove-account-property'\n  [k: string]: unknown\n}\nexport interface ClearAccount {\n  /**\n   * clearAccount API\n   */\n  feature: 'clear-account'\n  [k: string]: unknown\n}\nexport interface AddFeatureFlagEvaluation {\n  /**\n   * addFeatureFlagEvaluation API\n   */\n  feature: 'add-feature-flag-evaluation'\n  [k: string]: unknown\n}\nexport interface AddOperationStepVital {\n  /**\n   * addOperationStepVital API\n   */\n  feature: 'add-operation-step-vital'\n  /**\n   * Operations step type\n   */\n  action_type: 'start' | 'succeed' | 'fail'\n  [k: string]: unknown\n}\nexport interface GraphQLRequest {\n  /**\n   * GraphQL request detected\n   */\n  feature: 'graphql-request'\n  [k: string]: unknown\n}\nexport interface AddViewLoadingTime {\n  /**\n   * addViewLoadingTime API\n   */\n  feature: 'addViewLoadingTime'\n  /**\n   * Whether the view is not available\n   */\n  no_view?: boolean\n  /**\n   * Whether the available view is not active\n   */\n  no_active_view?: boolean\n  /**\n   * Whether this call overwrote a previously set loading time\n   */\n  overwritten?: boolean\n  [k: string]: unknown\n}\nexport interface StartSessionReplayRecording {\n  /**\n   * startSessionReplayRecording API\n   */\n  feature: 'start-session-replay-recording'\n  /**\n   * Whether the recording is allowed to start even on sessions sampled out of replay\n   */\n  is_forced?: boolean\n  [k: string]: unknown\n}\nexport interface StartDurationVital {\n  /**\n   * startDurationVital API\n   */\n  feature: 'start-duration-vital'\n  [k: string]: unknown\n}\nexport interface StopDurationVital {\n  /**\n   * stopDurationVital API\n   */\n  feature: 'stop-duration-vital'\n  [k: string]: unknown\n}\nexport interface AddDurationVital {\n  /**\n   * addDurationVital API\n   */\n  feature: 'add-duration-vital'\n  [k: string]: unknown\n}\nexport interface StartAction {\n  /**\n   * startAction API\n   */\n  feature: 'start-action'\n  [k: string]: unknown\n}\nexport interface StopAction {\n  /**\n   * stopAction API\n   */\n  feature: 'stop-action'\n  [k: string]: unknown\n}\nexport interface StartResource {\n  /**\n   * startResource API\n   */\n  feature: 'start-resource'\n  [k: string]: unknown\n}\nexport interface StopResource {\n  /**\n   * stopResource API\n   */\n  feature: 'stop-resource'\n  [k: string]: unknown\n}\nexport interface TrackWebView {\n  /**\n   * trackWebView API\n   */\n  feature: 'trackWebView'\n  [k: string]: unknown\n}\nexport interface AndroidNetworkInstrumentation {\n  /**\n   * Android network instrumentation\n   */\n  feature: 'androidNetworkInstrumentation'\n  /**\n   * The network instrumentation API used\n   */\n  type: 'CRONET' | 'OKHTTP'\n  [k: string]: unknown\n}\n"
  },
  {
    "path": "packages/core/src/domain/trackingConsent.spec.ts",
    "content": "import { TrackingConsent, createTrackingConsentState } from './trackingConsent'\n\ndescribe('createTrackingConsentState', () => {\n  it('creates a tracking consent state', () => {\n    const trackingConsentState = createTrackingConsentState()\n    expect(trackingConsentState).toBeDefined()\n  })\n\n  it('defaults to not granted', () => {\n    const trackingConsentState = createTrackingConsentState()\n    expect(trackingConsentState.isGranted()).toBeFalse()\n  })\n\n  it('can be created with a default consent state', () => {\n    const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n    expect(trackingConsentState.isGranted()).toBeTrue()\n  })\n\n  it('can be updated to granted', () => {\n    const trackingConsentState = createTrackingConsentState()\n    trackingConsentState.update(TrackingConsent.GRANTED)\n    expect(trackingConsentState.isGranted()).toBeTrue()\n  })\n\n  it('notifies when the consent is updated', () => {\n    const spy = jasmine.createSpy()\n    const trackingConsentState = createTrackingConsentState()\n    trackingConsentState.observable.subscribe(spy)\n    trackingConsentState.update(TrackingConsent.GRANTED)\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('can init a consent state if not defined yet', () => {\n    const trackingConsentState = createTrackingConsentState()\n    trackingConsentState.tryToInit(TrackingConsent.GRANTED)\n    expect(trackingConsentState.isGranted()).toBeTrue()\n  })\n\n  it('does not init a consent state if already defined', () => {\n    const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n    trackingConsentState.tryToInit(TrackingConsent.NOT_GRANTED)\n    expect(trackingConsentState.isGranted()).toBeTrue()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/domain/trackingConsent.ts",
    "content": "import { Observable } from '../tools/observable'\n\nexport const TrackingConsent = {\n  GRANTED: 'granted',\n  NOT_GRANTED: 'not-granted',\n} as const\nexport type TrackingConsent = (typeof TrackingConsent)[keyof typeof TrackingConsent]\n\nexport interface TrackingConsentState {\n  tryToInit: (trackingConsent: TrackingConsent) => void\n  update: (trackingConsent: TrackingConsent) => void\n  isGranted: () => boolean\n  observable: Observable<void>\n}\n\nexport function createTrackingConsentState(currentConsent?: TrackingConsent): TrackingConsentState {\n  const observable = new Observable<void>()\n\n  return {\n    tryToInit(trackingConsent: TrackingConsent) {\n      if (!currentConsent) {\n        currentConsent = trackingConsent\n      }\n    },\n    update(trackingConsent: TrackingConsent) {\n      currentConsent = trackingConsent\n      observable.notify()\n    },\n    isGranted() {\n      return currentConsent === TrackingConsent.GRANTED\n    },\n    observable,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/index.ts",
    "content": "export type { Configuration, InitConfiguration, EndpointBuilder, ProxyFn } from './domain/configuration'\nexport {\n  validateAndBuildConfiguration,\n  DefaultPrivacyLevel,\n  TraceContextInjection,\n  serializeConfiguration,\n  isSampleRate,\n  buildEndpointHost,\n  isIntakeUrl,\n} from './domain/configuration'\nexport * from './domain/intakeSites'\nexport type { TrackingConsentState } from './domain/trackingConsent'\nexport { TrackingConsent, createTrackingConsentState } from './domain/trackingConsent'\nexport {\n  isExperimentalFeatureEnabled,\n  addExperimentalFeatures,\n  getExperimentalFeatures,\n  initFeatureFlags,\n  ExperimentalFeature,\n} from './tools/experimentalFeatures'\nexport { trackRuntimeError } from './domain/error/trackRuntimeError'\nexport type { StackTrace } from './tools/stackTrace/computeStackTrace'\nexport { computeStackTrace } from './tools/stackTrace/computeStackTrace'\nexport type { PublicApi } from './boot/init'\nexport { defineGlobal, makePublicApi } from './boot/init'\nexport { displayAlreadyInitializedError } from './boot/displayAlreadyInitializedError'\nexport { initReportObservable, RawReportType } from './domain/report/reportObservable'\nexport type {\n  Telemetry,\n  RawTelemetryEvent,\n  RawTelemetryConfiguration,\n  TelemetryEvent,\n  TelemetryErrorEvent,\n  TelemetryDebugEvent,\n  TelemetryConfigurationEvent,\n  TelemetryUsageEvent,\n  RawTelemetryUsage,\n  RawTelemetryUsageFeature,\n} from './domain/telemetry'\nexport {\n  startTelemetry,\n  addTelemetryDebug,\n  addTelemetryError,\n  TelemetryService,\n  TelemetryMetrics,\n  addTelemetryConfiguration,\n  addTelemetryUsage,\n  addTelemetryMetrics,\n} from './domain/telemetry'\nexport { monitored, monitor, callMonitored, setDebugMode, monitorError } from './tools/monitor'\nexport type { Subscription } from './tools/observable'\nexport { Observable, BufferedObservable } from './tools/observable'\nexport type { SessionManager } from './domain/session/sessionManager'\nexport { startSessionManager, stopSessionManager } from './domain/session/sessionManager'\nexport {\n  SESSION_TIME_OUT_DELAY, // Exposed for tests\n  SESSION_NOT_TRACKED,\n  SessionPersistence,\n} from './domain/session/sessionConstants'\nexport type { BandwidthStats, HttpRequest, HttpRequestEvent, Payload, FlushEvent, FlushReason } from './transport'\nexport {\n  createHttpRequest,\n  canUseEventBridge,\n  getEventBridge,\n  bridgeSupports,\n  BridgeCapability,\n  createBatch,\n  createFlushController,\n  FLUSH_DURATION_LIMIT,\n} from './transport'\nexport * from './tools/display'\nexport type { Encoder, EncoderResult } from './tools/encoder'\nexport { createIdentityEncoder } from './tools/encoder'\nexport * from './tools/utils/urlPolyfill'\nexport * from './tools/utils/timeUtils'\nexport * from './tools/utils/arrayUtils'\nexport * from './tools/serialisation/sanitize'\nexport * from './tools/globalObject'\nexport { AbstractLifeCycle } from './tools/abstractLifeCycle'\nexport * from './domain/eventRateLimiter/createEventRateLimiter'\nexport * from './tools/utils/browserDetection'\nexport { sendToExtension } from './tools/sendToExtension'\nexport { runOnReadyState, asyncRunOnReadyState } from './browser/runOnReadyState'\nexport { getZoneJsOriginalValue } from './tools/getZoneJsOriginalValue'\nexport { mockable } from './tools/mockable'\nexport type { InstrumentedMethodCall } from './tools/instrumentMethod'\nexport { instrumentMethod, instrumentSetter } from './tools/instrumentMethod'\nexport {\n  computeRawError,\n  getFileFromStackTraceString,\n  isError,\n  NO_ERROR_STACK_PRESENT_MESSAGE,\n} from './domain/error/error'\nexport { NonErrorPrefix } from './domain/error/error.types'\nexport type { Context, ContextArray, ContextValue } from './tools/serialisation/context'\nexport {\n  areCookiesAuthorized,\n  getCookie,\n  getInitCookie,\n  setCookie,\n  deleteCookie,\n  resetInitCookies,\n} from './browser/cookie'\nexport type { CookieStore, WeakRef, WeakRefConstructor } from './browser/browser.types'\nexport type { XhrCompleteContext, XhrStartContext } from './browser/xhrObservable'\nexport { initXhrObservable } from './browser/xhrObservable'\nexport type { FetchResolveContext, FetchStartContext, FetchContext } from './browser/fetchObservable'\nexport { initFetchObservable, ResponseBodyAction } from './browser/fetchObservable'\nexport { fetch } from './browser/fetch'\nexport type { PageMayExitEvent } from './browser/pageMayExitObservable'\nexport { createPageMayExitObservable, PageExitReason, isPageExitReason } from './browser/pageMayExitObservable'\nexport * from './browser/addEventListener'\nexport { requestIdleCallback } from './tools/requestIdleCallback'\nexport * from './tools/taskQueue'\nexport * from './tools/timer'\nexport type { ConsoleLog } from './domain/console/consoleObservable'\nexport { initConsoleObservable } from './domain/console/consoleObservable'\nexport type { BoundedBuffer } from './tools/boundedBuffer'\nexport { createBoundedBuffer } from './tools/boundedBuffer'\nexport { catchUserErrors } from './tools/catchUserErrors'\nexport type { ContextManager } from './domain/context/contextManager'\nexport { createContextManager } from './domain/context/contextManager'\nexport { defineContextMethod, bufferContextCalls } from './domain/context/defineContextMethod'\nexport { storeContextManager, removeStorageListeners } from './domain/context/storeContextManager'\nexport { startAccountContext, buildAccountContextManager } from './domain/contexts/accountContext'\nexport { startTabContext } from './domain/contexts/tabContext'\nexport { startGlobalContext, buildGlobalContextManager } from './domain/contexts/globalContext'\nexport { startUserContext, buildUserContextManager } from './domain/contexts/userContext'\nexport type { User } from './domain/contexts/userContext'\nexport type { Account } from './domain/contexts/accountContext'\nexport type { RumInternalContext } from './domain/contexts/rumInternalContext.type'\nexport { CustomerDataType, CustomerContextKey, ContextManagerMethod } from './domain/context/contextConstants'\nexport type { ValueHistory, ValueHistoryEntry } from './tools/valueHistory'\nexport { createValueHistory, CLEAR_OLD_VALUES_INTERVAL } from './tools/valueHistory'\nexport { readBytesFromStream } from './tools/readBytesFromStream'\nexport type { SessionState } from './domain/session/sessionState'\nexport { STORAGE_POLL_DELAY } from './domain/session/sessionStore'\nexport { SESSION_STORE_KEY } from './domain/session/storeStrategies/sessionStoreStrategy'\nexport { MEMORY_SESSION_STORE_KEY } from './domain/session/storeStrategies/sessionInMemory'\nexport {\n  willSyntheticsInjectRum,\n  getSyntheticsContext,\n  isSyntheticsTest,\n} from './domain/synthetics/syntheticsWorkerValues'\nexport type { SyntheticsContext } from './domain/synthetics/syntheticsWorkerValues'\nexport { checkContext } from './domain/context/contextUtils'\nexport * from './domain/resourceUtils'\nexport * from './domain/bufferedData'\nexport * from './tools/utils/polyfills'\nexport * from './tools/utils/timezone'\nexport * from './tools/utils/numberUtils'\nexport * from './tools/utils/byteUtils'\nexport * from './tools/utils/objectUtils'\nexport * from './tools/utils/functionUtils'\nexport * from './tools/serialisation/jsonStringify'\nexport * from './tools/mergeInto'\nexport * from './tools/utils/stringUtils'\nexport * from './tools/matchOption'\nexport * from './tools/utils/responseUtils'\nexport * from './tools/utils/typeUtils'\nexport type { RawError, RawErrorCause, ErrorWithCause, Csp } from './domain/error/error.types'\nexport { ErrorHandling, ErrorSource } from './domain/error/error.types'\nexport * from './domain/deflate'\nexport * from './domain/connectivity'\nexport * from './tools/stackTrace/handlingStack'\nexport * from './tools/abstractHooks'\nexport * from './domain/tags'\n"
  },
  {
    "path": "packages/core/src/tools/abstractHooks.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { createHooks } from '../../test'\nimport { DISCARDED, HookNames } from './abstractHooks'\n\ndescribe('startHooks', () => {\n  let hooks: ReturnType<typeof createHooks>\n  const hookParams = { eventType: 'error', startTime: 1011 as RelativeTime } as any\n\n  beforeEach(() => {\n    hooks = createHooks()\n  })\n\n  it('unregister a hook callback', () => {\n    const callback = jasmine.createSpy().and.returnValue({ service: 'foo' })\n\n    const { unregister } = hooks.register(HookNames.Assemble, callback)\n    unregister()\n\n    const result = hooks.triggerHook(HookNames.Assemble, hookParams)\n\n    expect(callback).not.toHaveBeenCalled()\n    expect(result).toBeUndefined()\n  })\n\n  describe('assemble hook', () => {\n    it('combines results from multiple callbacks', () => {\n      const callback1 = jasmine.createSpy().and.returnValue({ type: 'action', service: 'foo' })\n      const callback2 = jasmine.createSpy().and.returnValue({ type: 'action', version: 'bar' })\n\n      hooks.register(HookNames.Assemble, callback1)\n      hooks.register(HookNames.Assemble, callback2)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, hookParams)\n\n      expect(defaultRumEventAttributes).toEqual({ type: 'action', service: 'foo', version: 'bar' })\n      expect(callback1).toHaveBeenCalled()\n      expect(callback2).toHaveBeenCalled()\n    })\n\n    it('does not combine undefined results from callbacks', () => {\n      const callback1 = jasmine.createSpy().and.returnValue({ type: 'action', service: 'foo' })\n      const callback2 = jasmine.createSpy().and.returnValue(undefined)\n\n      hooks.register(HookNames.Assemble, callback1)\n      hooks.register(HookNames.Assemble, callback2)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, hookParams)\n\n      expect(defaultRumEventAttributes).toEqual({ type: 'action', service: 'foo' })\n      expect(callback1).toHaveBeenCalled()\n      expect(callback2).toHaveBeenCalled()\n    })\n\n    it('returns DISCARDED if one callbacks returns DISCARDED', () => {\n      const callback1 = jasmine.createSpy().and.returnValue({ type: 'action', service: 'foo' })\n      const callback2 = jasmine.createSpy().and.returnValue(DISCARDED)\n      const callback3 = jasmine.createSpy().and.returnValue({ type: 'action', version: 'bar' })\n\n      hooks.register(HookNames.Assemble, callback1)\n      hooks.register(HookNames.Assemble, callback2)\n      hooks.register(HookNames.Assemble, callback3)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, hookParams)\n\n      expect(defaultRumEventAttributes).toEqual(DISCARDED)\n      expect(callback1).toHaveBeenCalled()\n      expect(callback2).toHaveBeenCalled()\n      expect(callback3).not.toHaveBeenCalled()\n    })\n\n    it('returns undefined when no registered hooks', () => {\n      const result = hooks.triggerHook(HookNames.Assemble, hookParams)\n      expect(result).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/abstractHooks.ts",
    "content": "import { combine } from './mergeInto'\n\nexport const enum HookNames {\n  Assemble,\n  AssembleTelemetry,\n}\n\n// This is a workaround for an issue occurring when the Browser SDK is included in a TypeScript\n// project configured with `isolatedModules: true`. Even if the const enum is declared in this\n// module, we cannot use it directly to define the EventMap interface keys (TS error: \"Cannot access\n// ambient const enums when the '--isolatedModules' flag is provided.\").\nexport declare const HookNamesAsConst: {\n  ASSEMBLE: HookNames.Assemble\n  ASSEMBLE_TELEMETRY: HookNames.AssembleTelemetry\n}\n\nexport type RecursivePartial<T> = {\n  [P in keyof T]?: T[P] extends Array<infer U>\n    ? Array<RecursivePartial<U>>\n    : T[P] extends object | undefined\n      ? RecursivePartial<T[P]>\n      : T[P]\n}\n\n// Discards the event from being sent\nexport const DISCARDED = 'DISCARDED'\n// Skips from the assembly of the event\nexport const SKIPPED = 'SKIPPED'\n\nexport type DISCARDED = typeof DISCARDED\nexport type SKIPPED = typeof SKIPPED\n\nexport type AbstractHooks = ReturnType<typeof abstractHooks>\n\nexport function abstractHooks<T extends { [K in HookNames]: (...args: any[]) => unknown }>() {\n  const callbacks: { [K in HookNames]?: Array<T[K]> } = {}\n\n  return {\n    register<K extends HookNames>(hookName: K, callback: T[K]) {\n      if (!callbacks[hookName]) {\n        callbacks[hookName] = []\n      }\n      callbacks[hookName]!.push(callback)\n      return {\n        unregister: () => {\n          callbacks[hookName] = callbacks[hookName]!.filter((cb) => cb !== callback)\n        },\n      }\n    },\n    triggerHook<K extends HookNames>(\n      hookName: K,\n      param: Parameters<T[K]>[0]\n    ): Exclude<ReturnType<T[K]>, SKIPPED> | DISCARDED | undefined {\n      const hookCallbacks = callbacks[hookName] || []\n      const results: any[] = []\n\n      for (const callback of hookCallbacks) {\n        const result = callback(param)\n        if (result === DISCARDED) {\n          return DISCARDED\n        }\n        if (result === SKIPPED) {\n          continue\n        }\n\n        results.push(result)\n      }\n\n      return combine(...(results as [any, any])) as Exclude<ReturnType<T[K]>, SKIPPED>\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/abstractLifeCycle.spec.ts",
    "content": "import { AbstractLifeCycle } from './abstractLifeCycle'\n\ndescribe('AbstractLifeCycle', () => {\n  const LifeCycle = AbstractLifeCycle<{\n    foo: 'bar'\n    no_data: void\n  }>\n\n  it('does nothing when notifying without subscribers', () => {\n    const lifeCycle = new LifeCycle()\n    expect(() => lifeCycle.notify('foo', 'bar')).not.toThrow()\n  })\n\n  it('notifies subscribers', () => {\n    const lifeCycle = new LifeCycle()\n    const subscriber1Spy = jasmine.createSpy()\n    const subscriber2Spy = jasmine.createSpy()\n    lifeCycle.subscribe('foo', subscriber1Spy)\n    lifeCycle.subscribe('foo', subscriber2Spy)\n\n    lifeCycle.notify('foo', 'bar')\n\n    expect(subscriber1Spy).toHaveBeenCalledOnceWith('bar')\n    expect(subscriber2Spy).toHaveBeenCalledOnceWith('bar')\n  })\n\n  it('notifies subscribers for events without data', () => {\n    const lifeCycle = new LifeCycle()\n    const subscriberSpy = jasmine.createSpy()\n    lifeCycle.subscribe('no_data', subscriberSpy)\n\n    lifeCycle.notify('no_data')\n\n    expect(subscriberSpy).toHaveBeenCalledOnceWith(undefined)\n  })\n\n  it('does not notify unsubscribed subscribers', () => {\n    const lifeCycle = new LifeCycle()\n    const subscriberSpy = jasmine.createSpy()\n    lifeCycle.subscribe('foo', subscriberSpy).unsubscribe()\n\n    lifeCycle.notify('foo', 'bar')\n\n    expect(subscriberSpy).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/abstractLifeCycle.ts",
    "content": "import type { Subscription } from './observable'\n\n/**\n * Type helper to extract event types that have \"void\" data. This allows to call `notify` without a\n * second argument. Ex:\n *\n * ```\n * interface EventMap {\n *   foo: void\n * }\n * const LifeCycle = AbstractLifeCycle<EventMap>\n * new LifeCycle().notify('foo')\n * ```\n */\ntype EventTypesWithoutData<EventMap> = {\n  [K in keyof EventMap]: EventMap[K] extends void ? K : never\n}[keyof EventMap]\n\n// eslint-disable-next-line no-restricted-syntax\nexport class AbstractLifeCycle<EventMap> {\n  private callbacks: { [key in keyof EventMap]?: Array<(data: any) => void> } = {}\n\n  notify<EventType extends EventTypesWithoutData<EventMap>>(eventType: EventType): void\n  notify<EventType extends keyof EventMap>(eventType: EventType, data: EventMap[EventType]): void\n  notify(eventType: keyof EventMap, data?: unknown) {\n    const eventCallbacks = this.callbacks[eventType]\n    if (eventCallbacks) {\n      eventCallbacks.forEach((callback) => callback(data))\n    }\n  }\n\n  subscribe<EventType extends keyof EventMap>(\n    eventType: EventType,\n    callback: (data: EventMap[EventType]) => void\n  ): Subscription {\n    if (!this.callbacks[eventType]) {\n      this.callbacks[eventType] = []\n    }\n    this.callbacks[eventType]!.push(callback)\n    return {\n      unsubscribe: () => {\n        this.callbacks[eventType] = this.callbacks[eventType]!.filter((other) => callback !== other)\n      },\n    }\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/boundedBuffer.spec.ts",
    "content": "import { createBoundedBuffer } from './boundedBuffer'\n\ndescribe('BoundedBuffer', () => {\n  it('collect and drain the callbacks', () => {\n    const spy = jasmine.createSpy<() => void>()\n    const buffered = createBoundedBuffer()\n\n    buffered.add(spy)\n    expect(spy.calls.count()).toBe(0)\n\n    buffered.drain()\n    expect(spy.calls.count()).toBe(1)\n\n    buffered.drain()\n    expect(spy.calls.count()).toBe(1)\n  })\n\n  it('store at most 500 callbacks', () => {\n    const spy = jasmine.createSpy<() => void>()\n    const buffered = createBoundedBuffer()\n    const limit = 500\n\n    for (let i = 0; i < limit + 1; i += 1) {\n      buffered.add(spy)\n    }\n\n    buffered.drain()\n    expect(spy.calls.count()).toEqual(limit)\n  })\n\n  it('removes a callback', () => {\n    const spy = jasmine.createSpy<() => void>()\n    const buffered = createBoundedBuffer()\n\n    buffered.add(spy)\n    buffered.remove(spy)\n    buffered.drain()\n    expect(spy).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/boundedBuffer.ts",
    "content": "import { removeItem } from './utils/arrayUtils'\n\nconst BUFFER_LIMIT = 500\n\n/**\n * BoundedBuffer is a deprecated interface.\n *\n * @deprecated Use `BufferedObservable` instead.\n */\nexport interface BoundedBuffer<T = void> {\n  add: (callback: (arg: T) => void) => void\n  remove: (callback: (arg: T) => void) => void\n  drain: (arg: T) => void\n}\n\n/**\n * createBoundedBuffer creates a BoundedBuffer.\n *\n * @deprecated Use `BufferedObservable` instead.\n */\nexport function createBoundedBuffer<T = void>(): BoundedBuffer<T> {\n  const buffer: Array<(arg: T) => void> = []\n\n  const add: BoundedBuffer<T>['add'] = (callback: (arg: T) => void) => {\n    const length = buffer.push(callback)\n    if (length > BUFFER_LIMIT) {\n      buffer.splice(0, 1)\n    }\n  }\n\n  const remove: BoundedBuffer<T>['remove'] = (callback: (arg: T) => void) => {\n    removeItem(buffer, callback)\n  }\n\n  const drain = (arg: T) => {\n    buffer.forEach((callback) => callback(arg))\n    buffer.length = 0\n  }\n\n  return {\n    add,\n    remove,\n    drain,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/catchUserErrors.spec.ts",
    "content": "import { catchUserErrors } from './catchUserErrors'\nimport { display } from './display'\n\ndescribe('catchUserErrors', () => {\n  it('returns the same result as the original function', () => {\n    const wrappedFn = catchUserErrors((a: number, b: number) => a + b, 'Error during callback')\n    expect(wrappedFn(10, 2)).toBe(12)\n  })\n\n  it('logs errors using console.error and returns undefined', () => {\n    const displaySpy = spyOn(display, 'error')\n    const myError = 'Ooops!'\n    const wrappedFn = catchUserErrors(() => {\n      // eslint-disable-next-line @typescript-eslint/only-throw-error\n      throw myError\n    }, 'Error during callback')\n    expect(wrappedFn()).toBe(undefined)\n    expect(displaySpy).toHaveBeenCalledWith('Error during callback', myError)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/catchUserErrors.ts",
    "content": "import { display } from './display'\n\nexport function catchUserErrors<Args extends any[], R>(fn: (...args: Args) => R, errorMsg: string) {\n  return (...args: Args) => {\n    try {\n      return fn(...args)\n    } catch (err) {\n      display.error(errorMsg, err)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/display.ts",
    "content": "/* eslint-disable local-rules/disallow-side-effects */\n/**\n * Keep references on console methods to avoid triggering patched behaviors\n *\n * NB: in some setup, console could already be patched by another SDK.\n * In this case, some display messages can be sent by the other SDK\n * but we should be safe from infinite loop nonetheless.\n */\n\nexport const ConsoleApiName = {\n  log: 'log',\n  debug: 'debug',\n  info: 'info',\n  warn: 'warn',\n  error: 'error',\n} as const\n\nexport type ConsoleApiName = (typeof ConsoleApiName)[keyof typeof ConsoleApiName]\n\ninterface Display {\n  debug: typeof console.debug\n  log: typeof console.log\n  info: typeof console.info\n  warn: typeof console.warn\n  error: typeof console.error\n}\n\n/**\n * When building JS bundles, some users might use a plugin[1] or configuration[2] to remove\n * \"console.*\" references. This causes some issue as we expect `console.*` to be defined.\n * As a workaround, let's use a variable alias, so those expressions won't be taken into account by\n * simple static analysis.\n *\n * [1]: https://babeljs.io/docs/babel-plugin-transform-remove-console/\n * [2]: https://github.com/terser/terser#compress-options (look for drop_console)\n */\nexport const globalConsole = console\n\nexport const originalConsoleMethods = {} as Display\nObject.keys(ConsoleApiName).forEach((name) => {\n  originalConsoleMethods[name as ConsoleApiName] = globalConsole[name as ConsoleApiName]\n})\n\nconst PREFIX = 'Datadog Browser SDK:'\n\nexport const display: Display = {\n  debug: originalConsoleMethods.debug.bind(globalConsole, PREFIX),\n  log: originalConsoleMethods.log.bind(globalConsole, PREFIX),\n  info: originalConsoleMethods.info.bind(globalConsole, PREFIX),\n  warn: originalConsoleMethods.warn.bind(globalConsole, PREFIX),\n  error: originalConsoleMethods.error.bind(globalConsole, PREFIX),\n}\n\nexport const DOCS_ORIGIN = 'https://docs.datadoghq.com'\nexport const DOCS_TROUBLESHOOTING = `${DOCS_ORIGIN}/real_user_monitoring/browser/troubleshooting`\nexport const MORE_DETAILS = 'More details:'\n"
  },
  {
    "path": "packages/core/src/tools/encoder.spec.ts",
    "content": "import { createIdentityEncoder } from './encoder'\nimport { noop } from './utils/functionUtils'\n\ndescribe('createIdentityEncoder', () => {\n  it('creates an encoder with initial values', () => {\n    const encoder = createIdentityEncoder()\n\n    expect(encoder.isEmpty).toBe(true)\n    expect(encoder.finishSync()).toEqual({\n      output: '',\n      outputBytesCount: 0,\n      rawBytesCount: 0,\n      pendingData: '',\n    })\n  })\n\n  describe('write()', () => {\n    it('writes data to the encoder', () => {\n      const encoder = createIdentityEncoder()\n      const data = 'Hello, world!'\n\n      encoder.write(data)\n\n      expect(encoder.isEmpty).toBe(false)\n    })\n\n    it('calls the callback when writing data with a callback', () => {\n      const encoder = createIdentityEncoder()\n      const data = 'Callback test'\n      const callbackSpy = jasmine.createSpy()\n\n      encoder.write(data, callbackSpy)\n\n      expect(callbackSpy).toHaveBeenCalledOnceWith(data.length)\n    })\n  })\n\n  describe('finish()', () => {\n    it('calls the callback with the result', () => {\n      const encoder = createIdentityEncoder()\n      const data = 'Final data'\n      encoder.write(data)\n      const callbackSpy = jasmine.createSpy()\n\n      encoder.finish(callbackSpy)\n\n      expect(callbackSpy).toHaveBeenCalledWith({\n        output: data,\n        outputBytesCount: data.length,\n        rawBytesCount: data.length,\n        pendingData: '',\n      })\n    })\n\n    it('after calling finish(), the encoder should be considered empty', () => {\n      const encoder = createIdentityEncoder()\n      encoder.write('Some data')\n\n      encoder.finish(noop)\n\n      expect(encoder.isEmpty).toBe(true)\n      expect(encoder.finishSync()).toEqual({\n        output: '',\n        outputBytesCount: 0,\n        rawBytesCount: 0,\n        pendingData: '',\n      })\n    })\n  })\n\n  describe('finishSync()', () => {\n    it('returns the encoder result', () => {\n      const encoder = createIdentityEncoder()\n      const data = 'Hello, world!'\n\n      encoder.write(data)\n\n      expect(encoder.finishSync()).toEqual({\n        output: data,\n        outputBytesCount: data.length,\n        rawBytesCount: data.length,\n        pendingData: '',\n      })\n    })\n\n    it('after calling finish(), the encoder should be considered empty', () => {\n      const encoder = createIdentityEncoder()\n      encoder.write('Some data')\n\n      encoder.finishSync()\n\n      expect(encoder.isEmpty).toBe(true)\n      expect(encoder.finishSync()).toEqual({\n        output: '',\n        outputBytesCount: 0,\n        rawBytesCount: 0,\n        pendingData: '',\n      })\n    })\n  })\n\n  describe('estimateEncodedBytesCount()', () => {\n    it('estimates encoded bytes count accurately', () => {\n      const encoder = createIdentityEncoder()\n      const data = 'Estimation test'\n\n      const estimatedBytes = encoder.estimateEncodedBytesCount(data)\n\n      expect(estimatedBytes).toBe(data.length)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/encoder.ts",
    "content": "import type { Uint8ArrayBuffer } from './utils/byteUtils'\nimport { computeBytesCount } from './utils/byteUtils'\n\nexport interface Encoder<Output extends string | Uint8ArrayBuffer = string | Uint8ArrayBuffer> {\n  /**\n   * Whether this encoder might call the provided callbacks asynchronously\n   */\n  isAsync: boolean\n\n  /**\n   * Whether some data has been written since the last finish() or finishSync() call\n   */\n  isEmpty: boolean\n\n  /**\n   * Write a string to be encoded.\n   *\n   * This operation can be synchronous or asynchronous depending on the encoder implementation.\n   *\n   * If specified, the callback will be invoked when the operation finishes, unless the operation is\n   * asynchronous and finish() or finishSync() is called in the meantime.\n   */\n  write(data: string, callback?: (additionalEncodedBytesCount: number) => void): void\n\n  /**\n   * Waits for pending data to be encoded and resets the encoder state.\n   *\n   * This operation can be synchronous or asynchronous depending on the encoder implementation.\n   *\n   * The callback will be invoked when the operation finishes, unless the operation is asynchronous\n   * and another call to finish() or finishSync() occurs in the meantime.\n   */\n  finish(callback: (result: EncoderResult<Output>) => void): void\n\n  /**\n   * Resets the encoder state then returns the encoded data and any potential pending data directly,\n   * discarding all pending write operations and finish() callbacks.\n   */\n  finishSync(): EncoderResult<Output> & { pendingData: string }\n\n  /**\n   * Returns a rough estimation of the bytes count if the data was encoded.\n   */\n  estimateEncodedBytesCount(data: string): number\n}\n\nexport interface EncoderResult<Output extends string | Uint8ArrayBuffer = string | Uint8ArrayBuffer> {\n  output: Output\n  outputBytesCount: number\n\n  /**\n   * An encoding type supported by HTTP Content-Encoding, if applicable.\n   * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#directives\n   */\n  encoding?: 'deflate'\n\n  /**\n   * Total bytes count of the input strings encoded to UTF-8.\n   */\n  rawBytesCount: number\n}\n\nexport function createIdentityEncoder(): Encoder<string> {\n  let output = ''\n  let outputBytesCount = 0\n\n  return {\n    isAsync: false,\n\n    get isEmpty() {\n      return !output\n    },\n\n    write(data, callback) {\n      const additionalEncodedBytesCount = computeBytesCount(data)\n      outputBytesCount += additionalEncodedBytesCount\n      output += data\n      if (callback) {\n        callback(additionalEncodedBytesCount)\n      }\n    },\n\n    finish(callback) {\n      callback(this.finishSync())\n    },\n\n    finishSync() {\n      const result = {\n        output,\n        outputBytesCount,\n        rawBytesCount: outputBytesCount,\n        pendingData: '',\n      }\n      output = ''\n      outputBytesCount = 0\n      return result\n    },\n\n    estimateEncodedBytesCount(data) {\n      return data.length\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/experimentalFeatures.spec.ts",
    "content": "import {\n  ExperimentalFeature,\n  addExperimentalFeatures,\n  initFeatureFlags,\n  isExperimentalFeatureEnabled,\n} from './experimentalFeatures'\n\nconst TEST_FEATURE_FLAG_ONE = 'foo' as ExperimentalFeature\nconst TEST_FEATURE_FLAG_TWO = 'bar' as ExperimentalFeature\n\ndescribe('experimentalFeatures', () => {\n  it('initial state is empty', () => {\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_ONE)).toBeFalse()\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_TWO)).toBeFalse()\n  })\n\n  it('should define enabled experimental features', () => {\n    addExperimentalFeatures([TEST_FEATURE_FLAG_ONE])\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_ONE)).toBeTrue()\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_TWO)).toBeFalse()\n  })\n\n  it('should allow to be shared between products', () => {\n    addExperimentalFeatures([TEST_FEATURE_FLAG_ONE])\n    addExperimentalFeatures([TEST_FEATURE_FLAG_TWO])\n\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_ONE)).toBeTrue()\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_TWO)).toBeTrue()\n  })\n})\n\ndescribe('initFeatureFlags', () => {\n  beforeEach(() => {\n    ;(ExperimentalFeature as any).FOO = TEST_FEATURE_FLAG_ONE\n  })\n\n  afterEach(() => {\n    delete (ExperimentalFeature as any).FOO\n  })\n\n  it('ignores unknown experimental features', () => {\n    initFeatureFlags(['bar', undefined as any, null as any, 11 as any])\n\n    expect(isExperimentalFeatureEnabled('bar' as any)).toBeFalse()\n    expect(isExperimentalFeatureEnabled(undefined as any)).toBeFalse()\n    expect(isExperimentalFeatureEnabled(null as any)).toBeFalse()\n    expect(isExperimentalFeatureEnabled(11 as any)).toBeFalse()\n  })\n\n  it('updates experimental feature flags', () => {\n    initFeatureFlags(['foo'])\n    expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_ONE)).toBeTrue()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/experimentalFeatures.ts",
    "content": "/**\n * LIMITATION:\n * For NPM setup, this feature flag singleton is shared between RUM and Logs product.\n * This means that an experimental flag set on the RUM product will be set on the Logs product.\n * So keep in mind that in certain configurations, your experimental feature flag may affect other products.\n *\n * FORMAT:\n * All feature flags should be snake_cased\n */\n// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary\n// string is an expected feature flag\n\nimport { objectHasValue } from './utils/objectUtils'\n\n// eslint-disable-next-line no-restricted-syntax\nexport enum ExperimentalFeature {\n  TRACK_INTAKE_REQUESTS = 'track_intake_requests',\n  USE_TREE_WALKER_FOR_ACTION_NAME = 'use_tree_walker_for_action_name',\n  FEATURE_OPERATION_VITAL = 'feature_operation_vital',\n  START_STOP_ACTION = 'start_stop_action',\n  START_STOP_RESOURCE = 'start_stop_resource',\n  USE_CHANGE_RECORDS = 'use_change_records',\n  USE_INCREMENTAL_CHANGE_RECORDS = 'use_incremental_change_records',\n  TOO_MANY_REQUESTS_INVESTIGATION = 'too_many_requests_investigation',\n  TRACK_RESOURCE_HEADERS = 'track_resource_headers',\n}\n\nconst enabledExperimentalFeatures: Set<ExperimentalFeature> = new Set()\n\nexport function initFeatureFlags(enableExperimentalFeatures: string[] | undefined) {\n  if (Array.isArray(enableExperimentalFeatures)) {\n    addExperimentalFeatures(\n      enableExperimentalFeatures.filter((flag): flag is ExperimentalFeature =>\n        objectHasValue(ExperimentalFeature, flag)\n      )\n    )\n  }\n}\n\nexport function addExperimentalFeatures(enabledFeatures: ExperimentalFeature[]): void {\n  enabledFeatures.forEach((flag) => {\n    enabledExperimentalFeatures.add(flag)\n  })\n}\n\nexport function isExperimentalFeatureEnabled(featureName: ExperimentalFeature): boolean {\n  return enabledExperimentalFeatures.has(featureName)\n}\n\nexport function resetExperimentalFeatures(): void {\n  enabledExperimentalFeatures.clear()\n}\n\nexport function getExperimentalFeatures(): Set<ExperimentalFeature> {\n  return enabledExperimentalFeatures\n}\n"
  },
  {
    "path": "packages/core/src/tools/getZoneJsOriginalValue.spec.ts",
    "content": "import { mockZoneJs } from '../../test'\n\nimport type { BrowserWindowWithZoneJs } from './getZoneJsOriginalValue'\nimport { getZoneJsOriginalValue } from './getZoneJsOriginalValue'\nimport { noop } from './utils/functionUtils'\n\ndescribe('getZoneJsOriginalValue', () => {\n  function originalValue() {\n    // just a function that does nothing but different than 'noop' as we'll want to differentiate\n    // them.\n  }\n  const object = {\n    name: originalValue,\n  }\n\n  it('returns the original value directly if Zone is not not defined', () => {\n    expect(getZoneJsOriginalValue(object, 'name')).toBe(originalValue)\n  })\n\n  it(\"returns the original value if Zone is defined but didn't patch that method\", () => {\n    mockZoneJs()\n    expect(getZoneJsOriginalValue(object, 'name')).toBe(originalValue)\n  })\n\n  it('returns the original value if Zone is defined but does not define the __symbol__ function', () => {\n    mockZoneJs()\n    delete (window as BrowserWindowWithZoneJs).Zone!.__symbol__\n    expect(getZoneJsOriginalValue(object, 'name')).toBe(originalValue)\n  })\n\n  it('returns the original value if Zone did patch the method', () => {\n    const zoneJs = mockZoneJs()\n    zoneJs.replaceProperty(object, 'name', noop)\n    expect(getZoneJsOriginalValue(object, 'name')).toBe(originalValue)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/getZoneJsOriginalValue.ts",
    "content": "import { getGlobalObject } from './globalObject'\n\nexport interface BrowserWindowWithZoneJs extends Window {\n  Zone?: {\n    // All Zone.js versions expose the __symbol__ method, but we observed that some website have a\n    // 'Zone' global variable unrelated to Zone.js, so let's consider this method optional\n    // nonetheless.\n    __symbol__?: (name: string) => string\n  }\n}\n\n/**\n * Gets the original value for a DOM API that was potentially patched by Zone.js.\n *\n * Zone.js[1] is a library that patches a bunch of JS and DOM APIs. It usually stores the original\n * value of the patched functions/constructors/methods in a hidden property prefixed by\n * __zone_symbol__.\n *\n * In multiple occasions, we observed that Zone.js is the culprit of important issues leading to\n * browser resource exhaustion (memory leak, high CPU usage). This method is used as a workaround to\n * use the original DOM API instead of the one patched by Zone.js.\n *\n * [1]: https://github.com/angular/angular/tree/main/packages/zone.js\n */\nexport function getZoneJsOriginalValue<Target, Name extends keyof Target & string>(\n  target: Target,\n  name: Name\n): Target[Name] {\n  const browserWindow = getGlobalObject<BrowserWindowWithZoneJs>()\n  let original: Target[Name] | undefined\n  if (browserWindow.Zone && typeof browserWindow.Zone.__symbol__ === 'function') {\n    original = (target as any)[browserWindow.Zone.__symbol__(name)]\n  }\n  if (!original) {\n    original = target[name]\n  }\n  return original\n}\n"
  },
  {
    "path": "packages/core/src/tools/globalObject.ts",
    "content": "/**\n * inspired by https://mathiasbynens.be/notes/globalthis\n */\n\n// Extend/Create the WorkerGlobalScope interface to avoid issues when used in a non-browser tsconfig environment\ninterface WorkerGlobalScope {\n  empty: never\n}\n\n// Utility type to enforce that exactly one of the two types is used\ntype Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }\ntype XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U\n\nexport type GlobalObject = XOR<Window, WorkerGlobalScope>\n\nexport function getGlobalObject<T = typeof globalThis>(): T {\n  if (typeof globalThis === 'object') {\n    return globalThis as unknown as T\n  }\n  Object.defineProperty(Object.prototype, '_dd_temp_', {\n    get() {\n      return this as object\n    },\n    configurable: true,\n  })\n  // @ts-ignore _dd_temp is defined using defineProperty\n  let globalObject: unknown = _dd_temp_\n  // @ts-ignore _dd_temp is defined using defineProperty\n  delete Object.prototype._dd_temp_\n  if (typeof globalObject !== 'object') {\n    // on safari _dd_temp_ is available on window but not globally\n    // fallback on other browser globals check\n    if (typeof self === 'object') {\n      globalObject = self\n    } else if (typeof window === 'object') {\n      globalObject = window\n    } else {\n      globalObject = {}\n    }\n  }\n  return globalObject as T\n}\n\n/**\n * Cached reference to the global object so it can be imported and re-used without\n * re-evaluating the heavyweight fallback logic in `getGlobalObject()`.\n */\n// eslint-disable-next-line local-rules/disallow-side-effects\nexport const globalObject = getGlobalObject<GlobalObject>()\n\nexport const isWorkerEnvironment = 'WorkerGlobalScope' in globalObject\n"
  },
  {
    "path": "packages/core/src/tools/instrumentMethod.spec.ts",
    "content": "import { mockClock, mockZoneJs } from '../../test'\nimport type { Clock, MockZoneJs } from '../../test'\nimport type { InstrumentedMethodCall } from './instrumentMethod'\nimport { instrumentMethod, instrumentSetter } from './instrumentMethod'\nimport { noop } from './utils/functionUtils'\n\ndescribe('instrumentMethod', () => {\n  const THIRD_PARTY_RESULT = 42\n\n  it('replaces the original method', () => {\n    const original = () => 1\n    const object = { method: original }\n\n    instrumentMethod(object, 'method', noop)\n\n    expect(object.method).not.toBe(original)\n  })\n\n  it('calls the instrumentation before the original method', () => {\n    const originalSpy = jasmine.createSpy()\n    const instrumentationSpy = jasmine.createSpy()\n    const object = { method: originalSpy }\n\n    instrumentMethod(object, 'method', instrumentationSpy)\n\n    object.method()\n\n    expect(instrumentationSpy).toHaveBeenCalledBefore(originalSpy)\n  })\n\n  it('does not set a method originally undefined', () => {\n    const object: { method?: () => number } = {}\n\n    instrumentMethod(object, 'method', noop)\n\n    expect(object.method).toBeUndefined()\n  })\n\n  it('sets an event handler even if it was originally undefined', () => {\n    const object: { onevent?: () => void } = { onevent: undefined }\n\n    const instrumentationSpy = jasmine.createSpy()\n    instrumentMethod(object, 'onevent', instrumentationSpy)\n\n    expect(object.onevent).toBeDefined()\n\n    object.onevent!()\n    expect(instrumentationSpy).toHaveBeenCalled()\n  })\n\n  it('do not set an event handler even if the event is not supported (i.e. property does not exist on object)', () => {\n    const object: { onevent?: () => void } = {}\n\n    const instrumentationSpy = jasmine.createSpy()\n    instrumentMethod(object, 'onevent', instrumentationSpy)\n\n    expect('onevent' in object).toBeFalse()\n  })\n\n  it('calls the instrumentation with method target and parameters', () => {\n    const object = { method: (a: number, b: number) => a + b }\n    const instrumentationSpy = jasmine.createSpy<(call: InstrumentedMethodCall<typeof object, 'method'>) => void>()\n    instrumentMethod(object, 'method', instrumentationSpy)\n\n    object.method(2, 3)\n\n    expect(instrumentationSpy).toHaveBeenCalledOnceWith({\n      target: object,\n      parameters: jasmine.any(Object),\n      onPostCall: jasmine.any(Function),\n      handlingStack: undefined,\n    })\n    expect(instrumentationSpy.calls.mostRecent().args[0].parameters[0]).toBe(2)\n    expect(instrumentationSpy.calls.mostRecent().args[0].parameters[1]).toBe(3)\n  })\n\n  it('allows replacing a parameter', () => {\n    const object = { method: (a: number) => a }\n    instrumentMethod(object, 'method', ({ parameters }) => {\n      parameters[0] = 2\n    })\n\n    expect(object.method(1)).toBe(2)\n  })\n\n  it('allows adding a parameter', () => {\n    const object = { method: (a?: number) => a }\n    instrumentMethod(object, 'method', ({ parameters }) => {\n      parameters[0] = 2\n    })\n\n    expect(object.method()).toBe(2)\n  })\n\n  it('calls the \"onPostCall\" callback with the original method result', () => {\n    const object = { method: () => 1 }\n    const onPostCallSpy = jasmine.createSpy()\n    instrumentMethod(object, 'method', ({ onPostCall }) => onPostCall(onPostCallSpy))\n\n    object.method()\n\n    expect(onPostCallSpy).toHaveBeenCalledOnceWith(1)\n  })\n\n  it('allows other instrumentations from third parties', () => {\n    const object = { method: () => 1 }\n    const instrumentationSpy = jasmine.createSpy()\n    instrumentMethod(object, 'method', instrumentationSpy)\n\n    thirdPartyInstrumentation(object)\n\n    expect(object.method()).toBe(THIRD_PARTY_RESULT)\n    expect(instrumentationSpy).toHaveBeenCalled()\n  })\n\n  it('computes the handling stack', () => {\n    const object = { method: () => 1 }\n    const instrumentationSpy = jasmine.createSpy()\n    instrumentMethod(object, 'method', instrumentationSpy, { computeHandlingStack: true })\n\n    function foo() {\n      object.method()\n    }\n\n    foo()\n\n    expect(instrumentationSpy.calls.mostRecent().args[0].handlingStack).toEqual(\n      jasmine.stringMatching(/^HandlingStack: instrumented method\\n {2}at foo @/)\n    )\n  })\n\n  describe('stop()', () => {\n    it('does not call the instrumentation anymore', () => {\n      const object = { method: () => 1 }\n      const instrumentationSpy = jasmine.createSpy()\n      const { stop } = instrumentMethod(object, 'method', () => instrumentationSpy)\n\n      stop()\n\n      object.method()\n      expect(instrumentationSpy).not.toHaveBeenCalled()\n    })\n\n    describe('when the method has been instrumented by a third party', () => {\n      it('should not break the third party instrumentation', () => {\n        const object = { method: () => 1 }\n        const { stop } = instrumentMethod(object, 'method', noop)\n\n        thirdPartyInstrumentation(object)\n        const instrumentedMethod = object.method\n\n        stop()\n\n        expect(object.method).toBe(instrumentedMethod)\n      })\n\n      it('does not call the instrumentation', () => {\n        const object = { method: () => 1 }\n        const instrumentationSpy = jasmine.createSpy()\n        const { stop } = instrumentMethod(object, 'method', instrumentationSpy)\n\n        thirdPartyInstrumentation(object)\n\n        stop()\n\n        expect(instrumentationSpy).not.toHaveBeenCalled()\n      })\n\n      it('should not throw errors if original method was undefined', () => {\n        const object: { onevent?: () => number } = {}\n        const instrumentationStub = () => 2\n        const { stop } = instrumentMethod(object, 'onevent', instrumentationStub)\n\n        thirdPartyInstrumentation(object)\n\n        stop()\n\n        expect(object.onevent).not.toThrow()\n      })\n    })\n  })\n\n  function thirdPartyInstrumentation(object: { method?: () => number; onevent?: () => void }) {\n    const originalMethod = object.method\n    if (typeof originalMethod === 'function') {\n      object.method = () => {\n        originalMethod()\n        return THIRD_PARTY_RESULT\n      }\n    }\n\n    const originalOnEvent = object.onevent\n    object.onevent = () => {\n      if (originalOnEvent) {\n        originalOnEvent()\n      }\n    }\n  }\n})\n\ndescribe('instrumentSetter', () => {\n  let clock: Clock\n  let zoneJs: MockZoneJs\n\n  beforeEach(() => {\n    clock = mockClock()\n    zoneJs = mockZoneJs()\n  })\n\n  it('replaces the original setter', () => {\n    const originalSetter = () => {\n      // do nothing particular, only used to test if this setter gets replaced\n    }\n    const object = {} as { foo: number }\n    Object.defineProperty(object, 'foo', { set: originalSetter, configurable: true })\n\n    instrumentSetter(object, 'foo', noop)\n\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(Object.getOwnPropertyDescriptor(object, 'foo')!.set).not.toBe(originalSetter)\n  })\n\n  it('skips instrumentation if there is no original setter', () => {\n    const object = { foo: 1 }\n\n    instrumentSetter(object, 'foo', noop)\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(Object.getOwnPropertyDescriptor(object, 'foo')!.set).toBeUndefined()\n  })\n\n  it('skips instrumentation if the descriptor is not configurable', () => {\n    const originalSetter = () => {\n      // do nothing particular, only used to test if this setter gets replaced\n    }\n    const object = {} as { foo: number }\n    Object.defineProperty(object, 'foo', { set: originalSetter, configurable: false })\n\n    instrumentSetter(object, 'foo', noop)\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(Object.getOwnPropertyDescriptor(object, 'foo')!.set).toBe(originalSetter)\n  })\n\n  it('calls the original setter', () => {\n    const originalSetterSpy = jasmine.createSpy()\n    const object = {} as { foo: number }\n    Object.defineProperty(object, 'foo', { set: originalSetterSpy, configurable: true })\n\n    instrumentSetter(object, 'foo', noop)\n\n    object.foo = 1\n    expect(originalSetterSpy).toHaveBeenCalledOnceWith(1)\n  })\n\n  it('calls the instrumentation asynchronously', () => {\n    const instrumentationSetterSpy = jasmine.createSpy()\n    const object = {} as { foo: number }\n    Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n\n    instrumentSetter(object, 'foo', instrumentationSetterSpy)\n\n    object.foo = 1\n    expect(instrumentationSetterSpy).not.toHaveBeenCalled()\n    clock.tick(0)\n    expect(instrumentationSetterSpy).toHaveBeenCalledOnceWith(object, 1)\n  })\n\n  it('does not use the Zone.js setTimeout function', () => {\n    const zoneJsSetTimeoutSpy = jasmine.createSpy()\n    zoneJs.replaceProperty(window, 'setTimeout', zoneJsSetTimeoutSpy)\n\n    const object = {} as { foo: number }\n    Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n\n    instrumentSetter(object, 'foo', noop)\n    object.foo = 2\n\n    clock.tick(0)\n\n    expect(zoneJsSetTimeoutSpy).not.toHaveBeenCalled()\n  })\n\n  it('allows other instrumentations from third parties', () => {\n    const object = {} as { foo: number }\n    Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n    const instrumentationSetterSpy = jasmine.createSpy()\n    instrumentSetter(object, 'foo', instrumentationSetterSpy)\n\n    const thirdPartyInstrumentationSpy = thirdPartyInstrumentation(object)\n\n    object.foo = 2\n    expect(thirdPartyInstrumentationSpy).toHaveBeenCalledOnceWith(2)\n    clock.tick(0)\n    expect(instrumentationSetterSpy).toHaveBeenCalledOnceWith(object, 2)\n  })\n\n  describe('stop()', () => {\n    it('restores the original behavior', () => {\n      const object = {} as { foo: number }\n      const originalSetter = () => {\n        // do nothing particular, only used to test if this setter gets replaced\n      }\n      Object.defineProperty(object, 'foo', { set: originalSetter, configurable: true })\n      const { stop } = instrumentSetter(object, 'foo', noop)\n\n      stop()\n\n      // eslint-disable-next-line @typescript-eslint/unbound-method\n      expect(Object.getOwnPropertyDescriptor(object, 'foo')!.set).toBe(originalSetter)\n    })\n\n    it('does not call the instrumentation anymore', () => {\n      const object = {} as { foo: number }\n      Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n      const instrumentationSetterSpy = jasmine.createSpy()\n      const { stop } = instrumentSetter(object, 'foo', instrumentationSetterSpy)\n\n      stop()\n\n      object.foo = 2\n      clock.tick(0)\n\n      expect(instrumentationSetterSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not call instrumentation pending in the event loop via setTimeout', () => {\n      const object = {} as { foo: number }\n      Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n      const instrumentationSetterSpy = jasmine.createSpy()\n      const { stop } = instrumentSetter(object, 'foo', instrumentationSetterSpy)\n\n      object.foo = 2\n      stop()\n      clock.tick(0)\n\n      expect(instrumentationSetterSpy).not.toHaveBeenCalled()\n    })\n\n    describe('when the method has been instrumented by a third party', () => {\n      it('should not break the third party instrumentation', () => {\n        const object = {} as { foo: number }\n        Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n        const { stop } = instrumentSetter(object, 'foo', noop)\n\n        const thirdPartyInstrumentationSpy = thirdPartyInstrumentation(object)\n\n        stop()\n\n        // eslint-disable-next-line @typescript-eslint/unbound-method\n        expect(Object.getOwnPropertyDescriptor(object, 'foo')!.set).toBe(thirdPartyInstrumentationSpy)\n      })\n\n      it('does not call the instrumentation', () => {\n        const object = {} as { foo: number }\n        Object.defineProperty(object, 'foo', { set: noop, configurable: true })\n        const instrumentationSetterSpy = jasmine.createSpy()\n        const { stop } = instrumentSetter(object, 'foo', instrumentationSetterSpy)\n\n        thirdPartyInstrumentation(object)\n\n        stop()\n\n        object.foo = 2\n        clock.tick(0)\n\n        expect(instrumentationSetterSpy).not.toHaveBeenCalled()\n      })\n    })\n  })\n\n  function thirdPartyInstrumentation(object: { foo: number }) {\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    const originalSetter = Object.getOwnPropertyDescriptor(object, 'foo')!.set\n    const thirdPartyInstrumentationSpy = jasmine.createSpy().and.callFake(function (this: any, value) {\n      if (originalSetter) {\n        originalSetter.call(this, value)\n      }\n    })\n    Object.defineProperty(object, 'foo', { set: thirdPartyInstrumentationSpy })\n    return thirdPartyInstrumentationSpy\n  }\n})\n"
  },
  {
    "path": "packages/core/src/tools/instrumentMethod.ts",
    "content": "import { setTimeout } from './timer'\nimport { callMonitored } from './monitor'\nimport { noop } from './utils/functionUtils'\nimport { createHandlingStack } from './stackTrace/handlingStack'\n\n/**\n * Object passed to the callback of an instrumented method call. See `instrumentMethod` for more\n * info.\n */\nexport interface InstrumentedMethodCall<TARGET extends { [key: string]: any }, METHOD extends keyof TARGET> {\n  /**\n   * The target object on which the method was called.\n   */\n  target: TARGET\n\n  /**\n   * The parameters with which the method was called.\n   *\n   * Note: if needed, parameters can be mutated by the instrumentation\n   */\n  parameters: Parameters<TARGET[METHOD]>\n\n  /**\n   * Registers a callback that will be called after the original method is called, with the method\n   * result passed as argument.\n   */\n  onPostCall: (callback: PostCallCallback<TARGET, METHOD>) => void\n\n  /**\n   * The stack trace of the method call.\n   */\n  handlingStack?: string\n}\n\ntype PostCallCallback<TARGET extends { [key: string]: any }, METHOD extends keyof TARGET> = (\n  result: ReturnType<TARGET[METHOD]>\n) => void\n\n/**\n * Instruments a method on a object, calling the given callback before the original method is\n * invoked. The callback receives an object with information about the method call.\n *\n * This function makes sure that we are \"good citizens\" regarding third party instrumentations: when\n * removing the instrumentation, the original method is usually restored, but if a third party\n * instrumentation was set after ours, we keep it in place and just replace our instrumentation with\n * a noop.\n *\n * Note: it is generally better to instrument methods that are \"owned\" by the object instead of ones\n * that are inherited from the prototype chain. Example:\n * * do:    `instrumentMethod(Array.prototype, 'push', ...)`\n * * don't: `instrumentMethod([], 'push', ...)`\n *\n * This method is also used to set event handler properties (ex: window.onerror = ...), as it has\n * the same requirements as instrumenting a method:\n * * if the event handler is already set by a third party, we need to call it and not just blindly\n * override it.\n * * if the event handler is set by a third party after us, we need to keep it in place when\n * removing ours.\n *\n * @example\n *\n *  instrumentMethod(window, 'fetch', ({ target, parameters, onPostCall }) => {\n *    console.log('Before calling fetch on', target, 'with parameters', parameters)\n *\n *    onPostCall((result) => {\n *      console.log('After fetch calling on', target, 'with parameters', parameters, 'and result', result)\n *    })\n *  })\n */\nexport function instrumentMethod<TARGET extends { [key: string]: any }, METHOD extends keyof TARGET>(\n  targetPrototype: TARGET,\n  method: METHOD,\n  onPreCall: (this: null, callInfos: InstrumentedMethodCall<TARGET, METHOD>) => void,\n  { computeHandlingStack }: { computeHandlingStack?: boolean } = {}\n) {\n  let original = targetPrototype[method]\n\n  if (typeof original !== 'function') {\n    if (method in targetPrototype && typeof method === 'string' && method.startsWith('on')) {\n      original = noop as TARGET[METHOD]\n    } else {\n      return { stop: noop }\n    }\n  }\n\n  let stopped = false\n\n  const instrumentation = function (this: TARGET): ReturnType<TARGET[METHOD]> {\n    if (stopped) {\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call\n      return original.apply(this, arguments as unknown as Parameters<TARGET[METHOD]>)\n    }\n\n    const parameters = Array.from(arguments) as Parameters<TARGET[METHOD]>\n\n    let postCallCallback: PostCallCallback<TARGET, METHOD> | undefined\n\n    callMonitored(onPreCall, null, [\n      {\n        target: this,\n        parameters,\n        onPostCall: (callback) => {\n          postCallCallback = callback\n        },\n        handlingStack: computeHandlingStack ? createHandlingStack('instrumented method') : undefined,\n      },\n    ])\n\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n    const result = original.apply(this, parameters)\n\n    if (postCallCallback) {\n      callMonitored(postCallCallback, null, [result])\n    }\n\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n    return result\n  }\n\n  targetPrototype[method] = instrumentation as TARGET[METHOD]\n\n  return {\n    stop: () => {\n      stopped = true\n      // If the instrumentation has been removed by a third party, keep the last one\n      if (targetPrototype[method] === instrumentation) {\n        targetPrototype[method] = original\n      }\n    },\n  }\n}\n\nexport function instrumentSetter<TARGET extends { [key: string]: any }, PROPERTY extends keyof TARGET>(\n  targetPrototype: TARGET,\n  property: PROPERTY,\n  after: (target: TARGET, value: TARGET[PROPERTY]) => void\n) {\n  const originalDescriptor = Object.getOwnPropertyDescriptor(targetPrototype, property)\n  if (!originalDescriptor || !originalDescriptor.set || !originalDescriptor.configurable) {\n    return { stop: noop }\n  }\n\n  const stoppedInstrumentation = noop\n  let instrumentation = (target: TARGET, value: TARGET[PROPERTY]) => {\n    // put hooked setter into event loop to avoid of set latency\n    setTimeout(() => {\n      if (instrumentation !== stoppedInstrumentation) {\n        after(target, value)\n      }\n    }, 0)\n  }\n\n  const instrumentationWrapper = function (this: TARGET, value: TARGET[PROPERTY]) {\n    originalDescriptor.set!.call(this, value)\n    instrumentation(this, value)\n  }\n\n  Object.defineProperty(targetPrototype, property, {\n    set: instrumentationWrapper,\n  })\n\n  return {\n    stop: () => {\n      if (Object.getOwnPropertyDescriptor(targetPrototype, property)?.set === instrumentationWrapper) {\n        Object.defineProperty(targetPrototype, property, originalDescriptor)\n      }\n      instrumentation = stoppedInstrumentation\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/matchOption.spec.ts",
    "content": "import { display } from './display'\nimport { matchList } from './matchOption'\n\ndescribe('matchList', () => {\n  it('should match exact value', () => {\n    const list = ['foo', 'bar']\n    expect(matchList(list, 'foo')).toBe(true)\n    expect(matchList(list, 'bar')).toBe(true)\n    expect(matchList(list, 'qux')).toBe(false)\n  })\n\n  it('should match regexp', () => {\n    const list = [/^foo/, /foo$/]\n    expect(matchList(list, 'foobar')).toBe(true)\n    expect(matchList(list, 'barfoo')).toBe(true)\n    expect(matchList(list, 'barqux')).toBe(false)\n  })\n\n  it('should match function', () => {\n    const list = [(value: string) => value === 'foo', (value: string) => value === 'bar']\n    expect(matchList(list, 'foo')).toBe(true)\n    expect(matchList(list, 'bar')).toBe(true)\n    expect(matchList(list, 'qux')).toBe(false)\n  })\n\n  it('should compare strings using startsWith when enabling the option', () => {\n    const list = ['http://my.domain.com']\n    expect(matchList(list, 'http://my.domain.com/action', true)).toBe(true)\n  })\n\n  it('should match consistently when regexp has global flag', () => {\n    const list = [/foo/g]\n    expect(matchList(list, 'foobar')).toBe(true)\n    expect(matchList(list, 'foobar')).toBe(true)\n    expect(matchList(list, 'foobar')).toBe(true)\n  })\n\n  it('should catch error from provided function', () => {\n    spyOn(display, 'error')\n    const list = [\n      (_: string) => {\n        throw new Error('oops')\n      },\n    ]\n    expect(matchList(list, 'foo')).toBe(false)\n    expect(display.error).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/matchOption.ts",
    "content": "import { display } from './display'\nimport { getType } from './utils/typeUtils'\n\nexport type MatchOption = string | RegExp | ((value: string) => boolean)\n\nexport function isMatchOption(item: unknown): item is MatchOption {\n  const itemType = getType(item)\n  return itemType === 'string' || itemType === 'function' || item instanceof RegExp\n}\n\n/**\n * Returns true if value can be matched by at least one of the provided MatchOptions.\n * When comparing strings, setting useStartsWith to true will compare the value with the start of\n * the option, instead of requiring an exact match.\n */\nexport function matchList(list: MatchOption[], value: string, useStartsWith = false): boolean {\n  return list.some((item) => {\n    try {\n      if (typeof item === 'function') {\n        return item(value)\n      } else if (item instanceof RegExp) {\n        // Prevent stateful matching\n        item.lastIndex = 0\n        return item.test(value)\n      } else if (typeof item === 'string') {\n        return useStartsWith ? value.startsWith(item) : item === value\n      }\n    } catch (e) {\n      display.error(e)\n    }\n    return false\n  })\n}\n"
  },
  {
    "path": "packages/core/src/tools/mergeInto.spec.ts",
    "content": "import { deepClone, mergeInto, combine } from './mergeInto'\n\ndescribe('mergeInto', () => {\n  describe('source is not an object or array', () => {\n    it('should ignore undefined sources', () => {\n      const destination = {}\n      expect(mergeInto(destination, undefined)).toBe(destination)\n    })\n\n    it('should ignore undefined destination', () => {\n      expect(mergeInto(undefined, 1)).toBe(1)\n    })\n\n    it('should ignore destinations with a different type', () => {\n      expect(mergeInto({}, 1)).toBe(1)\n    })\n  })\n\n  describe('source is an array', () => {\n    it('should create a new array if destination is undefined', () => {\n      const source = [1]\n      const result = mergeInto(undefined, source)\n      expect(result).not.toBe(source)\n      expect(result).toEqual(source)\n    })\n\n    it('should return the copy of source if the destination is not an array', () => {\n      const source = [1]\n      expect(mergeInto({}, source)).toEqual(source)\n    })\n\n    it('should mutate and return destination if it is an array', () => {\n      const destination = ['destination']\n      const source = ['source']\n      const result = mergeInto(destination, source)\n      expect(result).toBe(destination)\n      expect(result).toEqual(source)\n    })\n  })\n\n  describe('source is an object', () => {\n    it('should create a new object if destination is undefined', () => {\n      const source = {}\n      const result = mergeInto(undefined, source)\n      expect(result).not.toBe(source)\n      expect(result).toEqual(source)\n    })\n\n    it('should return the copy of source if the destination is not an object', () => {\n      const source = { a: 1 }\n      expect(mergeInto([], source)).toEqual(source)\n    })\n\n    it('should mutate and return destination if it is an object', () => {\n      const destination = {}\n      const source = { a: 'b' }\n      const result = mergeInto(destination, source)\n      expect(result).toBe(destination as any)\n      expect(result).toEqual(source)\n    })\n  })\n})\n\ndescribe('combine', () => {\n  it('should deeply add and replace keys', () => {\n    const sourceA = { a: { b: 'toBeReplaced', c: 'source a' } }\n    const sourceB = { a: { b: 'replaced', d: 'source b' } }\n    expect(combine(sourceA, sourceB)).toEqual({ a: { b: 'replaced', c: 'source a', d: 'source b' } })\n  })\n\n  it('should not replace with undefined', () => {\n    expect(combine({ a: 1 }, { a: undefined as number | undefined })).toEqual({ a: 1 })\n  })\n\n  it('should replace a sub-value with null', () => {\n    expect(combine({ a: {} }, { a: null as any })).toEqual({ a: null })\n  })\n\n  it('should ignore null arguments', () => {\n    expect(combine({ a: 1 }, null)).toEqual({ a: 1 })\n  })\n\n  it('should merge arrays', () => {\n    const sourceA = [{ a: 'source a' }, 'extraString'] as any\n    const sourceB = [{ b: 'source b' }] as any\n    expect(combine(sourceA, sourceB)).toEqual([{ a: 'source a', b: 'source b' }, 'extraString'])\n  })\n\n  it('should merge multiple objects', () => {\n    expect(combine({ a: 1 }, { b: 2 }, { c: 3 })).toEqual({ a: 1, b: 2, c: 3 })\n  })\n\n  it('should not keep references on objects', () => {\n    const source = { a: { b: 1 } }\n    const result = combine({}, source)\n    expect(result.a).not.toBe(source.a)\n  })\n\n  it('should not keep references on arrays', () => {\n    const source = { a: [1] }\n    const result = combine({}, source)\n    expect(result.a).not.toBe(source.a)\n  })\n})\n\ndescribe('deepClone', () => {\n  it('should pass-through primitive values', () => {\n    expect(deepClone('test')).toBe('test')\n    expect(deepClone(true)).toBe(true)\n    expect(deepClone(false)).toBe(false)\n    expect(deepClone(null)).toBe(null)\n    expect(deepClone(undefined)).toBe(undefined)\n    expect(deepClone(1)).toBe(1)\n    expect(deepClone(NaN)).toBeNaN()\n    expect(deepClone(Infinity)).toBe(Infinity)\n    expect(deepClone(-Infinity)).toBe(-Infinity)\n  })\n\n  it('should pass-through functions', () => {\n    const fn = () => null\n    expect(deepClone(fn)).toBe(fn)\n  })\n\n  it('should pass-through classes', () => {\n    class Foo {}\n    // typeof class is 'function' so it will behave the same as for function case\n    expect(deepClone(Foo)).toBe(Foo)\n  })\n\n  it('should clone array recursively', () => {\n    const source = [1, undefined, null, [4, 5, 6]]\n    const clone = deepClone(source)\n\n    expect(clone).toEqual(source)\n    expect(clone).not.toBe(source)\n    source.push(7)\n    ;(source[3] as any[]).push(8)\n\n    expect(clone[4]).toBeUndefined()\n    expect((clone[3] as any[])[3]).toBeUndefined()\n  })\n\n  it('should clone object recursively', () => {\n    const source = { foo: 'bar', baz: { arr: [1, 2], fn: () => undefined } }\n    const clone = deepClone(source)\n\n    expect(clone).toEqual(source)\n    expect(clone).not.toBe(source)\n    source.baz.arr.push(1)\n    ;(source.baz as any).added = 'test'\n\n    expect(clone.baz.arr).toEqual([1, 2])\n    expect((clone.baz as any).added).toBeUndefined()\n  })\n\n  it('should clone regexp', () => {\n    const source = { reg: /test/gi }\n    const clone = deepClone(source)\n\n    expect(clone).toEqual(source)\n    expect(clone).not.toBe(source)\n    expect(clone.reg).not.toBe(source.reg)\n\n    expect(clone.reg.ignoreCase).toBe(true)\n    expect(clone.reg.global).toBe(true)\n    expect(clone.reg.multiline).toBe(false)\n  })\n\n  it('should clone date', () => {\n    const source = [1, new Date('2012-12-12')] as const\n    const clone = deepClone(source)\n\n    expect(clone).toEqual(source)\n    expect(clone).not.toBe(source)\n    expect(clone[1]).not.toBe(source[1])\n\n    const originalTime = source[1].getTime()\n    source[1].setTime(originalTime + 100)\n    expect(clone[1].getTime()).toEqual(originalTime)\n  })\n\n  it('should remove circular references', () => {\n    const a: Record<string, any> = { foo: 'bar', ref: null }\n    const b: Record<string, any> = { baz: 'bar', ref: null }\n    // create circular reference\n    a.ref = b\n    b.ref = a\n\n    const clonedA = deepClone(a)\n    const clonedB = deepClone(b)\n\n    expect(clonedA).not.toEqual(a)\n    expect(clonedA.ref.ref).toBeUndefined()\n\n    expect(clonedB).not.toEqual(b)\n    expect(clonedB.ref.ref).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/mergeInto.ts",
    "content": "import { getType } from './utils/typeUtils'\n\ntype Merged<TDestination, TSource> =\n  // case 1 - source is undefined - return destination\n  TSource extends undefined\n    ? TDestination\n    : // case 2 - destination is undefined - return source\n      TDestination extends undefined\n      ? TSource\n      : // case 3 - source is an array - see if it merges or overwrites\n        TSource extends any[]\n        ? TDestination extends any[]\n          ? TDestination & TSource\n          : TSource\n        : // case 4 - source is an object - see if it merges or overwrites\n          TSource extends object\n          ? TDestination extends object\n            ? TDestination extends any[]\n              ? TSource\n              : TDestination & TSource\n            : TSource\n          : // case 5 - cannot merge - return source\n            TSource\n\n/**\n * Iterate over source and affect its sub values into destination, recursively.\n * If the source and destination can't be merged, return source.\n */\nexport function mergeInto<D, S>(\n  destination: D,\n  source: S,\n  circularReferenceChecker = createCircularReferenceChecker()\n): Merged<D, S> {\n  // ignore the source if it is undefined\n  if (source === undefined) {\n    return destination as Merged<D, S>\n  }\n\n  if (typeof source !== 'object' || source === null) {\n    // primitive values - just return source\n    return source as Merged<D, S>\n  } else if (source instanceof Date) {\n    return new Date(source.getTime()) as unknown as Merged<D, S>\n  } else if (source instanceof RegExp) {\n    const flags =\n      source.flags ||\n      // old browsers compatibility\n      [\n        source.global ? 'g' : '',\n        source.ignoreCase ? 'i' : '',\n        source.multiline ? 'm' : '',\n        source.sticky ? 'y' : '',\n        source.unicode ? 'u' : '',\n      ].join('')\n    return new RegExp(source.source, flags) as unknown as Merged<D, S>\n  }\n\n  if (circularReferenceChecker.hasAlreadyBeenSeen(source)) {\n    // remove circular references\n    return undefined as unknown as Merged<D, S>\n  } else if (Array.isArray(source)) {\n    const merged: any[] = Array.isArray(destination) ? destination : []\n    for (let i = 0; i < source.length; ++i) {\n      merged[i] = mergeInto(merged[i], source[i], circularReferenceChecker)\n    }\n    return merged as unknown as Merged<D, S>\n  }\n\n  const merged = getType(destination) === 'object' ? (destination as Record<any, any>) : {}\n  for (const key in source) {\n    if (Object.prototype.hasOwnProperty.call(source, key)) {\n      merged[key] = mergeInto(merged[key], source[key], circularReferenceChecker)\n    }\n  }\n  return merged as unknown as Merged<D, S>\n}\n\n/**\n * A simplistic implementation of a deep clone algorithm.\n * Caveats:\n * - It doesn't maintain prototype chains - don't use with instances of custom classes.\n * - It doesn't handle Map and Set\n */\nexport function deepClone<T>(value: T): T {\n  return mergeInto(undefined, value) as T\n}\n\ntype Combined<A, B> = A extends null ? B : B extends null ? A : Merged<A, B>\n\n/*\n * Performs a deep merge of objects and arrays.\n * - Arguments won't be mutated\n * - Object and arrays in the output value are de-referenced (\"deep cloned\")\n * - Arrays values are merged index by index\n * - Objects are merged by keys\n * - Values get replaced, unless undefined\n */\nexport function combine<A, B>(a: A, b: B): Combined<A, B>\nexport function combine<A, B, C>(a: A, b: B, c: C): Combined<Combined<A, B>, C>\nexport function combine<A, B, C, D>(a: A, b: B, c: C, d: D): Combined<Combined<Combined<A, B>, C>, D>\nexport function combine<A, B, C, D, E>(\n  a: A,\n  b: B,\n  c: C,\n  d: D,\n  e: E\n): Combined<Combined<Combined<Combined<A, B>, C>, D>, E>\nexport function combine<A, B, C, D, E, F>(\n  a: A,\n  b: B,\n  c: C,\n  d: D,\n  e: E,\n  f: F\n): Combined<Combined<Combined<Combined<Combined<A, B>, C>, D>, E>, F>\nexport function combine<A, B, C, D, E, F, G>(\n  a: A,\n  b: B,\n  c: C,\n  d: D,\n  e: E,\n  f: F,\n  g: G\n): Combined<Combined<Combined<Combined<Combined<Combined<A, B>, C>, D>, E>, F>, G>\nexport function combine<A, B, C, D, E, F, G, H>(\n  a: A,\n  b: B,\n  c: C,\n  d: D,\n  e: E,\n  f: F,\n  g: G,\n  h: H\n): Combined<Combined<Combined<Combined<Combined<Combined<Combined<A, B>, C>, D>, E>, F>, G>, H>\nexport function combine(...sources: any[]): unknown {\n  let destination: any\n\n  for (const source of sources) {\n    // Ignore any undefined or null sources.\n    if (source === undefined || source === null) {\n      continue\n    }\n\n    destination = mergeInto(destination, source)\n  }\n\n  return destination as unknown\n}\n\ninterface CircularReferenceChecker {\n  hasAlreadyBeenSeen(value: any): boolean\n}\n\nfunction createCircularReferenceChecker(): CircularReferenceChecker {\n  if (typeof WeakSet !== 'undefined') {\n    const set: WeakSet<any> = new WeakSet()\n    return {\n      hasAlreadyBeenSeen(value) {\n        const has = set.has(value)\n        if (!has) {\n          set.add(value)\n        }\n        return has\n      },\n    }\n  }\n  const array: any[] = []\n  return {\n    hasAlreadyBeenSeen(value) {\n      const has = array.indexOf(value) >= 0\n      if (!has) {\n        array.push(value)\n      }\n      return has\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/mockable.ts",
    "content": "declare const __BUILD_ENV__SDK_VERSION__: string\n\nexport const mockableReplacements = new Map<unknown, unknown>()\n\n/**\n * Wraps a value to make it mockable in tests. In production builds, this is a no-op\n * that returns the value as-is. In test builds, it checks if a mock replacement has\n * been registered and returns that instead.\n *\n * @example\n * // In source file:\n * import { mockable } from '../tools/mockable'\n * export function formatNavigationEntry(): string {\n *   const navigationEntry = mockable(getNavigationEntry)()\n *   ...\n * }\n *\n * // In test file:\n * import { replaceMockable } from '@datadog/browser-core/test'\n * it('...', () => {\n *   replaceMockable(getNavigationEntry, () => FAKE_NAVIGATION_ENTRY)\n *   expect(formatNavigationEntry()).toEqual(...)\n * })\n */\nexport function mockable<T>(value: T): T {\n  // In test builds, return a wrapper that checks for mocks at call time\n  if (__BUILD_ENV__SDK_VERSION__ === 'test' && mockableReplacements.has(value)) {\n    return mockableReplacements.get(value)! as T\n  }\n  // In production, return the value as-is\n  return value\n}\n"
  },
  {
    "path": "packages/core/src/tools/monitor.spec.ts",
    "content": "import { display } from './display'\nimport { callMonitored, monitor, monitored, startMonitorErrorCollection, setDebugMode } from './monitor'\n\ndescribe('monitor', () => {\n  let onMonitorErrorCollectedSpy: jasmine.Spy<(error: unknown) => void>\n\n  beforeEach(() => {\n    onMonitorErrorCollectedSpy = jasmine.createSpy()\n  })\n\n  describe('decorator', () => {\n    class Candidate {\n      @monitored\n      monitoredThrowing() {\n        throw new Error('monitored')\n      }\n\n      @monitored\n      monitoredStringErrorThrowing() {\n        // eslint-disable-next-line @typescript-eslint/only-throw-error\n        throw 'string error'\n      }\n\n      @monitored\n      monitoredObjectErrorThrowing() {\n        // eslint-disable-next-line @typescript-eslint/only-throw-error\n        throw { foo: 'bar' }\n      }\n\n      @monitored\n      monitoredNotThrowing() {\n        return 1\n      }\n\n      notMonitoredThrowing() {\n        throw new Error('not monitored')\n      }\n    }\n\n    let candidate: Candidate\n    beforeEach(() => {\n      candidate = new Candidate()\n    })\n\n    describe('before initialization', () => {\n      it('should not monitor', () => {\n        expect(() => candidate.notMonitoredThrowing()).toThrowError('not monitored')\n        expect(() => candidate.monitoredThrowing()).toThrowError('monitored')\n        expect(candidate.monitoredNotThrowing()).toEqual(1)\n      })\n    })\n\n    describe('after initialization', () => {\n      beforeEach(() => {\n        startMonitorErrorCollection(onMonitorErrorCollectedSpy)\n      })\n\n      it('should preserve original behavior', () => {\n        expect(candidate.monitoredNotThrowing()).toEqual(1)\n      })\n\n      it('should catch error', () => {\n        expect(() => candidate.notMonitoredThrowing()).toThrowError()\n        expect(() => candidate.monitoredThrowing()).not.toThrowError()\n      })\n\n      it('should report error', () => {\n        candidate.monitoredThrowing()\n\n        expect(onMonitorErrorCollectedSpy).toHaveBeenCalledOnceWith(new Error('monitored'))\n      })\n\n      it('should report string error', () => {\n        candidate.monitoredStringErrorThrowing()\n\n        expect(onMonitorErrorCollectedSpy).toHaveBeenCalledOnceWith('string error')\n      })\n\n      it('should report object error', () => {\n        candidate.monitoredObjectErrorThrowing()\n\n        expect(onMonitorErrorCollectedSpy).toHaveBeenCalledOnceWith({ foo: 'bar' })\n      })\n    })\n  })\n\n  describe('function', () => {\n    const notThrowing = () => 1\n    const throwing = () => {\n      throw new Error('error')\n    }\n\n    beforeEach(() => {\n      startMonitorErrorCollection(onMonitorErrorCollectedSpy)\n    })\n\n    describe('direct call', () => {\n      it('should preserve original behavior', () => {\n        expect(callMonitored(notThrowing)).toEqual(1)\n      })\n\n      it('should catch error', () => {\n        expect(() => callMonitored(throwing)).not.toThrowError()\n      })\n\n      it('should report error', () => {\n        callMonitored(throwing)\n\n        expect(onMonitorErrorCollectedSpy).toHaveBeenCalledOnceWith(new Error('error'))\n      })\n    })\n\n    describe('wrapper', () => {\n      it('should preserve original behavior', () => {\n        const decorated = monitor(notThrowing)\n        expect(decorated()).toEqual(1)\n      })\n\n      it('should catch error', () => {\n        const decorated = monitor(throwing)\n        expect(() => decorated()).not.toThrowError()\n      })\n\n      it('should report error', () => {\n        monitor(throwing)()\n\n        expect(onMonitorErrorCollectedSpy).toHaveBeenCalledOnceWith(new Error('error'))\n      })\n    })\n  })\n\n  describe('setDebugMode', () => {\n    let displaySpy: jasmine.Spy\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'error')\n    })\n\n    it('when not called, should not display error', () => {\n      callMonitored(() => {\n        throw new Error('message')\n      })\n\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('when called, should display error', () => {\n      setDebugMode(true)\n\n      callMonitored(() => {\n        throw new Error('message')\n      })\n\n      expect(displaySpy).toHaveBeenCalledOnceWith('[MONITOR]', new Error('message'))\n    })\n\n    it('displays errors thrown by the onMonitorErrorCollected callback', () => {\n      setDebugMode(true)\n      onMonitorErrorCollectedSpy.and.throwError(new Error('unexpected'))\n      startMonitorErrorCollection(onMonitorErrorCollectedSpy)\n\n      callMonitored(() => {\n        throw new Error('message')\n      })\n      expect(displaySpy).toHaveBeenCalledWith('[MONITOR]', new Error('message'))\n      expect(displaySpy).toHaveBeenCalledWith('[MONITOR]', new Error('unexpected'))\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/monitor.ts",
    "content": "import { display } from './display'\n\nlet onMonitorErrorCollected: undefined | ((error: unknown) => void)\nlet debugMode = false\n\nexport function startMonitorErrorCollection(newOnMonitorErrorCollected: (error: unknown) => void) {\n  onMonitorErrorCollected = newOnMonitorErrorCollected\n}\n\nexport function setDebugMode(newDebugMode: boolean) {\n  debugMode = newDebugMode\n}\n\nexport function resetMonitor() {\n  onMonitorErrorCollected = undefined\n  debugMode = false\n}\n\nexport function monitored<T extends (...params: any[]) => unknown>(\n  _: any,\n  __: string,\n  descriptor: TypedPropertyDescriptor<T>\n) {\n  const originalMethod = descriptor.value!\n  descriptor.value = function (this: ThisParameterType<T>, ...args: Parameters<T>) {\n    const decorated = onMonitorErrorCollected ? monitor(originalMethod) : originalMethod\n    return decorated.apply(this, args) as ReturnType<T>\n  } as T\n}\n\nexport function monitor<T extends (...args: any[]) => unknown>(fn: T): T {\n  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\n    return callMonitored(fn, this, args)\n  } as unknown as T // consider output type has input type\n}\n\nexport function callMonitored<T extends (...args: any[]) => unknown>(\n  fn: T,\n  context: ThisParameterType<T>,\n  args: Parameters<T>\n): ReturnType<T> | undefined\nexport function callMonitored<T extends (this: void) => unknown>(fn: T): ReturnType<T> | undefined\nexport function callMonitored<T extends (...args: any[]) => unknown>(\n  fn: T,\n  context?: any,\n  args?: any\n): ReturnType<T> | undefined {\n  try {\n    return fn.apply(context, args) as ReturnType<T>\n  } catch (e) {\n    monitorError(e)\n  }\n}\n\nexport function monitorError(e: unknown) {\n  displayIfDebugEnabled(e)\n  if (onMonitorErrorCollected) {\n    try {\n      onMonitorErrorCollected(e)\n    } catch (e) {\n      displayIfDebugEnabled(e)\n    }\n  }\n}\n\nexport function displayIfDebugEnabled(...args: unknown[]) {\n  if (debugMode) {\n    display.error('[MONITOR]', ...args)\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/observable.spec.ts",
    "content": "import { waitNextMicrotask } from '../../test'\nimport { BufferedObservable, mergeObservables, Observable } from './observable'\n\ndescribe('observable', () => {\n  let observable: Observable<void>\n  let subscriber: jasmine.Spy<jasmine.Func>\n\n  beforeEach(() => {\n    observable = new Observable()\n    subscriber = jasmine.createSpy('sub')\n  })\n\n  it('should allow to subscribe and be notified', () => {\n    observable.subscribe(subscriber)\n    expect(subscriber).not.toHaveBeenCalled()\n\n    observable.notify()\n    expect(subscriber).toHaveBeenCalledTimes(1)\n\n    observable.notify()\n    expect(subscriber).toHaveBeenCalledTimes(2)\n  })\n\n  it('should notify multiple clients', () => {\n    const otherSubscriber = jasmine.createSpy('sub2')\n    observable.subscribe(subscriber)\n    observable.subscribe(otherSubscriber)\n\n    observable.notify()\n\n    expect(subscriber).toHaveBeenCalled()\n    expect(otherSubscriber).toHaveBeenCalled()\n  })\n\n  it('should allow to unsubscribe', () => {\n    const subscription = observable.subscribe(subscriber)\n\n    subscription.unsubscribe()\n    observable.notify()\n\n    expect(subscriber).not.toHaveBeenCalled()\n  })\n\n  it('should execute onFirstSubscribe callback', () => {\n    const onFirstSubscribe = jasmine.createSpy('callback')\n    const otherSubscriber = jasmine.createSpy('sub2')\n    observable = new Observable(onFirstSubscribe)\n    expect(onFirstSubscribe).not.toHaveBeenCalled()\n\n    observable.subscribe(subscriber)\n    expect(onFirstSubscribe).toHaveBeenCalledTimes(1)\n\n    observable.subscribe(otherSubscriber)\n    expect(onFirstSubscribe).toHaveBeenCalledTimes(1)\n  })\n\n  it('should notify the first subscriber if the onFirstSubscribe callback notifies synchronously ', () => {\n    const onFirstSubscribe = jasmine.createSpy('callback').and.callFake((observable: Observable<void>) => {\n      observable.notify()\n    })\n    observable = new Observable(onFirstSubscribe)\n    observable.subscribe(subscriber)\n\n    expect(onFirstSubscribe).toHaveBeenCalledTimes(1)\n    expect(subscriber).toHaveBeenCalledTimes(1)\n  })\n\n  it('should pass the observable instance to the onFirstSubscribe callback', () => {\n    const onFirstSubscribe = jasmine.createSpy('callback')\n    observable = new Observable(onFirstSubscribe)\n    observable.subscribe(subscriber)\n\n    expect(onFirstSubscribe).toHaveBeenCalledWith(observable)\n  })\n\n  it('should execute onLastUnsubscribe callback', () => {\n    const onLastUnsubscribe = jasmine.createSpy('callback')\n    const otherSubscriber = jasmine.createSpy('sub2')\n    observable = new Observable(() => onLastUnsubscribe)\n    const subscription = observable.subscribe(subscriber)\n    const otherSubscription = observable.subscribe(otherSubscriber)\n    expect(onLastUnsubscribe).not.toHaveBeenCalled()\n\n    subscription.unsubscribe()\n    expect(onLastUnsubscribe).not.toHaveBeenCalled()\n\n    otherSubscription.unsubscribe()\n    expect(onLastUnsubscribe).toHaveBeenCalled()\n  })\n})\n\ndescribe('mergeObservables', () => {\n  let observableOne: Observable<void>\n  let observableTwo: Observable<void>\n  let mergedObservable: Observable<void>\n  let subscriber: jasmine.Spy<jasmine.Func>\n\n  beforeEach(() => {\n    observableOne = new Observable<void>()\n    observableTwo = new Observable<void>()\n    mergedObservable = mergeObservables(observableOne, observableTwo)\n    subscriber = jasmine.createSpy('subscriber')\n  })\n\n  it('should notify when one of the merged observable notifies', () => {\n    mergedObservable.subscribe(subscriber)\n    observableOne.notify()\n    observableTwo.notify()\n\n    expect(subscriber).toHaveBeenCalledTimes(2)\n  })\n\n  it('should allow to unsubscribe to all merged observables', () => {\n    const subscription = mergedObservable.subscribe(subscriber)\n\n    subscription.unsubscribe()\n    observableOne.notify()\n    observableTwo.notify()\n\n    expect(subscriber).not.toHaveBeenCalled()\n  })\n})\n\ndescribe('BufferedObservable', () => {\n  it('invokes the observer with buffered data', async () => {\n    const observable = new BufferedObservable<string>(100)\n    observable.notify('first')\n    observable.notify('second')\n\n    const observer = jasmine.createSpy('observer')\n    observable.subscribe(observer)\n\n    await waitNextMicrotask()\n\n    expect(observer).toHaveBeenCalledTimes(2)\n  })\n\n  it('invokes the observer asynchronously', async () => {\n    const observable = new BufferedObservable<string>(100)\n    observable.notify('first')\n\n    const observer = jasmine.createSpy('observer')\n    observable.subscribe(observer)\n\n    expect(observer).not.toHaveBeenCalled()\n\n    await waitNextMicrotask()\n\n    expect(observer).toHaveBeenCalledWith('first')\n  })\n\n  it('invokes the observer when new data is notified after subscription', async () => {\n    const observable = new BufferedObservable<string>(100)\n\n    const observer = jasmine.createSpy('observer')\n    observable.subscribe(observer)\n\n    observable.notify('first')\n\n    await waitNextMicrotask()\n\n    observable.notify('second')\n\n    expect(observer).toHaveBeenCalledTimes(2)\n    expect(observer).toHaveBeenCalledWith('first')\n    expect(observer).toHaveBeenCalledWith('second')\n  })\n\n  it('drops data when the buffer is full', async () => {\n    const observable = new BufferedObservable<string>(2)\n    observable.notify('first') // This should be dropped\n    observable.notify('second')\n    observable.notify('third')\n\n    const observer = jasmine.createSpy('observer')\n    observable.subscribe(observer)\n\n    await waitNextMicrotask()\n\n    expect(observer).toHaveBeenCalledTimes(2)\n    expect(observer).toHaveBeenCalledWith('second')\n    expect(observer).toHaveBeenCalledWith('third')\n  })\n\n  it('allows to unsubscribe from the observer, the middle of buffered data', async () => {\n    const observable = new BufferedObservable<string>(100)\n    observable.notify('first')\n    observable.notify('second')\n\n    const observer = jasmine.createSpy('observer').and.callFake(() => {\n      subscription.unsubscribe()\n    })\n    const subscription = observable.subscribe(observer)\n\n    await waitNextMicrotask()\n\n    expect(observer).toHaveBeenCalledTimes(1)\n  })\n\n  it('allows to unsubscribe before the buffered data', async () => {\n    const observable = new BufferedObservable<string>(100)\n    observable.notify('first')\n\n    const observer = jasmine.createSpy('observer')\n    const subscription = observable.subscribe(observer)\n\n    subscription.unsubscribe()\n\n    await waitNextMicrotask()\n\n    expect(observer).not.toHaveBeenCalled()\n  })\n\n  it('allows to unsubscribe after the buffered data', async () => {\n    const observable = new BufferedObservable<string>(100)\n\n    const observer = jasmine.createSpy('observer')\n    const subscription = observable.subscribe(observer)\n\n    await waitNextMicrotask()\n\n    subscription.unsubscribe()\n\n    observable.notify('first')\n\n    expect(observer).not.toHaveBeenCalled()\n  })\n\n  it('calling unbuffer() removes buffered data', async () => {\n    const observable = new BufferedObservable<string>(2)\n    observable.notify('first')\n    observable.notify('second')\n\n    observable.unbuffer()\n    await waitNextMicrotask()\n\n    const observer = jasmine.createSpy('observer')\n    observable.subscribe(observer)\n    await waitNextMicrotask()\n\n    expect(observer).not.toHaveBeenCalled()\n  })\n\n  it('when calling unbuffer() right after subscription, buffered data should still be notified', async () => {\n    const observable = new BufferedObservable<string>(2)\n    observable.notify('first')\n    observable.notify('second')\n\n    const observer = jasmine.createSpy('observer')\n    observable.subscribe(observer)\n\n    observable.unbuffer()\n    await waitNextMicrotask()\n\n    expect(observer).toHaveBeenCalledTimes(2)\n    expect(observer).toHaveBeenCalledWith('first')\n    expect(observer).toHaveBeenCalledWith('second')\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/observable.ts",
    "content": "import { queueMicrotask } from './queueMicrotask'\n\nexport interface Subscription {\n  unsubscribe: () => void\n}\n\ntype Observer<T> = (data: T) => void\n\n// eslint-disable-next-line no-restricted-syntax\nexport class Observable<T> {\n  protected observers: Array<Observer<T>> = []\n  private onLastUnsubscribe?: () => void\n\n  constructor(private onFirstSubscribe?: (observable: Observable<T>) => (() => void) | void) {}\n\n  subscribe(observer: Observer<T>): Subscription {\n    this.addObserver(observer)\n    return {\n      unsubscribe: () => this.removeObserver(observer),\n    }\n  }\n\n  notify(data: T) {\n    this.observers.forEach((observer) => observer(data))\n  }\n\n  protected addObserver(observer: Observer<T>) {\n    this.observers.push(observer)\n    if (this.observers.length === 1 && this.onFirstSubscribe) {\n      this.onLastUnsubscribe = this.onFirstSubscribe(this) || undefined\n    }\n  }\n\n  protected removeObserver(observer: Observer<T>) {\n    this.observers = this.observers.filter((other) => observer !== other)\n    if (!this.observers.length && this.onLastUnsubscribe) {\n      this.onLastUnsubscribe()\n    }\n  }\n}\n\nexport function mergeObservables<T>(...observables: Array<Observable<T>>) {\n  return new Observable<T>((globalObservable) => {\n    const subscriptions: Subscription[] = observables.map((observable) =>\n      observable.subscribe((data) => globalObservable.notify(data))\n    )\n    return () => subscriptions.forEach((subscription) => subscription.unsubscribe())\n  })\n}\n\n// eslint-disable-next-line no-restricted-syntax\nexport class BufferedObservable<T> extends Observable<T> {\n  private buffer: T[] = []\n\n  constructor(private maxBufferSize: number) {\n    super()\n  }\n\n  notify(data: T) {\n    this.buffer.push(data)\n    if (this.buffer.length > this.maxBufferSize) {\n      this.buffer.shift()\n    }\n    super.notify(data)\n  }\n\n  subscribe(observer: Observer<T>): Subscription {\n    let closed = false\n\n    const subscription = {\n      unsubscribe: () => {\n        closed = true\n        this.removeObserver(observer)\n      },\n    }\n\n    queueMicrotask(() => {\n      for (const data of this.buffer) {\n        if (closed) {\n          return\n        }\n        observer(data)\n      }\n\n      if (!closed) {\n        this.addObserver(observer)\n      }\n    })\n\n    return subscription\n  }\n\n  /**\n   * Drop buffered data and don't buffer future data. This is to avoid leaking memory when it's not\n   * needed anymore. This can be seen as a performance optimization, and things will work probably\n   * even if this method isn't called, but still useful to clarify our intent and lowering our\n   * memory impact.\n   */\n  unbuffer() {\n    queueMicrotask(() => {\n      this.maxBufferSize = this.buffer.length = 0\n    })\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/queueMicrotask.spec.ts",
    "content": "import { startMockTelemetry, waitNextMicrotask } from '../../test'\nimport { queueMicrotask } from './queueMicrotask'\n\ndescribe('queueMicrotask', () => {\n  it('calls the callback in a microtask', async () => {\n    let called = false\n    queueMicrotask(() => {\n      called = true\n    })\n    expect(called).toBe(false)\n    await waitNextMicrotask()\n    expect(called).toBe(true)\n  })\n\n  it('monitors the callback', async () => {\n    const telemetry = startMockTelemetry()\n    queueMicrotask(() => {\n      throw new Error('test error')\n    })\n    await waitNextMicrotask()\n\n    expect(await telemetry.hasEvents()).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/queueMicrotask.ts",
    "content": "import { monitor } from './monitor'\nimport { globalObject } from './globalObject'\n\nexport function queueMicrotask(callback: () => void) {\n  // Intentionally avoid .bind(globalObject): in some environments (e.g. Selenium GeckoDriver's\n  // executeScript), globalThis is not a proper global object, so calling the bound function throws\n  // 'queueMicrotask called on an object that does not implement interface Window'. Calling it as an\n  // unbound method is fine, as the proper global object will be used implicitly.\n  // See https://github.com/mozilla/geckodriver/issues/1798\n  // eslint-disable-next-line @typescript-eslint/unbound-method\n  const nativeImplementation = globalObject.queueMicrotask\n\n  if (typeof nativeImplementation === 'function') {\n    nativeImplementation(monitor(callback))\n  } else {\n    // eslint-disable-next-line @typescript-eslint/no-floating-promises -- the callback is monitored, so it'll never throw\n    Promise.resolve().then(monitor(callback))\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/readBytesFromStream.spec.ts",
    "content": "import { readBytesFromStream } from './readBytesFromStream'\n\ndescribe('readBytesFromStream', () => {\n  const str = 'Lorem ipsum dolor sit amet.'\n  let stream: ReadableStream\n\n  beforeEach(() => {\n    stream = new ReadableStream({\n      start: (controller) => {\n        controller.enqueue(new TextEncoder().encode(str))\n        controller.close()\n      },\n    })\n  })\n\n  it('should read full stream', async () => {\n    const bytes = await readBytesFromStream(stream, {\n      collectStreamBody: true,\n    })\n\n    expect(bytes?.length).toBe(27)\n  })\n\n  it('should read full stream without body', async () => {\n    const bytes = await readBytesFromStream(stream, {\n      collectStreamBody: false,\n    })\n    expect(bytes).toBeUndefined()\n  })\n\n  it('should handle rejection error on read', async () => {\n    const stream = new ReadableStream({\n      start: (controller) => {\n        controller.error(new Error('foo'))\n      },\n    })\n\n    try {\n      await readBytesFromStream(stream, {\n        collectStreamBody: true,\n      })\n      fail('Should have thrown an error')\n    } catch (error) {\n      expect(error).toEqual(jasmine.any(Error))\n    }\n  })\n\n  it('should handle rejection error on cancel', async () => {\n    const stream = new ReadableStream({\n      start: (controller) => {\n        controller.enqueue(new TextEncoder().encode('f'))\n        controller.close()\n      },\n      cancel: () => Promise.reject(new Error('foo')),\n    })\n\n    const bytes = await readBytesFromStream(stream, {\n      collectStreamBody: true,\n    })\n    expect(bytes).toBeDefined()\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/readBytesFromStream.ts",
    "content": "import type { Uint8ArrayBuffer } from './utils/byteUtils'\nimport { concatBuffers } from './utils/byteUtils'\nimport { noop } from './utils/functionUtils'\n\ninterface Options {\n  // TODO(next-major): always collect stream body when `trackEarlyRequests` is removed, as we don't\n  // need to use this function to just wait for the end of the stream without collecting it\n  collectStreamBody?: boolean\n}\n\n/**\n * Read bytes from a ReadableStream until the end of the stream.\n * Returns the bytes if collectStreamBody is true, otherwise returns undefined.\n */\nexport async function readBytesFromStream(stream: ReadableStream<Uint8ArrayBuffer>, options: Options) {\n  const reader = stream.getReader()\n  const chunks: Uint8ArrayBuffer[] = []\n\n  while (true) {\n    const result = await reader.read()\n    if (result.done) {\n      break\n    }\n\n    if (options.collectStreamBody) {\n      chunks.push(result.value)\n    }\n  }\n\n  reader.cancel().catch(\n    // we don't care if cancel fails, but we still need to catch the error to avoid reporting it\n    // as an unhandled rejection\n    noop\n  )\n\n  return options.collectStreamBody ? concatBuffers(chunks) : undefined\n}\n"
  },
  {
    "path": "packages/core/src/tools/requestIdleCallback.spec.ts",
    "content": "import { mockClock, registerCleanupTask, type Clock } from '../../test'\nimport { MAX_TASK_TIME, requestIdleCallbackShim, requestIdleCallback } from './requestIdleCallback'\n\ndescribe('requestIdleCallback', () => {\n  it('fallbacks to the shim when requestIdleCallback is not available', () => {\n    const clock = mockClock()\n    removeGlobalRequestIdleCallback()\n\n    const spy = jasmine.createSpy<(deadline: IdleDeadline) => void>()\n\n    requestIdleCallback(spy)\n    expect(spy).not.toHaveBeenCalled()\n\n    clock.tick(0)\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n})\n\ndescribe('requestIdleCallbackShim', () => {\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  it('calls the callback asynchronously', () => {\n    const spy = jasmine.createSpy<(deadline: IdleDeadline) => void>()\n    requestIdleCallbackShim(spy)\n    expect(spy).not.toHaveBeenCalled()\n    clock.tick(0)\n    expect(spy).toHaveBeenCalledOnceWith({ didTimeout: false, timeRemaining: jasmine.any(Function) })\n  })\n\n  it('notifies the remaining time', () => {\n    const spy = jasmine.createSpy<(deadline: IdleDeadline) => void>()\n    requestIdleCallbackShim(spy)\n\n    clock.tick(10)\n    const deadline = spy.calls.mostRecent().args[0]\n\n    expect(deadline.timeRemaining()).toBe(MAX_TASK_TIME - 10)\n\n    clock.tick(10)\n    expect(deadline.timeRemaining()).toBe(MAX_TASK_TIME - 20)\n\n    clock.tick(MAX_TASK_TIME + 100)\n    expect(deadline.timeRemaining()).toBe(0)\n  })\n\n  it('cancels the callback when calling the stop function', () => {\n    const spy = jasmine.createSpy<(deadline: IdleDeadline) => void>()\n    const stop = requestIdleCallbackShim(spy)\n    stop()\n    clock.tick(0)\n    expect(spy).not.toHaveBeenCalled()\n  })\n})\n\nfunction removeGlobalRequestIdleCallback() {\n  const original = window.requestIdleCallback\n  ;(window as any).requestIdleCallback = undefined\n  registerCleanupTask(() => {\n    window.requestIdleCallback = original\n  })\n}\n"
  },
  {
    "path": "packages/core/src/tools/requestIdleCallback.ts",
    "content": "import { setTimeout, clearTimeout } from './timer'\nimport { monitor } from './monitor'\nimport { dateNow } from './utils/timeUtils'\n\n// This type is not yet supported in TS 3.8. Imported from the TS source until we upgrade the\n// minimum supported TS version.\n// https://github.com/microsoft/TypeScript/blob/13c374a868c926f6a907666a5599992c1351b773/src/lib/dom.generated.d.ts#L9513-L9516\nexport interface IdleDeadline {\n  readonly didTimeout: boolean\n  timeRemaining(): DOMHighResTimeStamp\n}\n\n/**\n * 'requestIdleCallback' with a shim.\n */\nexport function requestIdleCallback(callback: (deadline: IdleDeadline) => void, opts?: { timeout?: number }) {\n  // Note: check both 'requestIdleCallback' and 'cancelIdleCallback' existence because some polyfills only implement 'requestIdleCallback'.\n  if (window.requestIdleCallback && window.cancelIdleCallback) {\n    const id = window.requestIdleCallback(monitor(callback), opts)\n    return () => window.cancelIdleCallback(id)\n  }\n  return requestIdleCallbackShim(callback)\n}\n\nexport const MAX_TASK_TIME = 50\n\n/*\n * Shim from https://developer.chrome.com/blog/using-requestidlecallback#checking_for_requestidlecallback\n * Note: there is no simple way to support the \"timeout\" option, so we ignore it.\n */\nexport function requestIdleCallbackShim(callback: (deadline: IdleDeadline) => void) {\n  const start = dateNow()\n  const timeoutId = setTimeout(() => {\n    callback({\n      didTimeout: false,\n      timeRemaining: () => Math.max(0, MAX_TASK_TIME - (dateNow() - start)),\n    })\n  }, 0)\n  return () => clearTimeout(timeoutId)\n}\n"
  },
  {
    "path": "packages/core/src/tools/sendToExtension.ts",
    "content": "import { globalObject } from './globalObject'\n\ninterface BrowserWindow {\n  __ddBrowserSdkExtensionCallback?: (message: unknown) => void\n}\n\ntype ExtensionMessageType = 'logs' | 'record' | 'rum' | 'telemetry'\n\nexport function sendToExtension(type: ExtensionMessageType, payload: unknown) {\n  const callback = (globalObject as BrowserWindow).__ddBrowserSdkExtensionCallback\n  if (callback) {\n    callback({ type, payload })\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/serialisation/context.ts",
    "content": "export interface Context {\n  [x: string]: ContextValue\n}\n\nexport type ContextValue = string | number | boolean | Context | ContextArray | undefined | null\n\n/**\n * @hidden\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ContextArray extends Array<ContextValue> {}\n"
  },
  {
    "path": "packages/core/src/tools/serialisation/jsonStringify.spec.ts",
    "content": "import { jsonStringify } from './jsonStringify'\n\ndescribe('jsonStringify', () => {\n  afterEach(() => {\n    delete (Array.prototype as any).toJSON\n    delete (Object.prototype as any).toJSON\n  })\n\n  it('should jsonStringify a value with toJSON directly defined', () => {\n    const value = { 1: 'a' }\n    const expectedJson = JSON.stringify(value)\n\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    ;(value as any).toJSON = () => '42'\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    expect(JSON.stringify(value)).toEqual('\"42\"')\n  })\n\n  it('should jsonStringify a value with toJSON defined on its prototype', () => {\n    const value = createSampleClassInstance()\n    const expectedJson = JSON.stringify(value)\n\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    Object.getPrototypeOf(value).toJSON = () => '42'\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    expect(JSON.stringify(value)).toEqual('\"42\"')\n  })\n\n  it('should jsonStringify a value when toJSON is defined on Object prototype', () => {\n    const value = createSampleClassInstance()\n    const expectedJson = JSON.stringify(value)\n\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    ;(Object.prototype as any).toJSON = () => '42'\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    expect(JSON.stringify(value)).toEqual('\"42\"')\n  })\n\n  it('should jsonStringify a value when toJSON is defined on Array prototype', () => {\n    const value = createSampleClassInstance([1])\n    const expectedJson = JSON.stringify(value)\n\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    ;(Array.prototype as any).toJSON = () => '42'\n    expect(jsonStringify(value)).toEqual(expectedJson)\n    expect(JSON.stringify(value)).toEqual('{\"value\":\"42\"}')\n  })\n\n  it('should not restore the toJSON method on the wrong prototype', () => {\n    const value = [{ 1: 'a' }]\n    ;(Object.prototype as any).toJSON = () => '42'\n    jsonStringify(value)\n    expect(Object.prototype.hasOwnProperty.call(Array.prototype, 'toJSON')).toBe(false)\n  })\n\n  it('should jsonStringify edge cases', () => {\n    expect(jsonStringify(undefined)).toEqual(undefined)\n    expect(jsonStringify(null)).toEqual('null')\n    expect(jsonStringify(1)).toEqual('1')\n    expect(jsonStringify(true)).toEqual('true')\n  })\n\n  it('should not crash on serialization error', () => {\n    const circularReference: any = { otherData: 123 }\n    circularReference.myself = circularReference\n\n    expect(jsonStringify(circularReference)).toEqual('<error: unable to serialize object>')\n  })\n\n  function createSampleClassInstance(value: any = 'value') {\n    class Foo {\n      value = value\n    }\n    return new Foo()\n  }\n})\n"
  },
  {
    "path": "packages/core/src/tools/serialisation/jsonStringify.ts",
    "content": "import { noop } from '../utils/functionUtils'\n\n/**\n * Custom implementation of JSON.stringify that ignores some toJSON methods. We need to do that\n * because some sites badly override toJSON on certain objects. Removing all toJSON methods from\n * nested values would be too costly, so we just detach them from the root value, and native classes\n * used to build JSON values (Array and Object).\n *\n * Note: this still assumes that JSON.stringify is correct.\n */\nexport function jsonStringify(\n  value: unknown,\n  replacer?: Array<string | number>,\n  space?: string | number\n): string | undefined {\n  if (typeof value !== 'object' || value === null) {\n    return JSON.stringify(value)\n  }\n\n  // Note: The order matter here. We need to detach toJSON methods on parent classes before their\n  // subclasses.\n  const restoreObjectPrototypeToJson = detachToJsonMethod(Object.prototype)\n  const restoreArrayPrototypeToJson = detachToJsonMethod(Array.prototype)\n  const restoreValuePrototypeToJson = detachToJsonMethod(Object.getPrototypeOf(value))\n  const restoreValueToJson = detachToJsonMethod(value)\n\n  try {\n    return JSON.stringify(value, replacer, space)\n  } catch {\n    return '<error: unable to serialize object>'\n  } finally {\n    restoreObjectPrototypeToJson()\n    restoreArrayPrototypeToJson()\n    restoreValuePrototypeToJson()\n    restoreValueToJson()\n  }\n}\n\nexport interface ObjectWithToJsonMethod {\n  toJSON?: () => unknown\n}\n\nexport function detachToJsonMethod(value: object) {\n  const object = value as ObjectWithToJsonMethod\n  const objectToJson = object.toJSON\n  if (objectToJson) {\n    delete object.toJSON\n    return () => {\n      object.toJSON = objectToJson\n    }\n  }\n  return noop\n}\n"
  },
  {
    "path": "packages/core/src/tools/serialisation/sanitize.spec.ts",
    "content": "import { display } from '../display'\nimport { registerCleanupTask } from '../../../test'\nimport { sanitize } from './sanitize'\n\ndescribe('sanitize', () => {\n  it('should deep clone an object', () => {\n    const obj = { a: 1, b: { c: 42 } }\n    const clone = sanitize(obj)\n\n    expect(clone).toEqual(obj)\n    expect(clone).not.toBe(obj)\n  })\n\n  it('should survive an undefined input', () => {\n    const obj = undefined\n    expect(sanitize(obj)).toBe(undefined)\n  })\n\n  describe('simple types handling', () => {\n    it('should handle numbers', () => {\n      expect(sanitize(42)).toBe(42)\n    })\n\n    it('should handle strings', () => {\n      expect(sanitize('test')).toBe('test')\n    })\n\n    it('should handle functions', () => {\n      function testFunction() {\n        return true\n      }\n      expect(sanitize(testFunction)).toBe('[Function] testFunction')\n    })\n\n    it('should handle bigint', () => {\n      const bigIntFunction: (val: number) => any = (window as any).BigInt\n      if (typeof bigIntFunction === 'function') {\n        const bigint = bigIntFunction(2)\n        expect(sanitize(bigint)).toEqual('[BigInt] 2')\n      } else {\n        pending('BigInt is not supported on this browser')\n      }\n    })\n\n    it('shoud handle symbols', () => {\n      const symbolFunction: (description: string) => any = (window as any).Symbol\n      if (typeof symbolFunction === 'function') {\n        const symbol = symbolFunction('description')\n        expect(sanitize(symbol)).toMatch(/\\[Symbol\\] (?:Symbol\\()?description\\)?/)\n      } else {\n        pending('Symbol is not supported on this browser')\n      }\n    })\n  })\n\n  describe('objects handling', () => {\n    it('should serialize a Date as a string', () => {\n      const date = new Date('2022-12-12')\n      expect(sanitize(date)).toBe('2022-12-12T00:00:00.000Z')\n    })\n\n    it('should not traverse instrumented DOM nodes', () => {\n      const node = document.createElement('div')\n      ;(node as any).__hiddenProp = { value: 42 }\n\n      expect(sanitize(node)).toBe('[HTMLDivElement]')\n    })\n\n    it('should serialize events', (done) => {\n      const button = document.createElement('button')\n      document.body.appendChild(button)\n\n      registerCleanupTask(() => {\n        document.body.removeChild(button)\n      })\n\n      document.addEventListener(\n        'click',\n        (event) => {\n          expect(sanitize(event)).toEqual({\n            type: 'click',\n            isTrusted: false,\n            target: '[HTMLButtonElement]',\n            currentTarget: '[HTMLDocument]',\n          })\n          done()\n        },\n        { once: true }\n      )\n\n      button.click()\n    })\n\n    it('should serialize errors as JSON.stringify does', () => {\n      // Explicitely keep the previous behavior to avoid breaking changes in 4.x\n      // Browsers have different behaviors:\n      // Safari IOS12 adds parts of the stack\n      const error = new Error('My Error')\n      expect(sanitize(error)).toEqual({ ...error })\n    })\n\n    it('should keep additional properties from errors', () => {\n      // JSON.stringify does not serialize message/name/stack from an Error, but\n      // will serialize all other additional properties\n      const error = new Error('My Error')\n      ;(error as any).additionalProperty = { inner: 'test' }\n      expect(sanitize(error)).toEqual({ ...error })\n    })\n\n    it('should serialize objects like maps as a string', () => {\n      const map = new Map([\n        ['a', 13],\n        ['b', 37],\n      ])\n      expect(sanitize(map)).toBe('[Map]')\n    })\n\n    it('should survive when toStringTag throws', () => {\n      class CannotSerialize {\n        get [Symbol.toStringTag]() {\n          throw Error('Cannot serialize')\n        }\n      }\n      const cannotSerialize = new CannotSerialize()\n\n      expect(sanitize(cannotSerialize)).toEqual('[Unserializable]')\n    })\n\n    it('should handle objects with properties including null or undefined', () => {\n      const obj = { a: null, b: undefined }\n      expect(sanitize(obj)).toEqual({ a: null, b: undefined })\n    })\n\n    it('should handle regular expression', () => {\n      expect(sanitize(/[a-zA-Z0-9]+/g)).toEqual('[RegExp] /[a-zA-Z0-9]+/g')\n      expect(sanitize(new RegExp('[a-zA-Z0-9]+', 'g'))).toEqual('[RegExp] /[a-zA-Z0-9]+/g')\n    })\n  })\n\n  describe('arrays handling', () => {\n    // JSON.stringify ignores properties on arrays - We replicate the behavior\n    it('should ignore non-numerical properties on arrays', () => {\n      const arr = [1, 2, 3, 4]\n      ;(arr as any)['test'] = 'test'\n\n      expect(sanitize(arr)).toEqual([1, 2, 3, 4])\n    })\n\n    it('should handle arrays containing null or undefined', () => {\n      const arr = [null, undefined]\n      expect(sanitize(arr)).toEqual([null, undefined])\n    })\n  })\n\n  describe('circular references handling', () => {\n    it('should remove circular references', () => {\n      const obj: any = { a: 42 }\n      obj.self = obj\n\n      expect(sanitize(obj)).toEqual({ a: 42, self: '[Reference seen at $]' })\n    })\n\n    it('should remove deep circular references', () => {\n      const obj: any = {}\n      obj.toto = { inner: obj }\n\n      expect(sanitize(obj)).toEqual({ toto: { inner: '[Reference seen at $]' } })\n    })\n\n    it('should remove circular references between two branches in a tree', () => {\n      const a: any = {}\n      const b: any = {}\n      a.link = b\n      b.link = a\n      const obj = { a, b }\n\n      expect(sanitize(obj)).toEqual({ a: { link: '[Reference seen at $.b]' }, b: { link: '[Reference seen at $.a]' } })\n    })\n\n    it('should replace already visited objects with a json path', () => {\n      const inner = [1]\n      const obj = { a: inner, b: inner }\n\n      expect(sanitize(obj)).toEqual({ a: [1], b: '[Reference seen at $.a]' })\n    })\n\n    it('should create an understandable path for visited objects in arrays', () => {\n      const inner = { a: 42 }\n      const arr = [inner, inner]\n\n      expect(sanitize(arr)).toEqual([{ a: 42 }, '[Reference seen at $.0]'])\n    })\n  })\n\n  describe('toJson functions handling', () => {\n    it('should use toJSON functions if available on root object', () => {\n      const toJSON = jasmine.createSpy('toJSON', () => 'Specific').and.callThrough()\n      const obj = { a: 1, b: 2, toJSON }\n\n      expect(sanitize(obj)).toEqual('Specific')\n      expect(toJSON).toHaveBeenCalledTimes(1)\n    })\n\n    it('should use toJSON functions if available on nested objects', () => {\n      const toJSON = jasmine.createSpy('toJSON', () => ({ d: 4 })).and.callThrough()\n      const obj = { a: 1, b: 2, c: { a: 3, toJSON } }\n\n      expect(sanitize(obj)).toEqual({ a: 1, b: 2, c: { d: 4 } })\n      expect(toJSON).toHaveBeenCalledTimes(1)\n    })\n\n    it('should switch to the proper container type after applying toJSON', () => {\n      const obj = { a: 42, toJSON: () => [42] }\n      expect(sanitize(obj)).toEqual([42])\n    })\n\n    it('should not use toJSON methods added to arrays and objects prototypes', () => {\n      const toJSONArray = jasmine.createSpy('toJSONArray', () => 'Array').and.callThrough()\n      const toJSONObject = jasmine.createSpy('toJSONObject', () => 'Object').and.callThrough()\n      ;(Array.prototype as any).toJSON = toJSONArray\n      ;(Object.prototype as any).toJSON = toJSONObject\n\n      const arr = [{ a: 1, b: 2 }]\n      expect(sanitize(arr)).toEqual([{ a: 1, b: 2 }])\n      expect(toJSONArray).toHaveBeenCalledTimes(0)\n      expect(toJSONObject).toHaveBeenCalledTimes(0)\n      delete (Array.prototype as any).toJSON\n      delete (Object.prototype as any).toJSON\n    })\n\n    it('should survive a faulty toJSON', () => {\n      const faulty = () => {\n        throw new Error('')\n      }\n      const obj = { b: 42, toJSON: faulty }\n\n      // Since toJSON throws, sanitize falls back to serialize property by property\n      expect(sanitize(obj)).toEqual({ b: 42, toJSON: '[Function] faulty' })\n    })\n  })\n\n  describe('maxSize verification', () => {\n    it('should return nothing if a simple type is over max size ', () => {\n      const displaySpy = spyOn(display, 'warn')\n      const str = 'A not so long string...'\n\n      expect(sanitize(str, 5)).toBe(undefined)\n      expect(displaySpy).toHaveBeenCalled()\n    })\n\n    it('should stop cloning if an object container type reaches max size', () => {\n      const displaySpy = spyOn(display, 'warn')\n      const obj = { a: 'abc', b: 'def', c: 'ghi' } // Length of 31 after JSON.stringify\n      const sanitized = sanitize(obj, 21)\n      expect(sanitized).toEqual({ a: 'abc', b: 'def' }) // Length of 21 after JSON.stringify\n      expect(displaySpy).toHaveBeenCalled()\n    })\n\n    it('should stop cloning if an array container type reaches max size', () => {\n      const displaySpy = spyOn(display, 'warn')\n      const obj = [1, 2, 3, 4] // Length of 9 after JSON.stringify\n      const sanitized = sanitize(obj, 5)\n      expect(sanitized).toEqual([1, 2]) // Length of 5 after JSON.stringify\n      expect(displaySpy).toHaveBeenCalled()\n    })\n\n    it('should count size properly when array contains undefined values', () => {\n      // This is a special case: JSON.stringify([undefined]) => '[null]'\n      const displaySpy = spyOn(display, 'warn')\n      const arr = [undefined, undefined] // Length of 11 after JSON.stringify\n      const sanitized = sanitize(arr, 10)\n      expect(sanitized).toEqual([undefined])\n      expect(displaySpy).toHaveBeenCalled()\n    })\n\n    it('should count size properly when an object contains properties with undefined values', () => {\n      const displaySpy = spyOn(display, 'warn')\n      const obj = { a: undefined, b: 42 } // Length of 8 after JSON.stringify\n      const sanitized = sanitize(obj, 8)\n      expect(sanitized).toEqual({ a: undefined, b: 42 })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/serialisation/sanitize.ts",
    "content": "import { display } from '../display'\nimport { ONE_KIBI_BYTE } from '../utils/byteUtils'\nimport type { Context, ContextArray, ContextValue } from './context'\nimport type { ObjectWithToJsonMethod } from './jsonStringify'\nimport { detachToJsonMethod } from './jsonStringify'\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\ntype PrimitivesAndFunctions = string | number | boolean | undefined | null | symbol | bigint | Function\ntype ExtendedContextValue = PrimitivesAndFunctions | ExtendedContext | ExtendedContextArray\ninterface ExtendedContext {\n  [key: string]: ExtendedContextValue\n}\ntype ExtendedContextArray = ExtendedContextValue[]\n\ninterface ContainerElementToProcess {\n  source: ExtendedContextArray | ExtendedContext\n  target: ContextArray | Context\n  path: string\n}\n\ninterface SanitizedEvent extends Context {\n  type: string\n  isTrusted: boolean\n  currentTarget: string | null | undefined\n  target: string | null | undefined\n}\n\n// The maximum size of a single event is 256KiB. By default, we ensure that user-provided data\n// going through sanitize fits inside our events, while leaving room for other contexts, metadata, ...\nexport const SANITIZE_DEFAULT_MAX_CHARACTER_COUNT = 220 * ONE_KIBI_BYTE\n\n// Symbol for the root element of the JSONPath used for visited objects\nconst JSON_PATH_ROOT_ELEMENT = '$'\n\n// When serializing (using JSON.stringify) a key of an object, { key: 42 } gets wrapped in quotes as \"key\".\n// With the separator (:), we need to add 3 characters to the count.\nconst KEY_DECORATION_LENGTH = 3\n\n/**\n * Ensures user-provided data is 'safe' for the SDK\n * - Deep clones data\n * - Removes cyclic references\n * - Transforms unserializable types to a string representation\n *\n * LIMITATIONS:\n * - Size is in characters, not byte count (may differ according to character encoding)\n * - Size does not take into account indentation that can be applied to JSON.stringify\n * - Non-numerical properties of Arrays are ignored. Same behavior as JSON.stringify\n *\n * @param source              - User-provided data meant to be serialized using JSON.stringify\n * @param maxCharacterCount   - Maximum number of characters allowed in serialized form\n */\nexport function sanitize(source: string, maxCharacterCount?: number): string | undefined\nexport function sanitize(source: Context, maxCharacterCount?: number): Context\nexport function sanitize(source: unknown, maxCharacterCount?: number): ContextValue\nexport function sanitize(source: unknown, maxCharacterCount = SANITIZE_DEFAULT_MAX_CHARACTER_COUNT) {\n  // Unbind any toJSON function we may have on [] or {} prototypes\n  const restoreObjectPrototypeToJson = detachToJsonMethod(Object.prototype)\n  const restoreArrayPrototypeToJson = detachToJsonMethod(Array.prototype)\n\n  // Initial call to sanitizeProcessor - will populate containerQueue if source is an Array or a plain Object\n  const containerQueue: ContainerElementToProcess[] = []\n  const visitedObjectsWithPath = new WeakMap<object, string>()\n  const sanitizedData = sanitizeProcessor(\n    source as ExtendedContextValue,\n    JSON_PATH_ROOT_ELEMENT,\n    undefined,\n    containerQueue,\n    visitedObjectsWithPath\n  )\n  const serializedSanitizedData = JSON.stringify(sanitizedData)\n  let accumulatedCharacterCount = serializedSanitizedData ? serializedSanitizedData.length : 0\n\n  if (accumulatedCharacterCount > maxCharacterCount) {\n    warnOverCharacterLimit(maxCharacterCount, 'discarded', source)\n    return undefined\n  }\n\n  while (containerQueue.length > 0 && accumulatedCharacterCount < maxCharacterCount) {\n    const containerToProcess = containerQueue.shift()!\n    let separatorLength = 0 // 0 for the first element, 1 for subsequent elements\n\n    // Arrays and Objects have to be handled distinctly to ensure\n    // we do not pick up non-numerical properties from Arrays\n    if (Array.isArray(containerToProcess.source)) {\n      for (let key = 0; key < containerToProcess.source.length; key++) {\n        const targetData = sanitizeProcessor(\n          containerToProcess.source[key],\n          containerToProcess.path,\n          key,\n          containerQueue,\n          visitedObjectsWithPath\n        )\n\n        if (targetData !== undefined) {\n          accumulatedCharacterCount += JSON.stringify(targetData).length\n        } else {\n          // When an element of an Array (targetData) is undefined, it is serialized as null:\n          // JSON.stringify([undefined]) => '[null]' - This accounts for 4 characters\n          accumulatedCharacterCount += 4\n        }\n        accumulatedCharacterCount += separatorLength\n        separatorLength = 1\n        if (accumulatedCharacterCount > maxCharacterCount) {\n          warnOverCharacterLimit(maxCharacterCount, 'truncated', source)\n          break\n        }\n        ;(containerToProcess.target as ContextArray)[key] = targetData\n      }\n    } else {\n      for (const key in containerToProcess.source) {\n        if (Object.prototype.hasOwnProperty.call(containerToProcess.source, key)) {\n          const targetData = sanitizeProcessor(\n            containerToProcess.source[key],\n            containerToProcess.path,\n            key,\n            containerQueue,\n            visitedObjectsWithPath\n          )\n          // When a property of an object has an undefined value, it will be dropped during serialization:\n          // JSON.stringify({a:undefined}) => '{}'\n          if (targetData !== undefined) {\n            accumulatedCharacterCount +=\n              JSON.stringify(targetData).length + separatorLength + key.length + KEY_DECORATION_LENGTH\n            separatorLength = 1\n          }\n          if (accumulatedCharacterCount > maxCharacterCount) {\n            warnOverCharacterLimit(maxCharacterCount, 'truncated', source)\n            break\n          }\n          ;(containerToProcess.target as Context)[key] = targetData\n        }\n      }\n    }\n  }\n\n  // Rebind detached toJSON functions\n  restoreObjectPrototypeToJson()\n  restoreArrayPrototypeToJson()\n\n  return sanitizedData\n}\n\n/**\n * Internal function to factorize the process common to the\n * initial call to sanitize, and iterations for Arrays and Objects\n *\n */\nfunction sanitizeProcessor(\n  source: ExtendedContextValue,\n  parentPath: string,\n  key: string | number | undefined,\n  queue: ContainerElementToProcess[],\n  visitedObjectsWithPath: WeakMap<object, string>\n) {\n  // Start by handling toJSON, as we want to sanitize its output\n  const sourceToSanitize = tryToApplyToJSON(source)\n\n  if (!sourceToSanitize || typeof sourceToSanitize !== 'object') {\n    return sanitizePrimitivesAndFunctions(sourceToSanitize)\n  }\n\n  const sanitizedSource = sanitizeObjects(sourceToSanitize)\n  if (sanitizedSource !== '[Object]' && sanitizedSource !== '[Array]' && sanitizedSource !== '[Error]') {\n    return sanitizedSource\n  }\n\n  // Handle potential cyclic references\n  // We need to use source as sourceToSanitize could be a reference to a new object\n  // At this stage, we know the source is an object type\n  const sourceAsObject = source as object\n  if (visitedObjectsWithPath.has(sourceAsObject)) {\n    return `[Reference seen at ${visitedObjectsWithPath.get(sourceAsObject)!}]`\n  }\n\n  // Add processed source to queue\n  const currentPath = key !== undefined ? `${parentPath}.${key}` : parentPath\n  const target = Array.isArray(sourceToSanitize) ? ([] as ContextArray) : ({} as Context)\n  visitedObjectsWithPath.set(sourceAsObject, currentPath)\n  queue.push({ source: sourceToSanitize, target, path: currentPath })\n\n  return target\n}\n\n/**\n * Handles sanitization of simple, non-object types\n *\n */\nfunction sanitizePrimitivesAndFunctions(value: PrimitivesAndFunctions) {\n  // BigInt cannot be serialized by JSON.stringify(), convert it to a string representation\n  if (typeof value === 'bigint') {\n    return `[BigInt] ${value.toString()}`\n  }\n  // Functions cannot be serialized by JSON.stringify(). Moreover, if a faulty toJSON is present, it needs to be converted\n  // so it won't prevent stringify from serializing later\n  if (typeof value === 'function') {\n    return `[Function] ${value.name || 'unknown'}`\n  }\n  // JSON.stringify() does not serialize symbols.\n  if (typeof value === 'symbol') {\n    // symbol.description is part of ES2019+\n    type symbolWithDescription = symbol & { description: string }\n    return `[Symbol] ${(value as symbolWithDescription).description || value.toString()}`\n  }\n\n  return value\n}\n\n/**\n * Handles sanitization of object types\n *\n * LIMITATIONS\n * - If a class defines a toStringTag Symbol, it will fall in the catch-all method and prevent enumeration of properties.\n * To avoid this, a toJSON method can be defined.\n */\nfunction sanitizeObjects(value: object): string | SanitizedEvent {\n  try {\n    if (value instanceof Event) {\n      return sanitizeEvent(value)\n    }\n\n    if (value instanceof RegExp) {\n      return `[RegExp] ${value.toString()}`\n    }\n\n    // Handle all remaining object types in a generic way\n    const result = Object.prototype.toString.call(value)\n    const match = result.match(/\\[object (.*)\\]/)\n    if (match && match[1]) {\n      return `[${match[1]}]`\n    }\n  } catch {\n    // If the previous serialization attempts failed, and we cannot convert using\n    // Object.prototype.toString, declare the value unserializable\n  }\n  return '[Unserializable]'\n}\n\nfunction sanitizeEvent(event: Event): SanitizedEvent {\n  return {\n    type: event.type,\n    isTrusted: event.isTrusted,\n    currentTarget: event.currentTarget ? (sanitizeObjects(event.currentTarget) as string) : null,\n    target: event.target ? (sanitizeObjects(event.target) as string) : null,\n  }\n}\n\n/**\n * Checks if a toJSON function exists and tries to execute it\n *\n */\nfunction tryToApplyToJSON(value: ExtendedContextValue) {\n  const object = value as ObjectWithToJsonMethod\n  if (object && typeof object.toJSON === 'function') {\n    try {\n      return object.toJSON() as ExtendedContextValue\n    } catch {\n      // If toJSON fails, we continue by trying to serialize the value manually\n    }\n  }\n\n  return value\n}\n\n/**\n * Helper function to display the warning when the accumulated character count is over the limit\n */\nfunction warnOverCharacterLimit(maxCharacterCount: number, changeType: 'discarded' | 'truncated', source: unknown) {\n  display.warn(\n    `The data provided has been ${changeType} as it is over the limit of ${maxCharacterCount} characters:`,\n    source\n  )\n}\n"
  },
  {
    "path": "packages/core/src/tools/stackTrace/capturedExceptions.specHelper.ts",
    "content": "export const OPERA_25 = {\n  message: \"Cannot read property 'undef' of null\",\n  name: 'TypeError',\n  stack: `TypeError: Cannot read property 'undef' of null\n    at http://path/to/file.js:47:22\n    at foo (http://path/to/file.js:52:15)\n    at bar (http://path/to/file.js:108:168)`,\n}\n\nexport const CHROME_15 = {\n  arguments: ['undef'],\n  message: \"Object #<Object> has no method 'undef'\",\n  stack: `TypeError: Object #<Object> has no method 'undef'\n    at bar (http://path/to/file.js:13:17)\n    at bar (http://path/to/file.js:16:5)\n    at foo (http://path/to/file.js:20:5)\n    at http://path/to/file.js:24:4`,\n}\n\nexport const CHROME_36 = {\n  message: 'Default error',\n  name: 'Error',\n  stack: `Error: Default error\n    at dumpExceptionError (http://localhost:8080/file.js:41:27)\n    at HTMLButtonElement.onclick (http://localhost:8080/file.js:107:146)\n    at I.e.fn.(anonymous function) [as index] (http://localhost:8080/file.js:10:3651)`,\n}\n\n// can be generated when Webpack is built with { devtool: eval }\nexport const CHROME_XX_WEBPACK = {\n  message: \"Cannot read property 'error' of undefined\",\n  name: 'TypeError',\n  stack: `TypeError: Cannot read property 'error' of undefined\n   at TESTTESTTEST.eval(webpack:///./src/components/test/test.jsx?:295:108)\n   at TESTTESTTEST.render(webpack:///./src/components/test/test.jsx?:272:32)\n   at TESTTESTTEST.tryRender(webpack:///./~/react-transform-catch-errors/lib/index.js?:34:31)\n   at TESTTESTTEST.proxiedMethod(webpack:///./~/react-proxy/modules/createPrototypeProxy.js?:44:30)`,\n}\n\nexport const ELECTRON = {\n  message: 'Default error',\n  name: 'Error',\n  stack: `Error: Default error\n    at dumpExceptionError (electron://-/file.js:41:27)\n    at HTMLButtonElement.onclick (electron://-/file.js:107:146)\n    at I.e.fn.(anonymous function) [as index] (electron://-/file.js:10:3651)`,\n}\n\nexport const FIREFOX_3 = {\n  fileName: 'http://127.0.0.1:8000/js/stacktrace.js',\n  lineNumber: 44,\n  message: 'this.undef is not a function',\n  name: 'TypeError',\n  stack: `()@http://127.0.0.1:8000/js/stacktrace.js:44\n(null)@http://127.0.0.1:8000/js/stacktrace.js:31\nprintStackTrace()@http://127.0.0.1:8000/js/stacktrace.js:18\nbar(1)@http://127.0.0.1:8000/js/file.js:13\nbar(2)@http://127.0.0.1:8000/js/file.js:16\nfoo()@http://127.0.0.1:8000/js/file.js:20\n@http://127.0.0.1:8000/js/file.js:24\n`,\n}\n\nexport const FIREFOX_7 = {\n  fileName: 'file:///G:/js/stacktrace.js',\n  lineNumber: 44,\n  stack: `()@file:///G:/js/stacktrace.js:44\n(null)@file:///G:/js/stacktrace.js:31\nprintStackTrace()@file:///G:/js/stacktrace.js:18\nbar(1)@file:///G:/js/file.js:13\nbar(2)@file:///G:/js/file.js:16\nfoo()@file:///G:/js/file.js:20\n@file:///G:/js/file.js:24\n`,\n}\n\nexport const FIREFOX_14 = {\n  fileName: 'http://path/to/file.js',\n  lineNumber: 48,\n  message: 'x is null',\n  stack: `@http://path/to/file.js:48\ndumpException3@http://path/to/file.js:52\nonclick@http://path/to/file.js:1\n`,\n}\n\nexport const FIREFOX_31 = {\n  columnNumber: 12,\n  fileName: 'http://path/to/file.js',\n  lineNumber: 41,\n  message: 'Default error',\n  name: 'Error',\n  stack: `foo@http://path/to/file.js:41:13\nbar@http://path/to/file.js:1:1\n.plugin/e.fn[c]/<@http://path/to/file.js:1:1\n`,\n}\n\nexport const FIREFOX_43_EVAL = {\n  columnNumber: 30,\n  fileName: 'http://localhost:8080/file.js line 25 > eval line 2 > eval',\n  lineNumber: 1,\n  message: 'message string',\n  stack: `baz@http://localhost:8080/file.js line 26 > eval line 2 > eval:1:30\nfoo@http://localhost:8080/file.js line 26 > eval:2:96\n@http://localhost:8080/file.js line 26 > eval:4:18\nspeak@http://localhost:8080/file.js:26:17\n@http://localhost:8080/file.js:33:9`,\n}\n\n// Internal errors sometimes thrown by Firefox\n// More here: https://developer.mozilla.org/en-US/docs/Mozilla/Errors\n//\n// Note that such errors are instanceof \"Exception\", not \"Error\"\nexport const FIREFOX_44_NS_EXCEPTION = {\n  columnNumber: 0,\n  fileName: 'http://path/to/file.js',\n  lineNumber: 703,\n  message: '',\n  name: 'NS_ERROR_FAILURE',\n  result: 2147500037,\n  stack: `[2]</Bar.prototype._baz/</<@http://path/to/file.js:703:28\nApp.prototype.foo@file:///path/to/file.js:15:2\nbar@file:///path/to/file.js:20:3\n@file:///path/to/index.html:23:1\n`,\n}\n\nexport const FIREFOX_50_RESOURCE_URL = {\n  columnNumber: 16,\n  fileName: 'resource://path/data/content/bundle.js',\n  lineNumber: 5529,\n  message: 'this.props.raw[this.state.dataSource].rows is undefined',\n  name: 'TypeError',\n  stack: `render@resource://path/data/content/bundle.js:5529:16\ndispatchEvent@resource://path/data/content/vendor.bundle.js:18:23028\nwrapped@resource://path/data/content/bundle.js:7270:25`,\n}\n\nexport const SAFARI_6 = {\n  line: 48,\n  message: \"'null' is not an object (evaluating 'x.undef')\",\n  sourceURL: 'http://path/to/file.js',\n  stack: `@http://path/to/file.js:48\ndumpException3@http://path/to/file.js:52\nonclick@http://path/to/file.js:82\n[native code]`,\n}\n\nexport const SAFARI_7 = {\n  line: 47,\n  message: \"'null' is not an object (evaluating 'x.undef')\",\n  name: 'TypeError',\n  sourceURL: 'http://path/to/file.js',\n  stack: `http://path/to/file.js:48:22\nfoo@http://path/to/file.js:52:15\nbar@http://path/to/file.js:108:107`,\n}\n\nexport const SAFARI_8 = {\n  column: 22,\n  line: 47,\n  message: \"null is not an object (evaluating 'x.undef')\",\n  name: 'TypeError',\n  sourceURL: 'http://path/to/file.js',\n  stack: `http://path/to/file.js:47:22\nfoo@http://path/to/file.js:52:15\nbar@http://path/to/file.js:108:23`,\n}\n\nexport const SAFARI_8_EVAL = {\n  column: 18,\n  line: 1,\n  message: \"Can't find variable: getExceptionProps\",\n  name: 'ReferenceError',\n  stack: `eval code\neval@[native code]\nfoo@http://path/to/file.js:58:21\nbar@http://path/to/file.js:109:91`,\n}\n\nexport const IE_9 = {\n  description: \"Unable to get property 'undef' of undefined or null reference\",\n  message: \"Unable to get property 'undef' of undefined or null reference\",\n}\n\nexport const IE_10 = {\n  description: \"Unable to get property 'undef' of undefined or null reference\",\n  message: \"Unable to get property 'undef' of undefined or null reference\",\n  number: -2146823281, // eslint-disable-line id-denylist\n  stack: `TypeError: Unable to get property 'undef' of undefined or null reference\n   at Anonymous function (http://path/to/file.js:48:13)\n   at foo (http://path/to/file.js:46:9)\n   at bar (http://path/to/file.js:82:1)`,\n}\n\nexport const IE_11 = {\n  description: \"Unable to get property 'undef' of undefined or null reference\",\n  message: \"Unable to get property 'undef' of undefined or null reference\",\n  name: 'TypeError',\n  number: -2146823281, // eslint-disable-line id-denylist\n  stack: `TypeError: Unable to get property 'undef' of undefined or null reference\n   at Anonymous function (http://path/to/file.js:47:21)\n   at foo (http://path/to/file.js:45:13)\n   at bar (http://path/to/file.js:108:1)`,\n}\n\nexport const IE_11_EVAL = {\n  description: \"'getExceptionProps' is undefined\",\n  message: \"'getExceptionProps' is undefined\",\n  name: 'ReferenceError',\n  number: -2146823279, // eslint-disable-line id-denylist\n  stack: `ReferenceError: 'getExceptionProps' is undefined\n   at eval code (eval code:1:1)\n   at foo (http://path/to/file.js:58:17)\n   at bar (http://path/to/file.js:109:1)`,\n}\n\nexport const CHROME_48_BLOB = {\n  message: 'Error: test',\n  name: 'Error',\n  stack: `Error: test\n    at Error (native)\n    at s (blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379:31:29146)\n    at Object.d [as add] (blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379:31:30039)\n    at blob:http%3A//localhost%3A8080/d4eefe0f-361a-4682-b217-76587d9f712a:15:10978\n    at blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379:1:6911\n    at n.fire (blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379:7:3019)\n    at n.handle (blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379:7:2863)`,\n}\n\nexport const CHROME_48_EVAL = {\n  message: 'message string',\n  name: 'Error',\n  stack: `Error: message string\nat baz (eval at foo (eval at speak (http://localhost:8080/file.js:21:17)), <anonymous>:1:30)\nat foo (eval at speak (http://localhost:8080/file.js:21:17), <anonymous>:2:96)\nat eval (eval at speak (http://localhost:8080/file.js:21:17), <anonymous>:4:18)\nat Object.speak (http://localhost:8080/file.js:21:17)\nat http://localhost:8080/file.js:31:13\\n`,\n}\n\nexport const CHROME_111_SNIPPET = {\n  message: 'message string',\n  name: 'Error',\n  stack: `Error: message string\nat snippet:///snippet_file:1:13`,\n}\n\nexport const CHROME_141_HTML_ANONYMOUS_LISTENER = {\n  message: 'message string',\n  name: 'Error',\n  stack: `Error: message string\nat HTMLButtonElement.<anonymous> @  http://path/to/file.js:1:4287`,\n}\n\nexport const PHANTOMJS_1_19 = {\n  stack: `Error: foo\n    at file:///path/to/file.js:878\n    at foo (http://path/to/file.js:4283)\n    at http://path/to/file.js:4287`,\n}\n\nexport const ANDROID_REACT_NATIVE = {\n  message: 'Error: test',\n  name: 'Error',\n  stack: `Error: test\n  at render(/home/username/sample-workspace/sampleapp.collect.react/src/components/GpsMonitorScene.js:78:24)\n  at _renderValidatedComponentWithoutOwnerOrContext(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:1050:29)\n  at _renderValidatedComponent(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:1075:15)\n  at renderedElement(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:484:29)\n  at _currentElement(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:346:40)\n  at child(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactReconciler.js:68:25)\n  at children(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactMultiChild.js:264:10)\n  at this(/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/native/ReactNativeBaseComponent.js:74:41)\\n`,\n}\n\nexport const ANDROID_REACT_NATIVE_PROD = {\n  message: 'Error: test',\n  name: 'Error',\n  stack: `value@index.android.bundle:12:1917\nonPress@index.android.bundle:12:2336\ntouchableHandlePress@index.android.bundle:258:1497\n[native code]\n_performSideEffectsForTransition@index.android.bundle:252:8508\n[native code]\n_receiveSignal@index.android.bundle:252:7291\n[native code]\ntouchableHandleResponderRelease@index.android.bundle:252:4735\n[native code]\nu@index.android.bundle:79:142\ninvokeGuardedCallback@index.android.bundle:79:459\ninvokeGuardedCallbackAndCatchFirstError@index.android.bundle:79:580\nc@index.android.bundle:95:365\na@index.android.bundle:95:567\nv@index.android.bundle:146:501\ng@index.android.bundle:146:604\nforEach@[native code]\ni@index.android.bundle:149:80\nprocessEventQueue@index.android.bundle:146:1432\ns@index.android.bundle:157:88\nhandleTopLevel@index.android.bundle:157:174\nindex.android.bundle:156:572\na@index.android.bundle:93:276\nc@index.android.bundle:93:60\nperform@index.android.bundle:177:596\nbatchedUpdates@index.android.bundle:188:464\ni@index.android.bundle:176:358\ni@index.android.bundle:93:90\nu@index.android.bundle:93:150\n_receiveRootNodeIDEvent@index.android.bundle:156:544\nreceiveTouches@index.android.bundle:156:918\nvalue@index.android.bundle:29:3016\nindex.android.bundle:29:955\nvalue@index.android.bundle:29:2417\nvalue@index.android.bundle:29:927\n[native code]`,\n}\n\nexport const IOS_CAPACITOR = {\n  stack: `capacitor://localhost/media/dist/bundle.js:34:99546\nr@capacitor://localhost/media/dist/bundle.js:34:47950`,\n}\n"
  },
  {
    "path": "packages/core/src/tools/stackTrace/computeStackTrace.spec.ts",
    "content": "import { isSafari } from '../utils/browserDetection'\nimport * as CapturedExceptions from './capturedExceptions.specHelper'\nimport { CHROME_141_HTML_ANONYMOUS_LISTENER } from './capturedExceptions.specHelper'\nimport { computeStackTrace } from './computeStackTrace'\n\ndescribe('computeStackTrace', () => {\n  it('should not remove anonymous functions from the stack', () => {\n    // mock up an error object with a stack trace that includes both\n    // named functions and anonymous functions\n    const stack = `\n  Error:\n    at new <anonymous> (http://example.com/js/test.js:63:1)\n    at namedFunc0 (http://example.com/js/script.js:10:2)\n    at http://example.com/js/test.js:65:10\n    at namedFunc2 (http://example.com/js/script.js:20:5)\n    at http://example.com/js/test.js:67:5\n    at namedFunc4 (http://example.com/js/script.js:100001:10002)`\n    const mockErr: any = { stack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack[0].func).toEqual('new <anonymous>')\n    expect(stackFrames.stack[0].url).toEqual('http://example.com/js/test.js')\n    expect(stackFrames.stack[0].line).toEqual(63)\n    expect(stackFrames.stack[0].column).toEqual(1)\n    expect(stackFrames.stack[1].func).toEqual('namedFunc0')\n    expect(stackFrames.stack[1].url).toEqual('http://example.com/js/script.js')\n    expect(stackFrames.stack[1].line).toEqual(10)\n    expect(stackFrames.stack[1].column).toEqual(2)\n\n    expect(stackFrames.stack[2].func).toEqual('?')\n    expect(stackFrames.stack[2].url).toEqual('http://example.com/js/test.js')\n    expect(stackFrames.stack[2].line).toEqual(65)\n    expect(stackFrames.stack[2].column).toEqual(10)\n\n    expect(stackFrames.stack[3].func).toEqual('namedFunc2')\n    expect(stackFrames.stack[3].url).toEqual('http://example.com/js/script.js')\n    expect(stackFrames.stack[3].line).toEqual(20)\n    expect(stackFrames.stack[3].column).toEqual(5)\n\n    expect(stackFrames.stack[4].func).toEqual('?')\n    expect(stackFrames.stack[4].url).toEqual('http://example.com/js/test.js')\n    expect(stackFrames.stack[4].line).toEqual(67)\n    expect(stackFrames.stack[4].column).toEqual(5)\n\n    expect(stackFrames.stack[5].func).toEqual('namedFunc4')\n    expect(stackFrames.stack[5].url).toEqual('http://example.com/js/script.js')\n    expect(stackFrames.stack[5].line).toEqual(100001)\n    expect(stackFrames.stack[5].column).toEqual(10002)\n  })\n\n  it('should handle eval/anonymous strings in Chrome 46', () => {\n    const stack = `\nReferenceError: baz is not defined\n   at bar (http://example.com/js/test.js:19:7)\n   at foo (http://example.com/js/test.js:23:7)\n   at eval (eval at <anonymous> (http://example.com/js/test.js:26:5)).toEqual(<anonymous>:1:26)\n`\n\n    const mockErr: any = { stack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack[0].func).toEqual('bar')\n    expect(stackFrames.stack[0].url).toEqual('http://example.com/js/test.js')\n    expect(stackFrames.stack[0].line).toEqual(19)\n    expect(stackFrames.stack[0].column).toEqual(7)\n\n    expect(stackFrames.stack[1].func).toEqual('foo')\n    expect(stackFrames.stack[1].url).toEqual('http://example.com/js/test.js')\n    expect(stackFrames.stack[1].line).toEqual(23)\n    expect(stackFrames.stack[1].column).toEqual(7)\n\n    expect(stackFrames.stack[2].func).toEqual('eval')\n    // TODO: fix nested evals\n    expect(stackFrames.stack[2].url).toEqual('http://example.com/js/test.js')\n    expect(stackFrames.stack[2].line).toEqual(26)\n    expect(stackFrames.stack[2].column).toEqual(5)\n  })\n\n  const stackStr = `\nError: foo\n    at <anonymous>:2:11\n    at Object.InjectedScript._evaluateOn (<anonymous>:904:140)\n    at Object.InjectedScript._evaluateAndWrap (<anonymous>:837:34)\n    at Object.InjectedScript.evaluate (<anonymous>:693:21)`\n\n  it('should handle a native error object', () => {\n    const ex = new Error('test')\n    const stack = computeStackTrace(ex)\n    expect(stack.name).toEqual('Error')\n    expect(stack.message).toEqual('test')\n  })\n\n  it('should handle a native error object stack from Chrome', () => {\n    const mockErr = { message: 'foo', name: 'Error', stack: stackStr }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack[0].url).toEqual('<anonymous>')\n  })\n\n  it('should handle edge case values', () => {\n    expect(computeStackTrace({ message: { foo: 'bar' } }).message).toBeUndefined()\n    expect(computeStackTrace({ name: { foo: 'bar' } }).name).toBeUndefined()\n    expect(computeStackTrace({ message: { foo: 'bar' }, stack: stackStr }).message).toBeUndefined()\n    expect(computeStackTrace({ name: { foo: 'bar' }, stack: stackStr }).name).toBeUndefined()\n    expect(computeStackTrace(2).message).toBeUndefined()\n    expect(computeStackTrace({ foo: 'bar' }).message).toBeUndefined()\n    expect(computeStackTrace(undefined).message).toBeUndefined()\n    expect(computeStackTrace(null).message).toBeUndefined()\n  })\n\n  it('should get the order of functions called right', () => {\n    if (isSafari()) {\n      pending()\n    }\n    function foo() {\n      return bar()\n    }\n\n    function bar() {\n      return baz()\n    }\n\n    function baz() {\n      return computeStackTrace(new Error())\n    }\n\n    const trace = foo()\n    const expected = ['baz', 'bar', 'foo']\n\n    for (let i = 0; i <= 2; i += 1) {\n      expect(trace.stack[i].func).toEqual(expected[i])\n    }\n  })\n\n  it('should parse Safari 6 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.SAFARI_6)\n\n    expect(stackFrames.stack.length).toEqual(4)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 48,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'dumpException3',\n      line: 52,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'onclick',\n      line: 82,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: undefined,\n      url: '[native code]',\n    })\n  })\n\n  it('should parse Safari 7 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.SAFARI_7)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 22, func: '?', line: 48, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 15, func: 'foo', line: 52, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 107,\n      func: 'bar',\n      line: 108,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse Safari 8 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.SAFARI_8)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 22, func: '?', line: 47, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 15, func: 'foo', line: 52, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 23,\n      func: 'bar',\n      line: 108,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse Safari 8 eval error', () => {\n    // TODO: Take into account the line and column properties\n    //  on the error object and use them for the first stack trace.\n    const stackFrames = computeStackTrace(CapturedExceptions.SAFARI_8_EVAL)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'eval',\n      line: undefined,\n      url: '[native code]',\n    })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 21, func: 'foo', line: 58, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 91,\n      func: 'bar',\n      line: 109,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse Firefox 3 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_3)\n\n    expect(stackFrames.stack.length).toEqual(7)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 44,\n      url: 'http://127.0.0.1:8000/js/stacktrace.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: ['null'],\n      column: undefined,\n      func: '?',\n      line: 31,\n      url: 'http://127.0.0.1:8000/js/stacktrace.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'printStackTrace',\n      line: 18,\n      url: 'http://127.0.0.1:8000/js/stacktrace.js',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: ['1'],\n      column: undefined,\n      func: 'bar',\n      line: 13,\n      url: 'http://127.0.0.1:8000/js/file.js',\n    })\n    expect(stackFrames.stack[4]).toEqual({\n      args: ['2'],\n      column: undefined,\n      func: 'bar',\n      line: 16,\n      url: 'http://127.0.0.1:8000/js/file.js',\n    })\n    expect(stackFrames.stack[5]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'foo',\n      line: 20,\n      url: 'http://127.0.0.1:8000/js/file.js',\n    })\n    expect(stackFrames.stack[6]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 24,\n      url: 'http://127.0.0.1:8000/js/file.js',\n    })\n  })\n\n  it('should parse Firefox 7 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_7)\n\n    expect(stackFrames.stack.length).toEqual(7)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 44,\n      url: 'file:///G:/js/stacktrace.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: ['null'],\n      column: undefined,\n      func: '?',\n      line: 31,\n      url: 'file:///G:/js/stacktrace.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'printStackTrace',\n      line: 18,\n      url: 'file:///G:/js/stacktrace.js',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: ['1'],\n      column: undefined,\n      func: 'bar',\n      line: 13,\n      url: 'file:///G:/js/file.js',\n    })\n    expect(stackFrames.stack[4]).toEqual({\n      args: ['2'],\n      column: undefined,\n      func: 'bar',\n      line: 16,\n      url: 'file:///G:/js/file.js',\n    })\n    expect(stackFrames.stack[5]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'foo',\n      line: 20,\n      url: 'file:///G:/js/file.js',\n    })\n    expect(stackFrames.stack[6]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 24,\n      url: 'file:///G:/js/file.js',\n    })\n  })\n\n  it('should parse Firefox 14 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_14)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 48,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'dumpException3',\n      line: 52,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'onclick',\n      line: 1,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse Firefox 31 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_31)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 13, func: 'foo', line: 41, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 1, func: 'bar', line: 1, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 1,\n      func: '.plugin/e.fn[c]/<',\n      line: 1,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse Firefox 44 ns exceptions', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_44_NS_EXCEPTION)\n\n    expect(stackFrames.stack.length).toEqual(4)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 28,\n      func: '[2]</Bar.prototype._baz/</<',\n      line: 703,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 2,\n      func: 'App.prototype.foo',\n      line: 15,\n      url: 'file:///path/to/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({ args: [], column: 3, func: 'bar', line: 20, url: 'file:///path/to/file.js' })\n    expect(stackFrames.stack[3]).toEqual({\n      args: [],\n      column: 1,\n      func: '?',\n      line: 23,\n      url: 'file:///path/to/index.html',\n    })\n  })\n\n  it('should parse Chrome error with no location', () => {\n    const error = { stack: 'error\\n at Array.forEach (native)' }\n    const stackFrames = computeStackTrace(error as Error)\n    expect(stackFrames.stack.length).toEqual(1)\n    expect(stackFrames.stack[0]).toEqual({\n      args: ['native'],\n      column: undefined,\n      func: 'Array.forEach',\n      line: undefined,\n      url: undefined,\n    })\n  })\n\n  it('should parse Chrome error that only contain file name, with no path prefix', () => {\n    const stack = `Error: RTE Simulation\n    at foo$bar$oof$rab (events.cljs:1060:12)\n    at func1$func2$func3$func4 (std_interceptors.js:128:19)\n    at eval (std_interceptors.jsx:132:29)`\n\n    const stackFrames = computeStackTrace({ stack } as Error)\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 12,\n      func: 'foo$bar$oof$rab',\n      line: 1060,\n      url: 'events.cljs',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 19,\n      func: 'func1$func2$func3$func4',\n      line: 128,\n      url: 'std_interceptors.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({ args: [], column: 29, func: 'eval', line: 132, url: 'std_interceptors.jsx' })\n  })\n\n  it('should not include error message into stacktrace ', () => {\n    const stackFrames = computeStackTrace(new Error('bar@http://path/to/file.js:1:1'))\n\n    expect(stackFrames.stack[0]?.url).not.toBe('http://path/to/file.js')\n  })\n\n  it('should parse Chrome anonymous function errors', () => {\n    const stack = `Error: RTE Simulation\n    at https://datadoghq.com/somefile.js:8489:191\n    at chrome-extension://<id>/content/index.js:85:37379`\n\n    const stackFrames = computeStackTrace({ stack } as Error)\n    expect(stackFrames.stack.length).toEqual(2)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 191,\n      func: '?',\n      line: 8489,\n      url: 'https://datadoghq.com/somefile.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 37379,\n      func: '?',\n      line: 85,\n      url: 'chrome-extension://<id>/content/index.js',\n    })\n  })\n\n  it('should parse Chrome 15 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.CHROME_15 as any)\n\n    expect(stackFrames.stack.length).toEqual(4)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 17, func: 'bar', line: 13, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 5, func: 'bar', line: 16, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({ args: [], column: 5, func: 'foo', line: 20, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[3]).toEqual({ args: [], column: 4, func: '?', line: 24, url: 'http://path/to/file.js' })\n  })\n\n  it('should parse Chrome 36 error with port numbers', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.CHROME_36)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 27,\n      func: 'dumpExceptionError',\n      line: 41,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 146,\n      func: 'HTMLButtonElement.onclick',\n      line: 107,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 3651,\n      func: 'I.e.fn.(anonymous function) [as index]',\n      line: 10,\n      url: 'http://localhost:8080/file.js',\n    })\n  })\n\n  it('should parse Chrome error with webpack URLs', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.CHROME_XX_WEBPACK)\n\n    expect(stackFrames.stack.length).toEqual(4)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 108,\n      func: 'TESTTESTTEST.eval',\n      line: 295,\n      url: 'webpack:///./src/components/test/test.jsx?',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 32,\n      func: 'TESTTESTTEST.render',\n      line: 272,\n      url: 'webpack:///./src/components/test/test.jsx?',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 31,\n      func: 'TESTTESTTEST.tryRender',\n      line: 34,\n      url: 'webpack:///./~/react-transform-catch-errors/lib/index.js?',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: [],\n      column: 30,\n      func: 'TESTTESTTEST.proxiedMethod',\n      line: 44,\n      url: 'webpack:///./~/react-proxy/modules/createPrototypeProxy.js?',\n    })\n  })\n\n  it('should parse Electron schema with Chrome error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.ELECTRON)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 27,\n      func: 'dumpExceptionError',\n      line: 41,\n      url: 'electron://-/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 146,\n      func: 'HTMLButtonElement.onclick',\n      line: 107,\n      url: 'electron://-/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 3651,\n      func: 'I.e.fn.(anonymous function) [as index]',\n      line: 10,\n      url: 'electron://-/file.js',\n    })\n  })\n\n  it('should parse nested eval() from Chrome', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.CHROME_48_EVAL)\n\n    expect(stackFrames.stack.length).toEqual(5)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 17,\n      func: 'baz',\n      line: 21,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 17,\n      func: 'foo',\n      line: 21,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 17,\n      func: 'eval',\n      line: 21,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: [],\n      column: 17,\n      func: 'Object.speak',\n      line: 21,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[4]).toEqual({\n      args: [],\n      column: 13,\n      func: '?',\n      line: 31,\n      url: 'http://localhost:8080/file.js',\n    })\n  })\n\n  it('should parse Chrome error with blob URLs', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.CHROME_48_BLOB)\n\n    expect(stackFrames.stack.length).toEqual(7)\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 29146,\n      func: 's',\n      line: 31,\n      url: 'blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 30039,\n      func: 'Object.d [as add]',\n      line: 31,\n      url: 'blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: [],\n      column: 10978,\n      func: '?',\n      line: 15,\n      url: 'blob:http%3A//localhost%3A8080/d4eefe0f-361a-4682-b217-76587d9f712a',\n    })\n    expect(stackFrames.stack[4]).toEqual({\n      args: [],\n      column: 6911,\n      func: '?',\n      line: 1,\n      url: 'blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379',\n    })\n    expect(stackFrames.stack[5]).toEqual({\n      args: [],\n      column: 3019,\n      func: 'n.fire',\n      line: 7,\n      url: 'blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379',\n    })\n    expect(stackFrames.stack[6]).toEqual({\n      args: [],\n      column: 2863,\n      func: 'n.handle',\n      line: 7,\n      url: 'blob:http%3A//localhost%3A8080/abfc40e9-4742-44ed-9dcd-af8f99a29379',\n    })\n  })\n\n  it('should parse errors from Chrome Snippets', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.CHROME_111_SNIPPET)\n\n    expect(stackFrames.stack.length).toEqual(1)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 13, func: '?', line: 1, url: 'snippet:///snippet_file' })\n  })\n\n  it('should parse empty IE 9 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.IE_9)\n\n    if (stackFrames.stack) {\n      expect(stackFrames.stack.length).toEqual(0)\n    }\n  })\n\n  it('should parse IE 10 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.IE_10 as any)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    // TODO: func should be normalized\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 13,\n      func: 'Anonymous function',\n      line: 48,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 9, func: 'foo', line: 46, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({ args: [], column: 1, func: 'bar', line: 82, url: 'http://path/to/file.js' })\n  })\n\n  it('should parse IE 11 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.IE_11)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    // TODO: func should be normalized\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 21,\n      func: 'Anonymous function',\n      line: 47,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 13, func: 'foo', line: 45, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({ args: [], column: 1, func: 'bar', line: 108, url: 'http://path/to/file.js' })\n  })\n\n  it('should parse IE 11 eval error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.IE_11_EVAL)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 1, func: 'eval code', line: 1, url: 'eval code' })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 17, func: 'foo', line: 58, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({ args: [], column: 1, func: 'bar', line: 109, url: 'http://path/to/file.js' })\n  })\n\n  it('should parse Opera 25 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.OPERA_25)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({ args: [], column: 22, func: '?', line: 47, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[1]).toEqual({ args: [], column: 15, func: 'foo', line: 52, url: 'http://path/to/file.js' })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: 168,\n      func: 'bar',\n      line: 108,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse PhantomJS 1.19 error', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.PHANTOMJS_1_19 as Error)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 878,\n      url: 'file:///path/to/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'foo',\n      line: 4283,\n      url: 'http://path/to/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 4287,\n      url: 'http://path/to/file.js',\n    })\n  })\n\n  it('should parse Firefox errors with resource: URLs', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_50_RESOURCE_URL)\n\n    expect(stackFrames.stack.length).toEqual(3)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 16,\n      func: 'render',\n      line: 5529,\n      url: 'resource://path/data/content/bundle.js',\n    })\n  })\n\n  it('should parse Firefox errors with eval URLs', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.FIREFOX_43_EVAL as any)\n\n    expect(stackFrames.stack.length).toEqual(5)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'baz',\n      line: 26,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: undefined,\n      func: 'foo',\n      line: 26,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[2]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: 26,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[3]).toEqual({\n      args: [],\n      column: 17,\n      func: 'speak',\n      line: 26,\n      url: 'http://localhost:8080/file.js',\n    })\n    expect(stackFrames.stack[4]).toEqual({\n      args: [],\n      column: 9,\n      func: '?',\n      line: 33,\n      url: 'http://localhost:8080/file.js',\n    })\n  })\n\n  it('should parse React Native errors on Android', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.ANDROID_REACT_NATIVE)\n\n    expect(stackFrames.stack.length).toEqual(8)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 24,\n      func: 'render',\n      line: 78,\n      url: '/home/username/sample-workspace/sampleapp.collect.react/src/components/GpsMonitorScene.js',\n    })\n    expect(stackFrames.stack[7]).toEqual({\n      args: [],\n      column: 41,\n      func: 'this',\n      line: 74,\n      url: '/home/username/sample-workspace/sampleapp.collect.react/node_modules/react-native/Libraries/Renderer/src/renderers/native/ReactNativeBaseComponent.js',\n    })\n  })\n\n  it('should parse React Native errors on Android Production', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.ANDROID_REACT_NATIVE_PROD)\n\n    expect(stackFrames.stack.length).toEqual(37)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 1917,\n      func: 'value',\n      line: 12,\n      url: 'index.android.bundle',\n    })\n    expect(stackFrames.stack[35]).toEqual({\n      args: [],\n      column: 927,\n      func: 'value',\n      line: 29,\n      url: 'index.android.bundle',\n    })\n    expect(stackFrames.stack[36]).toEqual({\n      args: [],\n      column: undefined,\n      func: '?',\n      line: undefined,\n      url: '[native code]',\n    })\n  })\n\n  it('should parse iOS capacitor', () => {\n    const stackFrames = computeStackTrace(CapturedExceptions.IOS_CAPACITOR)\n\n    expect(stackFrames.stack.length).toEqual(2)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 99546,\n      func: '?',\n      line: 34,\n      url: 'capacitor://localhost/media/dist/bundle.js',\n    })\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      column: 47950,\n      func: 'r',\n      line: 34,\n      url: 'capacitor://localhost/media/dist/bundle.js',\n    })\n  })\n\n  it('should parse Safari WebAssembly stack frames', () => {\n    const wasmStack = `\n  RuntimeError: Out of bounds memory access\n      myModule.wasm-function[crashHandler]@[wasm code]\n      <?>.wasm-function[42]@[wasm code]\n      handleError@http://192.168.1.113:3000/:98:25\n      @http://192.168.1.113:3000/:113:32\n    `\n    const mockErr = { message: 'Out of bounds memory access', name: 'RuntimeError', stack: wasmStack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack.length).toBe(4)\n\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      func: 'myModule.wasm-function[crashHandler]',\n      url: '[wasm code]',\n      column: undefined,\n      line: undefined,\n    })\n\n    expect(stackFrames.stack[1]).toEqual({\n      args: [],\n      func: '<?>.wasm-function[42]',\n      url: '[wasm code]',\n      column: undefined,\n      line: undefined,\n    })\n  })\n\n  it('should parse Safari Wasm stack frames from file URL', () => {\n    const wasmStack = `\n  RuntimeError: Some Wasm Error\n      myModule.wasm-function[crashFunc]@[wasm code]\n      regularJsFunc@http://example.com/script.js:10:5\n    `\n    const mockErr = { message: 'Some Wasm Error', name: 'RuntimeError', stack: wasmStack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack.length).toBe(2)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      func: 'myModule.wasm-function[crashFunc]',\n      url: '[wasm code]',\n      line: undefined,\n      column: undefined,\n    })\n  })\n\n  it('should parse Chrome WebAssembly stack frames', () => {\n    const wasmStack = `\n  Error: Wasm Error\n    at myModule.foo (http://example.com/myModule.wasm:wasm-function[42]:0x1a3b)\n    at bar (http://example.com/script.js:10:5)\n    `\n    const mockErr = { message: 'Wasm Error', name: 'Error', stack: wasmStack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack.length).toBe(2)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      func: 'myModule.foo',\n      url: 'http://example.com/myModule.wasm:wasm-function[42]:0x1a3b',\n      line: undefined,\n      column: undefined,\n    })\n  })\n\n  it('should parse Firefox WebAssembly stack frames', () => {\n    const wasmStack = `\n  Error: Wasm Error\n    myModule.foo@http://example.com/my-module.wasm:wasm-function[42]:0x1a3b\n    bar@http://example.com/script.js:10:5\n    `\n    const mockErr = { message: 'Wasm Error', name: 'Error', stack: wasmStack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack.length).toBe(2)\n\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      func: 'myModule.foo',\n      url: 'http://example.com/my-module.wasm:wasm-function[42]:0x1a3b',\n      line: undefined,\n      column: undefined,\n    })\n  })\n\n  it('should normalize non native errors stacktraces across browsers', () => {\n    class DatadogTestCustomError extends Error {\n      constructor() {\n        super()\n        this.name = 'Error' // set name to Error so that no browser would default to the constructor name\n      }\n    }\n    class DatadogTestCustomError2 extends DatadogTestCustomError {}\n\n    const [customError, customErrorWithInheritance, customErrorWithAnonymousInheritance, nativeError] = [\n      DatadogTestCustomError,\n      DatadogTestCustomError2,\n      // this is an anonymous class, which has no name\n      // we're checking if the stacktrace is correctly reported for this specific case (with the class name missing)\n      class extends DatadogTestCustomError2 {\n        constructor() {\n          super()\n          this.name = 'Error'\n        }\n      },\n      Error,\n    ].map((errConstructor) => new errConstructor()) // so that both errors should exactly have the same stacktrace\n\n    expect(computeStackTrace(customError.stack)).toEqual(computeStackTrace(nativeError.stack))\n    expect(computeStackTrace(customErrorWithInheritance.stack)).toEqual(computeStackTrace(nativeError.stack))\n    expect(computeStackTrace(customErrorWithAnonymousInheritance.stack)).toEqual(computeStackTrace(nativeError.stack))\n  })\n\n  it('should skip empty lines in stacktraces', () => {\n    const wasmStack = `\n  Error: Wasm Error\n    myModule.foo@http://example.com/my-module.wasm:wasm-function[42]:0x1a3b\\n \\n\\t\\n`\n    const mockErr = { message: 'Wasm Error', name: 'Error', stack: wasmStack }\n    const stackFrames = computeStackTrace(mockErr)\n\n    expect(stackFrames.stack.length).toBe(1)\n\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      func: 'myModule.foo',\n      url: 'http://example.com/my-module.wasm:wasm-function[42]:0x1a3b',\n      line: undefined,\n      column: undefined,\n    })\n  })\n\n  it('should parse stack from html button click listener', () => {\n    const stackFrames = computeStackTrace(CHROME_141_HTML_ANONYMOUS_LISTENER)\n\n    expect(stackFrames.stack.length).toEqual(1)\n    expect(stackFrames.stack[0]).toEqual({\n      args: [],\n      column: 4287,\n      func: 'HTMLButtonElement.<anonymous>',\n      line: 1,\n      url: 'http://path/to/file.js',\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/stackTrace/computeStackTrace.ts",
    "content": "/**\n * Cross-browser stack trace computation.\n *\n * Reference implementation: https://github.com/csnover/TraceKit/blob/04530298073c3823de72deb0b97e7b38ca7bcb59/tracekit.js\n */\n\nimport { isIndexableObject } from '../utils/typeUtils'\n\nexport interface StackFrame {\n  url?: string\n  func?: string\n  /** The arguments passed to the function, if known. */\n  args?: string[]\n  line?: number\n  column?: number\n  /** An array of source code lines; the middle element corresponds to the correct line. */\n  context?: string[]\n}\n\nexport interface StackTrace {\n  name?: string\n  message?: string\n  url?: string\n  stack: StackFrame[]\n  incomplete?: boolean\n  partial?: boolean\n}\n\nconst UNKNOWN_FUNCTION = '?'\n\nexport function computeStackTrace(ex: unknown): StackTrace {\n  const stack: StackFrame[] = []\n\n  let stackProperty = tryToGetString(ex, 'stack')\n  const exString = String(ex)\n  if (stackProperty && stackProperty.startsWith(exString)) {\n    stackProperty = stackProperty.slice(exString.length)\n  }\n  if (stackProperty) {\n    stackProperty.split('\\n').forEach((line) => {\n      const stackFrame =\n        parseChromeLine(line) || parseChromeAnonymousLine(line) || parseWinLine(line) || parseGeckoLine(line)\n      if (stackFrame) {\n        if (!stackFrame.func && stackFrame.line) {\n          stackFrame.func = UNKNOWN_FUNCTION\n        }\n\n        stack.push(stackFrame)\n      }\n    })\n  }\n\n  if (stack.length > 0 && isWronglyReportingCustomErrors() && ex instanceof Error) {\n    // if we are wrongly reporting custom errors\n    const constructors: string[] = []\n\n    // go through each inherited constructor\n    let currentPrototype: object | undefined = ex\n    while (\n      (currentPrototype = Object.getPrototypeOf(currentPrototype)) &&\n      isNonNativeClassPrototype(currentPrototype)\n    ) {\n      const constructorName = currentPrototype.constructor?.name || UNKNOWN_FUNCTION\n      constructors.push(constructorName)\n    }\n\n    // traverse the stacktrace in reverse order because the stacktrace starts with the last inherited constructor\n    // we check constructor names to ensure we remove the correct frame (and there isn't a weird unsupported environment behavior)\n    for (let i = constructors.length - 1; i >= 0 && stack[0]?.func === constructors[i]; i--) {\n      // if the first stack frame is the custom error constructor\n      // null stack frames may represent frames that failed to be parsed because the error class did not have a constructor\n      stack.shift() // remove it\n    }\n  }\n\n  return {\n    message: tryToGetString(ex, 'message'),\n    name: tryToGetString(ex, 'name'),\n    stack,\n  }\n}\nconst fileUrl =\n  '((?:file|https?|blob|chrome-extension|electron|native|eval|webpack|snippet|<anonymous>|\\\\w+\\\\.|\\\\/).*?)'\nconst filePosition = '(?::(\\\\d+))'\nconst CHROME_LINE_RE = new RegExp(`^\\\\s*at (.*?) ?\\\\(${fileUrl}${filePosition}?${filePosition}?\\\\)?\\\\s*$`, 'i')\n\nconst CHROME_EVAL_RE = new RegExp(`\\\\((\\\\S*)${filePosition}${filePosition}\\\\)`)\n\nfunction parseChromeLine(line: string): StackFrame | undefined {\n  const parts = CHROME_LINE_RE.exec(line)\n\n  if (!parts) {\n    return\n  }\n\n  const isNative = parts[2] && parts[2].indexOf('native') === 0 // start of line\n  const isEval = parts[2] && parts[2].indexOf('eval') === 0 // start of line\n  const submatch = CHROME_EVAL_RE.exec(parts[2])\n\n  if (isEval && submatch) {\n    // throw out eval line/column and use top-most line/column number\n    parts[2] = submatch[1] // url\n    parts[3] = submatch[2] // line\n    parts[4] = submatch[3] // column\n  }\n\n  return {\n    args: isNative ? [parts[2]] : [],\n    column: parts[4] ? +parts[4] : undefined,\n    func: parts[1] || UNKNOWN_FUNCTION,\n    line: parts[3] ? +parts[3] : undefined,\n    url: !isNative ? parts[2] : undefined,\n  }\n}\n\nconst htmlAnonymousPart = '(?:(.*)?(?: @))'\nconst CHROME_ANONYMOUS_FUNCTION_RE = new RegExp(\n  `^\\\\s*at\\\\s*${htmlAnonymousPart}?\\\\s*${fileUrl}${filePosition}?${filePosition}??\\\\s*$`,\n  'i'\n)\n\nfunction parseChromeAnonymousLine(line: string): StackFrame | undefined {\n  const parts = CHROME_ANONYMOUS_FUNCTION_RE.exec(line)\n\n  if (!parts) {\n    return\n  }\n\n  return {\n    args: [],\n    column: parts[4] ? +parts[4] : undefined,\n    func: parts[1] || UNKNOWN_FUNCTION,\n    line: parts[3] ? +parts[3] : undefined,\n    url: parts[2],\n  }\n}\n\nconst WINJS_LINE_RE =\n  /^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i\n\nfunction parseWinLine(line: string): StackFrame | undefined {\n  const parts = WINJS_LINE_RE.exec(line)\n  if (!parts) {\n    return\n  }\n\n  return {\n    args: [],\n    column: parts[4] ? +parts[4] : undefined,\n    func: parts[1] || UNKNOWN_FUNCTION,\n    line: +parts[3],\n    url: parts[2],\n  }\n}\n\nconst GECKO_LINE_RE =\n  /^\\s*(.*?)(?:\\((.*?)\\))?(?:(?:(?:^|@)((?:file|https?|blob|chrome|webpack|resource|capacitor|\\[native).*?|[^@]*bundle|\\[wasm code\\])(?::(\\d+))?(?::(\\d+))?)|@)\\s*$/i\nconst GECKO_EVAL_RE = /(\\S+) line (\\d+)(?: > eval line \\d+)* > eval/i\n\nfunction parseGeckoLine(line: string): StackFrame | undefined {\n  const parts = GECKO_LINE_RE.exec(line)\n  if (!parts) {\n    return\n  }\n\n  const isEval = parts[3] && parts[3].indexOf(' > eval') > -1\n  const submatch = GECKO_EVAL_RE.exec(parts[3])\n\n  if (isEval && submatch) {\n    // throw out eval line/column and use top-most line number\n    parts[3] = submatch[1]\n    parts[4] = submatch[2]\n    parts[5] = undefined! // no column when eval\n  }\n\n  return {\n    args: parts[2] ? parts[2].split(',') : [],\n    column: parts[5] ? +parts[5] : undefined,\n    func: parts[1] || UNKNOWN_FUNCTION,\n    line: parts[4] ? +parts[4] : undefined,\n    url: parts[3],\n  }\n}\n\nfunction tryToGetString(candidate: unknown, property: string) {\n  return isIndexableObject(candidate) && typeof candidate[property] === 'string' ? candidate[property] : undefined\n}\n\nexport function computeStackTraceFromOnErrorMessage(\n  messageObj: unknown,\n  url?: string,\n  line?: number,\n  column?: number\n): StackTrace | undefined {\n  if (url === undefined) {\n    return\n  }\n  const { name, message } = tryToParseMessage(messageObj)\n  return {\n    name,\n    message,\n    stack: [{ url, column, line }],\n  }\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types\nconst ERROR_TYPES_RE =\n  /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?([\\s\\S]*)$/\n\nfunction tryToParseMessage(messageObj: unknown) {\n  let name\n  let message\n  if ({}.toString.call(messageObj) === '[object String]') {\n    ;[, name, message] = ERROR_TYPES_RE.exec(messageObj as string)!\n  }\n  return { name, message }\n}\n\n// Custom error stacktrace fix\n// Some browsers (safari/firefox) add the error constructor as a frame in the stacktrace\n// In order to normalize the stacktrace, we need to remove it\n\nfunction isNonNativeClassPrototype(prototype: object) {\n  return String(prototype.constructor).startsWith('class ')\n}\n\nlet isWronglyReportingCustomErrorsCache: boolean | undefined\n\nfunction isWronglyReportingCustomErrors() {\n  if (isWronglyReportingCustomErrorsCache !== undefined) {\n    return isWronglyReportingCustomErrorsCache\n  }\n\n  /* eslint-disable no-restricted-syntax */\n  class DatadogTestCustomError extends Error {\n    constructor() {\n      super()\n      this.name = 'Error' // set name to Error so that no browser would default to the constructor name\n    }\n  }\n\n  const [customError, nativeError] = [DatadogTestCustomError, Error].map((errConstructor) => new errConstructor()) // so that both errors should exactly have the same stacktrace\n\n  isWronglyReportingCustomErrorsCache =\n    // If customError is not a class, it means that this was built with ES5 as target, converting the class to a normal object.\n    // Thus, error constructors will be reported on all browsers, which is the expected behavior.\n    isNonNativeClassPrototype(Object.getPrototypeOf(customError)) &&\n    // If the browser is correctly reporting the stacktrace, the normal error stacktrace should be the same as the custom error stacktrace\n    nativeError.stack !== customError.stack\n\n  return isWronglyReportingCustomErrorsCache\n}\n"
  },
  {
    "path": "packages/core/src/tools/stackTrace/handlingStack.spec.ts",
    "content": "import { createHandlingStack } from './handlingStack'\n\ndescribe('createHandlingStack', () => {\n  let handlingStack: string\n  function internalCall() {\n    handlingStack = createHandlingStack('error')\n  }\n  function userCallTwo() {\n    internalCall()\n  }\n  function userCallOne() {\n    userCallTwo()\n  }\n\n  it('should create handling stack trace without internal calls', () => {\n    userCallOne()\n\n    expect(handlingStack).toMatch(/^HandlingStack: error\\n\\s+at userCallTwo @ (.*)\\n\\s+at userCallOne @ (.*)/)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/stackTrace/handlingStack.ts",
    "content": "import { callMonitored } from '../monitor'\nimport type { StackTrace } from './computeStackTrace'\nimport { computeStackTrace } from './computeStackTrace'\n\n/**\n * Creates a stacktrace without SDK internal frames.\n * Constraints:\n * - Has to be called at the utmost position of the call stack.\n * - No monitored function should encapsulate it, that is why we need to use callMonitored inside it.\n */\nexport function createHandlingStack(\n  type:\n    | 'console error'\n    | 'action'\n    | 'error'\n    | 'instrumented method'\n    | 'log'\n    | 'react error'\n    | 'nextjs error'\n    | 'vue error'\n    | 'angular error'\n    | 'view'\n    | 'vital'\n): string {\n  /**\n   * Skip the two internal frames:\n   * - SDK API (console.error, ...)\n   * - this function\n   * in order to keep only the user calls\n   */\n  const internalFramesToSkip = 2\n  const error = new Error(type)\n  error.name = 'HandlingStack'\n  let formattedStack: string\n\n  callMonitored(() => {\n    const stackTrace = computeStackTrace(error)\n    stackTrace.stack = stackTrace.stack.slice(internalFramesToSkip)\n    formattedStack = toStackTraceString(stackTrace)\n  })\n\n  return formattedStack!\n}\n\nexport function toStackTraceString(stack: StackTrace) {\n  let result = formatErrorMessage(stack)\n  stack.stack.forEach((frame) => {\n    const func = frame.func === '?' ? '<anonymous>' : frame.func\n    const args = frame.args && frame.args.length > 0 ? `(${frame.args.join(', ')})` : ''\n    const line = frame.line ? `:${frame.line}` : ''\n    const column = frame.line && frame.column ? `:${frame.column}` : ''\n    result += `\\n  at ${func!}${args} @ ${frame.url!}${line}${column}`\n  })\n  return result\n}\n\nexport function formatErrorMessage(stack: StackTrace) {\n  return `${stack.name || 'Error'}: ${stack.message!}`\n}\n"
  },
  {
    "path": "packages/core/src/tools/taskQueue.spec.ts",
    "content": "import { mockClock, mockRequestIdleCallback, registerCleanupTask } from '../../test'\nimport { createTaskQueue, MAX_EXECUTION_TIME_ON_TIMEOUT } from './taskQueue'\n\ndescribe('createTaskQueue', () => {\n  it('runs the task using an idle callback', () => {\n    const requestIdleCallbackMock = mockRequestIdleCallback()\n    const taskQueue = createTaskQueue()\n    const task = jasmine.createSpy('task')\n\n    taskQueue.push(task)\n    expect(task).not.toHaveBeenCalled()\n\n    requestIdleCallbackMock.idle()\n    expect(task).toHaveBeenCalled()\n  })\n\n  it('runs as many tasks as possible in a single idle callback', () => {\n    const clock = mockClock()\n    const requestIdleCallbackMock = mockRequestIdleCallback()\n\n    // Each task takes 10ms to run\n    const task1 = jasmine.createSpy().and.callFake(() => clock.tick(10))\n    const task2 = jasmine.createSpy().and.callFake(() => clock.tick(10))\n    const task3 = jasmine.createSpy().and.callFake(() => clock.tick(10))\n\n    const taskQueue = createTaskQueue()\n\n    taskQueue.push(task1)\n    taskQueue.push(task2)\n    taskQueue.push(task3)\n\n    requestIdleCallbackMock.idle(15)\n    expect(task1).toHaveBeenCalled()\n    expect(task2).toHaveBeenCalled()\n    expect(task3).not.toHaveBeenCalled()\n\n    requestIdleCallbackMock.idle(5)\n    expect(task3).toHaveBeenCalled()\n  })\n\n  it('runs some tasks in case of timeout', () => {\n    const clock = mockClock()\n    const requestIdleCallbackMock = mockRequestIdleCallback()\n\n    const task1 = jasmine.createSpy().and.callFake(() => clock.tick(MAX_EXECUTION_TIME_ON_TIMEOUT - 10))\n    const task2 = jasmine.createSpy().and.callFake(() => clock.tick(20))\n    const task3 = jasmine.createSpy().and.callFake(() => clock.tick(20))\n\n    const taskQueue = createTaskQueue()\n\n    taskQueue.push(task1)\n    taskQueue.push(task2)\n    taskQueue.push(task3)\n\n    requestIdleCallbackMock.timeout()\n    expect(task1).toHaveBeenCalled()\n    expect(task2).toHaveBeenCalled()\n    expect(task3).not.toHaveBeenCalled()\n  })\n\n  it('runs pending tasks when requestIdleCallback invokes the callback with no deadline', () => {\n    const clock = mockClock()\n    replaceRequestIdleCallbackWithPolyfillShim()\n\n    const taskQueue = createTaskQueue()\n    const task1 = jasmine.createSpy('task1')\n    const task2 = jasmine.createSpy('task2')\n    const task3 = jasmine.createSpy('task3')\n\n    taskQueue.push(task1)\n    taskQueue.push(task2)\n    taskQueue.push(task3)\n\n    clock.tick(0)\n\n    expect(task1).toHaveBeenCalled()\n    expect(task2).toHaveBeenCalled()\n    expect(task3).toHaveBeenCalled()\n  })\n})\n\nfunction replaceRequestIdleCallbackWithPolyfillShim() {\n  const originalRequestIdleCallback = window.requestIdleCallback\n  const originalCancelIdleCallback = window.cancelIdleCallback\n  // Reproduces `(cb) => setTimeout(cb, 0)` — invokes the callback with no argument.\n  window.requestIdleCallback = ((cb: () => void) =>\n    setTimeout(() => cb(), 0) as unknown as number) as typeof window.requestIdleCallback\n  window.cancelIdleCallback = ((id: number) => clearTimeout(id)) as typeof window.cancelIdleCallback\n  registerCleanupTask(() => {\n    window.requestIdleCallback = originalRequestIdleCallback\n    window.cancelIdleCallback = originalCancelIdleCallback\n  })\n}\n"
  },
  {
    "path": "packages/core/src/tools/taskQueue.ts",
    "content": "import { ONE_SECOND } from './utils/timeUtils'\nimport { requestIdleCallback } from './requestIdleCallback'\n\n/**\n * Maximum delay before starting to execute tasks in the queue. We don't want to wait too long\n * before running tasks, as it might hurt reliability (ex: if the user navigates away, we might lose\n * the opportunity to send some data). We also don't want to run tasks too often, as it might hurt\n * performance.\n */\nconst IDLE_CALLBACK_TIMEOUT = ONE_SECOND\n\n/**\n * Maximum amount of time allocated to running tasks when a timeout (`IDLE_CALLBACK_TIMEOUT`) is\n * reached. We should not run tasks for too long as it will hurt performance, but we should still\n * run some tasks to avoid postponing them forever.\n *\n * Rational: Running tasks for 30ms every second (IDLE_CALLBACK_TIMEOUT) should be acceptable.\n */\nexport const MAX_EXECUTION_TIME_ON_TIMEOUT = 30\n\nexport interface TaskQueue {\n  push(task: Task): void\n  stop(): void\n}\n\ntype Task = () => void\n\nexport function createTaskQueue(): TaskQueue {\n  const pendingTasks: Task[] = []\n\n  function run(deadline: IdleDeadline | null) {\n    let executionTimeRemaining: () => number\n    // `deadline` can be null when `requestIdleCallback` is replaced by a page-injected polyfill\n    // (e.g. `setTimeout(cb, 0)` in some WKWebViews) that invokes the callback with no argument.\n    if (!deadline || deadline.didTimeout) {\n      const start = performance.now()\n      executionTimeRemaining = () => MAX_EXECUTION_TIME_ON_TIMEOUT - (performance.now() - start)\n    } else {\n      executionTimeRemaining = deadline.timeRemaining.bind(deadline)\n    }\n\n    while (executionTimeRemaining() > 0 && pendingTasks.length) {\n      pendingTasks.shift()!()\n    }\n\n    if (pendingTasks.length) {\n      scheduleNextRun()\n    }\n  }\n\n  function scheduleNextRun() {\n    requestIdleCallback(run, { timeout: IDLE_CALLBACK_TIMEOUT })\n  }\n\n  return {\n    push(task) {\n      if (pendingTasks.push(task) === 1) {\n        scheduleNextRun()\n      }\n    },\n    stop() {\n      pendingTasks.length = 0\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/timer.spec.ts",
    "content": "import { mockClock, mockZoneJs } from '../../test'\nimport type { Clock, MockZoneJs } from '../../test'\nimport { startMonitorErrorCollection } from './monitor'\nimport { setTimeout, clearTimeout, setInterval, clearInterval } from './timer'\nimport { noop } from './utils/functionUtils'\n;[\n  {\n    name: 'setTimeout' as const,\n    setTimer: setTimeout,\n    clearTimer: clearTimeout,\n  },\n  {\n    name: 'setInterval' as const,\n    setTimer: setInterval,\n    clearTimer: clearInterval,\n  },\n].forEach(({ name, setTimer, clearTimer }) => {\n  describe(name, () => {\n    let clock: Clock\n    let zoneJs: MockZoneJs\n\n    beforeEach(() => {\n      clock = mockClock()\n      zoneJs = mockZoneJs()\n    })\n\n    it('executes the callback asynchronously', () => {\n      const spy = jasmine.createSpy()\n      setTimer(spy)\n      expect(spy).not.toHaveBeenCalled()\n      clock.tick(0)\n      expect(spy).toHaveBeenCalledOnceWith()\n    })\n\n    it('schedules an asynchronous task', () => {\n      const spy = jasmine.createSpy()\n      setTimer(spy)\n      expect(spy).not.toHaveBeenCalled()\n      clock.tick(0)\n      expect(spy).toHaveBeenCalledOnceWith()\n    })\n\n    it('does not use the Zone.js function', () => {\n      const zoneJsSetTimerSpy = jasmine.createSpy()\n      zoneJs.replaceProperty(window, name, zoneJsSetTimerSpy)\n\n      setTimer(noop)\n      clock.tick(0)\n\n      expect(zoneJsSetTimerSpy).not.toHaveBeenCalled()\n    })\n\n    it('monitors the callback', () => {\n      const onMonitorErrorCollectedSpy = jasmine.createSpy()\n      startMonitorErrorCollection(onMonitorErrorCollectedSpy)\n\n      setTimer(() => {\n        throw new Error('foo')\n      })\n      clock.tick(0)\n\n      expect(onMonitorErrorCollectedSpy).toHaveBeenCalledOnceWith(new Error('foo'))\n    })\n\n    it('can be canceled', () => {\n      const spy = jasmine.createSpy()\n      const timerId = setTimer(spy)\n      clearTimer(timerId)\n      clock.tick(0)\n      expect(spy).not.toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/timer.ts",
    "content": "import { getZoneJsOriginalValue } from './getZoneJsOriginalValue'\nimport { monitor } from './monitor'\nimport { getGlobalObject } from './globalObject'\n\nexport type TimeoutId = ReturnType<typeof globalThis.setTimeout>\n\nexport function setTimeout(callback: () => void, delay?: number): TimeoutId {\n  return getZoneJsOriginalValue(getGlobalObject(), 'setTimeout')(monitor(callback), delay)\n}\n\nexport function clearTimeout(timeoutId: TimeoutId | undefined) {\n  getZoneJsOriginalValue(getGlobalObject(), 'clearTimeout')(timeoutId)\n}\n\nexport function setInterval(callback: () => void, delay?: number): TimeoutId {\n  return getZoneJsOriginalValue(getGlobalObject(), 'setInterval')(monitor(callback), delay)\n}\n\nexport function clearInterval(timeoutId: TimeoutId | undefined) {\n  getZoneJsOriginalValue(getGlobalObject(), 'clearInterval')(timeoutId)\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/arrayUtils.ts",
    "content": "export function removeDuplicates<T>(array: T[]) {\n  const set = new Set<T>()\n  array.forEach((item) => set.add(item))\n  return Array.from(set)\n}\n\nexport function removeItem<T>(array: T[], item: T) {\n  const index = array.indexOf(item)\n  if (index >= 0) {\n    array.splice(index, 1)\n  }\n}\nexport function isNonEmptyArray<T>(value: unknown): value is T[] {\n  return Array.isArray(value) && value.length > 0\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/browserDetection.spec.ts",
    "content": "import { combine } from '../mergeInto'\nimport { Browser, detectBrowser } from './browserDetection'\n\ndescribe('browserDetection', () => {\n  it('detects Safari', () => {\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent:\n              'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Safari/605.1.15',\n            vendor: 'Apple Computer, Inc.',\n          },\n        })\n      )\n    ).toBe(Browser.SAFARI)\n\n    // Emulates Safari detection if 'navigator.vendor' is removed one day\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent:\n              'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Safari/605.1.15',\n          },\n        })\n      )\n    ).toBe(Browser.SAFARI)\n\n    // Webview on iOS\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent:\n              'Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/20B110 [FBAN/FBIOS;FBDV/iPhone14,5;FBMD/iPhone;FBSN/iOS;FBSV/16.1.2;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5]',\n            vendor: 'Apple Computer, Inc.',\n          },\n        })\n      )\n    ).toBe(Browser.SAFARI)\n  })\n\n  it('detects Chromium', () => {\n    // Google Chrome 118\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent:\n              'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',\n            vendor: 'Google Inc.',\n          },\n          chrome: {},\n        })\n      )\n    ).toBe(Browser.CHROMIUM)\n\n    // Headless chrome\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent:\n              'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4512.0 Safari/537.36',\n            vendor: 'Google Inc.',\n          },\n        })\n      )\n    ).toBe(Browser.CHROMIUM)\n\n    // Microsoft Edge 89\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent:\n              'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 Edg/89.0.774.54',\n            vendor: 'Google Inc.',\n          },\n          chrome: {},\n        })\n      )\n    ).toBe(Browser.CHROMIUM)\n  })\n\n  it('other browsers', () => {\n    // Firefox 10\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: { userAgent: 'Mozilla/5.0 (X11; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0' },\n        })\n      )\n    ).toBe(Browser.OTHER)\n\n    // Firefox 120\n    expect(\n      detectBrowser(\n        fakeWindowWithDefaults({\n          navigator: {\n            userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:120.0) Gecko/20100101 Firefox/120.0',\n          },\n        })\n      )\n    ).toBe(Browser.OTHER)\n  })\n\n  function fakeWindowWithDefaults(partial: any): Window {\n    return combine(\n      {\n        navigator: {\n          userAgent: '',\n        },\n        document: {},\n      },\n      partial\n    ) as Window\n  }\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/browserDetection.ts",
    "content": "// Exported only for tests\nexport const enum Browser {\n  CHROMIUM,\n  SAFARI,\n  OTHER,\n}\n\nexport function isChromium() {\n  return detectBrowserCached() === Browser.CHROMIUM\n}\n\nexport function isSafari() {\n  return detectBrowserCached() === Browser.SAFARI\n}\n\nlet browserCache: Browser | undefined\nfunction detectBrowserCached() {\n  return browserCache ?? (browserCache = detectBrowser())\n}\n\n// Exported only for tests\nexport function detectBrowser(browserWindow: Window = window) {\n  const userAgent = browserWindow.navigator.userAgent\n  if ((browserWindow as any).chrome || /HeadlessChrome/.test(userAgent)) {\n    return Browser.CHROMIUM\n  }\n\n  if (\n    // navigator.vendor is deprecated, but it is the most resilient way we found to detect\n    // \"Apple maintained browsers\" (AKA Safari). If one day it gets removed, we still have the\n    // useragent test as a semi-working fallback.\n    browserWindow.navigator.vendor?.indexOf('Apple') === 0 ||\n    (/safari/i.test(userAgent) && !/chrome|android/i.test(userAgent))\n  ) {\n    return Browser.SAFARI\n  }\n\n  return Browser.OTHER\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/byteUtils.spec.ts",
    "content": "import { computeBytesCount, concatBuffers } from './byteUtils'\n\ndescribe('byteUtils', () => {\n  describe('computeBytesCount', () => {\n    it('should count the bytes of a message composed of 1 byte characters', () => {\n      expect(computeBytesCount('1234')).toEqual(4)\n    })\n\n    it('should count the bytes of a message composed of multiple bytes characters', () => {\n      expect(computeBytesCount('🪐')).toEqual(4)\n    })\n  })\n\n  describe('concatBuffers', () => {\n    it('concatenates buffers correctly', () => {\n      expect(concatBuffers([new Uint8Array([1, 2]), new Uint8Array([3, 4, 5]), new Uint8Array([6])])).toEqual(\n        new Uint8Array([1, 2, 3, 4, 5, 6])\n      )\n    })\n\n    it('concatenates an empty buffer and a non-empty buffer', () => {\n      expect(concatBuffers([new Uint8Array([]), new Uint8Array([1, 2, 3])])).toEqual(new Uint8Array([1, 2, 3]))\n    })\n\n    it('returns an empty buffer when an empty array is passed', () => {\n      expect(concatBuffers([])).toEqual(new Uint8Array([]))\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/byteUtils.ts",
    "content": "export const ONE_KIBI_BYTE = 1024\nexport const ONE_MEBI_BYTE = 1024 * ONE_KIBI_BYTE\n\n// eslint-disable-next-line no-control-regex\nconst HAS_MULTI_BYTES_CHARACTERS = /[^\\u0000-\\u007F]/\n\nexport interface Uint8ArrayBuffer extends Uint8Array {\n  readonly buffer: ArrayBuffer\n\n  subarray(begin?: number, end?: number): Uint8ArrayBuffer\n}\n\nexport function computeBytesCount(candidate: string): number {\n  // Accurate bytes count computations can degrade performances when there is a lot of events to process\n  if (!HAS_MULTI_BYTES_CHARACTERS.test(candidate)) {\n    return candidate.length\n  }\n\n  if (window.TextEncoder !== undefined) {\n    return new TextEncoder().encode(candidate).length\n  }\n\n  return new Blob([candidate]).size\n}\n\nexport function concatBuffers(buffers: Uint8ArrayBuffer[]): Uint8ArrayBuffer {\n  // Optimization: if there is a single buffer, no need to copy it\n  if (buffers.length === 1) {\n    return buffers[0]\n  }\n\n  const length = buffers.reduce((total, buffer) => total + buffer.length, 0)\n  const result: Uint8ArrayBuffer = new Uint8Array(length)\n  let offset = 0\n  for (const buffer of buffers) {\n    result.set(buffer, offset)\n    offset += buffer.length\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/functionUtils.spec.ts",
    "content": "import type { Clock } from '../../../test'\nimport { mockClock } from '../../../test'\nimport { throttle } from './functionUtils'\n\ndescribe('functionUtils', () => {\n  describe('throttle', () => {\n    let spy: jasmine.Spy\n    let throttled: () => void\n    let cancel: () => void\n    let clock: Clock\n\n    beforeEach(() => {\n      clock = mockClock()\n      spy = jasmine.createSpy()\n    })\n\n    describe('when {leading: false, trailing:false}', () => {\n      beforeEach(() => {\n        throttled = throttle(spy, 2, { leading: false, trailing: false }).throttled\n      })\n\n      it('should not call throttled function', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(0)\n      })\n\n      it('should not called throttled function after the wait period', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(0)\n      })\n\n      it('should not called throttled function performed after the wait period', () => {\n        throttled()\n        clock.tick(2)\n        throttled()\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(0)\n      })\n    })\n\n    describe('when {leading: false, trailing:true}', () => {\n      beforeEach(() => {\n        throttled = throttle(spy, 2, { leading: false }).throttled\n      })\n\n      it('should call throttled function after the wait period', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should dismiss calls made during the wait period', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(0)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(2)\n      })\n\n      it('should perform calls made after the wait period', () => {\n        throttled()\n        clock.tick(2)\n        throttled()\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(2)\n      })\n    })\n\n    describe('when {leading: true, trailing:false}', () => {\n      beforeEach(() => {\n        throttled = throttle(spy, 2, { trailing: false }).throttled\n      })\n\n      it('should call throttled function immediately', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should dismiss calls made during the wait period', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(2)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(2)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(2)\n      })\n\n      it('should perform calls made after the wait period', () => {\n        throttled()\n        clock.tick(2)\n        throttled()\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(2)\n      })\n    })\n\n    describe('when {leading: true, trailing:true}', () => {\n      beforeEach(() => {\n        throttled = throttle(spy, 2).throttled\n      })\n\n      it('should call throttled function immediately', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should postpone calls made during the wait period to after the period', () => {\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(2)\n\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(3)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(3)\n\n        clock.tick(1)\n        expect(spy).toHaveBeenCalledTimes(3)\n      })\n\n      it('should perform calls made after the wait period', () => {\n        throttled()\n        clock.tick(2)\n        throttled()\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(2)\n      })\n    })\n\n    describe('cancel', () => {\n      beforeEach(() => {\n        const result = throttle(spy, 2)\n        cancel = result.cancel\n        throttled = result.throttled\n      })\n\n      it('should abort pending execution', () => {\n        throttled()\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n\n        cancel()\n\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should allow future calls', () => {\n        cancel()\n        throttled()\n        expect(spy).toHaveBeenCalledTimes(1)\n        clock.tick(2)\n        expect(spy).toHaveBeenCalledTimes(1)\n      })\n    })\n\n    it('passes last parameters as arguments', () => {\n      const throttled = throttle(spy, 2).throttled\n      throttled(1)\n      throttled(2)\n      throttled(3)\n      clock.tick(2)\n      expect(spy.calls.allArgs()).toEqual([[1], [3]])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/functionUtils.ts",
    "content": "import type { TimeoutId } from '../timer'\nimport { setTimeout, clearTimeout } from '../timer'\n\n// use lodash API\nexport function throttle<T extends (...args: any[]) => void>(\n  fn: T,\n  wait: number,\n  options?: { leading?: boolean; trailing?: boolean }\n) {\n  const needLeadingExecution = options && options.leading !== undefined ? options.leading : true\n  const needTrailingExecution = options && options.trailing !== undefined ? options.trailing : true\n  let inWaitPeriod = false\n  let pendingExecutionWithParameters: Parameters<T> | undefined\n  let pendingTimeoutId: TimeoutId\n\n  return {\n    throttled: (...parameters: Parameters<T>) => {\n      if (inWaitPeriod) {\n        pendingExecutionWithParameters = parameters\n        return\n      }\n      if (needLeadingExecution) {\n        fn(...parameters)\n      } else {\n        pendingExecutionWithParameters = parameters\n      }\n      inWaitPeriod = true\n      pendingTimeoutId = setTimeout(() => {\n        if (needTrailingExecution && pendingExecutionWithParameters) {\n          fn(...pendingExecutionWithParameters)\n        }\n        inWaitPeriod = false\n        pendingExecutionWithParameters = undefined\n      }, wait)\n    },\n    cancel: () => {\n      clearTimeout(pendingTimeoutId)\n      inWaitPeriod = false\n      pendingExecutionWithParameters = undefined\n    },\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nexport function noop() {}\n"
  },
  {
    "path": "packages/core/src/tools/utils/numberUtils.spec.ts",
    "content": "import { performDraw, round } from './numberUtils'\n\ndescribe('numberUtils', () => {\n  it('should perform a draw', () => {\n    let random = 0\n    spyOn(Math, 'random').and.callFake(() => random)\n\n    expect(performDraw(0)).toBe(false)\n    expect(performDraw(100)).toEqual(true)\n\n    random = 1\n    expect(performDraw(100)).toEqual(true)\n\n    random = 0.0001\n    expect(performDraw(0.01)).toEqual(true)\n\n    random = 0.1\n    expect(performDraw(0.01)).toEqual(false)\n  })\n\n  it('should round', () => {\n    expect(round(10.12591, 0)).toEqual(10)\n    expect(round(10.12591, 1)).toEqual(10.1)\n    expect(round(10.12591, 2)).toEqual(10.13)\n    expect(round(10.12591, 3)).toEqual(10.126)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/numberUtils.ts",
    "content": "/**\n * Return true if the draw is successful\n *\n * @param threshold - Threshold between 0 and 100\n */\nexport function performDraw(threshold: number): boolean {\n  return threshold !== 0 && Math.random() * 100 <= threshold\n}\n\nexport function round(num: number, decimals: 0 | 1 | 2 | 3 | 4) {\n  return +num.toFixed(decimals)\n}\n\nexport function isPercentage(value: unknown) {\n  return isNumber(value) && value >= 0 && value <= 100\n}\n\nexport function isNumber(value: unknown): value is number {\n  return typeof value === 'number'\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/objectUtils.ts",
    "content": "export function tryJsonParse<T = unknown>(text: string): T | undefined {\n  try {\n    return JSON.parse(text) as T\n  } catch {\n    // ignore\n  }\n}\n\nexport function shallowClone<T>(object: T): T & Record<string, never> {\n  return { ...object } as T & Record<string, never>\n}\n\nexport function objectHasValue<T extends { [key: string]: unknown }>(object: T, value: unknown): value is T[keyof T] {\n  return Object.keys(object).some((key) => object[key] === value)\n}\n\nexport function isEmptyObject(object: object) {\n  return Object.keys(object).length === 0\n}\n\nexport function mapValues<A, B>(object: { [key: string]: A }, fn: (arg: A) => B) {\n  const newObject: { [key: string]: B } = {}\n  for (const key of Object.keys(object)) {\n    newObject[key] = fn(object[key])\n  }\n  return newObject\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/polyfills.ts",
    "content": "export function findLast<T, S extends T>(\n  array: readonly T[],\n  predicate: (item: T, index: number, array: readonly T[]) => item is S\n): S | undefined {\n  for (let i = array.length - 1; i >= 0; i -= 1) {\n    const item = array[i]\n    if (predicate(item, i, array)) {\n      return item\n    }\n  }\n  return undefined\n}\n\n// Keep the following wrapper functions as it can be mangled and will result in smaller bundle size that using\n// the native Object.values and Object.entries directly\n\nexport function objectValues<T = unknown>(object: { [key: string]: T }) {\n  return Object.values(object)\n}\n\nexport function objectEntries<T = unknown>(object: { [key: string]: T }): Array<[string, T]> {\n  return Object.entries(object)\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/responseUtils.ts",
    "content": "export function isServerError(status: number) {\n  return status >= 500\n}\n\nexport function tryToClone(response: Response): Response | undefined {\n  try {\n    return response.clone()\n  } catch {\n    // clone can throw if the response has already been used by another instrumentation or is disturbed\n    return\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/stringUtils.spec.ts",
    "content": "import {\n  safeTruncate,\n  findCommaSeparatedValue,\n  findCommaSeparatedValues,\n  findAllCommaSeparatedValues,\n} from './stringUtils'\n\ndescribe('stringUtils', () => {\n  describe('safeTruncate', () => {\n    it('should truncate a string', () => {\n      const truncated = safeTruncate('1234😎7890', 6)\n      expect(truncated.length).toBe(6)\n      expect(truncated).toBe('1234😎')\n    })\n\n    it('should not break a surrogate characters pair', () => {\n      const truncated = safeTruncate('12345😎890', 6)\n      expect(truncated.length).toBe(7)\n      expect(truncated).toBe('12345😎')\n    })\n\n    it('should add the suffix when the string is truncated', () => {\n      const truncated = safeTruncate('12345😎890', 6, '...')\n      expect(truncated).toBe('12345😎...')\n    })\n\n    it('should not add the suffix when the string is not truncated', () => {\n      const truncated = safeTruncate('1234😎', 5, '...')\n      expect(truncated).toBe('1234😎')\n    })\n  })\n\n  describe('findCommaSeparatedValue', () => {\n    it('returns the value from a comma separated hash', () => {\n      expect(findCommaSeparatedValue('foo=a;bar=b', 'foo')).toBe('a')\n      expect(findCommaSeparatedValue('foo=a;bar=b', 'bar')).toBe('b')\n    })\n\n    it('is white-spaces tolerant', () => {\n      expect(findCommaSeparatedValue('   foo  =   a;  bar  =   b', 'foo')).toBe('a')\n      expect(findCommaSeparatedValue('   foo  =   a;  bar  =   b', 'bar')).toBe('b')\n    })\n\n    it('supports values containing an = character', () => {\n      expect(findCommaSeparatedValue('foo=a=b', 'foo')).toBe('a=b')\n    })\n\n    it('supports names containing `-`', () => {\n      expect(findCommaSeparatedValue('foo-bar=baz', 'foo-bar')).toBe('baz')\n    })\n\n    it('supports names containing special characters', () => {\n      // See https://stackoverflow.com/a/1969339\n      // See RFC2616 section 2.2: https://www.ietf.org/rfc/rfc2616.txt\n      // See RFC6265 section 4.1.1: https://www.ietf.org/rfc/rfc6265.txt\n      const allAllowedSpecialCharacters = \"!#$%&'*+-.^_`|~\"\n      expect(findCommaSeparatedValue(`${allAllowedSpecialCharacters}=baz`, allAllowedSpecialCharacters)).toBe('baz')\n    })\n\n    it('returns undefined if the value is not found', () => {\n      expect(findCommaSeparatedValue('foo=a;bar=b', 'baz')).toBe(undefined)\n    })\n\n    it('returns undefined if the value is empty', () => {\n      expect(findCommaSeparatedValue('foo=', 'foo')).toBe(undefined)\n    })\n  })\n\n  describe('findCommaSeparatedValues', () => {\n    it('returns the values from a comma separated hash', () => {\n      const expectedValues = new Map<string, string>()\n      expectedValues.set('foo', 'a')\n      expectedValues.set('bar', 'b')\n      expect(findCommaSeparatedValues('foo=a;bar=b')).toEqual(expectedValues)\n    })\n  })\n\n  describe('findAllCommaSeparatedValues', () => {\n    it('returns all the values from a comma separated hash', () => {\n      const expectedValues = new Map<string, string[]>()\n      expectedValues.set('foo', ['a', 'c'])\n      expectedValues.set('bar', ['b'])\n      expect(findAllCommaSeparatedValues('foo=a;bar=b;foo=c')).toEqual(expectedValues)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/stringUtils.ts",
    "content": "/**\n * UUID v4\n * from https://gist.github.com/jed/982883\n */\nexport function generateUUID(placeholder?: string): string {\n  return placeholder\n    ? // eslint-disable-next-line  no-bitwise\n      (parseInt(placeholder, 10) ^ ((Math.random() * 16) >> (parseInt(placeholder, 10) / 4))).toString(16)\n    : `${1e7}-${1e3}-${4e3}-${8e3}-${1e11}`.replace(/[018]/g, generateUUID)\n}\n\n// Assuming input string is following the HTTP Cookie format defined in\n// https://www.ietf.org/rfc/rfc2616.txt and https://www.ietf.org/rfc/rfc6265.txt, we don't need to\n// be too strict with this regex.\nconst COMMA_SEPARATED_KEY_VALUE = /(\\S+?)\\s*=\\s*(.+?)(?:;|$)/g\n\n/**\n * Returns the value of the key with the given name\n * If there are multiple values with the same key, returns the first one\n */\nexport function findCommaSeparatedValue(rawString: string, name: string): string | undefined {\n  COMMA_SEPARATED_KEY_VALUE.lastIndex = 0\n  while (true) {\n    const match = COMMA_SEPARATED_KEY_VALUE.exec(rawString)\n    if (match) {\n      if (match[1] === name) {\n        return match[2]\n      }\n    } else {\n      break\n    }\n  }\n}\n\n/**\n * Returns a map of all the values with the given key\n * If there are multiple values with the same key, returns all the values\n */\nexport function findAllCommaSeparatedValues(rawString: string): Map<string, string[]> {\n  const result = new Map<string, string[]>()\n  COMMA_SEPARATED_KEY_VALUE.lastIndex = 0\n  while (true) {\n    const match = COMMA_SEPARATED_KEY_VALUE.exec(rawString)\n    if (match) {\n      const key = match[1]\n      const value = match[2]\n      if (result.has(key)) {\n        result.get(key)!.push(value)\n      } else {\n        result.set(key, [value])\n      }\n    } else {\n      break\n    }\n  }\n  return result\n}\n\n/**\n * Returns a map of the values with the given key\n * ⚠️ If there are multiple values with the same key, returns the LAST one\n *\n * @deprecated use `findAllCommaSeparatedValues()` instead\n */\nexport function findCommaSeparatedValues(rawString: string): Map<string, string> {\n  const result = new Map<string, string>()\n  COMMA_SEPARATED_KEY_VALUE.lastIndex = 0\n  while (true) {\n    const match = COMMA_SEPARATED_KEY_VALUE.exec(rawString)\n    if (match) {\n      result.set(match[1], match[2])\n    } else {\n      break\n    }\n  }\n  return result\n}\n\nexport function safeTruncate(candidate: string, length: number, suffix = '') {\n  const lastChar = candidate.charCodeAt(length - 1)\n  const isLastCharSurrogatePair = lastChar >= 0xd800 && lastChar <= 0xdbff\n  const correctedLength = isLastCharSurrogatePair ? length + 1 : length\n\n  if (candidate.length <= correctedLength) {\n    return candidate\n  }\n\n  return `${candidate.slice(0, correctedLength)}${suffix}`\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/timeUtils.ts",
    "content": "import { isNumber, round } from './numberUtils'\n\nexport const ONE_SECOND = 1000\nexport const ONE_MINUTE = 60 * ONE_SECOND\nexport const ONE_HOUR = 60 * ONE_MINUTE\nexport const ONE_DAY = 24 * ONE_HOUR\nexport const ONE_YEAR = 365 * ONE_DAY\n\nexport type Duration = number & { d: 'Duration in ms' }\nexport type ServerDuration = number & { s: 'Duration in ns' }\nexport type TimeStamp = number & { t: 'Epoch time' }\nexport type RelativeTime = number & { r: 'Time relative to navigation start' } & { d: 'Duration in ms' }\nexport interface ClocksState {\n  relative: RelativeTime\n  timeStamp: TimeStamp\n}\n\nexport function relativeToClocks(relative: RelativeTime) {\n  return { relative, timeStamp: getCorrectedTimeStamp(relative) }\n}\n\nexport function timeStampToClocks(timeStamp: TimeStamp) {\n  return { relative: getRelativeTime(timeStamp), timeStamp }\n}\n\nfunction getCorrectedTimeStamp(relativeTime: RelativeTime) {\n  const correctedOrigin = (dateNow() - performance.now()) as TimeStamp\n  // apply correction only for positive drift\n  if (correctedOrigin > getNavigationStart()) {\n    return Math.round(addDuration(correctedOrigin, relativeTime)) as TimeStamp\n  }\n  return getTimeStamp(relativeTime)\n}\n\nexport function currentDrift() {\n  return Math.round(dateNow() - addDuration(getNavigationStart(), performance.now() as Duration))\n}\n\nexport function toServerDuration(duration: Duration): ServerDuration\nexport function toServerDuration(duration: Duration | undefined): ServerDuration | undefined\nexport function toServerDuration(duration: Duration | undefined) {\n  if (!isNumber(duration)) {\n    return duration\n  }\n  return round(duration * 1e6, 0) as ServerDuration\n}\n\nexport function dateNow() {\n  // Do not use `Date.now` because sometimes websites are wrongly \"polyfilling\" it. For example, we\n  // had some users using a very old version of `datejs`, which patched `Date.now` to return a Date\n  // instance instead of a timestamp[1]. Those users are unlikely to fix this, so let's handle this\n  // case ourselves.\n  // [1]: https://github.com/datejs/Datejs/blob/97f5c7c58c5bc5accdab8aa7602b6ac56462d778/src/core-debug.js#L14-L16\n  return new Date().getTime()\n}\n\nexport function timeStampNow() {\n  return dateNow() as TimeStamp\n}\n\nexport function relativeNow() {\n  return performance.now() as RelativeTime\n}\n\nexport function clocksNow() {\n  return { relative: relativeNow(), timeStamp: timeStampNow() }\n}\n\nexport function clocksOrigin() {\n  return { relative: 0 as RelativeTime, timeStamp: getNavigationStart() }\n}\n\nexport function elapsed(start: TimeStamp, end: TimeStamp): Duration\nexport function elapsed(start: RelativeTime, end: RelativeTime): Duration\nexport function elapsed(start: number, end: number) {\n  return (end - start) as Duration\n}\n\nexport function addDuration(a: TimeStamp, b: Duration): TimeStamp\nexport function addDuration(a: RelativeTime, b: Duration): RelativeTime\nexport function addDuration(a: Duration, b: Duration): Duration\nexport function addDuration(a: number, b: number) {\n  return a + b\n}\n\n// Get the time since the navigation was started.\nexport function getRelativeTime(timestamp: TimeStamp) {\n  return (timestamp - getNavigationStart()) as RelativeTime\n}\n\nexport function getTimeStamp(relativeTime: RelativeTime) {\n  return Math.round(addDuration(getNavigationStart(), relativeTime)) as TimeStamp\n}\n\nexport function looksLikeRelativeTime(time: RelativeTime | TimeStamp): time is RelativeTime {\n  return time < ONE_YEAR\n}\n\n/**\n * Navigation start slightly change on some rare cases\n */\nlet navigationStart: TimeStamp | undefined\n\n/**\n * Notes: this does not use `performance.timeOrigin` because:\n * - It doesn't seem to reflect the actual time on which the navigation has started: it may be much farther in the past,\n * at least in Firefox 71. (see: https://bugzilla.mozilla.org/show_bug.cgi?id=1429926)\n * - It is not supported in Safari <15\n */\nfunction getNavigationStart() {\n  if (navigationStart === undefined) {\n    // ServiceWorkers do not support navigationStart (it's deprecated), so we fallback to timeOrigin\n    navigationStart = (performance.timing?.navigationStart ?? performance.timeOrigin) as TimeStamp\n  }\n\n  return navigationStart\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/timezone.ts",
    "content": "export function getTimeZone() {\n  try {\n    const intl = new Intl.DateTimeFormat()\n\n    return intl.resolvedOptions().timeZone\n  } catch {\n    return undefined\n  }\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/typeUtils.spec.ts",
    "content": "import { getType, isIndexableObject } from './typeUtils'\n\ndescribe('typeUtils', () => {\n  describe('getType', () => {\n    it('should return \"null\" for null value', () => {\n      expect(getType(null)).toEqual('null')\n      expect(getType(undefined)).not.toEqual('null')\n    })\n\n    it('should return \"array\" for array value', () => {\n      expect(getType([])).toEqual('array')\n      expect(getType([1, 2, 3])).toEqual('array')\n      expect(getType([1, 2, [3, 4, 5]])).toEqual('array')\n    })\n\n    it('should return result of typeof operator for other types', () => {\n      expect(getType({})).toEqual('object')\n      expect(getType(() => null)).toEqual('function')\n      expect(getType('test')).toEqual('string')\n      expect(getType(1)).toEqual('number')\n      expect(getType(false)).toEqual('boolean')\n      expect(getType(new Date())).toEqual('object')\n    })\n  })\n\n  describe('isIndexableObject', () => {\n    it('returns true for plain objects', () => {\n      expect(isIndexableObject({})).toBeTrue()\n    })\n\n    it('returns false for primitives', () => {\n      expect(isIndexableObject(null)).toBeFalse()\n      expect(isIndexableObject(undefined)).toBeFalse()\n      expect(isIndexableObject('')).toBeFalse()\n      expect(isIndexableObject(0)).toBeFalse()\n      expect(isIndexableObject(false)).toBeFalse()\n    })\n\n    it(\"returned value don't matter too much for non-plain objects\", () => {\n      // This test assertions are not strictly relevent. The goal of this function is to be able to\n      // use the value as a plain object. Using an array or a date as a plain object is fine, but\n      // it doesn't make much sense, so we don't really care.\n      expect(isIndexableObject([])).toBeFalse()\n      expect(isIndexableObject(new Date())).toBeTrue()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/typeUtils.ts",
    "content": "/**\n * Similar to `typeof`, but distinguish plain objects from `null` and arrays\n */\nexport function getType(value: unknown) {\n  if (value === null) {\n    return 'null'\n  }\n  if (Array.isArray(value)) {\n    return 'array'\n  }\n  return typeof value\n}\n\n/**\n * Checks whether a value can have properties. Use this when you have an unknown value and you want\n * to access its properties as unknown. This is a friendly solution for dealing with unknown objects\n * in TypeScript.\n *\n * This function is intended to be used on values that will be used as \"plain objects\", i.e. not\n * Array, Date, RegExp or other class instances. But it's safe to use on any value.\n *\n * @example\n * ```\n * // Before:\n * if (typeof value === 'object' && value !== null && 'property' in value && typeof value.property === 'string') {\n *   // use value.property\n * }\n * // After:\n * if (isIndexableObject(value) && typeof value.property === 'string') {\n *   // use value.property\n * }\n * ```\n */\nexport function isIndexableObject(value: unknown): value is Record<any, unknown> {\n  return getType(value) === 'object'\n}\n"
  },
  {
    "path": "packages/core/src/tools/utils/urlPolyfill.spec.ts",
    "content": "import { buildUrl, getPathName, isValidUrl, normalizeUrl, getPristineWindow } from './urlPolyfill'\n\ndescribe('normalize url', () => {\n  it('should resolve absolute paths', () => {\n    expect(normalizeUrl('/my/path')).toEqual(`${location.origin}/my/path`)\n  })\n\n  it('should resolve relative paths', () => {\n    history.pushState({}, '', '/foo/')\n    expect(normalizeUrl('./my/path')).toEqual(`${location.origin}/foo/my/path`)\n  })\n\n  it('should add protocol to relative url', () => {\n    expect(normalizeUrl('//foo.com:9876/my/path')).toEqual('http://foo.com:9876/my/path')\n  })\n\n  it('should keep full url unchanged', () => {\n    expect(normalizeUrl('https://foo.com/my/path')).toEqual('https://foo.com/my/path')\n  })\n\n  it('should keep non http url unchanged', () => {\n    expect(normalizeUrl('ftp://foo.com/my/path')).toEqual('ftp://foo.com/my/path')\n  })\n\n  it('should keep file url unchanged', () => {\n    // On firefox, URL host is empty for file URI: 'https://bugzilla.mozilla.org/show_bug.cgi?id=1578787'\n    // In some cases, Mobile Safari also have this issue.\n    // As we should follow the browser behavior, having one or the other doesn't matter too much, so\n    // let's check for both.\n    expect(['file:///my/path', 'file://foo.com/my/path']).toContain(normalizeUrl('file://foo.com/my/path'))\n  })\n})\n\ndescribe('isValidUrl', () => {\n  it('should ensure url is valid', () => {\n    expect(isValidUrl('http://www.datadoghq.com')).toBe(true)\n    expect(isValidUrl('http://www.datadoghq.com/foo/bar?a=b#hello')).toBe(true)\n    expect(isValidUrl('file:///www.datadoghq.com')).toBe(true)\n    expect(isValidUrl('/plop')).toBe(false)\n    expect(isValidUrl('')).toBe(false)\n  })\n\n  it('should return the same result if the URL has been wrongfully overridden between calls', () => {\n    expect(isValidUrl('http://www.datadoghq.com')).toBe(true)\n    spyOn(window, 'URL').and.throwError('wrong URL override')\n    expect(isValidUrl('http://www.datadoghq.com')).toBe(true)\n  })\n})\n\ndescribe('getPathName', () => {\n  it('should retrieve url path name', () => {\n    expect(getPathName('http://www.datadoghq.com')).toBe('/')\n    expect(getPathName('http://www.datadoghq.com/foo/bar?a=b#hello')).toBe('/foo/bar')\n    expect(getPathName('file://foo.com/bar?a=b#hello')).toBe('/bar')\n  })\n})\n\ndescribe('buildUrl', () => {\n  it('should normalize href for absolute URLs', () => {\n    expect(buildUrl('http://foo.com').href).toBe('http://foo.com/')\n    expect(buildUrl('http://foo.com:8080').href).toBe('http://foo.com:8080/')\n    expect(buildUrl('http://foo.com:80').href).toBe('http://foo.com/')\n    expect(buildUrl('https://foo.com:443').href).toBe('https://foo.com/')\n\n    expect(['file:///my/path', 'file://foo.com/my/path']).toContain(buildUrl('file://foo.com/my/path').href)\n  })\n\n  it('should normalize href for relative URLs', () => {\n    expect(buildUrl('./bar', 'http://foo.com').href).toBe('http://foo.com/bar')\n    expect(buildUrl('/bar', 'http://foo.com').href).toBe('http://foo.com/bar')\n\n    expect(buildUrl('./bar', 'http://foo.com/foo').href).toBe('http://foo.com/bar')\n    expect(buildUrl('/bar', 'http://foo.com/foo').href).toBe('http://foo.com/bar')\n\n    expect(buildUrl('./bar', 'http://foo.com/foo/').href).toBe('http://foo.com/foo/bar')\n    expect(buildUrl('/bar', 'http://foo.com/foo/').href).toBe('http://foo.com/bar')\n\n    expect(['file:///bar', 'file://foo.com/bar']).toContain(buildUrl('./bar', 'file://foo.com/faa').href)\n    expect(['file:///bar', 'file://foo.com/bar']).toContain(buildUrl('/bar', 'file://foo.com/faa').href)\n  })\n})\n\ndescribe('getNativeURLFromIframe', () => {\n  it('should get native URL constructor from iframe', () => {\n    const { URL } = getPristineWindow()\n\n    expect(URL).toBeDefined()\n    expect(typeof URL).toBe('function')\n\n    const url = new URL('http://example.com')\n    expect(url.href).toBe('http://example.com/')\n  })\n\n  it('should work even if main window URL is overridden', () => {\n    const originalURL = window.URL\n    ;(window as any).URL = function badURL() {\n      throw new Error('Bad polyfill')\n    }\n    const { URL } = getPristineWindow()\n\n    expect(URL).toBeDefined()\n    expect(typeof URL).toBe('function')\n\n    const url = new URL('http://example.com')\n    expect(url.href).toBe('http://example.com/')\n    ;(window as any).URL = originalURL\n  })\n\n  it('should keep the same constructor and still resolve relative URLs correctly', () => {\n    const { URL: nativeURL1 } = getPristineWindow()\n    expect(nativeURL1).toBeDefined()\n\n    history.pushState({}, '', '/foo/')\n    const url1 = buildUrl('./bar', location.href)\n    expect(url1.href).toBe(`${location.origin}/foo/bar`)\n\n    history.pushState({}, '', '/baz/')\n    const { URL: nativeURL2 } = getPristineWindow()\n    expect(nativeURL2).toBeDefined()\n    expect(nativeURL2).toBe(nativeURL1)\n\n    const url2 = buildUrl('./qux', location.href)\n    expect(url2.href).toBe(`${location.origin}/baz/qux`)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/utils/urlPolyfill.ts",
    "content": "import { globalObject } from '../globalObject'\n\nexport function normalizeUrl(url: string) {\n  return buildUrl(url, location.href).href\n}\n\nexport function isValidUrl(url: string) {\n  try {\n    return !!buildUrl(url)\n  } catch {\n    return false\n  }\n}\n\nexport function getPathName(url: string) {\n  const pathname = buildUrl(url).pathname\n  return pathname[0] === '/' ? pathname : `/${pathname}`\n}\n\nexport function buildUrl(url: string, base?: string) {\n  const { URL } = getPristineWindow()\n\n  try {\n    return base !== undefined ? new URL(url, base) : new URL(url)\n  } catch (error) {\n    throw new Error(`Failed to construct URL: ${String(error)}`)\n  }\n}\n\n/**\n * Get native URL constructor from a clean iframe\n * This avoids polyfill issues by getting the native implementation from a fresh iframe context\n * Falls back to the original URL constructor if iframe approach fails\n */\nlet getPristineGlobalObjectCache: Pick<typeof window, 'URL'> | undefined\n\nexport function getPristineWindow() {\n  if (!getPristineGlobalObjectCache) {\n    let iframe: HTMLIFrameElement | undefined\n    let pristineWindow: Window & typeof globalThis\n    try {\n      iframe = document.createElement('iframe')\n      iframe.style.display = 'none'\n      document.body.appendChild(iframe)\n      pristineWindow = (iframe.contentWindow ?? globalObject) as Window & typeof globalThis\n    } catch {\n      pristineWindow = globalObject as unknown as Window & typeof globalThis\n    }\n    getPristineGlobalObjectCache = {\n      URL: pristineWindow.URL,\n    }\n    iframe?.remove()\n  }\n\n  return getPristineGlobalObjectCache\n}\n"
  },
  {
    "path": "packages/core/src/tools/valueHistory.spec.ts",
    "content": "import type { Clock } from '../../test'\nimport { mockClock } from '../../test'\nimport type { Duration, RelativeTime } from './utils/timeUtils'\nimport { addDuration, ONE_MINUTE } from './utils/timeUtils'\nimport { CLEAR_OLD_VALUES_INTERVAL, type ValueHistory, createValueHistory } from './valueHistory'\n\nconst EXPIRE_DELAY = 10 * ONE_MINUTE\nconst MAX_ENTRIES = 5\n\ndescribe('valueHistory', () => {\n  let valueHistory: ValueHistory<string>\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    valueHistory = createValueHistory({ expireDelay: EXPIRE_DELAY, maxEntries: MAX_ENTRIES })\n  })\n\n  afterEach(() => {\n    valueHistory.stop()\n  })\n\n  describe('find', () => {\n    it('should return undefined when there is no active entry and no startTime', () => {\n      expect(valueHistory.find()).toBeUndefined()\n    })\n\n    it('should return the value of the first active entry when there is no startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime)\n\n      expect(valueHistory.find()).toEqual('foo')\n    })\n\n    it('should return undefined if the most recent entry is closed and no startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime).close(5 as RelativeTime)\n\n      expect(valueHistory.find()).toBeUndefined()\n    })\n\n    it('should return the value of entries matching startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime).close(5 as RelativeTime)\n      valueHistory.add('bar', 5 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('qux', 10 as RelativeTime)\n\n      expect(valueHistory.find(2 as RelativeTime)).toEqual('foo')\n      expect(valueHistory.find(7 as RelativeTime)).toEqual('bar')\n      expect(valueHistory.find(10 as RelativeTime)).toEqual('qux')\n    })\n\n    it('should return undefined when no entries matches startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('bar', 20 as RelativeTime)\n\n      expect(valueHistory.find(15 as RelativeTime)).toBeUndefined()\n    })\n\n    describe('with `option.returnInactive` true', () => {\n      it('should return the value of the closest entry regardless of the being closed', () => {\n        valueHistory.add('foo', 0 as RelativeTime).close(10 as RelativeTime)\n        valueHistory.add('bar', 20 as RelativeTime)\n        expect(valueHistory.find(15 as RelativeTime, { returnInactive: true })).toEqual('foo')\n      })\n    })\n  })\n\n  describe('findAll', () => {\n    it('should return an empty array when there is no active entry and no startTime', () => {\n      expect(valueHistory.findAll()).toEqual([])\n    })\n\n    it('should return all active entry value when there is no startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime)\n      valueHistory.add('bar', 5 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('qux', 10 as RelativeTime)\n\n      expect(valueHistory.findAll()).toEqual(['qux', 'foo'])\n    })\n\n    it('should return the entries of entries matching startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime).close(6 as RelativeTime)\n      valueHistory.add('bar', 5 as RelativeTime).close(8 as RelativeTime)\n      valueHistory.add('qux', 10 as RelativeTime)\n\n      expect(valueHistory.findAll(2 as RelativeTime)).toEqual(['foo'])\n      expect(valueHistory.findAll(5 as RelativeTime)).toEqual(['bar', 'foo'])\n      expect(valueHistory.findAll(7 as RelativeTime)).toEqual(['bar'])\n      expect(valueHistory.findAll(9 as RelativeTime)).toEqual([])\n      expect(valueHistory.findAll(10 as RelativeTime)).toEqual(['qux'])\n    })\n\n    it('should return an empty array when no entry is matching startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('bar', 20 as RelativeTime)\n\n      expect(valueHistory.findAll(15 as RelativeTime)).toEqual([])\n    })\n\n    it('should return all context overlapping with the duration', () => {\n      valueHistory.add('foo', 0 as RelativeTime)\n      valueHistory.add('bar', 5 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('baz', 10 as RelativeTime).close(15 as RelativeTime)\n      valueHistory.add('qux', 15 as RelativeTime)\n\n      expect(valueHistory.findAll(0 as RelativeTime, 20 as Duration)).toEqual(['qux', 'baz', 'bar', 'foo'])\n      expect(valueHistory.findAll(6 as RelativeTime, 5 as Duration)).toEqual(['baz', 'bar', 'foo'])\n      expect(valueHistory.findAll(11 as RelativeTime, 5 as Duration)).toEqual(['qux', 'baz', 'foo'])\n    })\n  })\n\n  describe('getEntries', () => {\n    const END_OF_TIMES = Infinity as RelativeTime\n\n    it('should return an empty array when there is no entry for the given startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('bar', 20 as RelativeTime)\n\n      expect(valueHistory.getEntries(15 as RelativeTime)).toEqual([])\n    })\n\n    it('should return the entries for the given startTime', () => {\n      valueHistory.add('foo', 0 as RelativeTime)\n      valueHistory.add('bar', 5 as RelativeTime).close(10 as RelativeTime)\n      valueHistory.add('qux', 5 as RelativeTime).close(15 as RelativeTime)\n      valueHistory.add('baz', 10 as RelativeTime)\n\n      expect(valueHistory.getEntries(0 as RelativeTime)).toEqual([\n        {\n          value: 'foo',\n          startTime: 0 as RelativeTime,\n          endTime: END_OF_TIMES,\n          remove: jasmine.any(Function),\n          close: jasmine.any(Function),\n        },\n      ])\n      expect(valueHistory.getEntries(5 as RelativeTime)).toEqual([\n        {\n          value: 'qux',\n          startTime: 5 as RelativeTime,\n          endTime: 15 as RelativeTime,\n          remove: jasmine.any(Function),\n          close: jasmine.any(Function),\n        },\n        {\n          value: 'bar',\n          startTime: 5 as RelativeTime,\n          endTime: 10 as RelativeTime,\n          remove: jasmine.any(Function),\n          close: jasmine.any(Function),\n        },\n      ])\n      expect(valueHistory.getEntries(10 as RelativeTime)).toEqual([\n        {\n          value: 'baz',\n          startTime: 10 as RelativeTime,\n          endTime: END_OF_TIMES,\n          remove: jasmine.any(Function),\n          close: jasmine.any(Function),\n        },\n      ])\n    })\n  })\n\n  describe('removing entries', () => {\n    it('should not return removed entries', () => {\n      valueHistory.add('foo', 0 as RelativeTime).remove()\n      expect(valueHistory.find()).toBeUndefined()\n    })\n\n    it('removing an entry twice should not impact other entries', () => {\n      valueHistory.add('bar', 5 as RelativeTime)\n      const entry = valueHistory.add('foo', 0 as RelativeTime)\n      entry.remove()\n      entry.remove()\n      expect(valueHistory.find()).toEqual('bar')\n    })\n  })\n\n  it('should reset values', () => {\n    valueHistory.add('foo', 0 as RelativeTime).close(10 as RelativeTime)\n    valueHistory.add('bar', 10 as RelativeTime)\n\n    valueHistory.reset()\n\n    expect(valueHistory.find()).toBeUndefined()\n    expect(valueHistory.find(0 as RelativeTime)).toBeUndefined()\n  })\n\n  describe('clearing old values', () => {\n    it('should clear old values after expiration', () => {\n      const originalTime = performance.now() as RelativeTime\n      valueHistory.add('foo', originalTime).close(addDuration(originalTime, 10 as Duration))\n      clock.tick(10)\n\n      expect(valueHistory.find(originalTime)).toBeDefined()\n\n      clock.tick(EXPIRE_DELAY + CLEAR_OLD_VALUES_INTERVAL)\n\n      expect(valueHistory.find(originalTime)).toBeUndefined()\n    })\n\n    it('should clear multiple histories at the same time to avoid race condition', () => {\n      const delay = 5\n      const originalTime = performance.now() as RelativeTime\n\n      const valueHistory1 = createValueHistory({ expireDelay: EXPIRE_DELAY })\n      clock.tick(delay)\n      const valueHistory2 = createValueHistory({ expireDelay: EXPIRE_DELAY })\n\n      valueHistory1.add('foo', originalTime).close(addDuration(originalTime, 10 as Duration))\n      valueHistory2.add('bar', originalTime).close(addDuration(originalTime, 10 as Duration))\n\n      expect(valueHistory1.find(originalTime)).toBeDefined()\n      expect(valueHistory2.find(originalTime)).toBeDefined()\n\n      clock.tick(EXPIRE_DELAY + CLEAR_OLD_VALUES_INTERVAL - delay)\n\n      expect(valueHistory1.find(originalTime)).toBeUndefined()\n      expect(valueHistory2.find(originalTime)).toBeUndefined()\n\n      valueHistory1.stop()\n      valueHistory2.stop()\n    })\n  })\n\n  it('should limit the number of entries', () => {\n    for (let i = 0; i < MAX_ENTRIES + 1; i++) {\n      valueHistory.add(`${i}`, 0 as RelativeTime)\n    }\n    const values = valueHistory.findAll()\n    expect(values.length).toEqual(5)\n    expect(values).toEqual(['5', '4', '3', '2', '1'])\n  })\n})\n"
  },
  {
    "path": "packages/core/src/tools/valueHistory.ts",
    "content": "import { setInterval, clearInterval } from './timer'\nimport type { TimeoutId } from './timer'\nimport { removeItem } from './utils/arrayUtils'\nimport type { Duration, RelativeTime } from './utils/timeUtils'\nimport { addDuration, relativeNow, ONE_MINUTE } from './utils/timeUtils'\n\nconst END_OF_TIMES = Infinity as RelativeTime\n\nexport interface ValueHistoryEntry<T> {\n  startTime: RelativeTime\n  endTime: RelativeTime\n  value: T\n  remove(): void\n  close(endTime: RelativeTime): void\n}\n\nexport const CLEAR_OLD_VALUES_INTERVAL = ONE_MINUTE\n\n/**\n * Store and keep track of values spans. This whole cache assumes that values are added in\n * chronological order (i.e. all entries have an increasing start time).\n */\nexport interface ValueHistory<Value> {\n  add: (value: Value, startTime: RelativeTime) => ValueHistoryEntry<Value>\n  find: (startTime?: RelativeTime, options?: { returnInactive: boolean }) => Value | undefined\n\n  closeActive: (endTime: RelativeTime) => void\n  findAll: (startTime?: RelativeTime, duration?: Duration) => Value[]\n  getEntries: (startTime: RelativeTime) => Array<ValueHistoryEntry<Value>>\n  reset: () => void\n  stop: () => void\n}\n\nlet cleanupHistoriesInterval: TimeoutId | undefined\n\nconst cleanupTasks: Set<() => void> = new Set()\n\nfunction cleanupHistories() {\n  cleanupTasks.forEach((task) => task())\n}\n\nexport function createValueHistory<Value>({\n  expireDelay,\n  maxEntries,\n}: {\n  expireDelay: number\n  maxEntries?: number\n}): ValueHistory<Value> {\n  let entries: Array<ValueHistoryEntry<Value>> = []\n\n  if (!cleanupHistoriesInterval) {\n    cleanupHistoriesInterval = setInterval(() => cleanupHistories(), CLEAR_OLD_VALUES_INTERVAL)\n  }\n\n  const clearExpiredValues = () => {\n    const oldTimeThreshold = relativeNow() - expireDelay\n    while (entries.length > 0 && entries[entries.length - 1].endTime < oldTimeThreshold) {\n      entries.pop()\n    }\n  }\n\n  cleanupTasks.add(clearExpiredValues)\n\n  /**\n   * Add a value to the history associated with a start time. Returns a reference to this newly\n   * added entry that can be removed or closed.\n   */\n  function add(value: Value, startTime: RelativeTime): ValueHistoryEntry<Value> {\n    const entry: ValueHistoryEntry<Value> = {\n      value,\n      startTime,\n      endTime: END_OF_TIMES,\n      remove: () => {\n        removeItem(entries, entry)\n      },\n      close: (endTime: RelativeTime) => {\n        entry.endTime = endTime\n      },\n    }\n\n    if (maxEntries && entries.length >= maxEntries) {\n      entries.pop()\n    }\n\n    entries.unshift(entry)\n\n    return entry\n  }\n\n  /**\n   * Return the latest value that was active during `startTime`, or the currently active value\n   * if no `startTime` is provided. This method assumes that entries are not overlapping.\n   *\n   * If `option.returnInactive` is true, returns the value at `startTime` (active or not).\n   */\n  function find(\n    startTime: RelativeTime = END_OF_TIMES,\n    options: { returnInactive: boolean } = { returnInactive: false }\n  ): Value | undefined {\n    for (const entry of entries) {\n      if (entry.startTime <= startTime) {\n        if (options.returnInactive || startTime <= entry.endTime) {\n          return entry.value\n        }\n        break\n      }\n    }\n  }\n\n  /**\n   * Helper function to close the currently active value, if any. This method assumes that entries\n   * are not overlapping.\n   */\n  function closeActive(endTime: RelativeTime) {\n    const latestEntry = entries[0]\n    if (latestEntry && latestEntry.endTime === END_OF_TIMES) {\n      latestEntry.close(endTime)\n    }\n  }\n\n  /**\n   * Return all values with an active period overlapping with the duration,\n   * or all values that were active during `startTime` if no duration is provided,\n   * or all currently active values if no `startTime` is provided.\n   */\n  function findAll(startTime: RelativeTime = END_OF_TIMES, duration = 0 as Duration): Value[] {\n    const endTime = addDuration(startTime, duration)\n    return entries\n      .filter((entry) => entry.startTime <= endTime && startTime <= entry.endTime)\n      .map((entry) => entry.value)\n  }\n\n  /**\n   * Return all the entries whose start time is equal to the given startTime.\n   */\n  function getEntries(startTime: RelativeTime): Array<ValueHistoryEntry<Value>> {\n    return entries.filter((entry) => entry.startTime === startTime)\n  }\n\n  /**\n   * Remove all entries from this collection.\n   */\n  function reset() {\n    entries = []\n  }\n\n  /**\n   * Stop internal garbage collection of past entries.\n   */\n  function stop() {\n    cleanupTasks.delete(clearExpiredValues)\n    if (cleanupTasks.size === 0 && cleanupHistoriesInterval) {\n      clearInterval(cleanupHistoriesInterval)\n      cleanupHistoriesInterval = undefined\n    }\n  }\n\n  return { add, find, closeActive, findAll, getEntries, reset, stop }\n}\n\n/**\n * Reset all global state. This is useful for testing to ensure clean state between tests.\n *\n * @internal\n */\nexport function resetValueHistoryGlobals() {\n  cleanupTasks.clear()\n  clearInterval(cleanupHistoriesInterval)\n  cleanupHistoriesInterval = undefined\n}\n"
  },
  {
    "path": "packages/core/src/transport/batch.spec.ts",
    "content": "import { Observable } from '..'\nimport type { MockFlushController } from '../../test'\nimport { createMockFlushController } from '../../test'\nimport { display } from '../tools/display'\nimport type { Encoder } from '../tools/encoder'\nimport { createIdentityEncoder } from '../tools/encoder'\nimport { createBatch, MESSAGE_BYTES_LIMIT, type Batch } from './batch'\nimport type { HttpRequest, HttpRequestEvent } from './httpRequest'\n\ndescribe('batch', () => {\n  const BIG_MESSAGE_OVER_BYTES_LIMIT = { message: 'x'.repeat(MESSAGE_BYTES_LIMIT + 1) }\n  const SMALL_MESSAGE = { message: 'hello' }\n  const SMALL_MESSAGE_BYTES_COUNT = 19\n  const SEPARATOR_BYTES_COUNT = 1\n\n  let batch: Batch\n  let transport: {\n    observable: Observable<HttpRequestEvent>\n    send: jasmine.Spy<HttpRequest['send']>\n    sendOnExit: jasmine.Spy<HttpRequest['sendOnExit']>\n  }\n\n  let flushController: MockFlushController\n  let encoder: Encoder<string>\n\n  beforeEach(() => {\n    transport = {\n      observable: new Observable<HttpRequestEvent>(),\n      send: jasmine.createSpy(),\n      sendOnExit: jasmine.createSpy(),\n    } satisfies HttpRequest\n    flushController = createMockFlushController()\n    encoder = createIdentityEncoder()\n    batch = createBatch({ encoder, request: transport, flushController })\n  })\n\n  it('should send a message', () => {\n    batch.add(SMALL_MESSAGE)\n\n    flushController.notifyFlush()\n\n    expect(transport.send.calls.mostRecent().args[0]).toEqual({\n      data: '{\"message\":\"hello\"}',\n      bytesCount: SMALL_MESSAGE_BYTES_COUNT,\n      encoding: undefined,\n    })\n  })\n\n  describe('adding a message', () => {\n    it('should add message to the flush controller', () => {\n      batch.add(SMALL_MESSAGE)\n\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledOnceWith(SMALL_MESSAGE_BYTES_COUNT)\n      expect(flushController.notifyAfterAddMessage).toHaveBeenCalledOnceWith(0)\n    })\n\n    it('should consider separators when adding message', () => {\n      batch.add(SMALL_MESSAGE)\n      batch.add(SMALL_MESSAGE)\n      batch.add(SMALL_MESSAGE)\n\n      expect(flushController.bytesCount).toEqual(\n        SMALL_MESSAGE_BYTES_COUNT +\n          SEPARATOR_BYTES_COUNT +\n          SMALL_MESSAGE_BYTES_COUNT +\n          SEPARATOR_BYTES_COUNT +\n          SMALL_MESSAGE_BYTES_COUNT\n      )\n    })\n\n    it('should remove the estimated message bytes count when replacing a message', () => {\n      batch.add(SMALL_MESSAGE)\n      batch.upsert(SMALL_MESSAGE, 'a')\n\n      flushController.notifyBeforeAddMessage.calls.reset()\n\n      batch.upsert(SMALL_MESSAGE, 'a')\n\n      expect(flushController.notifyAfterRemoveMessage).toHaveBeenCalledOnceWith(SMALL_MESSAGE_BYTES_COUNT)\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledOnceWith(SMALL_MESSAGE_BYTES_COUNT)\n      expect(flushController.bytesCount).toEqual(\n        // Note: contrary to added messages (see test above), we don't take separators into account\n        // when upserting messages, because it's irrelevant: upserted messages size are not yet\n        // encoded so the bytes count is only an estimation\n        SMALL_MESSAGE_BYTES_COUNT + SMALL_MESSAGE_BYTES_COUNT\n      )\n    })\n\n    it('should not send a message with a bytes size above the limit', () => {\n      const warnSpy = spyOn(display, 'warn')\n      batch.add(BIG_MESSAGE_OVER_BYTES_LIMIT)\n\n      expect(warnSpy).toHaveBeenCalled()\n      expect(flushController.notifyBeforeAddMessage).not.toHaveBeenCalled()\n    })\n\n    it('should adjust the message size after the message has been added', () => {\n      const message = { message: '😤' } // JS string length = 2, but 4 bytes once encoded to UTF-8\n      batch.add(message)\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledOnceWith(16)\n      expect(flushController.notifyAfterAddMessage).toHaveBeenCalledOnceWith(2) // 2 more bytes once encoded\n    })\n  })\n\n  it('should upsert a message for a given key', () => {\n    batch.upsert({ message: '1' }, 'a')\n    batch.upsert({ message: '2' }, 'a')\n    batch.upsert({ message: '3' }, 'b')\n    batch.upsert({ message: '4' }, 'c')\n    flushController.notifyFlush()\n\n    expect(transport.send.calls.mostRecent().args[0]).toEqual({\n      data: '{\"message\":\"2\"}\\n{\"message\":\"3\"}\\n{\"message\":\"4\"}',\n      bytesCount: jasmine.any(Number),\n      encoding: undefined,\n    })\n\n    batch.upsert({ message: '5' }, 'c')\n    batch.upsert({ message: '6' }, 'b')\n    batch.upsert({ message: '7' }, 'a')\n    flushController.notifyFlush()\n\n    expect(transport.send.calls.mostRecent().args[0]).toEqual({\n      data: '{\"message\":\"5\"}\\n{\"message\":\"6\"}\\n{\"message\":\"7\"}',\n      bytesCount: jasmine.any(Number),\n      encoding: undefined,\n    })\n\n    batch.upsert({ message: '8' }, 'a')\n    batch.upsert({ message: '9' }, 'b')\n    batch.upsert({ message: '10' }, 'a')\n    batch.upsert({ message: '11' }, 'b')\n    flushController.notifyFlush()\n\n    expect(transport.send.calls.mostRecent().args[0]).toEqual({\n      data: '{\"message\":\"10\"}\\n{\"message\":\"11\"}',\n      bytesCount: jasmine.any(Number),\n      encoding: undefined,\n    })\n  })\n\n  describe('flush messages when the page is not exiting or with a synchronous encoder', () => {\n    it('should send addend and upserted messages in the same request', () => {\n      batch.add({ message: '1' })\n      batch.upsert({ message: '2' }, 'a')\n\n      flushController.notifyFlush()\n\n      expect(transport.send.calls.mostRecent().args[0]).toEqual({\n        data: '{\"message\":\"1\"}\\n{\"message\":\"2\"}',\n        bytesCount: jasmine.any(Number),\n        encoding: undefined,\n      })\n    })\n\n    it('should encode upserted messages', () => {\n      const encoderWriteSpy = spyOn(encoder, 'write')\n\n      batch.upsert({ message: '2' }, 'a')\n\n      flushController.notifyFlush()\n\n      expect(encoderWriteSpy).toHaveBeenCalledOnceWith('{\"message\":\"2\"}')\n    })\n\n    it('should be able to use telemetry in the httpRequest.send', () => {\n      transport.send.and.callFake(() => {\n        addTelemetryDebugFake()\n      })\n      const addTelemetryDebugFake = () => batch.add({ message: 'telemetry message' })\n\n      batch.add({ message: 'normal message' })\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledTimes(1)\n\n      flushController.notifyFlush()\n      expect(transport.send).toHaveBeenCalledTimes(1)\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledTimes(2)\n\n      flushController.notifyFlush()\n      expect(transport.send).toHaveBeenCalledTimes(2)\n    })\n  })\n\n  describe('flush messages when the page is exiting and with an asynchronous encoder', () => {\n    beforeEach(() => {\n      encoder.isAsync = true\n    })\n\n    //\n    ;[\n      {\n        title: 'when adding a message, it should be sent in one request',\n        add: { message: 1 },\n        expectedRequests: ['{\"message\":1}'],\n      },\n      {\n        title: 'when upserting a message, it should be sent in one request',\n        upsert: { message: 1 },\n        expectedRequests: ['{\"message\":1}'],\n      },\n      {\n        title: 'when adding a message and upserting another, they should be sent in two separate requests',\n        add: { message: 1 },\n        upsert: { message: 2 },\n        expectedRequests: ['{\"message\":1}', '{\"message\":2}'],\n      },\n      {\n        title:\n          'when adding a message and another message is still pending, they should be sent in two separate requests',\n        add: { message: 1 },\n        pending: { message: 2 },\n        expectedRequests: ['{\"message\":1}', '{\"message\":2}'],\n      },\n      {\n        title: 'when upserting a message and another message is still pending, they should be sent in one request',\n        upsert: { message: 1 },\n        pending: { message: 2 },\n        expectedRequests: ['{\"message\":2}\\n{\"message\":1}'],\n      },\n    ].forEach(({ title, add, upsert, pending, expectedRequests }) => {\n      it(title, () => {\n        if (add) {\n          batch.add(add)\n        }\n        if (upsert) {\n          batch.upsert(upsert, 'a')\n        }\n        if (pending) {\n          // eslint-disable-next-line @typescript-eslint/unbound-method\n          const original = encoder.finishSync\n          spyOn(encoder, 'finishSync').and.callFake(() => ({\n            ...original(),\n            pendingData: JSON.stringify(pending),\n          }))\n        }\n\n        flushController.notifyFlush('before_unload')\n\n        expect(transport.sendOnExit.calls.allArgs().map(([payload]) => payload.data)).toEqual(expectedRequests)\n      })\n    })\n\n    it('should be able to use telemetry in the httpRequest.sendOnExit', () => {\n      transport.sendOnExit.and.callFake(() => {\n        addTelemetryDebugFake()\n      })\n      const addTelemetryDebugFake = () => batch.add({ message: 'telemetry message' })\n\n      batch.add({ message: 'normal message' })\n      batch.upsert({ message: '2' }, 'a')\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledTimes(2)\n\n      flushController.notifyFlush('before_unload')\n      expect(transport.sendOnExit).toHaveBeenCalledTimes(2)\n      expect(flushController.notifyBeforeAddMessage).toHaveBeenCalledTimes(4)\n\n      flushController.notifyFlush('before_unload')\n      expect(transport.sendOnExit).toHaveBeenCalledTimes(3)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/transport/batch.ts",
    "content": "import { DOCS_TROUBLESHOOTING, MORE_DETAILS, display } from '../tools/display'\nimport type { Context } from '../tools/serialisation/context'\nimport { objectValues } from '../tools/utils/polyfills'\nimport { isPageExitReason } from '../browser/pageMayExitObservable'\nimport { jsonStringify } from '../tools/serialisation/jsonStringify'\nimport type { Encoder, EncoderResult } from '../tools/encoder'\nimport { computeBytesCount, ONE_KIBI_BYTE } from '../tools/utils/byteUtils'\nimport type { HttpRequest, Payload } from './httpRequest'\nimport type { FlushController, FlushEvent } from './flushController'\n\nexport const MESSAGE_BYTES_LIMIT = 256 * ONE_KIBI_BYTE\n\nexport interface Batch {\n  flushController: FlushController\n  add: (message: Context) => void\n  upsert: (message: Context, key: string) => void\n  stop: () => void\n}\n\nexport function createBatch({\n  encoder,\n  request,\n  flushController,\n}: {\n  encoder: Encoder\n  request: HttpRequest\n  flushController: FlushController\n}): Batch {\n  let upsertBuffer: { [key: string]: string } = {}\n  const flushSubscription = flushController.flushObservable.subscribe((event) => flush(event))\n\n  function push(serializedMessage: string, estimatedMessageBytesCount: number, key?: string) {\n    flushController.notifyBeforeAddMessage(estimatedMessageBytesCount)\n\n    if (key !== undefined) {\n      upsertBuffer[key] = serializedMessage\n      flushController.notifyAfterAddMessage()\n    } else {\n      encoder.write(encoder.isEmpty ? serializedMessage : `\\n${serializedMessage}`, (realMessageBytesCount) => {\n        flushController.notifyAfterAddMessage(realMessageBytesCount - estimatedMessageBytesCount)\n      })\n    }\n  }\n\n  function hasMessageFor(key?: string): key is string {\n    return key !== undefined && upsertBuffer[key] !== undefined\n  }\n\n  function remove(key: string) {\n    const removedMessage = upsertBuffer[key]\n    delete upsertBuffer[key]\n    const messageBytesCount = encoder.estimateEncodedBytesCount(removedMessage)\n    flushController.notifyAfterRemoveMessage(messageBytesCount)\n  }\n\n  function addOrUpdate(message: Context, key?: string) {\n    const serializedMessage = jsonStringify(message)!\n\n    const estimatedMessageBytesCount = encoder.estimateEncodedBytesCount(serializedMessage)\n\n    if (estimatedMessageBytesCount >= MESSAGE_BYTES_LIMIT) {\n      display.warn(\n        `Discarded a message whose size was bigger than the maximum allowed size ${MESSAGE_BYTES_LIMIT / ONE_KIBI_BYTE}KiB. ${MORE_DETAILS} ${DOCS_TROUBLESHOOTING}/#technical-limitations`\n      )\n      return\n    }\n\n    if (hasMessageFor(key)) {\n      remove(key)\n    }\n\n    push(serializedMessage, estimatedMessageBytesCount, key)\n  }\n\n  function flush(event: FlushEvent) {\n    const upsertMessages = objectValues(upsertBuffer).join('\\n')\n    upsertBuffer = {}\n\n    const pageMightExit = isPageExitReason(event.reason)\n    const send = pageMightExit ? request.sendOnExit : request.send\n\n    if (\n      pageMightExit &&\n      // Note: checking that the encoder is async is not strictly needed, but it's an optimization:\n      // if the encoder is async we need to send two requests in some cases (one for encoded data\n      // and the other for non-encoded data). But if it's not async, we don't have to worry about\n      // it and always send a single request.\n      encoder.isAsync\n    ) {\n      const encoderResult = encoder.finishSync()\n\n      // Send encoded messages\n      if (encoderResult.outputBytesCount) {\n        send(formatPayloadFromEncoder(encoderResult))\n      }\n\n      // Send messages that are not yet encoded at this point\n      const pendingMessages = [encoderResult.pendingData, upsertMessages].filter(Boolean).join('\\n')\n      if (pendingMessages) {\n        send({\n          data: pendingMessages,\n          bytesCount: computeBytesCount(pendingMessages),\n        })\n      }\n    } else {\n      if (upsertMessages) {\n        encoder.write(encoder.isEmpty ? upsertMessages : `\\n${upsertMessages}`)\n      }\n      encoder.finish((encoderResult) => {\n        send(formatPayloadFromEncoder(encoderResult))\n      })\n    }\n  }\n\n  return {\n    flushController,\n    add: addOrUpdate,\n    upsert: addOrUpdate,\n    stop: flushSubscription.unsubscribe,\n  }\n}\n\nfunction formatPayloadFromEncoder(encoderResult: EncoderResult): Payload {\n  let data: string | Blob\n  if (typeof encoderResult.output === 'string') {\n    data = encoderResult.output\n  } else {\n    data = new Blob([encoderResult.output], {\n      // This will set the 'Content-Type: text/plain' header. Reasoning:\n      // * The intake rejects the request if there is no content type.\n      // * The browser will issue CORS preflight requests if we set it to 'application/json', which\n      // could induce higher intake load (and maybe has other impacts).\n      // * Also it's not quite JSON, since we are concatenating multiple JSON objects separated by\n      // new lines.\n      type: 'text/plain',\n    })\n  }\n\n  return {\n    data,\n    bytesCount: encoderResult.outputBytesCount,\n    encoding: encoderResult.encoding,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/transport/eventBridge.spec.ts",
    "content": "import { mockEventBridge } from '../../test'\nimport { DefaultPrivacyLevel } from '../domain/configuration'\nimport type { BrowserWindowWithEventBridge } from './eventBridge'\nimport { getEventBridge, canUseEventBridge, BridgeCapability, bridgeSupports } from './eventBridge'\n\ndescribe('canUseEventBridge', () => {\n  const allowedWebViewHosts = ['foo.bar']\n\n  it('should detect when the bridge is present and the webView host is allowed', () => {\n    mockEventBridge({ allowedWebViewHosts })\n    expect(canUseEventBridge('foo.bar')).toBeTrue()\n    expect(canUseEventBridge('baz.foo.bar')).toBeTrue()\n    expect(canUseEventBridge('www.foo.bar')).toBeTrue()\n    expect(canUseEventBridge('www.qux.foo.bar')).toBeTrue()\n  })\n\n  it('should not detect when the bridge is present and the webView host is not allowed', () => {\n    mockEventBridge({ allowedWebViewHosts })\n    expect(canUseEventBridge('foo.com')).toBeFalse()\n    expect(canUseEventBridge('foo.bar.baz')).toBeFalse()\n    expect(canUseEventBridge('bazfoo.bar')).toBeFalse()\n  })\n\n  it('should not detect when the bridge on the parent domain if only the subdomain is allowed', () => {\n    mockEventBridge({ allowedWebViewHosts: ['baz.foo.bar'] })\n    expect(canUseEventBridge('foo.bar')).toBeFalse()\n  })\n\n  it('should not detect when the bridge is absent', () => {\n    expect(canUseEventBridge()).toBeFalse()\n  })\n})\n\ndescribe('event bridge send', () => {\n  let sendSpy: jasmine.Spy<(msg: string) => void>\n\n  beforeEach(() => {\n    const eventBridge = mockEventBridge()\n    sendSpy = spyOn(eventBridge, 'send')\n  })\n\n  it('should serialize sent events without view', () => {\n    const eventBridge = getEventBridge()!\n\n    eventBridge.send('view', { foo: 'bar' })\n\n    expect(sendSpy).toHaveBeenCalledOnceWith('{\"eventType\":\"view\",\"event\":{\"foo\":\"bar\"}}')\n  })\n\n  it('should serialize sent events with view', () => {\n    const eventBridge = getEventBridge()!\n\n    eventBridge.send('view', { foo: 'bar' }, '123')\n\n    expect(sendSpy).toHaveBeenCalledOnceWith('{\"eventType\":\"view\",\"event\":{\"foo\":\"bar\"},\"view\":{\"id\":\"123\"}}')\n  })\n})\n\ndescribe('event bridge getPrivacyLevel', () => {\n  const bridgePrivacyLevel = DefaultPrivacyLevel.MASK\n\n  beforeEach(() => {\n    mockEventBridge({ privacyLevel: bridgePrivacyLevel })\n  })\n\n  it('should return the privacy level', () => {\n    const eventBridge = getEventBridge()!\n\n    expect(eventBridge.getPrivacyLevel()).toEqual(bridgePrivacyLevel)\n  })\n\n  it('should return undefined if getPrivacyLevel not present in the bridge', () => {\n    delete (window as BrowserWindowWithEventBridge).DatadogEventBridge?.getPrivacyLevel\n    const eventBridge = getEventBridge()!\n\n    expect(eventBridge.getPrivacyLevel()).toBeUndefined()\n  })\n\n  describe('bridgeSupports', () => {\n    it('should returns true when the bridge supports a capability', () => {\n      mockEventBridge({ capabilities: [BridgeCapability.RECORDS] })\n      expect(bridgeSupports(BridgeCapability.RECORDS)).toBeTrue()\n    })\n\n    it('should returns false when the bridge does not support a capability', () => {\n      mockEventBridge({ capabilities: [] })\n      expect(bridgeSupports(BridgeCapability.RECORDS)).toBeFalse()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/transport/eventBridge.ts",
    "content": "import { getGlobalObject } from '../tools/globalObject'\nimport type { DefaultPrivacyLevel } from '../domain/configuration'\n\nexport interface BrowserWindowWithEventBridge extends Window {\n  DatadogEventBridge?: DatadogEventBridge\n}\n\nexport interface DatadogEventBridge {\n  getCapabilities?(): string\n  getPrivacyLevel?(): DefaultPrivacyLevel\n  getAllowedWebViewHosts(): string\n  send(msg: string): void\n}\n\nexport const enum BridgeCapability {\n  RECORDS = 'records',\n}\n\nexport function getEventBridge<T, E>() {\n  const eventBridgeGlobal = getEventBridgeGlobal()\n\n  if (!eventBridgeGlobal) {\n    return\n  }\n\n  return {\n    getCapabilities() {\n      return JSON.parse(eventBridgeGlobal.getCapabilities?.() || '[]') as BridgeCapability[]\n    },\n    getPrivacyLevel() {\n      return eventBridgeGlobal.getPrivacyLevel?.()\n    },\n    getAllowedWebViewHosts() {\n      return JSON.parse(eventBridgeGlobal.getAllowedWebViewHosts()) as string[]\n    },\n    send(eventType: T, event: E, viewId?: string) {\n      const view = viewId ? { id: viewId } : undefined\n      eventBridgeGlobal.send(JSON.stringify({ eventType, event, view }))\n    },\n  }\n}\n\nexport function bridgeSupports(capability: BridgeCapability): boolean {\n  const bridge = getEventBridge()\n  return !!bridge && bridge.getCapabilities().includes(capability)\n}\n\nexport function canUseEventBridge(currentHost = getGlobalObject<Window>().location?.hostname): boolean {\n  const bridge = getEventBridge()\n\n  return (\n    !!bridge &&\n    bridge\n      .getAllowedWebViewHosts()\n      .some((allowedHost) => currentHost === allowedHost || currentHost.endsWith(`.${allowedHost}`))\n  )\n}\n\nfunction getEventBridgeGlobal() {\n  return getGlobalObject<BrowserWindowWithEventBridge>().DatadogEventBridge\n}\n"
  },
  {
    "path": "packages/core/src/transport/flushController.spec.ts",
    "content": "import type { Clock } from '../../test'\nimport { mockClock } from '../../test'\nimport type { PageMayExitEvent } from '../browser/pageMayExitObservable'\nimport { Observable } from '../tools/observable'\nimport type { FlushController, FlushEvent } from './flushController'\nimport { createFlushController, FLUSH_DURATION_LIMIT, MESSAGES_LIMIT } from './flushController'\nimport { RECOMMENDED_REQUEST_BYTES_LIMIT } from './httpRequest'\n\nconst BYTES_LIMIT = RECOMMENDED_REQUEST_BYTES_LIMIT\n// Arbitrary message size that is below the BYTES_LIMIT\nconst SMALL_MESSAGE_BYTE_COUNT = 2\n\ndescribe('flushController', () => {\n  let clock: Clock\n  let flushController: FlushController\n  let flushSpy: jasmine.Spy<(event: FlushEvent) => void>\n  let pageMayExitObservable: Observable<PageMayExitEvent>\n  let sessionExpireObservable: Observable<void>\n\n  beforeEach(() => {\n    clock = mockClock()\n    pageMayExitObservable = new Observable()\n    sessionExpireObservable = new Observable()\n    flushController = createFlushController({\n      pageMayExitObservable,\n      sessionExpireObservable,\n    })\n    flushSpy = jasmine.createSpy()\n    flushController.flushObservable.subscribe(flushSpy)\n  })\n\n  it('when flushing, the event contains a reason, the bytes count and the messages count', () => {\n    const messagesCount = 3\n    for (let i = 0; i < messagesCount; i += 1) {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n    }\n\n    pageMayExitObservable.notify({ reason: 'before_unload' })\n\n    expect(flushSpy).toHaveBeenCalledOnceWith({\n      reason: jasmine.any(String),\n      bytesCount: messagesCount * SMALL_MESSAGE_BYTE_COUNT,\n      messagesCount,\n    })\n  })\n\n  describe('page exit', () => {\n    it('notifies when the page is exiting', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      pageMayExitObservable.notify({ reason: 'before_unload' })\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('flush reason should be the page exit reason', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      pageMayExitObservable.notify({ reason: 'before_unload' })\n      expect(flushSpy.calls.first().args[0].reason).toBe('before_unload')\n    })\n\n    it('does not notify if no message was added', () => {\n      pageMayExitObservable.notify({ reason: 'before_unload' })\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('notifies when the page is exiting even if no message have been fully added yet', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      pageMayExitObservable.notify({ reason: 'before_unload' })\n      expect(flushSpy).toHaveBeenCalled()\n    })\n  })\n\n  describe('session expire', () => {\n    it('notifies when the session expires', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      sessionExpireObservable.notify()\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('flush reason should be \"session_expire\"', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      sessionExpireObservable.notify()\n      expect(flushSpy.calls.first().args[0].reason).toBe('session_expire')\n    })\n\n    it('does not notify if no message was added', () => {\n      sessionExpireObservable.notify()\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('notifies when the session expires even if no message have been fully added yet', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      sessionExpireObservable.notify()\n      expect(flushSpy).toHaveBeenCalled()\n    })\n  })\n\n  describe('bytes limit', () => {\n    it('uses the page exit reason as flush reason for intermediate flushes during page exit', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n\n      flushController.preparePageExitFlushObservable.subscribe(() => {\n        flushController.notifyBeforeAddMessage(BYTES_LIMIT)\n      })\n\n      pageMayExitObservable.notify({ reason: 'before_unload' })\n\n      expect(flushSpy.calls.first().args[0].reason).toBe('before_unload')\n    })\n\n    it('notifies when the bytes limit is reached after adding a message', () => {\n      flushController.notifyBeforeAddMessage(BYTES_LIMIT)\n      flushController.notifyAfterAddMessage()\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('flush reason should be \"bytes_limit\"', () => {\n      flushController.notifyBeforeAddMessage(BYTES_LIMIT)\n      flushController.notifyAfterAddMessage()\n      expect(flushSpy.calls.first().args[0].reason).toBe('bytes_limit')\n    })\n\n    it('notifies when the bytes limit will be reached before adding a message', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      flushController.notifyBeforeAddMessage(BYTES_LIMIT)\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('does not take removed messages into account', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      flushController.notifyAfterRemoveMessage(SMALL_MESSAGE_BYTE_COUNT)\n\n      flushController.notifyBeforeAddMessage(BYTES_LIMIT - SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not notify when the bytes limit will be reached if no message was added yet', () => {\n      flushController.notifyBeforeAddMessage(BYTES_LIMIT)\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('resets the current bytes count once flushed', () => {\n      flushController.notifyBeforeAddMessage(BYTES_LIMIT)\n      flushController.notifyAfterAddMessage()\n\n      flushSpy.calls.reset()\n\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('messages limit', () => {\n    it('notifies when the messages limit is reached', () => {\n      for (let i = 0; i < MESSAGES_LIMIT; i += 1) {\n        flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n        flushController.notifyAfterAddMessage()\n      }\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('flush reason should be \"messages_limit\"', () => {\n      for (let i = 0; i < MESSAGES_LIMIT; i += 1) {\n        flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n        flushController.notifyAfterAddMessage()\n      }\n      expect(flushSpy.calls.first().args[0].reason).toBe('messages_limit')\n    })\n\n    it('does not flush when the message was not fully added yet', () => {\n      for (let i = 0; i < MESSAGES_LIMIT - 1; i += 1) {\n        flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n        flushController.notifyAfterAddMessage()\n      }\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not take removed messages into account', () => {\n      for (let i = 0; i < MESSAGES_LIMIT - 1; i += 1) {\n        flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n        flushController.notifyAfterAddMessage()\n      }\n\n      flushController.notifyAfterRemoveMessage(SMALL_MESSAGE_BYTE_COUNT)\n\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('resets the messages count when flushed', () => {\n      for (let i = 0; i < MESSAGES_LIMIT; i += 1) {\n        flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n        flushController.notifyAfterAddMessage()\n      }\n\n      flushSpy.calls.reset()\n\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('duration limit', () => {\n    it('notifies when the duration limit is reached after adding a message', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      clock.tick(FLUSH_DURATION_LIMIT)\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('flush reason should be \"duration_limit\"', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      clock.tick(FLUSH_DURATION_LIMIT)\n      expect(flushSpy.calls.first().args[0].reason).toBe('duration_limit')\n    })\n\n    it('does not postpone the duration limit when another message was added', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      clock.tick(FLUSH_DURATION_LIMIT / 2)\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      clock.tick(FLUSH_DURATION_LIMIT / 2)\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('does not notify if no message was added yet', () => {\n      clock.tick(FLUSH_DURATION_LIMIT)\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not notify if a message was added then removed', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      flushController.notifyAfterRemoveMessage(SMALL_MESSAGE_BYTE_COUNT)\n      clock.tick(FLUSH_DURATION_LIMIT)\n      expect(flushSpy).not.toHaveBeenCalled()\n    })\n\n    it('notifies if a message was added, and another was added then removed', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      flushController.notifyAfterRemoveMessage(SMALL_MESSAGE_BYTE_COUNT)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n      expect(flushSpy).toHaveBeenCalled()\n    })\n\n    it('does not notify prematurely if a message was added then removed then another was added', () => {\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      flushController.notifyAfterRemoveMessage(SMALL_MESSAGE_BYTE_COUNT)\n      clock.tick(FLUSH_DURATION_LIMIT / 2)\n      flushController.notifyBeforeAddMessage(SMALL_MESSAGE_BYTE_COUNT)\n      flushController.notifyAfterAddMessage()\n      clock.tick(FLUSH_DURATION_LIMIT / 2)\n      expect(flushSpy).not.toHaveBeenCalled()\n      clock.tick(FLUSH_DURATION_LIMIT / 2)\n      expect(flushSpy).toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/transport/flushController.ts",
    "content": "import type { PageMayExitEvent, PageExitReason } from '../browser/pageMayExitObservable'\nimport { isWorkerEnvironment } from '../tools/globalObject'\nimport { Observable } from '../tools/observable'\nimport type { TimeoutId } from '../tools/timer'\nimport { clearTimeout, setTimeout } from '../tools/timer'\nimport { ONE_SECOND } from '../tools/utils/timeUtils'\nimport type { Duration } from '../tools/utils/timeUtils'\nimport { RECOMMENDED_REQUEST_BYTES_LIMIT } from './httpRequest'\n\nexport type FlushReason = PageExitReason | 'duration_limit' | 'bytes_limit' | 'messages_limit' | 'session_expire'\n\n/**\n * flush automatically, aim to be lower than ALB connection timeout\n * to maximize connection reuse.\n */\nexport const FLUSH_DURATION_LIMIT = (30 * ONE_SECOND) as Duration\n\n/**\n * When using the SDK in a Worker Environment, we limit the batch size to 1 to ensure it can be sent\n * in a single event.\n */\nexport const MESSAGES_LIMIT = isWorkerEnvironment ? 1 : 50\n\nexport type FlushController = ReturnType<typeof createFlushController>\nexport interface FlushEvent {\n  reason: FlushReason\n  bytesCount: number\n  messagesCount: number\n}\n\ninterface FlushControllerOptions {\n  pageMayExitObservable: Observable<PageMayExitEvent>\n  sessionExpireObservable: Observable<void>\n}\n\n/**\n * Returns a \"flush controller\", responsible of notifying when flushing a pool of pending data needs\n * to happen. The implementation is designed to support both synchronous and asynchronous usages,\n * but relies on invariants described in each method documentation to keep a coherent state.\n */\nexport function createFlushController({ pageMayExitObservable, sessionExpireObservable }: FlushControllerOptions) {\n  let forcedFlushReason: FlushReason | undefined\n  const preparePageExitFlushObservable = new Observable<PageExitReason>()\n  const pageMayExitSubscription = pageMayExitObservable.subscribe((event) => {\n    forcedFlushReason = event.reason\n    try {\n      preparePageExitFlushObservable.notify(event.reason)\n    } finally {\n      forcedFlushReason = undefined\n    }\n    flush(event.reason)\n  })\n  const sessionExpireSubscription = sessionExpireObservable.subscribe(() => flush('session_expire'))\n\n  const flushObservable = new Observable<FlushEvent>(() => () => {\n    pageMayExitSubscription.unsubscribe()\n    sessionExpireSubscription.unsubscribe()\n  })\n\n  let currentBytesCount = 0\n  let currentMessagesCount = 0\n\n  function flush(flushReason: FlushReason) {\n    if (currentMessagesCount === 0) {\n      return\n    }\n\n    const messagesCount = currentMessagesCount\n    const bytesCount = currentBytesCount\n\n    currentMessagesCount = 0\n    currentBytesCount = 0\n    cancelDurationLimitTimeout()\n\n    flushObservable.notify({\n      reason: flushReason,\n      messagesCount,\n      bytesCount,\n    })\n  }\n\n  let durationLimitTimeoutId: TimeoutId | undefined\n  function scheduleDurationLimitTimeout() {\n    if (durationLimitTimeoutId === undefined) {\n      durationLimitTimeoutId = setTimeout(() => {\n        flush('duration_limit')\n      }, FLUSH_DURATION_LIMIT)\n    }\n  }\n\n  function cancelDurationLimitTimeout() {\n    clearTimeout(durationLimitTimeoutId)\n    durationLimitTimeoutId = undefined\n  }\n\n  return {\n    flushObservable,\n    preparePageExitFlushObservable,\n    get messagesCount() {\n      return currentMessagesCount\n    },\n\n    /**\n     * Notifies that a message will be added to a pool of pending messages waiting to be flushed.\n     *\n     * This function needs to be called synchronously, right before adding the message, so no flush\n     * event can happen after `notifyBeforeAddMessage` and before adding the message.\n     *\n     * @param estimatedMessageBytesCount - an estimation of the message bytes count once it is\n     * actually added.\n     */\n    notifyBeforeAddMessage(estimatedMessageBytesCount: number) {\n      if (currentBytesCount + estimatedMessageBytesCount >= RECOMMENDED_REQUEST_BYTES_LIMIT) {\n        flush(forcedFlushReason ?? 'bytes_limit')\n      }\n      // Consider the message to be added now rather than in `notifyAfterAddMessage`, because if no\n      // message was added yet and `notifyAfterAddMessage` is called asynchronously, we still want\n      // to notify when a flush is needed (for example on page exit).\n      currentMessagesCount += 1\n      currentBytesCount += estimatedMessageBytesCount\n      scheduleDurationLimitTimeout()\n    },\n\n    /**\n     * Notifies that a message *was* added to a pool of pending messages waiting to be flushed.\n     *\n     * This function can be called asynchronously after the message was added, but in this case it\n     * should not be called if a flush event occurred in between.\n     *\n     * @param messageBytesCountDiff - the difference between the estimated message bytes count and\n     * its actual bytes count once added to the pool.\n     */\n    notifyAfterAddMessage(messageBytesCountDiff = 0) {\n      currentBytesCount += messageBytesCountDiff\n\n      if (currentMessagesCount >= MESSAGES_LIMIT) {\n        flush(forcedFlushReason ?? 'messages_limit')\n      } else if (currentBytesCount >= RECOMMENDED_REQUEST_BYTES_LIMIT) {\n        flush(forcedFlushReason ?? 'bytes_limit')\n      }\n    },\n\n    /**\n     * Notifies that a message was removed from a pool of pending messages waiting to be flushed.\n     *\n     * This function needs to be called synchronously, right after removing the message, so no flush\n     * event can happen after removing the message and before `notifyAfterRemoveMessage`.\n     *\n     * @param messageBytesCount - the message bytes count that was added to the pool. Should\n     * correspond to the sum of bytes counts passed to `notifyBeforeAddMessage` and\n     * `notifyAfterAddMessage`.\n     */\n    notifyAfterRemoveMessage(messageBytesCount: number) {\n      currentBytesCount -= messageBytesCount\n      currentMessagesCount -= 1\n      if (currentMessagesCount === 0) {\n        cancelDurationLimitTimeout()\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/src/transport/httpRequest.spec.ts",
    "content": "import type { Request } from '../../test'\nimport {\n  collectAsyncCalls,\n  mockEndpointBuilder,\n  interceptRequests,\n  DEFAULT_FETCH_MOCK,\n  TOO_MANY_REQUESTS_FETCH_MOCK,\n  NETWORK_ERROR_FETCH_MOCK,\n  wait,\n} from '../../test'\nimport type { EndpointBuilder } from '../domain/configuration'\nimport { createEndpointBuilder } from '../domain/configuration'\nimport { noop } from '../tools/utils/functionUtils'\nimport type { HttpRequest, HttpRequestEvent } from './httpRequest'\nimport { createHttpRequest, fetchStrategy, RECOMMENDED_REQUEST_BYTES_LIMIT } from './httpRequest'\n\ndescribe('httpRequest', () => {\n  const ENDPOINT_URL = 'http://my.website'\n  let interceptor: ReturnType<typeof interceptRequests>\n  let requests: Request[]\n  let endpointBuilder: EndpointBuilder\n  let request: HttpRequest\n\n  beforeEach(() => {\n    interceptor = interceptRequests()\n    requests = interceptor.requests\n    endpointBuilder = mockEndpointBuilder(ENDPOINT_URL)\n    request = createHttpRequest([endpointBuilder], noop)\n  })\n\n  describe('send', () => {\n    it('should use fetch to send intake payload to the endpoint', async () => {\n      const payloadData = '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}'\n      request.send({ data: payloadData, bytesCount: 10 })\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('fetch')\n      expect(requests[0].url).toContain(ENDPOINT_URL)\n      expect(requests[0].body).toEqual(payloadData)\n    })\n\n    it('should use fetch for payloads exceeding the bytes limit', async () => {\n      request.send({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: RECOMMENDED_REQUEST_BYTES_LIMIT })\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('fetch')\n    })\n\n    it('should use retry strategy', async () => {\n      const fetchSpy = interceptor.withFetch(TOO_MANY_REQUESTS_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n\n      request.send({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n\n      await interceptor.waitForAllFetchCalls()\n      await collectAsyncCalls(fetchSpy, 2)\n    })\n\n    it('sends the payload to multiple endpoints', async () => {\n      const endpointBuilder2 = mockEndpointBuilder('http://my.website2')\n\n      request = createHttpRequest([endpointBuilder, endpointBuilder2], noop)\n\n      interceptor.withFetch(DEFAULT_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n\n      const payloadData = '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}'\n      request.send({ data: payloadData, bytesCount: 10 })\n\n      await interceptor.waitForAllFetchCalls()\n      expect(requests.length).toEqual(2)\n      expect(requests[0].url).toContain('http://my.website')\n      expect(requests[0].body).toEqual(payloadData)\n      expect(requests[1].url).toContain('http://my.website2')\n      expect(requests[1].body).toEqual(payloadData)\n    })\n  })\n\n  describe('fetchStrategy onResponse', () => {\n    it('should be called with intake response', (done) => {\n      interceptor.withFetch(DEFAULT_FETCH_MOCK)\n\n      fetchStrategy(endpointBuilder, { data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 }, (response) => {\n        expect(response).toEqual({ status: 200, type: 'cors' })\n        done()\n      })\n    })\n\n    it('should be called with status 0 when fetch fails', (done) => {\n      interceptor.withFetch(NETWORK_ERROR_FETCH_MOCK)\n\n      fetchStrategy(endpointBuilder, { data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 }, (response) => {\n        expect(response).toEqual({ status: 0 })\n        done()\n      })\n    })\n  })\n\n  describe('sendOnExit', () => {\n    it('should use fetch when sendBeacon is not defined', async () => {\n      interceptor.withSendBeacon(false)\n\n      request.sendOnExit({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('fetch')\n      expect(requests[0].url).toContain(ENDPOINT_URL)\n      expect(requests[0].body).toEqual('{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}')\n    })\n\n    it('should use sendBeacon when the bytes count is correct', () => {\n      if (!interceptor.isSendBeaconSupported()) {\n        pending('no sendBeacon support')\n      }\n\n      request.sendOnExit({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('sendBeacon')\n    })\n\n    it('should use fetch over sendBeacon when the bytes count is too high', async () => {\n      request.sendOnExit({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: RECOMMENDED_REQUEST_BYTES_LIMIT })\n\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('fetch')\n    })\n\n    it('should fallback to fetch when sendBeacon is not queued', async () => {\n      if (!interceptor.isSendBeaconSupported()) {\n        pending('no sendBeacon support')\n      }\n      interceptor.withSendBeacon(() => false)\n\n      request.sendOnExit({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('fetch')\n    })\n\n    it('should fallback to fetch when sendBeacon throws', async () => {\n      if (!interceptor.isSendBeaconSupported()) {\n        pending('no sendBeacon support')\n      }\n      let sendBeaconCalled = false\n      interceptor.withSendBeacon(() => {\n        sendBeaconCalled = true\n        throw new Error('mock sendBeacon error')\n      })\n\n      request.sendOnExit({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n\n      await interceptor.waitForAllFetchCalls()\n\n      expect(sendBeaconCalled).toBe(true)\n      expect(requests.length).toEqual(1)\n      expect(requests[0].type).toBe('fetch')\n    })\n  })\n\n  describe('HttpRequestEvent observable', () => {\n    const observedEvents: HttpRequestEvent[] = []\n\n    function latestEvents() {\n      const events = [...observedEvents]\n      observedEvents.length = 0\n      return events\n    }\n\n    beforeEach(() => {\n      request.observable.subscribe((event) => {\n        observedEvents.push(event)\n      })\n    })\n\n    afterEach(() => {\n      observedEvents.length = 0\n    })\n\n    it('should report success for successful requests', async () => {\n      interceptor.withFetch(DEFAULT_FETCH_MOCK)\n\n      const payload = { data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 }\n      request.send(payload)\n      await interceptor.waitForAllFetchCalls()\n      await wait(0)\n\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n    })\n\n    it('should report failure for failing requests', async () => {\n      interceptor.withFetch(TOO_MANY_REQUESTS_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n\n      const payload = { data: '{\"foo\":\"barX\"}\\n{\"foo\":\"barY\"}', bytesCount: 10 }\n      request.send(payload)\n      await interceptor.waitForAllFetchCalls()\n      await wait(0)\n      await interceptor.waitForAllFetchCalls()\n      await wait(0)\n\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n    })\n\n    it('should report multiple failures when requests are retried repeatedly', async () => {\n      interceptor.withFetch(TOO_MANY_REQUESTS_FETCH_MOCK, TOO_MANY_REQUESTS_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n\n      const payload = { data: '{\"foo\":\"barA\"}\\n{\"foo\":\"barB\"}', bytesCount: 10 }\n      request.send(payload)\n      await interceptor.waitForAllFetchCalls()\n      await wait(0)\n      await interceptor.waitForAllFetchCalls()\n      await wait(0)\n      await interceptor.waitForAllFetchCalls()\n      await wait(0)\n\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n    })\n  })\n})\n\ndescribe('httpRequest intake parameters', () => {\n  const clientToken = 'some_client_token'\n  let interceptor: ReturnType<typeof interceptRequests>\n  let requests: Request[]\n  let endpointBuilder: EndpointBuilder\n  let request: HttpRequest\n\n  beforeEach(() => {\n    interceptor = interceptRequests()\n    requests = interceptor.requests\n    endpointBuilder = createEndpointBuilder({ clientToken }, 'logs')\n    request = createHttpRequest([endpointBuilder], noop)\n  })\n\n  it('should have a unique request id', async () => {\n    interceptor.withFetch(DEFAULT_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n\n    request.send({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n    request.send({ data: '{\"foo\":\"bar1\"}\\n{\"foo\":\"bar2\"}', bytesCount: 10 })\n\n    await interceptor.waitForAllFetchCalls()\n\n    const search = /dd-request-id=([^&]*)/\n    const requestId1 = search.exec(requests[0].url)?.[1]\n    const requestId2 = search.exec(requests[1].url)?.[1]\n\n    expect(requestId1).not.toBe(requestId2)\n    expect(requests.length).toEqual(2)\n  })\n})\n"
  },
  {
    "path": "packages/core/src/transport/httpRequest.ts",
    "content": "import type { EndpointBuilder } from '../domain/configuration'\nimport type { Context } from '../tools/serialisation/context'\nimport { fetch } from '../browser/fetch'\nimport { monitor, monitorError } from '../tools/monitor'\nimport type { RawError } from '../domain/error/error.types'\nimport { Observable } from '../tools/observable'\nimport { ONE_KIBI_BYTE } from '../tools/utils/byteUtils'\nimport { newRetryState, sendWithRetryStrategy } from './sendWithRetryStrategy'\n\n/**\n * beacon payload max queue size implementation is 64kb\n * ensure that we leave room for logs, rum and potential other users\n */\nexport const RECOMMENDED_REQUEST_BYTES_LIMIT = 16 * ONE_KIBI_BYTE\n\n/**\n * Use POST request without content type to:\n * - avoid CORS preflight requests\n * - allow usage of sendBeacon\n *\n * multiple elements are sent separated by \\n in order\n * to be parsed correctly without content type header\n */\n\nexport interface HttpRequest<Body extends Payload = Payload> {\n  observable: Observable<HttpRequestEvent<Body>>\n  send(this: void, payload: Body): void\n  sendOnExit(this: void, payload: Body): void\n}\n\nexport interface HttpResponse extends Context {\n  status: number\n  type?: ResponseType\n}\n\nexport interface BandwidthStats {\n  ongoingByteCount: number\n  ongoingRequestCount: number\n}\n\nexport type HttpRequestEvent<Body extends Payload = Payload> =\n  | {\n      // A request to send the given payload failed. (We may retry.)\n      type: 'failure'\n      bandwidth: BandwidthStats\n      payload: Body\n    }\n  | {\n      // The given payload was discarded because the request queue is full.\n      type: 'queue-full'\n      bandwidth: BandwidthStats\n      payload: Body\n    }\n  | {\n      // A request to send the given payload succeeded.\n      type: 'success'\n      bandwidth: BandwidthStats\n      payload: Body\n    }\n\nexport interface Payload {\n  data: string | FormData | Blob\n  bytesCount: number\n  retry?: RetryInfo\n  encoding?: 'deflate'\n}\n\nexport interface RetryInfo {\n  count: number\n  lastFailureStatus: number\n}\n\nexport function createHttpRequest<Body extends Payload = Payload>(\n  endpointBuilders: EndpointBuilder[],\n  reportError: (error: RawError) => void,\n  bytesLimit: number = RECOMMENDED_REQUEST_BYTES_LIMIT\n): HttpRequest<Body> {\n  const observable = new Observable<HttpRequestEvent<Body>>()\n  const retryState = newRetryState<Body>()\n\n  return {\n    observable,\n    send: (payload: Body) => {\n      for (const endpointBuilder of endpointBuilders) {\n        sendWithRetryStrategy(\n          payload,\n          retryState,\n          (payload, onResponse) => {\n            fetchStrategy(endpointBuilder, payload, onResponse)\n          },\n          endpointBuilder.trackType,\n          reportError,\n          observable\n        )\n      }\n    },\n    /**\n     * Since fetch keepalive behaves like regular fetch on Firefox,\n     * keep using sendBeaconStrategy on exit\n     */\n    sendOnExit: (payload: Body) => {\n      for (const endpointBuilder of endpointBuilders) {\n        sendBeaconStrategy(endpointBuilder, bytesLimit, payload)\n      }\n    },\n  }\n}\n\nfunction sendBeaconStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, payload: Payload) {\n  const canUseBeacon = !!navigator.sendBeacon && payload.bytesCount < bytesLimit\n  if (canUseBeacon) {\n    try {\n      const beaconUrl = endpointBuilder.build('beacon', payload)\n      const isQueued = navigator.sendBeacon(beaconUrl, payload.data)\n\n      if (isQueued) {\n        return\n      }\n    } catch (e) {\n      reportBeaconError(e)\n    }\n  }\n\n  fetchStrategy(endpointBuilder, payload)\n}\n\nlet hasReportedBeaconError = false\n\nfunction reportBeaconError(e: unknown) {\n  if (!hasReportedBeaconError) {\n    hasReportedBeaconError = true\n    monitorError(e)\n  }\n}\n\nexport function fetchStrategy(\n  endpointBuilder: EndpointBuilder,\n  payload: Payload,\n  onResponse?: (r: HttpResponse) => void\n) {\n  const fetchUrl = endpointBuilder.build('fetch', payload)\n\n  fetch(fetchUrl, { method: 'POST', body: payload.data, mode: 'cors' })\n    .then(monitor((response: Response) => onResponse?.({ status: response.status, type: response.type })))\n    .catch(monitor(() => onResponse?.({ status: 0 })))\n}\n"
  },
  {
    "path": "packages/core/src/transport/index.ts",
    "content": "export type { BandwidthStats, HttpRequest, HttpRequestEvent, Payload, RetryInfo } from './httpRequest'\nexport { createHttpRequest } from './httpRequest'\nexport type { BrowserWindowWithEventBridge, DatadogEventBridge } from './eventBridge'\nexport { canUseEventBridge, bridgeSupports, getEventBridge, BridgeCapability } from './eventBridge'\nexport { createBatch } from './batch'\nexport type { FlushController, FlushEvent, FlushReason } from './flushController'\nexport { createFlushController, FLUSH_DURATION_LIMIT } from './flushController'\n"
  },
  {
    "path": "packages/core/src/transport/sendWithRetryStrategy.spec.ts",
    "content": "import { mockClock, setNavigatorOnLine } from '../../test'\nimport type { Clock } from '../../test'\nimport { ErrorSource } from '../domain/error/error.types'\nimport { Observable } from '../tools/observable'\nimport { ONE_MEBI_BYTE } from '../tools/utils/byteUtils'\nimport type { RetryState } from './sendWithRetryStrategy'\nimport {\n  newRetryState,\n  sendWithRetryStrategy,\n  MAX_ONGOING_BYTES_COUNT,\n  MAX_ONGOING_REQUESTS,\n  MAX_QUEUE_BYTES_COUNT,\n  INITIAL_BACKOFF_TIME,\n} from './sendWithRetryStrategy'\nimport type { Payload, HttpResponse, HttpRequestEvent } from './httpRequest'\n\ndescribe('sendWithRetryStrategy', () => {\n  const ENDPOINT_TYPE = 'logs'\n  let sendMock: ReturnType<typeof mockSend>\n  let state: RetryState<Payload>\n  let sendRequest: (payload?: Partial<Payload>) => Payload\n  let clock: Clock\n  let reportErrorSpy: jasmine.Spy<jasmine.Func>\n  const observedEvents: HttpRequestEvent[] = []\n\n  function mockSend() {\n    const requests: Array<(r: HttpResponse) => void> = []\n    return {\n      sendStrategy: (_: Payload, onResponse: (r: HttpResponse) => void) => {\n        requests.push(onResponse)\n      },\n      respondWith: (index: number, r: HttpResponse) => {\n        requests[index](r)\n        requests[index] = () => {\n          throw new Error('response already handled')\n        }\n      },\n    }\n  }\n\n  function latestEvents() {\n    const events = [...observedEvents]\n    observedEvents.length = 0\n    return events\n  }\n\n  beforeEach(() => {\n    sendMock = mockSend()\n    state = newRetryState()\n    clock = mockClock()\n    reportErrorSpy = jasmine.createSpy('reportError')\n    const observable = new Observable<HttpRequestEvent>()\n    observable.subscribe((event) => observedEvents.push(event))\n    sendRequest = (payload) => {\n      const effectivePayload = {\n        data: payload?.data ?? 'a',\n        bytesCount: payload?.bytesCount ?? 1,\n      }\n      sendWithRetryStrategy(effectivePayload, state, sendMock.sendStrategy, ENDPOINT_TYPE, reportErrorSpy, observable)\n      return effectivePayload\n    }\n  })\n\n  afterEach(() => {\n    observedEvents.length = 0\n  })\n\n  describe('nominal cases:', () => {\n    it('should send request when no bandwidth limit reached', () => {\n      const payload = sendRequest()\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([])\n\n      sendMock.respondWith(0, { status: 200 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(0)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n    })\n\n    it('should allow to send request payload greater than bandwidth limit', () => {\n      sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT + 10 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([])\n    })\n\n    it('should send concurrent requests ', () => {\n      const payload0 = sendRequest()\n      const payload1 = sendRequest()\n      const payload2 = sendRequest()\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(3)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([])\n\n      sendMock.respondWith(0, { status: 200 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(2)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 2, ongoingRequestCount: 2 }, payload: payload0 },\n      ])\n\n      sendMock.respondWith(1, { status: 200 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 1, ongoingRequestCount: 1 }, payload: payload1 },\n      ])\n\n      sendMock.respondWith(2, { status: 200 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(0)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload: payload2 },\n      ])\n    })\n  })\n\n  describe('bandwidth limitation:', () => {\n    it('should queue request when its payload would overflow bytes limit', () => {\n      sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT - 10 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([])\n\n      sendRequest({ bytesCount: 11 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(state.queuedPayloads.size()).toBe(1)\n      expect(latestEvents()).toEqual([])\n    })\n\n    it('should queue request when too much ongoing requests', () => {\n      for (let i = 1; i <= MAX_ONGOING_REQUESTS; i++) {\n        sendRequest()\n      }\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(MAX_ONGOING_REQUESTS)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([])\n\n      sendRequest()\n      expect(state.queuedPayloads.size()).toBe(1)\n      expect(latestEvents()).toEqual([])\n    })\n  })\n\n  describe('queue limitation:', () => {\n    it('should stop queueing new payloads when queue bytes limit is reached', () => {\n      sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT })\n      sendRequest({ bytesCount: MAX_QUEUE_BYTES_COUNT - 20 })\n      sendRequest({ bytesCount: 30 })\n      expect(state.queuedPayloads.size()).toBe(2)\n      expect(state.queuedPayloads.bytesCount).toBe(MAX_QUEUE_BYTES_COUNT + 10)\n      expect(latestEvents()).toEqual([])\n\n      const payload = sendRequest({ bytesCount: 1 })\n      expect(state.queuedPayloads.size()).toBe(2)\n      expect(state.queuedPayloads.bytesCount).toBe(MAX_QUEUE_BYTES_COUNT + 10)\n      expect(latestEvents()).toEqual([\n        { type: 'queue-full', bandwidth: { ongoingByteCount: 81920, ongoingRequestCount: 1 }, payload },\n      ])\n    })\n\n    it('should report a single error when queue is full after request success', () => {\n      const payload0 = sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT })\n      const payload1 = sendRequest({ bytesCount: MAX_QUEUE_BYTES_COUNT })\n      expect(state.queuedPayloads.isFull()).toBe(true)\n      expect(latestEvents()).toEqual([])\n\n      sendMock.respondWith(0, { status: 200 })\n      expect(reportErrorSpy).toHaveBeenCalled()\n      expect(reportErrorSpy.calls.argsFor(0)[0]).toEqual(\n        jasmine.objectContaining({\n          message: `Reached max logs events size queued for upload: ${MAX_QUEUE_BYTES_COUNT / ONE_MEBI_BYTE}MiB`,\n          source: ErrorSource.AGENT,\n        })\n      )\n      reportErrorSpy.calls.reset()\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload: payload0 },\n      ])\n\n      sendRequest({ bytesCount: MAX_QUEUE_BYTES_COUNT })\n      expect(state.queuedPayloads.isFull()).toBe(true)\n      expect(latestEvents()).toEqual([])\n\n      sendMock.respondWith(1, { status: 200 })\n      expect(reportErrorSpy).not.toHaveBeenCalled()\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload: payload1 },\n      ])\n    })\n\n    it('should not report error when queue is full after resuming transport', () => {\n      const payload = sendRequest()\n      sendMock.respondWith(0, { status: 500 })\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n\n      sendRequest({ bytesCount: MAX_QUEUE_BYTES_COUNT })\n      expect(state.queuedPayloads.isFull()).toBe(true)\n      expect(latestEvents()).toEqual([])\n\n      clock.tick(INITIAL_BACKOFF_TIME)\n      sendMock.respondWith(1, { status: 200 })\n      expect(latestEvents()).toEqual([\n        {\n          type: 'success',\n          bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 },\n          payload: { ...payload, retry: { count: 1, lastFailureStatus: 500 } },\n        },\n      ])\n\n      expect(reportErrorSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('dequeue:', () => {\n    it('should send as much queued request as possible after a successful request', () => {\n      const payload = sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT })\n      for (let i = 1; i <= MAX_ONGOING_REQUESTS; i++) {\n        sendRequest()\n      }\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(state.queuedPayloads.size()).toBe(MAX_ONGOING_REQUESTS)\n      expect(latestEvents()).toEqual([])\n\n      sendMock.respondWith(0, { status: 200 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(MAX_ONGOING_REQUESTS)\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n    })\n\n    it('should respect request order', () => {\n      const payload0 = sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT - 10 })\n      const payload1 = sendRequest({ bytesCount: 20 })\n      sendRequest({ bytesCount: MAX_ONGOING_BYTES_COUNT - 15 })\n      sendRequest({ bytesCount: 10 })\n      expect(state.queuedPayloads.size()).toBe(3)\n      expect(state.queuedPayloads.bytesCount).toBe(20 + (MAX_ONGOING_BYTES_COUNT - 15) + 10)\n      expect(latestEvents()).toEqual([])\n\n      sendMock.respondWith(0, { status: 200 })\n      expect(state.queuedPayloads.size()).toBe(2)\n      expect(state.queuedPayloads.bytesCount).toBe(MAX_ONGOING_BYTES_COUNT - 15 + 10)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload: payload0 },\n      ])\n\n      sendMock.respondWith(1, { status: 200 })\n      expect(state.queuedPayloads.size()).toBe(0)\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload: payload1 },\n      ])\n    })\n  })\n  ;[\n    { expectRetry: true, description: 'when the intake returns error:', status: 500 },\n    { expectRetry: true, description: 'when the intake returns too many request:', status: 429 },\n    { expectRetry: true, description: 'when the intake returns request timeout:', status: 408 },\n    { expectRetry: true, description: 'when network error while offline:', status: 0, offLine: true },\n    { expectRetry: false, description: 'when network error while online:', status: 0 },\n    { expectRetry: false, description: 'when the intake returns opaque response:', status: 0, type: 'opaque' as const },\n  ].forEach(({ expectRetry, description, status, type, offLine }) => {\n    describe(description, () => {\n      beforeEach(() => {\n        setNavigatorOnLine(!offLine)\n      })\n\n      if (expectRetry) {\n        it('should start queueing following requests', () => {\n          const payload = sendRequest()\n          sendMock.respondWith(0, { status, type })\n          expect(state.queuedPayloads.size()).toBe(1)\n          expect(latestEvents()).toEqual([\n            { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n          ])\n\n          sendRequest()\n          expect(state.queuedPayloads.size()).toBe(2)\n          sendRequest()\n          expect(state.queuedPayloads.size()).toBe(3)\n          expect(latestEvents()).toEqual([])\n        })\n\n        it('should send queued requests if another ongoing request succeed', () => {\n          const payload0 = sendRequest()\n          const payload1 = sendRequest()\n          sendMock.respondWith(0, { status, type })\n          expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n          expect(state.queuedPayloads.size()).toBe(1)\n          expect(latestEvents()).toEqual([\n            { type: 'failure', bandwidth: { ongoingByteCount: 1, ongoingRequestCount: 1 }, payload: payload0 },\n          ])\n\n          sendRequest()\n          expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n          expect(state.queuedPayloads.size()).toBe(2)\n          expect(latestEvents()).toEqual([])\n\n          sendMock.respondWith(1, { status: 200 })\n          expect(state.bandwidthMonitor.ongoingRequestCount).toBe(2)\n          expect(state.queuedPayloads.size()).toBe(0)\n          expect(latestEvents()).toEqual([\n            { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload: payload1 },\n          ])\n        })\n\n        it('should add retry info to payloads', () => {\n          const payload = sendRequest()\n\n          sendMock.respondWith(0, { status, type })\n          expect(state.queuedPayloads.first().retry).toEqual({ count: 1, lastFailureStatus: status })\n          expect(latestEvents()).toEqual([\n            { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n          ])\n\n          clock.tick(INITIAL_BACKOFF_TIME)\n\n          sendMock.respondWith(1, { status, type })\n          expect(state.queuedPayloads.first().retry).toEqual({ count: 2, lastFailureStatus: status })\n          expect(latestEvents()).toEqual([\n            { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n          ])\n        })\n      } else {\n        it('should not queue the payload for retry', () => {\n          const payload = sendRequest()\n          sendMock.respondWith(0, { status, type })\n          expect(state.queuedPayloads.size()).toBe(0)\n          expect(latestEvents()).toEqual([\n            { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n          ])\n        })\n      }\n    })\n  })\n\n  describe('when transport down:', () => {\n    it('should regularly try to send first queued request', () => {\n      const payload = sendRequest()\n      sendMock.respondWith(0, { status: 500 })\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(0)\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n\n      clock.tick(INITIAL_BACKOFF_TIME)\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      sendMock.respondWith(1, { status: 500 })\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n\n      clock.tick(2 * INITIAL_BACKOFF_TIME)\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      sendMock.respondWith(2, { status: 500 })\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n\n      clock.tick(4 * INITIAL_BACKOFF_TIME)\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      expect(latestEvents()).toEqual([])\n    })\n\n    it('should send queued requests after first successful request', () => {\n      const payload = sendRequest()\n      sendMock.respondWith(0, { status: 500 })\n      expect(latestEvents()).toEqual([\n        { type: 'failure', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n\n      sendRequest()\n      sendRequest()\n      sendRequest()\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(0)\n      expect(state.queuedPayloads.size()).toBe(4)\n      expect(latestEvents()).toEqual([])\n\n      clock.tick(INITIAL_BACKOFF_TIME)\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(1)\n      sendMock.respondWith(1, { status: 200 })\n      expect(latestEvents()).toEqual([\n        { type: 'success', bandwidth: { ongoingByteCount: 0, ongoingRequestCount: 0 }, payload },\n      ])\n\n      expect(state.bandwidthMonitor.ongoingRequestCount).toBe(3)\n      expect(state.queuedPayloads.size()).toBe(0)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/core/src/transport/sendWithRetryStrategy.ts",
    "content": "import type { TrackType } from '../domain/configuration'\nimport { setTimeout } from '../tools/timer'\nimport { clocksNow, ONE_MINUTE, ONE_SECOND } from '../tools/utils/timeUtils'\nimport { ONE_MEBI_BYTE, ONE_KIBI_BYTE } from '../tools/utils/byteUtils'\nimport { isServerError } from '../tools/utils/responseUtils'\nimport type { RawError } from '../domain/error/error.types'\nimport { ErrorSource } from '../domain/error/error.types'\nimport type { Observable } from '../tools/observable'\nimport type { Payload, HttpRequestEvent, HttpResponse, BandwidthStats } from './httpRequest'\n\nexport const MAX_ONGOING_BYTES_COUNT = 80 * ONE_KIBI_BYTE\nexport const MAX_ONGOING_REQUESTS = 32\nexport const MAX_QUEUE_BYTES_COUNT = 20 * ONE_MEBI_BYTE\nexport const MAX_BACKOFF_TIME = ONE_MINUTE\nexport const INITIAL_BACKOFF_TIME = ONE_SECOND\n\nconst enum TransportStatus {\n  UP,\n  FAILURE_DETECTED,\n  DOWN,\n}\n\nconst enum RetryReason {\n  AFTER_SUCCESS,\n  AFTER_RESUME,\n}\n\nexport interface RetryState<Body extends Payload> {\n  transportStatus: TransportStatus\n  currentBackoffTime: number\n  bandwidthMonitor: ReturnType<typeof newBandwidthMonitor>\n  queuedPayloads: ReturnType<typeof newPayloadQueue<Body>>\n  queueFullReported: boolean\n}\n\ntype SendStrategy<Body extends Payload> = (payload: Body, onResponse: (r: HttpResponse) => void) => void\n\nexport function sendWithRetryStrategy<Body extends Payload>(\n  payload: Body,\n  state: RetryState<Body>,\n  sendStrategy: SendStrategy<Body>,\n  trackType: TrackType,\n  reportError: (error: RawError) => void,\n  requestObservable: Observable<HttpRequestEvent<Body>>\n) {\n  if (\n    state.transportStatus === TransportStatus.UP &&\n    state.queuedPayloads.size() === 0 &&\n    state.bandwidthMonitor.canHandle(payload)\n  ) {\n    send(payload, state, sendStrategy, requestObservable, {\n      onSuccess: () =>\n        retryQueuedPayloads(RetryReason.AFTER_SUCCESS, state, sendStrategy, trackType, reportError, requestObservable),\n      onFailure: () => {\n        if (!state.queuedPayloads.enqueue(payload)) {\n          requestObservable.notify({ type: 'queue-full', bandwidth: state.bandwidthMonitor.stats(), payload })\n        }\n        scheduleRetry(state, sendStrategy, trackType, reportError, requestObservable)\n      },\n    })\n  } else {\n    if (!state.queuedPayloads.enqueue(payload)) {\n      requestObservable.notify({ type: 'queue-full', bandwidth: state.bandwidthMonitor.stats(), payload })\n    }\n  }\n}\n\nfunction scheduleRetry<Body extends Payload>(\n  state: RetryState<Body>,\n  sendStrategy: SendStrategy<Body>,\n  trackType: TrackType,\n  reportError: (error: RawError) => void,\n  requestObservable: Observable<HttpRequestEvent<Body>>\n) {\n  if (state.transportStatus !== TransportStatus.DOWN) {\n    return\n  }\n  setTimeout(() => {\n    const payload = state.queuedPayloads.first()\n    send(payload, state, sendStrategy, requestObservable, {\n      onSuccess: () => {\n        state.queuedPayloads.dequeue()\n        state.currentBackoffTime = INITIAL_BACKOFF_TIME\n        retryQueuedPayloads(RetryReason.AFTER_RESUME, state, sendStrategy, trackType, reportError, requestObservable)\n      },\n      onFailure: () => {\n        state.currentBackoffTime = Math.min(MAX_BACKOFF_TIME, state.currentBackoffTime * 2)\n        scheduleRetry(state, sendStrategy, trackType, reportError, requestObservable)\n      },\n    })\n  }, state.currentBackoffTime)\n}\n\nfunction send<Body extends Payload>(\n  payload: Body,\n  state: RetryState<Body>,\n  sendStrategy: SendStrategy<Body>,\n  requestObservable: Observable<HttpRequestEvent<Body>>,\n  { onSuccess, onFailure }: { onSuccess: () => void; onFailure: () => void }\n) {\n  state.bandwidthMonitor.add(payload)\n  sendStrategy(payload, (response) => {\n    state.bandwidthMonitor.remove(payload)\n    if (!shouldRetryRequest(response)) {\n      state.transportStatus = TransportStatus.UP\n      requestObservable.notify({ type: 'success', bandwidth: state.bandwidthMonitor.stats(), payload })\n      onSuccess()\n    } else {\n      // do not consider transport down if another ongoing request could succeed\n      state.transportStatus =\n        state.bandwidthMonitor.ongoingRequestCount > 0 ? TransportStatus.FAILURE_DETECTED : TransportStatus.DOWN\n      payload.retry = {\n        count: payload.retry ? payload.retry.count + 1 : 1,\n        lastFailureStatus: response.status,\n      }\n      requestObservable.notify({ type: 'failure', bandwidth: state.bandwidthMonitor.stats(), payload })\n      onFailure()\n    }\n  })\n}\n\nfunction retryQueuedPayloads<Body extends Payload>(\n  reason: RetryReason,\n  state: RetryState<Body>,\n  sendStrategy: SendStrategy<Body>,\n  trackType: TrackType,\n  reportError: (error: RawError) => void,\n  requestObservable: Observable<HttpRequestEvent<Body>>\n) {\n  if (reason === RetryReason.AFTER_SUCCESS && state.queuedPayloads.isFull() && !state.queueFullReported) {\n    reportError({\n      message: `Reached max ${trackType} events size queued for upload: ${MAX_QUEUE_BYTES_COUNT / ONE_MEBI_BYTE}MiB`,\n      source: ErrorSource.AGENT,\n      startClocks: clocksNow(),\n    })\n    state.queueFullReported = true\n  }\n  const previousQueue = state.queuedPayloads\n  state.queuedPayloads = newPayloadQueue()\n  while (previousQueue.size() > 0) {\n    sendWithRetryStrategy(previousQueue.dequeue()!, state, sendStrategy, trackType, reportError, requestObservable)\n  }\n}\n\nfunction shouldRetryRequest(response: HttpResponse) {\n  return (\n    response.type !== 'opaque' &&\n    ((response.status === 0 && !navigator.onLine) ||\n      response.status === 408 ||\n      response.status === 429 ||\n      isServerError(response.status))\n  )\n}\n\nexport function newRetryState<Body extends Payload>(): RetryState<Body> {\n  return {\n    transportStatus: TransportStatus.UP,\n    currentBackoffTime: INITIAL_BACKOFF_TIME,\n    bandwidthMonitor: newBandwidthMonitor(),\n    queuedPayloads: newPayloadQueue(),\n    queueFullReported: false,\n  }\n}\n\nfunction newPayloadQueue<Body extends Payload>() {\n  const queue: Body[] = []\n  return {\n    bytesCount: 0,\n    enqueue(payload: Body) {\n      if (this.isFull()) {\n        return false\n      }\n      queue.push(payload)\n      this.bytesCount += payload.bytesCount\n      return true\n    },\n    first() {\n      return queue[0]\n    },\n    dequeue() {\n      const payload = queue.shift()\n      if (payload) {\n        this.bytesCount -= payload.bytesCount\n      }\n      return payload\n    },\n    size() {\n      return queue.length\n    },\n    isFull() {\n      return this.bytesCount >= MAX_QUEUE_BYTES_COUNT\n    },\n  }\n}\n\nfunction newBandwidthMonitor() {\n  return {\n    ongoingRequestCount: 0,\n    ongoingByteCount: 0,\n    canHandle(payload: Payload) {\n      return (\n        this.ongoingRequestCount === 0 ||\n        (this.ongoingByteCount + payload.bytesCount <= MAX_ONGOING_BYTES_COUNT &&\n          this.ongoingRequestCount < MAX_ONGOING_REQUESTS)\n      )\n    },\n    add(payload: Payload) {\n      this.ongoingRequestCount += 1\n      this.ongoingByteCount += payload.bytesCount\n    },\n    remove(payload: Payload) {\n      this.ongoingRequestCount -= 1\n      this.ongoingByteCount -= payload.bytesCount\n    },\n    stats(): BandwidthStats {\n      return {\n        ongoingByteCount: this.ongoingByteCount,\n        ongoingRequestCount: this.ongoingRequestCount,\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/test/browserChecks.ts",
    "content": "export function isFirefox() {\n  return navigator.userAgent.toLowerCase().indexOf('firefox') > -1\n}\n\nexport function isAdoptedStyleSheetsSupported() {\n  return Boolean((document as any).adoptedStyleSheets)\n}\n"
  },
  {
    "path": "packages/core/test/browserExtension.ts",
    "content": "// Base case, the page has the SDK in the init and the error stack is in the page.\nexport const STACK_WITH_INIT_IN_PAGE = `Error\n    at Object.init (http://localhost:8080/datadog-rum.js:3919:16)\n    at http://localhost:8080/:10:14`\n\n// Base case for extension, the extension has the SDK in the init and the error stack is in the extension.\nexport const STACK_WITH_INIT_IN_EXTENSION = `Error\n    at Object.init (chrome-extension://abcdef/dist/contentScript.js:254:14)\n    at chrome-extension://abcdef/dist/contentScript.js:13304:14\n    at chrome-extension://abcdef/dist/contentScript.js:13315:3`\n\nexport const STACK_WITH_INIT_IN_EXTENSION_FIREFOX = `Error\nObject.init@moz-extension://abcdef/dist/contentScript.js:254:14\n@moz-extension://abcdef/dist/contentScript.js:13304:14\n@moz-extension://abcdef/dist/contentScript.js:13315:3`\n"
  },
  {
    "path": "packages/core/test/buildEnv.ts",
    "content": "// to simulate different build env behavior\nexport interface BuildEnvWindow {\n  __BUILD_ENV__SDK_VERSION__: string\n}\n"
  },
  {
    "path": "packages/core/test/collectAsyncCalls.ts",
    "content": "import { getCurrentJasmineSpec } from './getCurrentJasmineSpec'\n\nexport function collectAsyncCalls<F extends jasmine.Func>(\n  spy: jasmine.Spy<F>,\n  expectedCallsCount = 1\n): Promise<jasmine.Calls<F>> {\n  return new Promise((resolve, reject) => {\n    const currentSpec = getCurrentJasmineSpec()\n    if (!currentSpec) {\n      reject(new Error('collectAsyncCalls should be called within jasmine code'))\n      return\n    }\n\n    const checkCalls = () => {\n      if (spy.calls.count() === expectedCallsCount) {\n        spy.and.callFake(extraCallDetected as F)\n        resolve(spy.calls)\n      } else if (spy.calls.count() > expectedCallsCount) {\n        extraCallDetected()\n      }\n    }\n\n    checkCalls()\n\n    spy.and.callFake((() => {\n      checkCalls()\n    }) as F)\n\n    function extraCallDetected() {\n      const message = `Unexpected extra call for spec '${currentSpec!.fullName}'`\n      fail(message)\n      reject(new Error(message))\n    }\n  })\n}\n"
  },
  {
    "path": "packages/core/test/consoleLog.ts",
    "content": "const ignoreList: Array<{ level: string; match: string }> = []\n\nafterEach(() => {\n  ignoreList.length = 0\n})\n\n/**\n * Ignore console logs that match the given level and message for the duration of the test. This\n * function can be called multiple times to ignore multiple logs.\n */\nexport function ignoreConsoleLogs(level: 'error' | 'warn' | 'log', match: string) {\n  ignoreList.push({ level, match })\n\n  if (!jasmine.isSpy(console[level])) {\n    const originalLogFunction = console[level].bind(console)\n\n    spyOn(console, level).and.callFake((...args: unknown[]) => {\n      // No need to be too precise with formating here, we just want something to match against\n      const message = args.map((arg) => String(arg)).join(' ')\n      if (ignoreList.some((ignoreEntry) => ignoreEntry.level === level && message.includes(ignoreEntry.match))) {\n        return\n      }\n      originalLogFunction(...args)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/core/test/cookie.ts",
    "content": "import { getCookie, setCookie } from '../src/browser/cookie'\nimport { toSessionState } from '../src/domain/session/sessionState'\nimport { SESSION_STORE_KEY } from '../src/domain/session/storeStrategies/sessionStoreStrategy'\nimport { ONE_MINUTE } from '../src/tools/utils/timeUtils'\nimport { registerCleanupTask } from './registerCleanupTask'\n\nexport function expireCookie() {\n  setCookie(SESSION_STORE_KEY, 'isExpired=1', ONE_MINUTE)\n}\n\nexport function getSessionState(sessionStoreKey: string) {\n  const sessionState = toSessionState(getCookie(sessionStoreKey))\n  // remove the cookie options from the session state so the test works the same way as the code\n  // see: packages/core/src/domain/session/storeStrategies/sessionInCookie.ts:148\n  delete sessionState.c\n  return sessionState\n}\n\ninterface Cookie {\n  name: string\n  value: string\n  domain?: string\n  path?: string\n  expires?: number\n  secure?: boolean\n  sameSite?: 'strict' | 'lax' | 'none'\n  partitioned?: boolean\n}\n\nexport function mockCookies({ filter }: { filter?: (cookie: Cookie) => boolean } = {}) {\n  let cookies: Cookie[] = []\n\n  const getter = jasmine.createSpy('document.cookie getter').and.callFake(() => {\n    removeExpiredCookies()\n    return cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join(';')\n  })\n\n  const setter = jasmine.createSpy('document.cookie setter').and.callFake((cookieString: string) => {\n    const cookie = parseSingleCookieString(cookieString)\n\n    if (filter && !filter(cookie)) {\n      return\n    }\n\n    const matchingCookieIndex = cookies.findIndex(\n      (otherCookie) =>\n        cookie.name === otherCookie.name && cookie.domain === otherCookie.domain && cookie.path === otherCookie.path\n    )\n    if (matchingCookieIndex !== -1) {\n      cookies[matchingCookieIndex] = cookie\n    } else {\n      cookies.push(cookie)\n    }\n    removeExpiredCookies()\n  })\n\n  // Define cookie on the document instance (not Document.prototype) to avoid Safari 12.1.2\n  // intermittently failing to intercept document.cookie accesses when spyOnProperty is called\n  // repeatedly on the same prototype property across tests.\n  Object.defineProperty(document, 'cookie', {\n    get: getter,\n    set: setter,\n    configurable: true,\n  })\n\n  registerCleanupTask(() => {\n    delete (document as any).cookie\n  })\n\n  function removeExpiredCookies() {\n    cookies = cookies.filter((cookie) => cookie.expires && cookie.expires > Date.now())\n  }\n\n  return {\n    getCookies: () => {\n      removeExpiredCookies()\n      return cookies\n    },\n    getter,\n    setter,\n  }\n}\n\nfunction parseSingleCookieString(cookieString: string) {\n  const parts = cookieString.split(';')\n  const [name, value] = parts.shift()!.split('=')\n  const parsedCookie: Cookie = {\n    name,\n    value,\n  }\n\n  for (const part of parts) {\n    const parsedPart = part.match(/^\\s*([^=]*)(?:=(.*))?/)\n    if (!parsedPart) {\n      continue\n    }\n\n    const name = parsedPart[1].toLowerCase()\n    const value: string | undefined = parsedPart[2]\n\n    if (value) {\n      if (name === 'domain') {\n        parsedCookie.domain = value.startsWith('.') ? value : `.${value}`\n      } else if (name === 'path') {\n        parsedCookie.path = value\n      } else if (name === 'expires') {\n        parsedCookie.expires = new Date(value).getTime()\n      } else if (name === 'max-age') {\n        parsedCookie.expires = Date.now() + Number(value) * 1000\n      } else if (name === 'samesite') {\n        parsedCookie.sameSite = value as Cookie['sameSite']\n      }\n    } else if (name === 'partitioned') {\n      parsedCookie.partitioned = true\n    } else if (name === 'secure') {\n      parsedCookie.secure = true\n    }\n  }\n  return parsedCookie\n}\n"
  },
  {
    "path": "packages/core/test/coreConfiguration.ts",
    "content": "import type { InitConfiguration } from '../src/domain/configuration'\nimport type { RawTelemetryConfiguration } from '../src/domain/telemetry'\nimport type { CamelToSnakeCase, RemoveIndex } from './typeUtils'\n\n// Defines a few constants and types related to the core package configuration, so it can be used in\n// other packages tests.\n\n/**\n * An object containing every single possible configuration initialization parameters, with\n * arbitrary values.\n */\nexport const EXHAUSTIVE_INIT_CONFIGURATION: Required<InitConfiguration> = {\n  clientToken: 'yes',\n  beforeSend: () => true,\n  sessionSampleRate: 50,\n  telemetrySampleRate: 60,\n  silentMultipleInit: true,\n  sessionPersistence: 'cookie',\n  allowFallbackToLocalStorage: true,\n  allowUntrustedEvents: true,\n  storeContextsAcrossPages: true,\n  trackingConsent: 'not-granted',\n  proxy: 'proxy',\n  site: 'datadoghq.com',\n  service: 'service',\n  env: 'env',\n  version: 'version',\n  usePartitionedCrossSiteSessionCookie: true,\n  useSecureSessionCookie: true,\n  trackAnonymousUser: true,\n  trackSessionAcrossSubdomains: true,\n  enableExperimentalFeatures: ['foo'],\n  replica: {\n    clientToken: 'yes',\n  },\n  datacenter: 'datacenter',\n  internalAnalyticsSubdomain: 'internal-analytics-subdomain.com',\n  telemetryConfigurationSampleRate: 70,\n  telemetryUsageSampleRate: 80,\n  allowedTrackingOrigins: ['chrome-extension://example'],\n  betaEncodeCookieOptions: true,\n  source: 'browser',\n  sdkVersion: '1.0.0',\n  variant: 'variant',\n}\n\nexport const SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION = {\n  session_sample_rate: 50,\n  telemetry_sample_rate: 60,\n  telemetry_configuration_sample_rate: 70,\n  telemetry_usage_sample_rate: 80,\n  use_before_send: true,\n  session_persistence: 'cookie' as const,\n  use_partitioned_cross_site_session_cookie: true,\n  use_secure_session_cookie: true,\n  use_proxy: true,\n  silent_multiple_init: true,\n  track_session_across_subdomains: true,\n  allow_fallback_to_local_storage: true,\n  store_contexts_across_pages: true,\n  allow_untrusted_events: true,\n  tracking_consent: 'not-granted' as const,\n  track_anonymous_user: true,\n  use_allowed_tracking_origins: true,\n  beta_encode_cookie_options: true,\n  source: 'browser',\n  sdk_version: '1.0.0',\n  variant: 'variant',\n}\n\n/**\n * Maps the keys of InitConfiguration to their serialized version.\n */\nexport type MapInitConfigurationKey<Key extends string> =\n  // Some keys cannot be serialized so we prefix them with `use_` to indicate that the option was set.\n  Key extends 'proxy' | 'beforeSend' | 'allowedTrackingOrigins'\n    ? `use_${CamelToSnakeCase<Key>}`\n    : // Those keys should not be serialized\n      Key extends\n          | 'site'\n          | 'service'\n          | 'clientToken'\n          | 'env'\n          | 'version'\n          | 'datacenter'\n          | 'internalAnalyticsSubdomain'\n          | 'replica'\n          | 'enableExperimentalFeatures'\n      ? never\n      : // Other keys are simply snake cased\n        CamelToSnakeCase<Key>\n\n/**\n * Extracts a sub-set of RawTelemetryConfiguration from the passed InitConfiguration keys, with all\n * properties required, to make sure they are all defined.\n *\n * This type is only used in tests because \"template literal types\" were introduced in (TS 4.1)[1] and we\n * still support TS 3.8.2.\n *\n * [1]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#template-literal-types\n *\n * @example\n * type SerializedInitConfiguration = ExtractTelemetryConfiguration<\n *   \"session_sample_rate\" | \"track_user_interactions\"\n * >\n * // equivalent to:\n * // type SerializedInitConfiguration = {\n * //   session_sample_rate: number | undefined;\n * //   track_user_interactions: boolean | undefined;\n * // }\n */\nexport type ExtractTelemetryConfiguration<Keys extends keyof RemoveIndex<RawTelemetryConfiguration>> = {\n  [Key in Keys]: RawTelemetryConfiguration[Key]\n}\n"
  },
  {
    "path": "packages/core/test/createHooks.ts",
    "content": "import type { HookNames } from '../src/tools/abstractHooks'\nimport { abstractHooks } from '../src/tools/abstractHooks'\n\nexport type Hooks = ReturnType<typeof createHooks>\n\nexport const createHooks = abstractHooks<{\n  [HookNames.Assemble]: (...args: any[]) => any\n  [HookNames.AssembleTelemetry]: (...args: any[]) => any\n}>\n"
  },
  {
    "path": "packages/core/test/disableJasmineUncaughtExceptionTracking.ts",
    "content": "/**\n * Disable Jasmine's uncaught error handling. This is useful for test cases throwing exceptions or\n * unhandled rejections that are expected to be caught somehow, but Jasmine also catch them and\n * fails the test.\n */\nexport function disableJasmineUncaughtExceptionTracking() {\n  spyOn(window as any, 'onerror')\n}\n"
  },
  {
    "path": "packages/core/test/emulate/buildLocation.ts",
    "content": "import { buildUrl } from '../../src'\n\nexport function buildLocation(url: string, base = location.href) {\n  const urlObject = buildUrl(url, base)\n  return {\n    hash: urlObject.hash,\n    href: urlObject.href,\n    pathname: urlObject.pathname,\n    search: urlObject.search,\n  } as Location\n}\n"
  },
  {
    "path": "packages/core/test/emulate/createNewEvent.ts",
    "content": "import type { MouseEventOnElement } from '@datadog/browser-rum-core'\nimport type { TrustableEvent } from '../../src'\nimport { objectEntries } from '../../src'\n\nexport function createNewEvent(eventName: 'click', properties?: Partial<MouseEvent>): MouseEvent\nexport function createNewEvent(eventName: 'pointerup', properties?: Partial<PointerEvent>): MouseEventOnElement\nexport function createNewEvent(eventName: 'message', properties?: Partial<MessageEvent>): MessageEvent\nexport function createNewEvent(\n  eventName: 'securitypolicyviolation',\n  properties?: Partial<SecurityPolicyViolationEvent>\n): SecurityPolicyViolationEvent\nexport function createNewEvent(eventName: string, properties?: { [name: string]: unknown }): Event\nexport function createNewEvent(eventName: string, properties: { [name: string]: unknown } = {}) {\n  let event: TrustableEvent\n  if (typeof Event === 'function') {\n    event = new Event(eventName)\n  } else {\n    event = document.createEvent('Event')\n    event.initEvent(eventName, true, true)\n  }\n  event.__ddIsTrusted = true\n  objectEntries(properties).forEach(([name, value]) => {\n    // Setting values directly or with a `value` descriptor seems unsupported in IE11\n    Object.defineProperty(event, name, {\n      get() {\n        return value\n      },\n    })\n  })\n  return event\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockClock.ts",
    "content": "import type { RelativeTime, TimeStamp } from '../../src/tools/utils/timeUtils'\nimport { registerCleanupTask } from '../registerCleanupTask'\n\nexport type Clock = ReturnType<typeof mockClock>\n\nexport function mockClock() {\n  jasmine.clock().install()\n  jasmine.clock().mockDate()\n\n  const timeOrigin = performance.timing.navigationStart // @see getNavigationStart() in timeUtils.ts\n  const timeStampStart = Date.now()\n  const relativeStart = timeStampStart - timeOrigin\n\n  spyOn(performance, 'now').and.callFake(() => Date.now() - timeOrigin)\n\n  registerCleanupTask(() => jasmine.clock().uninstall())\n\n  return {\n    /**\n     * Returns a RelativeTime representing the time it was X milliseconds after the `mockClock()`\n     * invokation (the start of the test).\n     */\n    relative: (duration: number) => (relativeStart + duration) as RelativeTime,\n    /**\n     * Returns a TimeStamp representing the time it was X milliseconds after the `mockClock()`\n     * invokation (the start of the test).\n     */\n    timeStamp: (duration: number) => (timeStampStart + duration) as TimeStamp,\n    tick: (ms: number) => jasmine.clock().tick(ms),\n    setDate: (date: Date) => jasmine.clock().mockDate(date),\n  }\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockEventBridge.ts",
    "content": "import { DefaultPrivacyLevel } from '../../src/domain/configuration'\nimport { BridgeCapability } from '../../src/transport'\nimport type { BrowserWindowWithEventBridge, DatadogEventBridge } from '../../src/transport'\nimport { registerCleanupTask } from '../registerCleanupTask'\n\nexport function mockEventBridge({\n  allowedWebViewHosts = [window.location.hostname],\n  privacyLevel = DefaultPrivacyLevel.MASK,\n  capabilities = [BridgeCapability.RECORDS],\n}: { allowedWebViewHosts?: string[]; privacyLevel?: DefaultPrivacyLevel; capabilities?: BridgeCapability[] } = {}) {\n  const eventBridge: DatadogEventBridge = {\n    send: (_msg: string) => undefined,\n    getAllowedWebViewHosts: () => JSON.stringify(allowedWebViewHosts),\n    getCapabilities: () => JSON.stringify(capabilities),\n    getPrivacyLevel: () => privacyLevel,\n  }\n\n  ;(window as BrowserWindowWithEventBridge).DatadogEventBridge = eventBridge\n\n  registerCleanupTask(() => {\n    delete (window as BrowserWindowWithEventBridge).DatadogEventBridge\n  })\n  return eventBridge\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockEventTarget.ts",
    "content": "export class MockEventTarget {\n  public listeners: { [k: string]: EventListener[] } = {}\n\n  addEventListener(type: string, listener: EventListener, _options?: boolean | AddEventListenerOptions): void {\n    if (!this.listeners[type]) {\n      this.listeners[type] = []\n    }\n\n    this.listeners[type].push(listener)\n  }\n\n  removeEventListener(type: string, listener: EventListenerOrEventListenerObject) {\n    if (!this.listeners[type]) {\n      throw new Error(`Can't remove a listener. Event \"${type}\" doesn't exits.`)\n    }\n\n    this.listeners[type] = this.listeners[type].filter((lst) => listener !== lst)\n  }\n\n  dispatchEvent(event: Event): boolean {\n    if (this.listeners[event.type]) {\n      this.listeners[event.type].forEach((listener) => {\n        listener.apply(this, [event])\n      })\n    }\n    return true\n  }\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockFetch.ts",
    "content": "import type { Uint8ArrayBuffer } from '../../src'\nimport { noop } from '../../src'\nimport { registerCleanupTask } from '../registerCleanupTask'\n\nexport type MockFetchManager = ReturnType<typeof mockFetch>\n\nexport function mockFetch() {\n  const originalFetch = window.fetch\n  let allFetchCompleteCallback = noop\n  let pendingRequests = 0\n\n  function onRequestEnd() {\n    pendingRequests -= 1\n    if (pendingRequests === 0) {\n      setTimeout(() => allFetchCompleteCallback())\n    }\n  }\n\n  window.fetch = ((_input, init) => {\n    pendingRequests += 1\n    let resolve: (response: Response) => unknown\n    let reject: (error: Error) => unknown\n    const promise = new Promise((res, rej) => {\n      resolve = res\n      reject = rej\n    }) as unknown as MockFetchPromise\n    promise.resolveWith = (responseOptions: MockResponseOptions) => {\n      resolve(new MockResponse(responseOptions))\n      onRequestEnd()\n    }\n    promise.rejectWith = (error: Error) => {\n      reject(error)\n      onRequestEnd()\n    }\n    promise.abort = () => {\n      promise.rejectWith(new DOMException('The user aborted a request', 'AbortError'))\n    }\n\n    init?.signal?.addEventListener('abort', () => {\n      promise.rejectWith(init.signal?.reason)\n    })\n\n    return promise\n  }) as typeof window.fetch\n\n  registerCleanupTask(() => {\n    window.fetch = originalFetch\n    allFetchCompleteCallback = noop\n  })\n\n  return {\n    whenAllComplete(callback: () => void) {\n      allFetchCompleteCallback = callback\n    },\n  }\n}\n\nexport class MockResponse implements Response {\n  private _body: ReadableStream<Uint8ArrayBuffer> | undefined\n\n  constructor(private options: Readonly<MockResponseOptions>) {\n    if (this.options.bodyUsed) {\n      this._body = { locked: true } as any\n    } else if (this.options.bodyDisturbed) {\n      this._body = { disturbed: true } as any\n    } else if (this.options.body) {\n      this._body = this.options.body\n    } else if (this.options.responseTextError !== undefined) {\n      this._body = new ReadableStream({\n        start: (controller) => {\n          controller.error(this.options.responseTextError)\n        },\n      })\n    } else if (this.options.responseText !== undefined) {\n      this._body = new ReadableStream({\n        start: (controller) => {\n          controller.enqueue(new TextEncoder().encode(this.options.responseText))\n          controller.close()\n        },\n      })\n    }\n  }\n\n  get status() {\n    return this.options.status ?? 200\n  }\n\n  get method() {\n    return this.options.method ?? 'GET'\n  }\n\n  get type() {\n    return this.options.type ?? 'basic'\n  }\n\n  get bodyUsed() {\n    return this._body ? this._body.locked : false\n  }\n\n  get bodyDisturbed() {\n    return this._body ? !!(this._body as any).disturbed : false\n  }\n\n  get body() {\n    return this._body || null\n  }\n\n  clone() {\n    if (this.bodyUsed) {\n      throw new TypeError(\"Failed to execute 'clone' on 'Response': Response body is already used\")\n    }\n    if (this.bodyDisturbed) {\n      throw new TypeError('Cannot clone a disturbed Response')\n    }\n    return new MockResponse(this.options)\n  }\n\n  // Partial implementation, feel free to implement\n  /* eslint-disable @typescript-eslint/member-ordering */\n  arrayBuffer = notYetImplemented\n  text = notYetImplemented\n  blob = notYetImplemented\n  formData = notYetImplemented\n  json = notYetImplemented\n  bytes = notYetImplemented\n\n  /* eslint-enable @typescript-eslint/member-ordering */\n  get ok() {\n    return notYetImplemented()\n  }\n\n  get headers() {\n    return notYetImplemented()\n  }\n\n  get redirected() {\n    return notYetImplemented()\n  }\n\n  get statusText() {\n    return notYetImplemented()\n  }\n\n  get trailer() {\n    return notYetImplemented()\n  }\n\n  get url() {\n    return notYetImplemented()\n  }\n}\n\nexport interface MockResponseOptions {\n  status?: number\n  method?: string\n  type?: ResponseType\n  responseText?: string\n  responseTextError?: Error\n  body?: ReadableStream<Uint8ArrayBuffer>\n  bodyUsed?: boolean\n  bodyDisturbed?: boolean\n}\nexport type MockFetch = (input: RequestInfo, init?: RequestInit) => MockFetchPromise\n\nexport interface MockFetchPromise extends Promise<Response> {\n  resolveWith: (response: MockResponseOptions) => void\n  rejectWith: (error: Error) => void\n  abort: () => void\n}\n\nfunction notYetImplemented(): never {\n  throw new Error('not yet implemented')\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockFlushController.ts",
    "content": "import { Observable } from '../../src/tools/observable'\nimport type { PageExitReason } from '../../src/browser/pageMayExitObservable'\nimport type { FlushEvent, FlushController, FlushReason } from '../../src/transport'\n\nexport type MockFlushController = ReturnType<typeof createMockFlushController>\n\nexport function createMockFlushController() {\n  const flushObservable = new Observable<FlushEvent>()\n  const preparePageExitFlushObservable = new Observable<PageExitReason>()\n  let currentMessagesCount = 0\n  let currentBytesCount = 0\n\n  return {\n    notifyBeforeAddMessage: jasmine\n      .createSpy<FlushController['notifyBeforeAddMessage']>()\n      .and.callFake((messageBytesCount) => {\n        currentBytesCount += messageBytesCount\n        currentMessagesCount += 1\n      }),\n    notifyAfterAddMessage: jasmine\n      .createSpy<FlushController['notifyAfterAddMessage']>()\n      .and.callFake((messageBytesCountDiff = 0) => {\n        currentBytesCount += messageBytesCountDiff\n      }),\n    notifyAfterRemoveMessage: jasmine\n      .createSpy<FlushController['notifyAfterRemoveMessage']>()\n      .and.callFake((messageBytesCount) => {\n        currentBytesCount -= messageBytesCount\n        currentMessagesCount -= 1\n      }),\n    get messagesCount() {\n      return currentMessagesCount\n    },\n    get bytesCount() {\n      return currentBytesCount\n    },\n    flushObservable,\n    preparePageExitFlushObservable,\n    notifyFlush(reason: FlushReason = 'bytes_limit') {\n      if (currentMessagesCount === 0) {\n        throw new Error(\n          'MockFlushController.notifyFlush(): the original FlushController would not notify flush if no message was added'\n        )\n      }\n\n      const messagesCount = currentMessagesCount\n      const bytesCount = currentBytesCount\n\n      currentMessagesCount = 0\n      currentBytesCount = 0\n\n      flushObservable.notify({\n        reason,\n        bytesCount,\n        messagesCount,\n      })\n    },\n  } satisfies Record<any, any> & FlushController\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockNavigator.ts",
    "content": "import { registerCleanupTask } from '../registerCleanupTask'\nimport type { NetworkInformation } from '../../src'\n\nexport function setNavigatorOnLine(onLine: boolean) {\n  Object.defineProperty(navigator, 'onLine', {\n    get() {\n      return onLine\n    },\n    configurable: true,\n  })\n  registerCleanupTask(() => {\n    delete (navigator as any).onLine\n  })\n}\n\nexport function setNavigatorConnection(connection: Partial<NetworkInformation> | undefined) {\n  Object.defineProperty(navigator, 'connection', {\n    get() {\n      return connection\n    },\n    configurable: true,\n  })\n  registerCleanupTask(() => {\n    delete (navigator as any).connection\n  })\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockReportingObserver.ts",
    "content": "import type { InterventionReport, ReportType } from '../../src/domain/report/browser.types'\nimport { noop } from '../../src/tools/utils/functionUtils'\nimport { registerCleanupTask } from '../registerCleanupTask'\nimport { createNewEvent } from './createNewEvent'\n\nexport type MockReportingObserver = ReturnType<typeof mockReportingObserver>\n\nexport function mockReportingObserver() {\n  const originalReportingObserver = window.ReportingObserver\n  let callbacks: { [k: string]: ReportingObserverCallback[] } = {}\n  let reportingObserver: ReportingObserver\n\n  window.ReportingObserver = function (callback: ReportingObserverCallback, { types }: ReportingObserverOptions) {\n    types?.forEach((type) => {\n      if (!callbacks[type]) {\n        callbacks[type] = []\n      }\n\n      callbacks[type]?.push(callback)\n    })\n\n    reportingObserver = {\n      disconnect() {\n        noop()\n      },\n      observe() {\n        noop()\n      },\n      takeRecords() {\n        return []\n      },\n    }\n    return reportingObserver\n  } as unknown as typeof originalReportingObserver\n\n  registerCleanupTask(() => {\n    window.ReportingObserver = originalReportingObserver\n    callbacks = {}\n  })\n\n  return {\n    raiseReport(type: ReportType) {\n      if (callbacks[type]) {\n        callbacks[type].forEach((callback) => callback([{ ...FAKE_REPORT, type }], reportingObserver))\n      }\n    },\n  }\n}\n\nexport type MockCspEventListener = ReturnType<typeof mockCspEventListener>\n\nexport function mockCspEventListener() {\n  // eslint-disable-next-line @typescript-eslint/unbound-method\n  const originalAddEventListener = EventTarget.prototype.addEventListener\n  EventTarget.prototype.addEventListener = jasmine\n    .createSpy()\n    .and.callFake((_type: string, listener: EventListener) => {\n      listeners.push(listener)\n    })\n\n  registerCleanupTask(() => {\n    EventTarget.prototype.addEventListener = originalAddEventListener\n  })\n\n  const listeners: EventListener[] = []\n\n  return {\n    dispatchEvent() {\n      listeners.forEach((listener) => listener(FAKE_CSP_VIOLATION_EVENT))\n    },\n  }\n}\n\nexport const FAKE_CSP_VIOLATION_EVENT = createNewEvent('securitypolicyviolation', {\n  blockedURI: 'blob',\n  columnNumber: 8,\n  disposition: 'enforce',\n  documentURI: 'blob',\n  effectiveDirective: 'worker-src',\n  lineNumber: 17,\n  originalPolicy: \"worker-src 'none'\",\n  referrer: '',\n  sourceFile: 'http://foo.bar/index.js',\n  statusCode: 200,\n  violatedDirective: 'worker-src',\n})\n\nexport const FAKE_REPORT: InterventionReport = {\n  type: 'intervention',\n  url: 'http://foo.bar',\n  body: {\n    id: 'NavigatorVibrate',\n    columnNumber: 10,\n    lineNumber: 20,\n    message: 'foo bar',\n    sourceFile: 'http://foo.bar/index.js',\n    toJSON: noop,\n  },\n  toJSON: noop,\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockRequestIdleCallback.ts",
    "content": "import { registerCleanupTask } from '../registerCleanupTask'\n\n// Arbitrary remaining time for tests that don't care about remaining time\nconst DEFAULT_TIME_REMAINING = 10\n\nexport interface RequestIdleCallbackMock {\n  idle(timeRemaining?: number): void\n  timeout(): void\n  spy: jasmine.Spy<typeof window.requestIdleCallback>\n}\n\nexport function mockRequestIdleCallback(): RequestIdleCallbackMock {\n  let nextId = 1\n  const activeIds = new Set<number>()\n\n  const requestSpy = jasmine.createSpy<typeof window.requestIdleCallback>().and.callFake(() => {\n    const id = nextId\n    activeIds.add(id)\n    nextId++\n    return id\n  })\n\n  const cancelSpy = jasmine.createSpy<typeof window.cancelIdleCallback>().and.callFake((id: number) => {\n    activeIds.delete(id)\n  })\n\n  const originalRequestIdleCallback = window.requestIdleCallback\n  const originalCancelIdleCallback = window.cancelIdleCallback\n\n  window.requestIdleCallback = requestSpy\n  window.cancelIdleCallback = cancelSpy\n  registerCleanupTask(() => {\n    window.requestIdleCallback = originalRequestIdleCallback\n    window.cancelIdleCallback = originalCancelIdleCallback\n  })\n\n  function callAllActiveCallbacks(deadline: IdleDeadline) {\n    for (const call of requestSpy.calls.all().slice()) {\n      if (!activeIds.has(call.returnValue)) {\n        continue\n      }\n      activeIds.delete(call.returnValue)\n      call.args[0](deadline)\n    }\n  }\n\n  return {\n    idle(timeRemaining = DEFAULT_TIME_REMAINING) {\n      const now = Date.now()\n      callAllActiveCallbacks({\n        didTimeout: false,\n        timeRemaining: () => Math.max(0, timeRemaining - (Date.now() - now)),\n      })\n    },\n    timeout() {\n      callAllActiveCallbacks({\n        didTimeout: true,\n        timeRemaining: () => 0,\n      })\n    },\n    spy: requestSpy,\n  }\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockSyntheticsWorkerValues.ts",
    "content": "import { ONE_MINUTE } from '../../src/tools/utils/timeUtils'\nimport { deleteCookie, resetInitCookies, setCookie } from '../../src/browser/cookie'\nimport type { BrowserWindow, SyntheticsContext } from '../../src/domain/synthetics/syntheticsWorkerValues'\nimport {\n  SYNTHETICS_INJECTS_RUM_COOKIE_NAME,\n  SYNTHETICS_CONTEXT_COOKIE_NAME,\n  SYNTHETICS_TEST_ID_COOKIE_NAME,\n  SYNTHETICS_RESULT_ID_COOKIE_NAME,\n} from '../../src/domain/synthetics/syntheticsWorkerValues'\nimport { registerCleanupTask } from '../registerCleanupTask'\n\n// Duration to create a cookie lasting at least until the end of the test\nconst COOKIE_DURATION = ONE_MINUTE\n\nexport function mockSyntheticsWorkerValues(\n  {\n    injectsRum,\n    context,\n    publicId,\n    resultId,\n  }: {\n    injectsRum?: any\n    context?: SyntheticsContext\n    publicId?: any\n    resultId?: any\n  } = {\n    context: { test_id: 'synthetics_public_id', result_id: 'synthetics_result_id' },\n    injectsRum: false,\n  },\n  method: 'globals' | 'cookies' = 'globals'\n) {\n  switch (method) {\n    case 'globals':\n      ;(window as BrowserWindow)._DATADOG_SYNTHETICS_INJECTS_RUM = injectsRum\n      ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RUM_CONTEXT = context\n      ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = publicId\n      ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID = resultId\n      break\n    case 'cookies':\n      if (injectsRum !== undefined) {\n        setCookie(SYNTHETICS_INJECTS_RUM_COOKIE_NAME, injectsRum, COOKIE_DURATION)\n      }\n      if (context !== undefined) {\n        setCookie(SYNTHETICS_CONTEXT_COOKIE_NAME, encodeURIComponent(JSON.stringify(context)), COOKIE_DURATION)\n      }\n      if (publicId !== undefined) {\n        setCookie(SYNTHETICS_TEST_ID_COOKIE_NAME, publicId, COOKIE_DURATION)\n      }\n      if (resultId !== undefined) {\n        setCookie(SYNTHETICS_RESULT_ID_COOKIE_NAME, resultId, COOKIE_DURATION)\n      }\n      break\n  }\n  resetInitCookies()\n\n  registerCleanupTask(() => {\n    delete (window as BrowserWindow)._DATADOG_SYNTHETICS_INJECTS_RUM\n    delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RUM_CONTEXT\n    delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID\n    delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID\n    deleteCookie(SYNTHETICS_INJECTS_RUM_COOKIE_NAME)\n    deleteCookie(SYNTHETICS_CONTEXT_COOKIE_NAME)\n    deleteCookie(SYNTHETICS_TEST_ID_COOKIE_NAME)\n    deleteCookie(SYNTHETICS_RESULT_ID_COOKIE_NAME)\n    resetInitCookies()\n  })\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockTelemetry.ts",
    "content": "import { startMonitorErrorCollection } from '../../src/tools/monitor'\nimport {\n  addTelemetryError,\n  getTelemetryObservable,\n  resetTelemetry,\n  type RawTelemetryEvent,\n  type Telemetry,\n} from '../../src/domain/telemetry'\nimport { registerCleanupTask } from '../registerCleanupTask'\nimport { noop } from '../../src/tools/utils/functionUtils'\n\nexport interface MockTelemetry {\n  getEvents: () => Promise<RawTelemetryEvent[]>\n  hasEvents: () => Promise<boolean>\n  reset: () => void\n}\n\nexport function startMockTelemetry() {\n  resetTelemetry()\n  const events: RawTelemetryEvent[] = []\n\n  const telemetryObservable = getTelemetryObservable()\n  const subscription = telemetryObservable.subscribe(({ rawEvent }) => {\n    events.push(rawEvent)\n  })\n  telemetryObservable.unbuffer()\n\n  startMonitorErrorCollection(addTelemetryError)\n\n  registerCleanupTask(() => {\n    subscription.unsubscribe()\n  })\n\n  function getEvents() {\n    // Using a Promise to ensure the consumer waits after the next microtask so events are collected\n    return Promise.resolve(events)\n  }\n\n  return {\n    getEvents,\n    hasEvents: () => getEvents().then((events) => events.length > 0),\n    reset: () => {\n      events.length = 0\n    },\n  }\n}\n\nexport function createFakeTelemetryObject(): Telemetry {\n  return {\n    stop: noop,\n    enabled: false,\n    metricsEnabled: false,\n  }\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockVisibilityState.ts",
    "content": "export function setPageVisibility(visibility: 'visible' | 'hidden') {\n  Object.defineProperty(document, 'visibilityState', {\n    get() {\n      return visibility\n    },\n    configurable: true,\n  })\n}\n\nexport function restorePageVisibility() {\n  delete (document as any).visibilityState\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockXhr.ts",
    "content": "import { isServerError, noop } from '../../src'\nimport { registerCleanupTask } from '../registerCleanupTask'\nimport { createNewEvent } from './createNewEvent'\nimport { MockEventTarget } from './mockEventTarget'\n\nexport function mockXhr() {\n  const originalXhr = XMLHttpRequest\n\n  window.XMLHttpRequest = MockXhr as any\n\n  registerCleanupTask(() => {\n    window.XMLHttpRequest = originalXhr\n  })\n}\n\nexport function withXhr({\n  setup,\n  onComplete,\n}: {\n  setup: (xhr: MockXhr) => void\n  onComplete: (xhr: XMLHttpRequest) => void\n}) {\n  const xhr = new XMLHttpRequest()\n  const loadend = () => {\n    xhr.removeEventListener('loadend', loadend)\n    setTimeout(() => {\n      onComplete(xhr)\n    })\n  }\n  xhr.addEventListener('loadend', loadend)\n  setup(xhr as unknown as MockXhr)\n}\n\nexport class MockXhr extends MockEventTarget {\n  public static onSend: (xhr: MockXhr) => void\n  public response: string | undefined = undefined\n  public responseText: string | undefined = undefined\n  public status: number | undefined = undefined\n  public readyState: number = XMLHttpRequest.UNSENT\n  public onreadystatechange: () => void = noop\n\n  private hasEnded = false\n\n  /* eslint-disable @typescript-eslint/no-unused-vars */\n  open(method: string | undefined | null, url: string | URL | undefined | null) {\n    this.hasEnded = false\n  }\n\n  send() {\n    MockXhr.onSend?.(this)\n  }\n\n  abort() {\n    this.status = 0\n    if (this.hasEnded) {\n      // Calling xhr.abort() on an ended request does not trigger events\n      return\n    }\n    this.hasEnded = true\n    this.readyState = XMLHttpRequest.DONE\n    this.onreadystatechange()\n    this.dispatchEvent(createNewEvent('abort'))\n    this.dispatchEvent(createNewEvent('loadend'))\n  }\n\n  complete(status: number, response?: string) {\n    if (this.hasEnded) {\n      throw new Error(\"Can't call complete() on a ended request\")\n    }\n    this.hasEnded = true\n    this.response = response\n    this.responseText = response\n    this.status = status\n    this.readyState = XMLHttpRequest.DONE\n\n    this.onreadystatechange()\n\n    if (status >= 200 && status < 500) {\n      this.dispatchEvent(createNewEvent('load'))\n    }\n    if (isServerError(status)) {\n      this.dispatchEvent(createNewEvent('error'))\n    }\n    this.dispatchEvent(createNewEvent('loadend'))\n  }\n}\n"
  },
  {
    "path": "packages/core/test/emulate/mockZoneJs.ts",
    "content": "import type { BrowserWindowWithZoneJs } from '../../src/tools/getZoneJsOriginalValue'\nimport { registerCleanupTask } from '../registerCleanupTask'\n\nexport type MockZoneJs = ReturnType<typeof mockZoneJs>\n\nexport function mockZoneJs() {\n  const browserWindow = window as BrowserWindowWithZoneJs\n  const restorers: Array<() => void> = []\n\n  function getSymbol(name: string) {\n    return `__zone_symbol__${name}`\n  }\n\n  browserWindow.Zone = { __symbol__: getSymbol }\n\n  registerCleanupTask(() => {\n    delete browserWindow.Zone\n    restorers.forEach((restorer) => restorer())\n  })\n\n  return {\n    getSymbol,\n    replaceProperty<Target, Name extends keyof Target & string>(target: Target, name: Name, replacement: Target[Name]) {\n      const original = target[name]\n      target[name] = replacement\n      ;(target as any)[getSymbol(name)] = original\n      restorers.push(() => {\n        delete (target as any)[getSymbol(name)]\n        target[name] = original\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/test/fakeSessionStoreStrategy.ts",
    "content": "import type { Configuration } from '../src/domain/configuration'\nimport type { SessionState } from '../src/domain/session/sessionState'\nimport { getExpiredSessionState } from '../src/domain/session/sessionState'\n\nexport function createFakeSessionStoreStrategy({\n  isLockEnabled = false,\n  initialSession = {},\n}: { isLockEnabled?: boolean; initialSession?: SessionState } = {}) {\n  let session: SessionState = initialSession\n  const plannedRetrieveSessions: SessionState[] = []\n\n  return {\n    isLockEnabled,\n\n    persistSession: jasmine.createSpy('persistSession').and.callFake((newSession) => {\n      session = newSession\n    }),\n\n    retrieveSession: jasmine.createSpy<() => SessionState>('retrieveSession').and.callFake(() => {\n      const plannedSession = plannedRetrieveSessions.shift()\n      if (plannedSession) {\n        session = plannedSession\n      }\n      return { ...session }\n    }),\n\n    expireSession: jasmine.createSpy('expireSession').and.callFake((previousSession) => {\n      session = getExpiredSessionState(previousSession, { trackAnonymousUser: true } as Configuration)\n    }),\n\n    planRetrieveSession: (index: number, fakeSession: SessionState) => {\n      plannedRetrieveSessions[index] = fakeSession\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/test/forEach.spec.ts",
    "content": "import { resetManageResourceTimingBufferFull } from '../../rum-core/src/browser/performanceObservable'\nimport { resetExperimentalFeatures } from '../src/tools/experimentalFeatures'\nimport { resetValueHistoryGlobals } from '../src/tools/valueHistory'\nimport { resetFetchObservable } from '../src/browser/fetchObservable'\nimport { resetConsoleObservable } from '../src/domain/console/consoleObservable'\nimport { resetXhrObservable } from '../src/browser/xhrObservable'\nimport { resetGetCurrentSite } from '../src/browser/cookie'\nimport { resetReplayStats } from '../../rum/src/domain/replayStats'\nimport { resetInteractionCountPolyfill } from '../../rum-core/src/domain/view/viewMetrics/interactionCountPolyfill'\nimport { resetMonitor } from '../src/tools/monitor'\nimport { resetTelemetry } from '../src/domain/telemetry'\nimport { startLeakDetection } from './leakDetection'\nimport type { BuildEnvWindow } from './buildEnv'\n;(window as unknown as BuildEnvWindow).__BUILD_ENV__SDK_VERSION__ = 'test'\n;(window as any).IS_REACT_ACT_ENVIRONMENT = true\n\nbeforeEach(() => {\n  // prevent 'Some of your tests did a full page reload!' issue\n  window.onbeforeunload = () => 'stop'\n  startLeakDetection()\n  // Note: clearing cookies should be done in `beforeEach` rather than `afterEach`, because in some\n  // cases the test patches the `document.cookie` getter (ex: `spyOnProperty(document, 'cookie',\n  // 'get')`), which would prevent the `clearAllCookies` function from working properly.\n  clearAllCookies()\n})\n\nafterEach(() => {\n  // reset globals\n  delete (window as any).DD_LOGS\n  delete (window as any).DD_RUM\n  resetValueHistoryGlobals()\n  resetFetchObservable()\n  resetConsoleObservable()\n  resetXhrObservable()\n  resetGetCurrentSite()\n  resetReplayStats()\n  resetMonitor()\n  resetTelemetry()\n  resetInteractionCountPolyfill()\n  resetExperimentalFeatures()\n  resetManageResourceTimingBufferFull()\n})\n\nfunction clearAllCookies() {\n  document.cookie.split(';').forEach((c) => {\n    document.cookie = c.replace(/=.*/, `=;expires=${new Date(0).toUTCString()};path=/;samesite=strict`)\n  })\n}\n"
  },
  {
    "path": "packages/core/test/getCurrentJasmineSpec.ts",
    "content": "let currentSpec: jasmine.SpecResult | null = null\n\nexport function getCurrentJasmineSpec() {\n  return currentSpec\n}\n\njasmine.getEnv().addReporter({\n  specStarted(specResult) {\n    currentSpec = specResult\n  },\n  specDone() {\n    currentSpec = null\n  },\n})\n"
  },
  {
    "path": "packages/core/test/index.ts",
    "content": "export * from './browserChecks'\nexport * from './browserExtension'\nexport type * from './buildEnv'\nexport * from './collectAsyncCalls'\nexport * from './cookie'\nexport * from './registerCleanupTask'\nexport * from './interceptRequests'\nexport * from './emulate/createNewEvent'\nexport * from './emulate/buildLocation'\nexport * from './emulate/mockClock'\nexport * from './emulate/mockReportingObserver'\nexport * from './emulate/mockZoneJs'\nexport * from './emulate/mockSyntheticsWorkerValues'\nexport * from './emulate/mockVisibilityState'\nexport * from './emulate/mockNavigator'\nexport * from './emulate/mockEventBridge'\nexport * from './emulate/mockFlushController'\nexport * from './emulate/mockFetch'\nexport * from './emulate/mockXhr'\nexport * from './emulate/mockEventTarget'\nexport * from './emulate/mockRequestIdleCallback'\nexport * from './emulate/mockTelemetry'\nexport type * from './typeUtils'\nexport * from './coreConfiguration'\nexport * from './disableJasmineUncaughtExceptionTracking'\nexport * from './instrumentation'\nexport * from './wait'\nexport * from './consoleLog'\nexport * from './createHooks'\nexport * from './fakeSessionStoreStrategy'\nexport * from './readFormData'\nexport * from './replaceMockable'\n"
  },
  {
    "path": "packages/core/test/instrumentation.ts",
    "content": "/**\n * Create a fluent interface for asserting that the given callback adds\n *\n * @example\n * ```ts\n * callbackAddsInstrumentation(() => {\n *   // ... code that's intended to instrument window.foo ...\n * }).toMethod(window, 'foo').whenCalled()\n * ```\n */\nexport function callbackAddsInstrumentation(callback: () => void) {\n  const existingMethods: Array<[any, PropertyKey, unknown]> = []\n  const expectation = {\n    callback,\n    toMethod<TARGET extends { [key: string]: any }, METHOD extends keyof TARGET>(target: TARGET, method: METHOD) {\n      existingMethods.push([target, method, target[method]])\n      return expectation\n    },\n    whenCalled() {\n      callback()\n      return existingMethods.every(([target, method, original]) => target[method] !== original)\n    },\n  }\n  return expectation\n}\n"
  },
  {
    "path": "packages/core/test/interceptRequests.ts",
    "content": "import type { EndpointBuilder } from '../src'\nimport { INTAKE_URL_PARAMETERS, noop } from '../src'\nimport { mockXhr, MockXhr } from './emulate/mockXhr'\nimport { readFormData } from './readFormData'\nimport { registerCleanupTask } from './registerCleanupTask'\n\nconst INTAKE_PARAMS = INTAKE_URL_PARAMETERS.join('&')\n\nexport const DEFAULT_FETCH_MOCK = () => Promise.resolve({ status: 200, type: 'cors' })\nexport const TOO_MANY_REQUESTS_FETCH_MOCK = () => Promise.resolve({ status: 429, type: 'cors' })\nexport const NETWORK_ERROR_FETCH_MOCK = () => Promise.reject(new Error('Network request failed'))\n\nexport const SPEC_ENDPOINTS = {\n  logsEndpointBuilder: mockEndpointBuilder(`https://mock.com/abcde?${INTAKE_PARAMS}`),\n  rumEndpointBuilder: mockEndpointBuilder(`https://mock.com/abcde?${INTAKE_PARAMS}`),\n}\n\nexport function mockEndpointBuilder(url: string) {\n  return { build: (..._: any) => url } as EndpointBuilder\n}\n\nexport interface Request {\n  type: 'sendBeacon' | 'fetch'\n  url: string\n  body: string\n}\n\nexport function interceptRequests() {\n  const requests: Request[] = []\n  const originalSendBeacon = isSendBeaconSupported() && navigator.sendBeacon.bind(navigator)\n  const originalRequest = window.Request\n  const originalFetch = window.fetch\n\n  if (isSendBeaconSupported()) {\n    spyOn(navigator, 'sendBeacon').and.callFake((url, body) => {\n      requests.push({ type: 'sendBeacon', url: url as string, body: body as string })\n      return true\n    })\n  }\n\n  let fetchMocks: Array<() => Promise<unknown>> = [DEFAULT_FETCH_MOCK]\n\n  let resolveFetchCallReturns: (() => void) | undefined\n  const endAllPromises = new Promise<void>((resolve) => {\n    resolveFetchCallReturns = resolve\n  })\n\n  const fetchSpy = spyOn(window, 'fetch').and.callFake((url, config) => {\n    const fetchPromise = fetchMocks.shift()\n\n    if (!fetchPromise) {\n      throw new Error('No fetch mock provided')\n    }\n\n    requests.push({\n      type: 'fetch',\n      url: url as string,\n      body: config?.body as string,\n    })\n    return fetchPromise()\n      .then((response) => response as Response)\n      .finally(() => {\n        if (fetchMocks.length === 0) {\n          resolveFetchCallReturns?.()\n        }\n      })\n  })\n\n  function isSendBeaconSupported() {\n    return !!navigator.sendBeacon\n  }\n\n  registerCleanupTask(() => {\n    if (originalSendBeacon) {\n      navigator.sendBeacon = originalSendBeacon\n    }\n    if (originalRequest) {\n      window.Request = originalRequest\n    }\n    if (originalFetch) {\n      window.fetch = originalFetch\n    }\n    MockXhr.onSend = noop\n  })\n\n  return {\n    requests,\n    isSendBeaconSupported,\n    waitForAllFetchCalls: () => endAllPromises,\n    withSendBeacon(newSendBeacon: any) {\n      navigator.sendBeacon = newSendBeacon\n    },\n    withRequest(newRequest: any) {\n      window.Request = newRequest\n    },\n    withFetch(...responses: Array<() => Promise<unknown>>) {\n      fetchMocks = responses\n      return fetchSpy\n    },\n    withMockXhr(onSend: (xhr: MockXhr) => void) {\n      mockXhr()\n      MockXhr.onSend = onSend\n    },\n  }\n}\nexport function readFormDataRequest<T>(request: Request): Promise<T> {\n  return readFormData(request.body as unknown as FormData)\n}\n"
  },
  {
    "path": "packages/core/test/leakDetection.ts",
    "content": "import { display } from '../src/tools/display'\nimport { getCurrentJasmineSpec } from './getCurrentJasmineSpec'\nimport { registerCleanupTask } from './registerCleanupTask'\n\nexport function startLeakDetection() {\n  let wrappedListeners: {\n    [key: string]: Map<EventListenerOrEventListenerObject | null, EventListenerOrEventListenerObject | null>\n  } = {}\n\n  // eslint-disable-next-line @typescript-eslint/unbound-method\n  const originalAddEventListener = EventTarget.prototype.addEventListener\n  // eslint-disable-next-line @typescript-eslint/unbound-method\n  const originalRemoveEventListener = EventTarget.prototype.removeEventListener\n\n  EventTarget.prototype.addEventListener = function (event, listener, options) {\n    if (!wrappedListeners[event]) {\n      wrappedListeners[event] = new Map()\n    }\n    const wrappedListener = withLeakDetection(event, listener as EventListener)\n    wrappedListeners[event].set(listener, wrappedListener)\n    return originalAddEventListener.call(this, event, wrappedListener, options)\n  }\n  EventTarget.prototype.removeEventListener = function (event, listener, options) {\n    const wrappedListener = wrappedListeners[event]?.get(listener)\n    wrappedListeners[event]?.delete(listener)\n    return originalRemoveEventListener.call(this, event, wrappedListener || listener, options)\n  }\n\n  registerCleanupTask(() => {\n    EventTarget.prototype.addEventListener = originalAddEventListener\n    EventTarget.prototype.removeEventListener = originalRemoveEventListener\n    wrappedListeners = {}\n  })\n}\n\nfunction withLeakDetection(eventName: string, listener: EventListener) {\n  const specWhenAdded = getCurrentJasmineSpec()\n  const stackWhenAdded = new Error().stack\n  if (\n    !specWhenAdded ||\n    // Ignore listeners added by React: React is adding listeners to DOM elements for synthetic events, and there is no way to remove them\n    stackWhenAdded?.includes('listenToAllSupportedEvents')\n  ) {\n    return listener\n  }\n\n  return (event: Event) => {\n    const currentSpec = getCurrentJasmineSpec()\n    if (!currentSpec || specWhenAdded.fullName !== currentSpec.fullName) {\n      display.error(`Leaked listener\n  event names: \"${eventName}\"\n  attached with: \"${specWhenAdded.fullName}\"\n  ${currentSpec ? `executed with: \"${currentSpec.fullName}\"` : 'executed outside of a spec'}\n  attachment stack: ${stackWhenAdded}`)\n    }\n    listener(event)\n  }\n}\n"
  },
  {
    "path": "packages/core/test/mockGlobalContext.ts",
    "content": "import type { ContextManager } from '../src/domain/context/contextManager'\n\nexport function mockContextManager() {\n  return {\n    getContext: () => ({}),\n    setContext: jasmine.createSpy(),\n    setContextProperty: jasmine.createSpy(),\n    removeContextProperty: jasmine.createSpy(),\n    clearContext: jasmine.createSpy(),\n  } as unknown as ContextManager\n}\n"
  },
  {
    "path": "packages/core/test/readFormData.ts",
    "content": "import { inflate } from 'pako'\n\n// Zlib streams using a default compression are starting with bytes 120 156 (0x78 0x9c)\n// https://stackoverflow.com/a/9050274\nconst Z_LIB_MAGIC_BYTES = 0x789c\n\nexport async function readFormData<T>(formData: FormData): Promise<T> {\n  const entries = getEntries(formData)\n  const data: Record<string, unknown> = {}\n\n  for (const [key, value] of Object.entries(entries)) {\n    if (value instanceof Blob) {\n      data[key] = await readJsonBlob(value)\n    } else {\n      data[key] = value\n    }\n  }\n\n  return data as T\n}\n\nfunction getEntries(payload: FormData) {\n  const entries = {} as Record<string, FormDataEntryValue>\n  payload.forEach((data, key) => {\n    entries[key] = data\n  })\n  return entries\n}\n\nfunction isZlibCompressed(buffer: ArrayBuffer) {\n  return new DataView(buffer).getUint16(0) === Z_LIB_MAGIC_BYTES\n}\n\nfunction readJsonBlob<T>(blob: Blob): Promise<T> {\n  // Safari Mobile 14 should support blob.text() or blob.arrayBuffer() but the APIs are not defined on the safari\n  // provided by browserstack, so we still need to use a FileReader for now.\n  // https://caniuse.com/mdn-api_blob_arraybuffer\n  // https://caniuse.com/mdn-api_blob_text\n  return new Promise((resolve) => {\n    const reader = new FileReader()\n    reader.addEventListener('loadend', () => {\n      const buffer = reader.result as ArrayBuffer\n      const decompressed = isZlibCompressed(buffer) ? inflate(buffer) : buffer\n      const decoded = new TextDecoder().decode(decompressed)\n      const deserialized = JSON.parse(decoded)\n\n      resolve(deserialized as T)\n    })\n    reader.readAsArrayBuffer(blob)\n  })\n}\n"
  },
  {
    "path": "packages/core/test/registerCleanupTask.ts",
    "content": "type CleanupTask = () => unknown\n\nconst cleanupTasks: CleanupTask[] = []\n\nexport function registerCleanupTask(task: CleanupTask) {\n  cleanupTasks.unshift(task)\n}\n\nafterEach(async () => {\n  for (const task of cleanupTasks.splice(0)) {\n    await task()\n  }\n})\n"
  },
  {
    "path": "packages/core/test/replaceMockable.ts",
    "content": "import { mockableReplacements } from '../src/tools/mockable'\nimport { registerCleanupTask } from './registerCleanupTask'\n\n/**\n * Registers a mock replacement for a mockable value. The mock is automatically\n * cleaned up after each test via registerCleanupTask.\n *\n * @param value - The original value (must be the same reference passed to mockable())\n * @param replacement - The mock replacement\n * @example\n * import { replaceMockable } from '@datadog/browser-core/test'\n * import { trackRuntimeError } from '../domain/error/trackRuntimeError'\n *\n * it('...', () => {\n *   replaceMockable(trackRuntimeError, () => new Observable<RawError>())\n *   // ... test code ...\n * })\n */\nexport function replaceMockable<T>(value: T, replacement: T): void {\n  if (mockableReplacements.has(value)) {\n    throw new Error('Mock has already been set')\n  }\n  mockableReplacements.set(value, replacement)\n  registerCleanupTask(() => {\n    mockableReplacements.delete(value)\n  })\n}\n\n/**\n * Creates a Jasmine spy and registers it as a mock replacement for a mockable function.\n * The mock is automatically cleaned up after each test via registerCleanupTask.\n *\n * @param value - The original function (must be the same reference passed to mockable())\n * @returns A Jasmine spy that can be used for assertions\n * @example\n * import { replaceMockableWithSpy } from '@datadog/browser-core/test'\n * import { trackRuntimeError } from '../domain/error/trackRuntimeError'\n *\n * it('...', () => {\n *   const spy = replaceMockableWithSpy(trackRuntimeError)\n *   // ... test code ...\n *   expect(spy).toHaveBeenCalled()\n * })\n */\nexport function replaceMockableWithSpy<T extends (...args: any[]) => any>(value: T): jasmine.Spy<T> {\n  const spy = jasmine.createSpy<T>()\n  replaceMockable(value, spy as unknown as T)\n  return spy\n}\n"
  },
  {
    "path": "packages/core/test/typeUtils.ts",
    "content": "/**\n * Remove the index signature from an object type\n *\n * @example\n * type Foo = { a: string, b: number, [key: string]: any }\n * type Bar = RemoveIndex<Foo> // { a: string, b: number }\n */\nexport type RemoveIndex<T> = {\n  [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K]\n}\n\n/**\n * Turn a camel case string into a snake case string\n *\n * @example\n * type Foo = CamelToSnakeCase<'fooBarBaz'> // 'foo_bar_baz'\n */\nexport type CamelToSnakeCase<S extends string> = S extends `${infer T}${infer U}`\n  ? `${T extends Capitalize<T> ? '_' : ''}${Lowercase<T>}${CamelToSnakeCase<U>}`\n  : S\n"
  },
  {
    "path": "packages/core/test/wait.ts",
    "content": "export function wait(durationMs: number = 0): Promise<void> {\n  return new Promise((resolve) => {\n    setTimeout(resolve, durationMs)\n  })\n}\n\nexport function waitNextMicrotask(): Promise<void> {\n  return Promise.resolve()\n}\n\nexport function waitAfterNextPaint() {\n  return new Promise<void>((resolve) => {\n    requestAnimationFrame(() => {\n      requestAnimationFrame(() => {\n        resolve()\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "packages/logs/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/logs/BROWSER_SUPPORT.md",
    "content": "# Browser Support\n\n| Feature        | Chrome | Firefox | Safari | Edge | Chrome Android | Safari iOS | IE  | Opera |\n| -------------- | ------ | ------- | ------ | ---- | -------------- | ---------- | --- | ----- |\n| loading        | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| init           | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| global context | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| logs request   | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| flush on hide  | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| console error  | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| network error  | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| runtime error  | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| CSP violation  | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| reports        | ✅     | ❌      | ❌     | ✅   | ✅             | ❌         | ❌  | ✅    |\n| custom logger  | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| handler        | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n"
  },
  {
    "path": "packages/logs/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/logs/README.md",
    "content": "# Browser Log Collection\n\nSend logs to Datadog from web browser pages with the browser logs SDK.\n\nSee the [dedicated datadog documentation][1] for more details.\n\n## Usage\n\nAfter adding [`@datadog/browser-logs`][2] to your `package.json` file, initialize it with:\n\n```javascript\nimport { datadogLogs } from '@datadog/browser-logs'\n\ndatadogLogs.init({\n  clientToken: '<DATADOG_CLIENT_TOKEN>',\n  site: '<DATADOG_SITE>',\n  forwardErrorsToLogs: true,\n  sessionSampleRate: 100,\n})\n```\n\nAfter the Datadog browser logs SDK is initialized, send custom log entries directly to Datadog:\n\n```javascript\nimport { datadogLogs } from '@datadog/browser-logs'\n\ndatadogLogs.logger.info('Button clicked', { name: 'buttonName', id: 123 })\n\ntry {\n  ...\n  throw new Error('Wrong behavior')\n  ...\n} catch (ex) {\n  datadogLogs.logger.error('Error occurred', { team: 'myTeam' }, ex)\n}\n```\n\n<!-- Note: all URLs should be absolute -->\n\n[1]: https://docs.datadoghq.com/logs/log_collection/javascript\n[2]: https://www.npmjs.com/package/@datadog/browser-logs\n"
  },
  {
    "path": "packages/logs/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-logs\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"bundle/**/*.js\",\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules --bundle datadog-logs.js\",\n    \"build:bundle\": \"node ../../scripts/build/build-package.ts --bundle datadog-logs.js\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"6.32.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    }\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/logs\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/boot/logsPublicApi.spec.ts",
    "content": "import type { ContextManager } from '@datadog/browser-core'\nimport { monitor, display, createContextManager, TrackingConsent, startTelemetry } from '@datadog/browser-core'\nimport { HandlerType } from '../domain/logger'\nimport { StatusType } from '../domain/logger/isAuthorized'\nimport { createFakeTelemetryObject, replaceMockable, replaceMockableWithSpy } from '../../../core/test'\nimport type { LogsPublicApi } from './logsPublicApi'\nimport { makeLogsPublicApi } from './logsPublicApi'\nimport type { StartLogs, StartLogsResult } from './startLogs'\nimport { startLogs } from './startLogs'\n\nconst DEFAULT_INIT_CONFIGURATION = { clientToken: 'xxx', trackingConsent: TrackingConsent.GRANTED }\n\nconst mockSessionId = 'some-session-id'\nconst getInternalContext = () => ({ session_id: mockSessionId })\n\ndescribe('logs entry', () => {\n  it('should add a `_setDebug` that works', () => {\n    const displaySpy = spyOn(display, 'error')\n    const { logsPublicApi } = makeLogsPublicApiWithDefaults()\n    const setDebug: (debug: boolean) => void = (logsPublicApi as any)._setDebug\n    expect(!!setDebug).toEqual(true)\n\n    monitor(() => {\n      throw new Error()\n    })()\n    expect(displaySpy).toHaveBeenCalledTimes(0)\n\n    setDebug(true)\n    monitor(() => {\n      throw new Error()\n    })()\n    expect(displaySpy).toHaveBeenCalledTimes(1)\n\n    setDebug(false)\n  })\n\n  it('should define the public API with init', () => {\n    const { logsPublicApi } = makeLogsPublicApiWithDefaults()\n    expect(!!logsPublicApi).toEqual(true)\n    expect(!!logsPublicApi.init).toEqual(true)\n  })\n\n  it('should provide sdk version', () => {\n    const { logsPublicApi } = makeLogsPublicApiWithDefaults()\n    expect(logsPublicApi.version).toBe('test')\n  })\n\n  describe('common context', () => {\n    let logsPublicApi: LogsPublicApi\n    let startLogsSpy: jasmine.Spy<StartLogs>\n\n    beforeEach(() => {\n      ;({ logsPublicApi, startLogsSpy } = makeLogsPublicApiWithDefaults())\n      logsPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n    })\n\n    it('should have the current date, view and global context', () => {\n      logsPublicApi.setGlobalContextProperty('foo', 'bar')\n\n      const getCommonContext = startLogsSpy.calls.mostRecent().args[1]\n      expect(getCommonContext()).toEqual({\n        view: {\n          referrer: document.referrer,\n          url: window.location.href,\n        },\n      })\n    })\n  })\n\n  describe('post start API usages', () => {\n    let logsPublicApi: LogsPublicApi\n    let getLoggedMessage: ReturnType<typeof makeLogsPublicApiWithDefaults>['getLoggedMessage']\n    let userContext: ContextManager\n    let accountContext: ContextManager\n\n    beforeEach(() => {\n      userContext = createContextManager('mock')\n      accountContext = createContextManager('mock')\n      ;({ logsPublicApi, getLoggedMessage } = makeLogsPublicApiWithDefaults({\n        startLogsResult: {\n          userContext,\n          accountContext,\n        },\n      }))\n      logsPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n    })\n\n    it('main logger logs a message', () => {\n      logsPublicApi.logger.log('message')\n\n      expect(getLoggedMessage(0).message).toEqual({\n        message: 'message',\n        status: StatusType.info,\n        context: undefined,\n      })\n    })\n\n    it('returns cloned initial configuration', () => {\n      expect(logsPublicApi.getInitConfiguration()).toEqual(DEFAULT_INIT_CONFIGURATION)\n      expect(logsPublicApi.getInitConfiguration()).not.toBe(DEFAULT_INIT_CONFIGURATION)\n    })\n\n    describe('custom loggers', () => {\n      it('logs a message', () => {\n        const logger = logsPublicApi.createLogger('foo')\n        logger.log('message')\n\n        expect(getLoggedMessage(0).message).toEqual({\n          message: 'message',\n          status: StatusType.info,\n          context: undefined,\n        })\n      })\n\n      it('should have a default configuration', () => {\n        const logger = logsPublicApi.createLogger('foo')\n\n        expect(logger.getHandler()).toEqual(HandlerType.http)\n        expect(logger.getLevel()).toEqual(StatusType.debug)\n      })\n\n      it('should be configurable', () => {\n        const logger = logsPublicApi.createLogger('foo', {\n          handler: HandlerType.console,\n          level: StatusType.info,\n        })\n\n        expect(logger.getHandler()).toEqual(HandlerType.console)\n        expect(logger.getLevel()).toEqual(StatusType.info)\n      })\n\n      it('should be configurable with multiple handlers', () => {\n        const logger = logsPublicApi.createLogger('foo', {\n          handler: [HandlerType.console, HandlerType.http],\n        })\n\n        expect(logger.getHandler()).toEqual([HandlerType.console, HandlerType.http])\n      })\n\n      it('should have their name in their context', () => {\n        const logger = logsPublicApi.createLogger('foo')\n\n        expect(logger.getContext().logger).toEqual({ name: 'foo' })\n      })\n\n      it('could be initialized with a dedicated context', () => {\n        const logger = logsPublicApi.createLogger('context', {\n          context: { foo: 'bar' },\n        })\n\n        expect(logger.getContext().foo).toEqual('bar')\n      })\n\n      it('should be retrievable', () => {\n        const logger = logsPublicApi.createLogger('foo')\n        expect(logsPublicApi.getLogger('foo')).toEqual(logger)\n        expect(logsPublicApi.getLogger('bar')).toBeUndefined()\n      })\n    })\n\n    describe('internal context', () => {\n      it('should get the internal context', () => {\n        expect(logsPublicApi.getInternalContext()?.session_id).toEqual(mockSessionId)\n      })\n    })\n\n    describe('user', () => {\n      it('should call setContext', () => {\n        spyOn(userContext, 'setContext')\n        logsPublicApi.setUser(2 as any)\n        expect(userContext.setContext).toHaveBeenCalledTimes(1)\n      })\n\n      it('should call setContextProperty', () => {\n        spyOn(userContext, 'setContextProperty')\n        logsPublicApi.setUserProperty('foo', 'bar')\n        expect(userContext.setContextProperty).toHaveBeenCalledTimes(1)\n      })\n\n      it('should call removeContextProperty', () => {\n        spyOn(userContext, 'removeContextProperty')\n        logsPublicApi.removeUserProperty('foo')\n        expect(userContext.removeContextProperty).toHaveBeenCalledTimes(1)\n      })\n\n      it('should call clearContext', () => {\n        spyOn(userContext, 'clearContext')\n        logsPublicApi.clearUser()\n        expect(userContext.clearContext).toHaveBeenCalledTimes(1)\n      })\n    })\n\n    describe('account', () => {\n      it('should call setContext', () => {\n        spyOn(accountContext, 'setContext')\n        logsPublicApi.setAccount(2 as any)\n        expect(accountContext.setContext).toHaveBeenCalledTimes(1)\n      })\n\n      it('should call setContextProperty', () => {\n        spyOn(accountContext, 'setContextProperty')\n        logsPublicApi.setAccountProperty('foo', 'bar')\n        expect(accountContext.setContextProperty).toHaveBeenCalledTimes(1)\n      })\n\n      it('should call removeContextProperty', () => {\n        spyOn(accountContext, 'removeContextProperty')\n        logsPublicApi.removeAccountProperty('foo')\n        expect(accountContext.removeContextProperty).toHaveBeenCalledTimes(1)\n      })\n\n      it('should call clearContext', () => {\n        spyOn(accountContext, 'clearContext')\n        logsPublicApi.clearAccount()\n        expect(accountContext.clearContext).toHaveBeenCalledTimes(1)\n      })\n    })\n  })\n})\n\nfunction makeLogsPublicApiWithDefaults({\n  startLogsResult,\n}: {\n  startLogsResult?: Partial<StartLogsResult>\n} = {}) {\n  const handleLogSpy = jasmine.createSpy<StartLogsResult['handleLog']>()\n  const startLogsSpy = replaceMockableWithSpy(startLogs).and.callFake(() => ({\n    handleLog: handleLogSpy,\n    getInternalContext,\n    accountContext: {} as any,\n    globalContext: {} as any,\n    userContext: {} as any,\n    stop: () => undefined,\n    ...startLogsResult,\n  }))\n\n  function getLoggedMessage(index: number) {\n    const [message, logger, savedCommonContext, savedDate] = handleLogSpy.calls.argsFor(index)\n    return { message, logger, savedCommonContext, savedDate }\n  }\n\n  replaceMockable(startTelemetry, createFakeTelemetryObject)\n\n  return {\n    startLogsSpy,\n    logsPublicApi: makeLogsPublicApi(),\n    getLoggedMessage,\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/boot/logsPublicApi.ts",
    "content": "import type { TrackingConsent, PublicApi, ContextManager, Account, Context, User } from '@datadog/browser-core'\nimport {\n  ContextManagerMethod,\n  CustomerContextKey,\n  addTelemetryUsage,\n  makePublicApi,\n  monitor,\n  sanitize,\n  displayAlreadyInitializedError,\n  deepClone,\n  createTrackingConsentState,\n  defineContextMethod,\n  startBufferingData,\n  callMonitored,\n  mockable,\n} from '@datadog/browser-core'\nimport type { LogsInitConfiguration } from '../domain/configuration'\nimport type { HandlerType } from '../domain/logger'\nimport type { StatusType } from '../domain/logger/isAuthorized'\nimport { Logger } from '../domain/logger'\nimport { buildCommonContext } from '../domain/contexts/commonContext'\nimport type { InternalContext } from '../domain/contexts/internalContext'\nimport type { StartLogsResult } from './startLogs'\nimport { startLogs } from './startLogs'\nimport { createPreStartStrategy } from './preStartLogs'\n\nexport interface LoggerConfiguration {\n  level?: StatusType\n  handler?: HandlerType | HandlerType[]\n  context?: object\n}\n\n/**\n * Public API for the Logs browser SDK.\n *\n * See [Browser Log Collection](https://docs.datadoghq.com/logs/log_collection/javascript) for further information.\n *\n * @category Main\n */\nexport interface LogsPublicApi extends PublicApi {\n  /**\n   * The default logger\n   *\n   * @category Logger\n   */\n  logger: Logger\n\n  /**\n   * Init the Logs browser SDK.\n   *\n   * See [Browser Log Collection](https://docs.datadoghq.com/logs/log_collection/javascript) for further information.\n   *\n   * @category Init\n   * @param initConfiguration - Configuration options of the SDK\n   */\n  init: (initConfiguration: LogsInitConfiguration) => void\n\n  /**\n   * Set the tracking consent of the current user.\n   *\n   * Logs will be sent only if it is set to \"granted\". This value won't be stored by the library\n   * across page loads: you will need to call this method or set the appropriate `trackingConsent`\n   * field in the init() method at each page load.\n   *\n   * If this method is called before the init() method, the provided value will take precedence\n   * over the one provided as initialization parameter.\n   *\n   * See [User tracking consent](https://docs.datadoghq.com/logs/log_collection/javascript/#user-tracking-consent) for further information.\n   *\n   * @category Privacy\n   * @param trackingConsent - The user tracking consent\n   */\n  setTrackingConsent: (trackingConsent: TrackingConsent) => void\n\n  /**\n   * Set the global context information to all events, stored in `@context`\n   * See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.\n   *\n   * @category Context - Global Context\n   * @param context - Global context\n   */\n  setGlobalContext: (context: any) => void\n\n  /**\n   * Get the global Context\n   *\n   * See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.\n   *\n   * @category Context - Global Context\n   */\n  getGlobalContext: () => Context\n\n  /**\n   * Set or update a global context property, stored in `@context.<key>`\n   *\n   * See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.\n   *\n   * @category Context - Global Context\n   * @param key - Key of the property\n   * @param value - Value of the property\n   */\n  setGlobalContextProperty: (key: any, value: any) => void\n\n  /**\n   * Remove a global context property\n   *\n   * See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.\n   *\n   * @category Context - Global Context\n   */\n  removeGlobalContextProperty: (key: any) => void\n\n  /**\n   * Clear the global context\n   *\n   * See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.\n   *\n   * @category Context - Global Context\n   */\n  clearGlobalContext: () => void\n\n  /**\n   * Set user information to all events, stored in `@usr`\n   *\n   * See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.\n   *\n   * @category Context - User\n   * @param newUser - User information\n   */\n  setUser(newUser: User & { id: string }): void\n\n  /**\n   * Set user information to all events, stored in `@usr`\n   *\n   * @category Context - User\n   * @deprecated You must specify a user id, favor using {@link setUser} instead\n   * @param newUser - User information with optional id\n   */\n  setUser(newUser: User): void\n\n  /**\n   * Get user information\n   *\n   * See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.\n   *\n   * @category Context - User\n   * @returns User information\n   */\n  getUser: () => Context\n\n  /**\n   * Set or update the user property, stored in `@usr.<key>`\n   *\n   * See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.\n   *\n   * @category Context - User\n   * @param key - Key of the property\n   * @param property - Value of the property\n   */\n  setUserProperty: (key: any, property: any) => void\n\n  /**\n   * Remove a user property\n   *\n   * @category Context - User\n   * @param key - Key of the property to remove\n   * @see [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.\n   */\n  removeUserProperty: (key: any) => void\n\n  /**\n   * Clear all user information\n   *\n   * See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.\n   *\n   * @category Context - User\n   */\n  clearUser: () => void\n\n  /**\n   * Set account information to all events, stored in `@account`\n   *\n   * @category Context - Account\n   * @param newAccount - Account information\n   */\n  setAccount: (newAccount: Account) => void\n\n  /**\n   * Get account information\n   *\n   * @category Context - Account\n   * @returns Account information\n   */\n  getAccount: () => Context\n\n  /**\n   * Set or update the account property, stored in `@account.<key>`\n   *\n   * @category Context - Account\n   * @param key - Key of the property\n   * @param property - Value of the property\n   */\n  setAccountProperty: (key: string, property: any) => void\n\n  /**\n   * Remove an account property\n   *\n   * @category Context - Account\n   * @param key - Key of the property to remove\n   */\n  removeAccountProperty: (key: string) => void\n\n  /**\n   * Clear all account information\n   *\n   * @category Context - Account\n   * @returns Clear all account information\n   */\n  clearAccount: () => void\n\n  /**\n   * The Datadog browser logs SDK contains a default logger `DD_LOGS.logger`, but this API allows to create different ones.\n   *\n   * See [Define multiple loggers](https://docs.datadoghq.com/logs/log_collection/javascript/#define-multiple-loggers) for further information.\n   *\n   * @category Logger\n   * @param name - Name of the logger\n   * @param conf - Configuration of the logger (level, handler, context)\n   */\n  createLogger: (name: string, conf?: LoggerConfiguration) => Logger\n\n  /**\n   * Get a logger\n   *\n   * See [Define multiple loggers](https://docs.datadoghq.com/logs/log_collection/javascript/#define-multiple-loggers) for further information.\n   *\n   * @category Logger\n   * @param name - Name of the logger\n   */\n  getLogger: (name: string) => Logger | undefined\n\n  /**\n   * Get the init configuration\n   *\n   * @category Init\n   * @returns The init configuration\n   */\n  getInitConfiguration: () => LogsInitConfiguration | undefined\n\n  /**\n   * [Internal API] Get the internal SDK context\n   *\n   * See [Access internal context](https://docs.datadoghq.com/logs/log_collection/javascript/#access-internal-context) for further information.\n   *\n   * @internal\n   */\n  getInternalContext: (startTime?: number) => InternalContext | undefined\n}\n\nexport interface Strategy {\n  init: (initConfiguration: LogsInitConfiguration, errorStack?: string) => void\n  initConfiguration: LogsInitConfiguration | undefined\n  globalContext: ContextManager\n  accountContext: ContextManager\n  userContext: ContextManager\n  getInternalContext: StartLogsResult['getInternalContext']\n  handleLog: StartLogsResult['handleLog']\n}\n\nexport function makeLogsPublicApi(): LogsPublicApi {\n  const trackingConsentState = createTrackingConsentState()\n  const bufferedDataObservable = startBufferingData().observable\n\n  let strategy = createPreStartStrategy(\n    buildCommonContext,\n    trackingConsentState,\n    (initConfiguration, configuration, hooks) => {\n      const startLogsResult = mockable(startLogs)(\n        configuration,\n        buildCommonContext,\n        trackingConsentState,\n        bufferedDataObservable,\n        hooks\n      )\n\n      strategy = createPostStartStrategy(initConfiguration, startLogsResult)\n      return startLogsResult\n    }\n  )\n\n  const getStrategy = () => strategy\n\n  const customLoggers: { [name: string]: Logger | undefined } = {}\n\n  const mainLogger = new Logger((...params) => strategy.handleLog(...params))\n\n  return makePublicApi<LogsPublicApi>({\n    logger: mainLogger,\n\n    init: (initConfiguration) => {\n      const errorStack = new Error().stack\n      callMonitored(() => strategy.init(initConfiguration, errorStack))\n    },\n\n    setTrackingConsent: monitor((trackingConsent) => {\n      trackingConsentState.update(trackingConsent)\n      addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: trackingConsent })\n    }),\n\n    getGlobalContext: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.getContext\n    ),\n    setGlobalContext: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.setContext\n    ),\n\n    setGlobalContextProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.setContextProperty\n    ),\n\n    removeGlobalContextProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.removeContextProperty\n    ),\n\n    clearGlobalContext: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.clearContext\n    ),\n\n    createLogger: monitor((name, conf = {}) => {\n      customLoggers[name] = new Logger(\n        (...params) => strategy.handleLog(...params),\n        sanitize(name),\n        conf.handler,\n        conf.level,\n        sanitize(conf.context) as object\n      )\n\n      return customLoggers[name]\n    }),\n\n    getLogger: monitor((name) => customLoggers[name]),\n\n    getInitConfiguration: monitor(() => deepClone(strategy.initConfiguration)),\n\n    getInternalContext: monitor((startTime) => strategy.getInternalContext(startTime)),\n\n    setUser: defineContextMethod(getStrategy, CustomerContextKey.userContext, ContextManagerMethod.setContext),\n\n    getUser: defineContextMethod(getStrategy, CustomerContextKey.userContext, ContextManagerMethod.getContext),\n\n    setUserProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.setContextProperty\n    ),\n\n    removeUserProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.removeContextProperty\n    ),\n\n    clearUser: defineContextMethod(getStrategy, CustomerContextKey.userContext, ContextManagerMethod.clearContext),\n\n    setAccount: defineContextMethod(getStrategy, CustomerContextKey.accountContext, ContextManagerMethod.setContext),\n\n    getAccount: defineContextMethod(getStrategy, CustomerContextKey.accountContext, ContextManagerMethod.getContext),\n\n    setAccountProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.setContextProperty\n    ),\n\n    removeAccountProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.removeContextProperty\n    ),\n\n    clearAccount: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.clearContext\n    ),\n  })\n}\n\nfunction createPostStartStrategy(initConfiguration: LogsInitConfiguration, startLogsResult: StartLogsResult): Strategy {\n  return {\n    init: (initConfiguration: LogsInitConfiguration) => {\n      displayAlreadyInitializedError('DD_LOGS', initConfiguration)\n    },\n    initConfiguration,\n    ...startLogsResult,\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/boot/preStartLogs.spec.ts",
    "content": "import {\n  callbackAddsInstrumentation,\n  type Clock,\n  mockClock,\n  mockEventBridge,\n  createFakeTelemetryObject,\n  replaceMockableWithSpy,\n} from '@datadog/browser-core/test'\nimport type { TimeStamp, TrackingConsentState } from '@datadog/browser-core'\nimport { ONE_SECOND, TrackingConsent, createTrackingConsentState, display, startTelemetry } from '@datadog/browser-core'\nimport type { CommonContext } from '../rawLogsEvent.types'\nimport type { HybridInitConfiguration, LogsInitConfiguration } from '../domain/configuration'\nimport type { Logger } from '../domain/logger'\nimport { StatusType } from '../domain/logger/isAuthorized'\nimport type { Strategy } from './logsPublicApi'\nimport type { DoStartLogs } from './preStartLogs'\nimport { createPreStartStrategy } from './preStartLogs'\nimport type { StartLogsResult } from './startLogs'\n\nconst DEFAULT_INIT_CONFIGURATION = { clientToken: 'xxx' }\nconst INVALID_INIT_CONFIGURATION = {} as LogsInitConfiguration\n\ndescribe('preStartLogs', () => {\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  describe('configuration validation', () => {\n    let displaySpy: jasmine.Spy\n    let doStartLogsSpy: jasmine.Spy<DoStartLogs>\n    let strategy: Strategy\n\n    beforeEach(() => {\n      ;({ strategy, doStartLogsSpy } = createPreStartStrategyWithDefaults())\n      displaySpy = spyOn(display, 'error')\n    })\n\n    it('should start when the configuration is valid', () => {\n      strategy.init(DEFAULT_INIT_CONFIGURATION)\n      expect(displaySpy).not.toHaveBeenCalled()\n      expect(doStartLogsSpy).toHaveBeenCalled()\n    })\n\n    it('should not start when the configuration is missing', () => {\n      ;(strategy.init as () => void)()\n      expect(displaySpy).toHaveBeenCalled()\n      expect(doStartLogsSpy).not.toHaveBeenCalled()\n    })\n\n    it('should not start when the configuration is invalid', () => {\n      strategy.init(INVALID_INIT_CONFIGURATION)\n      expect(displaySpy).toHaveBeenCalled()\n      expect(doStartLogsSpy).not.toHaveBeenCalled()\n    })\n\n    it(\"should return init configuration even if it's invalid\", () => {\n      strategy.init(INVALID_INIT_CONFIGURATION)\n      expect(strategy.initConfiguration).toEqual(INVALID_INIT_CONFIGURATION)\n    })\n\n    describe('multiple init', () => {\n      it('should log an error if init is called several times', () => {\n        strategy.init(DEFAULT_INIT_CONFIGURATION)\n        expect(displaySpy).toHaveBeenCalledTimes(0)\n\n        strategy.init(DEFAULT_INIT_CONFIGURATION)\n        expect(displaySpy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should not log an error if init is called several times and silentMultipleInit is true', () => {\n        strategy.init({\n          ...DEFAULT_INIT_CONFIGURATION,\n          silentMultipleInit: true,\n        })\n        expect(displaySpy).toHaveBeenCalledTimes(0)\n\n        strategy.init({\n          ...DEFAULT_INIT_CONFIGURATION,\n          silentMultipleInit: true,\n        })\n        expect(displaySpy).toHaveBeenCalledTimes(0)\n      })\n    })\n\n    describe('if event bridge present', () => {\n      beforeEach(() => {\n        mockEventBridge()\n      })\n\n      it('init should accept empty client token', () => {\n        const hybridInitConfiguration: HybridInitConfiguration = {}\n        strategy.init(hybridInitConfiguration as LogsInitConfiguration)\n\n        expect(displaySpy).not.toHaveBeenCalled()\n        expect(doStartLogsSpy).toHaveBeenCalled()\n      })\n    })\n  })\n\n  it('allows sending logs', () => {\n    const { strategy, handleLogSpy, getLoggedMessage } = createPreStartStrategyWithDefaults()\n    strategy.handleLog(\n      {\n        status: StatusType.info,\n        message: 'message',\n      },\n      {} as Logger\n    )\n\n    expect(handleLogSpy).not.toHaveBeenCalled()\n    strategy.init(DEFAULT_INIT_CONFIGURATION)\n\n    expect(handleLogSpy.calls.all().length).toBe(1)\n    expect(getLoggedMessage(0).message.message).toBe('message')\n  })\n\n  it('returns undefined initial configuration', () => {\n    const { strategy } = createPreStartStrategyWithDefaults()\n    expect(strategy.initConfiguration).toBeUndefined()\n  })\n\n  describe('save context when submitting a log', () => {\n    it('saves the date', () => {\n      const { strategy, getLoggedMessage } = createPreStartStrategyWithDefaults()\n      strategy.handleLog(\n        {\n          status: StatusType.info,\n          message: 'message',\n        },\n        {} as Logger\n      )\n      clock.tick(ONE_SECOND)\n      strategy.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(getLoggedMessage(0).savedDate).toEqual((Date.now() - ONE_SECOND) as TimeStamp)\n    })\n\n    it('saves the URL', () => {\n      const { strategy, getLoggedMessage, getCommonContextSpy } = createPreStartStrategyWithDefaults()\n      getCommonContextSpy.and.returnValue({ view: { url: 'url' } } as unknown as CommonContext)\n      strategy.handleLog(\n        {\n          status: StatusType.info,\n          message: 'message',\n        },\n        {} as Logger\n      )\n      strategy.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(getLoggedMessage(0).savedCommonContext!.view?.url).toEqual('url')\n    })\n\n    it('saves the log context', () => {\n      const { strategy, getLoggedMessage } = createPreStartStrategyWithDefaults()\n      const context = { foo: 'bar' }\n      strategy.handleLog(\n        {\n          status: StatusType.info,\n          message: 'message',\n          context: { foo: 'bar' },\n        },\n        {} as Logger\n      )\n      context.foo = 'baz'\n\n      strategy.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(getLoggedMessage(0).message.context!.foo).toEqual('bar')\n    })\n  })\n\n  describe('internal context', () => {\n    it('should return undefined if not initialized', () => {\n      const { strategy } = createPreStartStrategyWithDefaults()\n      expect(strategy.getInternalContext()).toBeUndefined()\n    })\n  })\n\n  describe('tracking consent', () => {\n    let strategy: Strategy\n    let doStartLogsSpy: jasmine.Spy<DoStartLogs>\n    let trackingConsentState: TrackingConsentState\n\n    beforeEach(() => {\n      trackingConsentState = createTrackingConsentState()\n      ;({ strategy, doStartLogsSpy } = createPreStartStrategyWithDefaults({ trackingConsentState }))\n    })\n\n    describe('basic methods instrumentation', () => {\n      it('should instrument fetch even if tracking consent is not granted', () => {\n        expect(\n          callbackAddsInstrumentation(() => {\n            strategy.init({\n              ...DEFAULT_INIT_CONFIGURATION,\n              trackingConsent: TrackingConsent.NOT_GRANTED,\n            })\n          })\n            .toMethod(window, 'fetch')\n            .whenCalled()\n        ).toBeTrue()\n      })\n    })\n\n    it('does not start logs if tracking consent is not granted at init', () => {\n      strategy.init({\n        ...DEFAULT_INIT_CONFIGURATION,\n        trackingConsent: TrackingConsent.NOT_GRANTED,\n      })\n      expect(doStartLogsSpy).not.toHaveBeenCalled()\n    })\n\n    it('starts logs if tracking consent is granted before init', () => {\n      trackingConsentState.update(TrackingConsent.GRANTED)\n      strategy.init({\n        ...DEFAULT_INIT_CONFIGURATION,\n        trackingConsent: TrackingConsent.NOT_GRANTED,\n      })\n      expect(doStartLogsSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('does not start logs if tracking consent is not withdrawn before init', () => {\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n      strategy.init({\n        ...DEFAULT_INIT_CONFIGURATION,\n        trackingConsent: TrackingConsent.GRANTED,\n      })\n      expect(doStartLogsSpy).not.toHaveBeenCalled()\n    })\n\n    it('do not call startLogs when tracking consent state is updated after init', () => {\n      strategy.init(DEFAULT_INIT_CONFIGURATION)\n      doStartLogsSpy.calls.reset()\n\n      trackingConsentState.update(TrackingConsent.GRANTED)\n\n      expect(doStartLogsSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('telemetry', () => {\n    it('starts telemetry during init() by default', () => {\n      const { strategy, startTelemetrySpy } = createPreStartStrategyWithDefaults()\n      strategy.init(DEFAULT_INIT_CONFIGURATION)\n      expect(startTelemetrySpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('does not start telemetry until consent is granted', () => {\n      const trackingConsentState = createTrackingConsentState()\n      const { strategy, startTelemetrySpy } = createPreStartStrategyWithDefaults({\n        trackingConsentState,\n      })\n\n      strategy.init({\n        ...DEFAULT_INIT_CONFIGURATION,\n        trackingConsent: TrackingConsent.NOT_GRANTED,\n      })\n\n      expect(startTelemetrySpy).not.toHaveBeenCalled()\n\n      trackingConsentState.update(TrackingConsent.GRANTED)\n\n      expect(startTelemetrySpy).toHaveBeenCalledTimes(1)\n    })\n  })\n})\n\nfunction createPreStartStrategyWithDefaults({\n  trackingConsentState = createTrackingConsentState(),\n}: {\n  trackingConsentState?: TrackingConsentState\n} = {}) {\n  const handleLogSpy = jasmine.createSpy()\n  const doStartLogsSpy = jasmine.createSpy<DoStartLogs>().and.returnValue({\n    handleLog: handleLogSpy,\n  } as unknown as StartLogsResult)\n  const getCommonContextSpy = jasmine.createSpy<() => CommonContext>()\n  const startTelemetrySpy = replaceMockableWithSpy(startTelemetry).and.callFake(createFakeTelemetryObject)\n\n  return {\n    strategy: createPreStartStrategy(getCommonContextSpy, trackingConsentState, doStartLogsSpy),\n    startTelemetrySpy,\n    handleLogSpy,\n    doStartLogsSpy,\n    getCommonContextSpy,\n    getLoggedMessage: (index: number) => {\n      const [message, logger, handlingStack, savedCommonContext, savedDate] = handleLogSpy.calls.argsFor(index)\n      return { message, logger, handlingStack, savedCommonContext, savedDate }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/boot/preStartLogs.ts",
    "content": "import type { TrackingConsentState } from '@datadog/browser-core'\nimport {\n  createBoundedBuffer,\n  canUseEventBridge,\n  display,\n  displayAlreadyInitializedError,\n  initFeatureFlags,\n  initFetchObservable,\n  noop,\n  timeStampNow,\n  buildAccountContextManager,\n  CustomerContextKey,\n  bufferContextCalls,\n  addTelemetryConfiguration,\n  buildGlobalContextManager,\n  buildUserContextManager,\n  startTelemetry,\n  TelemetryService,\n  mockable,\n} from '@datadog/browser-core'\nimport type { Hooks } from '../domain/hooks'\nimport { createHooks } from '../domain/hooks'\nimport type { LogsConfiguration, LogsInitConfiguration } from '../domain/configuration'\nimport { serializeLogsConfiguration, validateAndBuildLogsConfiguration } from '../domain/configuration'\nimport type { CommonContext } from '../rawLogsEvent.types'\nimport type { Strategy } from './logsPublicApi'\nimport type { StartLogsResult } from './startLogs'\n\nexport type DoStartLogs = (\n  initConfiguration: LogsInitConfiguration,\n  configuration: LogsConfiguration,\n  hooks: Hooks\n) => StartLogsResult\n\nexport function createPreStartStrategy(\n  getCommonContext: () => CommonContext,\n  trackingConsentState: TrackingConsentState,\n  doStartLogs: DoStartLogs\n): Strategy {\n  const bufferApiCalls = createBoundedBuffer<StartLogsResult>()\n\n  // TODO next major: remove the globalContext, accountContextManager, userContext from preStartStrategy and use an empty context instead\n  const globalContext = buildGlobalContextManager()\n  bufferContextCalls(globalContext, CustomerContextKey.globalContext, bufferApiCalls)\n\n  const accountContext = buildAccountContextManager()\n  bufferContextCalls(accountContext, CustomerContextKey.accountContext, bufferApiCalls)\n\n  const userContext = buildUserContextManager()\n  bufferContextCalls(userContext, CustomerContextKey.userContext, bufferApiCalls)\n\n  let cachedInitConfiguration: LogsInitConfiguration | undefined\n  let cachedConfiguration: LogsConfiguration | undefined\n  const hooks = createHooks()\n  const trackingConsentStateSubscription = trackingConsentState.observable.subscribe(tryStartLogs)\n\n  function tryStartLogs() {\n    if (!cachedConfiguration || !cachedInitConfiguration || !trackingConsentState.isGranted()) {\n      return\n    }\n\n    mockable(startTelemetry)(TelemetryService.LOGS, cachedConfiguration, hooks)\n\n    trackingConsentStateSubscription.unsubscribe()\n    const startLogsResult = doStartLogs(cachedInitConfiguration, cachedConfiguration, hooks)\n\n    bufferApiCalls.drain(startLogsResult)\n  }\n\n  return {\n    init(initConfiguration, errorStack) {\n      if (!initConfiguration) {\n        display.error('Missing configuration')\n        return\n      }\n      // Set the experimental feature flags as early as possible, so we can use them in most places\n      initFeatureFlags(initConfiguration.enableExperimentalFeatures)\n\n      if (canUseEventBridge()) {\n        initConfiguration = overrideInitConfigurationForBridge(initConfiguration)\n      }\n\n      // Expose the initial configuration regardless of initialization success.\n      cachedInitConfiguration = initConfiguration\n      addTelemetryConfiguration(serializeLogsConfiguration(initConfiguration))\n\n      if (cachedConfiguration) {\n        displayAlreadyInitializedError('DD_LOGS', initConfiguration)\n        return\n      }\n\n      const configuration = validateAndBuildLogsConfiguration(initConfiguration, errorStack)\n      if (!configuration) {\n        return\n      }\n\n      cachedConfiguration = configuration\n\n      // Instrument fetch to track network requests\n      // This is needed in case the consent is not granted and some customer\n      // library (Apollo Client) is storing uninstrumented fetch to be used later\n      // The subscrption is needed so that the instrumentation process is completed\n      initFetchObservable().subscribe(noop)\n\n      trackingConsentState.tryToInit(configuration.trackingConsent)\n      tryStartLogs()\n    },\n\n    get initConfiguration() {\n      return cachedInitConfiguration\n    },\n\n    globalContext,\n    accountContext,\n    userContext,\n\n    getInternalContext: noop as () => undefined,\n\n    handleLog(message, statusType, handlingStack, context = getCommonContext(), date = timeStampNow()) {\n      bufferApiCalls.add((startLogsResult) =>\n        startLogsResult.handleLog(message, statusType, handlingStack, context, date)\n      )\n    },\n  }\n}\n\nfunction overrideInitConfigurationForBridge(initConfiguration: LogsInitConfiguration): LogsInitConfiguration {\n  return { ...initConfiguration, clientToken: 'empty' }\n}\n"
  },
  {
    "path": "packages/logs/src/boot/startLogs.spec.ts",
    "content": "import type { BufferedData, Payload } from '@datadog/browser-core'\nimport {\n  ErrorSource,\n  display,\n  stopSessionManager,\n  getCookie,\n  SESSION_STORE_KEY,\n  createTrackingConsentState,\n  TrackingConsent,\n  setCookie,\n  STORAGE_POLL_DELAY,\n  ONE_MINUTE,\n  BufferedObservable,\n  FLUSH_DURATION_LIMIT,\n} from '@datadog/browser-core'\nimport type { Clock, Request } from '@datadog/browser-core/test'\nimport {\n  interceptRequests,\n  mockEndpointBuilder,\n  mockEventBridge,\n  mockSyntheticsWorkerValues,\n  registerCleanupTask,\n  mockClock,\n  expireCookie,\n  DEFAULT_FETCH_MOCK,\n} from '@datadog/browser-core/test'\n\nimport type { LogsConfiguration } from '../domain/configuration'\nimport { validateAndBuildLogsConfiguration } from '../domain/configuration'\nimport { Logger } from '../domain/logger'\nimport { createHooks } from '../domain/hooks'\nimport { StatusType } from '../domain/logger/isAuthorized'\nimport type { LogsEvent } from '../logsEvent.types'\nimport { startLogs } from './startLogs'\n\nfunction getLoggedMessage(requests: Request[], index: number) {\n  return JSON.parse(requests[index].body) as LogsEvent\n}\n\ninterface Rum {\n  getInternalContext(startTime?: number): any\n}\ndeclare global {\n  interface Window {\n    DD_RUM?: Rum\n    DD_RUM_SYNTHETICS?: Rum\n  }\n}\n\nconst DEFAULT_MESSAGE = { status: StatusType.info, message: 'message' }\nconst COMMON_CONTEXT = {\n  view: { referrer: 'common_referrer', url: 'common_url' },\n}\nconst DEFAULT_PAYLOAD = {} as Payload\n\nfunction startLogsWithDefaults(\n  { configuration }: { configuration?: Partial<LogsConfiguration> } = {},\n  trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n) {\n  const endpointBuilder = mockEndpointBuilder('https://localhost/v1/input/log')\n  const { handleLog, stop, globalContext, accountContext, userContext } = startLogs(\n    {\n      ...validateAndBuildLogsConfiguration({ clientToken: 'xxx', service: 'service', telemetrySampleRate: 0 })!,\n      logsEndpointBuilder: endpointBuilder,\n      ...configuration,\n    },\n    () => COMMON_CONTEXT,\n    trackingConsentState,\n    new BufferedObservable<BufferedData>(100),\n    createHooks()\n  )\n\n  registerCleanupTask(stop)\n\n  const logger = new Logger(handleLog)\n\n  return { handleLog, logger, endpointBuilder, globalContext, accountContext, userContext }\n}\n\ndescribe('logs', () => {\n  let interceptor: ReturnType<typeof interceptRequests>\n  let requests: Request[]\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    interceptor = interceptRequests()\n    requests = interceptor.requests\n  })\n\n  afterEach(() => {\n    delete window.DD_RUM\n    stopSessionManager()\n  })\n\n  describe('request', () => {\n    it('should send the needed data', async () => {\n      const { handleLog, logger, endpointBuilder } = startLogsWithDefaults()\n\n      handleLog(\n        { message: 'message', status: StatusType.warn, context: { foo: 'bar' } },\n        logger,\n        'fake-handling-stack',\n        COMMON_CONTEXT\n      )\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n      expect(requests[0].url).toContain(endpointBuilder.build('fetch', DEFAULT_PAYLOAD))\n      expect(getLoggedMessage(requests, 0)).toEqual({\n        date: jasmine.any(Number),\n        foo: 'bar',\n        message: 'message',\n        service: 'service',\n        ddtags: 'sdk_version:test,service:service',\n        session_id: jasmine.any(String),\n        session: {\n          id: jasmine.any(String),\n        },\n        status: StatusType.warn,\n        view: {\n          referrer: 'common_referrer',\n          url: 'common_url',\n        },\n        origin: ErrorSource.LOGGER,\n        usr: {\n          anonymous_id: jasmine.any(String),\n        },\n        tab: {\n          id: jasmine.any(String),\n        },\n      })\n    })\n\n    it('should all use the same batch', async () => {\n      const { handleLog, logger } = startLogsWithDefaults()\n\n      handleLog(DEFAULT_MESSAGE, logger)\n      handleLog(DEFAULT_MESSAGE, logger)\n      handleLog(DEFAULT_MESSAGE, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n      await interceptor.waitForAllFetchCalls()\n\n      expect(requests.length).toEqual(1)\n    })\n\n    it('should send bridge event when bridge is present', () => {\n      const sendSpy = spyOn(mockEventBridge(), 'send')\n      const { handleLog, logger } = startLogsWithDefaults()\n\n      handleLog(DEFAULT_MESSAGE, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n\n      expect(requests.length).toEqual(0)\n      const [message] = sendSpy.calls.mostRecent().args\n      const parsedMessage = JSON.parse(message)\n      expect(parsedMessage).toEqual({\n        eventType: 'log',\n        event: jasmine.objectContaining({ message: 'message' }),\n      })\n    })\n  })\n\n  describe('sampling', () => {\n    it('should be applied when event bridge is present (rate 0)', () => {\n      const sendSpy = spyOn(mockEventBridge(), 'send')\n\n      const { handleLog, logger } = startLogsWithDefaults({\n        configuration: { sessionSampleRate: 0 },\n      })\n      handleLog(DEFAULT_MESSAGE, logger)\n\n      expect(sendSpy).not.toHaveBeenCalled()\n    })\n\n    it('should be applied when event bridge is present (rate 100)', () => {\n      const sendSpy = spyOn(mockEventBridge(), 'send')\n\n      const { handleLog, logger } = startLogsWithDefaults({\n        configuration: { sessionSampleRate: 100 },\n      })\n      handleLog(DEFAULT_MESSAGE, logger)\n\n      expect(sendSpy).toHaveBeenCalled()\n    })\n  })\n\n  it('should not print the log twice when console handler is enabled', () => {\n    const consoleLogSpy = spyOn(console, 'log')\n    const displayLogSpy = spyOn(display, 'log')\n    startLogsWithDefaults({\n      configuration: { forwardConsoleLogs: ['log'] },\n    })\n\n    /* eslint-disable-next-line no-console */\n    console.log('foo', 'bar')\n\n    expect(consoleLogSpy).toHaveBeenCalledTimes(1)\n    expect(displayLogSpy).not.toHaveBeenCalled()\n  })\n\n  describe('logs session creation', () => {\n    it('creates a session on normal conditions', () => {\n      startLogsWithDefaults()\n      expect(getCookie(SESSION_STORE_KEY)).toBeDefined()\n    })\n\n    it('does not create a session if event bridge is present', () => {\n      mockEventBridge()\n      startLogsWithDefaults()\n      expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n    })\n\n    it('does not create a session if synthetics worker will inject RUM', () => {\n      mockSyntheticsWorkerValues({ injectsRum: true })\n      startLogsWithDefaults()\n      expect(getCookie(SESSION_STORE_KEY)).toBeUndefined()\n    })\n  })\n\n  describe('session lifecycle', () => {\n    it('sends logs without session id when the session expires ', async () => {\n      setCookie(SESSION_STORE_KEY, 'id=foo&logs=1', ONE_MINUTE)\n      const { handleLog, logger } = startLogsWithDefaults()\n\n      interceptor.withFetch(DEFAULT_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n\n      handleLog({ status: StatusType.info, message: 'message 1' }, logger)\n\n      expireCookie()\n      clock.tick(STORAGE_POLL_DELAY * 2)\n\n      handleLog({ status: StatusType.info, message: 'message 2' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n      await interceptor.waitForAllFetchCalls()\n\n      const firstRequest = getLoggedMessage(requests, 0)\n      const secondRequest = getLoggedMessage(requests, 1)\n\n      expect(requests.length).toEqual(2)\n      expect(firstRequest.message).toEqual('message 1')\n      expect(firstRequest.session_id).toEqual('foo')\n\n      expect(secondRequest.message).toEqual('message 2')\n      expect(secondRequest.session_id).toBeUndefined()\n    })\n  })\n\n  describe('contexts precedence', () => {\n    it('global context should take precedence over session', () => {\n      const { handleLog, logger, globalContext } = startLogsWithDefaults()\n      globalContext.setContext({ session_id: 'from-global-context' })\n\n      handleLog({ status: StatusType.info, message: 'message 1' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n\n      const firstRequest = getLoggedMessage(requests, 0)\n      expect(firstRequest.session_id).toEqual('from-global-context')\n    })\n\n    it('global context should take precedence over account', () => {\n      const { handleLog, logger, globalContext, accountContext } = startLogsWithDefaults()\n      globalContext.setContext({ account: { id: 'from-global-context' } })\n      accountContext.setContext({ id: 'from-account-context' })\n\n      handleLog({ status: StatusType.info, message: 'message 1' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n\n      const firstRequest = getLoggedMessage(requests, 0)\n      expect(firstRequest.account).toEqual({ id: 'from-global-context' })\n    })\n\n    it('global context should take precedence over usr', () => {\n      const { handleLog, logger, globalContext, userContext } = startLogsWithDefaults()\n      globalContext.setContext({ usr: { id: 'from-global-context' } })\n      userContext.setContext({ id: 'from-user-context' })\n\n      handleLog({ status: StatusType.info, message: 'message 1' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n\n      const firstRequest = getLoggedMessage(requests, 0)\n      expect(firstRequest.usr).toEqual(jasmine.objectContaining({ id: 'from-global-context' }))\n    })\n\n    it('RUM context should take precedence over global context', () => {\n      const { handleLog, logger, globalContext } = startLogsWithDefaults()\n      window.DD_RUM = {\n        getInternalContext: () => ({ view: { url: 'from-rum-context' } }),\n      }\n      globalContext.setContext({ view: { url: 'from-global-context' } })\n\n      handleLog({ status: StatusType.info, message: 'message 1' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n\n      const firstRequest = getLoggedMessage(requests, 0)\n      expect(firstRequest.view.url).toEqual('from-rum-context')\n    })\n  })\n\n  describe('tracking consent', () => {\n    it('should not send logs after tracking consent is revoked', async () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n      const { handleLog, logger } = startLogsWithDefaults({}, trackingConsentState)\n\n      // Log a message with consent granted - should be sent\n      handleLog({ status: StatusType.info, message: 'message before revocation' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n      await interceptor.waitForAllFetchCalls()\n      expect(requests.length).toEqual(1)\n      expect(getLoggedMessage(requests, 0).message).toBe('message before revocation')\n\n      // Revoke consent\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n\n      // Log another message - should not be sent\n      handleLog({ status: StatusType.info, message: 'message after revocation' }, logger)\n\n      clock.tick(FLUSH_DURATION_LIMIT)\n      await interceptor.waitForAllFetchCalls()\n      // Should still only have the first request\n      expect(requests.length).toEqual(1)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/boot/startLogs.ts",
    "content": "import type { TrackingConsentState, BufferedObservable, BufferedData } from '@datadog/browser-core'\nimport {\n  sendToExtension,\n  createPageMayExitObservable,\n  willSyntheticsInjectRum,\n  canUseEventBridge,\n  startAccountContext,\n  startGlobalContext,\n  startUserContext,\n  startTabContext,\n} from '@datadog/browser-core'\nimport { startLogsSessionManager, startLogsSessionManagerStub } from '../domain/logsSessionManager'\nimport type { LogsConfiguration } from '../domain/configuration'\nimport { startLogsAssembly } from '../domain/assembly'\nimport { startConsoleCollection } from '../domain/console/consoleCollection'\nimport { startReportCollection } from '../domain/report/reportCollection'\nimport { startNetworkErrorCollection } from '../domain/networkError/networkErrorCollection'\nimport { startRuntimeErrorCollection } from '../domain/runtimeError/runtimeErrorCollection'\nimport { LifeCycle, LifeCycleEventType } from '../domain/lifeCycle'\nimport { startLoggerCollection } from '../domain/logger/loggerCollection'\nimport { startLogsBatch } from '../transport/startLogsBatch'\nimport { startLogsBridge } from '../transport/startLogsBridge'\nimport { startInternalContext } from '../domain/contexts/internalContext'\nimport { startReportError } from '../domain/reportError'\nimport type { CommonContext } from '../rawLogsEvent.types'\nimport type { Hooks } from '../domain/hooks'\nimport { startRUMInternalContext } from '../domain/contexts/rumInternalContext'\nimport { startSessionContext } from '../domain/contexts/sessionContext'\nimport { startTrackingConsentContext } from '../domain/contexts/trackingConsentContext'\n\nconst LOGS_STORAGE_KEY = 'logs'\n\nexport type StartLogs = typeof startLogs\nexport type StartLogsResult = ReturnType<StartLogs>\n\nexport function startLogs(\n  configuration: LogsConfiguration,\n  getCommonContext: () => CommonContext,\n\n  // `startLogs` and its subcomponents assume tracking consent is granted initially and starts\n  // collecting logs unconditionally. As such, `startLogs` should be called with a\n  // `trackingConsentState` set to \"granted\".\n  trackingConsentState: TrackingConsentState,\n  bufferedDataObservable: BufferedObservable<BufferedData>,\n  hooks: Hooks\n) {\n  const lifeCycle = new LifeCycle()\n  const cleanupTasks: Array<() => void> = []\n\n  lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (log) => sendToExtension('logs', log))\n\n  const reportError = startReportError(lifeCycle)\n  const pageMayExitObservable = createPageMayExitObservable(configuration)\n\n  const session =\n    configuration.sessionStoreStrategyType && !canUseEventBridge() && !willSyntheticsInjectRum()\n      ? startLogsSessionManager(configuration, trackingConsentState)\n      : startLogsSessionManagerStub(configuration)\n\n  startTrackingConsentContext(hooks, trackingConsentState)\n  // Start user and account context first to allow overrides from global context\n  startSessionContext(hooks, configuration, session)\n  const accountContext = startAccountContext(hooks, configuration, LOGS_STORAGE_KEY)\n  const userContext = startUserContext(hooks, configuration, session, LOGS_STORAGE_KEY)\n  const globalContext = startGlobalContext(hooks, configuration, LOGS_STORAGE_KEY, false)\n  startRUMInternalContext(hooks)\n  startTabContext(hooks)\n\n  startNetworkErrorCollection(configuration, lifeCycle)\n  startRuntimeErrorCollection(configuration, lifeCycle, bufferedDataObservable)\n  bufferedDataObservable.unbuffer()\n  startConsoleCollection(configuration, lifeCycle)\n  startReportCollection(configuration, lifeCycle)\n  const { handleLog } = startLoggerCollection(lifeCycle)\n\n  startLogsAssembly(configuration, lifeCycle, hooks, getCommonContext, reportError)\n\n  if (!canUseEventBridge()) {\n    const { stop: stopLogsBatch } = startLogsBatch(\n      configuration,\n      lifeCycle,\n      reportError,\n      pageMayExitObservable,\n      session\n    )\n    cleanupTasks.push(() => stopLogsBatch())\n  } else {\n    startLogsBridge(lifeCycle)\n  }\n\n  const internalContext = startInternalContext(session)\n\n  return {\n    handleLog,\n    getInternalContext: internalContext.get,\n    accountContext,\n    globalContext,\n    userContext,\n    stop: () => {\n      cleanupTasks.forEach((task) => task())\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/assembly.spec.ts",
    "content": "import type { Context, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { ErrorSource, ONE_MINUTE, getTimeStamp, noop, HookNames } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport type { LogsEvent } from '../logsEvent.types'\nimport type { CommonContext } from '../rawLogsEvent.types'\nimport { startLogsAssembly } from './assembly'\nimport type { LogsConfiguration } from './configuration'\nimport { validateAndBuildLogsConfiguration } from './configuration'\nimport { Logger } from './logger'\nimport { StatusType } from './logger/isAuthorized'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport type { Hooks } from './hooks'\nimport { createHooks } from './hooks'\nimport { startRUMInternalContext } from './contexts/rumInternalContext'\n\nconst initConfiguration = { clientToken: 'xxx', service: 'service', env: 'test', version: '1.0.0' }\nconst DEFAULT_MESSAGE = {\n  status: StatusType.info,\n  message: 'message',\n  origin: ErrorSource.LOGGER,\n  date: 123456 as TimeStamp,\n}\nconst COMMON_CONTEXT: CommonContext = {\n  view: {\n    referrer: 'referrer_from_common_context',\n    url: 'url_from_common_context',\n  },\n}\n\ndescribe('startLogsAssembly', () => {\n  let beforeSend: (event: LogsEvent) => void | boolean\n  let lifeCycle: LifeCycle\n  let configuration: LogsConfiguration\n  let serverLogs: Array<LogsEvent & Context> = []\n  let mainLogger: Logger\n  let hooks: Hooks\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (serverRumEvent) => serverLogs.push(serverRumEvent))\n    configuration = {\n      ...validateAndBuildLogsConfiguration({ ...initConfiguration })!,\n      beforeSend: (x: LogsEvent) => beforeSend(x),\n    }\n    beforeSend = noop\n    mainLogger = new Logger(() => noop)\n    hooks = createHooks()\n    startRUMInternalContext(hooks)\n    startLogsAssembly(configuration, lifeCycle, hooks, () => COMMON_CONTEXT, noop)\n    window.DD_RUM = {\n      getInternalContext: noop,\n    }\n  })\n\n  afterEach(() => {\n    delete window.DD_RUM\n    serverLogs = []\n  })\n\n  it('should send if beforeSend returned true', () => {\n    beforeSend = () => true\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: DEFAULT_MESSAGE,\n    })\n    expect(serverLogs.length).toEqual(1)\n  })\n\n  it('should send if beforeSend returned undefined', () => {\n    beforeSend = () => undefined\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: DEFAULT_MESSAGE,\n    })\n    expect(serverLogs.length).toEqual(1)\n  })\n\n  it('should not send if beforeSend returned false', () => {\n    beforeSend = () => false\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: DEFAULT_MESSAGE,\n    })\n    expect(serverLogs.length).toEqual(0)\n  })\n\n  describe('contexts inclusion', () => {\n    it('should include message context', () => {\n      spyOn(window.DD_RUM!, 'getInternalContext').and.returnValue({\n        view: { url: 'http://from-rum-context.com', id: 'view-id' },\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: DEFAULT_MESSAGE,\n        messageContext: { foo: 'from-message-context' },\n      })\n\n      expect(serverLogs[0].foo).toEqual('from-message-context')\n    })\n\n    it('should include common context', () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n\n      expect(serverLogs[0]).toEqual(\n        jasmine.objectContaining({\n          view: COMMON_CONTEXT.view,\n        })\n      )\n    })\n\n    it('should include saved common context instead of common context when present', () => {\n      const savedCommonContext = {\n        view: {\n          referrer: 'referrer_from_saved_common_context',\n          url: 'url_from_saved_common_context',\n        },\n        user: { email: 'test@test.com' },\n        account: { id: '123' },\n      }\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE, savedCommonContext })\n\n      expect(serverLogs[0]).toEqual(\n        jasmine.objectContaining({\n          view: savedCommonContext.view,\n        })\n      )\n      expect(serverLogs[0].common_context_key).toBeUndefined()\n    })\n\n    it('should not include main logger context', () => {\n      mainLogger.setContext({ foo: 'from-main-logger' })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n\n      expect(serverLogs[0].foo).toBeUndefined()\n    })\n\n    it('should include rum internal context related to the error time', () => {\n      window.DD_RUM = {\n        getInternalContext(startTime) {\n          return { foo: startTime === 1234 ? 'b' : 'a' }\n        },\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, date: getTimeStamp(1234 as RelativeTime) },\n      })\n\n      expect(serverLogs[0].foo).toBe('b')\n    })\n\n    it('should include RUM context', () => {\n      window.DD_RUM = {\n        getInternalContext() {\n          return { view: { url: 'http://from-rum-context.com', id: 'view-id' } }\n        },\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n\n      expect(serverLogs[0].view).toEqual({\n        id: 'view-id',\n        url: 'http://from-rum-context.com',\n        referrer: 'referrer_from_common_context',\n      })\n    })\n\n    it('should include raw log', () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n\n      expect(serverLogs[0]).toEqual(jasmine.objectContaining(DEFAULT_MESSAGE))\n    })\n  })\n\n  describe('assembly precedence', () => {\n    it('defaultLogsEventAttributes should take precedence over service, session_id', () => {\n      hooks.register(HookNames.Assemble, () => ({\n        service: 'foo',\n        session_id: 'bar',\n      }))\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n\n      expect(serverLogs[0].service).toBe('foo')\n      expect(serverLogs[0].session_id).toBe('bar')\n    })\n\n    it('defaultLogsEventAttributes should take precedence over common context', () => {\n      hooks.register(HookNames.Assemble, () => ({\n        view: {\n          referrer: 'referrer_from_defaultLogsEventAttributes',\n          url: 'url_from_defaultLogsEventAttributes',\n        },\n        user: { name: 'name_from_defaultLogsEventAttributes' },\n      }))\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: DEFAULT_MESSAGE,\n        savedCommonContext: {\n          view: {\n            referrer: 'referrer_from_common_context',\n            url: 'url_from_common_context',\n          },\n        },\n      })\n\n      expect(serverLogs[0]).toEqual(\n        jasmine.objectContaining({\n          view: {\n            referrer: 'referrer_from_defaultLogsEventAttributes',\n            url: 'url_from_defaultLogsEventAttributes',\n          },\n          user: { name: 'name_from_defaultLogsEventAttributes' },\n        })\n      )\n    })\n\n    it('raw log should take precedence over defaultLogsEventAttributes', () => {\n      hooks.register(HookNames.Assemble, () => ({\n        message: 'from-defaultLogsEventAttributes',\n      }))\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n\n      expect(serverLogs[0].message).toEqual('message')\n    })\n\n    it('message context should take precedence over raw log', () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: DEFAULT_MESSAGE,\n        messageContext: { message: 'from-message-context' },\n      })\n\n      expect(serverLogs[0].message).toEqual('from-message-context')\n    })\n  })\n\n  describe('ddtags', () => {\n    it('should contain and format the default tags', () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, { rawLogsEvent: DEFAULT_MESSAGE })\n      expect(serverLogs[0].ddtags).toEqual('sdk_version:test,env:test,service:service,version:1.0.0')\n    })\n\n    it('should append custom tags', () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: DEFAULT_MESSAGE,\n        ddtags: ['foo:bar'],\n      })\n      expect(serverLogs[0].ddtags).toEqual('sdk_version:test,env:test,service:service,version:1.0.0,foo:bar')\n    })\n  })\n\n  describe('beforeSend', () => {\n    it('should allow modification of existing fields', () => {\n      beforeSend = (event: LogsEvent) => {\n        event.message = 'modified message'\n        ;(event.service as any) = 'modified service'\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: DEFAULT_MESSAGE,\n      })\n\n      expect(serverLogs[0].message).toBe('modified message')\n      expect(serverLogs[0].service).toBe('modified service')\n    })\n\n    it('should allow adding new fields', () => {\n      beforeSend = (event: LogsEvent) => {\n        event.foo = 'bar'\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: DEFAULT_MESSAGE,\n      })\n\n      expect(serverLogs[0].foo).toBe('bar')\n    })\n  })\n})\n\ndescribe('logs limitation', () => {\n  let clock: Clock\n  let beforeSend: (event: LogsEvent) => void | boolean\n  let lifeCycle: LifeCycle\n  let hooks: Hooks\n  let serverLogs: Array<LogsEvent & Context> = []\n  let reportErrorSpy: jasmine.Spy<jasmine.Func>\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    hooks = createHooks()\n    lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (serverRumEvent) => serverLogs.push(serverRumEvent))\n    const configuration = {\n      ...validateAndBuildLogsConfiguration(initConfiguration)!,\n      maxBatchSize: 1,\n      beforeSend: (x: LogsEvent) => beforeSend(x),\n    }\n\n    beforeSend = noop\n    reportErrorSpy = jasmine.createSpy('reportError')\n    startLogsAssembly(configuration, lifeCycle, hooks, () => COMMON_CONTEXT, reportErrorSpy, 1)\n    clock = mockClock()\n  })\n\n  afterEach(() => {\n    serverLogs = []\n  })\n\n  it('should not apply to agent logs', () => {\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: { ...DEFAULT_MESSAGE, origin: ErrorSource.AGENT, status: 'error', message: 'foo' },\n    })\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: { ...DEFAULT_MESSAGE, origin: ErrorSource.AGENT, status: 'error', message: 'bar' },\n    })\n\n    expect(serverLogs.length).toEqual(2)\n    expect(reportErrorSpy).not.toHaveBeenCalled()\n    expect(serverLogs[0].message).toBe('foo')\n    expect(serverLogs[1].message).toBe('bar')\n  })\n  ;[\n    { status: StatusType.error, messageContext: {}, message: 'Reached max number of errors by minute: 1' },\n    { status: StatusType.warn, messageContext: {}, message: 'Reached max number of warns by minute: 1' },\n    { status: StatusType.info, messageContext: {}, message: 'Reached max number of infos by minute: 1' },\n    { status: StatusType.debug, messageContext: {}, message: 'Reached max number of debugs by minute: 1' },\n    {\n      status: StatusType.debug,\n      messageContext: { status: 'unknown' }, // overrides the rawLogsEvent status\n      message: 'Reached max number of customs by minute: 1',\n    },\n  ].forEach(({ status, message, messageContext }) => {\n    it(`stops sending ${status} logs when reaching the limit (message: \"${message}\")`, () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'foo', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'bar', status },\n        messageContext,\n      })\n\n      expect(serverLogs.length).toEqual(1)\n      expect(serverLogs[0].message).toBe('foo')\n      expect(reportErrorSpy).toHaveBeenCalledTimes(1)\n      expect(reportErrorSpy.calls.argsFor(0)[0]).toEqual(\n        jasmine.objectContaining({\n          message,\n          source: ErrorSource.AGENT,\n        })\n      )\n    })\n\n    it(`does not take discarded ${status} logs into account (message: \"${message}\")`, () => {\n      beforeSend = (event) => {\n        if (event.message === 'discard me') {\n          return false\n        }\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'discard me', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'discard me', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'discard me', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'foo', status },\n        messageContext,\n      })\n\n      expect(serverLogs.length).toEqual(1)\n      expect(serverLogs[0].message).toBe('foo')\n    })\n\n    it(`allows to send new ${status}s after a minute (message: \"${message}\")`, () => {\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'foo', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'bar', status },\n        messageContext,\n      })\n      clock.tick(ONE_MINUTE)\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'baz', status },\n        messageContext,\n      })\n\n      expect(serverLogs.length).toEqual(2)\n      expect(serverLogs[0].message).toEqual('foo')\n      expect(serverLogs[1].message).toEqual('baz')\n      expect(reportErrorSpy).toHaveBeenCalledTimes(1)\n      expect(reportErrorSpy.calls.argsFor(0)[0]).toEqual(\n        jasmine.objectContaining({\n          source: ErrorSource.AGENT,\n        })\n      )\n    })\n\n    it(`allows to send logs with a different status when reaching the limit (message: \"${message}\")`, () => {\n      const otherLogStatus = status === StatusType.error ? StatusType.info : StatusType.error\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'foo', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'bar', status },\n        messageContext,\n      })\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'baz', status: otherLogStatus },\n        ...{ ...messageContext, status: otherLogStatus },\n      })\n\n      expect(serverLogs.length).toEqual(2)\n      expect(serverLogs[0].message).toEqual('foo')\n      expect(serverLogs[1].message).toEqual('baz')\n      expect(reportErrorSpy).toHaveBeenCalledTimes(1)\n      expect(reportErrorSpy.calls.argsFor(0)[0]).toEqual(\n        jasmine.objectContaining({\n          source: ErrorSource.AGENT,\n        })\n      )\n    })\n  })\n\n  it('two different custom statuses are accounted by the same limit', () => {\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'foo', status: StatusType.info },\n      messageContext: { status: 'foo' },\n    })\n\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: { ...DEFAULT_MESSAGE, message: 'bar', status: StatusType.info },\n      messageContext: { status: 'bar' },\n    })\n\n    expect(serverLogs.length).toEqual(1)\n    expect(serverLogs[0].message).toEqual('foo')\n    expect(reportErrorSpy).toHaveBeenCalledTimes(1)\n    expect(reportErrorSpy.calls.argsFor(0)[0]).toEqual(\n      jasmine.objectContaining({\n        source: ErrorSource.AGENT,\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/assembly.ts",
    "content": "import type { Context, EventRateLimiter, RawError } from '@datadog/browser-core'\nimport {\n  DISCARDED,\n  ErrorSource,\n  HookNames,\n  buildTags,\n  combine,\n  createEventRateLimiter,\n  getRelativeTime,\n} from '@datadog/browser-core'\nimport type { CommonContext } from '../rawLogsEvent.types'\nimport type { LogsEvent } from '../logsEvent.types'\nimport type { LogsConfiguration } from './configuration'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\nimport { STATUSES } from './logger'\nimport type { Hooks } from './hooks'\n\nexport function startLogsAssembly(\n  configuration: LogsConfiguration,\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  getCommonContext: () => CommonContext,\n  reportError: (error: RawError) => void,\n  eventRateLimit?: number\n) {\n  const statusWithCustom = (STATUSES as string[]).concat(['custom'])\n  const logRateLimiters: { [key: string]: EventRateLimiter } = {}\n  statusWithCustom.forEach((status) => {\n    logRateLimiters[status] = createEventRateLimiter(status, reportError, eventRateLimit)\n  })\n\n  lifeCycle.subscribe(\n    LifeCycleEventType.RAW_LOG_COLLECTED,\n    ({ rawLogsEvent, messageContext = undefined, savedCommonContext = undefined, domainContext, ddtags = [] }) => {\n      const startTime = getRelativeTime(rawLogsEvent.date)\n      const commonContext = savedCommonContext || getCommonContext()\n      const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime,\n      })\n\n      if (defaultLogsEventAttributes === DISCARDED) {\n        return\n      }\n\n      const defaultDdtags = buildTags(configuration)\n\n      const log = combine(\n        {\n          view: commonContext.view,\n        },\n        defaultLogsEventAttributes,\n        rawLogsEvent,\n        messageContext,\n        {\n          ddtags: defaultDdtags.concat(ddtags).join(','),\n        }\n      ) as LogsEvent & Context\n\n      if (\n        configuration.beforeSend?.(log, domainContext) === false ||\n        (log.origin !== ErrorSource.AGENT &&\n          (logRateLimiters[log.status] ?? logRateLimiters['custom']).isLimitReached())\n      ) {\n        return\n      }\n\n      lifeCycle.notify(LifeCycleEventType.LOG_COLLECTED, log)\n    }\n  )\n}\n"
  },
  {
    "path": "packages/logs/src/domain/configuration.spec.ts",
    "content": "import type { InitConfiguration } from '@datadog/browser-core'\nimport { display } from '@datadog/browser-core'\nimport {\n  EXHAUSTIVE_INIT_CONFIGURATION,\n  type CamelToSnakeCase,\n  type ExtractTelemetryConfiguration,\n  type MapInitConfigurationKey,\n  SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION,\n} from '../../../core/test'\nimport type { LogsInitConfiguration } from './configuration'\nimport {\n  serializeLogsConfiguration,\n  validateAndBuildForwardOption,\n  validateAndBuildLogsConfiguration,\n} from './configuration'\n\nconst DEFAULT_INIT_CONFIGURATION = { clientToken: 'xxx' }\n\ndescribe('validateAndBuildLogsConfiguration', () => {\n  describe('forwardErrorsToLogs', () => {\n    it('defaults to true if the option is not provided', () => {\n      expect(validateAndBuildLogsConfiguration(DEFAULT_INIT_CONFIGURATION)!.forwardErrorsToLogs).toBeTrue()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: true })!\n          .forwardErrorsToLogs\n      ).toBeTrue()\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: false })!\n          .forwardErrorsToLogs\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: 'foo' as any })!\n          .forwardErrorsToLogs\n      ).toBeTrue()\n    })\n\n    it('is set to true for falsy values other than `false`', () => {\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: null as any })!\n          .forwardErrorsToLogs\n      ).toBeTrue()\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: '' as any })!\n          .forwardErrorsToLogs\n      ).toBeTrue()\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: 0 as any })!\n          .forwardErrorsToLogs\n      ).toBeTrue()\n    })\n  })\n\n  describe('forwardConsoleLogs', () => {\n    it('contains \"error\" when forwardErrorsToLogs is enabled', () => {\n      expect(\n        validateAndBuildLogsConfiguration({ ...DEFAULT_INIT_CONFIGURATION, forwardErrorsToLogs: true })!\n          .forwardConsoleLogs\n      ).toEqual(['error'])\n    })\n\n    it('contains \"error\" once when both forwardErrorsToLogs and forwardConsoleLogs are enabled', () => {\n      expect(\n        validateAndBuildLogsConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          forwardConsoleLogs: ['error'],\n          forwardErrorsToLogs: true,\n        })!.forwardConsoleLogs\n      ).toEqual(['error'])\n    })\n  })\n\n  describe('PCI compliant intake option', () => {\n    let warnSpy: jasmine.Spy<typeof display.warn>\n\n    beforeEach(() => {\n      warnSpy = spyOn(display, 'warn')\n    })\n    it('should display warning with wrong PCI intake configuration', () => {\n      validateAndBuildLogsConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        site: 'us3.datadoghq.com',\n        usePciIntake: true,\n      })\n      expect(warnSpy).toHaveBeenCalledOnceWith(\n        'PCI compliance for Logs is only available for Datadog organizations in the US1 site. Default intake will be used.'\n      )\n    })\n  })\n})\n\ndescribe('validateAndBuildForwardOption', () => {\n  let displaySpy: jasmine.Spy<typeof display.error>\n  const allowedValues = ['foo', 'bar']\n  const label = 'Label'\n  const errorMessage = 'Label should be \"all\" or an array with allowed values \"foo\", \"bar\"'\n\n  beforeEach(() => {\n    displaySpy = spyOn(display, 'error')\n  })\n\n  it('does not validate the configuration if an incorrect string is provided', () => {\n    validateAndBuildForwardOption('foo' as any, allowedValues, label)\n\n    expect(displaySpy).toHaveBeenCalledOnceWith(errorMessage)\n  })\n\n  it('does not validate the configuration if an incorrect api is provided', () => {\n    validateAndBuildForwardOption(['dir'], allowedValues, label)\n\n    expect(displaySpy).toHaveBeenCalledOnceWith(errorMessage)\n  })\n\n  it('defaults to an empty array', () => {\n    expect(validateAndBuildForwardOption(undefined, allowedValues, label)).toEqual([])\n  })\n\n  it('is set to provided value', () => {\n    expect(validateAndBuildForwardOption(['foo'], allowedValues, label)).toEqual(['foo'])\n  })\n\n  it('contains all options when \"all\" is provided', () => {\n    expect(validateAndBuildForwardOption('all', allowedValues, label)).toEqual(allowedValues)\n  })\n})\n\ndescribe('serializeLogsConfiguration', () => {\n  it('should serialize the configuration', () => {\n    const exhaustiveLogsInitConfiguration: Required<LogsInitConfiguration> = {\n      ...EXHAUSTIVE_INIT_CONFIGURATION,\n      beforeSend: () => true,\n      forwardErrorsToLogs: true,\n      forwardConsoleLogs: 'all',\n      forwardReports: 'all',\n      usePciIntake: false,\n    }\n\n    type MapLogsInitConfigurationKey<Key extends string> = Key extends keyof InitConfiguration\n      ? MapInitConfigurationKey<Key>\n      : CamelToSnakeCase<Key>\n\n    // By specifying the type here, we can ensure that serializeConfiguration is returning an\n    // object containing all expected properties.\n    const serializedConfiguration: ExtractTelemetryConfiguration<\n      MapLogsInitConfigurationKey<keyof LogsInitConfiguration>\n    > = serializeLogsConfiguration(exhaustiveLogsInitConfiguration)\n\n    expect(serializedConfiguration).toEqual({\n      ...SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION,\n      forward_errors_to_logs: true,\n      forward_console_logs: 'all',\n      forward_reports: 'all',\n      use_pci_intake: false,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/configuration.ts",
    "content": "import type { Configuration, InitConfiguration, RawTelemetryConfiguration } from '@datadog/browser-core'\nimport {\n  serializeConfiguration,\n  ONE_KIBI_BYTE,\n  validateAndBuildConfiguration,\n  display,\n  removeDuplicates,\n  ConsoleApiName,\n  RawReportType,\n  objectValues,\n} from '@datadog/browser-core'\nimport type { LogsEvent } from '../logsEvent.types'\nimport type { LogsEventDomainContext } from '../domainContext.types'\n\n/**\n * Init Configuration for the Logs browser SDK.\n *\n * @category Main\n * @example NPM\n * ```ts\n * import { datadogLogs } from '@datadog/browser-logs'\n *\n * datadogLogs.init({\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   site: '<DATADOG_SITE>',\n *   // ...\n * })\n * ```\n * @example CDN\n * ```ts\n * DD_LOGS.init({\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   site: '<DATADOG_SITE>',\n *   // ...\n * })\n * ```\n */\nexport interface LogsInitConfiguration extends InitConfiguration {\n  /**\n   * Access to every logs collected by the Logs SDK before they are sent to Datadog.\n   * It allows:\n   * - Enrich your logs with additional context attributes\n   * - Modify your logs to modify their content, or redact sensitive sequences (see the list of editable properties)\n   * - Discard selected logs\n   *\n   * @category Data Collection\n   */\n  beforeSend?: LogsBeforeSend | undefined\n\n  /**\n   * Forward console.error logs, uncaught exceptions and network errors to Datadog.\n   *\n   * @category Data Collection\n   * @defaultValue true\n   */\n  forwardErrorsToLogs?: boolean | undefined\n\n  /**\n   * Forward logs from console.* to Datadog. Use \"all\" to forward everything or an array of console API names to forward only a subset.\n   *\n   * @category Data Collection\n   */\n  forwardConsoleLogs?: ConsoleApiName[] | 'all' | undefined\n\n  /**\n   * Forward reports from the [Reporting API](https://developer.mozilla.org/en-US/docs/Web/API/Reporting_API) to Datadog. Use \"all\" to forward everything or an array of report types to forward only a subset.\n   *\n   * @category Data Collection\n   */\n  forwardReports?: RawReportType[] | 'all' | undefined\n\n  /**\n   * Use PCI-compliant intake. See [PCI DSS Compliance](https://docs.datadoghq.com/data_security/pci_compliance/?tab=logmanagement) for further information.\n   *\n   * @category Privacy\n   * @defaultValue false\n   */\n  usePciIntake?: boolean\n}\n\n/**\n * Function called before a Log event is sent to Datadog. See {@link LogsInitConfiguration.beforeSend}\n *\n * @param event - The log event\n * @param context - The log event domain context\n * @returns true if the event should be sent to Datadog, false otherwise\n */\nexport type LogsBeforeSend = (event: LogsEvent, context: LogsEventDomainContext) => boolean\n\nexport type HybridInitConfiguration = Omit<LogsInitConfiguration, 'clientToken'>\n\nexport interface LogsConfiguration extends Configuration {\n  forwardErrorsToLogs: boolean\n  forwardConsoleLogs: ConsoleApiName[]\n  forwardReports: RawReportType[]\n  requestErrorResponseLengthLimit: number\n}\n\n/**\n * arbitrary value, byte precision not needed\n */\nexport const DEFAULT_REQUEST_ERROR_RESPONSE_LENGTH_LIMIT = 32 * ONE_KIBI_BYTE\n\nexport function validateAndBuildLogsConfiguration(\n  initConfiguration: LogsInitConfiguration,\n  errorStack?: string\n): LogsConfiguration | undefined {\n  if (initConfiguration.usePciIntake === true && initConfiguration.site && initConfiguration.site !== 'datadoghq.com') {\n    display.warn(\n      'PCI compliance for Logs is only available for Datadog organizations in the US1 site. Default intake will be used.'\n    )\n  }\n\n  const baseConfiguration = validateAndBuildConfiguration(initConfiguration, errorStack)\n\n  const forwardConsoleLogs = validateAndBuildForwardOption<ConsoleApiName>(\n    initConfiguration.forwardConsoleLogs,\n    objectValues(ConsoleApiName),\n    'Forward Console Logs'\n  )\n\n  const forwardReports = validateAndBuildForwardOption<RawReportType>(\n    initConfiguration.forwardReports,\n    objectValues(RawReportType),\n    'Forward Reports'\n  )\n\n  if (!baseConfiguration || !forwardConsoleLogs || !forwardReports) {\n    return\n  }\n\n  if (initConfiguration.forwardErrorsToLogs && !forwardConsoleLogs.includes(ConsoleApiName.error)) {\n    forwardConsoleLogs.push(ConsoleApiName.error)\n  }\n\n  return {\n    forwardErrorsToLogs: initConfiguration.forwardErrorsToLogs !== false,\n    forwardConsoleLogs,\n    forwardReports,\n    requestErrorResponseLengthLimit: DEFAULT_REQUEST_ERROR_RESPONSE_LENGTH_LIMIT,\n    ...baseConfiguration,\n  }\n}\n\nexport function validateAndBuildForwardOption<T>(\n  option: readonly T[] | 'all' | undefined,\n  allowedValues: T[],\n  label: string\n): T[] | undefined {\n  if (option === undefined) {\n    return []\n  }\n\n  if (!(option === 'all' || (Array.isArray(option) && option.every((api) => allowedValues.includes(api))))) {\n    display.error(`${label} should be \"all\" or an array with allowed values \"${allowedValues.join('\", \"')}\"`)\n    return\n  }\n\n  return option === 'all' ? allowedValues : removeDuplicates<T>(option)\n}\n\nexport function serializeLogsConfiguration(configuration: LogsInitConfiguration) {\n  const baseSerializedInitConfiguration = serializeConfiguration(configuration)\n\n  return {\n    forward_errors_to_logs: configuration.forwardErrorsToLogs,\n    forward_console_logs: configuration.forwardConsoleLogs,\n    forward_reports: configuration.forwardReports,\n    use_pci_intake: configuration.usePciIntake,\n    ...baseSerializedInitConfiguration,\n  } satisfies RawTelemetryConfiguration\n}\n"
  },
  {
    "path": "packages/logs/src/domain/console/consoleCollection.spec.ts",
    "content": "import type { Context, ErrorWithCause } from '@datadog/browser-core'\nimport { ErrorHandling, ErrorSource, noop, objectEntries } from '@datadog/browser-core'\nimport type { RawConsoleLogsEvent } from '../../rawLogsEvent.types'\nimport { validateAndBuildLogsConfiguration } from '../configuration'\nimport type { RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { startConsoleCollection, LogStatusForApi } from './consoleCollection'\n\ndescribe('console collection', () => {\n  const initConfiguration = { clientToken: 'xxx', service: 'service' }\n  let consoleSpies: { [key: string]: jasmine.Spy }\n  let stopConsoleCollection: () => void\n  let lifeCycle: LifeCycle\n  let rawLogsEvents: Array<RawLogsEventCollectedData<RawConsoleLogsEvent>>\n\n  beforeEach(() => {\n    rawLogsEvents = []\n    lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.RAW_LOG_COLLECTED, (rawLogsEvent) =>\n      rawLogsEvents.push(rawLogsEvent as RawLogsEventCollectedData<RawConsoleLogsEvent>)\n    )\n    stopConsoleCollection = noop\n    consoleSpies = {\n      log: spyOn(console, 'log').and.callFake(() => true),\n      debug: spyOn(console, 'debug').and.callFake(() => true),\n      info: spyOn(console, 'info').and.callFake(() => true),\n      warn: spyOn(console, 'warn').and.callFake(() => true),\n      error: spyOn(console, 'error').and.callFake(() => true),\n    }\n  })\n\n  afterEach(() => {\n    stopConsoleCollection()\n  })\n\n  objectEntries(LogStatusForApi).forEach(([api, status]) => {\n    it(`should collect ${status} logs from console.${api}`, () => {\n      ;({ stop: stopConsoleCollection } = startConsoleCollection(\n        validateAndBuildLogsConfiguration({ ...initConfiguration, forwardConsoleLogs: 'all' })!,\n        lifeCycle\n      ))\n\n      /* eslint-disable-next-line no-console */\n      console[api as keyof typeof LogStatusForApi]('foo', 'bar')\n\n      expect(rawLogsEvents[0].rawLogsEvent).toEqual({\n        date: jasmine.any(Number),\n        message: 'foo bar',\n        status,\n        origin: ErrorSource.CONSOLE,\n        error: whatever(),\n      })\n\n      expect(rawLogsEvents[0].domainContext).toEqual({\n        handlingStack: jasmine.any(String),\n      })\n\n      expect(consoleSpies[api]).toHaveBeenCalled()\n    })\n  })\n\n  it('console error should have an error object defined', () => {\n    ;({ stop: stopConsoleCollection } = startConsoleCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration, forwardErrorsToLogs: true })!,\n      lifeCycle\n    ))\n\n    /* eslint-disable-next-line no-console */\n    console.error('foo', 'bar')\n\n    expect(rawLogsEvents[0].rawLogsEvent.error).toEqual({\n      stack: undefined,\n      fingerprint: undefined,\n      causes: undefined,\n      handling: ErrorHandling.HANDLED,\n      kind: undefined,\n      message: undefined,\n    })\n  })\n\n  it('should retrieve fingerprint from console error', () => {\n    ;({ stop: stopConsoleCollection } = startConsoleCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration, forwardErrorsToLogs: true })!,\n      lifeCycle\n    ))\n    interface DatadogError extends Error {\n      dd_fingerprint?: string\n    }\n    const error = new Error('foo')\n    ;(error as DatadogError).dd_fingerprint = 'my-fingerprint'\n\n    // eslint-disable-next-line no-console\n    console.error(error)\n\n    expect(rawLogsEvents[0].rawLogsEvent.error).toEqual({\n      stack: jasmine.any(String),\n      fingerprint: 'my-fingerprint',\n      causes: undefined,\n      handling: ErrorHandling.HANDLED,\n      kind: 'Error',\n      message: undefined,\n    })\n  })\n\n  it('should retrieve dd_context from console', () => {\n    ;({ stop: stopConsoleCollection } = startConsoleCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration, forwardErrorsToLogs: true })!,\n      lifeCycle\n    ))\n    interface DatadogError extends Error {\n      dd_context?: Context\n    }\n    const error = new Error('foo')\n    ;(error as DatadogError).dd_context = { foo: 'bar' }\n\n    // eslint-disable-next-line no-console\n    console.error(error)\n\n    expect(rawLogsEvents[0].messageContext).toEqual({ foo: 'bar' })\n  })\n\n  it('should retrieve causes from console error', () => {\n    ;({ stop: stopConsoleCollection } = startConsoleCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration, forwardErrorsToLogs: true })!,\n      lifeCycle\n    ))\n    const error = new Error('High level error') as ErrorWithCause\n    error.stack = 'Error: High level error'\n\n    const nestedError = new Error('Mid level error') as ErrorWithCause\n    nestedError.stack = 'Error: Mid level error'\n\n    const deepNestedError = new TypeError('Low level error') as ErrorWithCause\n    deepNestedError.stack = 'TypeError: Low level error'\n\n    nestedError.cause = deepNestedError\n    error.cause = nestedError\n\n    // eslint-disable-next-line no-console\n    console.error(error)\n\n    expect(rawLogsEvents[0].rawLogsEvent.error).toEqual({\n      stack: jasmine.any(String),\n      handling: ErrorHandling.HANDLED,\n      causes: [\n        {\n          source: ErrorSource.CONSOLE,\n          type: 'Error',\n          stack: jasmine.any(String),\n          message: 'Mid level error',\n        },\n        {\n          source: ErrorSource.CONSOLE,\n          type: 'TypeError',\n          stack: jasmine.any(String),\n          message: 'Low level error',\n        },\n      ],\n      fingerprint: undefined,\n      kind: 'Error',\n      message: undefined,\n    })\n  })\n})\n\nfunction whatever() {\n  return {\n    asymmetricMatch: () => true,\n    jasmineToString: () => '<whatever>',\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/console/consoleCollection.ts",
    "content": "import type { Context, ClocksState, ConsoleLog } from '@datadog/browser-core'\nimport { timeStampNow, ConsoleApiName, ErrorSource, initConsoleObservable } from '@datadog/browser-core'\nimport type { LogsConfiguration } from '../configuration'\nimport type { LifeCycle, RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { StatusType } from '../logger/isAuthorized'\nimport type { RawLogsEvent } from '../../rawLogsEvent.types'\nimport { createErrorFieldFromRawError } from '../createErrorFieldFromRawError'\n\nexport interface ProvidedError {\n  startClocks: ClocksState\n  error: unknown\n  context?: Context\n  handlingStack: string\n}\n\nexport const LogStatusForApi = {\n  [ConsoleApiName.log]: StatusType.info,\n  [ConsoleApiName.debug]: StatusType.debug,\n  [ConsoleApiName.info]: StatusType.info,\n  [ConsoleApiName.warn]: StatusType.warn,\n  [ConsoleApiName.error]: StatusType.error,\n}\nexport function startConsoleCollection(configuration: LogsConfiguration, lifeCycle: LifeCycle) {\n  const consoleSubscription = initConsoleObservable(configuration.forwardConsoleLogs).subscribe((log: ConsoleLog) => {\n    const collectedData: RawLogsEventCollectedData<RawLogsEvent> = {\n      rawLogsEvent: {\n        date: timeStampNow(),\n        message: log.message,\n        origin: ErrorSource.CONSOLE,\n        error: log.error && createErrorFieldFromRawError(log.error),\n        status: LogStatusForApi[log.api],\n      },\n      messageContext: log.error?.context,\n      domainContext: {\n        handlingStack: log.handlingStack,\n      },\n    }\n\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, collectedData)\n  })\n\n  return {\n    stop: () => {\n      consoleSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/commonContext.ts",
    "content": "import { isWorkerEnvironment } from '@datadog/browser-core'\nimport type { CommonContext } from '../../rawLogsEvent.types'\n\nexport function buildCommonContext(): CommonContext {\n  if (isWorkerEnvironment) {\n    return {}\n  }\n\n  return {\n    view: {\n      referrer: document.referrer,\n      url: window.location.href,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/internalContext.spec.ts",
    "content": "import { createLogsSessionManagerMock } from '../../../test/mockLogsSessionManager'\nimport { startInternalContext } from './internalContext'\n\ndescribe('internal context', () => {\n  it('should return undefined if session is not tracked', () => {\n    const sessionManagerMock = createLogsSessionManagerMock().setNotTracked()\n    expect(startInternalContext(sessionManagerMock).get()).toEqual(undefined)\n  })\n\n  it('should return internal context corresponding to startTime', () => {\n    const sessionManagerMock = createLogsSessionManagerMock().setTracked()\n    expect(startInternalContext(sessionManagerMock).get()).toEqual({\n      session_id: jasmine.any(String),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/internalContext.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport type { LogsSessionManager } from '../logsSessionManager'\n\nexport interface InternalContext {\n  session_id: string | undefined\n}\n\nexport function startInternalContext(sessionManager: LogsSessionManager) {\n  return {\n    get: (startTime?: number): InternalContext | undefined => {\n      const trackedSession = sessionManager.findTrackedSession(startTime as RelativeTime)\n      if (trackedSession) {\n        return {\n          session_id: trackedSession.id,\n        }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/rumInternalContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { HookNames } from '@datadog/browser-core'\nimport { mockSyntheticsWorkerValues } from '@datadog/browser-core/test'\nimport type { Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startRUMInternalContext } from './rumInternalContext'\n\ndescribe('startRUMInternalContext', () => {\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n    startRUMInternalContext(hooks)\n  })\n\n  afterEach(() => {\n    delete window.DD_RUM\n    delete window.DD_RUM_SYNTHETICS\n  })\n\n  describe('assemble hook', () => {\n    it('returns undefined if no RUM instance is present', () => {\n      const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultLogsEventAttributes).toBeUndefined()\n    })\n\n    it('returns undefined if the global variable does not have a `getInternalContext` method', () => {\n      window.DD_RUM = {} as any\n      const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n      expect(defaultLogsEventAttributes).toBeUndefined()\n    })\n\n    it('returns the internal context from the `getInternalContext` method', () => {\n      window.DD_RUM = {\n        getInternalContext: () => ({ foo: 'bar' }),\n      }\n      const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n      expect(defaultLogsEventAttributes).toEqual({ foo: 'bar' })\n    })\n\n    describe('when RUM is injected by Synthetics', () => {\n      beforeEach(() => {\n        mockSyntheticsWorkerValues({ injectsRum: true, context: { test_id: 'test-id', result_id: 'result-id' } })\n      })\n\n      it('uses the global variable created when the synthetics worker is injecting RUM', () => {\n        window.DD_RUM_SYNTHETICS = {\n          getInternalContext: () => ({ foo: 'bar' }),\n        }\n        const defaultLogsEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          startTime: 0 as RelativeTime,\n        })\n        expect(defaultLogsEventAttributes).toEqual({ foo: 'bar' })\n      })\n    })\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should set internal context', () => {\n      window.DD_RUM = {\n        getInternalContext: () => ({ application_id: '123', view: { id: '456' }, user_action: { id: '789' } }),\n      }\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        application: { id: '123' },\n        view: { id: '456' },\n        action: { id: '789' },\n      })\n    })\n\n    it('should not set internal context if the RUM instance is not present', () => {\n      window.DD_RUM = {\n        getInternalContext: () => undefined,\n      }\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual(undefined)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/rumInternalContext.ts",
    "content": "import type { RelativeTime, RumInternalContext } from '@datadog/browser-core'\nimport { globalObject, willSyntheticsInjectRum, HookNames, SKIPPED } from '@datadog/browser-core'\nimport type { Hooks } from '../hooks'\n\ninterface Rum {\n  getInternalContext?: (startTime?: RelativeTime) => RumInternalContext | undefined\n}\n\ninterface BrowserWindow {\n  DD_RUM?: Rum\n  DD_RUM_SYNTHETICS?: Rum\n}\n\nexport function startRUMInternalContext(hooks: Hooks) {\n  const browserWindow = globalObject as BrowserWindow\n\n  hooks.register(HookNames.Assemble, ({ startTime }) => {\n    const internalContext = getRUMInternalContext(startTime)\n    if (!internalContext) {\n      return SKIPPED\n    }\n\n    return internalContext\n  })\n\n  hooks.register(HookNames.AssembleTelemetry, ({ startTime }) => {\n    const internalContext = getRUMInternalContext(startTime)\n\n    if (!internalContext) {\n      return SKIPPED\n    }\n\n    return {\n      application: { id: internalContext.application_id },\n      view: { id: internalContext.view?.id },\n      action: { id: internalContext.user_action?.id as string },\n    }\n  })\n\n  function getRUMInternalContext(startTime?: RelativeTime) {\n    const willSyntheticsInjectRumResult = willSyntheticsInjectRum()\n    const rumSource = willSyntheticsInjectRumResult ? browserWindow.DD_RUM_SYNTHETICS : browserWindow.DD_RUM\n    const rumContext = getInternalContextFromRumGlobal(startTime, rumSource)\n\n    if (rumContext) {\n      return rumContext\n    }\n  }\n\n  function getInternalContextFromRumGlobal(startTime?: RelativeTime, rumGlobal?: Rum): RumInternalContext | undefined {\n    if (rumGlobal && rumGlobal.getInternalContext) {\n      return rumGlobal.getInternalContext(startTime)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/sessionContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { DISCARDED, HookNames } from '@datadog/browser-core'\nimport type { LogsSessionManager } from '../logsSessionManager'\nimport type { DefaultLogsEventAttributes, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport type { LogsConfiguration } from '../configuration'\nimport { createLogsSessionManagerMock } from '../../../test/mockLogsSessionManager'\nimport { startSessionContext } from './sessionContext'\n\ndescribe('session context', () => {\n  let hooks: Hooks\n  let sessionManager: LogsSessionManager\n  const configuration = { service: 'foo' } as LogsConfiguration\n\n  beforeEach(() => {\n    hooks = createHooks()\n    sessionManager = createLogsSessionManagerMock().setTracked()\n  })\n\n  describe('assemble  hook', () => {\n    it('should set service', () => {\n      startSessionContext(hooks, configuration, sessionManager)\n\n      const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      }) as DefaultLogsEventAttributes\n\n      expect(defaultLogAttributes.service).toEqual(jasmine.any(String))\n    })\n\n    it('should discard logs if session is not tracked', () => {\n      startSessionContext(hooks, configuration, createLogsSessionManagerMock().setNotTracked())\n\n      const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultLogAttributes).toBe(DISCARDED)\n    })\n\n    it('should set session id if session is active', () => {\n      startSessionContext(hooks, configuration, createLogsSessionManagerMock().setTracked())\n\n      const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultLogAttributes).toEqual({\n        service: jasmine.any(String),\n        session_id: jasmine.any(String),\n        session: { id: jasmine.any(String) },\n      })\n    })\n\n    it('should no set session id if session has expired', () => {\n      startSessionContext(hooks, configuration, createLogsSessionManagerMock().expire())\n\n      const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultLogAttributes).toEqual({\n        service: jasmine.any(String),\n        session_id: undefined,\n        session: undefined,\n      })\n    })\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should set the session id', () => {\n      startSessionContext(hooks, configuration, createLogsSessionManagerMock())\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toEqual({\n        session: { id: jasmine.any(String) },\n      })\n    })\n\n    it('should not set the session id if session is not tracked', () => {\n      startSessionContext(hooks, configuration, createLogsSessionManagerMock().setNotTracked())\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/sessionContext.ts",
    "content": "import { DISCARDED, HookNames, SKIPPED } from '@datadog/browser-core'\nimport type { LogsConfiguration } from '../configuration'\nimport type { LogsSessionManager } from '../logsSessionManager'\nimport type { Hooks } from '../hooks'\n\nexport function startSessionContext(\n  hooks: Hooks,\n  configuration: LogsConfiguration,\n  sessionManager: LogsSessionManager\n) {\n  hooks.register(HookNames.Assemble, ({ startTime }) => {\n    const session = sessionManager.findTrackedSession(startTime)\n\n    const isSessionTracked = sessionManager.findTrackedSession(startTime, { returnInactive: true })\n\n    if (!isSessionTracked) {\n      return DISCARDED\n    }\n\n    return {\n      service: configuration.service,\n      session_id: session ? session.id : undefined,\n      session: session ? { id: session.id } : undefined,\n    }\n  })\n\n  hooks.register(HookNames.AssembleTelemetry, ({ startTime }) => {\n    const session = sessionManager.findTrackedSession(startTime)\n\n    if (!session || !session.id) {\n      return SKIPPED\n    }\n\n    return {\n      session: { id: session.id },\n    }\n  })\n}\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/trackingConsentContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { DISCARDED, HookNames, createTrackingConsentState, TrackingConsent } from '@datadog/browser-core'\nimport type { DefaultLogsEventAttributes, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startTrackingConsentContext } from './trackingConsentContext'\n\ndescribe('tracking consent context', () => {\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n  })\n\n  it('should discard logs if consent is not granted', () => {\n    const trackingConsentState = createTrackingConsentState(TrackingConsent.NOT_GRANTED)\n    startTrackingConsentContext(hooks, trackingConsentState)\n\n    const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 0 as RelativeTime,\n    })\n\n    expect(defaultLogAttributes).toBe(DISCARDED)\n  })\n\n  it('should not discard logs if consent is granted and no startTime is provided', () => {\n    const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n    startTrackingConsentContext(hooks, trackingConsentState)\n\n    const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n      startTime: undefined as any,\n    }) as DefaultLogsEventAttributes\n\n    expect(defaultLogAttributes).toBeUndefined()\n  })\n\n  it('should not discard logs when startTime is provided (due to empty history)', () => {\n    const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n    startTrackingConsentContext(hooks, trackingConsentState)\n\n    const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 100 as RelativeTime,\n    })\n\n    expect(defaultLogAttributes).toBeUndefined()\n  })\n\n  it('should discard logs when startTime is provided and consent was not granted initially', () => {\n    const trackingConsentState = createTrackingConsentState(TrackingConsent.NOT_GRANTED)\n    startTrackingConsentContext(hooks, trackingConsentState)\n\n    const defaultLogAttributes = hooks.triggerHook(HookNames.Assemble, {\n      startTime: 100 as RelativeTime,\n    })\n\n    expect(defaultLogAttributes).toBe(DISCARDED)\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/contexts/trackingConsentContext.ts",
    "content": "import { DISCARDED, HookNames, SKIPPED } from '@datadog/browser-core'\nimport type { TrackingConsentState } from '@datadog/browser-core'\nimport type { Hooks } from '../hooks'\n\nexport function startTrackingConsentContext(hooks: Hooks, trackingConsentState: TrackingConsentState) {\n  function isConsented() {\n    const wasConsented = trackingConsentState.isGranted()\n\n    if (!wasConsented) {\n      return DISCARDED\n    }\n\n    return SKIPPED\n  }\n\n  hooks.register(HookNames.Assemble, isConsented)\n  hooks.register(HookNames.AssembleTelemetry, isConsented)\n}\n"
  },
  {
    "path": "packages/logs/src/domain/createErrorFieldFromRawError.spec.ts",
    "content": "import { ErrorHandling, ErrorSource, type RawError, type RelativeTime, type TimeStamp } from '@datadog/browser-core'\nimport { createErrorFieldFromRawError } from './createErrorFieldFromRawError'\n\ndescribe('createErrorFieldFromRawError', () => {\n  const exhaustiveRawError: Required<RawError> = {\n    startClocks: {\n      relative: 0 as RelativeTime,\n      timeStamp: 0 as TimeStamp,\n    },\n    source: ErrorSource.LOGGER,\n    handling: ErrorHandling.HANDLED,\n    handlingStack: 'Error\\n    at foo (bar)',\n    componentStack: 'at Flex',\n    originalError: new Error('baz'),\n    type: 'qux',\n    message: 'quux',\n    stack: 'quuz',\n    causes: [],\n    fingerprint: 'corge',\n    csp: {\n      disposition: 'enforce',\n    },\n    context: {\n      foo: 'bar',\n    },\n  }\n\n  it('creates an error field from a raw error', () => {\n    expect(createErrorFieldFromRawError(exhaustiveRawError)).toEqual({\n      message: undefined,\n      kind: 'qux',\n      stack: 'quuz',\n      causes: [],\n      fingerprint: 'corge',\n      handling: ErrorHandling.HANDLED,\n    })\n  })\n\n  it('includes the message if includeMessage is true', () => {\n    expect(createErrorFieldFromRawError(exhaustiveRawError, { includeMessage: true }).message).toBe('quux')\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/createErrorFieldFromRawError.ts",
    "content": "import type { RawError } from '@datadog/browser-core'\nimport type { RawLoggerLogsEvent } from '../rawLogsEvent.types'\n\nexport function createErrorFieldFromRawError(\n  rawError: RawError,\n  {\n    /**\n     * Set this to `true` to include the error message in the error field. In most cases, the error\n     * message is already included in the log message, so we don't need to include it again.\n     */\n    includeMessage = false,\n  } = {}\n): NonNullable<RawLoggerLogsEvent['error']> {\n  return {\n    stack: rawError.stack,\n    kind: rawError.type,\n    message: includeMessage ? rawError.message : undefined,\n    causes: rawError.causes,\n    fingerprint: rawError.fingerprint,\n    handling: rawError.handling,\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/hooks.ts",
    "content": "import type {\n  DISCARDED,\n  HookNamesAsConst,\n  RecursivePartial,\n  RelativeTime,\n  SKIPPED,\n  TelemetryEvent,\n} from '@datadog/browser-core'\nimport { abstractHooks } from '@datadog/browser-core'\nimport type { LogsEvent } from '../logsEvent.types'\n\nexport type DefaultLogsEventAttributes = RecursivePartial<LogsEvent>\nexport type DefaultTelemetryEventAttributes = RecursivePartial<TelemetryEvent>\n\nexport interface HookCallbackMap {\n  [HookNamesAsConst.ASSEMBLE]: (param: { startTime: RelativeTime }) => DefaultLogsEventAttributes | SKIPPED | DISCARDED\n  [HookNamesAsConst.ASSEMBLE_TELEMETRY]: (param: {\n    startTime: RelativeTime\n  }) => DefaultTelemetryEventAttributes | SKIPPED | DISCARDED\n}\n\nexport type Hooks = ReturnType<typeof createHooks>\n\nexport const createHooks = abstractHooks<HookCallbackMap>\n"
  },
  {
    "path": "packages/logs/src/domain/lifeCycle.ts",
    "content": "import { AbstractLifeCycle } from '@datadog/browser-core'\nimport type { Context } from '@datadog/browser-core'\nimport type { LogsEvent } from '../logsEvent.types'\nimport type { CommonContext, RawLogsEvent } from '../rawLogsEvent.types'\nimport type { LogsEventDomainContext } from '../domainContext.types'\n\nexport const enum LifeCycleEventType {\n  RAW_LOG_COLLECTED,\n  LOG_COLLECTED,\n}\n\ninterface LifeCycleEventMap {\n  [LifeCycleEventType.RAW_LOG_COLLECTED]: RawLogsEventCollectedData\n  [LifeCycleEventType.LOG_COLLECTED]: LogsEvent & Context\n}\n\nexport const LifeCycle = AbstractLifeCycle<LifeCycleEventMap>\nexport type LifeCycle = AbstractLifeCycle<LifeCycleEventMap>\n\nexport interface RawLogsEventCollectedData<E extends RawLogsEvent = RawLogsEvent> {\n  rawLogsEvent: E\n  messageContext?: Context\n  savedCommonContext?: CommonContext\n  domainContext?: LogsEventDomainContext<E['origin']>\n  ddtags?: string[]\n}\n"
  },
  {
    "path": "packages/logs/src/domain/logger/isAuthorized.ts",
    "content": "import type { Logger, HandlerType } from '../logger'\n\nexport function isAuthorized(status: StatusType, handlerType: HandlerType, logger: Logger) {\n  const loggerHandler = logger.getHandler()\n  const sanitizedHandlerType = Array.isArray(loggerHandler) ? loggerHandler : [loggerHandler]\n  return STATUS_PRIORITIES[status] >= STATUS_PRIORITIES[logger.getLevel()] && sanitizedHandlerType.includes(handlerType)\n}\n\nexport const StatusType = {\n  ok: 'ok',\n  debug: 'debug',\n  info: 'info',\n  notice: 'notice',\n  warn: 'warn',\n  error: 'error',\n  critical: 'critical',\n  alert: 'alert',\n  emerg: 'emerg',\n} as const\n\nexport const STATUS_PRIORITIES: { [key in StatusType]: number } = {\n  [StatusType.ok]: 0,\n  [StatusType.debug]: 1,\n  [StatusType.info]: 2,\n  [StatusType.notice]: 4,\n  [StatusType.warn]: 5,\n  [StatusType.error]: 6,\n  [StatusType.critical]: 7,\n  [StatusType.alert]: 8,\n  [StatusType.emerg]: 9,\n}\n\nexport type StatusType = (typeof StatusType)[keyof typeof StatusType]\n"
  },
  {
    "path": "packages/logs/src/domain/logger/loggerCollection.spec.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport { ConsoleApiName, timeStampNow, ErrorSource, originalConsoleMethods } from '@datadog/browser-core'\nimport { mockClock } from '@datadog/browser-core/test'\nimport type { CommonContext, RawLoggerLogsEvent } from '../../rawLogsEvent.types'\nimport type { RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { HandlerType, Logger } from '../logger'\nimport { StatusType } from './isAuthorized'\nimport { startLoggerCollection } from './loggerCollection'\n\nconst HANDLING_STACK = 'handlingStack'\nconst COMMON_CONTEXT = {} as CommonContext\nconst FAKE_DATE = 1234 as TimeStamp\n\ndescribe('logger collection', () => {\n  let lifeCycle: LifeCycle\n  let handleLog: ReturnType<typeof startLoggerCollection>['handleLog']\n  let logger: Logger\n  let rawLogsEvents: Array<RawLogsEventCollectedData<RawLoggerLogsEvent>>\n\n  beforeEach(() => {\n    rawLogsEvents = []\n    lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.RAW_LOG_COLLECTED, (rawLogsEvent) =>\n      rawLogsEvents.push(rawLogsEvent as RawLogsEventCollectedData<RawLoggerLogsEvent>)\n    )\n    spyOn(console, 'error').and.callFake(() => true)\n    logger = new Logger((...params) => handleLog(...params))\n    ;({ handleLog: handleLog } = startLoggerCollection(lifeCycle))\n    mockClock()\n  })\n\n  describe('when handle type is set to \"console\"', () => {\n    beforeEach(() => {\n      logger.setHandler(HandlerType.console)\n      spyOn(originalConsoleMethods, 'debug')\n      spyOn(originalConsoleMethods, 'info')\n      spyOn(originalConsoleMethods, 'warn')\n      spyOn(originalConsoleMethods, 'error')\n      spyOn(originalConsoleMethods, 'log')\n    })\n\n    it('should print the log message and context to the console', () => {\n      logger.setContext({ foo: 'from-logger', bar: 'from-logger' })\n\n      handleLog(\n        { message: 'message', status: StatusType.error, context: { bar: 'from-message' } },\n        logger,\n        HANDLING_STACK,\n        COMMON_CONTEXT\n      )\n\n      expect(originalConsoleMethods.error).toHaveBeenCalledOnceWith('message', {\n        foo: 'from-logger',\n        bar: 'from-message',\n      })\n    })\n\n    for (const { status, api } of [\n      { status: StatusType.ok, api: ConsoleApiName.debug },\n      { status: StatusType.debug, api: ConsoleApiName.debug },\n      { status: StatusType.info, api: ConsoleApiName.info },\n      { status: StatusType.notice, api: ConsoleApiName.info },\n      { status: StatusType.warn, api: ConsoleApiName.warn },\n      { status: StatusType.error, api: ConsoleApiName.error },\n      { status: StatusType.critical, api: ConsoleApiName.error },\n      { status: StatusType.alert, api: ConsoleApiName.error },\n      { status: StatusType.emerg, api: ConsoleApiName.error },\n    ]) {\n      it(`should use console.${api} to log messages with status ${status}`, () => {\n        logger.setLevel(StatusType.ok)\n        handleLog({ message: 'message', status }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n        expect(originalConsoleMethods[api]).toHaveBeenCalled()\n      })\n    }\n\n    it('does not print the log if its status is below the logger level', () => {\n      logger.setLevel(StatusType.warn)\n      handleLog({ message: 'message', status: StatusType.info }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n      expect(originalConsoleMethods.info).not.toHaveBeenCalled()\n    })\n\n    it('does not print the log and does not crash if its status is unknown', () => {\n      handleLog({ message: 'message', status: 'unknown' as StatusType }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n      expect(originalConsoleMethods.info).not.toHaveBeenCalled()\n      expect(originalConsoleMethods.log).not.toHaveBeenCalled()\n      expect(originalConsoleMethods.error).not.toHaveBeenCalled()\n      expect(originalConsoleMethods.warn).not.toHaveBeenCalled()\n      expect(originalConsoleMethods.debug).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('when handle type is set to \"http\"', () => {\n    beforeEach(() => {\n      logger.setHandler(HandlerType.http)\n    })\n\n    it('should send the log message and context', () => {\n      logger.setContext({ foo: 'from-logger', bar: 'from-logger' })\n\n      handleLog(\n        { message: 'message', status: StatusType.error, context: { bar: 'from-message' } },\n        logger,\n        HANDLING_STACK,\n        COMMON_CONTEXT\n      )\n\n      expect(rawLogsEvents[0]).toEqual({\n        rawLogsEvent: {\n          date: timeStampNow(),\n          origin: ErrorSource.LOGGER,\n          message: 'message',\n          status: StatusType.error,\n        },\n        messageContext: {\n          foo: 'from-logger',\n          bar: 'from-message',\n        },\n        savedCommonContext: COMMON_CONTEXT,\n        domainContext: {\n          handlingStack: HANDLING_STACK,\n        },\n        ddtags: [],\n      })\n    })\n\n    it('should send the saved date when present', () => {\n      handleLog({ message: 'message', status: StatusType.error }, logger, HANDLING_STACK, COMMON_CONTEXT, FAKE_DATE)\n\n      expect(rawLogsEvents[0].rawLogsEvent.date).toEqual(FAKE_DATE)\n    })\n\n    it('does not send the log if its status is below the logger level', () => {\n      logger.setLevel(StatusType.warn)\n      handleLog({ message: 'message', status: StatusType.info }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n      expect(rawLogsEvents.length).toBe(0)\n    })\n\n    it('does not send the log and does not crash if its status is unknown', () => {\n      handleLog({ message: 'message', status: 'unknown' as StatusType }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n      expect(rawLogsEvents.length).toBe(0)\n    })\n  })\n\n  describe('ddtags', () => {\n    beforeEach(() => {\n      logger.setHandler(HandlerType.http)\n    })\n\n    it('should contain the ddtags of the logger', () => {\n      logger.addTag('tag1', 'value1')\n      handleLog({ message: 'message', status: StatusType.error }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n      expect(rawLogsEvents[0].ddtags).toEqual(['tag1:value1'])\n    })\n\n    it('should ignore the tags of the message context', () => {\n      handleLog(\n        { message: 'message', status: StatusType.error, context: { ddtags: ['tag3:value3'] } },\n        logger,\n        HANDLING_STACK,\n        COMMON_CONTEXT\n      )\n\n      expect(rawLogsEvents[0].ddtags).toEqual([])\n    })\n\n    it('should ignore the tags of the logger context', () => {\n      logger.setContext({ ddtags: ['tag1:value1'] })\n      handleLog({ message: 'message', status: StatusType.error }, logger, HANDLING_STACK, COMMON_CONTEXT)\n\n      expect(rawLogsEvents[0].ddtags).toEqual([])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/logger/loggerCollection.ts",
    "content": "import type { Context, TimeStamp } from '@datadog/browser-core'\nimport {\n  combine,\n  ErrorSource,\n  timeStampNow,\n  originalConsoleMethods,\n  globalConsole,\n  ConsoleApiName,\n} from '@datadog/browser-core'\nimport type { CommonContext, RawLogsEvent } from '../../rawLogsEvent.types'\nimport type { LifeCycle, RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { Logger, LogsMessage } from '../logger'\nimport { HandlerType } from '../logger'\nimport { isAuthorized, StatusType } from './isAuthorized'\n\nexport function startLoggerCollection(lifeCycle: LifeCycle) {\n  function handleLog(\n    logsMessage: LogsMessage,\n    logger: Logger,\n    handlingStack?: string,\n    savedCommonContext?: CommonContext,\n    savedDate?: TimeStamp\n  ) {\n    const messageContext = combine(logger.getContext(), logsMessage.context)\n\n    if (isAuthorized(logsMessage.status, HandlerType.console, logger)) {\n      displayInConsole(logsMessage, messageContext)\n    }\n\n    if (isAuthorized(logsMessage.status, HandlerType.http, logger)) {\n      const rawLogEventData: RawLogsEventCollectedData<RawLogsEvent> = {\n        rawLogsEvent: {\n          date: savedDate || timeStampNow(),\n          message: logsMessage.message,\n          status: logsMessage.status,\n          origin: ErrorSource.LOGGER,\n        },\n        messageContext,\n        savedCommonContext,\n        ddtags: logger.getTags(),\n      }\n\n      if (handlingStack) {\n        rawLogEventData.domainContext = { handlingStack }\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, rawLogEventData)\n    }\n  }\n\n  return {\n    handleLog,\n  }\n}\nconst loggerToConsoleApiName: { [key in StatusType]: ConsoleApiName } = {\n  [StatusType.ok]: ConsoleApiName.debug,\n  [StatusType.debug]: ConsoleApiName.debug,\n  [StatusType.info]: ConsoleApiName.info,\n  [StatusType.notice]: ConsoleApiName.info,\n  [StatusType.warn]: ConsoleApiName.warn,\n  [StatusType.error]: ConsoleApiName.error,\n  [StatusType.critical]: ConsoleApiName.error,\n  [StatusType.alert]: ConsoleApiName.error,\n  [StatusType.emerg]: ConsoleApiName.error,\n}\n\nfunction displayInConsole({ status, message }: LogsMessage, messageContext: Context | undefined) {\n  originalConsoleMethods[loggerToConsoleApiName[status]].call(globalConsole, message, messageContext)\n}\n"
  },
  {
    "path": "packages/logs/src/domain/logger.spec.ts",
    "content": "import type { ErrorWithCause } from '@datadog/browser-core'\nimport {\n  display,\n  ErrorHandling,\n  NO_ERROR_STACK_PRESENT_MESSAGE,\n  supportUnicodePropertyEscapes,\n} from '@datadog/browser-core'\nimport type { LogsMessage } from './logger'\nimport { HandlerType, Logger, STATUSES } from './logger'\nimport { StatusType } from './logger/isAuthorized'\n\ndescribe('Logger', () => {\n  let logger: Logger\n  let handleLogSpy: jasmine.Spy<(message: LogsMessage, logger: Logger, handlingStack?: string) => void>\n\n  function getLoggedMessage(index: number) {\n    return handleLogSpy.calls.argsFor(index)[0]\n  }\n\n  function getMessageLogger(index: number) {\n    return handleLogSpy.calls.argsFor(index)[1]\n  }\n\n  function getLoggedHandlingStack(index: number) {\n    return handleLogSpy.calls.argsFor(index)[2]\n  }\n\n  beforeEach(() => {\n    handleLogSpy = jasmine.createSpy()\n    logger = new Logger(handleLogSpy)\n  })\n\n  describe('log methods', () => {\n    beforeEach(() => {\n      logger.setLevel(StatusType.ok)\n    })\n\n    it(\"'logger.log' should have info status by default\", () => {\n      logger.log('message')\n\n      expect(getLoggedMessage(0).status).toEqual(StatusType.info)\n    })\n\n    STATUSES.forEach((status) => {\n      it(`'logger.${status}' should have ${status} status`, () => {\n        logger[status]('message')\n        expect(getLoggedMessage(0).status).toEqual(status)\n      })\n\n      it(`'logger.${status}' should populate an error context when an Error object is provided`, () => {\n        logger[status]('message', {}, SyntaxError('My Error'))\n\n        expect(getLoggedMessage(0).context).toEqual({\n          error: {\n            kind: 'SyntaxError',\n            message: 'My Error',\n            stack: jasmine.stringMatching(/^SyntaxError: My Error/),\n            causes: undefined,\n            handling: ErrorHandling.HANDLED,\n            fingerprint: undefined,\n          },\n        })\n      })\n\n      it(`'logger.${status}' should create an handling stack`, () => {\n        logger[status]('message')\n\n        expect(getLoggedHandlingStack(0)).toBeDefined()\n      })\n\n      it(`'logger.${status}' should not create an handling stack if the handler is 'console'`, () => {\n        logger.setHandler(HandlerType.console)\n        logger[status]('message')\n\n        expect(getLoggedHandlingStack(0)).not.toBeDefined()\n      })\n\n      it(`'logger.${status}' should not create an handling stack if the handler is 'silent'`, () => {\n        logger.setHandler(HandlerType.silent)\n        logger[status]('message')\n\n        expect(getLoggedHandlingStack(0)).not.toBeDefined()\n      })\n    })\n\n    it('should not create an handling stack if level is below the logger level', () => {\n      logger.setLevel(StatusType.warn)\n      logger.log('message')\n      logger.warn('message')\n\n      expect(getLoggedHandlingStack(0)).not.toBeDefined()\n      expect(getLoggedHandlingStack(1)).toBeDefined()\n    })\n\n    it(\"'logger.log' should send the log message\", () => {\n      logger.log('message', { foo: 'bar' }, StatusType.info)\n\n      expect(getLoggedMessage(0)).toEqual({\n        message: 'message',\n        context: { foo: 'bar' },\n        status: StatusType.info,\n      })\n    })\n\n    it(\"'logger.log' should send the logger\", () => {\n      logger.log('message')\n\n      expect(getMessageLogger(0)).toBe(logger)\n    })\n\n    it(\"'logger.log' should serialize error parameter value when type is not Error\", () => {\n      logger.log('message', {}, StatusType.error, 'My Error' as any)\n\n      expect(getLoggedMessage(0)).toEqual({\n        message: 'message',\n        context: {\n          error: {\n            message: 'Provided \"My Error\"',\n            stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n            kind: undefined,\n            causes: undefined,\n            handling: ErrorHandling.HANDLED,\n            fingerprint: undefined,\n          },\n        },\n        status: 'error',\n      })\n    })\n\n    it('uses the error dd_context property as context', () => {\n      const error = new TypeError('My Error')\n      ;(error as any).dd_context = { foo: 'bar' }\n      logger.log('message', {}, StatusType.error, error)\n\n      expect(getLoggedMessage(0).context!.foo).toBe('bar')\n    })\n\n    describe('when using logger.error', () => {\n      it(\"'logger.error' should have an empty context if no Error object is provided\", () => {\n        logger.error('message')\n\n        expect(getLoggedMessage(0)).toEqual({\n          message: 'message',\n          status: 'error',\n          context: undefined,\n        })\n      })\n\n      it('should include causes when provided with an error', () => {\n        const error = new Error('High level error') as ErrorWithCause\n        error.stack = 'Error: High level error'\n\n        const nestedError = new Error('Mid level error') as ErrorWithCause\n        nestedError.stack = 'Error: Mid level error'\n\n        const deepNestedError = new TypeError('Low level error') as ErrorWithCause\n        deepNestedError.stack = 'TypeError: Low level error'\n\n        nestedError.cause = deepNestedError\n        error.cause = nestedError\n\n        logger.log('Logging message', {}, StatusType.error, error)\n\n        expect(getLoggedMessage(0)).toEqual({\n          message: 'Logging message',\n          status: 'error',\n          context: {\n            error: {\n              stack: 'Error: High level error',\n              kind: 'Error',\n              message: 'High level error',\n              handling: ErrorHandling.HANDLED,\n              causes: [\n                {\n                  message: 'Mid level error',\n                  source: 'logger',\n                  type: 'Error',\n                  stack: 'Error: Mid level error',\n                },\n                {\n                  message: 'Low level error',\n                  source: 'logger',\n                  type: 'TypeError',\n                  stack: 'TypeError: Low level error',\n                },\n              ],\n              fingerprint: undefined,\n            },\n          },\n        })\n      })\n    })\n  })\n\n  describe('tags', () => {\n    let displaySpy: jasmine.Spy<typeof display.warn>\n    function expectWarning() {\n      if (supportUnicodePropertyEscapes()) {\n        expect(displaySpy).toHaveBeenCalledOnceWith(\n          jasmine.stringMatching(\"Tag .* doesn't meet tag requirements and will be sanitized\")\n        )\n      }\n    }\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'warn')\n    })\n\n    it('should add a key:value tag', () => {\n      logger.addTag('foo', 'bar')\n      expect(logger.getTags()).toEqual(['foo:bar'])\n    })\n\n    it('should add a key only tag', () => {\n      logger.addTag('foo')\n      expect(logger.getTags()).toEqual(['foo'])\n    })\n\n    it('should sanitize a key with a comma', () => {\n      logger.addTag('foo,bar', 'baz')\n      expect(logger.getTags()).toEqual(['foo_bar:baz'])\n      expectWarning()\n    })\n\n    it('should sanitize a tag with a comma in the value', () => {\n      logger.addTag('foo', 'baz,qux')\n      expect(logger.getTags()).toEqual(['foo:baz_qux'])\n      expectWarning()\n    })\n\n    it('should remove tags with key', () => {\n      logger.addTag('foo', 'bar')\n      logger.addTag('foo', 'baz')\n      logger.removeTagsWithKey('foo')\n      expect(logger.getTags()).toEqual([])\n    })\n\n    it('should remove key only tags', () => {\n      logger.addTag('foo')\n      logger.removeTagsWithKey('foo')\n      expect(logger.getTags()).toEqual([])\n    })\n\n    it('should remove tag keys that were sanitized', () => {\n      logger.addTag('foo,bar', 'baz')\n      logger.removeTagsWithKey('foo,bar')\n      expect(logger.getTags()).toEqual([])\n      expectWarning()\n    })\n\n    it('should not remove tags starting with the key', () => {\n      logger.addTag('foo', 'bar')\n      logger.addTag('foo-bar', 'baz')\n      logger.removeTagsWithKey('foo')\n      expect(logger.getTags()).toEqual(['foo-bar:baz'])\n    })\n\n    it('should not be able to edit tags in place', () => {\n      const tags = logger.getTags()\n      tags.push('foo-bar:baz')\n      expect(logger.getTags()).toEqual([])\n    })\n  })\n\n  describe('context methods', () => {\n    beforeEach(() => {\n      const loggerContext = { foo: 'bar' }\n      logger = new Logger(handleLogSpy, undefined, HandlerType.http, StatusType.debug, loggerContext)\n    })\n\n    it('getContext should return the context', () => {\n      expect(logger.getContext()).toEqual({ foo: 'bar' })\n    })\n\n    it('setContext should overwrite the whole context', () => {\n      logger.setContext({ qux: 'qix' })\n      expect(logger.getContext()).toEqual({ qux: 'qix' })\n    })\n\n    it('setContextProperty should set a context value', () => {\n      logger.setContextProperty('qux', 'qix')\n      expect(logger.getContext()).toEqual({ foo: 'bar', qux: 'qix' })\n    })\n\n    it('removeContextProperty should remove a context value', () => {\n      logger.removeContextProperty('foo')\n      expect(logger.getContext()).toEqual({})\n    })\n\n    it('clearContext should clear the context', () => {\n      logger.clearContext()\n      expect(logger.getContext()).toEqual({})\n    })\n  })\n\n  describe('contexts', () => {\n    it('logger context should be deep copied', () => {\n      const loggerContext = { foo: 'bar' }\n      logger = new Logger(handleLogSpy, undefined, HandlerType.http, StatusType.debug, loggerContext)\n      loggerContext.foo = 'baz'\n\n      expect(logger.getContext()).toEqual({ foo: 'bar' })\n    })\n\n    it('message context should be deep copied', () => {\n      const messageContext = { foo: 'bar' }\n      logger.log('message', messageContext)\n      messageContext.foo = 'baz'\n\n      expect(getLoggedMessage(0).context).toEqual({ foo: 'bar' })\n    })\n  })\n\n  describe('level', () => {\n    it('should be debug by default', () => {\n      expect(logger.getLevel()).toEqual(StatusType.debug)\n    })\n\n    it('should be configurable', () => {\n      logger.setLevel(StatusType.info)\n\n      expect(logger.getLevel()).toEqual(StatusType.info)\n    })\n  })\n\n  describe('error handling in logImplementation', () => {\n    it('should compute stackTrace when error is an instance of Error', () => {\n      const error = new Error('Test error')\n      logger.log('Test message', undefined, StatusType.error, error)\n\n      const loggedError = getLoggedMessage(0).context?.error\n\n      expect(loggedError).toEqual({\n        message: 'Test error',\n        stack: jasmine.stringMatching(/^Error: Test error/),\n        kind: 'Error',\n        causes: undefined,\n        handling: ErrorHandling.HANDLED,\n        fingerprint: undefined,\n      })\n    })\n\n    it('should not compute stackTrace when error is not an instance of Error', () => {\n      const nonErrorObject = { message: 'Not an Error instance', stack: 'Fake stack trace' }\n      logger.log('Test message', undefined, StatusType.error, nonErrorObject as any)\n\n      const loggedError = getLoggedMessage(0).context?.error\n\n      expect(loggedError).toEqual({\n        message: 'Provided {\"message\":\"Not an Error instance\",\"stack\":\"Fake stack trace\"}',\n        stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n        kind: undefined,\n        causes: undefined,\n        handling: ErrorHandling.HANDLED,\n        fingerprint: undefined,\n      })\n    })\n\n    it('should not include error context when error is undefined', () => {\n      logger.log('Test message', undefined, StatusType.error, undefined)\n\n      const loggedMessage = getLoggedMessage(0)\n      expect(loggedMessage.context).toBeUndefined()\n    })\n  })\n\n  describe('handler type', () => {\n    it('should be \"http\" by default', () => {\n      logger.debug('message')\n\n      expect(logger.getHandler()).toEqual(HandlerType.http)\n    })\n\n    it('should be configurable to \"console\"', () => {\n      logger.setHandler(HandlerType.console)\n\n      expect(logger.getHandler()).toEqual(HandlerType.console)\n    })\n\n    it('should be configurable to \"silent\"', () => {\n      logger.setHandler(HandlerType.silent)\n\n      expect(logger.getHandler()).toEqual(HandlerType.silent)\n    })\n\n    it('should be configurable with multiple handlers', () => {\n      logger.setHandler([HandlerType.console, HandlerType.http])\n\n      expect(logger.getHandler()).toEqual([HandlerType.console, HandlerType.http])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/logger.ts",
    "content": "import type { Context, ContextManager } from '@datadog/browser-core'\nimport {\n  clocksNow,\n  computeRawError,\n  ErrorHandling,\n  combine,\n  createContextManager,\n  ErrorSource,\n  monitored,\n  sanitize,\n  NonErrorPrefix,\n  createHandlingStack,\n  buildTag,\n  sanitizeTag,\n} from '@datadog/browser-core'\n\nimport { isAuthorized, StatusType } from './logger/isAuthorized'\nimport { createErrorFieldFromRawError } from './createErrorFieldFromRawError'\n\nexport interface LogsMessage {\n  message: string\n  status: StatusType\n  context?: Context\n}\n\nexport const HandlerType = {\n  console: 'console',\n  http: 'http',\n  silent: 'silent',\n} as const\n\nexport type HandlerType = (typeof HandlerType)[keyof typeof HandlerType]\nexport const STATUSES = Object.keys(StatusType) as StatusType[]\n\n// note: it is safe to merge declarations as long as the methods are actually defined on the prototype\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging, no-restricted-syntax\nexport class Logger {\n  private contextManager: ContextManager\n\n  // Tags are formatted as either `key:value` or `key_only`\n  private tags: string[]\n\n  constructor(\n    private handleLogStrategy: (logsMessage: LogsMessage, logger: Logger, handlingStack?: string) => void,\n    name?: string,\n    private handlerType: HandlerType | HandlerType[] = HandlerType.http,\n    private level: StatusType = StatusType.debug,\n    loggerContext: object = {}\n  ) {\n    this.contextManager = createContextManager('logger')\n    this.tags = []\n    this.contextManager.setContext(loggerContext as Context)\n    if (name) {\n      this.contextManager.setContextProperty('logger', { name })\n    }\n  }\n\n  @monitored\n  logImplementation(\n    message: string,\n    messageContext?: object,\n    status: StatusType = StatusType.info,\n    error?: Error,\n    handlingStack?: string\n  ) {\n    const sanitizedMessageContext = sanitize(messageContext) as Context\n    let context: Context\n\n    if (error !== undefined && error !== null) {\n      const rawError = computeRawError({\n        originalError: error,\n        nonErrorPrefix: NonErrorPrefix.PROVIDED,\n        source: ErrorSource.LOGGER,\n        handling: ErrorHandling.HANDLED,\n        startClocks: clocksNow(),\n      })\n\n      context = combine(\n        {\n          error: createErrorFieldFromRawError(rawError, { includeMessage: true }),\n        },\n        rawError.context,\n        sanitizedMessageContext\n      )\n    } else {\n      context = sanitizedMessageContext\n    }\n\n    this.handleLogStrategy(\n      {\n        message: sanitize(message)!,\n        context,\n        status,\n      },\n      this,\n      handlingStack\n    )\n  }\n\n  log(message: string, messageContext?: object, status: StatusType = StatusType.info, error?: Error) {\n    let handlingStack: string | undefined\n\n    if (isAuthorized(status, HandlerType.http, this)) {\n      handlingStack = createHandlingStack('log')\n    }\n\n    this.logImplementation(message, messageContext, status, error, handlingStack)\n  }\n\n  setContext(context: object) {\n    this.contextManager.setContext(context as Context)\n  }\n\n  getContext() {\n    return this.contextManager.getContext()\n  }\n\n  setContextProperty(key: string, value: any) {\n    this.contextManager.setContextProperty(key, value)\n  }\n\n  removeContextProperty(key: string) {\n    this.contextManager.removeContextProperty(key)\n  }\n\n  clearContext() {\n    this.contextManager.clearContext()\n  }\n\n  addTag(key: string, value?: string) {\n    this.tags.push(buildTag(key, value))\n  }\n\n  removeTagsWithKey(key: string) {\n    const sanitizedKey = sanitizeTag(key)\n\n    this.tags = this.tags.filter((tag) => tag !== sanitizedKey && !tag.startsWith(`${sanitizedKey}:`))\n  }\n\n  getTags() {\n    return this.tags.slice()\n  }\n\n  setHandler(handler: HandlerType | HandlerType[]) {\n    this.handlerType = handler\n  }\n\n  getHandler() {\n    return this.handlerType\n  }\n\n  setLevel(level: StatusType) {\n    this.level = level\n  }\n\n  getLevel() {\n    return this.level\n  }\n}\n\n/* eslint-disable local-rules/disallow-side-effects */\nLogger.prototype.ok = createLoggerMethod(StatusType.ok)\nLogger.prototype.debug = createLoggerMethod(StatusType.debug)\nLogger.prototype.info = createLoggerMethod(StatusType.info)\nLogger.prototype.notice = createLoggerMethod(StatusType.notice)\nLogger.prototype.warn = createLoggerMethod(StatusType.warn)\nLogger.prototype.error = createLoggerMethod(StatusType.error)\nLogger.prototype.critical = createLoggerMethod(StatusType.critical)\nLogger.prototype.alert = createLoggerMethod(StatusType.alert)\nLogger.prototype.emerg = createLoggerMethod(StatusType.emerg)\n/* eslint-enable local-rules/disallow-side-effects */\n\n// note: it is safe to merge declarations as long as the methods are actually defined on the prototype\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nexport interface Logger {\n  ok(message: string, messageContext?: object, error?: Error): void\n  debug(message: string, messageContext?: object, error?: Error): void\n  info(message: string, messageContext?: object, error?: Error): void\n  notice(message: string, messageContext?: object, error?: Error): void\n  warn(message: string, messageContext?: object, error?: Error): void\n  error(message: string, messageContext?: object, error?: Error): void\n  critical(message: string, messageContext?: object, error?: Error): void\n  alert(message: string, messageContext?: object, error?: Error): void\n  emerg(message: string, messageContext?: object, error?: Error): void\n}\n\nfunction createLoggerMethod(status: StatusType) {\n  return function (this: Logger, message: string, messageContext?: object, error?: Error) {\n    let handlingStack: string | undefined\n\n    if (isAuthorized(status, HandlerType.http, this)) {\n      handlingStack = createHandlingStack('log')\n    }\n\n    this.logImplementation(message, messageContext, status, error, handlingStack)\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/logsSessionManager.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport {\n  STORAGE_POLL_DELAY,\n  SESSION_STORE_KEY,\n  setCookie,\n  stopSessionManager,\n  ONE_SECOND,\n  DOM_EVENT,\n  relativeNow,\n  createTrackingConsentState,\n  TrackingConsent,\n  SessionPersistence,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { createNewEvent, expireCookie, getSessionState, mockClock } from '@datadog/browser-core/test'\n\nimport type { LogsConfiguration } from './configuration'\nimport {\n  LOGS_SESSION_KEY,\n  LoggerTrackingType,\n  startLogsSessionManager,\n  startLogsSessionManagerStub,\n} from './logsSessionManager'\n\ndescribe('logs session manager', () => {\n  const DURATION = 123456\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  afterEach(() => {\n    // remove intervals first\n    stopSessionManager()\n    // flush pending callbacks to avoid random failures\n    clock.tick(new Date().getTime())\n  })\n\n  it('when tracked should store tracking type and session id', () => {\n    startLogsSessionManagerWithDefaults()\n\n    expect(getSessionState(SESSION_STORE_KEY).id).toMatch(/[a-f0-9-]+/)\n    expect(getSessionState(SESSION_STORE_KEY)[LOGS_SESSION_KEY]).toBe(LoggerTrackingType.TRACKED)\n  })\n\n  it('when not tracked should store tracking type', () => {\n    startLogsSessionManagerWithDefaults({ configuration: { sessionSampleRate: 0 } })\n\n    expect(getSessionState(SESSION_STORE_KEY)[LOGS_SESSION_KEY]).toBe(LoggerTrackingType.NOT_TRACKED)\n    expect(getSessionState(SESSION_STORE_KEY).isExpired).toBeUndefined()\n  })\n\n  it('when tracked should keep existing tracking type and session id', () => {\n    setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION)\n\n    startLogsSessionManagerWithDefaults()\n\n    expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcdef')\n    expect(getSessionState(SESSION_STORE_KEY)[LOGS_SESSION_KEY]).toBe(LoggerTrackingType.TRACKED)\n  })\n\n  it('when not tracked should keep existing tracking type', () => {\n    setCookie(SESSION_STORE_KEY, 'logs=0', DURATION)\n\n    startLogsSessionManagerWithDefaults()\n\n    expect(getSessionState(SESSION_STORE_KEY)[LOGS_SESSION_KEY]).toBe(LoggerTrackingType.NOT_TRACKED)\n  })\n\n  it('should renew on activity after expiration', () => {\n    startLogsSessionManagerWithDefaults()\n\n    expireCookie()\n    expect(getSessionState(SESSION_STORE_KEY).isExpired).toBe('1')\n    clock.tick(STORAGE_POLL_DELAY)\n\n    document.body.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n    expect(getSessionState(SESSION_STORE_KEY).id).toMatch(/[a-f0-9-]+/)\n    expect(getSessionState(SESSION_STORE_KEY)[LOGS_SESSION_KEY]).toBe(LoggerTrackingType.TRACKED)\n  })\n\n  describe('findTrackedSession', () => {\n    it('should return the current active session', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION)\n      const logsSessionManager = startLogsSessionManagerWithDefaults()\n      expect(logsSessionManager.findTrackedSession()!.id).toBe('abcdef')\n    })\n\n    it('should return undefined if the session is not tracked', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=0', DURATION)\n      const logsSessionManager = startLogsSessionManagerWithDefaults()\n      expect(logsSessionManager.findTrackedSession()).toBeUndefined()\n    })\n\n    it('should not return the current session if it has expired by default', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&logs=1', DURATION)\n      const logsSessionManager = startLogsSessionManagerWithDefaults()\n      clock.tick(10 * ONE_SECOND)\n      expireCookie()\n      clock.tick(STORAGE_POLL_DELAY)\n      expect(logsSessionManager.findTrackedSession()).toBeUndefined()\n    })\n\n    it('should return the current session if it has expired when returnExpired = true', () => {\n      const logsSessionManager = startLogsSessionManagerWithDefaults()\n      expireCookie()\n      clock.tick(STORAGE_POLL_DELAY)\n      expect(logsSessionManager.findTrackedSession(relativeNow(), { returnInactive: true })).toBeDefined()\n    })\n\n    it('should return session corresponding to start time', () => {\n      setCookie(SESSION_STORE_KEY, 'id=foo&logs=1', DURATION)\n      const logsSessionManager = startLogsSessionManagerWithDefaults()\n      clock.tick(10 * ONE_SECOND)\n      setCookie(SESSION_STORE_KEY, 'id=bar&logs=1', DURATION)\n      // simulate a click to renew the session\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n      clock.tick(STORAGE_POLL_DELAY)\n      expect(logsSessionManager.findTrackedSession(0 as RelativeTime)!.id).toEqual('foo')\n      expect(logsSessionManager.findTrackedSession()!.id).toEqual('bar')\n    })\n  })\n\n  function startLogsSessionManagerWithDefaults({ configuration }: { configuration?: Partial<LogsConfiguration> } = {}) {\n    return startLogsSessionManager(\n      {\n        sessionSampleRate: 100,\n        sessionStoreStrategyType: { type: SessionPersistence.COOKIE, cookieOptions: {} },\n        ...configuration,\n      } as LogsConfiguration,\n      createTrackingConsentState(TrackingConsent.GRANTED)\n    )\n  }\n})\n\ndescribe('logger session stub', () => {\n  it('isTracked is computed at each init and getId is always undefined', () => {\n    const firstLogsSessionManager = startLogsSessionManagerStub({ sessionSampleRate: 100 } as LogsConfiguration)\n    expect(firstLogsSessionManager.findTrackedSession()).toBeDefined()\n    expect(firstLogsSessionManager.findTrackedSession()!.id).toBeUndefined()\n\n    const secondLogsSessionManager = startLogsSessionManagerStub({ sessionSampleRate: 0 } as LogsConfiguration)\n    expect(secondLogsSessionManager.findTrackedSession()).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/logsSessionManager.ts",
    "content": "import type { RelativeTime, TrackingConsentState } from '@datadog/browser-core'\nimport { Observable, performDraw, SESSION_NOT_TRACKED, startSessionManager } from '@datadog/browser-core'\nimport type { LogsConfiguration } from './configuration'\n\nexport const LOGS_SESSION_KEY = 'logs'\n\nexport interface LogsSessionManager {\n  findTrackedSession: (startTime?: RelativeTime, options?: { returnInactive: boolean }) => LogsSession | undefined\n  expireObservable: Observable<void>\n}\n\nexport interface LogsSession {\n  id?: string // session can be tracked without id\n  anonymousId?: string // device id lasts across session\n}\n\nexport const enum LoggerTrackingType {\n  NOT_TRACKED = SESSION_NOT_TRACKED,\n  TRACKED = '1',\n}\n\nexport function startLogsSessionManager(\n  configuration: LogsConfiguration,\n  trackingConsentState: TrackingConsentState\n): LogsSessionManager {\n  const sessionManager = startSessionManager(\n    configuration,\n    LOGS_SESSION_KEY,\n    (rawTrackingType) => computeTrackingType(configuration, rawTrackingType),\n    trackingConsentState\n  )\n  return {\n    findTrackedSession: (startTime?: RelativeTime, options = { returnInactive: false }) => {\n      const session = sessionManager.findSession(startTime, options)\n      return session && session.trackingType === LoggerTrackingType.TRACKED\n        ? {\n            id: session.id,\n            anonymousId: session.anonymousId,\n          }\n        : undefined\n    },\n    expireObservable: sessionManager.expireObservable,\n  }\n}\n\nexport function startLogsSessionManagerStub(configuration: LogsConfiguration): LogsSessionManager {\n  const isTracked = computeTrackingType(configuration) === LoggerTrackingType.TRACKED\n  const session = isTracked ? {} : undefined\n  return {\n    findTrackedSession: () => session,\n    expireObservable: new Observable(),\n  }\n}\n\nfunction computeTrackingType(configuration: LogsConfiguration, rawTrackingType?: string) {\n  if (hasValidLoggerSession(rawTrackingType)) {\n    return rawTrackingType\n  }\n  if (!performDraw(configuration.sessionSampleRate)) {\n    return LoggerTrackingType.NOT_TRACKED\n  }\n  return LoggerTrackingType.TRACKED\n}\n\nfunction hasValidLoggerSession(trackingType?: string): trackingType is LoggerTrackingType {\n  return trackingType === LoggerTrackingType.NOT_TRACKED || trackingType === LoggerTrackingType.TRACKED\n}\n"
  },
  {
    "path": "packages/logs/src/domain/networkError/networkErrorCollection.spec.ts",
    "content": "import { ErrorSource } from '@datadog/browser-core'\nimport type { MockFetch, MockFetchManager } from '@datadog/browser-core/test'\nimport { SPEC_ENDPOINTS, mockFetch, registerCleanupTask } from '@datadog/browser-core/test'\nimport type { RawNetworkLogsEvent } from '../../rawLogsEvent.types'\nimport type { LogsConfiguration } from '../configuration'\nimport type { RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { StatusType } from '../logger/isAuthorized'\n\nimport { startNetworkErrorCollection } from './networkErrorCollection'\n\nconst CONFIGURATION = {\n  requestErrorResponseLengthLimit: 64,\n  ...SPEC_ENDPOINTS,\n} as LogsConfiguration\n\ndescribe('network error collection', () => {\n  let fetch: MockFetch\n  let mockFetchManager: MockFetchManager\n  let lifeCycle: LifeCycle\n  let rawLogsEvents: Array<RawLogsEventCollectedData<RawNetworkLogsEvent>>\n  const FAKE_URL = 'http://fake.com/'\n  const DEFAULT_REQUEST = {\n    duration: 10,\n    method: 'GET',\n    responseText: 'Server error',\n    startTime: 0,\n    status: 503,\n    url: FAKE_URL,\n  }\n\n  function startCollection(forwardErrorsToLogs = true) {\n    mockFetchManager = mockFetch()\n    const { stop } = startNetworkErrorCollection({ ...CONFIGURATION, forwardErrorsToLogs }, lifeCycle)\n    registerCleanupTask(() => {\n      stop()\n    })\n    fetch = window.fetch as MockFetch\n  }\n\n  beforeEach(() => {\n    rawLogsEvents = []\n    lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.RAW_LOG_COLLECTED, (rawLogsEvent) =>\n      rawLogsEvents.push(rawLogsEvent as RawLogsEventCollectedData<RawNetworkLogsEvent>)\n    )\n  })\n\n  it('should track server error', (done) => {\n    startCollection()\n    fetch(FAKE_URL).resolveWith(DEFAULT_REQUEST)\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents[0].rawLogsEvent).toEqual({\n        message: 'Fetch error GET http://fake.com/',\n        date: jasmine.any(Number),\n        status: StatusType.error,\n        origin: ErrorSource.NETWORK,\n        error: {\n          stack: 'Server error',\n          handling: undefined,\n        },\n        http: {\n          method: 'GET',\n          status_code: 503,\n          url: 'http://fake.com/',\n        },\n      })\n      done()\n    })\n  })\n\n  it('should not track network error when forwardErrorsToLogs is false', (done) => {\n    startCollection(false)\n    fetch(FAKE_URL).resolveWith(DEFAULT_REQUEST)\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(0)\n      done()\n    })\n  })\n\n  it('should not track intake error', (done) => {\n    startCollection()\n    fetch(\n      'https://logs-intake.com/v1/input/send?ddsource=browser&dd-api-key=xxxx&dd-request-id=1234567890'\n    ).resolveWith(DEFAULT_REQUEST)\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(0)\n      done()\n    })\n  })\n\n  it('should track aborted requests', (done) => {\n    startCollection()\n    fetch(FAKE_URL).abort()\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(1)\n      expect(rawLogsEvents[0].domainContext).toEqual({\n        isAborted: true,\n        handlingStack: jasmine.any(String),\n      })\n      done()\n    })\n  })\n\n  it('should track refused request', (done) => {\n    startCollection()\n    fetch(FAKE_URL).resolveWith({ ...DEFAULT_REQUEST, status: 0 })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(1)\n      done()\n    })\n  })\n\n  it('should not track client error', (done) => {\n    startCollection()\n    fetch(FAKE_URL).resolveWith({ ...DEFAULT_REQUEST, status: 400 })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(0)\n      done()\n    })\n  })\n\n  it('should not track successful request', (done) => {\n    startCollection()\n    fetch(FAKE_URL).resolveWith({ ...DEFAULT_REQUEST, status: 200 })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(0)\n      done()\n    })\n  })\n\n  it('uses a fallback when the response text is empty', (done) => {\n    startCollection()\n    fetch(FAKE_URL).resolveWith({ ...DEFAULT_REQUEST, responseText: '' })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(rawLogsEvents.length).toEqual(1)\n      expect(rawLogsEvents[0].rawLogsEvent.error.stack).toEqual('Failed to load')\n      done()\n    })\n  })\n\n  describe('response body handling', () => {\n    beforeEach(() => {\n      startCollection()\n    })\n\n    it('should use responseBody for fetch server errors', (done) => {\n      const responseBody = 'Internal Server Error Details'\n      fetch('http://fake-url/').resolveWith({\n        status: 500,\n        responseText: responseBody,\n      })\n\n      mockFetchManager.whenAllComplete(() => {\n        const log = rawLogsEvents[0].rawLogsEvent\n        expect(log.error.stack).toBe(responseBody)\n        done()\n      })\n    })\n\n    it('should use error stack trace for fetch rejections', (done) => {\n      fetch('http://fake-url/').rejectWith(new Error('Network failure'))\n\n      mockFetchManager.whenAllComplete(() => {\n        const log = rawLogsEvents[0].rawLogsEvent\n        expect(log.error.stack).toContain('Error: Network failure')\n        done()\n      })\n    })\n\n    it('should truncate responseBody according to limit', (done) => {\n      const longResponse = 'a'.repeat(100)\n\n      fetch('http://fake-url/').resolveWith({\n        status: 500,\n        responseText: longResponse,\n      })\n\n      mockFetchManager.whenAllComplete(() => {\n        const log = rawLogsEvents[0].rawLogsEvent\n        expect(log.error.stack?.length).toBe(67) // 64 chars + '...'\n        expect(log.error.stack).toMatch(/^a{64}\\.\\.\\.$/)\n        done()\n      })\n    })\n\n    it('should use fallback message when no responseBody available', (done) => {\n      fetch('http://fake-url/').resolveWith({ status: 500 })\n\n      mockFetchManager.whenAllComplete(() => {\n        const log = rawLogsEvents[0].rawLogsEvent\n        expect(log.error.stack).toBe('Failed to load')\n        done()\n      })\n    })\n\n    it('should use fallback message when response body is already used', (done) => {\n      fetch('http://fake-url/').resolveWith({ status: 500, bodyUsed: true })\n\n      mockFetchManager.whenAllComplete(() => {\n        const log = rawLogsEvents[0].rawLogsEvent\n        expect(log.error.stack).toBe('Failed to load')\n        done()\n      })\n    })\n\n    it('should use fallback message when response body is disturbed', (done) => {\n      fetch('http://fake-url/').resolveWith({ status: 500, bodyDisturbed: true })\n\n      mockFetchManager.whenAllComplete(() => {\n        const log = rawLogsEvents[0].rawLogsEvent\n        expect(log.error.stack).toBe('Failed to load')\n        done()\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/networkError/networkErrorCollection.ts",
    "content": "import type { FetchResolveContext, XhrCompleteContext } from '@datadog/browser-core'\nimport {\n  isWorkerEnvironment,\n  Observable,\n  ErrorSource,\n  initXhrObservable,\n  RequestType,\n  initFetchObservable,\n  computeStackTrace,\n  toStackTraceString,\n  noop,\n  isServerError,\n  isIntakeUrl,\n  ResponseBodyAction,\n  safeTruncate,\n} from '@datadog/browser-core'\nimport type { LogsConfiguration } from '../configuration'\nimport type { LifeCycle } from '../lifeCycle'\nimport type { LogsEventDomainContext } from '../../domainContext.types'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { StatusType } from '../logger/isAuthorized'\n\nexport function startNetworkErrorCollection(configuration: LogsConfiguration, lifeCycle: LifeCycle) {\n  if (!configuration.forwardErrorsToLogs) {\n    return { stop: noop }\n  }\n\n  // XHR is not available in web workers, so we use an empty observable that never emits\n  const xhrSubscription = (\n    isWorkerEnvironment ? new Observable<XhrCompleteContext>() : initXhrObservable(configuration)\n  ).subscribe((context) => {\n    if (context.state === 'complete') {\n      handleResponse(RequestType.XHR, context)\n    }\n  })\n\n  const fetchSubscription = initFetchObservable({\n    responseBodyAction: (context) => (isNetworkError(context) ? ResponseBodyAction.COLLECT : ResponseBodyAction.IGNORE),\n  }).subscribe((context) => {\n    if (context.state === 'resolve') {\n      handleResponse(RequestType.FETCH, context)\n    }\n  })\n\n  function isNetworkError(request: XhrCompleteContext | FetchResolveContext) {\n    return !isIntakeUrl(request.url) && (isRejected(request) || isServerError(request.status))\n  }\n\n  function handleResponse(type: RequestType, request: XhrCompleteContext | FetchResolveContext) {\n    if (!isNetworkError(request)) {\n      return\n    }\n\n    const stack =\n      'error' in request && request.error\n        ? toStackTraceString(computeStackTrace(request.error))\n        : request.responseBody || 'Failed to load'\n\n    const domainContext: LogsEventDomainContext<typeof ErrorSource.NETWORK> = {\n      isAborted: request.isAborted,\n      handlingStack: request.handlingStack,\n    }\n\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: {\n        message: `${format(type)} error ${request.method} ${request.url}`,\n        date: request.startClocks.timeStamp,\n        error: {\n          stack: safeTruncate(stack, configuration.requestErrorResponseLengthLimit, '...'),\n          // We don't know if the error was handled or not, so we set it to undefined\n          handling: undefined,\n        },\n        http: {\n          method: request.method as any, // Cast resource method because of case mismatch cf issue RUMF-1152\n          status_code: request.status,\n          url: request.url,\n        },\n        status: StatusType.error,\n        origin: ErrorSource.NETWORK,\n      },\n      domainContext,\n    })\n  }\n\n  return {\n    stop: () => {\n      xhrSubscription.unsubscribe()\n      fetchSubscription.unsubscribe()\n    },\n  }\n}\n\nfunction isRejected(request: { status: number; responseType?: string }) {\n  return request.status === 0 && request.responseType !== 'opaque'\n}\n\nfunction format(type: RequestType) {\n  if (RequestType.XHR === type) {\n    return 'XHR'\n  }\n  return 'Fetch'\n}\n"
  },
  {
    "path": "packages/logs/src/domain/report/reportCollection.spec.ts",
    "content": "import { ErrorHandling, ErrorSource, noop } from '@datadog/browser-core'\nimport type { MockReportingObserver } from '@datadog/browser-core/test'\nimport { mockReportingObserver } from '@datadog/browser-core/test'\nimport type { RawReportLogsEvent } from '../../rawLogsEvent.types'\nimport { validateAndBuildLogsConfiguration } from '../configuration'\nimport type { RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { StatusType } from '../logger/isAuthorized'\nimport { startReportCollection } from './reportCollection'\n\ndescribe('reports', () => {\n  const initConfiguration = { clientToken: 'xxx', service: 'service' }\n  let reportingObserver: MockReportingObserver\n  let stopReportCollection: () => void\n  let lifeCycle: LifeCycle\n  let rawLogsEvents: Array<RawLogsEventCollectedData<RawReportLogsEvent>>\n\n  beforeEach(() => {\n    rawLogsEvents = []\n    stopReportCollection = noop\n    lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.RAW_LOG_COLLECTED, (rawLogsEvent) =>\n      rawLogsEvents.push(rawLogsEvent as RawLogsEventCollectedData<RawReportLogsEvent>)\n    )\n    reportingObserver = mockReportingObserver()\n  })\n\n  afterEach(() => {\n    stopReportCollection()\n  })\n\n  it('should send reports', () => {\n    ;({ stop: stopReportCollection } = startReportCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration, forwardReports: ['intervention'] })!,\n      lifeCycle\n    ))\n\n    reportingObserver.raiseReport('intervention')\n    expect(rawLogsEvents[0].rawLogsEvent).toEqual({\n      error: {\n        kind: 'NavigatorVibrate',\n        stack: jasmine.any(String),\n        handling: ErrorHandling.UNHANDLED,\n        causes: undefined,\n        fingerprint: undefined,\n        message: undefined,\n      },\n      date: jasmine.any(Number),\n      message: 'intervention: foo bar',\n      status: StatusType.error,\n      origin: ErrorSource.REPORT,\n    })\n  })\n\n  it('should not send reports when forwardReports init option not specified', () => {\n    ;({ stop: stopReportCollection } = startReportCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration })!,\n      lifeCycle\n    ))\n    reportingObserver.raiseReport('intervention')\n\n    expect(rawLogsEvents.length).toEqual(0)\n  })\n\n  it('should add the source file information to the message for non error reports', () => {\n    ;({ stop: stopReportCollection } = startReportCollection(\n      validateAndBuildLogsConfiguration({ ...initConfiguration, forwardReports: ['deprecation'] })!,\n      lifeCycle\n    ))\n\n    reportingObserver.raiseReport('deprecation')\n\n    expect(rawLogsEvents[0].rawLogsEvent).toEqual({\n      date: jasmine.any(Number),\n      message: 'deprecation: foo bar Found in http://foo.bar/index.js:20:10',\n      status: StatusType.warn,\n      origin: ErrorSource.REPORT,\n      error: undefined,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/report/reportCollection.ts",
    "content": "import type { Context, ClocksState } from '@datadog/browser-core'\nimport { timeStampNow, ErrorSource, getFileFromStackTraceString, initReportObservable } from '@datadog/browser-core'\nimport type { LogsConfiguration } from '../configuration'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { StatusType } from '../logger/isAuthorized'\nimport { createErrorFieldFromRawError } from '../createErrorFieldFromRawError'\n\nexport interface ProvidedError {\n  startClocks: ClocksState\n  error: unknown\n  context?: Context\n  handlingStack: string\n}\n\nexport function startReportCollection(configuration: LogsConfiguration, lifeCycle: LifeCycle) {\n  const reportSubscription = initReportObservable(configuration, configuration.forwardReports).subscribe((rawError) => {\n    let message = rawError.message\n    let error\n    const status = rawError.originalError.type === 'deprecation' ? StatusType.warn : StatusType.error\n\n    if (status === StatusType.error) {\n      error = createErrorFieldFromRawError(rawError)\n    } else if (rawError.stack) {\n      message += ` Found in ${getFileFromStackTraceString(rawError.stack)!}`\n    }\n\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: {\n        date: timeStampNow(),\n        message,\n        origin: ErrorSource.REPORT,\n        error,\n        status,\n      },\n    })\n  })\n\n  return {\n    stop: () => {\n      reportSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/reportError.ts",
    "content": "import type { RawError } from '@datadog/browser-core'\nimport { ErrorSource, addTelemetryDebug } from '@datadog/browser-core'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\nimport { StatusType } from './logger/isAuthorized'\n\nexport function startReportError(lifeCycle: LifeCycle) {\n  return (error: RawError) => {\n    lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n      rawLogsEvent: {\n        message: error.message,\n        date: error.startClocks.timeStamp,\n        origin: ErrorSource.AGENT,\n        status: StatusType.error,\n      },\n    })\n    // monitor-until: forever, to keep an eye on the errors reported to customers\n    addTelemetryDebug('Error reported to customer', { 'error.message': error.message })\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domain/runtimeError/runtimeErrorCollection.spec.ts",
    "content": "import type { BufferedData, RawError } from '@datadog/browser-core'\nimport { ErrorSource, ErrorHandling, Observable, BufferedDataType, clocksNow } from '@datadog/browser-core'\nimport { registerCleanupTask } from '../../../../core/test'\nimport type { RawRuntimeLogsEvent } from '../../rawLogsEvent.types'\nimport type { LogsConfiguration } from '../configuration'\nimport { StatusType } from '../logger/isAuthorized'\nimport type { RawLogsEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { startRuntimeErrorCollection } from './runtimeErrorCollection'\n\nfunction startRuntimeErrorCollectionWithDefaults({\n  forwardErrorsToLogs = true,\n}: { forwardErrorsToLogs?: boolean } = {}) {\n  const rawLogsEvents: Array<RawLogsEventCollectedData<RawRuntimeLogsEvent>> = []\n  const lifeCycle = new LifeCycle()\n  lifeCycle.subscribe(LifeCycleEventType.RAW_LOG_COLLECTED, (rawLogsEvent) =>\n    rawLogsEvents.push(rawLogsEvent as RawLogsEventCollectedData<RawRuntimeLogsEvent>)\n  )\n  const bufferedDataObservable = new Observable<BufferedData>()\n  const { stop } = startRuntimeErrorCollection(\n    { forwardErrorsToLogs } as LogsConfiguration,\n    lifeCycle,\n    bufferedDataObservable\n  )\n  registerCleanupTask(stop)\n\n  return { rawLogsEvents, bufferedDataObservable }\n}\n\nconst RAW_ERROR: RawError = {\n  startClocks: clocksNow(),\n  source: ErrorSource.SOURCE,\n  type: 'Error',\n  stack: 'Error: error!',\n  handling: ErrorHandling.UNHANDLED,\n  causes: undefined,\n  fingerprint: undefined,\n  message: 'error!',\n}\n\ndescribe('runtime error collection', () => {\n  let onErrorSpy: jasmine.Spy\n  let originalOnErrorHandler: OnErrorEventHandler\n\n  beforeEach(() => {\n    originalOnErrorHandler = window.onerror\n    onErrorSpy = jasmine.createSpy()\n    window.onerror = onErrorSpy\n  })\n\n  afterEach(() => {\n    window.onerror = originalOnErrorHandler\n  })\n\n  it('should send runtime errors', () => {\n    const { rawLogsEvents, bufferedDataObservable } = startRuntimeErrorCollectionWithDefaults()\n\n    bufferedDataObservable.notify({\n      type: BufferedDataType.RUNTIME_ERROR,\n      error: RAW_ERROR,\n    })\n\n    expect(rawLogsEvents[0].rawLogsEvent).toEqual({\n      date: jasmine.any(Number),\n      error: {\n        kind: 'Error',\n        stack: jasmine.any(String),\n        causes: undefined,\n        handling: ErrorHandling.UNHANDLED,\n        fingerprint: undefined,\n        message: undefined,\n      },\n      message: 'error!',\n      status: StatusType.error,\n      origin: ErrorSource.SOURCE,\n    })\n  })\n\n  it('should send runtime errors with causes', () => {\n    const { rawLogsEvents, bufferedDataObservable } = startRuntimeErrorCollectionWithDefaults()\n\n    bufferedDataObservable.notify({\n      type: BufferedDataType.RUNTIME_ERROR,\n      error: {\n        ...RAW_ERROR,\n        message: 'High level error',\n        causes: [\n          {\n            message: 'Mid level error',\n            type: 'Error',\n            stack: 'Error: Mid level error',\n            source: ErrorSource.SOURCE,\n          },\n          {\n            message: 'Low level error',\n            type: 'TypeError',\n            stack: 'TypeError: Low level error',\n            source: ErrorSource.SOURCE,\n          },\n        ],\n      },\n    })\n\n    expect(rawLogsEvents[0].rawLogsEvent).toEqual({\n      date: jasmine.any(Number),\n      error: {\n        kind: 'Error',\n        stack: jasmine.any(String),\n        handling: ErrorHandling.UNHANDLED,\n        causes: [\n          {\n            source: ErrorSource.SOURCE,\n            type: 'Error',\n            stack: jasmine.any(String),\n            message: 'Mid level error',\n          },\n          {\n            source: ErrorSource.SOURCE,\n            type: 'TypeError',\n            stack: jasmine.any(String),\n            message: 'Low level error',\n          },\n        ],\n        fingerprint: undefined,\n        message: undefined,\n      },\n      message: 'High level error',\n      status: StatusType.error,\n      origin: ErrorSource.SOURCE,\n    })\n  })\n\n  it('should not send runtime errors when forwardErrorsToLogs is false', () => {\n    const { rawLogsEvents, bufferedDataObservable } = startRuntimeErrorCollectionWithDefaults({\n      forwardErrorsToLogs: false,\n    })\n\n    bufferedDataObservable.notify({\n      type: BufferedDataType.RUNTIME_ERROR,\n      error: RAW_ERROR,\n    })\n\n    expect(rawLogsEvents.length).toEqual(0)\n  })\n\n  it('should retrieve dd_context from runtime errors', () => {\n    const { rawLogsEvents, bufferedDataObservable } = startRuntimeErrorCollectionWithDefaults()\n\n    bufferedDataObservable.notify({\n      type: BufferedDataType.RUNTIME_ERROR,\n      error: {\n        ...RAW_ERROR,\n        context: { foo: 'bar' },\n      },\n    })\n\n    expect(rawLogsEvents[0].messageContext).toEqual({ foo: 'bar' })\n  })\n})\n"
  },
  {
    "path": "packages/logs/src/domain/runtimeError/runtimeErrorCollection.ts",
    "content": "import type { Context, ClocksState, Observable, BufferedData } from '@datadog/browser-core'\nimport { noop, ErrorSource, BufferedDataType } from '@datadog/browser-core'\nimport type { LogsConfiguration } from '../configuration'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { StatusType } from '../logger/isAuthorized'\nimport { createErrorFieldFromRawError } from '../createErrorFieldFromRawError'\n\nexport interface ProvidedError {\n  startClocks: ClocksState\n  error: unknown\n  context?: Context\n  handlingStack: string\n}\n\nexport function startRuntimeErrorCollection(\n  configuration: LogsConfiguration,\n  lifeCycle: LifeCycle,\n  bufferedDataObservable: Observable<BufferedData>\n) {\n  if (!configuration.forwardErrorsToLogs) {\n    return { stop: noop }\n  }\n\n  const rawErrorSubscription = bufferedDataObservable.subscribe((bufferedData) => {\n    if (bufferedData.type === BufferedDataType.RUNTIME_ERROR) {\n      const error = bufferedData.error\n      lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {\n        rawLogsEvent: {\n          message: error.message,\n          date: error.startClocks.timeStamp,\n          error: createErrorFieldFromRawError(error),\n          origin: ErrorSource.SOURCE,\n          status: StatusType.error,\n        },\n        messageContext: error.context,\n      })\n    }\n  })\n\n  return {\n    stop: () => {\n      rawErrorSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/domainContext.types.ts",
    "content": "import type { ErrorSource } from '@datadog/browser-core'\n\nexport type LogsEventDomainContext<T extends ErrorSource = any> = T extends typeof ErrorSource.NETWORK\n  ? NetworkLogsEventDomainContext\n  : T extends typeof ErrorSource.CONSOLE\n    ? ConsoleLogsEventDomainContext\n    : T extends typeof ErrorSource.LOGGER\n      ? LoggerLogsEventDomainContext\n      : undefined\n\nexport interface NetworkLogsEventDomainContext {\n  isAborted: boolean\n  handlingStack?: string\n}\n\nexport interface ConsoleLogsEventDomainContext {\n  handlingStack: string\n}\n\nexport interface LoggerLogsEventDomainContext {\n  handlingStack: string\n}\n"
  },
  {
    "path": "packages/logs/src/entries/main.ts",
    "content": "/**\n *\n * Datadog Browser Logs SDK for collecting and forwarding browser logs to Datadog.\n * Provides comprehensive logging capabilities with automatic error tracking and custom log collection.\n *\n * @packageDocumentation\n * @see [Browser Log Collection](https://docs.datadoghq.com/logs/log_collection/javascript/)\n */\n\nimport { defineGlobal, getGlobalObject } from '@datadog/browser-core'\nimport type { LogsPublicApi } from '../boot/logsPublicApi'\nimport { makeLogsPublicApi } from '../boot/logsPublicApi'\n\nexport type { InternalContext } from '../domain/contexts/internalContext'\nexport type { LogsMessage } from '../domain/logger'\nexport { Logger, HandlerType } from '../domain/logger'\nexport { StatusType } from '../domain/logger/isAuthorized'\nexport type { LoggerConfiguration, LogsPublicApi as DatadogLogs } from '../boot/logsPublicApi'\nexport type { LogsInitConfiguration, LogsBeforeSend } from '../domain/configuration'\nexport type { LogsEvent } from '../logsEvent.types'\nexport type {\n  LogsEventDomainContext,\n  NetworkLogsEventDomainContext,\n  ConsoleLogsEventDomainContext,\n  LoggerLogsEventDomainContext,\n} from '../domainContext.types'\n\n/**\n * @deprecated Use {@link DatadogLogs} instead\n */\nexport type LogsGlobal = LogsPublicApi\n\nexport type {\n  InitConfiguration,\n  PublicApi,\n  Context,\n  ContextValue,\n  ContextArray,\n  User,\n  Account,\n  TraceContextInjection,\n  SessionPersistence,\n  TrackingConsent,\n  MatchOption,\n  ProxyFn,\n  Site,\n  ConsoleApiName,\n  RawReportType,\n  ErrorSource,\n} from '@datadog/browser-core'\n\n/**\n * The global Logs instance. Use this to call Logs methods.\n *\n * @category Main\n * @see {@link DatadogLogs}\n * @see [Browser Log Collection](https://docs.datadoghq.com/logs/log_collection/javascript/)\n */\nexport const datadogLogs = makeLogsPublicApi()\n\ninterface BrowserWindow extends Window {\n  DD_LOGS?: LogsPublicApi\n}\ndefineGlobal(getGlobalObject<BrowserWindow>(), 'DD_LOGS', datadogLogs)\n"
  },
  {
    "path": "packages/logs/src/logsEvent.types.ts",
    "content": "export interface LogsEvent {\n  /**\n   * Start of the log in ms from epoch\n   */\n  date: number\n  /**\n   * The log message\n   */\n  message: string\n  /**\n   * The log status\n   */\n  status: 'ok' | 'debug' | 'info' | 'notice' | 'warn' | 'error' | 'critical' | 'alert' | 'emerg'\n  /**\n   * Origin of the log\n   */\n  origin: 'network' | 'source' | 'console' | 'logger' | 'agent' | 'report'\n  /**\n   * UUID of the application\n   */\n  application_id?: string\n  /**\n   * The service name\n   */\n  service?: string\n  /**\n   * Tags of the log\n   */\n  ddtags?: string\n  /**\n   * UUID of the session (deprecated in favor of session.id)\n   */\n  session_id?: string\n  /**\n   * Session properties\n   */\n  session?: {\n    /**\n     * UUID of the session\n     */\n    id?: string\n\n    [k: string]: unknown\n  }\n  /**\n   * View properties\n   */\n  view: {\n    /**\n     * URL that linked to the initial view of the page\n     */\n    referrer?: string\n    /**\n     * URL of the view\n     */\n    url: string\n    /**\n     * UUID of the view\n     */\n    id?: string\n    /**\n     * User defined name of the view\n     */\n    name?: string\n\n    [k: string]: unknown\n  }\n  /**\n   * Logger properties\n   */\n  logger?: {\n    /**\n     * Name of the logger\n     */\n    name: string\n\n    [k: string]: unknown\n  }\n  /**\n   * Error properties\n   */\n  error?: {\n    /**\n     * Kind of the error\n     */\n    kind?: string\n    /**\n     * Stacktrace of the error\n     */\n    stack?: string\n    /**\n     * Fingerprint of the error\n     */\n    fingerprint?: string\n    /**\n     * Message of the error\n     */\n    message?: string\n    /**\n     * Flattened causes of the error\n     */\n    causes?: Array<{\n      message: string\n      source: string\n      type?: string\n      stack?: string\n    }>\n\n    [k: string]: unknown\n  }\n  /**\n   * Resource properties of the error\n   */\n  http?: {\n    /**\n     * HTTP method of the resource\n     */\n    method: 'POST' | 'GET' | 'HEAD' | 'PUT' | 'DELETE' | 'PATCH'\n    /**\n     * HTTP Status code of the resource\n     */\n    status_code: number\n    /**\n     * URL of the resource\n     */\n    url: string\n\n    [k: string]: unknown\n  }\n  user_action?: {\n    id: string | string[]\n  }\n  usr?: {\n    /**\n     * Identifier of the user\n     */\n    id?: string\n    /**\n     * Name of the user\n     */\n    name?: string\n    /**\n     * Email of the user\n     */\n    email?: string\n    /**\n     * Identifier of the user across sessions\n     */\n    anonymous_id?: string\n    [k: string]: unknown\n  }\n  account?: {\n    /**\n     * Identifier of the account\n     */\n    id: string\n    /**\n     * Name of the account\n     */\n    name?: string\n    [k: string]: unknown\n  }\n\n  [k: string]: unknown\n}\n"
  },
  {
    "path": "packages/logs/src/rawLogsEvent.types.ts",
    "content": "import type { ErrorSource, RawErrorCause, TimeStamp, ErrorHandling } from '@datadog/browser-core'\nimport type { StatusType } from './domain/logger/isAuthorized'\n\nexport type RawLogsEvent =\n  | RawConsoleLogsEvent\n  | RawNetworkLogsEvent\n  | RawLoggerLogsEvent\n  | RawAgentLogsEvent\n  | RawReportLogsEvent\n  | RawRuntimeLogsEvent\n\ninterface Error {\n  message?: string\n  kind?: string\n  stack?: string\n  fingerprint?: string\n  causes?: RawErrorCause[]\n  handling: ErrorHandling | undefined\n}\n\ninterface CommonRawLogsEvent {\n  date: TimeStamp\n  message: string\n  status: StatusType\n  error?: Error\n  origin: ErrorSource\n}\n\nexport interface RawConsoleLogsEvent extends CommonRawLogsEvent {\n  origin: typeof ErrorSource.CONSOLE\n}\n\nexport interface RawLoggerLogsEvent extends CommonRawLogsEvent {\n  origin: typeof ErrorSource.LOGGER\n}\n\nexport interface RawNetworkLogsEvent extends CommonRawLogsEvent {\n  origin: typeof ErrorSource.NETWORK\n  status: typeof StatusType.error\n  error: Error\n  http: {\n    method: 'POST' | 'GET' | 'HEAD' | 'PUT' | 'DELETE' | 'PATCH'\n    status_code: number\n    url: string\n    [k: string]: unknown\n  }\n}\n\nexport interface RawReportLogsEvent extends CommonRawLogsEvent {\n  origin: typeof ErrorSource.REPORT\n}\n\nexport interface RawRuntimeLogsEvent extends CommonRawLogsEvent {\n  origin: typeof ErrorSource.SOURCE\n  status: typeof StatusType.error\n  error: Error\n}\n\nexport interface RawAgentLogsEvent extends CommonRawLogsEvent {\n  origin: typeof ErrorSource.AGENT\n  status: typeof StatusType.error\n}\n\nexport interface CommonContext {\n  view?: {\n    referrer: string\n    url: string\n  }\n}\n"
  },
  {
    "path": "packages/logs/src/transport/startLogsBatch.ts",
    "content": "import type { Context, Observable, PageMayExitEvent, RawError } from '@datadog/browser-core'\nimport { createBatch, createFlushController, createHttpRequest, createIdentityEncoder } from '@datadog/browser-core'\nimport type { LogsConfiguration } from '../domain/configuration'\nimport type { LifeCycle } from '../domain/lifeCycle'\nimport { LifeCycleEventType } from '../domain/lifeCycle'\nimport type { LogsEvent } from '../logsEvent.types'\nimport type { LogsSessionManager } from '../domain/logsSessionManager'\n\nexport function startLogsBatch(\n  configuration: LogsConfiguration,\n  lifeCycle: LifeCycle,\n  reportError: (error: RawError) => void,\n  pageMayExitObservable: Observable<PageMayExitEvent>,\n  session: LogsSessionManager\n) {\n  const endpoints = [configuration.logsEndpointBuilder]\n  if (configuration.replica) {\n    endpoints.push(configuration.replica.logsEndpointBuilder)\n  }\n\n  const batch = createBatch({\n    encoder: createIdentityEncoder(),\n    request: createHttpRequest(endpoints, reportError),\n    flushController: createFlushController({\n      pageMayExitObservable,\n      sessionExpireObservable: session.expireObservable,\n    }),\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (serverLogsEvent: LogsEvent & Context) => {\n    batch.add(serverLogsEvent)\n  })\n\n  return batch\n}\n"
  },
  {
    "path": "packages/logs/src/transport/startLogsBridge.ts",
    "content": "import type { Context } from '@datadog/browser-core'\nimport { getEventBridge } from '@datadog/browser-core'\nimport type { LifeCycle } from '../domain/lifeCycle'\nimport { LifeCycleEventType } from '../domain/lifeCycle'\nimport type { LogsEvent } from '../logsEvent.types'\n\nexport function startLogsBridge(lifeCycle: LifeCycle) {\n  const bridge = getEventBridge<'log', LogsEvent>()!\n\n  lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (serverLogsEvent: LogsEvent & Context) => {\n    bridge.send('log', serverLogsEvent)\n  })\n}\n"
  },
  {
    "path": "packages/logs/test/mockLogsSessionManager.ts",
    "content": "import { Observable } from '@datadog/browser-core'\nimport { LoggerTrackingType, type LogsSessionManager } from '../src/domain/logsSessionManager'\n\nexport interface LogsSessionManagerMock extends LogsSessionManager {\n  setId(id: string): LogsSessionManager\n  setNotTracked(): LogsSessionManager\n  setTracked(): LogsSessionManager\n  expire(): LogsSessionManager\n}\n\nexport function createLogsSessionManagerMock(): LogsSessionManagerMock {\n  let id = 'session-id'\n  let sessionIsActive: boolean = true\n  let sessionStatus = LoggerTrackingType.TRACKED\n\n  return {\n    setId(newId: string) {\n      id = newId\n      return this\n    },\n    findTrackedSession: (_startTime, options) => {\n      if (sessionStatus === LoggerTrackingType.TRACKED && (sessionIsActive || options?.returnInactive)) {\n        return { id }\n      }\n    },\n    expireObservable: new Observable(),\n    expire() {\n      sessionIsActive = false\n      this.expireObservable.notify()\n      return this\n    },\n    setNotTracked() {\n      sessionStatus = LoggerTrackingType.NOT_TRACKED\n      return this\n    },\n    setTracked() {\n      sessionStatus = LoggerTrackingType.TRACKED\n      return this\n    },\n  }\n}\n"
  },
  {
    "path": "packages/logs/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/entries/main.ts\"]\n}\n"
  },
  {
    "path": "packages/rum/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/rum/BROWSER_SUPPORT.md",
    "content": "# Browser Support\n\n| Feature           | Chrome | Firefox | Safari | Edge | Chrome Android | Safari iOS | IE  | Opera |\n| ----------------- | ------ | ------- | ------ | ---- | -------------- | ---------- | --- | ----- |\n| loading           | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| init              | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| rum request       | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| flush on hide     | ✅     | ✅      | ✅     | ✅   | ✅             | ❌         | ❌  | ✅    |\n| console error     | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| runtime error     | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| CSP violation     | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| intervention      | ✅     | ❌      | ❌     | ✅   | ✅             | ❌         | ❌  | ✅    |\n| auto action       | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| custom action     | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| long task         | ✅     | ❌      | ❌     | ✅   | ✅             | ❌         | ❌  | ✅    |\n| tracing           | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| route change      | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| loading time      | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| resource timing   | ✅     | ✅      | ⚠️(2)  | ✅   | ✅             | ⚠️(2)      | ❌  | ✅    |\n| navigation timing | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n| web vitals        | ✅     | ⚠️(1)   | ⚠️(1)  | ✅   | ✅             | ⚠️(1)      | ❌  | ✅    |\n| FCP               | ✅     | ✅      | ✅     | ✅   | ✅             | ✅         | ❌  | ✅    |\n\n1. FID only\n2. size information not available\n3. firstByte and download only\n"
  },
  {
    "path": "packages/rum/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum/README.md",
    "content": "# RUM Browser Monitoring\n\nDatadog Real User Monitoring (RUM) enables you to visualize and analyze the real-time performance and user journeys of your application's individual users.\n\nSee the [dedicated datadog documentation][1] for more details.\n\n## Usage\n\nTo start collecting events, add [`@datadog/browser-rum`][2] to your `package.json` file, then initialize it with:\n\n```javascript\nimport { datadogRum } from '@datadog/browser-rum'\n\ndatadogRum.init({\n  applicationId: '<DATADOG_APPLICATION_ID>',\n  clientToken: '<DATADOG_CLIENT_TOKEN>',\n  site: '<DATADOG_SITE>',\n  //  service: 'my-web-application',\n  //  env: 'production',\n  //  version: '1.0.0',\n  sessionSampleRate: 100,\n  sessionReplaySampleRate: 100,\n  trackResources: true,\n  trackLongTasks: true,\n  trackUserInteractions: true,\n})\n```\n\n**Note**: The `trackUserInteractions` parameter enables the automatic collection of user clicks in your application. **Sensitive and private data** contained in your pages may be included to identify the elements interacted with.\n\n<!-- Note: all URLs should be absolute -->\n\n[1]: https://docs.datadoghq.com/real_user_monitoring/browser\n[2]: https://www.npmjs.com/package/@datadog/browser-rum\n"
  },
  {
    "path": "packages/rum/internal/package.json",
    "content": "{\n  \"private\": true,\n  \"main\": \"../cjs/entries/internal.js\",\n  \"module\": \"../esm/entries/internal.js\",\n  \"types\": \"../cjs/entries/internal.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum/internal-synthetics/package.json",
    "content": "{\n  \"private\": true,\n  \"main\": \"../cjs/entries/internalSynthetics.js\",\n  \"module\": \"../esm/entries/internalSynthetics.js\",\n  \"types\": \"../cjs/entries/internalSynthetics.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"bundle/**/*.js\",\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"internal\",\n    \"internal-synthetics\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules --bundle datadog-rum.js\",\n    \"build:bundle\": \"node ../../scripts/build/build-package.ts --bundle datadog-rum.js\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-logs\": \"6.32.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-logs\": {\n      \"optional\": true\n    }\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum\"\n  },\n  \"devDependencies\": {\n    \"@types/pako\": \"2.0.4\",\n    \"pako\": \"2.1.0\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/boot/isBrowserSupported.ts",
    "content": "/**\n * Test for Browser features used while recording\n */\nexport function isBrowserSupported() {\n  return (\n    // Array.from is a bit less supported by browsers than CSSSupportsRule, but has higher chances\n    // to be polyfilled. Test for both to be more confident. We could add more things if we find out\n    // this test is not sufficient.\n    typeof Array.from === 'function' &&\n    typeof CSSSupportsRule === 'function' &&\n    typeof URL.createObjectURL === 'function' &&\n    'forEach' in NodeList.prototype\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/boot/lazyLoadProfiler.ts",
    "content": "import { mockable } from '@datadog/browser-core'\nimport { reportScriptLoadingError } from '../domain/scriptLoadingError'\nimport type { createRumProfiler } from '../domain/profiling/profiler'\n\nexport async function lazyLoadProfiler(): Promise<typeof createRumProfiler | undefined> {\n  try {\n    return await mockable(importProfiler)()\n  } catch (error: unknown) {\n    reportScriptLoadingError({\n      error,\n      source: 'Profiler',\n      scriptType: 'module',\n    })\n  }\n}\n\nexport async function importProfiler() {\n  const module = await import(/* webpackChunkName: \"profiler\" */ '../domain/profiling/profiler')\n  return module.createRumProfiler\n}\n"
  },
  {
    "path": "packages/rum/src/boot/lazyLoadRecorder.spec.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport type { MockTelemetry } from '@datadog/browser-core/test'\nimport { replaceMockable, startMockTelemetry } from '@datadog/browser-core/test'\nimport { lazyLoadRecorder, importRecorder } from './lazyLoadRecorder'\n\ndescribe('lazyLoadRecorder', () => {\n  let displaySpy: jasmine.Spy\n  let telemetry: MockTelemetry\n\n  beforeEach(() => {\n    telemetry = startMockTelemetry()\n    displaySpy = spyOn(display, 'error')\n  })\n\n  it('should report a console error and metrics but no telemetry error if CSP blocks the module', async () => {\n    const loadRecorderError = new Error('Dynamic import was blocked due to Content Security Policy')\n    replaceMockable(importRecorder, () => Promise.reject(loadRecorderError))\n    await lazyLoadRecorder()\n\n    expect(displaySpy).toHaveBeenCalledWith(jasmine.stringContaining('Recorder failed to start'), loadRecorderError)\n    expect(displaySpy).toHaveBeenCalledWith(jasmine.stringContaining('Please make sure CSP is correctly configured'))\n    expect(await telemetry.getEvents()).toEqual([])\n  })\n\n  it('should report a console error and metrics but no telemetry error if importing fails for non-CSP reasons', async () => {\n    const loadRecorderError = new Error('Dynamic import failed')\n    replaceMockable(importRecorder, () => Promise.reject(loadRecorderError))\n    await lazyLoadRecorder()\n\n    expect(displaySpy).toHaveBeenCalledWith(jasmine.stringContaining('Recorder failed to start'), loadRecorderError)\n    expect(await telemetry.getEvents()).toEqual([])\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/boot/lazyLoadRecorder.ts",
    "content": "import { mockable } from '@datadog/browser-core'\nimport { reportScriptLoadingError } from '../domain/scriptLoadingError'\nimport type { startRecording } from './startRecording'\n\nexport async function lazyLoadRecorder(): Promise<typeof startRecording | undefined> {\n  try {\n    return await mockable(importRecorder)()\n  } catch (error: unknown) {\n    reportScriptLoadingError({\n      error,\n      source: 'Recorder',\n      scriptType: 'module',\n    })\n  }\n}\n\nexport async function importRecorder() {\n  const module = await import(/* webpackChunkName: \"recorder\" */ './startRecording')\n  return module.startRecording\n}\n"
  },
  {
    "path": "packages/rum/src/boot/postStartStrategy.ts",
    "content": "import type {\n  LifeCycle,\n  RumConfiguration,\n  RumSessionManager,\n  StartRecordingOptions,\n  ViewHistory,\n  RumSession,\n} from '@datadog/browser-rum-core'\nimport { LifeCycleEventType, SessionReplayState } from '@datadog/browser-rum-core'\nimport type { Telemetry, DeflateEncoder } from '@datadog/browser-core'\nimport { asyncRunOnReadyState, monitorError, Observable } from '@datadog/browser-core'\nimport { getSessionReplayLink } from '../domain/getSessionReplayLink'\nimport { startRecorderInitTelemetry } from '../domain/startRecorderInitTelemetry'\nimport type { startRecording } from './startRecording'\nimport { lazyLoadRecorder } from './lazyLoadRecorder'\n\nexport type StartRecording = typeof startRecording\n\nexport const enum RecorderStatus {\n  // The recorder is stopped.\n  Stopped,\n  // The user started the recording while it wasn't possible yet. The recorder should start as soon\n  // as possible.\n  IntentToStart,\n  // The recorder is starting. It does not record anything yet.\n  Starting,\n  // The recorder is started, it records the session.\n  Started,\n}\n\nexport type RecorderInitEvent =\n  | { type: 'start'; forced: boolean }\n  | { type: 'document-ready' }\n  | { type: 'recorder-settled' }\n  | { type: 'aborted' }\n  | { type: 'deflate-encoder-load-failed' }\n  | { type: 'recorder-load-failed' }\n  | { type: 'succeeded' }\n\nexport interface Strategy {\n  start: (options?: StartRecordingOptions) => void\n  stop: () => void\n  isRecording: () => boolean\n  getSessionReplayLink: () => string | undefined\n}\n\nexport function createPostStartStrategy(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  sessionManager: RumSessionManager,\n  viewHistory: ViewHistory,\n  getOrCreateDeflateEncoder: () => DeflateEncoder | undefined,\n  telemetry: Telemetry\n): Strategy {\n  let status = RecorderStatus.Stopped\n  let stopRecording: () => void\n\n  lifeCycle.subscribe(LifeCycleEventType.SESSION_EXPIRED, () => {\n    if (status === RecorderStatus.Starting || status === RecorderStatus.Started) {\n      stop()\n      status = RecorderStatus.IntentToStart\n    }\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {\n    if (status === RecorderStatus.IntentToStart) {\n      start()\n    }\n  })\n\n  const observable = new Observable<RecorderInitEvent>()\n  startRecorderInitTelemetry(telemetry, observable)\n\n  const doStart = async (forced: boolean) => {\n    observable.notify({ type: 'start', forced })\n\n    const [startRecordingImpl] = await Promise.all([\n      notifyWhenSettled(observable, { type: 'recorder-settled' }, lazyLoadRecorder()),\n      notifyWhenSettled(observable, { type: 'document-ready' }, asyncRunOnReadyState(configuration, 'interactive')),\n    ])\n\n    if (status !== RecorderStatus.Starting) {\n      observable.notify({ type: 'aborted' })\n      return\n    }\n\n    if (!startRecordingImpl) {\n      status = RecorderStatus.Stopped\n      observable.notify({ type: 'recorder-load-failed' })\n      return\n    }\n\n    const deflateEncoder = getOrCreateDeflateEncoder()\n    if (!deflateEncoder) {\n      status = RecorderStatus.Stopped\n      observable.notify({ type: 'deflate-encoder-load-failed' })\n      return\n    }\n\n    ;({ stop: stopRecording } = startRecordingImpl(\n      lifeCycle,\n      configuration,\n      sessionManager,\n      viewHistory,\n      deflateEncoder,\n      telemetry\n    ))\n\n    status = RecorderStatus.Started\n    observable.notify({ type: 'succeeded' })\n  }\n\n  function start(options?: StartRecordingOptions) {\n    const session = sessionManager.findTrackedSession()\n    if (canStartRecording(session, options)) {\n      status = RecorderStatus.IntentToStart\n      return\n    }\n\n    if (isRecordingInProgress(status)) {\n      return\n    }\n\n    status = RecorderStatus.Starting\n\n    const forced = shouldForceReplay(session!, options) || false\n\n    // Intentionally not awaiting doStart() to keep it asynchronous\n    doStart(forced).catch(monitorError)\n\n    if (forced) {\n      sessionManager.setForcedReplay()\n    }\n  }\n\n  function stop() {\n    if (status === RecorderStatus.Started) {\n      stopRecording?.()\n    }\n\n    status = RecorderStatus.Stopped\n  }\n\n  return {\n    start,\n    stop,\n    getSessionReplayLink() {\n      return getSessionReplayLink(configuration, sessionManager, viewHistory, status !== RecorderStatus.Stopped)\n    },\n    isRecording: () => status === RecorderStatus.Started,\n  }\n}\n\nfunction canStartRecording(session: RumSession | undefined, options?: StartRecordingOptions) {\n  return !session || (session.sessionReplay === SessionReplayState.OFF && (!options || !options.force))\n}\n\nfunction isRecordingInProgress(status: RecorderStatus) {\n  return status === RecorderStatus.Starting || status === RecorderStatus.Started\n}\n\nfunction shouldForceReplay(session: RumSession, options?: StartRecordingOptions) {\n  return options && options.force && session.sessionReplay === SessionReplayState.OFF\n}\n\nasync function notifyWhenSettled<Event, Result>(\n  observable: Observable<Event>,\n  event: Event,\n  promise: Promise<Result>\n): Promise<Result> {\n  try {\n    return await promise\n  } finally {\n    observable.notify(event)\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/boot/preStartStrategy.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport type { Strategy } from './postStartStrategy'\n\nconst enum PreStartRecorderStatus {\n  None,\n  HadManualStart,\n  HadManualStop,\n}\n\nexport function createPreStartStrategy(): {\n  strategy: Strategy\n  shouldStartImmediately: (configuration: RumConfiguration) => boolean\n} {\n  let status = PreStartRecorderStatus.None\n  return {\n    strategy: {\n      start() {\n        status = PreStartRecorderStatus.HadManualStart\n      },\n      stop() {\n        status = PreStartRecorderStatus.HadManualStop\n      },\n      isRecording: () => false,\n      getSessionReplayLink: noop as () => string | undefined,\n    },\n    shouldStartImmediately(configuration) {\n      return (\n        status === PreStartRecorderStatus.HadManualStart ||\n        (status === PreStartRecorderStatus.None && !configuration.startSessionReplayRecordingManually)\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/boot/profilerApi.ts",
    "content": "import type {\n  LifeCycle,\n  ViewHistory,\n  RumSessionManager,\n  RumConfiguration,\n  ProfilerApi,\n  Hooks,\n} from '@datadog/browser-rum-core'\nimport type { DeflateEncoderStreamId, Encoder } from '@datadog/browser-core'\nimport { isSampled } from '@datadog/browser-rum-core'\nimport { monitorError } from '@datadog/browser-core'\nimport type { RUMProfiler } from '../domain/profiling/types'\nimport { isProfilingSupported } from '../domain/profiling/profilingSupported'\nimport { startProfilingContext } from '../domain/profiling/profilingContext'\nimport { lazyLoadProfiler } from './lazyLoadProfiler'\n\nexport function makeProfilerApi(): ProfilerApi {\n  let profiler: RUMProfiler | undefined\n\n  function onRumStart(\n    lifeCycle: LifeCycle,\n    hooks: Hooks,\n    configuration: RumConfiguration,\n    sessionManager: RumSessionManager,\n    viewHistory: ViewHistory,\n    createEncoder: (streamId: DeflateEncoderStreamId) => Encoder\n  ) {\n    const session = sessionManager.findTrackedSession() // Check if the session is tracked.\n\n    if (!session) {\n      // No session tracked, no profiling.\n      // Note: No Profiling context is set at this stage.\n      return\n    }\n\n    // Sampling (sticky sampling based on session id)\n    if (!isSampled(session.id, configuration.profilingSampleRate)) {\n      // No sampling, no profiling.\n      // Note: No Profiling context is set at this stage.\n      return\n    }\n\n    // Listen to events and add the profiling context to them.\n    const profilingContextManager = startProfilingContext(hooks)\n\n    // Browser support check\n    if (!isProfilingSupported()) {\n      profilingContextManager.set({\n        status: 'error',\n        error_reason: 'not-supported-by-browser',\n      })\n      return\n    }\n\n    lazyLoadProfiler()\n      .then((createRumProfiler) => {\n        if (!createRumProfiler) {\n          profilingContextManager.set({ status: 'error', error_reason: 'failed-to-lazy-load' })\n          return\n        }\n\n        profiler = createRumProfiler(\n          configuration,\n          lifeCycle,\n          sessionManager,\n          profilingContextManager,\n          createEncoder,\n          viewHistory,\n          undefined\n        )\n        profiler.start()\n      })\n      .catch(monitorError)\n  }\n\n  return {\n    onRumStart,\n    stop: () => {\n      profiler?.stop()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/boot/recorderApi.spec.ts",
    "content": "import type {\n  DeflateEncoder,\n  DeflateWorker,\n  DeflateWorkerAction,\n  RawTelemetryEvent,\n  Telemetry,\n} from '@datadog/browser-core'\nimport { BridgeCapability, display } from '@datadog/browser-core'\nimport type { RecorderApi, RumSessionManager } from '@datadog/browser-rum-core'\nimport { LifeCycle, LifeCycleEventType } from '@datadog/browser-rum-core'\nimport type { MockTelemetry } from '@datadog/browser-core/test'\nimport {\n  collectAsyncCalls,\n  mockEventBridge,\n  replaceMockableWithSpy,\n  registerCleanupTask,\n  startMockTelemetry,\n} from '@datadog/browser-core/test'\nimport type { RumSessionManagerMock } from '../../../rum-core/test'\nimport {\n  createRumSessionManagerMock,\n  mockDocumentReadyState,\n  mockRumConfiguration,\n  mockViewHistory,\n} from '../../../rum-core/test'\nimport type { CreateDeflateWorker } from '../domain/deflate'\nimport { resetDeflateWorkerState, createDeflateWorker } from '../domain/deflate'\nimport { MockWorker } from '../../test'\nimport * as replayStats from '../domain/replayStats'\nimport { type RecorderInitMetrics } from '../domain/startRecorderInitTelemetry'\nimport { makeRecorderApi } from './recorderApi'\nimport type { StartRecording } from './postStartStrategy'\nimport { importRecorder } from './lazyLoadRecorder'\n\ndescribe('makeRecorderApi', () => {\n  let lifeCycle: LifeCycle\n  let recorderApi: RecorderApi\n  let startRecordingSpy: jasmine.Spy\n  let importRecorderSpy: jasmine.Spy<() => Promise<StartRecording>>\n  let stopRecordingSpy: jasmine.Spy<() => void>\n  let mockWorker: MockWorker\n  let createDeflateWorkerSpy: jasmine.Spy<CreateDeflateWorker>\n  let rumInit: (options?: { worker?: DeflateWorker }) => void\n  let telemetry: MockTelemetry\n\n  function setupRecorderApi({\n    sessionManager,\n    loadRecorderError,\n    startSessionReplayRecordingManually,\n  }: {\n    sessionManager?: RumSessionManager\n    loadRecorderError?: boolean\n    startSessionReplayRecordingManually?: boolean\n  } = {}) {\n    telemetry = startMockTelemetry()\n    mockWorker = new MockWorker()\n    createDeflateWorkerSpy = replaceMockableWithSpy(createDeflateWorker).and.callFake(() => mockWorker)\n    spyOn(display, 'error')\n\n    lifeCycle = new LifeCycle()\n    stopRecordingSpy = jasmine.createSpy('stopRecording')\n    startRecordingSpy = jasmine.createSpy('startRecording')\n    importRecorderSpy = replaceMockableWithSpy(importRecorder)\n\n    if (loadRecorderError) {\n      importRecorderSpy.and.resolveTo(undefined)\n    } else {\n      // Workaround because using resolveTo(startRecordingSpy) was not working\n      importRecorderSpy.and.resolveTo((...args: any) => {\n        startRecordingSpy(...args)\n        return {\n          stop: stopRecordingSpy,\n        }\n      })\n    }\n\n    const configuration = mockRumConfiguration({\n      startSessionReplayRecordingManually: startSessionReplayRecordingManually ?? false,\n    })\n\n    recorderApi = makeRecorderApi()\n    rumInit = ({ worker } = {}) => {\n      recorderApi.onRumStart(\n        lifeCycle,\n        configuration,\n        sessionManager ?? createRumSessionManagerMock().setId('1234'),\n        mockViewHistory(),\n        worker,\n        { enabled: true, metricsEnabled: true } as Telemetry\n      )\n    }\n\n    registerCleanupTask(() => {\n      resetDeflateWorkerState()\n    })\n  }\n\n  describe('recorder boot', () => {\n    describe('with automatic start', () => {\n      it('starts recording when init() is called', async () => {\n        setupRecorderApi()\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n        expect(await telemetry.hasEvents()).toEqual(false)\n        rumInit()\n        await collectAsyncCalls(startRecordingSpy, 1)\n        expect(startRecordingSpy).toHaveBeenCalled()\n        expect(await telemetry.getEvents()).toEqual([expectedRecorderInitTelemetry()])\n      })\n\n      it('starts recording after the DOM is loaded', async () => {\n        setupRecorderApi()\n        const { triggerOnDomLoaded } = mockDocumentReadyState()\n        rumInit()\n\n        expect(importRecorderSpy).toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n        expect(await telemetry.hasEvents()).toEqual(false)\n\n        triggerOnDomLoaded()\n        await collectAsyncCalls(startRecordingSpy, 1)\n\n        expect(startRecordingSpy).toHaveBeenCalled()\n        expect(await telemetry.getEvents()).toEqual([expectedRecorderInitTelemetry()])\n      })\n    })\n\n    describe('with manual start', () => {\n      it('does not start recording when init() is called', async () => {\n        setupRecorderApi({ startSessionReplayRecordingManually: true })\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n        expect(await telemetry.hasEvents()).toEqual(false)\n        rumInit()\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n        expect(await telemetry.hasEvents()).toEqual(false)\n      })\n\n      it('does not start recording after the DOM is loaded', async () => {\n        setupRecorderApi({ startSessionReplayRecordingManually: true })\n        const { triggerOnDomLoaded } = mockDocumentReadyState()\n        rumInit()\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n        expect(await telemetry.hasEvents()).toEqual(false)\n        triggerOnDomLoaded()\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n        expect(await telemetry.hasEvents()).toEqual(false)\n      })\n    })\n  })\n\n  describe('recorder start', () => {\n    it('ignores additional start calls while recording is already started', async () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit()\n      recorderApi.start()\n      recorderApi.start()\n      recorderApi.start()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('ignores restart before the DOM is loaded', async () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      const { triggerOnDomLoaded } = mockDocumentReadyState()\n      rumInit()\n      recorderApi.stop()\n      recorderApi.start()\n      triggerOnDomLoaded()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('ignores start calls if the session is not tracked', () => {\n      setupRecorderApi({\n        sessionManager: createRumSessionManagerMock().setNotTracked(),\n        startSessionReplayRecordingManually: true,\n      })\n      rumInit()\n      recorderApi.start()\n\n      expect(importRecorderSpy).not.toHaveBeenCalled()\n      expect(startRecordingSpy).not.toHaveBeenCalled()\n    })\n\n    it('ignores start calls if the session is tracked without session replay', () => {\n      setupRecorderApi({\n        sessionManager: createRumSessionManagerMock().setTrackedWithoutSessionReplay(),\n        startSessionReplayRecordingManually: true,\n      })\n      rumInit()\n      recorderApi.start()\n      expect(importRecorderSpy).not.toHaveBeenCalled()\n      expect(startRecordingSpy).not.toHaveBeenCalled()\n    })\n\n    it('should start recording if session is tracked without session replay when forced', async () => {\n      const setForcedReplaySpy = jasmine.createSpy()\n\n      setupRecorderApi({\n        sessionManager: {\n          ...createRumSessionManagerMock().setTrackedWithoutSessionReplay(),\n          setForcedReplay: setForcedReplaySpy,\n        },\n        startSessionReplayRecordingManually: true,\n      })\n\n      rumInit()\n      recorderApi.start({ force: true })\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n      expect(setForcedReplaySpy).toHaveBeenCalledTimes(1)\n      expect(await telemetry.getEvents()).toEqual([expectedRecorderInitTelemetry({ forced: true })])\n    })\n\n    it('uses the previously created worker if available', async () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit({ worker: mockWorker })\n      recorderApi.start()\n\n      await collectAsyncCalls(startRecordingSpy, 1)\n      expect(createDeflateWorkerSpy).not.toHaveBeenCalled()\n      expect(startRecordingSpy).toHaveBeenCalled()\n    })\n\n    it('does not start recording if load fails', async () => {\n      setupRecorderApi({ loadRecorderError: true })\n      rumInit()\n\n      expect(importRecorderSpy).toHaveBeenCalled()\n\n      await new Promise((resolve) => setTimeout(resolve, 1000))\n\n      const events = await telemetry.getEvents()\n      expect(events).toEqual([expectedRecorderInitTelemetry({ result: 'recorder-load-failed' })])\n    })\n\n    it('does not start recording if worker creation fails', async () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit()\n\n      createDeflateWorkerSpy.and.throwError('Crash')\n      recorderApi.start()\n\n      expect(importRecorderSpy).toHaveBeenCalled()\n      await collectAsyncCalls(createDeflateWorkerSpy, 1)\n\n      expect(startRecordingSpy).not.toHaveBeenCalled()\n      const events = await telemetry.getEvents()\n      expect(events).toEqual([\n        jasmine.objectContaining({\n          error: jasmine.anything(),\n        }),\n        expectedRecorderInitTelemetry({ result: 'deflate-encoder-load-failed' }),\n      ])\n    })\n\n    it('stops recording if worker initialization fails', async () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit()\n      recorderApi.start()\n      expect(importRecorderSpy).toHaveBeenCalled()\n\n      await collectAsyncCalls(startRecordingSpy, 1)\n      mockWorker.dispatchErrorEvent()\n\n      expect(stopRecordingSpy).toHaveBeenCalled()\n    })\n\n    it('restarting the recording should not reset the worker action id', async () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit()\n      recorderApi.start()\n\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      const firstCallDeflateEncoder: DeflateEncoder = startRecordingSpy.calls.mostRecent().args[4]\n      firstCallDeflateEncoder.write('foo')\n\n      recorderApi.stop()\n      recorderApi.start()\n      await collectAsyncCalls(startRecordingSpy, 2)\n\n      const secondCallDeflateEncoder: DeflateEncoder = startRecordingSpy.calls.mostRecent().args[4]\n      secondCallDeflateEncoder.write('foo')\n\n      const writeMessages = mockWorker.pendingMessages.filter(\n        (message): message is Extract<DeflateWorkerAction, { action: 'write' }> => message.action === 'write'\n      )\n      expect(writeMessages.length).toBe(2)\n      expect(writeMessages[0].id).toBeLessThan(writeMessages[1].id)\n    })\n\n    describe('if event bridge present', () => {\n      it('should start recording when the bridge supports records', async () => {\n        mockEventBridge({ capabilities: [BridgeCapability.RECORDS] })\n\n        setupRecorderApi()\n        rumInit()\n        recorderApi.start()\n        await collectAsyncCalls(startRecordingSpy, 1)\n\n        expect(startRecordingSpy).toHaveBeenCalled()\n      })\n\n      it('should not start recording when the bridge does not support records', () => {\n        mockEventBridge({ capabilities: [] })\n\n        setupRecorderApi({ startSessionReplayRecordingManually: true })\n        rumInit()\n        recorderApi.start()\n\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n      })\n    })\n\n    describe('if browser is not supported', () => {\n      let originalArrayFrom: (typeof Array)['from']\n\n      beforeEach(() => {\n        originalArrayFrom = Array.from\n        delete (Array as any).from\n      })\n\n      afterEach(() => {\n        Array.from = originalArrayFrom\n      })\n\n      it('does not start recording', () => {\n        setupRecorderApi({ startSessionReplayRecordingManually: true })\n        recorderApi.start()\n        rumInit()\n        expect(importRecorderSpy).not.toHaveBeenCalled()\n        expect(startRecordingSpy).not.toHaveBeenCalled()\n      })\n    })\n  })\n\n  describe('recorder stop', () => {\n    it('ignores calls while recording is already stopped', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      recorderApi.stop()\n      recorderApi.stop()\n      recorderApi.stop()\n      expect(stopRecordingSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('prevents recording to start when the DOM is loaded', async () => {\n      setupRecorderApi()\n      const { triggerOnDomLoaded } = mockDocumentReadyState()\n      rumInit()\n      recorderApi.stop()\n      triggerOnDomLoaded()\n\n      await collectAsyncCalls(importRecorderSpy, 1)\n\n      expect(startRecordingSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('recorder lifecycle', () => {\n    let sessionManager: RumSessionManagerMock\n    beforeEach(() => {\n      sessionManager = createRumSessionManagerMock()\n      setupRecorderApi({ sessionManager })\n    })\n\n    describe('when session renewal change the tracking type', () => {\n      describe('from WITHOUT_REPLAY to WITH_REPLAY', () => {\n        beforeEach(() => {\n          sessionManager.setTrackedWithoutSessionReplay()\n        })\n\n        it('starts recording if startSessionReplayRecording was called', async () => {\n          rumInit()\n          sessionManager.setTrackedWithSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          await collectAsyncCalls(startRecordingSpy, 1)\n\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n\n        it('does not starts recording if stopSessionReplayRecording was called', () => {\n          rumInit()\n          recorderApi.stop()\n          sessionManager.setTrackedWithSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n          expect(importRecorderSpy).not.toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n\n      describe('from WITHOUT_REPLAY to untracked', () => {\n        beforeEach(() => {\n          sessionManager.setTrackedWithoutSessionReplay()\n        })\n\n        it('keeps not recording if startSessionReplayRecording was called', () => {\n          rumInit()\n          sessionManager.setNotTracked()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n          expect(importRecorderSpy).not.toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n\n      describe('from WITHOUT_REPLAY to WITHOUT_REPLAY', () => {\n        beforeEach(() => {\n          sessionManager.setTrackedWithoutSessionReplay()\n        })\n\n        it('keeps not recording if startSessionReplayRecording was called', () => {\n          rumInit()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n          expect(importRecorderSpy).not.toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n\n      describe('from WITH_REPLAY to WITHOUT_REPLAY', () => {\n        beforeEach(() => {\n          sessionManager.setTrackedWithSessionReplay()\n        })\n\n        it('stops recording if startSessionReplayRecording was called', async () => {\n          rumInit()\n          await collectAsyncCalls(startRecordingSpy, 1)\n\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n          sessionManager.setTrackedWithoutSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          expect(stopRecordingSpy).toHaveBeenCalled()\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          expect(importRecorderSpy).toHaveBeenCalledTimes(1)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n        })\n\n        // reassess this test\n        it('prevents session recording to start if the session is renewed before the DOM is loaded', () => {\n          const { triggerOnDomLoaded } = mockDocumentReadyState()\n          rumInit()\n          sessionManager.setTrackedWithoutSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          triggerOnDomLoaded()\n          expect(importRecorderSpy).toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n\n      describe('from WITH_REPLAY to untracked', () => {\n        beforeEach(() => {\n          sessionManager.setTrackedWithSessionReplay()\n        })\n\n        it('stops recording if startSessionReplayRecording was called', async () => {\n          rumInit()\n          await collectAsyncCalls(startRecordingSpy, 1)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n          sessionManager.setNotTracked()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          expect(stopRecordingSpy).toHaveBeenCalled()\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          expect(importRecorderSpy).toHaveBeenCalledTimes(1)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n        })\n      })\n\n      describe('from WITH_REPLAY to WITH_REPLAY', () => {\n        beforeEach(() => {\n          sessionManager.setTrackedWithSessionReplay()\n        })\n\n        it('keeps recording if startSessionReplayRecording was called', async () => {\n          rumInit()\n          await collectAsyncCalls(startRecordingSpy, 1)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          expect(stopRecordingSpy).toHaveBeenCalled()\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          await collectAsyncCalls(startRecordingSpy, 2)\n\n          expect(importRecorderSpy).toHaveBeenCalledTimes(2)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(2)\n        })\n\n        it('does not starts recording if stopSessionReplayRecording was called', async () => {\n          rumInit()\n          await collectAsyncCalls(startRecordingSpy, 1)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n          recorderApi.stop()\n          expect(stopRecordingSpy).toHaveBeenCalledTimes(1)\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          expect(importRecorderSpy).toHaveBeenCalledTimes(1)\n          expect(startRecordingSpy).toHaveBeenCalledTimes(1)\n          expect(stopRecordingSpy).toHaveBeenCalledTimes(1)\n        })\n      })\n\n      describe('from untracked to REPLAY', () => {\n        beforeEach(() => {\n          sessionManager.setNotTracked()\n        })\n\n        it('starts recording if startSessionReplayRecording was called', async () => {\n          rumInit()\n          sessionManager.setTrackedWithSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          await collectAsyncCalls(startRecordingSpy, 1)\n\n          expect(startRecordingSpy).toHaveBeenCalled()\n\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n\n        it('does not starts recording if stopSessionReplayRecording was called', () => {\n          rumInit()\n          recorderApi.stop()\n          sessionManager.setTrackedWithSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          expect(importRecorderSpy).not.toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n\n      describe('from untracked to WITHOUT_REPLAY', () => {\n        beforeEach(() => {\n          sessionManager.setNotTracked()\n        })\n\n        it('keeps not recording if startSessionReplayRecording was called', () => {\n          rumInit()\n          sessionManager.setTrackedWithoutSessionReplay()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          expect(importRecorderSpy).not.toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n\n      describe('from untracked to untracked', () => {\n        beforeEach(() => {\n          sessionManager.setNotTracked()\n        })\n\n        it('keeps not recording if startSessionReplayRecording was called', () => {\n          rumInit()\n          lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n          lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n          expect(importRecorderSpy).not.toHaveBeenCalled()\n          expect(startRecordingSpy).not.toHaveBeenCalled()\n          expect(stopRecordingSpy).not.toHaveBeenCalled()\n        })\n      })\n    })\n  })\n\n  describe('isRecording', () => {\n    it('is false when recording has not been started', () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit()\n\n      mockWorker.processAllMessages()\n\n      expect(recorderApi.isRecording()).toBeFalse()\n    })\n\n    it('is false when the worker is not yet initialized', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      expect(recorderApi.isRecording()).toBeFalse()\n    })\n\n    it('is false when the worker failed to initialize', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      mockWorker.dispatchErrorEvent()\n\n      expect(recorderApi.isRecording()).toBeFalse()\n    })\n\n    it('is true when recording is started and the worker is initialized', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      mockWorker.processAllMessages()\n\n      expect(recorderApi.isRecording()).toBeTrue()\n    })\n\n    it('is false before the DOM is loaded', async () => {\n      setupRecorderApi()\n      const { triggerOnDomLoaded } = mockDocumentReadyState()\n      rumInit()\n\n      recorderApi.start()\n\n      mockWorker.processAllMessages()\n\n      expect(recorderApi.isRecording()).toBeFalse()\n\n      triggerOnDomLoaded()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      mockWorker.processAllMessages()\n\n      expect(recorderApi.isRecording()).toBeTrue()\n    })\n  })\n\n  describe('getReplayStats', () => {\n    const VIEW_ID = 'xxx'\n\n    it('is undefined when recording has not been started', () => {\n      setupRecorderApi({ startSessionReplayRecordingManually: true })\n      rumInit()\n\n      replayStats.addSegment(VIEW_ID)\n      mockWorker.processAllMessages()\n\n      expect(recorderApi.getReplayStats(VIEW_ID)).toBeUndefined()\n    })\n\n    it('is undefined when the worker is not yet initialized', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      replayStats.addSegment(VIEW_ID)\n      expect(recorderApi.getReplayStats(VIEW_ID)).toBeUndefined()\n    })\n\n    it('is undefined when the worker failed to initialize', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      replayStats.addSegment(VIEW_ID)\n      mockWorker.dispatchErrorEvent()\n\n      expect(recorderApi.getReplayStats(VIEW_ID)).toBeUndefined()\n    })\n\n    it('is defined when recording is started and the worker is initialized', async () => {\n      setupRecorderApi()\n      rumInit()\n      await collectAsyncCalls(startRecordingSpy, 1)\n\n      replayStats.addSegment(VIEW_ID)\n      mockWorker.processAllMessages()\n\n      expect(recorderApi.getReplayStats(VIEW_ID)).toEqual({\n        records_count: 0,\n        segments_count: 1,\n        segments_total_raw_size: 0,\n      })\n    })\n  })\n})\n\nfunction expectedRecorderInitTelemetry(overrides: Partial<RecorderInitMetrics> = {}): RawTelemetryEvent {\n  return {\n    type: 'log',\n    status: 'debug',\n    message: 'Recorder init metrics',\n    metrics: {\n      forced: false,\n      loadRecorderModuleDuration: jasmine.any(Number),\n      recorderInitDuration: jasmine.any(Number),\n      result: 'succeeded',\n      waitForDocReadyDuration: jasmine.any(Number),\n      ...overrides,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/boot/recorderApi.ts",
    "content": "import type { DeflateEncoder, DeflateWorker, Telemetry } from '@datadog/browser-core'\nimport {\n  canUseEventBridge,\n  noop,\n  BridgeCapability,\n  bridgeSupports,\n  DeflateEncoderStreamId,\n} from '@datadog/browser-core'\nimport type {\n  LifeCycle,\n  ViewHistory,\n  RumSessionManager,\n  RecorderApi,\n  RumConfiguration,\n  StartRecordingOptions,\n} from '@datadog/browser-rum-core'\nimport { getReplayStats as getReplayStatsImpl } from '../domain/replayStats'\nimport {\n  createDeflateEncoder,\n  DeflateWorkerStatus,\n  getDeflateWorkerStatus,\n  startDeflateWorker,\n} from '../domain/deflate'\nimport { isBrowserSupported } from './isBrowserSupported'\nimport { createPostStartStrategy } from './postStartStrategy'\nimport { createPreStartStrategy } from './preStartStrategy'\n\nexport function makeRecorderApi(): RecorderApi {\n  if ((canUseEventBridge() && !bridgeSupports(BridgeCapability.RECORDS)) || !isBrowserSupported()) {\n    return {\n      start: noop,\n      stop: noop,\n      getReplayStats: () => undefined,\n      onRumStart: noop,\n      isRecording: () => false,\n      getSessionReplayLink: () => undefined,\n    }\n  }\n\n  // eslint-disable-next-line prefer-const\n  let { strategy, shouldStartImmediately } = createPreStartStrategy()\n\n  return {\n    start: (options?: StartRecordingOptions) => strategy.start(options),\n    stop: () => strategy.stop(),\n    getSessionReplayLink: () => strategy.getSessionReplayLink(),\n    onRumStart,\n    isRecording: () =>\n      // The worker is started optimistically, meaning we could have started to record but its\n      // initialization fails a bit later. This could happen when:\n      // * the worker URL (blob or plain URL) is blocked by CSP in Firefox only (Chromium and Safari\n      // throw an exception when instantiating the worker, and IE doesn't care about CSP)\n      // * the browser fails to load the worker in case the workerUrl is used\n      // * an unexpected error occurs in the Worker before initialization, ex:\n      //   * a runtime exception collected by monitor()\n      //   * a syntax error notified by the browser via an error event\n      // * the worker is unresponsive for some reason and timeouts\n      //\n      // It is not expected to happen often. Nonetheless, the \"replayable\" status on RUM events is\n      // an important part of the Datadog App:\n      // * If we have a false positive (we set has_replay: true even if no replay data is present),\n      // we might display broken links to the Session Replay player.\n      // * If we have a false negative (we don't set has_replay: true even if replay data is\n      // available), it is less noticeable because no link will be displayed.\n      //\n      // Thus, it is better to have false negative, so let's make sure the worker is correctly\n      // initialized before advertizing that we are recording.\n      //\n      // In the future, when the compression worker will also be used for RUM data, this will be\n      // less important since no RUM event will be sent when the worker fails to initialize.\n      getDeflateWorkerStatus() === DeflateWorkerStatus.Initialized && strategy.isRecording(),\n\n    getReplayStats: (viewId) =>\n      getDeflateWorkerStatus() === DeflateWorkerStatus.Initialized ? getReplayStatsImpl(viewId) : undefined,\n  }\n\n  function onRumStart(\n    lifeCycle: LifeCycle,\n    configuration: RumConfiguration,\n    sessionManager: RumSessionManager,\n    viewHistory: ViewHistory,\n    worker: DeflateWorker | undefined,\n    telemetry: Telemetry\n  ) {\n    let cachedDeflateEncoder: DeflateEncoder | undefined\n\n    function getOrCreateDeflateEncoder() {\n      if (!cachedDeflateEncoder) {\n        worker ??= startDeflateWorker(configuration, 'Datadog Session Replay', () => strategy.stop())\n\n        if (worker) {\n          cachedDeflateEncoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n        }\n      }\n      return cachedDeflateEncoder\n    }\n\n    strategy = createPostStartStrategy(\n      configuration,\n      lifeCycle,\n      sessionManager,\n      viewHistory,\n      getOrCreateDeflateEncoder,\n      telemetry\n    )\n\n    if (shouldStartImmediately(configuration)) {\n      strategy.start()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/boot/startRecording.spec.ts",
    "content": "import type { TimeStamp, HttpRequest, HttpRequestEvent, Telemetry } from '@datadog/browser-core'\nimport {\n  PageExitReason,\n  DefaultPrivacyLevel,\n  noop,\n  DeflateEncoderStreamId,\n  Observable,\n  ExperimentalFeature,\n  addExperimentalFeatures,\n} from '@datadog/browser-core'\nimport type { ViewCreatedEvent } from '@datadog/browser-rum-core'\nimport { LifeCycle, LifeCycleEventType, startViewHistory } from '@datadog/browser-rum-core'\nimport { collectAsyncCalls, createNewEvent, mockEventBridge, registerCleanupTask } from '@datadog/browser-core/test'\nimport type { ViewEndedEvent } from '../../../rum-core/src/domain/view/trackViews'\nimport type { RumSessionManagerMock } from '../../../rum-core/test'\nimport { appendElement, createRumSessionManagerMock, mockRumConfiguration } from '../../../rum-core/test'\n\nimport { recordsPerFullSnapshot, readReplayPayload } from '../../test'\nimport type { ReplayPayload } from '../domain/segmentCollection'\nimport { setSegmentBytesLimit } from '../domain/segmentCollection'\n\nimport { RecordType } from '../types'\nimport { createDeflateEncoder, resetDeflateWorkerState, startDeflateWorker } from '../domain/deflate'\nimport { startRecording } from './startRecording'\n\nconst VIEW_TIMESTAMP = 1 as TimeStamp\n\ndescribe('startRecording', () => {\n  const lifeCycle = new LifeCycle()\n  let sessionManager: RumSessionManagerMock\n  let viewId: string\n  let textField: HTMLInputElement\n  let requestSendSpy: jasmine.Spy<HttpRequest['sendOnExit']>\n  let stopRecording: () => void\n\n  function setupStartRecording() {\n    const configuration = mockRumConfiguration({ defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW })\n    const worker = startDeflateWorker(configuration, 'Session Replay', noop)\n\n    requestSendSpy = jasmine.createSpy()\n    const httpRequest = {\n      observable: new Observable<HttpRequestEvent<ReplayPayload>>(),\n      send: requestSendSpy,\n      sendOnExit: requestSendSpy,\n    }\n\n    const deflateEncoder = createDeflateEncoder(configuration, worker!, DeflateEncoderStreamId.REPLAY)\n    const viewHistory = startViewHistory(lifeCycle)\n    initialView(lifeCycle)\n\n    const mockTelemetry = { enabled: true, metricsEnabled: true } as Telemetry\n\n    const recording = startRecording(\n      lifeCycle,\n      configuration,\n      sessionManager,\n      viewHistory,\n      deflateEncoder,\n      mockTelemetry,\n      httpRequest\n    )\n    stopRecording = recording ? recording.stop : noop\n\n    registerCleanupTask(() => {\n      stopRecording()\n      deflateEncoder.stop()\n      setSegmentBytesLimit()\n      resetDeflateWorkerState()\n    })\n  }\n\n  beforeEach(() => {\n    sessionManager = createRumSessionManagerMock()\n    viewId = 'view-id'\n\n    textField = appendElement('<input />') as HTMLInputElement\n  })\n\n  it('sends recorded segments with valid context', async () => {\n    setupStartRecording()\n    flushSegment(lifeCycle)\n\n    const requests = await readSentRequests(1)\n    expect(requests[0].segment).toEqual(jasmine.any(Object))\n    expect(requests[0].event).toEqual({\n      application: {\n        id: 'appId',\n      },\n      creation_reason: 'init',\n      end: jasmine.stringMatching(/^\\d{13}$/),\n      has_full_snapshot: true,\n      records_count: recordsPerFullSnapshot(),\n      session: {\n        id: 'session-id',\n      },\n      start: jasmine.any(Number),\n      raw_segment_size: jasmine.any(Number),\n      compressed_segment_size: jasmine.any(Number),\n      view: {\n        id: 'view-id',\n      },\n      index_in_view: 0,\n      source: 'browser',\n    })\n  })\n\n  it('sends recorded segments with valid context when Change records are enabled', async () => {\n    addExperimentalFeatures([ExperimentalFeature.USE_CHANGE_RECORDS])\n    setupStartRecording()\n    flushSegment(lifeCycle)\n\n    const requests = await readSentRequests(1)\n    expect(requests[0].segment).toEqual(jasmine.any(Object))\n    expect(requests[0].event).toEqual({\n      application: {\n        id: 'appId',\n      },\n      creation_reason: 'init',\n      end: jasmine.stringMatching(/^\\d{13}$/),\n      has_full_snapshot: true,\n      records_count: recordsPerFullSnapshot(),\n      session: {\n        id: 'session-id',\n      },\n      start: jasmine.any(Number),\n      raw_segment_size: jasmine.any(Number),\n      compressed_segment_size: jasmine.any(Number),\n      view: {\n        id: 'view-id',\n      },\n      index_in_view: 0,\n      source: 'browser',\n    })\n  })\n\n  it('flushes the segment when its compressed data reaches the segment bytes limit', async () => {\n    setupStartRecording()\n    const inputCount = 150\n    const inputEvent = createNewEvent('input', { target: textField })\n    for (let i = 0; i < inputCount; i += 1) {\n      // Create a random value harder to deflate, so we don't have to send too many events to reach\n      // the limit.\n      textField.value = createRandomString(1000)\n      document.body.dispatchEvent(inputEvent)\n    }\n\n    const requests = await readSentRequests(1)\n    expect(requests[0].event.records_count).toBe(inputCount + recordsPerFullSnapshot())\n  })\n\n  it('stops sending new segment when the session is expired', async () => {\n    setupStartRecording()\n\n    document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n\n    sessionManager.setNotTracked()\n    flushSegment(lifeCycle)\n    document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n\n    flushSegment(lifeCycle)\n\n    const requests = await readSentRequests(1)\n    expect(requests[0].event.records_count).toBe(1 + recordsPerFullSnapshot())\n  })\n\n  it('restarts sending segments when the session is renewed', async () => {\n    sessionManager.setNotTracked()\n    setupStartRecording()\n\n    document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n\n    sessionManager.setId('new-session-id').setTrackedWithSessionReplay()\n    flushSegment(lifeCycle)\n    document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n\n    flushSegment(lifeCycle)\n\n    const requests = await readSentRequests(1)\n    expect(requests[0].event.records_count).toBe(1)\n    expect(requests[0].event.session.id).toBe('new-session-id')\n  })\n\n  it('flushes pending mutations before ending the view', async () => {\n    setupStartRecording()\n\n    appendElement('<hr/>')\n    changeView(lifeCycle)\n    flushSegment(lifeCycle)\n\n    const requests = await readSentRequests(2)\n    const firstSegment = requests[0].segment\n    expect(firstSegment.records[firstSegment.records.length - 2].type).toBe(RecordType.IncrementalSnapshot)\n    expect(firstSegment.records[firstSegment.records.length - 1].type).toBe(RecordType.ViewEnd)\n\n    const secondSegment = requests[1].segment\n    expect(secondSegment.records[0].type).toBe(RecordType.Meta)\n  })\n\n  it('flushes pending mutations before ending the view, even after the segment has been flushed', async () => {\n    setupStartRecording()\n\n    // flush segment right before the view change to set the segment collection in the waiting state\n    flushSegment(lifeCycle)\n    changeView(lifeCycle)\n    flushSegment(lifeCycle)\n\n    const requests = await readSentRequests(3)\n    const secondSegment = requests[1].segment\n\n    expect(secondSegment.records[0].type).toBe(RecordType.ViewEnd)\n  })\n\n  it('does not split Meta, Focus and FullSnapshot records between multiple segments when taking a full snapshot', async () => {\n    setSegmentBytesLimit(0)\n    setupStartRecording()\n\n    const requests = await readSentRequests(1)\n    expect(requests[0].segment.records[0].type).toBe(RecordType.Meta)\n    expect(requests[0].segment.records[1].type).toBe(RecordType.Focus)\n    expect(requests[0].segment.records[2].type).toBe(RecordType.FullSnapshot)\n  })\n\n  describe('when calling stop()', () => {\n    it('stops collecting records', async () => {\n      setupStartRecording()\n\n      document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n      stopRecording()\n      document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n      flushSegment(lifeCycle)\n\n      const requests = await readSentRequests(1)\n      expect(requests[0].event.records_count).toBe(1 + recordsPerFullSnapshot())\n    })\n\n    it('stops taking full snapshots on view creation', async () => {\n      setupStartRecording()\n\n      stopRecording()\n      changeView(lifeCycle)\n      flushSegment(lifeCycle)\n\n      const requests = await readSentRequests(1)\n      expect(requests[0].event.records_count).toBe(recordsPerFullSnapshot())\n    })\n  })\n\n  it('should send records through the bridge when it is present', () => {\n    const eventBridge = mockEventBridge()\n    setupStartRecording()\n    const sendSpy = spyOn(eventBridge, 'send')\n\n    // send click record\n    document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n\n    // send view end record and meta record\n    changeView(lifeCycle)\n\n    const record1 = JSON.parse(sendSpy.calls.argsFor(0)[0])\n    const record2 = JSON.parse(sendSpy.calls.argsFor(1)[0])\n    const record3 = JSON.parse(sendSpy.calls.argsFor(2)[0])\n\n    expect(record1).toEqual({\n      eventType: 'record',\n      event: jasmine.objectContaining({ type: RecordType.IncrementalSnapshot }),\n      view: { id: 'view-id' },\n    })\n\n    expect(record2).toEqual({\n      eventType: 'record',\n      event: jasmine.objectContaining({ type: RecordType.ViewEnd }),\n      view: { id: 'view-id' },\n    })\n\n    expect(record3).toEqual({\n      eventType: 'record',\n      event: jasmine.objectContaining({ type: RecordType.Meta }),\n      view: { id: 'view-id-2' },\n    })\n  })\n\n  function initialView(lifeCycle: LifeCycle) {\n    const viewCreatedEvent = { id: viewId, startClocks: { relative: 1, timeStamp: VIEW_TIMESTAMP } } as ViewCreatedEvent\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, viewCreatedEvent)\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, viewCreatedEvent)\n  }\n\n  function changeView(lifeCycle: LifeCycle) {\n    const viewEndedEvent = { endClocks: { relative: 2, timeStamp: 2 as TimeStamp } } as ViewEndedEvent\n    viewId = 'view-id-2'\n    const viewCreatedEvent = {\n      id: viewId,\n      startClocks: { relative: 1, timeStamp: VIEW_TIMESTAMP },\n    } as ViewCreatedEvent\n    lifeCycle.notify(LifeCycleEventType.VIEW_ENDED, viewEndedEvent)\n    lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, viewEndedEvent)\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, viewCreatedEvent)\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, viewCreatedEvent)\n  }\n\n  async function readSentRequests(expectedSentRequestCount: number) {\n    const calls = await collectAsyncCalls(requestSendSpy, expectedSentRequestCount)\n    return Promise.all(calls.all().map((call) => readReplayPayload(call.args[0])))\n  }\n})\n\nfunction flushSegment(lifeCycle: LifeCycle) {\n  lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.UNLOADING })\n}\n\nfunction createRandomString(minLength: number) {\n  let result = ''\n  while (result.length < minLength) {\n    result += Math.random().toString(36)\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/rum/src/boot/startRecording.ts",
    "content": "import type { RawError, HttpRequest, DeflateEncoder, Telemetry } from '@datadog/browser-core'\nimport { createHttpRequest, addTelemetryDebug, canUseEventBridge, noop } from '@datadog/browser-core'\nimport type { LifeCycle, ViewHistory, RumConfiguration, RumSessionManager } from '@datadog/browser-rum-core'\nimport { LifeCycleEventType } from '@datadog/browser-rum-core'\n\nimport type { SerializationStats } from '../domain/record'\nimport { record } from '../domain/record'\nimport type { ReplayPayload } from '../domain/segmentCollection'\nimport { startSegmentCollection, SEGMENT_BYTES_LIMIT, startSegmentTelemetry } from '../domain/segmentCollection'\nimport type { BrowserRecord } from '../types'\nimport { startRecordBridge } from '../domain/startRecordBridge'\n\nexport function startRecording(\n  lifeCycle: LifeCycle,\n  configuration: RumConfiguration,\n  sessionManager: RumSessionManager,\n  viewHistory: ViewHistory,\n  encoder: DeflateEncoder,\n  telemetry: Telemetry,\n  httpRequest?: HttpRequest<ReplayPayload>\n) {\n  const cleanupTasks: Array<() => void> = []\n\n  const reportError = (error: RawError) => {\n    lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, { error })\n    // monitor-until: forever, to keep an eye on the errors reported to customers\n    addTelemetryDebug('Error reported to customer', { 'error.message': error.message })\n  }\n\n  const replayRequest =\n    httpRequest || createHttpRequest([configuration.sessionReplayEndpointBuilder], reportError, SEGMENT_BYTES_LIMIT)\n\n  let addRecord: (record: BrowserRecord) => void\n  let addStats: (stats: SerializationStats) => void\n\n  if (!canUseEventBridge()) {\n    const segmentCollection = startSegmentCollection(\n      lifeCycle,\n      configuration,\n      sessionManager,\n      viewHistory,\n      replayRequest,\n      encoder\n    )\n    addRecord = segmentCollection.addRecord\n    addStats = segmentCollection.addStats\n    cleanupTasks.push(segmentCollection.stop)\n\n    const segmentTelemetry = startSegmentTelemetry(telemetry, replayRequest.observable)\n    cleanupTasks.push(segmentTelemetry.stop)\n  } else {\n    ;({ addRecord } = startRecordBridge(viewHistory))\n    addStats = noop\n  }\n\n  const { stop: stopRecording } = record({\n    emitRecord: addRecord,\n    emitStats: addStats,\n    configuration,\n    lifeCycle,\n    viewHistory,\n  })\n  cleanupTasks.push(stopRecording)\n\n  return {\n    stop: () => {\n      cleanupTasks.forEach((task) => task())\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/deflate/deflateEncoder.spec.ts",
    "content": "import type { EncoderResult, Uint8ArrayBuffer } from '@datadog/browser-core'\nimport { noop, DeflateEncoderStreamId } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { MockWorker } from '../../../test'\nimport { createDeflateEncoder } from './deflateEncoder'\n\nconst OTHER_STREAM_ID = 10 as DeflateEncoderStreamId\n\ndescribe('createDeflateEncoder', () => {\n  const configuration = {} as RumConfiguration\n  let worker: MockWorker\n\n  const ENCODED_FOO = [102, 111, 111]\n  const ENCODED_BAR = [98, 97, 114]\n  const TRAILER = [32]\n\n  beforeEach(() => {\n    worker = new MockWorker()\n  })\n\n  describe('write()', () => {\n    it('invokes write callbacks', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const writeCallbackSpy = jasmine.createSpy()\n      encoder.write('foo', writeCallbackSpy)\n      encoder.write('bar', writeCallbackSpy)\n\n      expect(writeCallbackSpy).not.toHaveBeenCalled()\n\n      worker.processAllMessages()\n\n      expect(writeCallbackSpy).toHaveBeenCalledTimes(2)\n      expect(writeCallbackSpy.calls.argsFor(0)).toEqual([3])\n      expect(writeCallbackSpy.calls.argsFor(1)).toEqual([3])\n    })\n\n    it('marks the encoder as not empty', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      encoder.write('foo')\n      expect(encoder.isEmpty).toBe(false)\n    })\n  })\n\n  describe('finish()', () => {\n    it('invokes the callback with the encoded data', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const finishCallbackSpy = jasmine.createSpy<(result: EncoderResult<Uint8ArrayBuffer>) => void>()\n      encoder.write('foo')\n      encoder.write('bar')\n      encoder.finish(finishCallbackSpy)\n\n      worker.processAllMessages()\n\n      expect(finishCallbackSpy).toHaveBeenCalledOnceWith({\n        output: new Uint8Array([...ENCODED_FOO, ...ENCODED_BAR, ...TRAILER]),\n        outputBytesCount: 7,\n        rawBytesCount: 6,\n        encoding: 'deflate',\n      })\n    })\n\n    it('invokes the callback even if nothing has been written', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const finishCallbackSpy = jasmine.createSpy<(result: EncoderResult<Uint8ArrayBuffer>) => void>()\n      encoder.finish(finishCallbackSpy)\n\n      expect(finishCallbackSpy).toHaveBeenCalledOnceWith({\n        output: new Uint8Array(0),\n        outputBytesCount: 0,\n        rawBytesCount: 0,\n        encoding: 'deflate',\n      })\n    })\n\n    it('cancels pending write callbacks', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const writeCallbackSpy = jasmine.createSpy()\n      encoder.write('foo', writeCallbackSpy)\n      encoder.write('bar', writeCallbackSpy)\n      encoder.finish(noop)\n\n      worker.processAllMessages()\n\n      expect(writeCallbackSpy).not.toHaveBeenCalled()\n    })\n\n    it('marks the encoder as empty', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      encoder.write('foo')\n      encoder.finish(noop)\n      expect(encoder.isEmpty).toBe(true)\n    })\n\n    it('supports calling finish() while another finish() call is pending', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const finishCallbackSpy = jasmine.createSpy<(result: EncoderResult<Uint8ArrayBuffer>) => void>()\n      encoder.write('foo')\n      encoder.finish(finishCallbackSpy)\n      encoder.write('bar')\n      encoder.finish(finishCallbackSpy)\n\n      worker.processAllMessages()\n\n      expect(finishCallbackSpy).toHaveBeenCalledTimes(2)\n      expect(finishCallbackSpy.calls.allArgs()).toEqual([\n        [\n          {\n            output: new Uint8Array([...ENCODED_FOO, ...TRAILER]),\n            outputBytesCount: 4,\n            rawBytesCount: 3,\n            encoding: 'deflate',\n          },\n        ],\n        [\n          {\n            output: new Uint8Array([...ENCODED_BAR, ...TRAILER]),\n            outputBytesCount: 4,\n            rawBytesCount: 3,\n            encoding: 'deflate',\n          },\n        ],\n      ])\n    })\n  })\n\n  describe('finishSync()', () => {\n    it('returns the encoded data up to this point and any pending data', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      encoder.write('foo')\n      encoder.write('bar')\n\n      worker.processNextMessage()\n\n      expect(encoder.finishSync()).toEqual({\n        output: new Uint8Array([...ENCODED_FOO, ...TRAILER]),\n        outputBytesCount: 4,\n        rawBytesCount: 3,\n        pendingData: 'bar',\n        encoding: 'deflate',\n      })\n    })\n\n    it('cancels pending write callbacks', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const writeCallbackSpy = jasmine.createSpy()\n      encoder.write('foo', writeCallbackSpy)\n      encoder.write('bar', writeCallbackSpy)\n      encoder.finishSync()\n\n      worker.processAllMessages()\n\n      expect(writeCallbackSpy).not.toHaveBeenCalled()\n    })\n\n    it('marks the encoder as empty', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      encoder.write('foo')\n      encoder.finishSync()\n      expect(encoder.isEmpty).toBe(true)\n    })\n\n    it('supports calling finishSync() while another finish() call is pending', () => {\n      const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n      const finishCallbackSpy = jasmine.createSpy<(result: EncoderResult<Uint8ArrayBuffer>) => void>()\n      encoder.write('foo')\n      encoder.finish(finishCallbackSpy)\n      encoder.write('bar')\n      expect(encoder.finishSync()).toEqual({\n        output: new Uint8Array(0),\n        outputBytesCount: 0,\n        rawBytesCount: 0,\n        pendingData: 'foobar',\n        encoding: 'deflate',\n      })\n\n      worker.processAllMessages()\n\n      expect(finishCallbackSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  it('ignores messages destined to other streams', () => {\n    // Let's assume another encoder is sending something to the worker\n    createDeflateEncoder(configuration, worker, OTHER_STREAM_ID).write('foo', noop)\n\n    const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n    const writeCallbackSpy = jasmine.createSpy()\n    encoder.write('foo', writeCallbackSpy)\n\n    // Process the first write action only\n    worker.processNextMessage()\n\n    expect(writeCallbackSpy).not.toHaveBeenCalled()\n  })\n\n  it('unsubscribes from the worker responses come out of order', () => {\n    const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n    encoder.write('foo', noop)\n    encoder.write('bar', noop)\n\n    worker.dropNextMessage() // drop the first write action\n    worker.processAllMessages()\n\n    expect(worker.messageListenersCount).toBe(0)\n  })\n\n  it('do not notify data twice when calling finishSync() then finish()', () => {\n    const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n    const finishCallbackSpy = jasmine.createSpy<(result: EncoderResult<Uint8ArrayBuffer>) => void>()\n\n    encoder.write('foo')\n    encoder.finishSync()\n\n    encoder.write('bar')\n    encoder.finish(finishCallbackSpy)\n\n    worker.processAllMessages()\n\n    expect(finishCallbackSpy).toHaveBeenCalledOnceWith({\n      rawBytesCount: 3,\n      output: new Uint8Array([...ENCODED_BAR, ...TRAILER]),\n      outputBytesCount: 4,\n      encoding: 'deflate',\n    })\n  })\n\n  it('do not notify data twice when calling finishSync() then finishSync()', () => {\n    const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n\n    encoder.write('foo')\n    encoder.finishSync()\n\n    encoder.write('bar')\n    expect(encoder.finishSync().pendingData).toBe('bar')\n  })\n\n  it('does not unsubscribe when there is no pending action', () => {\n    const encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n\n    encoder.write('foo')\n    encoder.finishSync()\n    worker.processAllMessages()\n\n    expect(worker.messageListenersCount).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/deflate/deflateEncoder.ts",
    "content": "import type {\n  DeflateWorkerResponse,\n  DeflateEncoder,\n  DeflateEncoderStreamId,\n  DeflateWorker,\n  EncoderResult,\n  Uint8ArrayBuffer,\n} from '@datadog/browser-core'\nimport { addEventListener, concatBuffers } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\n\nexport function createDeflateEncoder(\n  configuration: RumConfiguration,\n  worker: DeflateWorker,\n  streamId: DeflateEncoderStreamId\n): DeflateEncoder {\n  let rawBytesCount = 0\n  let compressedData: Uint8ArrayBuffer[] = []\n  let compressedDataTrailer: Uint8ArrayBuffer\n\n  let isEmpty = true\n  let nextWriteActionId = 0\n  const pendingWriteActions: Array<{\n    writeCallback?: (additionalEncodedBytesCount: number) => void\n    finishCallback?: () => void\n    id: number\n    data: string\n  }> = []\n\n  const { stop: removeMessageListener } = addEventListener(\n    configuration,\n    worker,\n    'message',\n    ({ data: workerResponse }: MessageEvent<DeflateWorkerResponse>) => {\n      if (workerResponse.type !== 'wrote' || (workerResponse.streamId as DeflateEncoderStreamId) !== streamId) {\n        return\n      }\n\n      const nextPendingAction = pendingWriteActions[0]\n      if (nextPendingAction) {\n        if (nextPendingAction.id === workerResponse.id) {\n          pendingWriteActions.shift()\n\n          rawBytesCount += workerResponse.additionalBytesCount\n          compressedData.push(workerResponse.result)\n          compressedDataTrailer = workerResponse.trailer\n\n          if (nextPendingAction.writeCallback) {\n            nextPendingAction.writeCallback(workerResponse.result.byteLength)\n          } else if (nextPendingAction.finishCallback) {\n            nextPendingAction.finishCallback()\n          }\n        } else if (nextPendingAction.id < workerResponse.id) {\n          // Worker responses received out of order\n          removeMessageListener()\n        }\n      }\n    }\n  )\n\n  function consumeResult(): EncoderResult<Uint8ArrayBuffer> {\n    const output =\n      compressedData.length === 0 ? new Uint8Array(0) : concatBuffers(compressedData.concat(compressedDataTrailer))\n    const result: EncoderResult<Uint8ArrayBuffer> = {\n      rawBytesCount,\n      output,\n      outputBytesCount: output.byteLength,\n      encoding: 'deflate',\n    }\n    rawBytesCount = 0\n    compressedData = []\n    return result\n  }\n\n  function sendResetIfNeeded() {\n    if (!isEmpty) {\n      worker.postMessage({\n        action: 'reset',\n        streamId,\n      })\n      isEmpty = true\n    }\n  }\n\n  return {\n    isAsync: true,\n\n    get isEmpty() {\n      return isEmpty\n    },\n\n    write(data, callback) {\n      worker.postMessage({\n        action: 'write',\n        id: nextWriteActionId,\n        data,\n        streamId,\n      })\n      pendingWriteActions.push({\n        id: nextWriteActionId,\n        writeCallback: callback,\n        data,\n      })\n      isEmpty = false\n      nextWriteActionId += 1\n    },\n\n    finish(callback) {\n      sendResetIfNeeded()\n\n      if (!pendingWriteActions.length) {\n        callback(consumeResult())\n      } else {\n        // Make sure we do not call any write callback\n        pendingWriteActions.forEach((pendingWriteAction) => {\n          delete pendingWriteAction.writeCallback\n        })\n\n        // Wait for the last action to finish before calling the finish callback\n        pendingWriteActions[pendingWriteActions.length - 1].finishCallback = () => callback(consumeResult())\n      }\n    },\n\n    finishSync() {\n      sendResetIfNeeded()\n      const pendingData = pendingWriteActions.map((pendingWriteAction) => pendingWriteAction.data).join('')\n      // Ignore all pending write actions responses from the worker\n      pendingWriteActions.length = 0\n      return { ...consumeResult(), pendingData }\n    },\n\n    estimateEncodedBytesCount(data) {\n      // This is a rough estimation of the data size once it'll be encoded by deflate. We observed\n      // that if it's the first chunk of data pushed to the stream, the ratio is lower (3-4), but\n      // after that the ratio is greater (10+). We chose 8 here, which (on average) seems to produce\n      // requests of the expected size.\n      return data.length / 8\n    },\n\n    stop() {\n      removeMessageListener()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/deflate/deflateWorker.spec.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport type { Clock, MockTelemetry } from '@datadog/browser-core/test'\nimport { mockClock, startMockTelemetry, replaceMockableWithSpy } from '@datadog/browser-core/test'\nimport { MockWorker } from '../../../test'\nimport type { CreateDeflateWorker } from './deflateWorker'\nimport {\n  startDeflateWorker,\n  resetDeflateWorkerState,\n  INITIALIZATION_TIME_OUT_DELAY,\n  createDeflateWorker,\n} from './deflateWorker'\n\n// Arbitrary stream ids used for tests\nconst TEST_STREAM_ID = 5\n\ndescribe('startDeflateWorker', () => {\n  let mockWorker: MockWorker\n  let createDeflateWorkerSpy: jasmine.Spy<CreateDeflateWorker>\n  let onInitializationFailureSpy: jasmine.Spy<() => void>\n\n  function startDeflateWorkerWithDefaults({\n    configuration = {},\n    source = 'Session Replay',\n  }: {\n    configuration?: Partial<RumConfiguration>\n    source?: string\n  } = {}) {\n    return startDeflateWorker(configuration as RumConfiguration, source, onInitializationFailureSpy)\n  }\n\n  beforeEach(() => {\n    mockWorker = new MockWorker()\n    onInitializationFailureSpy = jasmine.createSpy('onInitializationFailureSpy')\n    createDeflateWorkerSpy = replaceMockableWithSpy(createDeflateWorker).and.callFake(() => mockWorker)\n  })\n\n  afterEach(() => {\n    resetDeflateWorkerState()\n  })\n\n  it('creates a deflate worker', () => {\n    const worker = startDeflateWorkerWithDefaults()\n    expect(createDeflateWorkerSpy).toHaveBeenCalledTimes(1)\n    expect(worker).toBe(mockWorker)\n\n    mockWorker.processAllMessages()\n    expect(onInitializationFailureSpy).not.toHaveBeenCalled()\n  })\n\n  it('uses the previously created worker during loading', () => {\n    const worker1 = startDeflateWorkerWithDefaults()\n    const worker2 = startDeflateWorkerWithDefaults()\n    expect(createDeflateWorkerSpy).toHaveBeenCalledTimes(1)\n    expect(worker1).toBe(worker2)\n  })\n\n  it('uses the previously created worker once initialized', () => {\n    const worker1 = startDeflateWorkerWithDefaults()\n    mockWorker.processAllMessages()\n\n    const worker2 = startDeflateWorkerWithDefaults()\n    expect(createDeflateWorkerSpy).toHaveBeenCalledTimes(1)\n    expect(worker1).toBe(worker2)\n\n    mockWorker.processAllMessages()\n    expect(onInitializationFailureSpy).not.toHaveBeenCalled()\n  })\n\n  describe('worker CSP error', () => {\n    let telemetry: MockTelemetry\n    // mimic Chrome behavior\n    let CSP_ERROR: DOMException\n    let displaySpy: jasmine.Spy\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'error')\n      telemetry = startMockTelemetry()\n      CSP_ERROR = new DOMException(\n        \"Failed to construct 'Worker': Access to the script at 'blob:https://example.org/9aadbb61-effe-41ee-aa76-fc607053d642' is denied by the document's Content Security Policy.\"\n      )\n    })\n\n    describe('Chrome and Safari behavior: exception during worker creation', () => {\n      it('returns undefined when the worker creation throws an exception', () => {\n        createDeflateWorkerSpy.and.throwError(CSP_ERROR)\n        const worker = startDeflateWorkerWithDefaults()\n        expect(worker).toBeUndefined()\n      })\n\n      it('displays CSP instructions when the worker creation throws a CSP error', () => {\n        createDeflateWorkerSpy.and.throwError(CSP_ERROR)\n        startDeflateWorkerWithDefaults()\n        expect(displaySpy).toHaveBeenCalledWith(\n          jasmine.stringContaining('Please make sure CSP is correctly configured')\n        )\n      })\n\n      it('does not report CSP errors to telemetry', async () => {\n        createDeflateWorkerSpy.and.throwError(CSP_ERROR)\n        startDeflateWorkerWithDefaults()\n        expect(await telemetry.hasEvents()).toBe(false)\n      })\n\n      it('does not try to create a worker again after the creation failed', () => {\n        createDeflateWorkerSpy.and.throwError(CSP_ERROR)\n        startDeflateWorkerWithDefaults()\n        createDeflateWorkerSpy.calls.reset()\n        startDeflateWorkerWithDefaults()\n        expect(createDeflateWorkerSpy).not.toHaveBeenCalled()\n      })\n    })\n\n    describe('Firefox behavior: error during worker loading', () => {\n      it('displays ErrorEvent as CSP error', () => {\n        startDeflateWorkerWithDefaults()\n        mockWorker.dispatchErrorEvent()\n        expect(displaySpy).toHaveBeenCalledWith(\n          jasmine.stringContaining('Please make sure CSP is correctly configured')\n        )\n      })\n\n      it('calls the initialization failure callback when of an error occurs during loading', () => {\n        startDeflateWorkerWithDefaults()\n        mockWorker.dispatchErrorEvent()\n        expect(onInitializationFailureSpy).toHaveBeenCalledTimes(1)\n      })\n\n      it('returns undefined if an error occurred in a previous loading', () => {\n        startDeflateWorkerWithDefaults()\n        mockWorker.dispatchErrorEvent()\n        onInitializationFailureSpy.calls.reset()\n\n        const worker = startDeflateWorkerWithDefaults()\n\n        expect(worker).toBeUndefined()\n        expect(onInitializationFailureSpy).not.toHaveBeenCalled()\n      })\n\n      it('adjusts the error message when a workerUrl is set', () => {\n        startDeflateWorkerWithDefaults({\n          configuration: {\n            workerUrl: '/worker.js',\n          },\n        })\n        mockWorker.dispatchErrorEvent()\n        expect(displaySpy).toHaveBeenCalledWith(\n          jasmine.stringContaining(\n            'Please make sure the worker URL /worker.js is correct and CSP is correctly configured.'\n          )\n        )\n      })\n\n      it('calls all registered callbacks when the worker initialization fails', () => {\n        startDeflateWorkerWithDefaults()\n        startDeflateWorkerWithDefaults()\n        mockWorker.dispatchErrorEvent()\n        expect(onInitializationFailureSpy).toHaveBeenCalledTimes(2)\n      })\n    })\n  })\n\n  describe('initialization timeout', () => {\n    let displaySpy: jasmine.Spy\n    let clock: Clock\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'error')\n      createDeflateWorkerSpy.and.callFake(\n        () =>\n          // Creates a worker that does nothing\n          new Worker(URL.createObjectURL(new Blob([''])))\n      )\n      clock = mockClock()\n    })\n\n    it('displays an error message when the worker does not respond to the init action', () => {\n      startDeflateWorkerWithDefaults()\n      clock.tick(INITIALIZATION_TIME_OUT_DELAY)\n      expect(displaySpy).toHaveBeenCalledOnceWith(\n        'Session Replay failed to start: a timeout occurred while initializing the Worker'\n      )\n    })\n\n    it('displays a customized error message', () => {\n      startDeflateWorkerWithDefaults({ source: 'Foo' })\n      clock.tick(INITIALIZATION_TIME_OUT_DELAY)\n      expect(displaySpy).toHaveBeenCalledOnceWith(\n        'Foo failed to start: a timeout occurred while initializing the Worker'\n      )\n    })\n  })\n\n  describe('worker unknown error', () => {\n    let telemetry: MockTelemetry\n    const UNKNOWN_ERROR = new Error('boom')\n    let displaySpy: jasmine.Spy\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'error')\n      telemetry = startMockTelemetry()\n    })\n\n    it('displays an error message when the worker creation throws an unknown error', () => {\n      createDeflateWorkerSpy.and.throwError(UNKNOWN_ERROR)\n      startDeflateWorkerWithDefaults()\n      expect(displaySpy).toHaveBeenCalledOnceWith(\n        'Session Replay failed to start: an error occurred while initializing the worker:',\n        UNKNOWN_ERROR\n      )\n    })\n\n    it('displays a customized error message', () => {\n      createDeflateWorkerSpy.and.throwError(UNKNOWN_ERROR)\n      startDeflateWorkerWithDefaults({ source: 'Foo' })\n      expect(displaySpy).toHaveBeenCalledOnceWith(\n        'Foo failed to start: an error occurred while initializing the worker:',\n        UNKNOWN_ERROR\n      )\n    })\n\n    it('reports unknown errors to telemetry', async () => {\n      createDeflateWorkerSpy.and.throwError(UNKNOWN_ERROR)\n      startDeflateWorkerWithDefaults()\n      expect(await telemetry.getEvents()).toEqual([\n        {\n          type: 'log',\n          status: 'error',\n          message: 'boom',\n          error: { kind: 'Error', stack: jasmine.any(String) },\n        },\n      ])\n    })\n\n    it('does not display error messages as CSP error', () => {\n      startDeflateWorkerWithDefaults()\n      mockWorker.dispatchErrorMessage('foo')\n      expect(displaySpy).not.toHaveBeenCalledWith(jasmine.stringContaining('CSP'))\n    })\n\n    it('reports errors occurring after loading to telemetry', async () => {\n      startDeflateWorkerWithDefaults()\n      mockWorker.processAllMessages()\n\n      mockWorker.dispatchErrorMessage('boom', TEST_STREAM_ID)\n      expect(await telemetry.getEvents()).toEqual([\n        {\n          type: 'log',\n          status: 'error',\n          message: 'Uncaught \"boom\"',\n          error: { stack: jasmine.any(String) },\n          worker_version: 'dev',\n          stream_id: TEST_STREAM_ID,\n        },\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/deflate/deflateWorker.ts",
    "content": "import type { DeflateWorker, DeflateWorkerResponse } from '@datadog/browser-core'\nimport { addTelemetryError, display, addEventListener, setTimeout, ONE_SECOND, mockable } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { reportScriptLoadingError } from '../scriptLoadingError'\n\nexport const INITIALIZATION_TIME_OUT_DELAY = 30 * ONE_SECOND\n\ndeclare const __BUILD_ENV__WORKER_STRING__: string\n\n/**\n * In order to be sure that the worker is correctly working, we need a round trip of\n * initialization messages, making the creation asynchronous.\n * These worker lifecycle states handle this case.\n */\nexport const enum DeflateWorkerStatus {\n  Nil,\n  Loading,\n  Error,\n  Initialized,\n}\n\ntype DeflateWorkerState =\n  | {\n      status: DeflateWorkerStatus.Nil\n    }\n  | {\n      status: DeflateWorkerStatus.Loading\n      worker: DeflateWorker\n      stop: () => void\n      initializationFailureCallbacks: Array<() => void>\n    }\n  | {\n      status: DeflateWorkerStatus.Error\n    }\n  | {\n      status: DeflateWorkerStatus.Initialized\n      worker: DeflateWorker\n      stop: () => void\n      version: string\n    }\n\nexport type CreateDeflateWorker = typeof createDeflateWorker\n\nexport function createDeflateWorker(configuration: RumConfiguration): DeflateWorker {\n  return new Worker(configuration.workerUrl || URL.createObjectURL(new Blob([__BUILD_ENV__WORKER_STRING__])))\n}\n\nlet state: DeflateWorkerState = { status: DeflateWorkerStatus.Nil }\n\nexport function startDeflateWorker(\n  configuration: RumConfiguration,\n  source: string,\n  onInitializationFailure: () => void\n) {\n  if (state.status === DeflateWorkerStatus.Nil) {\n    // doStartDeflateWorker updates the state to \"loading\" or \"error\"\n    doStartDeflateWorker(configuration, source)\n  }\n\n  switch (state.status) {\n    case DeflateWorkerStatus.Loading:\n      state.initializationFailureCallbacks.push(onInitializationFailure)\n      return state.worker\n    case DeflateWorkerStatus.Initialized:\n      return state.worker\n  }\n}\n\nexport function resetDeflateWorkerState() {\n  if (state.status === DeflateWorkerStatus.Initialized || state.status === DeflateWorkerStatus.Loading) {\n    state.stop()\n  }\n  state = { status: DeflateWorkerStatus.Nil }\n}\n\nexport function getDeflateWorkerStatus() {\n  return state.status\n}\n\n/**\n * Starts the deflate worker and handle messages and errors\n *\n * The spec allow browsers to handle worker errors differently:\n * - Chromium throws an exception\n * - Firefox fires an error event\n *\n * more details: https://bugzilla.mozilla.org/show_bug.cgi?id=1736865#c2\n */\nexport function doStartDeflateWorker(configuration: RumConfiguration, source: string) {\n  try {\n    const worker = mockable(createDeflateWorker)(configuration)\n    const { stop: removeErrorListener } = addEventListener(configuration, worker, 'error', (error) => {\n      onError(configuration, source, error)\n    })\n    const { stop: removeMessageListener } = addEventListener(\n      configuration,\n      worker,\n      'message',\n      ({ data }: MessageEvent<DeflateWorkerResponse>) => {\n        if (data.type === 'errored') {\n          onError(configuration, source, data.error, data.streamId)\n        } else if (data.type === 'initialized') {\n          onInitialized(data.version)\n        }\n      }\n    )\n    worker.postMessage({ action: 'init' })\n    setTimeout(() => onTimeout(source), INITIALIZATION_TIME_OUT_DELAY)\n    const stop = () => {\n      removeErrorListener()\n      removeMessageListener()\n    }\n\n    state = { status: DeflateWorkerStatus.Loading, worker, stop, initializationFailureCallbacks: [] }\n  } catch (error) {\n    onError(configuration, source, error)\n  }\n}\n\nfunction onTimeout(source: string) {\n  if (state.status === DeflateWorkerStatus.Loading) {\n    display.error(`${source} failed to start: a timeout occurred while initializing the Worker`)\n    state.initializationFailureCallbacks.forEach((callback) => callback())\n    state = { status: DeflateWorkerStatus.Error }\n  }\n}\n\nfunction onInitialized(version: string) {\n  if (state.status === DeflateWorkerStatus.Loading) {\n    state = { status: DeflateWorkerStatus.Initialized, worker: state.worker, stop: state.stop, version }\n  }\n}\n\nfunction onError(configuration: RumConfiguration, source: string, error: unknown, streamId?: number) {\n  if (state.status === DeflateWorkerStatus.Loading || state.status === DeflateWorkerStatus.Nil) {\n    reportScriptLoadingError({\n      configuredUrl: configuration.workerUrl,\n      error,\n      source,\n      scriptType: 'worker',\n    })\n    if (state.status === DeflateWorkerStatus.Loading) {\n      state.initializationFailureCallbacks.forEach((callback) => callback())\n    }\n    state = { status: DeflateWorkerStatus.Error }\n  } else {\n    addTelemetryError(error, {\n      worker_version: state.status === DeflateWorkerStatus.Initialized && state.version,\n      stream_id: streamId,\n    })\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/deflate/index.ts",
    "content": "export { createDeflateEncoder } from './deflateEncoder'\nexport type { CreateDeflateWorker } from './deflateWorker'\nexport {\n  startDeflateWorker,\n  DeflateWorkerStatus,\n  getDeflateWorkerStatus,\n  resetDeflateWorkerState,\n  createDeflateWorker,\n} from './deflateWorker'\n"
  },
  {
    "path": "packages/rum/src/domain/getSessionReplayLink.spec.ts",
    "content": "import type { RumConfiguration, ViewHistory } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport { createRumSessionManagerMock } from '../../../rum-core/test'\nimport { getSessionReplayLink } from './getSessionReplayLink'\nimport { addRecord } from './replayStats'\n\nconst DEFAULT_CONFIGURATION = {\n  site: 'datadoghq.com',\n} as RumConfiguration\n\ndescribe('getReplayLink', () => {\n  it('should return url without query param if no view', () => {\n    const sessionManager = createRumSessionManagerMock().setId('session-id-1')\n    const viewHistory = { findView: () => undefined } as ViewHistory\n\n    const link = getSessionReplayLink(DEFAULT_CONFIGURATION, sessionManager, viewHistory, true)\n\n    expect(link).toBe('https://app.datadoghq.com/rum/replay/sessions/session-id-1?')\n  })\n\n  it('should return the replay link', () => {\n    const sessionManager = createRumSessionManagerMock().setId('session-id-1')\n    const viewHistory = {\n      findView: () => ({\n        id: 'view-id-1',\n        startClocks: {\n          timeStamp: 123456,\n        },\n      }),\n    } as ViewHistory\n    addRecord('view-id-1')\n\n    const link = getSessionReplayLink(\n      { ...DEFAULT_CONFIGURATION, subdomain: 'toto' },\n      sessionManager,\n      viewHistory,\n      true\n    )\n\n    expect(link).toBe('https://toto.datadoghq.com/rum/replay/sessions/session-id-1?seed=view-id-1&from=123456')\n  })\n\n  it('should return link when replay is forced', () => {\n    const sessionManager = createRumSessionManagerMock()\n      .setId('session-id-1')\n      .setTrackedWithoutSessionReplay()\n      .setForcedReplay()\n\n    const viewHistory = {\n      findView: () => ({\n        id: 'view-id-1',\n        startClocks: {\n          timeStamp: 123456,\n        },\n      }),\n    } as ViewHistory\n    addRecord('view-id-1')\n\n    const link = getSessionReplayLink(\n      { ...DEFAULT_CONFIGURATION, subdomain: 'toto' },\n      sessionManager,\n      viewHistory,\n      true\n    )\n\n    expect(link).toBe('https://toto.datadoghq.com/rum/replay/sessions/session-id-1?seed=view-id-1&from=123456')\n  })\n\n  it('return a param if replay is sampled out', () => {\n    const sessionManager = createRumSessionManagerMock().setId('session-id-1').setTrackedWithoutSessionReplay()\n    const viewHistory = {\n      findView: () => ({\n        id: 'view-id-1',\n        startClocks: {\n          timeStamp: 123456,\n        },\n      }),\n    } as ViewHistory\n\n    const link = getSessionReplayLink(DEFAULT_CONFIGURATION, sessionManager, viewHistory, true)\n    expect(link).toBe(\n      'https://app.datadoghq.com/rum/replay/sessions/session-id-1?error-type=incorrect-session-plan&seed=view-id-1&from=123456'\n    )\n  })\n\n  it('return a param if rum is sampled out', () => {\n    const sessionManager = createRumSessionManagerMock().setNotTracked()\n    const viewHistory = {\n      findView: () => undefined,\n    } as ViewHistory\n\n    const link = getSessionReplayLink(DEFAULT_CONFIGURATION, sessionManager, viewHistory, true)\n\n    expect(link).toBe('https://app.datadoghq.com/rum/replay/sessions/no-session-id?error-type=rum-not-tracked')\n  })\n\n  it('should add a param if the replay was not started', () => {\n    const sessionManager = createRumSessionManagerMock().setId('session-id-1')\n    const viewHistory = {\n      findView: () => ({\n        id: 'view-id-1',\n        startClocks: {\n          timeStamp: 123456,\n        },\n      }),\n    } as ViewHistory\n\n    const link = getSessionReplayLink(DEFAULT_CONFIGURATION, sessionManager, viewHistory, false)\n\n    expect(link).toBe(\n      'https://app.datadoghq.com/rum/replay/sessions/session-id-1?error-type=replay-not-started&seed=view-id-1&from=123456'\n    )\n  })\n\n  describe('browser not supported', () => {\n    beforeEach(() => {\n      // browser support function rely on Array.from being a function.\n      const original = Array.from\n      Array.from = undefined as any\n\n      registerCleanupTask(() => {\n        Array.from = original\n      })\n    })\n\n    it('should add a param if the browser is not supported', () => {\n      const sessionManager = createRumSessionManagerMock().setId('session-id-1')\n      const viewContexts = {\n        findView: () => ({\n          id: 'view-id-1',\n          startClocks: {\n            timeStamp: 123456,\n          },\n        }),\n      } as ViewHistory\n\n      const link = getSessionReplayLink(DEFAULT_CONFIGURATION, sessionManager, viewContexts, false)\n\n      expect(link).toBe(\n        'https://app.datadoghq.com/rum/replay/sessions/session-id-1?error-type=browser-not-supported&seed=view-id-1&from=123456'\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/getSessionReplayLink.ts",
    "content": "import type { RumConfiguration, RumSessionManager, ViewHistory, RumSession } from '@datadog/browser-rum-core'\nimport { getSessionReplayUrl, SessionReplayState } from '@datadog/browser-rum-core'\nimport { isBrowserSupported } from '../boot/isBrowserSupported'\n\nexport function getSessionReplayLink(\n  configuration: RumConfiguration,\n  sessionManager: RumSessionManager,\n  viewHistory: ViewHistory,\n  isRecordingStarted: boolean\n): string | undefined {\n  const session = sessionManager.findTrackedSession()\n  const errorType = getErrorType(session, isRecordingStarted)\n  const viewContext = viewHistory.findView()\n\n  return getSessionReplayUrl(configuration, {\n    viewContext,\n    errorType,\n    session,\n  })\n}\n\nfunction getErrorType(session: RumSession | undefined, isRecordingStarted: boolean) {\n  if (!isBrowserSupported()) {\n    return 'browser-not-supported'\n  }\n  if (!session) {\n    // possibilities:\n    // - rum sampled out\n    // - session expired (edge case)\n    return 'rum-not-tracked'\n  }\n  if (session.sessionReplay === SessionReplayState.OFF) {\n    // possibilities\n    // - replay sampled out\n    return 'incorrect-session-plan'\n  }\n  if (!isRecordingStarted) {\n    return 'replay-not-started'\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/actionHistory.spec.ts",
    "content": "import { noop, relativeToClocks, type Duration, type RelativeTime } from '@datadog/browser-core'\nimport { LifeCycle, LifeCycleEventType, RumEventType } from '@datadog/browser-rum-core'\nimport { createRawRumEvent } from '@datadog/browser-rum-core/test'\nimport { createActionHistory } from './actionHistory'\n\ndescribe('actionHistory', () => {\n  let lifeCycle: LifeCycle\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n  })\n\n  const fakeDomainContext = {\n    performanceEntry: {} as PerformanceEntry,\n  }\n\n  describe('createActionHistory', () => {\n    it('should create a history', () => {\n      const history = createActionHistory(lifeCycle)\n      expect(history).toBeDefined()\n    })\n\n    it('should add action information to history when RAW_RUM_EVENT_COLLECTED is triggered with action event', () => {\n      const history = createActionHistory(lifeCycle)\n      const startClocks = relativeToClocks(10 as RelativeTime)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-123',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks,\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(5 as RelativeTime, 30 as RelativeTime)).toEqual([\n        {\n          id: 'action-123',\n          label: '',\n          startClocks,\n          duration: 20 as Duration,\n        },\n      ])\n    })\n\n    it('should not add events to history for non-action events', () => {\n      const history = createActionHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW, {\n          view: {\n            id: 'view-123',\n          },\n        }),\n        startClocks: relativeToClocks(50 as RelativeTime),\n        duration: 10 as Duration,\n        domainContext: { location: window.location },\n      })\n\n      expect(history.findAll(40 as RelativeTime, 30 as RelativeTime)).toEqual([])\n    })\n\n    it('should store multiple action IDs with their time ranges', () => {\n      const history = createActionHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-1',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-2',\n            duration: 30 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(50 as RelativeTime),\n        duration: 30 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(5 as RelativeTime, 30 as RelativeTime).map((action) => action.id)).toEqual(['action-1'])\n      expect(history.findAll(45 as RelativeTime, 40 as RelativeTime).map((action) => action.id)).toEqual(['action-2'])\n      expect(history.findAll(0 as RelativeTime, 100 as RelativeTime).map((action) => action.id)).toEqual([\n        'action-2',\n        'action-1',\n      ])\n    })\n\n    it('should handle overlapping action time ranges', () => {\n      const history = createActionHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-1',\n            duration: 40 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 40 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-2',\n            duration: 40 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(30 as RelativeTime),\n        duration: 40 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(35 as RelativeTime, 20 as RelativeTime).map((action) => action.id)).toEqual([\n        'action-2',\n        'action-1',\n      ])\n    })\n\n    it('should add a action to the history with duration 0 when ACTION_STARTED is triggered', () => {\n      const history = createActionHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.ACTION_STARTED, {\n        key: 'action-1',\n        id: 'action-1',\n        data: { name: 'action-1' },\n        startClocks: relativeToClocks(10 as RelativeTime),\n        historyEntry: {\n          startTime: 10 as RelativeTime,\n          endTime: 10 as RelativeTime,\n          value: 'action-1',\n          remove: noop,\n          close: noop,\n        },\n      })\n\n      const matchingActions = history.findAll(10 as RelativeTime, 10 as RelativeTime)\n\n      expect(matchingActions[0].id).toEqual('action-1')\n      expect(matchingActions[0].duration).toBeUndefined()\n    })\n\n    it('should add a action to the history when ACTION_STARTED is triggered, and close it when RAW_RUM_EVENT_COLLECTED is triggered', () => {\n      const history = createActionHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.ACTION_STARTED, {\n        key: 'action-1',\n        id: 'action-1',\n        data: { name: 'action-1' },\n        startClocks: relativeToClocks(10 as RelativeTime),\n        historyEntry: {\n          startTime: 10 as RelativeTime,\n          endTime: 10 as RelativeTime,\n          value: 'action-1',\n          remove: noop,\n          close: noop,\n        },\n      })\n\n      expect(history.findAll(10 as RelativeTime, 10 as RelativeTime).map((action) => action.id)).toEqual(['action-1'])\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-1',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      const matchingActions = history.findAll(10 as RelativeTime, 30 as RelativeTime)\n\n      expect(matchingActions[0].id).toEqual('action-1')\n      expect(matchingActions[0].duration).toEqual(20 as Duration)\n    })\n\n    it('should be able to handle multiple actions being started and stopped', () => {\n      const history = createActionHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.ACTION_STARTED, {\n        key: 'action-1',\n        id: 'action-1',\n        data: { name: 'action-1' },\n        startClocks: relativeToClocks(10 as RelativeTime),\n        historyEntry: {\n          startTime: 10 as RelativeTime,\n          endTime: 10 as RelativeTime,\n          value: 'action-1',\n          remove: noop,\n          close: noop,\n        },\n      })\n\n      lifeCycle.notify(LifeCycleEventType.ACTION_STARTED, {\n        key: 'action-2',\n        id: 'action-2',\n        data: { name: 'action-2' },\n        startClocks: relativeToClocks(10 as RelativeTime),\n        historyEntry: {\n          startTime: 10 as RelativeTime,\n          endTime: 10 as RelativeTime,\n          value: 'action-2',\n          remove: noop,\n          close: noop,\n        },\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-2',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      let matchingActions = history.findAll(10 as RelativeTime, 30 as RelativeTime)\n\n      expect(matchingActions.map((action) => action.id)).toEqual(['action-2', 'action-1'])\n\n      expect(matchingActions.map((action) => action.duration)).toEqual([20 as Duration, undefined])\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          action: {\n            id: 'action-1',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      matchingActions = history.findAll(10 as RelativeTime, 30 as RelativeTime)\n\n      expect(matchingActions.map((action) => action.id)).toEqual(['action-2', 'action-1'])\n\n      expect(matchingActions.map((action) => action.duration)).toEqual([20 as Duration, 20 as Duration])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/actionHistory.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport { addDuration, createValueHistory, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core'\nimport type { LifeCycle } from '@datadog/browser-rum-core'\nimport { LifeCycleEventType } from '@datadog/browser-rum-core'\n\nexport const ACTION_ID_HISTORY_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY\n\nexport interface ActionContext {\n  id: string\n  label: string\n  duration?: Duration\n  startClocks: ClocksState\n}\n\nexport function createActionHistory(lifeCycle: LifeCycle) {\n  const history = createValueHistory<ActionContext>({\n    expireDelay: ACTION_ID_HISTORY_TIME_OUT_DELAY,\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.ACTION_STARTED, (actionStart) => {\n    history.add(\n      {\n        id: actionStart.id,\n        // The label is temporarily empty since we need to account for customers that might\n        // redact the action name in the beforeSend callback. We will either try to do patch this\n        // behavior, or remove the label field entirely.\n        label: '',\n        startClocks: actionStart.startClocks,\n        duration: undefined,\n      },\n      actionStart.startClocks.relative\n    )\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, ({ rawRumEvent, startClocks, duration }) => {\n    if (rawRumEvent.type === 'action') {\n      const historyEntry = history\n        .getEntries(startClocks.relative)\n        .find((entry) => entry.value.id === rawRumEvent.action.id)\n      const durationForEntry = duration ?? (0 as Duration)\n\n      if (historyEntry) {\n        historyEntry.value.duration = durationForEntry\n        historyEntry.close(addDuration(startClocks.relative, durationForEntry))\n      } else {\n        history\n          .add(\n            {\n              id: rawRumEvent.action.id,\n              // The label is temporarily empty since we need to account for customers that might\n              // redact the action name in the beforeSend callback. We will either try to do patch this\n              // behavior, or remove the label field entirely.\n              label: '',\n              startClocks,\n              duration,\n            },\n            startClocks.relative\n          )\n          .close(addDuration(startClocks.relative, durationForEntry))\n      }\n    }\n  })\n\n  return history\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/longTaskHistory.spec.ts",
    "content": "import { relativeToClocks, type Duration, type RelativeTime } from '@datadog/browser-core'\nimport { LifeCycle, LifeCycleEventType, RumEventType, RumPerformanceEntryType } from '@datadog/browser-rum-core'\nimport { createRawRumEvent } from '@datadog/browser-rum-core/test'\nimport { createLongTaskHistory } from './longTaskHistory'\n\ndescribe('longTaskHistory', () => {\n  let lifeCycle: LifeCycle\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n  })\n\n  const fakeDomainContext = {\n    performanceEntry: {} as PerformanceEntry,\n  }\n\n  describe('createLongTaskHistory', () => {\n    it('should create a history with the correct expire delay', () => {\n      const history = createLongTaskHistory(lifeCycle)\n      expect(history).toBeDefined()\n    })\n\n    it('should add long task IDs to history when RAW_RUM_EVENT_COLLECTED is triggered with long_task event', () => {\n      const history = createLongTaskHistory(lifeCycle)\n\n      const startClocks = relativeToClocks(10 as RelativeTime)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n          long_task: {\n            id: 'long-task-123',\n          },\n        }),\n        startClocks,\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(5 as RelativeTime, 30 as RelativeTime)).toEqual([\n        {\n          id: 'long-task-123',\n          startClocks,\n          duration: 20 as Duration,\n          entryType: RumPerformanceEntryType.LONG_TASK,\n        },\n      ])\n    })\n\n    it('should not add events to history for non-long_task events', () => {\n      const history = createLongTaskHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW, {\n          view: {\n            id: 'view-123',\n          },\n        }),\n        startClocks: relativeToClocks(50 as RelativeTime),\n        duration: 10 as Duration,\n        domainContext: { location: window.location },\n      })\n\n      expect(history.findAll(40 as RelativeTime, 30 as RelativeTime)).toEqual([])\n    })\n\n    it('should store multiple long task IDs with their time ranges', () => {\n      const history = createLongTaskHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n          long_task: {\n            id: 'long-task-1',\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n          long_task: {\n            id: 'long-task-2',\n          },\n        }),\n        startClocks: relativeToClocks(50 as RelativeTime),\n        duration: 30 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(5 as RelativeTime, 30 as RelativeTime).map((longTask) => longTask.id)).toEqual([\n        'long-task-1',\n      ])\n      expect(history.findAll(45 as RelativeTime, 40 as RelativeTime).map((longTask) => longTask.id)).toEqual([\n        'long-task-2',\n      ])\n      expect(history.findAll(0 as RelativeTime, 100 as RelativeTime).map((longTask) => longTask.id)).toEqual([\n        'long-task-2',\n        'long-task-1',\n      ])\n    })\n\n    it('should handle overlapping long task time ranges', () => {\n      const history = createLongTaskHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n          long_task: {\n            id: 'long-task-1',\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 40 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n          long_task: {\n            id: 'long-task-2',\n          },\n        }),\n        startClocks: relativeToClocks(30 as RelativeTime),\n        duration: 40 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(35 as RelativeTime, 20 as RelativeTime).map((longTask) => longTask.id)).toEqual([\n        'long-task-2',\n        'long-task-1',\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/longTaskHistory.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport { addDuration, createValueHistory, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core'\nimport type { LifeCycle } from '@datadog/browser-rum-core'\nimport { RumPerformanceEntryType, LifeCycleEventType, RumLongTaskEntryType } from '@datadog/browser-rum-core'\n\nexport const LONG_TASK_ID_HISTORY_EXPIRE_DELAY = SESSION_TIME_OUT_DELAY\n\nexport interface LongTaskContext {\n  id: string\n  startClocks: ClocksState\n  duration: Duration\n  entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME | RumPerformanceEntryType.LONG_TASK\n}\n\nexport function createLongTaskHistory(lifeCycle: LifeCycle) {\n  const history = createValueHistory<LongTaskContext>({\n    expireDelay: LONG_TASK_ID_HISTORY_EXPIRE_DELAY,\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, ({ rawRumEvent, startClocks, duration }) => {\n    if (rawRumEvent.type === 'long_task') {\n      history\n        .add(\n          {\n            id: rawRumEvent.long_task.id,\n            startClocks,\n            duration: duration!,\n            entryType:\n              rawRumEvent.long_task.entry_type === RumLongTaskEntryType.LONG_TASK\n                ? RumPerformanceEntryType.LONG_TASK\n                : RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n          },\n          startClocks.relative\n        )\n        .close(addDuration(startClocks.relative, duration!))\n    }\n  })\n\n  return history\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/profiler.spec.ts",
    "content": "import type { ViewHistoryEntry } from '@datadog/browser-rum-core'\nimport { LifeCycle, LifeCycleEventType, RumPerformanceEntryType, createHooks } from '@datadog/browser-rum-core'\nimport type { Duration } from '@datadog/browser-core'\nimport {\n  addDuration,\n  clocksNow,\n  clocksOrigin,\n  createIdentityEncoder,\n  createValueHistory,\n  deepClone,\n  ONE_DAY,\n  relativeNow,\n  timeStampNow,\n} from '@datadog/browser-core'\nimport {\n  setPageVisibility,\n  restorePageVisibility,\n  createNewEvent,\n  interceptRequests,\n  DEFAULT_FETCH_MOCK,\n  readFormDataRequest,\n  mockClock,\n  waitNextMicrotask,\n  replaceMockable,\n} from '@datadog/browser-core/test'\nimport { createRumSessionManagerMock, mockRumConfiguration, mockViewHistory } from '../../../../rum-core/test'\nimport { mockProfiler } from '../../../test'\nimport type { BrowserProfilerTrace } from '../../types'\nimport { mockedTrace } from './test-utils/mockedTrace'\nimport { createRumProfiler } from './profiler'\nimport type { ProfilerTrace } from './types'\nimport type { ProfilingContextManager } from './profilingContext'\nimport { startProfilingContext } from './profilingContext'\nimport type { ProfileEventPayload } from './transport/assembly'\nimport { createLongTaskHistory, type LongTaskContext } from './longTaskHistory'\nimport type { ActionContext } from './actionHistory'\nimport { createActionHistory } from './actionHistory'\nimport type { VitalContext } from './vitalHistory'\nimport { createVitalHistory } from './vitalHistory'\n\ndescribe('profiler', () => {\n  // Store the original pathname\n  const originalPathname = document.location.pathname\n  let interceptor: ReturnType<typeof interceptRequests>\n\n  beforeEach(() => {\n    interceptor = interceptRequests()\n    interceptor.withFetch(DEFAULT_FETCH_MOCK, DEFAULT_FETCH_MOCK, DEFAULT_FETCH_MOCK)\n  })\n\n  afterEach(() => {\n    restorePageVisibility()\n    // Go back to the original pathname\n    history.pushState({}, '', originalPathname)\n  })\n\n  let lifeCycle = new LifeCycle()\n\n  function setupProfiler(currentView?: ViewHistoryEntry) {\n    const sessionManager = createRumSessionManagerMock().setId('session-id-1')\n    lifeCycle = new LifeCycle()\n    const hooks = createHooks()\n    const profilingContextManager: ProfilingContextManager = startProfilingContext(hooks)\n\n    const mockProfilerTrace: ProfilerTrace = deepClone(mockedTrace)\n\n    const mockedRumProfilerTrace: BrowserProfilerTrace = Object.assign(mockProfilerTrace, {\n      startClocks: {\n        relative: relativeNow(),\n        timeStamp: timeStampNow(),\n      },\n      endClocks: {\n        relative: relativeNow(),\n        timeStamp: timeStampNow(),\n      },\n      clocksOrigin: clocksOrigin(),\n      sampleInterval: 10,\n      longTasks: [],\n      views: [],\n      actions: [],\n      vitals: [],\n    })\n\n    const viewHistory = mockViewHistory(\n      currentView ?? {\n        id: 'view-id-1',\n        name: 'view-name-1',\n        startClocks: {\n          relative: relativeNow(),\n          timeStamp: timeStampNow(),\n        },\n      }\n    )\n\n    // Replace Browser's Profiler with a mock for testing purpose.\n    mockProfiler(mockProfilerTrace)\n\n    const longTaskHistory = createValueHistory<LongTaskContext>({\n      expireDelay: ONE_DAY,\n    })\n    replaceMockable(createLongTaskHistory, () => longTaskHistory)\n\n    const actionHistory = createValueHistory<ActionContext>({\n      expireDelay: ONE_DAY,\n    })\n    replaceMockable(createActionHistory, () => actionHistory)\n\n    const vitalHistory = createValueHistory<VitalContext>({\n      expireDelay: ONE_DAY,\n    })\n    replaceMockable(createVitalHistory, () => vitalHistory)\n\n    // Start collection of profile.\n    const profiler = createRumProfiler(\n      mockRumConfiguration({ trackLongTasks: true, profilingSampleRate: 100 }),\n      lifeCycle,\n      sessionManager,\n      profilingContextManager,\n      createIdentityEncoder,\n      viewHistory,\n      // Overrides default configuration for testing purpose.\n      {\n        sampleIntervalMs: 10,\n        collectIntervalMs: 60000, // 1min\n        minNumberOfSamples: 0,\n        minProfileDurationMs: 0,\n      }\n    )\n    return {\n      profiler,\n      profilingContextManager,\n      mockedRumProfilerTrace,\n      addLongTask: (longTask: LongTaskContext) => {\n        longTaskHistory.add(longTask, relativeNow()).close(addDuration(relativeNow(), longTask.duration))\n      },\n      addAction: (action: ActionContext) => {\n        actionHistory.add(action, relativeNow()).close(addDuration(relativeNow(), action.duration ?? (0 as Duration)))\n      },\n      addVital: (vital: VitalContext) => {\n        vitalHistory.add(vital, relativeNow()).close(addDuration(relativeNow(), vital.duration ?? (0 as Duration)))\n      },\n    }\n  }\n\n  it('should start profiling collection and collect data on stop', async () => {\n    const { profiler, profilingContextManager, mockedRumProfilerTrace } = setupProfiler()\n\n    expect(profilingContextManager.get()?.status).toBe('starting')\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Stop collection of profile (sync - state changes immediately)\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n\n    expect(interceptor.requests.length).toBe(1)\n\n    const request = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    expect(request.event.session?.id).toBe('session-id-1')\n    expect(request['wall-time.json']).toEqual(mockedRumProfilerTrace)\n  })\n\n  it('should pause profiling collection on hidden visibility and restart on visible visibility', async () => {\n    const { profiler, profilingContextManager, mockedRumProfilerTrace } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Emulate visibility change to `hidden` state\n    setVisibilityState('hidden')\n\n    // Wait for profiler to pause\n    await waitForBoolean(() => profiler.isPaused())\n\n    // From an external point of view, the profiler is still running, but it's not collecting data.\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n\n    // Assert that the profiler has collected data on pause.\n    expect(interceptor.requests.length).toBe(1)\n\n    // Change back to visible\n    setVisibilityState('visible')\n    document.dispatchEvent(new Event('visibilitychange'))\n\n    // Wait for profiler to restart\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Stop collection of profile (sync - state changes immediately)\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 2)\n\n    expect(interceptor.requests.length).toBe(2)\n\n    // Check the the sendProfilesSpy was called with the mocked trace\n    const request = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[1])\n\n    expect(request.event.session?.id).toBe('session-id-1')\n    expect(request['wall-time.json']).toEqual(mockedRumProfilerTrace)\n  })\n\n  it('should collect long task happening during a profiling session', async () => {\n    const clock = mockClock()\n    const { profiler, profilingContextManager, addLongTask } = setupProfiler()\n\n    // Start collection of profile.\n    profiler.start()\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n    addLongTask({\n      id: 'long-task-id-1',\n      startClocks: clocksNow(),\n      duration: 50 as Duration,\n      entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n    })\n    clock.tick(50)\n\n    addLongTask({\n      id: 'long-task-id-2',\n      startClocks: clocksNow(),\n      duration: 100 as Duration,\n      entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n    })\n\n    // Stop first profiling session (sync - state changes immediately)\n    clock.tick(105)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n\n    // Flush microtasks for first session's data collection\n    await waitNextMicrotask()\n\n    // start a new profiling session\n    profiler.start()\n    await waitForBoolean(() => profiler.isRunning())\n\n    addLongTask({\n      id: 'long-task-id-3',\n      startClocks: clocksNow(),\n      duration: 100 as Duration,\n      entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n    })\n\n    clock.tick(500)\n\n    // stop the second profiling session (sync - state changes immediately)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Data collection uses Promises (microtasks), not setTimeout.\n    // With mockClock(), we can't use waitForBoolean (which polls via setTimeout).\n    // Flush microtasks: one for profiler.stop() Promise, one for transport.send()\n    await waitNextMicrotask()\n    await waitNextMicrotask()\n\n    expect(interceptor.requests.length).toBe(2)\n\n    const requestOne = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    const requestTwo = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[1])\n\n    const traceOne = requestOne['wall-time.json']\n    const traceTwo = requestTwo['wall-time.json']\n\n    expect(requestOne.event.long_task?.id.length).toBe(2)\n    expect(traceOne.longTasks).toEqual([\n      {\n        id: 'long-task-id-2',\n        startClocks: jasmine.any(Object),\n        duration: 100 as Duration,\n        entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n      },\n      {\n        id: 'long-task-id-1',\n        startClocks: jasmine.any(Object),\n        duration: 50 as Duration,\n        entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n      },\n    ])\n\n    expect(requestTwo.event.long_task?.id.length).toBe(1)\n    expect(traceTwo.longTasks).toEqual([\n      {\n        id: 'long-task-id-3',\n        startClocks: jasmine.any(Object),\n        duration: 100 as Duration,\n        entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n      },\n    ])\n  })\n\n  it('should collect actions happening during a profiling session', async () => {\n    const clock = mockClock()\n    const { profiler, profilingContextManager, addAction } = setupProfiler()\n\n    // Start collection of profile.\n    profiler.start()\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n    addAction({\n      id: 'action-id-1',\n      label: 'action-label-1',\n      startClocks: clocksNow(),\n      duration: 50 as Duration,\n    })\n    clock.tick(50)\n\n    addAction({\n      id: 'action-id-2',\n      label: 'action-label-2',\n      startClocks: clocksNow(),\n      duration: 100 as Duration,\n    })\n\n    // Stop first profiling session (sync - state changes immediately)\n    clock.tick(105)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n\n    // Flush microtasks for first session's data collection\n    await waitNextMicrotask()\n\n    // start a new profiling session\n    profiler.start()\n    await waitForBoolean(() => profiler.isRunning())\n\n    addAction({\n      id: 'action-id-3',\n      label: 'action-label-3',\n      startClocks: clocksNow(),\n      duration: 100 as Duration,\n    })\n\n    clock.tick(500)\n\n    // stop the second profiling session (sync - state changes immediately)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Data collection uses Promises (microtasks), not setTimeout.\n    // With mockClock(), we can't use waitForBoolean (which polls via setTimeout).\n    // Flush microtasks: one for profiler.stop() Promise, one for transport.send()\n    await waitNextMicrotask()\n    await waitNextMicrotask()\n\n    expect(interceptor.requests.length).toBe(2)\n\n    const requestOne = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    const requestTwo = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[1])\n\n    const traceOne = requestOne['wall-time.json']\n    const traceTwo = requestTwo['wall-time.json']\n\n    expect(requestOne.event.action?.id.length).toBe(2)\n    expect(traceOne.actions).toEqual([\n      {\n        id: 'action-id-2',\n        startClocks: jasmine.any(Object),\n        duration: 100 as Duration,\n        label: 'action-label-2',\n      },\n      {\n        id: 'action-id-1',\n        startClocks: jasmine.any(Object),\n        duration: 50 as Duration,\n        label: 'action-label-1',\n      },\n    ])\n\n    expect(requestTwo.event.action?.id.length).toBe(1)\n    expect(traceTwo.actions).toEqual([\n      {\n        id: 'action-id-3',\n        startClocks: jasmine.any(Object),\n        duration: 100 as Duration,\n        label: 'action-label-3',\n      },\n    ])\n  })\n\n  it('should collect vitals happening during a profiling session', async () => {\n    const clock = mockClock()\n    const { profiler, profilingContextManager, addVital } = setupProfiler()\n\n    // Start collection of profile.\n    profiler.start()\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n    addVital({\n      id: 'vital-id-1',\n      label: 'vital-label-1',\n      startClocks: clocksNow(),\n      duration: 50 as Duration,\n    })\n    clock.tick(50)\n\n    addVital({\n      id: 'vital-id-2',\n      label: 'vital-label-2',\n      startClocks: clocksNow(),\n      duration: 100 as Duration,\n    })\n\n    // Stop first profiling session (sync - state changes immediately)\n    clock.tick(105)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n\n    // Flush microtasks for first session's data collection\n    await waitNextMicrotask()\n\n    // start a new profiling session\n    profiler.start()\n    await waitForBoolean(() => profiler.isRunning())\n\n    addVital({\n      id: 'vital-id-3',\n      label: 'vital-label-3',\n      startClocks: clocksNow(),\n      duration: 100 as Duration,\n    })\n\n    clock.tick(500)\n\n    // stop the second profiling session (sync - state changes immediately)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Data collection uses Promises (microtasks), not setTimeout.\n    // With mockClock(), we can't use waitForBoolean (which polls via setTimeout).\n    // Flush microtasks: one for profiler.stop() Promise, one for transport.send()\n    await waitNextMicrotask()\n    await waitNextMicrotask()\n\n    expect(interceptor.requests.length).toBe(2)\n\n    const requestOne = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    const requestTwo = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[1])\n\n    const traceOne = requestOne['wall-time.json']\n    const traceTwo = requestTwo['wall-time.json']\n\n    expect(requestOne.event.vital?.id.length).toBe(2)\n    expect(traceOne.vitals).toEqual([\n      {\n        id: 'vital-id-2',\n        startClocks: jasmine.any(Object),\n        duration: 100 as Duration,\n        label: 'vital-label-2',\n      },\n      {\n        id: 'vital-id-1',\n        startClocks: jasmine.any(Object),\n        duration: 50 as Duration,\n        label: 'vital-label-1',\n      },\n    ])\n\n    expect(requestTwo.event.vital?.id.length).toBe(1)\n    expect(traceTwo.vitals).toEqual([\n      {\n        id: 'vital-id-3',\n        startClocks: jasmine.any(Object),\n        duration: 100 as Duration,\n        label: 'vital-label-3',\n      },\n    ])\n  })\n\n  it('should collect views and set default view name in the Profile', async () => {\n    const initialViewEntry = {\n      id: 'view-user',\n      name: '', // no custom view name, should fallback to default view name\n      startClocks: {\n        relative: relativeNow(),\n        timeStamp: timeStampNow(),\n      },\n    }\n    const { profiler, profilingContextManager } = setupProfiler(initialViewEntry)\n\n    // Navigate to the user view\n    history.pushState({}, '', '/user/123')\n\n    profiler.start()\n\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Navigate to the profile view\n    history.pushState({}, '', '/v1/user/3A2/profile')\n\n    // Emit a view created event\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, {\n      id: 'view-profile',\n      name: '', // no custom view name, should fallback to default view name\n      startClocks: {\n        relative: relativeNow(),\n        timeStamp: timeStampNow(),\n      },\n    })\n\n    // Stop collection of profile (sync - state changes immediately)\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n\n    const request = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    const views = request['wall-time.json'].views\n\n    expect(views.length).toBe(2)\n    expect(views[0].viewId).toBe('view-user')\n    expect(views[0].viewName).toBe('/user/?')\n    expect(views[1].viewId).toBe('view-profile')\n    expect(views[1].viewName).toBe('/v1/user/?/profile')\n  })\n\n  it('should keep track of the latest view in the Profiler', async () => {\n    const initialViewEntry = {\n      id: 'view-initial',\n      name: 'view-initial',\n      startClocks: {\n        relative: relativeNow(),\n        timeStamp: timeStampNow(),\n      },\n    }\n\n    const { profiler, profilingContextManager, mockedRumProfilerTrace } = setupProfiler(initialViewEntry)\n\n    // Navigate to the user view\n    history.pushState({}, '', '/user/123')\n\n    profiler.start()\n\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Navigate to a new profile view\n    history.pushState({}, '', '/v1/user/3A2/profile')\n\n    const nextViewEntry = {\n      id: 'view-next',\n      name: 'view-next',\n      startClocks: {\n        relative: relativeNow(),\n        timeStamp: timeStampNow(),\n      },\n    }\n\n    // Emit a view created event\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, nextViewEntry)\n\n    // Emulate visibility change to `hidden` state\n    setVisibilityState('hidden')\n\n    // Wait for profiler to pause\n    await waitForBoolean(() => profiler.isPaused())\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n\n    // Assert that the profiler has collected data on pause.\n    expect(interceptor.requests.length).toBe(1)\n\n    const request = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    expect(request.event.session?.id).toBe('session-id-1')\n    expect(request['wall-time.json'].views).toEqual([\n      {\n        viewId: initialViewEntry.id,\n        viewName: initialViewEntry.name,\n        startClocks: initialViewEntry.startClocks,\n      },\n      {\n        viewId: nextViewEntry.id,\n        viewName: nextViewEntry.name,\n        startClocks: nextViewEntry.startClocks,\n      },\n    ])\n\n    // Change back to visible\n    setVisibilityState('visible')\n    document.dispatchEvent(new Event('visibilitychange'))\n\n    // Wait for profiler to restart\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Stop collection of profile (sync - state changes immediately)\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 2)\n\n    expect(interceptor.requests.length).toBe(2)\n\n    // Check the the sendProfilesSpy was called with the mocked trace\n    const request2 = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[1])\n    expect(request2.event.session?.id).toBe('session-id-1')\n    expect(request2['wall-time.json']).toEqual(mockedRumProfilerTrace)\n  })\n\n  it('should stop profiling when session expires', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Notify that the session has expired (sync - state changes immediately)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n\n    // Verify that profiler collected data before stopping\n    expect(interceptor.requests.length).toBe(1)\n  })\n\n  it('should not restart profiling after session expiration when visibility changes', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Notify that the session has expired (sync - state changes immediately)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Change visibility to hidden and back to visible\n    setVisibilityState('hidden')\n\n    setVisibilityState('visible')\n\n    // Wait a bit to ensure profiler doesn't restart\n    await new Promise((resolve) => setTimeout(resolve, 100))\n\n    // Profiler should remain stopped, not paused or running\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n  })\n\n  it('should restart profiling when session is renewed', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Notify that the session has expired (sync - state changes immediately)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n\n    // Verify that profiler collected data before stopping\n    expect(interceptor.requests.length).toBe(1)\n\n    // Notify that the session has been renewed\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n    // Wait for profiler to restart\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Stop profiler and verify it collected data from the new session (sync)\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n\n    // Wait for data collection to complete (async fire-and-forget)\n    await waitForBoolean(() => interceptor.requests.length >= 2)\n\n    // Should have collected data from both sessions (before expiration and after renewal)\n    expect(interceptor.requests.length).toBe(2)\n  })\n\n  it('should handle multiple session expiration and renewal cycles', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // First cycle: expire and renew (sync - state changes immediately)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    await waitForBoolean(() => interceptor.requests.length >= 1)\n    expect(interceptor.requests.length).toBe(1)\n\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Second cycle: expire and renew again (sync)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    await waitForBoolean(() => interceptor.requests.length >= 2)\n    expect(interceptor.requests.length).toBe(2)\n\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Stop profiler (sync)\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n\n    // Should have collected data from: initial session + first renewal + second renewal = 3 profiles\n    await waitForBoolean(() => interceptor.requests.length >= 3)\n    expect(interceptor.requests.length).toBe(3)\n  })\n\n  it('should not restart profiling on session renewal if profiler was manually stopped', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Manually stop the profiler (not via session expiration) - sync\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Notify that the session has been renewed\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n    // Wait a bit to ensure profiler doesn't restart\n    await new Promise((resolve) => setTimeout(resolve, 100))\n\n    // Profiler should remain stopped - manual stop should not be overridden by session renewal\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n  })\n\n  it('should restart profiling when session renews while stop is still in progress', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Session expires while profiler is running\n    // With sync state changes, the profiler state becomes 'stopped' immediately\n    // while data collection continues in the background (fire-and-forget)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    // State is immediately 'stopped' (sync), even though data collection is async\n    expect(profiler.isStopped()).toBe(true)\n\n    // Session renews IMMEDIATELY - even before async data collection completes\n    // This simulates the scenario where user activity triggers renewal\n    // while data is still being collected in the background\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n    // The profiler should restart because the sync state was already 'stopped'\n    // when SESSION_RENEWED fired\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profiler.isRunning()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Clean up\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n  })\n\n  it('should not restart profiling on session renewal if user called stop after session expiration', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Session expires (sync - state changes immediately)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // User explicitly stops the profiler after session expiration\n    profiler.stop()\n\n    expect(profiler.isStopped()).toBe(true)\n\n    // Session is renewed — start() is called synchronously, so no need to wait\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n    // Profiler should remain stopped - user's explicit stop should take priority over session expiration\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n  })\n\n  it('should not include long tasks outside the profiling window when clocks drift', async () => {\n    const clock = mockClock()\n    const timeOrigin = performance.timing.navigationStart\n    const { profiler, addLongTask } = setupProfiler()\n\n    profiler.start()\n    expect(profiler.isRunning()).toBe(true)\n\n    // Add a long task at T=100ms (inside the profile window)\n    clock.tick(100)\n    addLongTask({\n      id: 'long-task-inside',\n      startClocks: clocksNow(),\n      duration: 50 as Duration,\n      entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n    })\n\n    // Add a long task at T=1000ms (outside the actual profile relative window)\n    clock.tick(900)\n    addLongTask({\n      id: 'long-task-outside',\n      startClocks: clocksNow(),\n      duration: 50 as Duration,\n      entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n    })\n\n    // Advance to T=1100ms\n    clock.tick(100)\n\n    // Simulate clock drift: Date.now() drifted 1000ms ahead of performance.now()\n    // This mimics NTP sync or system clock adjustments in production\n    ;(performance.now as jasmine.Spy).and.callFake(() => Date.now() - timeOrigin - 1000)\n\n    // Stop profiler — state changes synchronously, data collection is async via Promise\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n\n    // Flush microtasks for profiler.stop() Promise and transport.send()\n    await waitNextMicrotask()\n    await waitNextMicrotask()\n\n    expect(interceptor.requests.length).toBe(1)\n    const request = await readFormDataRequest<ProfileEventPayload>(interceptor.requests[0])\n    const trace = request['wall-time.json']\n\n    // Should only include the long task that occurred during the actual profiling window.\n    // Without the fix (using timeStamp for duration), both long tasks would be included\n    // because the inflated timeStamp-based duration extends the query window.\n    expect(trace.longTasks.length).toBe(1)\n    expect(trace.longTasks[0].id).toBe('long-task-inside')\n  })\n\n  it('should restart profiling when session expires while paused and then renews', async () => {\n    const { profiler, profilingContextManager } = setupProfiler()\n\n    profiler.start()\n\n    // Wait for start of collection.\n    await waitForBoolean(() => profiler.isRunning())\n\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Pause the profiler by hiding the tab\n    setVisibilityState('hidden')\n\n    // Wait for profiler to pause\n    await waitForBoolean(() => profiler.isPaused())\n\n    // Session expires while profiler is paused (sync - state changes immediately)\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    expect(profiler.isStopped()).toBe(true)\n    expect(profilingContextManager.get()?.status).toBe('stopped')\n\n    // Session is renewed\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n    // Wait for profiler to restart\n    await waitForBoolean(() => profiler.isRunning())\n    expect(profilingContextManager.get()?.status).toBe('running')\n\n    // Clean up\n    profiler.stop()\n    expect(profiler.isStopped()).toBe(true)\n  })\n})\n\nfunction waitForBoolean(booleanCallback: () => boolean) {\n  return new Promise<void>((resolve) => {\n    function poll() {\n      if (booleanCallback()) {\n        resolve()\n      } else {\n        setTimeout(() => poll(), 50)\n      }\n    }\n    poll()\n  })\n}\n\nfunction setVisibilityState(state: 'hidden' | 'visible') {\n  setPageVisibility(state)\n  window.dispatchEvent(createNewEvent('visibilitychange'))\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/profiler.ts",
    "content": "import type { Encoder } from '@datadog/browser-core'\nimport {\n  addEventListener,\n  clearTimeout,\n  setTimeout,\n  DOM_EVENT,\n  monitorError,\n  display,\n  getGlobalObject,\n  clocksOrigin,\n  clocksNow,\n  elapsed,\n  DeflateEncoderStreamId,\n  mockable,\n} from '@datadog/browser-core'\n\nimport type {\n  LifeCycle,\n  RumConfiguration,\n  RumSessionManager,\n  TransportPayload,\n  ViewHistory,\n} from '@datadog/browser-rum-core'\nimport { createFormDataTransport, LifeCycleEventType } from '@datadog/browser-rum-core'\nimport type { BrowserProfilerTrace, RumViewEntry } from '../../types'\nimport type {\n  RumProfilerInstance,\n  RumProfilerRunningInstance,\n  Profiler,\n  RUMProfiler,\n  RUMProfilerConfiguration,\n  RumProfilerStoppedInstance,\n} from './types'\nimport { getNumberOfSamples } from './utils/getNumberOfSamples'\nimport type { ProfilingContextManager } from './profilingContext'\nimport { getCustomOrDefaultViewName } from './utils/getCustomOrDefaultViewName'\nimport { assembleProfilingPayload } from './transport/assembly'\nimport { createLongTaskHistory } from './longTaskHistory'\nimport { createActionHistory } from './actionHistory'\nimport { createVitalHistory } from './vitalHistory'\n\nexport const DEFAULT_RUM_PROFILER_CONFIGURATION: RUMProfilerConfiguration = {\n  sampleIntervalMs: 10, // Sample stack trace every 10ms\n  collectIntervalMs: 60000, // Collect data every minute\n  minProfileDurationMs: 5000, // Require at least 5 seconds of profile data to reduce noise and cost\n  minNumberOfSamples: 50, // Require at least 50 samples (~500 ms) to report a profile to reduce noise and cost\n}\n\nexport function createRumProfiler(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  session: RumSessionManager,\n  profilingContextManager: ProfilingContextManager,\n  createEncoder: (streamId: DeflateEncoderStreamId) => Encoder,\n  viewHistory: ViewHistory,\n  profilerConfiguration: RUMProfilerConfiguration = DEFAULT_RUM_PROFILER_CONFIGURATION\n): RUMProfiler {\n  const transport = createFormDataTransport(configuration, lifeCycle, createEncoder, DeflateEncoderStreamId.PROFILING)\n\n  let lastViewEntry: RumViewEntry | undefined\n\n  // Global clean-up tasks for listeners that are not specific to a profiler instance (eg. visibility change, before unload)\n  const globalCleanupTasks: Array<() => void> = []\n  const longTaskHistory = mockable(createLongTaskHistory)(lifeCycle)\n  const actionHistory = mockable(createActionHistory)(lifeCycle)\n  const vitalHistory = mockable(createVitalHistory)(lifeCycle)\n\n  let instance: RumProfilerInstance = { state: 'stopped', stateReason: 'initializing' }\n\n  // Stops the profiler when session expires\n  lifeCycle.subscribe(LifeCycleEventType.SESSION_EXPIRED, () => {\n    stopProfiling('session-expired')\n  })\n\n  // Start the profiler again when session is renewed\n  lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {\n    if (instance.state === 'stopped' && instance.stateReason === 'session-expired') {\n      start()\n    }\n  })\n\n  // Public API to start the profiler.\n  function start(): void {\n    if (instance.state === 'running') {\n      return\n    }\n\n    const viewEntry = viewHistory.findView()\n\n    // Add initial view\n    // Note: `viewEntry.name` is only filled when users use manual view creation via `startView` method.\n    lastViewEntry = viewEntry\n      ? {\n          startClocks: viewEntry.startClocks,\n          viewId: viewEntry.id,\n          viewName: getCustomOrDefaultViewName(viewEntry.name, document.location.pathname),\n        }\n      : undefined\n\n    // Add global clean-up tasks for listeners that are not specific to a profiler instance (eg. visibility change, before unload)\n    globalCleanupTasks.push(\n      addEventListener(configuration, window, DOM_EVENT.VISIBILITY_CHANGE, handleVisibilityChange).stop,\n      addEventListener(configuration, window, DOM_EVENT.BEFORE_UNLOAD, handleBeforeUnload).stop\n    )\n\n    // Start profiler instance\n    startNextProfilerInstance()\n  }\n\n  // Public API to manually stop the profiler.\n  function stop() {\n    stopProfiling('stopped-by-user')\n  }\n\n  function stopProfiling(reason: RumProfilerStoppedInstance['stateReason']) {\n    // Stop current profiler instance (data collection happens async in background)\n    stopProfilerInstance(reason)\n\n    // Cleanup global listeners and reset the array to prevent accumulation across start/stop cycles\n    globalCleanupTasks.forEach((task) => task())\n    globalCleanupTasks.length = 0\n\n    // Update Profiling status once the Profiler has been stopped.\n    profilingContextManager.set({ status: 'stopped', error_reason: undefined })\n  }\n\n  /**\n   * Whenever a new Profiler instance is started, we need to add event listeners to surroundings (RUM Events, Long Tasks, etc) to enrich the Profiler data.\n   * If the instance is already running, we can keep the same event listeners.\n   */\n  function addEventListeners(existingInstance: RumProfilerInstance) {\n    if (existingInstance.state === 'running') {\n      // Instance is already running, so we can keep same event listeners.\n      return {\n        cleanupTasks: existingInstance.cleanupTasks,\n      }\n    }\n\n    // Store clean-up tasks for this instance (tasks to be executed when the Profiler is stopped or paused.)\n    const cleanupTasks = []\n\n    // Whenever the View is updated, we add a views entry to the profiler instance.\n    const viewUpdatedSubscription = lifeCycle.subscribe(LifeCycleEventType.VIEW_CREATED, (view) => {\n      const viewEntry = {\n        viewId: view.id,\n        // Note: `viewName` is only filled when users use manual view creation via `startView` method.\n        viewName: getCustomOrDefaultViewName(view.name, document.location.pathname),\n        startClocks: view.startClocks,\n      }\n\n      collectViewEntry(viewEntry)\n\n      // Update last view entry\n      lastViewEntry = viewEntry\n    })\n    cleanupTasks.push(viewUpdatedSubscription.unsubscribe)\n\n    return {\n      cleanupTasks,\n    }\n  }\n\n  function startNextProfilerInstance(): void {\n    // These APIs might be unavailable in some browsers\n    const globalThisProfiler: Profiler | undefined = getGlobalObject<any>().Profiler\n\n    if (!globalThisProfiler) {\n      profilingContextManager.set({ status: 'error', error_reason: 'not-supported-by-browser' })\n      throw new Error('RUM Profiler is not supported in this browser.')\n    }\n\n    // Collect data from previous running instance (fire-and-forget)\n    if (instance.state === 'running') {\n      collectProfilerInstance(instance)\n    }\n\n    const { cleanupTasks } = addEventListeners(instance)\n\n    let profiler: Profiler\n    try {\n      // We have to create new Profiler each time we start a new instance\n      profiler = new globalThisProfiler({\n        sampleInterval: profilerConfiguration.sampleIntervalMs,\n        // Keep buffer size at 1.5 times of minimum required to collect data for a profiling instance\n        maxBufferSize: Math.round(\n          (profilerConfiguration.collectIntervalMs * 1.5) / profilerConfiguration.sampleIntervalMs\n        ),\n      })\n    } catch (e) {\n      if (e instanceof Error && e.message.includes('disabled by Document Policy')) {\n        // Missing Response Header (`js-profiling`) that is required to enable the profiler.\n        // We should suggest the user to enable the Response Header in their server configuration.\n        display.warn(\n          '[DD_RUM] Profiler startup failed. Ensure your server includes the `Document-Policy: js-profiling` response header when serving HTML pages.',\n          e\n        )\n        profilingContextManager.set({ status: 'error', error_reason: 'missing-document-policy-header' })\n      } else {\n        profilingContextManager.set({ status: 'error', error_reason: 'unexpected-exception' })\n      }\n      return\n    }\n\n    profilingContextManager.set({ status: 'running', error_reason: undefined })\n\n    // Kick-off the new instance\n    instance = {\n      state: 'running',\n      startClocks: clocksNow(),\n      profiler,\n      timeoutId: setTimeout(startNextProfilerInstance, profilerConfiguration.collectIntervalMs),\n      views: [],\n      cleanupTasks,\n      longTasks: [],\n    }\n\n    // Add last view entry\n    collectViewEntry(lastViewEntry)\n\n    // Add event handler case we overflow the buffer\n    profiler.addEventListener('samplebufferfull', handleSampleBufferFull)\n  }\n\n  function collectProfilerInstance(runningInstance: RumProfilerRunningInstance) {\n    // Cleanup instance\n    clearTimeout(runningInstance.timeoutId)\n    runningInstance.profiler.removeEventListener('samplebufferfull', handleSampleBufferFull)\n\n    // Store instance data snapshot in local variables to use in async callback\n    const { startClocks, views } = runningInstance\n\n    // Stop current profiler to get trace\n    runningInstance.profiler\n      .stop()\n      .then((trace) => {\n        const endClocks = clocksNow()\n        const duration = elapsed(startClocks.relative, endClocks.relative)\n        const longTasks = longTaskHistory.findAll(startClocks.relative, duration)\n        const actions = actionHistory.findAll(startClocks.relative, duration)\n        const vitals = vitalHistory.findAll(startClocks.relative, duration)\n        const isBelowDurationThreshold = duration < profilerConfiguration.minProfileDurationMs\n        const isBelowSampleThreshold = getNumberOfSamples(trace.samples) < profilerConfiguration.minNumberOfSamples\n\n        if (longTasks.length === 0 && (isBelowDurationThreshold || isBelowSampleThreshold)) {\n          // Skip very short profiles to reduce noise and cost, but keep them if they contain long tasks.\n          return\n        }\n\n        handleProfilerTrace(\n          // Enrich trace with time and instance data\n          Object.assign(trace, {\n            startClocks,\n            endClocks,\n            clocksOrigin: clocksOrigin(),\n            longTasks,\n            actions,\n            vitals,\n            views,\n            sampleInterval: profilerConfiguration.sampleIntervalMs,\n          })\n        )\n      })\n      .catch(monitorError)\n  }\n\n  function stopProfilerInstance(stateReason: RumProfilerStoppedInstance['stateReason']) {\n    if (instance.state !== 'running') {\n      if (\n        // If paused, profiler data was already collected during pause, just update state\n        instance.state === 'paused' ||\n        // Update stateReason when already stopped and the user explicitly stops the profiler,\n        // so that SESSION_RENEWED does not override the user's intent.\n        (instance.state === 'stopped' && stateReason === 'stopped-by-user')\n      ) {\n        instance = { state: 'stopped', stateReason }\n      }\n\n      return\n    }\n\n    // Capture the running instance before changing state\n    const runningInstance = instance\n\n    // Update state synchronously so SESSION_RENEWED check works immediately\n    instance = { state: 'stopped', stateReason }\n\n    // Cleanup instance-specific tasks (e.g., view listener)\n    runningInstance.cleanupTasks.forEach((cleanupTask) => cleanupTask())\n\n    // Collect and send profile data in background - doesn't block state transitions\n    collectProfilerInstance(runningInstance)\n  }\n\n  function pauseProfilerInstance() {\n    if (instance.state !== 'running') {\n      return\n    }\n\n    // Capture the running instance before changing state\n    const runningInstance = instance\n\n    // Update state synchronously\n    instance = { state: 'paused' }\n\n    // Cleanup instance-specific tasks\n    runningInstance.cleanupTasks.forEach((cleanupTask) => cleanupTask())\n\n    // Collect and send profile data in background\n    collectProfilerInstance(runningInstance)\n  }\n\n  function collectViewEntry(viewEntry: RumViewEntry | undefined): void {\n    if (instance.state !== 'running' || !viewEntry) {\n      return\n    }\n\n    // Add entry to views\n    instance.views.push(viewEntry)\n  }\n\n  function handleProfilerTrace(trace: BrowserProfilerTrace): void {\n    // Find current session to assign it to the Profile.\n    const sessionId = session.findTrackedSession()?.id\n    const payload = assembleProfilingPayload(trace, configuration, sessionId)\n\n    void transport.send(payload as unknown as TransportPayload)\n  }\n\n  function handleSampleBufferFull(): void {\n    startNextProfilerInstance()\n  }\n\n  function handleVisibilityChange(): void {\n    if (document.visibilityState === 'hidden' && instance.state === 'running') {\n      // Pause when tab is hidden. We use paused state to distinguish between\n      // paused by visibility change and stopped by user.\n      // If profiler is paused by the visibility change, we should resume when\n      // tab becomes visible again. That's not the case when user stops the profiler.\n      pauseProfilerInstance()\n    } else if (document.visibilityState === 'visible' && instance.state === 'paused') {\n      // Resume when tab becomes visible again\n      startNextProfilerInstance()\n    }\n  }\n\n  function handleBeforeUnload(): void {\n    // `unload` can in some cases be triggered while the page is still active (link to a different protocol like mailto:).\n    // We can immediately flush (by starting a new profiler instance) to make sure we receive the data, and at the same time keep the profiler active.\n    // In case of the regular unload, the profiler will be shut down anyway.\n    startNextProfilerInstance()\n  }\n\n  function isStopped() {\n    return instance.state === 'stopped'\n  }\n\n  function isRunning() {\n    return instance.state === 'running'\n  }\n\n  function isPaused() {\n    return instance.state === 'paused'\n  }\n\n  return { start, stop, isStopped, isRunning, isPaused }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/profilingContext.spec.ts",
    "content": "import { RumEventType, createHooks } from '@datadog/browser-rum-core'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport { HookNames } from '@datadog/browser-core'\nimport type { AssembleHookParams } from '@datadog/browser-rum-core/src/domain/hooks'\nimport { startProfilingContext } from './profilingContext'\n\nconst relativeTime: RelativeTime = 1000 as RelativeTime\n\ndescribe('Profiling Context', () => {\n  it('should add the profiling context to the event attributes only for the right event types', () => {\n    const hooks = createHooks()\n    const profilingContextManager = startProfilingContext(hooks)\n\n    profilingContextManager.set({ status: 'running' })\n\n    for (const eventType of [RumEventType.VIEW, RumEventType.LONG_TASK, RumEventType.ACTION, RumEventType.VITAL]) {\n      const eventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType,\n        startTime: relativeTime,\n      } as AssembleHookParams)\n\n      expect(eventAttributes).toEqual(\n        jasmine.objectContaining({\n          _dd: {\n            profiling: { status: 'running' },\n          },\n        })\n      )\n    }\n\n    for (const eventType of [RumEventType.ERROR, RumEventType.RESOURCE]) {\n      const eventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType,\n        startTime: relativeTime,\n      } as AssembleHookParams)\n\n      expect(eventAttributes).toBeUndefined()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/profilingContext.ts",
    "content": "import { HookNames, SKIPPED } from '@datadog/browser-core'\nimport type { Hooks, ProfilingInternalContextSchema } from '@datadog/browser-rum-core'\nimport { RumEventType } from '@datadog/browser-rum-core'\n\nexport interface ProfilingContextManager {\n  set: (next: ProfilingInternalContextSchema) => void\n  get: () => ProfilingInternalContextSchema | undefined\n}\n\nexport function startProfilingContext(hooks: Hooks): ProfilingContextManager {\n  let currentContext: ProfilingInternalContextSchema = {\n    status: 'starting',\n  }\n\n  hooks.register(HookNames.Assemble, ({ eventType }) => {\n    if (\n      eventType !== RumEventType.VIEW &&\n      eventType !== RumEventType.LONG_TASK &&\n      eventType !== RumEventType.ACTION &&\n      eventType !== RumEventType.VITAL\n    ) {\n      return SKIPPED\n    }\n\n    return {\n      type: eventType,\n      _dd: {\n        profiling: currentContext,\n      },\n    }\n  })\n\n  return {\n    get: () => currentContext,\n    set: (newContext: ProfilingInternalContextSchema) => {\n      currentContext = newContext\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/profilingSupported.ts",
    "content": "import { getGlobalObject } from '@datadog/browser-core'\nimport type { Profiler } from './types'\n\nexport function isProfilingSupported(): boolean {\n  const globalThis = getGlobalObject()\n\n  // This API might be unavailable in some browsers\n  const globalThisProfiler: Profiler | undefined = (globalThis as any).Profiler\n  return globalThisProfiler !== undefined\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/test-utils/mockedTrace.ts",
    "content": "import type { ProfilerTrace } from '../types'\n\nconst generateFiftyRandomSamples = () => {\n  const samples = []\n  for (let i = 0; i < 50; i++) {\n    samples.push({\n      timestamp: i,\n      stackId: i % 3,\n    })\n  }\n  return samples\n}\n\n// eslint-disable-next-line local-rules/disallow-side-effects\nconst randomSamples = generateFiftyRandomSamples()\n\nexport const mockedEmptyTrace: ProfilerTrace = {\n  resources: [],\n  frames: [],\n  stacks: [],\n  samples: [],\n}\n\nexport const mockedTrace: ProfilerTrace = {\n  resources: ['resource1', 'resource2', 'resource3'],\n  frames: [\n    {\n      name: 'frame-0',\n      line: 1,\n      column: 1,\n      resourceId: 0,\n    },\n    {\n      name: 'frame-1',\n      line: 2,\n      column: 2,\n      resourceId: 1,\n    },\n    {\n      name: 'frame-2',\n      line: 3,\n      column: 3,\n      resourceId: 2,\n    },\n  ],\n  stacks: [\n    {\n      frameId: 0,\n    },\n    {\n      frameId: 1,\n    },\n    {\n      frameId: 2,\n    },\n  ],\n  samples: randomSamples,\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/transport/assembly.ts",
    "content": "import { buildTags, currentDrift } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport type { BrowserProfileEvent, BrowserProfilerTrace } from '../../../types'\nimport { buildProfileEventAttributes } from './buildProfileEventAttributes'\n\nexport interface ProfileEventPayload {\n  event: BrowserProfileEvent\n  'wall-time.json': BrowserProfilerTrace\n}\n\nexport function assembleProfilingPayload(\n  profilerTrace: BrowserProfilerTrace,\n  configuration: RumConfiguration,\n  sessionId: string | undefined\n): ProfileEventPayload {\n  const event = buildProfileEvent(profilerTrace, configuration, sessionId)\n\n  return {\n    event,\n    'wall-time.json': profilerTrace,\n  }\n}\n\nfunction buildProfileEvent(\n  profilerTrace: BrowserProfilerTrace,\n  configuration: RumConfiguration,\n  sessionId: string | undefined\n): ProfileEventPayload['event'] {\n  const tags = buildTags(configuration) // TODO: get that from the tagContext hook\n  const profileAttributes = buildProfileEventAttributes(profilerTrace, configuration.applicationId, sessionId)\n  const profileEventTags = buildProfileEventTags(tags)\n\n  const profileEvent: ProfileEventPayload['event'] = {\n    ...profileAttributes,\n    attachments: ['wall-time.json'],\n    start: new Date(profilerTrace.startClocks.timeStamp).toISOString(),\n    end: new Date(profilerTrace.endClocks.timeStamp).toISOString(),\n    family: 'chrome',\n    runtime: 'chrome',\n    format: 'json',\n    version: 4, // Ingestion event version (not the version application tag)\n    tags_profiler: profileEventTags.join(','),\n    _dd: {\n      clock_drift: currentDrift(),\n    },\n  }\n\n  return profileEvent\n}\n\n/**\n * Builds tags for the Profile Event.\n *\n * @param tags - RUM tags\n * @returns Combined tags for the Profile Event.\n */\nfunction buildProfileEventTags(tags: string[]): string[] {\n  // Tags already contains the common tags for all events. (service, env, version, etc.)\n  // Here we are adding some specific-to-profiling tags.\n  const profileEventTags = tags.concat(['language:javascript', 'runtime:chrome', 'family:chrome', 'host:browser'])\n\n  return profileEventTags\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/transport/buildProfileEventAttributes.spec.ts",
    "content": "import { clocksOrigin } from '@datadog/browser-core'\nimport { RumPerformanceEntryType } from '@datadog/browser-rum-core'\nimport type { BrowserProfilerTrace, RumViewEntry } from '../../../types'\nimport type { LongTaskContext } from '../longTaskHistory'\nimport { buildProfileEventAttributes, type ProfileEventAttributes } from './buildProfileEventAttributes'\n\ndescribe('buildProfileEventAttributes', () => {\n  const applicationId = 'test-app-id'\n  const sessionId = 'test-session-id'\n\n  function createMockViewEntry(overrides: Partial<RumViewEntry> = {}): RumViewEntry {\n    return {\n      startClocks: clocksOrigin(),\n      viewId: 'view-123',\n      viewName: 'Home Page',\n      ...overrides,\n    }\n  }\n\n  function createMockLongTaskEntry(overrides: Partial<LongTaskContext> = {}): LongTaskContext {\n    return {\n      id: 'longtask-456',\n      duration: 100 as any,\n      entryType: RumPerformanceEntryType.LONG_TASK,\n      startClocks: clocksOrigin(),\n      ...overrides,\n    }\n  }\n\n  function createMockProfilerTrace(overrides: Partial<BrowserProfilerTrace> = {}): BrowserProfilerTrace {\n    return {\n      startClocks: clocksOrigin(),\n      endClocks: clocksOrigin(),\n      clocksOrigin: clocksOrigin(),\n      sampleInterval: 10,\n      views: [],\n      longTasks: [],\n      actions: [],\n      vitals: [],\n      resources: [],\n      frames: [],\n      stacks: [],\n      samples: [],\n      ...overrides,\n    }\n  }\n\n  describe('when creating basic profile event attributes', () => {\n    it('should include application id', () => {\n      const profilerTrace = createMockProfilerTrace()\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.application).toEqual({ id: applicationId })\n    })\n\n    it('should include session id when provided', () => {\n      const profilerTrace = createMockProfilerTrace()\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.session).toEqual({ id: sessionId })\n    })\n\n    it('should omit session when sessionId is undefined', () => {\n      const profilerTrace = createMockProfilerTrace()\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, undefined)\n\n      expect(result.session).toBeUndefined()\n    })\n\n    it('should omit session when sessionId is empty string', () => {\n      const profilerTrace = createMockProfilerTrace()\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, '')\n\n      expect(result.session).toBeUndefined()\n    })\n  })\n\n  describe('when handling views', () => {\n    it('should extract view ids and names from single view', () => {\n      const view = createMockViewEntry({\n        viewId: 'view-123',\n        viewName: 'Home Page',\n      })\n      const profilerTrace = createMockProfilerTrace({ views: [view] })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-123'],\n        name: ['Home Page'],\n      })\n    })\n\n    it('should extract view ids and names from multiple views', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-123', viewName: 'Home Page' }),\n        createMockViewEntry({ viewId: 'view-456', viewName: 'About Page' }),\n        createMockViewEntry({ viewId: 'view-789', viewName: 'Contact Page' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-123', 'view-456', 'view-789'],\n        name: ['Home Page', 'About Page', 'Contact Page'],\n      })\n    })\n\n    it('should handle views with undefined names', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-123', viewName: 'Home Page' }),\n        createMockViewEntry({ viewId: 'view-456', viewName: undefined }),\n        createMockViewEntry({ viewId: 'view-789', viewName: 'Contact Page' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-123', 'view-456', 'view-789'],\n        name: ['Home Page', 'Contact Page'],\n      })\n    })\n\n    it('should remove duplicate view names', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-123', viewName: 'Home Page' }),\n        createMockViewEntry({ viewId: 'view-456', viewName: 'Home Page' }),\n        createMockViewEntry({ viewId: 'view-789', viewName: 'About Page' }),\n        createMockViewEntry({ viewId: 'view-abc', viewName: 'Home Page' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-123', 'view-456', 'view-789', 'view-abc'],\n        name: ['Home Page', 'About Page'],\n      })\n    })\n\n    it('should handle all views without names', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-123', viewName: undefined }),\n        createMockViewEntry({ viewId: 'view-456', viewName: undefined }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-123', 'view-456'],\n        name: [],\n      })\n    })\n\n    it('should omit view attribute when no views are present', () => {\n      const profilerTrace = createMockProfilerTrace({ views: [] })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toBeUndefined()\n    })\n  })\n\n  describe('when handling long tasks', () => {\n    it('should extract long task ids from single long task', () => {\n      const longTask = createMockLongTaskEntry({ id: 'longtask-123' })\n      const profilerTrace = createMockProfilerTrace({ longTasks: [longTask] })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.long_task).toEqual({\n        id: ['longtask-123'],\n      })\n    })\n\n    it('should extract long task ids from multiple long tasks', () => {\n      const longTasks = [\n        createMockLongTaskEntry({ id: 'longtask-123' }),\n        createMockLongTaskEntry({ id: 'longtask-456' }),\n        createMockLongTaskEntry({ id: 'longtask-789' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ longTasks })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.long_task).toEqual({\n        id: ['longtask-123', 'longtask-456', 'longtask-789'],\n      })\n    })\n\n    it('should filter out long tasks with undefined ids', () => {\n      const longTasks = [\n        createMockLongTaskEntry({ id: 'longtask-123' }),\n        createMockLongTaskEntry({ id: undefined }),\n        createMockLongTaskEntry({ id: 'longtask-789' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ longTasks })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.long_task).toEqual({\n        id: ['longtask-123', 'longtask-789'],\n      })\n    })\n\n    it('should omit long_task attribute when no long tasks have ids', () => {\n      const longTasks = [createMockLongTaskEntry({ id: undefined }), createMockLongTaskEntry({ id: undefined })]\n      const profilerTrace = createMockProfilerTrace({ longTasks })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.long_task).toBeUndefined()\n    })\n\n    it('should omit long_task attribute when no long tasks are present', () => {\n      const profilerTrace = createMockProfilerTrace({ longTasks: [] })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.long_task).toBeUndefined()\n    })\n  })\n\n  describe('when handling complex scenarios', () => {\n    it('should handle profiler trace with both views and long tasks', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-123', viewName: 'Home Page' }),\n        createMockViewEntry({ viewId: 'view-456', viewName: 'About Page' }),\n      ]\n      const longTasks = [\n        createMockLongTaskEntry({ id: 'longtask-123' }),\n        createMockLongTaskEntry({ id: 'longtask-456' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views, longTasks })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      const expected: ProfileEventAttributes = {\n        application: { id: applicationId },\n        session: { id: sessionId },\n        view: {\n          id: ['view-123', 'view-456'],\n          name: ['Home Page', 'About Page'],\n        },\n        long_task: {\n          id: ['longtask-123', 'longtask-456'],\n        },\n      }\n\n      expect(result).toEqual(expected)\n    })\n\n    it('should handle empty profiler trace', () => {\n      const profilerTrace = createMockProfilerTrace()\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      const expected: ProfileEventAttributes = {\n        application: { id: applicationId },\n        session: { id: sessionId },\n      }\n\n      expect(result).toEqual(expected)\n    })\n\n    it('should handle profiler trace with empty string view names consistently', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-123', viewName: '' }), // will be ignored\n        createMockViewEntry({ viewId: 'view-456', viewName: 'Valid Page' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-123', 'view-456'],\n        name: ['Valid Page'],\n      })\n    })\n  })\n\n  describe('edge cases', () => {\n    it('should handle profiler trace with duplicate view names and mixed undefined names', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-1', viewName: 'Page A' }),\n        createMockViewEntry({ viewId: 'view-2', viewName: undefined }),\n        createMockViewEntry({ viewId: 'view-3', viewName: 'Page A' }),\n        createMockViewEntry({ viewId: 'view-4', viewName: 'Page B' }),\n        createMockViewEntry({ viewId: 'view-5', viewName: undefined }),\n        createMockViewEntry({ viewId: 'view-6', viewName: 'Page A' }),\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view).toEqual({\n        id: ['view-1', 'view-2', 'view-3', 'view-4', 'view-5', 'view-6'],\n        name: ['Page A', 'Page B'], // Duplicates removed\n      })\n    })\n\n    it('should preserve order of view ids but deduplicate names', () => {\n      const views = [\n        createMockViewEntry({ viewId: 'view-last', viewName: 'Page Z' }),\n        createMockViewEntry({ viewId: 'view-first', viewName: 'Page A' }),\n        createMockViewEntry({ viewId: 'view-middle', viewName: 'Page Z' }), // Duplicate name\n      ]\n      const profilerTrace = createMockProfilerTrace({ views })\n\n      const result = buildProfileEventAttributes(profilerTrace, applicationId, sessionId)\n\n      expect(result.view?.id).toEqual(['view-last', 'view-first', 'view-middle'])\n      expect(result.view?.name).toEqual(['Page Z', 'Page A']) // Order based on first occurrence\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/transport/buildProfileEventAttributes.ts",
    "content": "import type { BrowserProfilerTrace, RumProfilerVitalEntry, RumViewEntry } from '../../../types'\n\nexport interface ProfileEventAttributes {\n  application: {\n    id: string\n  }\n  session?: {\n    id: string\n  }\n  view?: {\n    id: string[]\n    name: string[]\n  }\n  long_task?: {\n    id: string[]\n  }\n  action?: {\n    id: string[]\n    label: string[]\n  }\n  vital?: {\n    id: string[]\n    label: string[]\n  }\n}\n\n/**\n * Builds attributes for the Profile Event.\n *\n * @param profilerTrace - Profiler trace\n * @param applicationId - application id.\n * @param sessionId - session id.\n * @returns Additional attributes.\n */\nexport function buildProfileEventAttributes(\n  profilerTrace: BrowserProfilerTrace,\n  applicationId: string,\n  sessionId: string | undefined\n): ProfileEventAttributes {\n  // Extract view ids and names from the profiler trace and add them as attributes of the profile event.\n  // This will be used to filter the profiles by @view.id and/or @view.name.\n  const { ids, names } = extractViewIdsAndNames(profilerTrace.views)\n\n  const longTaskIds: string[] = profilerTrace.longTasks.map((longTask) => longTask.id).filter((id) => id !== undefined)\n\n  const actionIds: string[] =\n    profilerTrace.actions?.map((longTask) => longTask.id).filter((id) => id !== undefined) ?? []\n\n  const { ids: vitalIds, labels: vitalLabels } = extractVitalIdsAndLabels(profilerTrace.vitals)\n\n  const attributes: ProfileEventAttributes = { application: { id: applicationId } }\n\n  if (sessionId) {\n    attributes.session = { id: sessionId }\n  }\n  if (ids.length) {\n    attributes.view = { id: ids, name: names }\n  }\n  if (longTaskIds.length) {\n    attributes.long_task = { id: longTaskIds }\n  }\n  if (actionIds.length) {\n    attributes.action = { id: actionIds, label: [] }\n  }\n  if (vitalIds.length) {\n    attributes.vital = { id: vitalIds, label: vitalLabels }\n  }\n  return attributes\n}\n\nfunction extractViewIdsAndNames(views: RumViewEntry[]): { ids: string[]; names: string[] } {\n  const result: { ids: string[]; names: string[] } = { ids: [], names: [] }\n  for (const view of views) {\n    result.ids.push(view.viewId)\n\n    if (view.viewName) {\n      result.names.push(view.viewName)\n    }\n  }\n\n  // Remove duplicates\n  result.names = Array.from(new Set(result.names))\n\n  return result\n}\n\nfunction extractVitalIdsAndLabels(vitals?: RumProfilerVitalEntry[]): {\n  ids: string[]\n  labels: string[]\n} {\n  const result: { ids: string[]; labels: string[] } = { ids: [], labels: [] }\n\n  if (!vitals) {\n    return result\n  }\n\n  for (const vital of vitals) {\n    result.ids.push(vital.id)\n    result.labels.push(vital.label)\n  }\n\n  // Remove duplicates\n  result.labels = Array.from(new Set(result.labels))\n\n  return result\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/types/index.ts",
    "content": "export type * from './profilerApi.types'\nexport type * from './rumProfiler.types'\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/types/profilerApi.types.ts",
    "content": "// Define types for the new Profiler API\n// https://wicg.github.io/js-self-profiling/\n\nexport interface ProfilerFrame {\n  /** A function instance name. */\n  readonly name: string\n  /** Index in the trace.resources array. */\n  readonly resourceId?: number\n  /** 1-based index of the line. */\n  readonly line?: number\n  /** 1-based index of the column. */\n  readonly column?: number\n}\n\nexport interface ProfilerStack {\n  /** Index in the trace.stacks array. */\n  readonly parentId?: number\n  /** Index in the trace.frames array. */\n  readonly frameId: number\n}\n\nexport interface ProfilerSample {\n  /** High resolution time relative to the profiling session's time origin. */\n  readonly timestamp: number\n  /** Index in the trace.stacks array. */\n  readonly stackId?: number\n}\n\nexport type ProfilerResource = string\n\nexport interface ProfilerTrace {\n  /** An array of profiler resources. */\n  readonly resources: ProfilerResource[]\n  /** An array of profiler frames. */\n  readonly frames: ProfilerFrame[]\n  /** An array of profiler stacks. */\n  readonly stacks: ProfilerStack[]\n  /** An array of profiler samples. */\n  readonly samples: ProfilerSample[]\n}\n\nexport interface ProfilerInitOptions {\n  /** Sample interval in ms. */\n  readonly sampleInterval: number\n  /** Max buffer size in number of samples. */\n  readonly maxBufferSize: number\n}\n\nexport interface Profiler extends EventTarget {\n  /** Sample interval in ms. */\n  readonly sampleInterval: number\n  /** True if profiler is stopped. */\n  readonly stopped: boolean\n\n  // eslint-disable-next-line @typescript-eslint/no-misused-new\n  new (options: ProfilerInitOptions): Profiler\n  stop(): Promise<ProfilerTrace>\n\n  addEventListener<K extends keyof ProfilerEventMap>(\n    type: K,\n    listener: (this: typeof globalThis, ev: ProfilerEventMap[K]) => any,\n    options?: boolean | AddEventListenerOptions\n  ): void\n  addEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions\n  ): void\n  removeEventListener<K extends keyof ProfilerEventMap>(\n    type: K,\n    listener: (this: typeof globalThis, ev: ProfilerEventMap[K]) => any,\n    options?: boolean | EventListenerOptions\n  ): void\n  removeEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | EventListenerOptions\n  ): void\n}\n\ninterface ProfilerEventMap {\n  samplebufferfull: SampleBufferFullEvent\n}\n\nexport interface SampleBufferFullEvent extends Event {\n  readonly target: Profiler\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/types/rumProfiler.types.ts",
    "content": "import type { TimeoutId, ClocksState } from '@datadog/browser-core'\nimport type { RumViewEntry } from '../../../types'\nimport type { LongTaskContext } from '../longTaskHistory'\nimport type { Profiler } from './profilerApi.types'\n\n/**\n * Additional data recorded during profiling session\n */\nexport interface RumProfilerEnrichmentData {\n  /** List of detected long tasks */\n  readonly longTasks: LongTaskContext[]\n  /** List of detected navigation entries */\n  readonly views: RumViewEntry[]\n}\n\n/**\n * Describes profiler session state when it's stopped\n */\nexport interface RumProfilerStoppedInstance {\n  readonly state: 'stopped'\n  readonly stateReason: 'session-expired' | 'stopped-by-user' | 'initializing'\n}\n\n/**\n * Describes profiler session state when it's paused\n * (this happens when user focuses on a different tab)\n */\nexport interface RumProfilerPausedInstance {\n  readonly state: 'paused'\n}\n\n/**\n * Describes profiler session state when it's running\n */\nexport interface RumProfilerRunningInstance extends RumProfilerEnrichmentData {\n  readonly state: 'running'\n  /** Current profiler instance */\n  readonly profiler: Profiler\n  /** High resolution time when profiler session started */\n  readonly startClocks: ClocksState\n  /** Timeout id to stop current session */\n  readonly timeoutId: TimeoutId\n  /** Clean-up tasks to execute after running the Profiler */\n  readonly cleanupTasks: Array<() => void>\n}\n\nexport type RumProfilerInstance = RumProfilerStoppedInstance | RumProfilerPausedInstance | RumProfilerRunningInstance\n\nexport interface RUMProfiler {\n  start: () => void\n  stop: () => void\n  isStopped: () => boolean\n  isRunning: () => boolean\n  isPaused: () => boolean\n}\n\nexport interface RUMProfilerConfiguration {\n  sampleIntervalMs: number // Sample stack trace every x milliseconds (defaults to 10ms for Unix, 16ms on Windows)\n  collectIntervalMs: number // Interval for collecting RUM Profiles (defaults to 1min)\n  minProfileDurationMs: number // Minimum duration of a profile for it be sent (defaults to 5s). Profiles shorter than this duration are discarded.\n  minNumberOfSamples: number // Minimum number of samples to be collected before it can be sent (defaults to 50). Profiles with fewer samples are discarded.\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/utils/getCustomOrDefaultViewName.spec.ts",
    "content": "import { getCustomOrDefaultViewName } from './getCustomOrDefaultViewName'\n\ndescribe('getCustomOrDefaultViewName', () => {\n  describe('when customViewName is provided', () => {\n    it('should return the custom view name when it is a non-empty string', () => {\n      expect(getCustomOrDefaultViewName('Custom View Name', '/user/123')).toBe('Custom View Name')\n    })\n\n    it('should return the default view name when it is an empty string', () => {\n      expect(getCustomOrDefaultViewName('', '/user/123')).toBe('/user/?')\n    })\n\n    it('should return the custom view name for various URL paths', () => {\n      expect(getCustomOrDefaultViewName('Home Page', '/')).toBe('Home Page')\n      expect(getCustomOrDefaultViewName('User Profile', '/user/342')).toBe('User Profile')\n      expect(getCustomOrDefaultViewName('API Endpoint', '/v1/user/3A2/profile')).toBe('API Endpoint')\n    })\n  })\n\n  describe('when customViewName is undefined', () => {\n    it('should fall back to default view name for empty path', () => {\n      expect(getCustomOrDefaultViewName(undefined, '')).toBe('/')\n    })\n\n    it('should fall back to default view name for simple path', () => {\n      expect(getCustomOrDefaultViewName(undefined, '/user/342')).toBe('/user/?')\n    })\n\n    it('should fall back to default view name for alphanumeric path', () => {\n      expect(getCustomOrDefaultViewName(undefined, '/user/3A2')).toBe('/user/?')\n    })\n\n    it('should fall back to default view name for versioned path', () => {\n      expect(getCustomOrDefaultViewName(undefined, '/v1/user/3A2')).toBe('/v1/user/?')\n    })\n\n    it('should fall back to default view name for complex path', () => {\n      expect(getCustomOrDefaultViewName(undefined, '/v1/user/3A2/profile/2A3')).toBe('/v1/user/?/profile/?')\n    })\n\n    it('should fall back to default view name for UUID path', () => {\n      expect(getCustomOrDefaultViewName(undefined, '/v1/user/dc893c65-a46d-4f63-a7be-e119b97b1b32/profile/2A3')).toBe(\n        '/v1/user/?/profile/?'\n      )\n    })\n  })\n\n  describe('edge cases', () => {\n    it('should handle null customViewName (treated as undefined)', () => {\n      expect(getCustomOrDefaultViewName(null as any, '/user/123')).toBe('/user/?')\n    })\n\n    it('should handle customViewName with special characters', () => {\n      expect(getCustomOrDefaultViewName('Special & Characters!', '/user/123')).toBe('Special & Characters!')\n    })\n\n    it('should handle very long custom view names', () => {\n      const longName = 'A'.repeat(1000)\n      expect(getCustomOrDefaultViewName(longName, '/user/123')).toBe(longName)\n    })\n\n    it('should handle customViewName that matches the default pattern', () => {\n      expect(getCustomOrDefaultViewName('/user/?', '/user/123')).toBe('/user/?')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/utils/getCustomOrDefaultViewName.ts",
    "content": "import { getDefaultViewName } from './getDefaultViewName'\n\nexport const getCustomOrDefaultViewName = (customViewName: string | undefined, viewPathUrl: string): string =>\n  customViewName || getDefaultViewName(viewPathUrl)\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/utils/getDefaultViewName.spec.ts",
    "content": "import { getDefaultViewName } from './getDefaultViewName'\n\n// Replicating the tests from SimpleUrlGroupingProcessorTest.java\ndescribe('getDefaultViewName', () => {\n  describe('url grouping', () => {\n    it('should handle empty path', () => {\n      expect(getDefaultViewName('')).toBe('/')\n    })\n\n    it('should handle simple URL path with numeric ID', () => {\n      expect(getDefaultViewName('/user/342')).toBe('/user/?')\n    })\n\n    it('should handle URL path with alphanumeric ID', () => {\n      expect(getDefaultViewName('/user/3A2')).toBe('/user/?')\n    })\n\n    it('should handle versioned URL path with alphanumeric ID', () => {\n      expect(getDefaultViewName('/v1/user/3A2')).toBe('/v1/user/?')\n    })\n\n    it('should handle versioned URL path with alphanumeric ID and additional segments', () => {\n      expect(getDefaultViewName('/v1/user/3A2/profile')).toBe('/v1/user/?/profile')\n    })\n\n    it('should handle multiple alphanumeric segments', () => {\n      expect(getDefaultViewName('/v1/user/3A2/profile/2A3')).toBe('/v1/user/?/profile/?')\n    })\n\n    it('should handle UUID and alphanumeric segments', () => {\n      expect(getDefaultViewName('/v1/user/dc893c65-a46d-4f63-a7be-e119b97b1b32/profile/2A3')).toBe(\n        '/v1/user/?/profile/?'\n      )\n    })\n\n    it('should not touch text-only segments', () => {\n      expect(getDefaultViewName('/v1/user/explorer')).toBe('/v1/user/explorer')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/utils/getDefaultViewName.ts",
    "content": "// This is the regex used to extract the path from the url (from SimpleUrlGroupingProcessor.java)\n// It's a bit different from the one in the java code because we removed the lookbehind unsupported by Safari.\nconst PATH_MIXED_ALPHANUMERICS = /\\/(?![vV]\\d{1,2}\\/)([^/\\d?]*\\d+[^/?]*)/g\n\nexport function getDefaultViewName(viewPathUrl: string): string {\n  if (!viewPathUrl) {\n    return '/'\n  }\n\n  // Replace all the mixed alphanumerics with a ?\n  return viewPathUrl.replace(PATH_MIXED_ALPHANUMERICS, '/?')\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/utils/getNumberOfSamples.spec.ts",
    "content": "import type { ProfilerSample } from '../types'\n\nimport { getNumberOfSamples } from './getNumberOfSamples'\n\ndescribe('getNumberOfSamples', () => {\n  it('returns 0 for empty array', () => {\n    const samples: ProfilerSample[] = []\n    const result = getNumberOfSamples(samples)\n    expect(result).toBe(0)\n  })\n\n  it('returns 0 for array with samples without stackId', () => {\n    const samples: ProfilerSample[] = [\n      { stackId: undefined, timestamp: 0 },\n      { stackId: undefined, timestamp: 1 },\n    ]\n    const result = getNumberOfSamples(samples)\n    expect(result).toBe(0)\n  })\n\n  it('returns 1 for array with one sample with stackId', () => {\n    const samples: ProfilerSample[] = [{ stackId: 1, timestamp: 0 }]\n    const result = getNumberOfSamples(samples)\n    expect(result).toBe(1)\n  })\n\n  it('returns 2 for array with two samples with stackId', () => {\n    const samples: ProfilerSample[] = [\n      { stackId: 1, timestamp: 0 },\n      { stackId: undefined, timestamp: 1 },\n      { stackId: 2, timestamp: 2 },\n    ]\n    const result = getNumberOfSamples(samples)\n    expect(result).toBe(2)\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/utils/getNumberOfSamples.ts",
    "content": "import type { ProfilerSample } from '../types'\n\n/**\n * Counts number of samples when the thread was not idle (stackId is defined)\n *\n * @param samples - Array of collected samples\n * @returns Number of samples\n */\nexport function getNumberOfSamples(samples: ProfilerSample[]): number {\n  let numberOfSamples = 0\n  for (const sample of samples) {\n    if (sample.stackId !== undefined) {\n      numberOfSamples++\n    }\n  }\n  return numberOfSamples\n}\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/vitalHistory.spec.ts",
    "content": "import { relativeToClocks, type Duration, type RelativeTime } from '@datadog/browser-core'\nimport { LifeCycle, LifeCycleEventType, RumEventType } from '@datadog/browser-rum-core'\nimport { createRawRumEvent } from '@datadog/browser-rum-core/test'\nimport { createVitalHistory } from './vitalHistory'\n\ndescribe('vitalHistory', () => {\n  let lifeCycle: LifeCycle\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n  })\n\n  const fakeDomainContext = {\n    performanceEntry: {} as PerformanceEntry,\n  }\n\n  describe('createVitalHistory', () => {\n    it('should create a history', () => {\n      const history = createVitalHistory(lifeCycle)\n      expect(history).toBeDefined()\n    })\n\n    it('should add vital information to history when RAW_RUM_EVENT_COLLECTED is triggered with vital event', () => {\n      const history = createVitalHistory(lifeCycle)\n      const startClocks = relativeToClocks(10 as RelativeTime)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-123',\n            name: 'vital-name',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks,\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(5 as RelativeTime, 30 as RelativeTime)).toEqual([\n        {\n          id: 'vital-123',\n          startClocks,\n          duration: 20 as Duration,\n          label: 'vital-name',\n        },\n      ])\n    })\n\n    it('should not add events to history for non-vital events', () => {\n      const history = createVitalHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW, {\n          view: {\n            id: 'view-123',\n          },\n        }),\n        startClocks: relativeToClocks(50 as RelativeTime),\n        duration: 10 as Duration,\n        domainContext: { location: window.location },\n      })\n\n      expect(history.findAll(40 as RelativeTime, 30 as RelativeTime)).toEqual([])\n    })\n\n    it('should store multiple vital IDs with their time ranges', () => {\n      const history = createVitalHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-1',\n            name: 'vital-name-1',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-2',\n            name: 'vital-name-2',\n            duration: 30 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(50 as RelativeTime),\n        duration: 30 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(5 as RelativeTime, 30 as RelativeTime).map((vital) => vital.id)).toEqual(['vital-1'])\n      expect(history.findAll(45 as RelativeTime, 40 as RelativeTime).map((vital) => vital.id)).toEqual(['vital-2'])\n      expect(history.findAll(0 as RelativeTime, 100 as RelativeTime).map((vital) => vital.id)).toEqual([\n        'vital-2',\n        'vital-1',\n      ])\n    })\n\n    it('should handle overlapping vital time ranges', () => {\n      const history = createVitalHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-1',\n            name: 'vital-name-1',\n            duration: 40 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 40 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-2',\n            name: 'vital-name-2',\n            duration: 40 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(30 as RelativeTime),\n        duration: 40 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      expect(history.findAll(35 as RelativeTime, 20 as RelativeTime).map((vital) => vital.id)).toEqual([\n        'vital-2',\n        'vital-1',\n      ])\n    })\n\n    it('should add a vital to the history with duration 0 when VITAL_STARTED is triggered', () => {\n      const history = createVitalHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.VITAL_STARTED, {\n        id: 'vital-1',\n        name: 'vital-name-1',\n        startClocks: relativeToClocks(10 as RelativeTime),\n      })\n\n      const matchingVitals = history.findAll(10 as RelativeTime, 10 as RelativeTime)\n\n      expect(matchingVitals[0].id).toEqual('vital-1')\n      expect(matchingVitals[0].duration).toBeUndefined()\n    })\n\n    it('should add a vital to the history when VITAL_STARTED is triggered, and close it when RAW_RUM_EVENT_COLLECTED is triggered', () => {\n      const history = createVitalHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.VITAL_STARTED, {\n        id: 'vital-1',\n        name: 'vital-name-1',\n        startClocks: relativeToClocks(10 as RelativeTime),\n      })\n\n      expect(history.findAll(10 as RelativeTime, 10 as RelativeTime).map((vital) => vital.id)).toEqual(['vital-1'])\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-1',\n            name: 'vital-name-1',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      const matchingVitals = history.findAll(10 as RelativeTime, 30 as RelativeTime)\n\n      expect(matchingVitals[0].id).toEqual('vital-1')\n      expect(matchingVitals[0].duration).toEqual(20 as Duration)\n    })\n\n    it('should be able to handle multiple vitals being started and stopped', () => {\n      const history = createVitalHistory(lifeCycle)\n\n      lifeCycle.notify(LifeCycleEventType.VITAL_STARTED, {\n        id: 'vital-1',\n        name: 'vital-name-1',\n        startClocks: relativeToClocks(10 as RelativeTime),\n      })\n\n      lifeCycle.notify(LifeCycleEventType.VITAL_STARTED, {\n        id: 'vital-2',\n        name: 'vital-name-2',\n        startClocks: relativeToClocks(10 as RelativeTime),\n      })\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-2',\n            name: 'vital-name-2',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      let matchingVitals = history.findAll(10 as RelativeTime, 30 as RelativeTime)\n\n      expect(matchingVitals.map((vital) => vital.id)).toEqual(['vital-2', 'vital-1'])\n\n      expect(matchingVitals.map((vital) => vital.duration)).toEqual([20 as Duration, undefined])\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent: createRawRumEvent(RumEventType.VITAL, {\n          vital: {\n            id: 'vital-1',\n            name: 'vital-name-1',\n            duration: 20 as Duration,\n          },\n        }),\n        startClocks: relativeToClocks(10 as RelativeTime),\n        duration: 20 as Duration,\n        domainContext: fakeDomainContext,\n      })\n\n      matchingVitals = history.findAll(10 as RelativeTime, 30 as RelativeTime)\n\n      expect(matchingVitals.map((vital) => vital.id)).toEqual(['vital-2', 'vital-1'])\n\n      expect(matchingVitals.map((vital) => vital.duration)).toEqual([20 as Duration, 20 as Duration])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/profiling/vitalHistory.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport { addDuration, createValueHistory, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core'\nimport type { LifeCycle } from '@datadog/browser-rum-core'\nimport { LifeCycleEventType } from '@datadog/browser-rum-core'\n\nexport const VITAL_ID_HISTORY_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY\n\nexport interface VitalContext {\n  id: string\n  label: string\n  duration?: Duration\n  startClocks: ClocksState\n}\n\nexport function createVitalHistory(lifeCycle: LifeCycle) {\n  const history = createValueHistory<VitalContext>({\n    expireDelay: VITAL_ID_HISTORY_TIME_OUT_DELAY,\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.VITAL_STARTED, (vitalStart) => {\n    history.add(\n      {\n        id: vitalStart.id,\n        startClocks: vitalStart.startClocks,\n        duration: undefined,\n        label: vitalStart.name,\n      },\n      vitalStart.startClocks.relative\n    )\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, ({ rawRumEvent, startClocks, duration }) => {\n    if (rawRumEvent.type === 'vital') {\n      const historyEntry = history\n        .getEntries(startClocks.relative)\n        .find((entry) => entry.value.id === rawRumEvent.vital.id)\n\n      if (historyEntry) {\n        historyEntry.value.duration = duration!\n        historyEntry.close(addDuration(startClocks.relative, duration!))\n      } else {\n        history\n          .add(\n            {\n              id: rawRumEvent.vital.id,\n              startClocks,\n              duration,\n              label: rawRumEvent.vital.name,\n            },\n            startClocks.relative\n          )\n          .close(addDuration(startClocks.relative, duration!))\n      }\n    }\n  })\n\n  return history\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/assembly.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport { timeStampNow } from '@datadog/browser-core'\nimport type { BrowserIncrementalData, BrowserIncrementalSnapshotRecord } from '../../types'\nimport { RecordType } from '../../types'\n\nexport function assembleIncrementalSnapshot<Data extends BrowserIncrementalData>(\n  source: Data['source'],\n  data: Omit<Data, 'source'>,\n  timestamp: TimeStamp = timeStampNow()\n): BrowserIncrementalSnapshotRecord {\n  return {\n    data: {\n      source,\n      ...data,\n    } as Data,\n    type: RecordType.IncrementalSnapshot,\n    timestamp,\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/elementsScrollPositions.ts",
    "content": "export type ElementsScrollPositions = ReturnType<typeof createElementsScrollPositions>\nexport interface ScrollPositions {\n  scrollLeft: number\n  scrollTop: number\n}\n\nexport function createElementsScrollPositions() {\n  const scrollPositionsByElement = new WeakMap<Element, ScrollPositions>()\n  return {\n    set(element: Element | Document, scrollPositions: ScrollPositions) {\n      if (element === document && !document.scrollingElement) {\n        // cf https://drafts.csswg.org/cssom-view/#dom-document-scrollingelement,\n        // in some cases scrolling elements can not be defined, we don't support those for now\n        return\n      }\n      scrollPositionsByElement.set(\n        element === document ? document.scrollingElement! : (element as Element),\n        scrollPositions\n      )\n    },\n    get(element: Element) {\n      return scrollPositionsByElement.get(element)\n    },\n    has(element: Element) {\n      return scrollPositionsByElement.has(element)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/eventsUtils.ts",
    "content": "import { isNodeShadowHost } from '@datadog/browser-rum-core'\n\nexport function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {\n  return Boolean((event as TouchEvent).changedTouches)\n}\n\nexport function getEventTarget(event: Event): Node {\n  if (event.composed === true && isNodeShadowHost(event.target as Node)) {\n    return event.composedPath()[0] as Node\n  }\n  return event.target as Node\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/index.ts",
    "content": "export { takeFullSnapshot, takeNodeSnapshot } from './internalApi'\nexport { record } from './record'\nexport type { ChangeDecoder, SerializationMetric, SerializationStats } from './serialization'\nexport {\n  aggregateSerializationStats,\n  createChangeDecoder,\n  createSerializationStats,\n  isFullSnapshotChangeRecordsEnabled,\n  isIncrementalSnapshotChangeRecordsEnabled,\n  serializeNode,\n} from './serialization'\nexport { createElementsScrollPositions } from './elementsScrollPositions'\nexport type { ShadowRootsController } from './shadowRootsController'\n"
  },
  {
    "path": "packages/rum/src/domain/record/internalApi.spec.ts",
    "content": "import { NodeType, RecordType, SnapshotFormat } from '../../types'\nimport { appendElement } from '../../../../rum-core/test'\nimport { takeFullSnapshot, takeNodeSnapshot } from './internalApi'\n\ndescribe('takeFullSnapshot', () => {\n  it('should produce Meta, Focus, and FullSnapshot records', () => {\n    expect(takeFullSnapshot()).toEqual(\n      jasmine.arrayContaining([\n        {\n          data: {\n            height: jasmine.any(Number),\n            href: window.location.href,\n            width: jasmine.any(Number),\n          },\n          type: RecordType.Meta,\n          timestamp: jasmine.any(Number),\n        },\n        {\n          data: {\n            has_focus: document.hasFocus(),\n          },\n          type: RecordType.Focus,\n          timestamp: jasmine.any(Number),\n        },\n        {\n          data: {\n            node: jasmine.any(Object),\n            initialOffset: {\n              left: jasmine.any(Number),\n              top: jasmine.any(Number),\n            },\n          },\n          format: SnapshotFormat.V1,\n          type: RecordType.FullSnapshot,\n          timestamp: jasmine.any(Number),\n        },\n      ])\n    )\n  })\n\n  it('should produce VisualViewport records when supported', () => {\n    if (!window.visualViewport) {\n      pending('visualViewport not supported')\n    }\n\n    expect(takeFullSnapshot()).toEqual(\n      jasmine.arrayContaining([\n        {\n          data: jasmine.any(Object),\n          type: RecordType.VisualViewport,\n          timestamp: jasmine.any(Number),\n        },\n      ])\n    )\n  })\n})\n\ndescribe('takeNodeSnapshot', () => {\n  it('should serialize nodes', () => {\n    const node = appendElement('<div>Hello <b>world</b></div>', document.body)\n    expect(takeNodeSnapshot(node)).toEqual({\n      type: NodeType.Element,\n      id: 0,\n      tagName: 'div',\n      isSVG: undefined,\n      attributes: {},\n      childNodes: [\n        {\n          type: NodeType.Text,\n          id: 1,\n          textContent: 'Hello ',\n        },\n        {\n          type: NodeType.Element,\n          id: 2,\n          tagName: 'b',\n          isSVG: undefined,\n          attributes: {},\n          childNodes: [\n            {\n              type: NodeType.Text,\n              id: 3,\n              textContent: 'world',\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  it('should serialize shadow hosts', () => {\n    const node = appendElement('<div>Hello</div>', document.body)\n    const shadowRoot = node.attachShadow({ mode: 'open' })\n    shadowRoot.appendChild(document.createTextNode('world'))\n    expect(takeNodeSnapshot(node)).toEqual({\n      type: NodeType.Element,\n      id: 0,\n      tagName: 'div',\n      isSVG: undefined,\n      attributes: {},\n      childNodes: [\n        {\n          type: NodeType.Text,\n          id: 1,\n          textContent: 'Hello',\n        },\n        {\n          type: NodeType.DocumentFragment,\n          id: 2,\n          isShadowRoot: true,\n          adoptedStyleSheets: undefined,\n          childNodes: [\n            {\n              type: NodeType.Text,\n              id: 3,\n              textContent: 'world',\n            },\n          ],\n        },\n      ],\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/internalApi.ts",
    "content": "import { noop, timeStampNow } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { getNodePrivacyLevel, NodePrivacyLevel } from '@datadog/browser-rum-core'\nimport type { BrowserRecord, SerializedNodeWithId } from '../../types'\nimport { takeFullSnapshot as doTakeFullSnapshot } from './startFullSnapshots'\nimport type { ShadowRootsController } from './shadowRootsController'\nimport type { RecordingScope } from './recordingScope'\nimport { createRecordingScope } from './recordingScope'\nimport { createElementsScrollPositions } from './elementsScrollPositions'\nimport type { EmitRecordCallback } from './record.types'\nimport type { SerializationTransaction } from './serialization'\nimport { SerializationKind, serializeInTransaction, serializeNode } from './serialization'\n\n/**\n * Take a full snapshot of the document, generating the same records that the browser SDK\n * would generate.\n *\n * This is an internal API function. Be sure to update Datadog-internal callers if you\n * change its signature or behavior.\n */\nexport function takeFullSnapshot({\n  configuration,\n}: { configuration?: Partial<RumConfiguration> } = {}): BrowserRecord[] {\n  const records: BrowserRecord[] = []\n  const emitRecord: EmitRecordCallback = (record: BrowserRecord) => {\n    records.push(record)\n  }\n\n  doTakeFullSnapshot(\n    timeStampNow(),\n    SerializationKind.INITIAL_FULL_SNAPSHOT,\n    emitRecord,\n    noop,\n    createTemporaryRecordingScope(configuration)\n  )\n\n  return records\n}\n\n/**\n * Take a snapshot of a DOM node, generating the serialized representation that the\n * browser SDK would generate.\n *\n * This is an internal API function. Be sure to update Datadog-internal callers if you\n * change its signature or behavior.\n */\nexport function takeNodeSnapshot(\n  node: Node,\n  { configuration }: { configuration?: Partial<RumConfiguration> } = {}\n): SerializedNodeWithId | null {\n  let serializedNode: SerializedNodeWithId | null = null\n\n  serializeInTransaction(\n    SerializationKind.INITIAL_FULL_SNAPSHOT,\n    noop,\n    noop,\n    createTemporaryRecordingScope(configuration),\n    (transaction: SerializationTransaction): void => {\n      const privacyLevel = getNodePrivacyLevel(node, transaction.scope.configuration.defaultPrivacyLevel)\n      if (privacyLevel === NodePrivacyLevel.HIDDEN || privacyLevel === NodePrivacyLevel.IGNORE) {\n        return\n      }\n      serializedNode = serializeNode(node, privacyLevel, transaction)\n    }\n  )\n\n  return serializedNode\n}\n\nfunction createTemporaryRecordingScope(configuration?: Partial<RumConfiguration>): RecordingScope {\n  return createRecordingScope(\n    {\n      defaultPrivacyLevel: NodePrivacyLevel.ALLOW,\n      ...configuration,\n    } as RumConfiguration,\n    createElementsScrollPositions(),\n    {\n      addShadowRoot: noop,\n      removeShadowRoot: noop,\n      flush: noop,\n      stop: noop,\n    } as ShadowRootsController\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/itemIds.spec.ts",
    "content": "import type { EventId, ItemIds, NodeId, StringId, StyleSheetId } from './itemIds'\nimport {\n  createEventIds,\n  createNodeIds,\n  createStringIds,\n  createStyleSheetIds,\n  EventIdConstants,\n  NodeIdConstants,\n  StringIdConstants,\n  StyleSheetIdConstants,\n} from './itemIds'\n\ndescribe('ItemIds', () => {\n  const describeItemIdVariant = <ItemType, ItemId extends number>(\n    name: string,\n    createIdMap: () => ItemIds<ItemType, ItemId>,\n    createItem: () => ItemType,\n    firstId: ItemId\n  ) => {\n    describe(name, () => {\n      let itemIds = createIdMap()\n\n      beforeEach(() => {\n        itemIds = createIdMap()\n      })\n\n      describe('clear', () => {\n        it('removes all id mappings', () => {\n          const item = createItem()\n          itemIds.getOrInsert(item)\n          expect(itemIds.get(item)).toBe(firstId)\n\n          itemIds.clear()\n          expect(itemIds.get(item)).toBeUndefined()\n        })\n\n        it('restarts the id sequence', () => {\n          for (let id = firstId; id < firstId + 3; id++) {\n            const item = createItem()\n            expect(itemIds.getOrInsert(item)).toBe(id)\n            expect(itemIds.getOrInsert(item)).toBe(id)\n          }\n\n          itemIds.clear()\n\n          for (let id = firstId; id < firstId + 3; id++) {\n            const item = createItem()\n            expect(itemIds.getOrInsert(item)).toBe(id)\n            expect(itemIds.getOrInsert(item)).toBe(id)\n          }\n        })\n      })\n\n      describe('delete', () => {\n        it('allows an item to be re-inserted and receive a new id', () => {\n          const item = createItem()\n          expect(itemIds.getOrInsert(item)).toBe(firstId)\n          expect(itemIds.getOrInsert(item)).toBe(firstId)\n\n          itemIds.delete(item)\n\n          expect(itemIds.getOrInsert(item)).toBe((firstId + 1) as ItemId)\n          expect(itemIds.getOrInsert(item)).toBe((firstId + 1) as ItemId)\n        })\n\n        it('does not change the next assigned id', () => {\n          const item = createItem()\n          expect(itemIds.getOrInsert(item)).toBe(firstId)\n          expect(itemIds.getOrInsert(item)).toBe(firstId)\n          expect(itemIds.nextId).toBe((firstId + 1) as ItemId)\n\n          itemIds.delete(item)\n          expect(itemIds.nextId).toBe((firstId + 1) as ItemId)\n\n          const newItem = createItem()\n          expect(itemIds.getOrInsert(newItem)).toBe((firstId + 1) as ItemId)\n          expect(itemIds.getOrInsert(newItem)).toBe((firstId + 1) as ItemId)\n        })\n      })\n\n      describe('get', () => {\n        it('returns undefined for items that have not been assigned an id', () => {\n          expect(itemIds.get(createItem())).toBe(undefined)\n        })\n\n        it('returns the assigned id if one exists', () => {\n          const item = createItem()\n          itemIds.getOrInsert(item)\n          expect(itemIds.get(item)).toBe(firstId)\n        })\n      })\n\n      describe('getOrInsert', () => {\n        it('assigns ids in order', () => {\n          for (let id = firstId; id < firstId + 3; id++) {\n            const item = createItem()\n            expect(itemIds.getOrInsert(item)).toBe(id)\n            expect(itemIds.getOrInsert(item)).toBe(id)\n          }\n        })\n\n        it('reuses any existing id', () => {\n          itemIds.getOrInsert(createItem())\n          itemIds.getOrInsert(createItem())\n          const item = createItem()\n          const itemId = itemIds.getOrInsert(item)\n          expect(itemIds.getOrInsert(item)).toBe(itemId)\n          expect(itemIds.get(item)).toBe(itemId)\n        })\n      })\n\n      describe('nextId getter', () => {\n        it('initially returns the first id', () => {\n          expect(itemIds.nextId).toBe(firstId)\n        })\n\n        it('increments after each insertion', () => {\n          for (let id = firstId; id < firstId + 3; id++) {\n            const item = createItem()\n            expect(itemIds.getOrInsert(item)).toBe(id)\n            expect(itemIds.getOrInsert(item)).toBe(id)\n            expect(itemIds.nextId).toBe((id + 1) as ItemId)\n          }\n        })\n      })\n\n      describe('size', () => {\n        it('increments when an id is assigned', () => {\n          expect(itemIds.size).toBe(0)\n          itemIds.getOrInsert(createItem())\n          expect(itemIds.size).toBe(1)\n          itemIds.getOrInsert(createItem())\n          expect(itemIds.size).toBe(2)\n        })\n      })\n    })\n  }\n\n  describeItemIdVariant(\n    'EventIds',\n    createEventIds,\n    () => new Event('someCustomEvent'),\n    EventIdConstants.FIRST_ID as EventId\n  )\n\n  describeItemIdVariant(\n    'NodeIds',\n    createNodeIds,\n    () => document.createElement('div'),\n    NodeIdConstants.FIRST_ID as NodeId\n  )\n\n  let nextString = 0\n  describeItemIdVariant(\n    'StringIds',\n    createStringIds,\n    () => `string${nextString++}`,\n    StringIdConstants.FIRST_ID as StringId\n  )\n\n  describeItemIdVariant(\n    'StyleSheetIds',\n    createStyleSheetIds,\n    // The CSSStyleSheet constructor is not available on older browsers.\n    () => ({ type: 'CSSStyleSheet' }),\n    StyleSheetIdConstants.FIRST_ID as StyleSheetId\n  )\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/itemIds.ts",
    "content": "export type EventId = number & { __brand: 'EventId' }\nexport type EventIds = ItemIds<Event, EventId>\nexport const enum EventIdConstants {\n  FIRST_ID = 1,\n}\nexport function createEventIds(): EventIds {\n  return createWeakIdMap(EventIdConstants.FIRST_ID as EventId)\n}\n\nexport type NodeId = number & { __brand: 'NodeId' }\nexport type NodeIds = ItemIds<Node, NodeId>\nexport const enum NodeIdConstants {\n  FIRST_ID = 0,\n}\nexport function createNodeIds(): NodeIds {\n  return createWeakIdMap(NodeIdConstants.FIRST_ID as NodeId)\n}\n\nexport type StringId = number & { __brand: 'StringId' }\nexport type StringIds = ItemIds<string, StringId>\nexport const enum StringIdConstants {\n  FIRST_ID = 0,\n}\nexport function createStringIds(): StringIds {\n  return createIdMap(StringIdConstants.FIRST_ID as StringId)\n}\n\nexport type StyleSheetId = number & { __brand: 'StyleSheetId' }\nexport type StyleSheetIds = ItemIds<CSSStyleSheet, StyleSheetId>\nexport const enum StyleSheetIdConstants {\n  FIRST_ID = 0,\n}\nexport function createStyleSheetIds(): StyleSheetIds {\n  return createWeakIdMap(StyleSheetIdConstants.FIRST_ID as StyleSheetId)\n}\n\nexport interface ItemIds<ItemType, ItemId extends number> {\n  clear(this: void): void\n  delete(this: void, item: ItemType): void\n  get(this: void, item: ItemType): ItemId | undefined\n  getOrInsert(this: void, item: ItemType): ItemId\n  get nextId(): ItemId\n  get size(): number\n}\n\nfunction createIdMap<ItemType, ItemId extends number>(firstId: ItemId): ItemIds<ItemType, ItemId> {\n  return createItemIds(() => new Map<ItemType, ItemId>(), firstId)\n}\n\nfunction createWeakIdMap<ItemType extends object, ItemId extends number>(firstId: ItemId): ItemIds<ItemType, ItemId> {\n  return createItemIds(() => new WeakMap<ItemType, ItemId>(), firstId)\n}\n\ninterface MapLike<Key, Value> {\n  delete(key: Key): void\n  get(key: Key): Value | undefined\n  set(key: Key, value: Value): void\n}\n\nfunction createItemIds<ItemType, ItemId extends number>(\n  createMap: () => MapLike<ItemType, ItemId>,\n  firstId: ItemId\n): ItemIds<ItemType, ItemId> {\n  let map = createMap()\n  let nextId = firstId\n\n  const get = (object: ItemType): ItemId | undefined => map.get(object)\n\n  return {\n    clear(): void {\n      if (nextId === firstId) {\n        return\n      }\n      map = createMap()\n      nextId = firstId\n    },\n    delete(object: ItemType): void {\n      map.delete(object)\n    },\n    get,\n    getOrInsert(object: ItemType): ItemId {\n      // Try to reuse any existing id.\n      let id = get(object)\n      if (id === undefined) {\n        id = nextId++ as ItemId\n        map.set(object, id)\n      }\n      return id\n    },\n    get nextId(): ItemId {\n      return nextId\n    },\n    get size(): number {\n      return nextId - firstId\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/mutationBatch.spec.ts",
    "content": "import type { Clock, RequestIdleCallbackMock } from '@datadog/browser-core/test'\nimport { mockClock, mockRequestIdleCallback } from '@datadog/browser-core/test'\nimport type { RumMutationRecord } from '@datadog/browser-rum-core'\nimport { MUTATION_PROCESS_MIN_DELAY, createMutationBatch } from './mutationBatch'\n\ndescribe('createMutationBatch', () => {\n  let mutationBatch: ReturnType<typeof createMutationBatch>\n  let processMutationBatchSpy: jasmine.Spy<(mutations: RumMutationRecord[]) => void>\n  let clock: Clock\n  let requestIdleCallbackMock: RequestIdleCallbackMock\n\n  beforeEach(() => {\n    clock = mockClock()\n    requestIdleCallbackMock = mockRequestIdleCallback()\n    processMutationBatchSpy = jasmine.createSpy()\n    mutationBatch = createMutationBatch(processMutationBatchSpy)\n  })\n\n  afterEach(() => {\n    mutationBatch.stop()\n  })\n\n  it('calls the callback asynchronously after MUTATION_PROCESS_MIN_DELAY', () => {\n    const mutation = { type: 'childList' } as RumMutationRecord\n    mutationBatch.addMutations([mutation])\n\n    expect(requestIdleCallbackMock.spy).toHaveBeenCalled()\n    expect(processMutationBatchSpy).not.toHaveBeenCalled()\n    requestIdleCallbackMock.idle()\n    clock.tick(MUTATION_PROCESS_MIN_DELAY)\n    expect(processMutationBatchSpy).toHaveBeenCalledWith([mutation])\n  })\n\n  it('calls the callback synchronously on flush', () => {\n    const mutation = { type: 'childList' } as RumMutationRecord\n    mutationBatch.addMutations([mutation])\n    mutationBatch.flush()\n\n    expect(processMutationBatchSpy).toHaveBeenCalledOnceWith([mutation])\n  })\n\n  it('appends mutations to the batch when adding more mutations', () => {\n    const mutation1 = { type: 'childList' } as RumMutationRecord\n    const mutation2 = { type: 'characterData' } as RumMutationRecord\n    const mutation3 = { type: 'attributes' } as RumMutationRecord\n    mutationBatch.addMutations([mutation1])\n    mutationBatch.addMutations([mutation2, mutation3])\n    mutationBatch.flush()\n\n    expect(processMutationBatchSpy).toHaveBeenCalledOnceWith([mutation1, mutation2, mutation3])\n  })\n\n  it('calls the callback on flush even if there is no pending mutation', () => {\n    mutationBatch.flush()\n\n    expect(processMutationBatchSpy).toHaveBeenCalledOnceWith([])\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/mutationBatch.ts",
    "content": "import { noop, throttle, requestIdleCallback } from '@datadog/browser-core'\nimport type { RumMutationRecord } from '@datadog/browser-rum-core'\n\n/**\n * Maximum duration to wait before processing mutations. If the browser is idle, mutations will be\n * processed more quickly. If the browser is busy executing small tasks (ex: rendering frames), the\n * mutations will wait MUTATION_PROCESS_MAX_DELAY milliseconds before being processed. If the\n * browser is busy executing a longer task, mutations will be processed after this task.\n */\nconst MUTATION_PROCESS_MAX_DELAY = 100\n/**\n * Minimum duration to wait before processing mutations. This is used to batch mutations together\n * and be able to deduplicate them to save processing time and bandwidth.\n * 16ms is the duration of a frame at 60fps that ensure fluid UI.\n */\nexport const MUTATION_PROCESS_MIN_DELAY = 16\n\nexport function createMutationBatch(processMutationBatch: (mutations: RumMutationRecord[]) => void) {\n  let cancelScheduledFlush = noop\n  let pendingMutations: RumMutationRecord[] = []\n\n  function flush() {\n    cancelScheduledFlush()\n    processMutationBatch(pendingMutations)\n    pendingMutations = []\n  }\n\n  const { throttled: throttledFlush, cancel: cancelThrottle } = throttle(flush, MUTATION_PROCESS_MIN_DELAY, {\n    leading: false,\n  })\n\n  return {\n    addMutations: (mutations: RumMutationRecord[]) => {\n      if (pendingMutations.length === 0) {\n        cancelScheduledFlush = requestIdleCallback(throttledFlush, { timeout: MUTATION_PROCESS_MAX_DELAY })\n      }\n      pendingMutations.push(...mutations)\n    },\n\n    flush,\n\n    stop: () => {\n      cancelScheduledFlush()\n      cancelThrottle()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/record.spec.ts",
    "content": "import { DefaultPrivacyLevel, findLast, noop } from '@datadog/browser-core'\nimport type { RumConfiguration, ViewCreatedEvent } from '@datadog/browser-rum-core'\nimport { LifeCycle, LifeCycleEventType } from '@datadog/browser-rum-core'\nimport { createNewEvent, collectAsyncCalls, registerCleanupTask } from '@datadog/browser-core/test'\nimport { findElement, findFullSnapshotInFormat, findNode, recordsPerFullSnapshot } from '../../../test'\nimport type {\n  BrowserIncrementalSnapshotRecord,\n  BrowserMutationData,\n  BrowserRecord,\n  DocumentFragmentNode,\n  ElementNode,\n  ScrollData,\n} from '../../types'\nimport { NodeType, RecordType, IncrementalSource, SnapshotFormat } from '../../types'\nimport { appendElement } from '../../../../rum-core/test'\nimport { getReplayStats } from '../replayStats'\nimport type { RecordAPI } from './record'\nimport { record } from './record'\nimport type { EmitRecordCallback } from './record.types'\n\ndescribe('record', () => {\n  let recordApi: RecordAPI\n  let lifeCycle: LifeCycle\n  let emitSpy: jasmine.Spy<EmitRecordCallback>\n  const FAKE_VIEW_ID = '123'\n\n  beforeEach(() => {\n    emitSpy = jasmine.createSpy()\n\n    registerCleanupTask(() => {\n      recordApi?.stop()\n    })\n  })\n\n  it('captures stylesheet rules', async () => {\n    const styleElement = appendElement('<style></style>') as HTMLStyleElement\n\n    startRecording()\n\n    const styleSheet = styleElement.sheet as CSSStyleSheet\n    const ruleIdx0 = styleSheet.insertRule('body { background: #000; }')\n    const ruleIdx1 = styleSheet.insertRule('body { background: #111; }')\n    styleSheet.deleteRule(ruleIdx1)\n    setTimeout(() => {\n      styleSheet.insertRule('body { color: #fff; }')\n    }, 0)\n    setTimeout(() => {\n      styleSheet.deleteRule(ruleIdx0)\n    }, 5)\n    setTimeout(() => {\n      styleSheet.insertRule('body { color: #ccc; }')\n    }, 10)\n\n    await collectAsyncCalls(emitSpy, recordsPerFullSnapshot() + 6)\n\n    const records = getEmittedRecords()\n    let i = 0\n\n    expect(records[i++].type).toEqual(RecordType.Meta)\n    expect(records[i++].type).toEqual(RecordType.Focus)\n    expect(records[i++].type).toEqual(RecordType.FullSnapshot)\n\n    if (window.visualViewport) {\n      expect(records[i++].type).toEqual(RecordType.VisualViewport)\n    }\n\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(\n      jasmine.objectContaining({\n        source: IncrementalSource.StyleSheetRule,\n        adds: [{ rule: 'body { background: #000; }', index: undefined }],\n      })\n    )\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(\n      jasmine.objectContaining({\n        source: IncrementalSource.StyleSheetRule,\n        adds: [{ rule: 'body { background: #111; }', index: undefined }],\n      })\n    )\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(\n      jasmine.objectContaining({\n        source: IncrementalSource.StyleSheetRule,\n        removes: [{ index: 0 }],\n      })\n    )\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(\n      jasmine.objectContaining({\n        source: IncrementalSource.StyleSheetRule,\n        adds: [{ rule: 'body { color: #fff; }', index: undefined }],\n      })\n    )\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(\n      jasmine.objectContaining({\n        source: IncrementalSource.StyleSheetRule,\n        removes: [{ index: 0 }],\n      })\n    )\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data).toEqual(\n      jasmine.objectContaining({\n        source: IncrementalSource.StyleSheetRule,\n        adds: [{ rule: 'body { color: #ccc; }', index: undefined }],\n      })\n    )\n  })\n\n  it('flushes pending mutation records before taking a full snapshot', async () => {\n    startRecording()\n\n    appendElement('<hr/>')\n\n    // trigger full snapshot by starting a new view\n    newView()\n\n    await collectAsyncCalls(emitSpy, 1 + 2 * recordsPerFullSnapshot())\n\n    const records = getEmittedRecords()\n    let i = 0\n\n    expect(records[i++].type).toEqual(RecordType.Meta)\n    expect(records[i++].type).toEqual(RecordType.Focus)\n    expect(records[i++].type).toEqual(RecordType.FullSnapshot)\n\n    if (window.visualViewport) {\n      expect(records[i++].type).toEqual(RecordType.VisualViewport)\n    }\n    expect(records[i].type).toEqual(RecordType.IncrementalSnapshot)\n    expect((records[i++] as BrowserIncrementalSnapshotRecord).data.source).toEqual(IncrementalSource.Mutation)\n    expect(records[i++].type).toEqual(RecordType.Meta)\n    expect(records[i++].type).toEqual(RecordType.Focus)\n    expect(records[i++].type).toEqual(RecordType.FullSnapshot)\n  })\n\n  describe('Shadow dom', () => {\n    it('should record a simple mutation inside a shadow root', () => {\n      const element = appendElement('<hr class=\"toto\" />', createShadow())\n      startRecording()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n\n      element.className = 'titi'\n\n      recordApi.flushMutations()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 1)\n      const innerMutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(innerMutationData.attributes[0].attributes.class).toBe('titi')\n    })\n\n    it('should record a direct removal inside a shadow root', () => {\n      const element = appendElement('<hr/>', createShadow())\n      startRecording()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n\n      element.remove()\n\n      recordApi.flushMutations()\n      const fs = findFullSnapshotInFormat(SnapshotFormat.V1, { records: getEmittedRecords() })!\n      const shadowRootNode = findNode(\n        fs.data.node,\n        (node) => node.type === NodeType.DocumentFragment && node.isShadowRoot\n      )!\n      expect(shadowRootNode).toBeTruthy()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 1)\n      const innerMutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(innerMutationData.removes.length).toBe(1)\n      expect(innerMutationData.removes[0].parentId).toBe(shadowRootNode.id)\n    })\n\n    it('should record a direct addition inside a shadow root', () => {\n      const shadowRoot = createShadow()\n      appendElement('<hr/>', shadowRoot)\n      startRecording()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n\n      appendElement('<span></span>', shadowRoot)\n\n      recordApi.flushMutations()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 1)\n      const fs = findFullSnapshotInFormat(SnapshotFormat.V1, { records: getEmittedRecords() })!\n      const shadowRootNode = findNode(\n        fs.data.node,\n        (node) => node.type === NodeType.DocumentFragment && node.isShadowRoot\n      )!\n      expect(shadowRootNode).toBeTruthy()\n      const innerMutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(innerMutationData.adds.length).toBe(1)\n      expect(innerMutationData.adds[0].node.type).toBe(2)\n      expect(innerMutationData.adds[0].parentId).toBe(shadowRootNode.id)\n      const addedNode = innerMutationData.adds[0].node as ElementNode\n      expect(addedNode.tagName).toBe('span')\n    })\n\n    it('should record mutation inside a shadow root added after the FS', () => {\n      startRecording()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n\n      // shadow DOM mutation\n      const span = appendElement('<span class=\"toto\"></span>', createShadow())\n      recordApi.flushMutations()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 1)\n      const hostMutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(hostMutationData.adds.length).toBe(1)\n      const hostNode = hostMutationData.adds[0].node as ElementNode\n      const shadowRoot = hostNode.childNodes[0] as DocumentFragmentNode\n      expect(shadowRoot.type).toBe(NodeType.DocumentFragment)\n      expect(shadowRoot.isShadowRoot).toBe(true)\n\n      // inner mutation\n      span.className = 'titi'\n      recordApi.flushMutations()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 2)\n      const innerMutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(innerMutationData.attributes.length).toBe(1)\n      expect(innerMutationData.attributes[0].attributes.class).toBe('titi')\n    })\n\n    it('should record the change event inside a shadow root', () => {\n      const radio = appendElement('<input type=\"radio\"/>', createShadow()) as HTMLInputElement\n      startRecording()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n\n      // inner mutation\n      radio.checked = true\n      radio.dispatchEvent(createNewEvent('change', { target: radio, composed: false }))\n\n      recordApi.flushMutations()\n      const innerMutationData = getLastIncrementalSnapshotData<BrowserMutationData & { isChecked: boolean }>(\n        getEmittedRecords(),\n        IncrementalSource.Input\n      )\n      expect(innerMutationData.isChecked).toBe(true)\n    })\n\n    it('should record the change event inside a shadow root only once, regardless if the DOM is serialized multiple times', () => {\n      const radio = appendElement('<input type=\"radio\"/>', createShadow()) as HTMLInputElement\n      startRecording()\n\n      // trigger full snapshot by starting a new view\n      newView()\n\n      radio.checked = true\n      radio.dispatchEvent(createNewEvent('change', { target: radio, composed: false }))\n\n      const inputRecords = getEmittedRecords().filter(\n        (record) => record.type === RecordType.IncrementalSnapshot && record.data.source === IncrementalSource.Input\n      )\n\n      expect(inputRecords.length).toBe(1)\n    })\n\n    it('should record the scroll event inside a shadow root', () => {\n      const div = appendElement('<div unique-selector=\"enabled\"></div>', createShadow()) as HTMLDivElement\n      startRecording()\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n\n      div.dispatchEvent(createNewEvent('scroll', { target: div, composed: false }))\n\n      recordApi.flushMutations()\n\n      const scrollRecords = getEmittedRecords().filter(\n        (record) => record.type === RecordType.IncrementalSnapshot && record.data.source === IncrementalSource.Scroll\n      )\n      expect(scrollRecords.length).toBe(1)\n\n      const scrollData = getLastIncrementalSnapshotData<ScrollData>(getEmittedRecords(), IncrementalSource.Scroll)\n\n      const fs = findFullSnapshotInFormat(SnapshotFormat.V1, { records: getEmittedRecords() })!\n      const scrollableNode = findElement(fs.data.node, (node) => node.attributes['unique-selector'] === 'enabled')!\n\n      expect(scrollData.id).toBe(scrollableNode.id)\n    })\n\n    it('should clean the state once the shadow dom is removed to avoid memory leak', () => {\n      const shadowRoot = createShadow()\n      appendElement('<div class=\"toto\"></div>', shadowRoot)\n      startRecording()\n      spyOn(recordApi.shadowRootsController, 'removeShadowRoot')\n\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n      expect(recordApi.shadowRootsController.removeShadowRoot).toHaveBeenCalledTimes(0)\n      shadowRoot.host.remove()\n      recordApi.flushMutations()\n      expect(recordApi.shadowRootsController.removeShadowRoot).toHaveBeenCalledTimes(1)\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 1)\n      const mutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(mutationData.removes.length).toBe(1)\n    })\n\n    it('should clean the state when both the parent and the shadow host is removed to avoid memory leak', () => {\n      const host = appendElement(`\n      <div id=\"grand-parent\">\n        <div id=\"parent\">\n          <div class=\"host\" target></div>\n        </div>\n      </div>`)\n      host.attachShadow({ mode: 'open' })\n      const parent = host.parentElement!\n      const grandParent = parent.parentElement!\n      appendElement('<div></div>', host.shadowRoot!)\n\n      startRecording()\n      spyOn(recordApi.shadowRootsController, 'removeShadowRoot')\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot())\n      expect(recordApi.shadowRootsController.removeShadowRoot).toHaveBeenCalledTimes(0)\n\n      parent.remove()\n      grandParent.remove()\n      recordApi.flushMutations()\n      expect(recordApi.shadowRootsController.removeShadowRoot).toHaveBeenCalledTimes(1)\n      expect(getEmittedRecords().length).toBe(recordsPerFullSnapshot() + 1)\n      const mutationData = getLastIncrementalSnapshotData<BrowserMutationData>(\n        getEmittedRecords(),\n        IncrementalSource.Mutation\n      )\n      expect(mutationData.removes.length).toBe(1)\n    })\n\n    function createShadow() {\n      const host = appendElement('<div></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n      return shadowRoot\n    }\n  })\n\n  describe('updates record replay stats', () => {\n    it('when recording new records', () => {\n      startRecording()\n\n      const records = getEmittedRecords()\n      expect(getReplayStats(FAKE_VIEW_ID)?.records_count).toEqual(records.length)\n    })\n  })\n\n  describe('should collect records', () => {\n    let div: HTMLDivElement\n    let input: HTMLInputElement\n    let audio: HTMLAudioElement\n    beforeEach(() => {\n      div = appendElement('<div target></div>') as HTMLDivElement\n      input = appendElement('<input target />') as HTMLInputElement\n      audio = appendElement('<audio controls autoplay target></audio>') as HTMLAudioElement\n      startRecording()\n      emitSpy.calls.reset()\n    })\n\n    it('move', () => {\n      document.body.dispatchEvent(createNewEvent('mousemove', { clientX: 1, clientY: 2 }))\n      expect(getEmittedRecords()[0].type).toBe(RecordType.IncrementalSnapshot)\n      expect((getEmittedRecords()[0] as BrowserIncrementalSnapshotRecord).data.source).toBe(IncrementalSource.MouseMove)\n    })\n\n    it('interaction', () => {\n      document.body.dispatchEvent(createNewEvent('click', { clientX: 1, clientY: 2 }))\n      expect((getEmittedRecords()[0] as BrowserIncrementalSnapshotRecord).data.source).toBe(\n        IncrementalSource.MouseInteraction\n      )\n    })\n\n    it('scroll', () => {\n      div.dispatchEvent(createNewEvent('scroll', { target: div }))\n\n      expect(getEmittedRecords()[0].type).toBe(RecordType.IncrementalSnapshot)\n      expect((getEmittedRecords()[0] as BrowserIncrementalSnapshotRecord).data.source).toBe(IncrementalSource.Scroll)\n    })\n\n    it('viewport resize', () => {\n      window.dispatchEvent(createNewEvent('resize'))\n\n      expect(getEmittedRecords()[0].type).toBe(RecordType.IncrementalSnapshot)\n      expect((getEmittedRecords()[0] as BrowserIncrementalSnapshotRecord).data.source).toBe(\n        IncrementalSource.ViewportResize\n      )\n    })\n\n    it('input', () => {\n      input.value = 'newValue'\n      input.dispatchEvent(createNewEvent('input', { target: input }))\n\n      expect(getEmittedRecords()[0].type).toBe(RecordType.IncrementalSnapshot)\n      expect((getEmittedRecords()[0] as BrowserIncrementalSnapshotRecord).data.source).toBe(IncrementalSource.Input)\n    })\n\n    it('media interaction', () => {\n      audio.dispatchEvent(createNewEvent('play', { target: audio }))\n\n      expect(getEmittedRecords()[0].type).toBe(RecordType.IncrementalSnapshot)\n      expect((getEmittedRecords()[0] as BrowserIncrementalSnapshotRecord).data.source).toBe(\n        IncrementalSource.MediaInteraction\n      )\n    })\n\n    it('focus', () => {\n      window.dispatchEvent(createNewEvent('blur'))\n\n      expect(getEmittedRecords()[0].type).toBe(RecordType.Focus)\n    })\n\n    it('visual viewport resize', () => {\n      if (!window.visualViewport) {\n        pending('visualViewport not supported')\n      }\n\n      visualViewport!.dispatchEvent(createNewEvent('resize'))\n      expect(getEmittedRecords()[0].type).toBe(RecordType.VisualViewport)\n    })\n\n    it('view end event', () => {\n      lifeCycle.notify(LifeCycleEventType.VIEW_ENDED, {} as any)\n\n      expect(getEmittedRecords()[0].type).toBe(RecordType.ViewEnd)\n    })\n  })\n\n  function startRecording() {\n    lifeCycle = new LifeCycle()\n    recordApi = record({\n      emitRecord: emitSpy,\n      emitStats: noop,\n      configuration: { defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW } as RumConfiguration,\n      lifeCycle,\n      viewHistory: {\n        findView: () => ({ id: FAKE_VIEW_ID, startClocks: {} }),\n      } as any,\n    })\n  }\n\n  function newView() {\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, {\n      startClocks: { relative: 0, timeStamp: 0 },\n    } as ViewCreatedEvent)\n  }\n\n  function getEmittedRecords() {\n    return emitSpy.calls.allArgs().map(([record]) => record)\n  }\n})\n\nexport function getLastIncrementalSnapshotData<T extends BrowserIncrementalSnapshotRecord['data']>(\n  records: BrowserRecord[],\n  source: IncrementalSource\n): T {\n  const record = findLast(\n    records,\n    (record): record is BrowserIncrementalSnapshotRecord & { data: T } =>\n      record.type === RecordType.IncrementalSnapshot && record.data.source === source\n  )\n  expect(record).toBeTruthy(`Could not find IncrementalSnapshot/${source} in ${records.length} records`)\n  return record!.data\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/record.ts",
    "content": "import { sendToExtension } from '@datadog/browser-core'\nimport type { LifeCycle, RumConfiguration, ViewHistory } from '@datadog/browser-rum-core'\nimport * as replayStats from '../replayStats'\nimport type { BrowserRecord } from '../../types'\nimport type { Tracker } from './trackers'\nimport {\n  trackFocus,\n  trackInput,\n  trackMediaInteraction,\n  trackMouseInteraction,\n  trackMove,\n  trackMutation,\n  trackScroll,\n  trackStyleSheet,\n  trackViewEnd,\n  trackViewportResize,\n  trackVisualViewportResize,\n} from './trackers'\nimport { createElementsScrollPositions } from './elementsScrollPositions'\nimport type { ShadowRootsController } from './shadowRootsController'\nimport { initShadowRootsController } from './shadowRootsController'\nimport { startFullSnapshots } from './startFullSnapshots'\nimport type { EmitRecordCallback, EmitStatsCallback } from './record.types'\nimport { createRecordingScope } from './recordingScope'\n\nexport interface RecordOptions {\n  emitRecord: EmitRecordCallback\n  emitStats: EmitStatsCallback\n  configuration: RumConfiguration\n  lifeCycle: LifeCycle\n  viewHistory: ViewHistory\n}\n\nexport interface RecordAPI {\n  stop: () => void\n  flushMutations: () => void\n  shadowRootsController: ShadowRootsController\n}\n\nexport function record(options: RecordOptions): RecordAPI {\n  const { emitRecord, emitStats, configuration, lifeCycle } = options\n  // runtime checks for user options\n  if (!emitRecord || !emitStats) {\n    throw new Error('emit functions are required')\n  }\n\n  const processRecord: EmitRecordCallback = (record: BrowserRecord) => {\n    emitRecord(record)\n    sendToExtension('record', { record })\n    const view = options.viewHistory.findView()!\n    replayStats.addRecord(view.id)\n  }\n\n  const shadowRootsController = initShadowRootsController(processRecord, emitStats)\n  const scope = createRecordingScope(configuration, createElementsScrollPositions(), shadowRootsController)\n\n  const { stop: stopFullSnapshots } = startFullSnapshots(lifeCycle, processRecord, emitStats, flushMutations, scope)\n\n  function flushMutations() {\n    shadowRootsController.flush()\n    mutationTracker.flush()\n  }\n\n  const mutationTracker = trackMutation(document, processRecord, emitStats, scope)\n  const trackers: Tracker[] = [\n    mutationTracker,\n    trackMove(processRecord, scope),\n    trackMouseInteraction(processRecord, scope),\n    trackScroll(document, processRecord, scope),\n    trackViewportResize(processRecord, scope),\n    trackInput(document, processRecord, scope),\n    trackMediaInteraction(processRecord, scope),\n    trackStyleSheet(processRecord, scope),\n    trackFocus(processRecord, scope),\n    trackVisualViewportResize(processRecord, scope),\n    trackViewEnd(lifeCycle, processRecord, flushMutations),\n  ]\n\n  return {\n    stop: () => {\n      shadowRootsController.stop()\n      trackers.forEach((tracker) => tracker.stop())\n      stopFullSnapshots()\n    },\n    flushMutations,\n    shadowRootsController,\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/record.types.ts",
    "content": "import type { RumMutationRecord } from '@datadog/browser-rum-core'\nimport type { TimeStamp } from '@datadog/browser-core'\nimport type { BrowserFullSnapshotRecord, BrowserIncrementalSnapshotRecord, BrowserRecord } from '../../types'\nimport type { SerializationKind, SerializationStats } from './serialization'\n\nexport type EmitRecordCallback<Record extends BrowserRecord = BrowserRecord> = (record: Record) => void\nexport type EmitStatsCallback = (stats: SerializationStats) => void\n\nexport type SerializeEvent =\n  | {\n      type: 'full'\n      kind: SerializationKind\n      target: Document\n      timestamp: TimeStamp\n      v1: BrowserFullSnapshotRecord\n    }\n  | {\n      type: 'incremental'\n      target: RumMutationRecord[]\n      timestamp: TimeStamp\n      v1: BrowserIncrementalSnapshotRecord\n    }\n"
  },
  {
    "path": "packages/rum/src/domain/record/recordingScope.ts",
    "content": "import type { RumConfiguration } from '@datadog/browser-rum-core'\n\nimport { Observable } from '@datadog/browser-core'\nimport type { ElementsScrollPositions } from './elementsScrollPositions'\nimport { createEventIds, createNodeIds, createStringIds, createStyleSheetIds } from './itemIds'\nimport type { EventIds, NodeIds, StringIds, StyleSheetIds } from './itemIds'\nimport type { ShadowRootsController } from './shadowRootsController'\nimport type { SerializeEvent } from './record.types'\n\n/**\n * State associated with a stream of session replay records. When a new stream of records\n * starts (e.g. because recording has shut down and restarted), a new RecordingScope\n * object must be created; this ensures that we don't generate records that reference ids\n * or data which aren't present in the current stream.\n */\nexport interface RecordingScope {\n  resetIds(): void\n\n  configuration: RumConfiguration\n  elementsScrollPositions: ElementsScrollPositions\n  eventIds: EventIds\n  nodeIds: NodeIds\n  serializeObservable: Observable<SerializeEvent>\n  shadowRootsController: ShadowRootsController\n  stringIds: StringIds\n  styleSheetIds: StyleSheetIds\n}\n\nexport function createRecordingScope(\n  configuration: RumConfiguration,\n  elementsScrollPositions: ElementsScrollPositions,\n  shadowRootsController: ShadowRootsController\n): RecordingScope {\n  const eventIds = createEventIds()\n  const nodeIds = createNodeIds()\n  const stringIds = createStringIds()\n  const styleSheetIds = createStyleSheetIds()\n\n  const scope: RecordingScope = {\n    resetIds(): void {\n      scope.eventIds.clear()\n      scope.nodeIds.clear()\n      scope.stringIds.clear()\n      scope.styleSheetIds.clear()\n    },\n\n    configuration,\n    elementsScrollPositions,\n    eventIds,\n    nodeIds,\n    serializeObservable: new Observable<SerializeEvent>(),\n    shadowRootsController,\n    stringIds,\n    styleSheetIds,\n  }\n\n  return scope\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/changeEncoder.spec.ts",
    "content": "import { ChangeType } from '../../../types'\nimport type { StringId } from '../itemIds'\nimport { createStringIds } from '../itemIds'\nimport type { ChangeEncoder } from './changeEncoder'\nimport { createChangeEncoder } from './changeEncoder'\n\ndescribe('ChangeEncoder', () => {\n  let encoder: ChangeEncoder\n  let stringIds: ReturnType<typeof createStringIds>\n\n  beforeEach(() => {\n    stringIds = createStringIds()\n    encoder = createChangeEncoder(stringIds)\n  })\n\n  it('handles a realistic DOM mutation sequence', () => {\n    encoder.add(ChangeType.AddNode, [null, 'div', ['class', 'container'], ['id', 'main']])\n    encoder.add(ChangeType.AddNode, [0, '#text', 'Hello World'])\n    encoder.add(ChangeType.Size, [0, 800, 600])\n\n    const changes = encoder.flush()\n    expect(changes).toEqual([\n      [ChangeType.AddString, 'div', 'class', 'container', 'id', 'main', '#text', 'Hello World'],\n      [ChangeType.AddNode, [null, 0, [1, 2], [3, 4]], [0, 5, 6]],\n      [ChangeType.Size, [0, 800, 600]],\n    ])\n  })\n\n  describe('add', () => {\n    it('adds a single change to the encoder', () => {\n      encoder.add(ChangeType.Size, [0, 100, 200])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([[ChangeType.Size, [0, 100, 200]]])\n    })\n\n    it('converts strings in change data to string table references', () => {\n      encoder.add(ChangeType.Text, [0, 'Hello World'])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.AddString, 'Hello World'],\n        [ChangeType.Text, [0, 0 as StringId]],\n      ])\n    })\n\n    it('reuses existing string table references for duplicate strings', () => {\n      encoder.add(ChangeType.Text, [0, 'foo'])\n      encoder.add(ChangeType.Text, [1, 'bar'])\n      encoder.add(ChangeType.Text, [2, 'foo']) // Duplicate of first string\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.AddString, 'foo', 'bar'],\n        [ChangeType.Text, [0, 0 as StringId], [1, 1 as StringId], [2, 0 as StringId]],\n      ])\n    })\n\n    it('converts strings to string table references at multiple nesting levels', () => {\n      encoder.add(ChangeType.AddNode, [null, 'div', ['class', 'container'], ['span', 'text']])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.AddString, 'div', 'class', 'container', 'span', 'text'],\n        [ChangeType.AddNode, [null, 0 as StringId, [1 as StringId, 2 as StringId], [3 as StringId, 4 as StringId]]],\n      ])\n    })\n\n    it('does not convert strings for AddString changes', () => {\n      encoder.add(ChangeType.AddString, 'test-string')\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([[ChangeType.AddString, 'test-string']])\n    })\n\n    it('preserves non-string primitive values', () => {\n      encoder.add(ChangeType.Size, [5, 100, 200])\n      encoder.add(ChangeType.ScrollPosition, [10, 50, 75])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.Size, [5, 100, 200]],\n        [ChangeType.ScrollPosition, [10, 50, 75]],\n      ])\n    })\n\n    it('groups multiple changes of the same type', () => {\n      encoder.add(ChangeType.Size, [0, 100, 200])\n      encoder.add(ChangeType.Size, [1, 300, 400])\n      encoder.add(ChangeType.Size, [2, 500, 600])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([[ChangeType.Size, [0, 100, 200], [1, 300, 400], [2, 500, 600]]])\n    })\n\n    it('handles mixed change types', () => {\n      encoder.add(ChangeType.Size, [0, 100, 200])\n      encoder.add(ChangeType.ScrollPosition, [1, 10, 20])\n      encoder.add(ChangeType.Size, [2, 300, 400])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.Size, [0, 100, 200], [2, 300, 400]],\n        [ChangeType.ScrollPosition, [1, 10, 20]],\n      ])\n    })\n\n    it('handles empty strings', () => {\n      encoder.add(ChangeType.Text, [0, ''])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.AddString, ''],\n        [ChangeType.Text, [0, 0 as StringId]],\n      ])\n    })\n\n    it('uses existing string ids from the string table', () => {\n      // Pre-populate the string table.\n      const preExistingId = stringIds.getOrInsert('pre-existing')\n\n      encoder.add(ChangeType.Text, [0, 'pre-existing'])\n      encoder.add(ChangeType.Text, [1, 'new-string'])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([\n        [ChangeType.AddString, 'new-string'], // Only the new string is added.\n        [ChangeType.Text, [0, preExistingId], [1, 1 as StringId]],\n      ])\n    })\n\n    it('maintains string table across multiple flushes', () => {\n      encoder.add(ChangeType.Text, [0, 'persistent'])\n      encoder.flush()\n\n      encoder.add(ChangeType.Text, [1, 'persistent'])\n      const changes = encoder.flush()\n\n      // The second flush should not have an AddString change for 'persistent'.\n      expect(changes).toEqual([[ChangeType.Text, [1, 0 as StringId]]])\n    })\n  })\n\n  describe('flush', () => {\n    it('returns an empty array when no changes have been added', () => {\n      const changes = encoder.flush()\n      expect(changes).toEqual([])\n    })\n\n    it('clears the buffer after flushing', () => {\n      encoder.add(ChangeType.Size, [0, 100, 200])\n      encoder.flush()\n\n      const secondFlush = encoder.flush()\n      expect(secondFlush).toEqual([])\n    })\n\n    it('allows adding new changes after flushing', () => {\n      encoder.add(ChangeType.Size, [0, 100, 200])\n      encoder.flush()\n\n      encoder.add(ChangeType.ScrollPosition, [1, 10, 20])\n      const changes = encoder.flush()\n\n      expect(changes).toEqual([[ChangeType.ScrollPosition, [1, 10, 20]]])\n    })\n\n    it('respects dependency order for all change types', () => {\n      encoder.add(ChangeType.VisualViewport, [100, 200, 100, 200, 100, 200, 300])\n      encoder.add(ChangeType.MediaPlaybackState, [0, 0])\n      encoder.add(ChangeType.AttachedStyleSheets, [0, 1, 2])\n      encoder.add(ChangeType.AddStyleSheet, [['rule1']])\n      encoder.add(ChangeType.ScrollPosition, [0, 10, 20])\n      encoder.add(ChangeType.Size, [0, 100, 200])\n      encoder.add(ChangeType.Text, [0, 'text'])\n      encoder.add(ChangeType.Attribute, [0, ['id', 'test']])\n      encoder.add(ChangeType.RemoveNode, 1)\n      encoder.add(ChangeType.AddNode, [null, 'div'])\n\n      const changes = encoder.flush()\n\n      // Ensure that the flushed changes are ordered in a way that respects potential\n      // dependencies between them.\n      const changeTypes = changes.map((change) => change[0])\n      expect(changeTypes).toEqual([\n        ChangeType.AddString, // Automatically added for strings.\n        ChangeType.AddNode,\n        ChangeType.RemoveNode,\n        ChangeType.Attribute,\n        ChangeType.Text,\n        ChangeType.Size,\n        ChangeType.ScrollPosition,\n        ChangeType.AddStyleSheet,\n        ChangeType.AttachedStyleSheets,\n        ChangeType.MediaPlaybackState,\n        ChangeType.VisualViewport,\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/changeEncoder.ts",
    "content": "import type { Change } from '../../../types'\nimport { ChangeType } from '../../../types'\nimport type { StringIds } from '../itemIds'\n\ntype ChangeData<T extends ChangeType> =\n  Extract<Change, [T, ...unknown[]]> extends [T, ...infer Rest] ? Rest[number] : never\n\n/**\n * ChangeEncoder handles the low-level work of building compact, optimized sequences of\n * Changes. In particular, it:\n * - Converts literal strings to string table references, to eliminate the duplication\n * of transferring the same strings repeatedly.\n * - Groups changes by type, instead of transmitting them strictly in order, so that we\n * can avoid transmitting a separate Change data structure with an independent type tag\n * for each small mutation. (It's safe to do this for changes that occur within the same\n * SerializationTransaction since they logically happen at the same time.)\n */\nexport interface ChangeEncoder {\n  /** Encode a Change of the given type and add it to the internal buffer. */\n  add<T extends ChangeType>(type: T, data: ChangeData<T>): void\n  /** Flush the internal buffer, returning all Changes added since the last flush(). */\n  flush(): Change[]\n}\n\nexport function createChangeEncoder(stringIds: StringIds): ChangeEncoder {\n  let pendingChanges: Partial<Record<ChangeType, unknown[]>> = {}\n\n  // A helper that searches for strings in arbitrarily-nested arrays, inserts any strings\n  // it finds into the string table, and replaces the strings with string table\n  // references.\n  const convertStringsToStringReferences = (array: any[]): void => {\n    for (let index = 0, length = array.length; index < length; index++) {\n      const item = array[index]\n      if (typeof item === 'string') {\n        const previousSize = stringIds.size\n        array[index] = stringIds.getOrInsert(item)\n        if (stringIds.size > previousSize) {\n          add(ChangeType.AddString, item)\n        }\n      } else if (Array.isArray(item)) {\n        convertStringsToStringReferences(item)\n      }\n    }\n  }\n\n  const add = <T extends ChangeType>(type: T, data: ChangeData<T>): void => {\n    if (!(type in pendingChanges)) {\n      pendingChanges[type] = [type]\n    }\n    if (type !== ChangeType.AddString && Array.isArray(data)) {\n      convertStringsToStringReferences(data)\n    }\n    pendingChanges[type]!.push(data)\n  }\n\n  const flush = (): Change[] => {\n    const changes: Change[] = []\n\n    // Place all changes into a single array. Because the player always just plays back\n    // the changes in order, the ordering of the changes matters; if a dependency can\n    // exist between two kinds of change, then the dependent change must come after the\n    // change it depends on. This list defines an ordering that ensures that these\n    // dependencies are always satisfied.\n    ;[\n      ChangeType.AddString,\n      ChangeType.AddNode,\n      ChangeType.RemoveNode,\n      ChangeType.Attribute,\n      ChangeType.Text,\n      ChangeType.Size,\n      ChangeType.ScrollPosition,\n      ChangeType.AddStyleSheet,\n      ChangeType.AttachedStyleSheets,\n      ChangeType.MediaPlaybackState,\n      ChangeType.VisualViewport,\n    ].forEach((changeType: ChangeType): void => {\n      const change = pendingChanges[changeType]\n      if (change) {\n        changes.push(change as Change)\n      }\n    })\n\n    pendingChanges = {}\n\n    return changes\n  }\n\n  return { add, flush }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/changeConverter.ts",
    "content": "import type {\n  AddDocTypeNodeChange,\n  AddElementNodeChange,\n  AddNodeChange,\n  AddStyleSheetChange,\n  AddTextNodeChange,\n  AttachedStyleSheetsChange,\n  AttributeChange,\n  BrowserChangeRecord,\n  BrowserFullSnapshotChangeRecord,\n  BrowserFullSnapshotV1Record,\n  BrowserIncrementalSnapshotRecord,\n  MediaPlaybackStateChange,\n  RemoveNodeChange,\n  ScrollPositionChange,\n  SizeChange,\n  TextChange,\n} from '../../../../types'\nimport { ChangeType } from '../../../../types'\nimport type { NodeId, StyleSheetId } from '../../itemIds'\nimport type { V1RenderOptions } from './renderOptions'\nimport type { StringTable } from './stringTable'\nimport { createStringTable } from './stringTable'\nimport type { VDocument } from './vDocument'\nimport { createVDocument } from './vDocument'\nimport type { VNode } from './vNode'\n\nexport interface ChangeConverter {\n  convert(\n    record: BrowserChangeRecord | BrowserFullSnapshotChangeRecord,\n    options?: Partial<V1RenderOptions>\n  ): BrowserFullSnapshotV1Record | BrowserIncrementalSnapshotRecord\n\n  document: VDocument\n  stringTable: StringTable\n}\n\nexport function createChangeConverter(): ChangeConverter {\n  const self: ChangeConverter = {\n    convert(\n      record: BrowserChangeRecord | BrowserFullSnapshotChangeRecord,\n      options: Partial<V1RenderOptions> = {}\n    ): BrowserFullSnapshotV1Record | BrowserIncrementalSnapshotRecord {\n      applyChangeToVDOM(record, self.document, self.stringTable)\n      return self.document.render({ timestamp: record.timestamp, ...options })\n    },\n\n    document: createVDocument(),\n    stringTable: createStringTable(),\n  }\n\n  return self\n}\n\nfunction applyChangeToVDOM(\n  record: BrowserChangeRecord | BrowserFullSnapshotChangeRecord,\n  document: VDocument,\n  stringTable: StringTable\n): void {\n  document.mutations.clear()\n\n  for (const change of record.data) {\n    switch (change[0]) {\n      case ChangeType.AddString: {\n        for (let i = 1; i < change.length; i++) {\n          stringTable.add(change[i] as string)\n        }\n        break\n      }\n\n      case ChangeType.AddNode: {\n        for (let i = 1; i < change.length; i++) {\n          applyAddNodeChange(change[i] as AddNodeChange, document, stringTable)\n        }\n        break\n      }\n\n      case ChangeType.RemoveNode: {\n        for (let i = 1; i < change.length; i++) {\n          applyRemoveNodeChange(change[i], document)\n        }\n        break\n      }\n\n      case ChangeType.Attribute: {\n        for (let i = 1; i < change.length; i++) {\n          applyAttributeChange(change[i] as AttributeChange, document, stringTable)\n        }\n        break\n      }\n\n      case ChangeType.Text: {\n        for (let i = 1; i < change.length; i++) {\n          applyTextChange(change[i] as TextChange, document, stringTable)\n        }\n        break\n      }\n\n      case ChangeType.ScrollPosition: {\n        for (let i = 1; i < change.length; i++) {\n          applyScrollPositionChange(change[i] as ScrollPositionChange, document)\n        }\n        break\n      }\n\n      case ChangeType.Size: {\n        for (let i = 1; i < change.length; i++) {\n          applySizeChange(change[i] as SizeChange, document)\n        }\n        break\n      }\n\n      case ChangeType.AddStyleSheet: {\n        for (let i = 1; i < change.length; i++) {\n          applyAddStyleSheetChange(change[i] as AddStyleSheetChange, document, stringTable)\n        }\n        break\n      }\n\n      case ChangeType.AttachedStyleSheets: {\n        for (let i = 1; i < change.length; i++) {\n          applyAttachedStyleSheetsChange(change[i] as AttachedStyleSheetsChange, document)\n        }\n        break\n      }\n\n      case ChangeType.MediaPlaybackState: {\n        for (let i = 1; i < change.length; i++) {\n          applyMediaPlaybackStateChange(change[i] as MediaPlaybackStateChange, document)\n        }\n        break\n      }\n\n      case ChangeType.VisualViewport:\n        // Not yet supported.\n        break\n\n      default:\n        change satisfies never\n        throw new Error(`Unsupported BrowserChangeType: ${change[0] as any}`)\n    }\n  }\n}\n\nfunction applyAddNodeChange(addedNode: AddNodeChange, document: VDocument, stringTable: StringTable): void {\n  const nodeName = stringTable.decode(addedNode[1])\n\n  let node: VNode\n  switch (nodeName) {\n    case '#cdata-section':\n      node = document.createNode({ kind: '#cdata-section' })\n      break\n\n    case '#doctype': {\n      const [, , name, publicId, systemId] = addedNode as AddDocTypeNodeChange\n      node = document.createNode({\n        kind: '#doctype',\n        name: stringTable.decode(name),\n        publicId: stringTable.decode(publicId),\n        systemId: stringTable.decode(systemId),\n      })\n      break\n    }\n\n    case '#document':\n      node = document.createNode({ kind: '#document' })\n      break\n\n    case '#document-fragment':\n      node = document.createNode({ kind: '#document-fragment' })\n      break\n\n    case '#shadow-root':\n      node = document.createNode({ kind: '#shadow-root' })\n      break\n\n    case '#text': {\n      const [, , textContent] = addedNode as AddTextNodeChange\n      node = document.createNode({\n        kind: '#text',\n        textContent: stringTable.decode(textContent),\n      })\n      break\n    }\n\n    default: {\n      let tagName: string\n      let isSVG = false\n      if (nodeName.startsWith('svg>')) {\n        tagName = nodeName.substring(4).toLowerCase()\n        isSVG = true\n      } else {\n        tagName = nodeName.toLowerCase()\n      }\n\n      const [, , ...attributeAssignments] = addedNode as AddElementNodeChange\n      const attributes: Record<string, string> = {}\n      for (const [name, value] of attributeAssignments) {\n        attributes[stringTable.decode(name)] = stringTable.decode(value)\n      }\n\n      node = document.createNode({ kind: '#element', tag: tagName, attributes, isSVG })\n      break\n    }\n  }\n\n  const insertionPoint = addedNode[0]\n  if (insertionPoint === null) {\n    document.root = node\n  } else if (insertionPoint === 0) {\n    const previousSiblingId = (node.id - 1) as NodeId\n    const previousSibling = document.getNodeById(previousSiblingId)\n    previousSibling.after(node)\n  } else if (insertionPoint > 0) {\n    const parentId = (node.id - insertionPoint) as NodeId\n    const parent = document.getNodeById(parentId)\n    parent.appendChild(node)\n  } else {\n    const nextSiblingId = (node.id + insertionPoint) as NodeId\n    const nextSibling = document.getNodeById(nextSiblingId)\n    nextSibling.before(node)\n  }\n}\n\nfunction applyAddStyleSheetChange(change: AddStyleSheetChange, document: VDocument, stringTable: StringTable): void {\n  const [encodedRules, encodedMediaList = [], disabled = false] = change\n  const rules: string | string[] = Array.isArray(encodedRules)\n    ? encodedRules.map((rule) => stringTable.decode(rule))\n    : stringTable.decode(encodedRules)\n  const mediaList = encodedMediaList.map((item) => stringTable.decode(item))\n  document.createStyleSheet({ rules, mediaList, disabled })\n}\n\nfunction applyAttachedStyleSheetsChange(change: AttachedStyleSheetsChange, document: VDocument): void {\n  const [nodeId, ...sheetIds] = change\n  const node = document.getNodeById(nodeId as NodeId)\n  node.setAttachedStyleSheets(sheetIds.map((sheetId) => document.getStyleSheetById(sheetId as StyleSheetId)))\n}\n\nfunction applyAttributeChange(change: AttributeChange, document: VDocument, stringTable: StringTable): void {\n  const [nodeId, ...attributeMutations] = change\n  const node = document.getNodeById(nodeId as NodeId)\n  for (const [nameOrId, valueOrId = null] of attributeMutations) {\n    const name = stringTable.decode(nameOrId)\n    if (valueOrId === null) {\n      node.setAttribute(name, null)\n    } else {\n      const value = stringTable.decode(valueOrId)\n      node.setAttribute(name, value)\n    }\n  }\n}\n\nfunction applyMediaPlaybackStateChange(change: MediaPlaybackStateChange, document: VDocument): void {\n  const [nodeId, playbackState] = change\n  const node = document.getNodeById(nodeId as NodeId)\n  node.setPlaybackState(playbackState)\n}\n\nfunction applyRemoveNodeChange(change: RemoveNodeChange, document: VDocument): void {\n  const nodeId = change as NodeId\n  const node = document.getNodeById(nodeId)\n  node.remove()\n}\n\nfunction applyScrollPositionChange(change: ScrollPositionChange, document: VDocument): void {\n  const [nodeId, left, top] = change\n  const node = document.getNodeById(nodeId as NodeId)\n  node.setScrollPosition(left, top)\n}\n\nfunction applySizeChange(change: SizeChange, document: VDocument): void {\n  const [nodeId, width, height] = change\n  const node = document.getNodeById(nodeId as NodeId)\n  node.setSize(width, height)\n}\n\nfunction applyTextChange(change: TextChange, document: VDocument, stringTable: StringTable): void {\n  const [nodeId, textContent] = change\n  const node = document.getNodeById(nodeId as NodeId)\n  node.setTextContent(stringTable.decode(textContent))\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/changeDecoder.ts",
    "content": "import { ChangeType } from '../../../../types'\nimport type {\n  AddDocTypeNodeChange,\n  AddElementNodeChange,\n  AddNodeChange,\n  AddStyleSheetChange,\n  AddTextNodeChange,\n  AttributeAssignmentOrDeletion,\n  AttributeChange,\n  BrowserChangeRecord,\n  BrowserFullSnapshotChangeRecord,\n  Change,\n  StyleSheetRules,\n  TextChange,\n} from '../../../../types'\nimport type { StringTable } from './stringTable'\nimport { createStringTable } from './stringTable'\n\n/**\n * ChangeDecoder converts a BrowserChangeRecord, or a stream of BrowserChangeRecords, into\n * a more human-readable form by:\n * - Removing AddString changes (string table definitions).\n * - Replacing string table references in all other changes with their literal values.\n *\n * This makes it easier to visualize the contents of BrowserChangeRecords or to write test\n * expectations against the record's content.\n */\nexport interface ChangeDecoder {\n  decode(\n    record: BrowserChangeRecord | BrowserFullSnapshotChangeRecord\n  ): BrowserChangeRecord | BrowserFullSnapshotChangeRecord\n\n  stringTable: StringTable\n}\n\nexport function createChangeDecoder(): ChangeDecoder {\n  const self: ChangeDecoder = {\n    decode(\n      record: BrowserChangeRecord | BrowserFullSnapshotChangeRecord\n    ): BrowserChangeRecord | BrowserFullSnapshotChangeRecord {\n      return decodeChangeRecord(record, self.stringTable)\n    },\n\n    stringTable: createStringTable(),\n  }\n\n  return self\n}\n\nfunction decodeChangeRecord(\n  record: BrowserChangeRecord | BrowserFullSnapshotChangeRecord,\n  stringTable: StringTable\n): BrowserChangeRecord | BrowserFullSnapshotChangeRecord {\n  const decodedData: Change[] = []\n\n  for (const change of record.data) {\n    switch (change[0]) {\n      case ChangeType.AddString:\n        // Update the string table.\n        for (let i = 1; i < change.length; i++) {\n          stringTable.add(change[i] as string)\n        }\n\n        // Deliberately don't include this change in the decoded record.\n        break\n\n      case ChangeType.AddNode: {\n        const decoded: [typeof ChangeType.AddNode, ...AddNodeChange[]] = [ChangeType.AddNode]\n        for (let i = 1; i < change.length; i++) {\n          decoded.push(decodeAddNodeChange(change[i] as AddNodeChange, stringTable))\n        }\n        decodedData.push(decoded)\n        break\n      }\n\n      case ChangeType.RemoveNode:\n        decodedData.push(change)\n        break\n\n      case ChangeType.Attribute: {\n        const decoded: [typeof ChangeType.Attribute, ...AttributeChange[]] = [ChangeType.Attribute]\n        for (let i = 1; i < change.length; i++) {\n          decoded.push(decodeAttributeChange(change[i] as AttributeChange, stringTable))\n        }\n        decodedData.push(decoded)\n        break\n      }\n\n      case ChangeType.Text: {\n        const decoded: [typeof ChangeType.Text, ...TextChange[]] = [ChangeType.Text]\n        for (let i = 1; i < change.length; i++) {\n          decoded.push(decodeTextChange(change[i] as TextChange, stringTable))\n        }\n        decodedData.push(decoded)\n        break\n      }\n\n      case ChangeType.Size:\n      case ChangeType.ScrollPosition:\n      case ChangeType.AttachedStyleSheets:\n      case ChangeType.MediaPlaybackState:\n      case ChangeType.VisualViewport:\n        decodedData.push(change)\n        break\n\n      case ChangeType.AddStyleSheet: {\n        const decoded: [typeof ChangeType.AddStyleSheet, ...AddStyleSheetChange[]] = [ChangeType.AddStyleSheet]\n        for (let i = 1; i < change.length; i++) {\n          decoded.push(decodeAddStyleSheetChange(change[i] as AddStyleSheetChange, stringTable))\n        }\n        decodedData.push(decoded)\n        break\n      }\n\n      default:\n        change satisfies never\n        throw new Error(`Unsupported ChangeType: ${change[0] as any}`)\n    }\n  }\n\n  return { ...record, data: decodedData }\n}\n\nfunction decodeAddNodeChange(change: AddNodeChange, stringTable: StringTable): AddNodeChange {\n  const insertionPoint = change[0]\n  const nodeName = stringTable.decode(change[1])\n\n  switch (nodeName) {\n    case '#cdata-section':\n    case '#document':\n    case '#document-fragment':\n    case '#shadow-root':\n      return [insertionPoint, nodeName]\n\n    case '#doctype': {\n      const [, , name, publicId, systemId] = change as AddDocTypeNodeChange\n      return [\n        insertionPoint,\n        '#doctype',\n        stringTable.decode(name),\n        stringTable.decode(publicId),\n        stringTable.decode(systemId),\n      ]\n    }\n\n    case '#text': {\n      const [, , textContent] = change as AddTextNodeChange\n      return [insertionPoint, '#text', stringTable.decode(textContent)]\n    }\n\n    default: {\n      const decodedChange: AddElementNodeChange = [insertionPoint, nodeName]\n\n      const [, , ...attrs] = change as AddElementNodeChange\n      for (const [name, value] of attrs) {\n        decodedChange.push([stringTable.decode(name), stringTable.decode(value)])\n      }\n\n      return decodedChange\n    }\n  }\n}\n\nfunction decodeAttributeChange(change: AttributeChange, stringTable: StringTable): AttributeChange {\n  const [nodeId, ...mutations] = change\n\n  const decodedMutations: AttributeAssignmentOrDeletion[] = mutations.map((mutation) => {\n    if (mutation.length === 1) {\n      return [stringTable.decode(mutation[0])]\n    }\n    return [stringTable.decode(mutation[0]), stringTable.decode(mutation[1])]\n  })\n\n  const decodedChange: AttributeChange = [nodeId]\n  decodedChange.push(...decodedMutations)\n  return decodedChange\n}\n\nfunction decodeTextChange(change: TextChange, stringTable: StringTable): TextChange {\n  return [change[0], stringTable.decode(change[1])]\n}\n\nfunction decodeAddStyleSheetChange(change: AddStyleSheetChange, stringTable: StringTable): AddStyleSheetChange {\n  const rules = change[0]\n  const decodedRules: StyleSheetRules = Array.isArray(rules)\n    ? rules.map((rule) => stringTable.decode(rule))\n    : stringTable.decode(rules)\n\n  if (change.length === 1) {\n    return [decodedRules]\n  }\n\n  const decodedMediaList = change[1].map((item) => stringTable.decode(item))\n\n  if (change.length === 2) {\n    return [decodedRules, decodedMediaList]\n  }\n\n  return [decodedRules, decodedMediaList, change[2]]\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/index.ts",
    "content": "export type { ChangeConverter } from './changeConverter'\nexport { createChangeConverter } from './changeConverter'\nexport type { ChangeDecoder } from './changeDecoder'\nexport { createChangeDecoder } from './changeDecoder'\nexport type { MutationLog } from './mutationLog'\nexport type { NodeIdRemapper } from './nodeIdRemapper'\nexport { createCopyingNodeIdRemapper, createIdentityNodeIdRemapper } from './nodeIdRemapper'\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/mutationLog.ts",
    "content": "import type { NodeId } from '../../itemIds'\n\ntype ParentNodeId = NodeId\n\nexport interface MutationLog {\n  onAttributeChanged(nodeId: NodeId, name: string): void\n  onNodeConnected(nodeId: NodeId): void\n  onNodeDisconnected(nodeId: NodeId, parentId: ParentNodeId): void\n  onTextChanged(nodeId: NodeId): void\n\n  clear(): void\n\n  attributeChanges: Map<NodeId, Set<string>>\n  nodeAdds: Set<NodeId>\n  nodeRemoves: Map<NodeId, ParentNodeId>\n  textChanges: Set<NodeId>\n}\n\nexport function createMutationLog(): MutationLog {\n  const self: MutationLog = {\n    onAttributeChanged(nodeId: NodeId, name: string): void {\n      let changedAttributes = self.attributeChanges.get(nodeId)\n      if (!changedAttributes) {\n        changedAttributes = new Set<string>()\n        self.attributeChanges.set(nodeId, changedAttributes)\n      }\n      changedAttributes.add(name)\n    },\n\n    onNodeConnected(nodeId: NodeId): void {\n      self.nodeAdds.add(nodeId)\n    },\n\n    onNodeDisconnected(nodeId: NodeId, parentId: ParentNodeId): void {\n      self.nodeRemoves.set(nodeId, parentId)\n    },\n\n    onTextChanged(nodeId: NodeId): void {\n      self.textChanges.add(nodeId)\n    },\n\n    clear(): void {\n      self.attributeChanges.clear()\n      self.nodeAdds.clear()\n      self.nodeRemoves.clear()\n      self.textChanges.clear()\n    },\n\n    attributeChanges: new Map<NodeId, Set<string>>(),\n    nodeAdds: new Set<NodeId>(),\n    nodeRemoves: new Map<NodeId, ParentNodeId>(),\n    textChanges: new Set<NodeId>(),\n  }\n\n  return self\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/nodeIdRemapper.ts",
    "content": "import type { NodeId, NodeIds } from '../../itemIds'\nimport { createNodeIds } from '../../itemIds'\n\nexport interface NodeIdRemapper {\n  remap(inputNodeId: NodeId): NodeId\n}\n\nexport function createIdentityNodeIdRemapper(): NodeIdRemapper {\n  return {\n    remap(inputNodeId: NodeId): NodeId {\n      return inputNodeId\n    },\n  }\n}\n\nexport interface CopyingNodeIdRemapper extends NodeIdRemapper {\n  inputNodeIds: NodeIds\n  outputNodeIds: NodeIds\n}\n\nexport function createCopyingNodeIdRemapper(): CopyingNodeIdRemapper {\n  const { nodeIds: inputNodeIds, nodesByNodeId: inputNodesByNodeId } = createTrackedNodeIds()\n  const { nodeIds: outputNodeIds, nodeIdsByNode: outputNodeIdsByNode } = createTrackedNodeIds()\n\n  const self: CopyingNodeIdRemapper = {\n    remap(inputNodeId: NodeId): NodeId {\n      const node = inputNodesByNodeId.get(inputNodeId)\n      if (!node) {\n        throw new Error(`Input node id ${inputNodeId} not found`)\n      }\n      return outputNodeIdsByNode.get(node) ?? outputNodeIds.getOrInsert(node)\n    },\n\n    inputNodeIds,\n    outputNodeIds,\n  }\n\n  return self\n}\n\nfunction createTrackedNodeIds(): {\n  nodeIds: NodeIds\n  nodeIdsByNode: Map<Node, NodeId>\n  nodesByNodeId: Map<NodeId, Node>\n} {\n  const wrappedNodeIds = createNodeIds()\n  const nodeIdsByNode = new Map<Node, NodeId>()\n  const nodesByNodeId = new Map<NodeId, Node>()\n\n  const nodeIds: NodeIds = {\n    clear: wrappedNodeIds.clear,\n    delete: wrappedNodeIds.delete,\n    get: wrappedNodeIds.get,\n    getOrInsert(node: Node): NodeId {\n      const nodeId = wrappedNodeIds.getOrInsert(node)\n      nodeIdsByNode.set(node, nodeId)\n      nodesByNodeId.set(nodeId, node)\n      return nodeId\n    },\n    get nextId(): NodeId {\n      return wrappedNodeIds.nextId\n    },\n    get size(): number {\n      return wrappedNodeIds.size\n    },\n  }\n\n  return { nodeIds, nodeIdsByNode, nodesByNodeId }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/renderOptions.ts",
    "content": "import type { NodeIdRemapper } from './nodeIdRemapper'\nimport { createIdentityNodeIdRemapper } from './nodeIdRemapper'\n\nexport interface V1RenderOptions {\n  nodeIdRemapper: NodeIdRemapper\n  timestamp: number\n}\n\nexport function createV1RenderOptions(options: Partial<V1RenderOptions> = {}): V1RenderOptions {\n  return {\n    nodeIdRemapper: options.nodeIdRemapper ?? createIdentityNodeIdRemapper(),\n    timestamp: options.timestamp ?? 0,\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/stringTable.ts",
    "content": "import type { StringId } from '../../itemIds'\n\nexport interface StringTable {\n  add(newString: string): void\n  decode(stringOrStringId: number | string): string\n}\n\nexport function createStringTable(): StringTable {\n  const strings = new Map<StringId, string>()\n  return {\n    add(newString: string): void {\n      strings.set(strings.size as StringId, newString)\n    },\n    decode(stringOrStringId: number | string): string {\n      if (typeof stringOrStringId === 'string') {\n        return stringOrStringId\n      }\n      const referencedString = strings.get(stringOrStringId as StringId)\n      if (referencedString === undefined) {\n        throw new Error(`Reference to unknown string: ${stringOrStringId}`)\n      }\n      return referencedString\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vDocument.spec.ts",
    "content": "import type { NodeId, StyleSheetId } from '../../itemIds'\nimport type { VDocument } from './vDocument'\nimport { createVDocument } from './vDocument'\n\nimport { expectConnections, expectFullSnapshotRendering, expectIncrementalSnapshotRendering } from './vDom.specHelper'\n\ndescribe('VDocument', () => {\n  let document: VDocument\n\n  beforeEach(() => {\n    document = createVDocument()\n  })\n\n  it('initially contains no nodes', () => {\n    expect(document.root).toBeUndefined()\n    expect(() => {\n      document.getNodeById(0 as NodeId)\n    }).toThrowError()\n  })\n\n  it('initially contains no stylesheets', () => {\n    expect(() => {\n      document.getStyleSheetById(0 as StyleSheetId)\n    }).toThrowError()\n  })\n\n  describe('createNode', () => {\n    it('creates nodes with monotonically increasing ids', () => {\n      const node0 = document.createNode({ kind: '#document' })\n      expect(node0.id).toBe(0 as NodeId)\n      const node1 = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n      expect(node1.id).toBe(1 as NodeId)\n      const node2 = document.createNode({ kind: '#element', tag: 'span', attributes: {} })\n      expect(node2.id).toBe(2 as NodeId)\n    })\n  })\n\n  describe('createStyleSheet', () => {\n    it('creates stylesheets with monotonically increasing ids', () => {\n      const sheet0 = document.createStyleSheet({ disabled: false, mediaList: [], rules: '' })\n      expect(sheet0.id).toBe(0 as StyleSheetId)\n      const sheet1 = document.createStyleSheet({ disabled: false, mediaList: [], rules: 'foo { color: red }' })\n      expect(sheet1.id).toBe(1 as StyleSheetId)\n      const sheet2 = document.createStyleSheet({ disabled: false, mediaList: [], rules: 'bar { width: 100px }' })\n      expect(sheet2.id).toBe(2 as StyleSheetId)\n    })\n  })\n\n  describe('root', () => {\n    it('can be attached', () => {\n      const rootNode = document.createNode({ kind: '#document' })\n      expect(document.root).toBeUndefined()\n\n      document.root = rootNode\n\n      expect(document.root).toBe(rootNode)\n      expectConnections(rootNode, {})\n    })\n\n    it('cannot be replaced', () => {\n      const rootNode = document.createNode({ kind: '#document' })\n      document.root = rootNode\n      const secondRootNode = document.createNode({ kind: '#document' })\n\n      expect(() => {\n        document.root = secondRootNode\n      }).toThrowError()\n    })\n\n    it('cannot be detached', () => {\n      const rootNode = document.createNode({ kind: '#document' })\n      document.root = rootNode\n\n      expect(() => {\n        document.root = undefined\n      }).toThrowError()\n    })\n  })\n\n  describe('renderAsFullSnapshot', () => {\n    it('can render a realistic document', () => {\n      // Construct a document which resembles a simple, but realistic, web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const head = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      html.appendChild(head)\n\n      const title = document.createNode({ kind: '#element', tag: 'title', attributes: {} })\n      head.appendChild(title)\n\n      const titleText = document.createNode({ kind: '#text', textContent: 'Test Page' })\n      title.appendChild(titleText)\n\n      const meta = document.createNode({ kind: '#element', tag: 'meta', attributes: { charset: 'utf-8' } })\n      head.appendChild(meta)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      const div = document.createNode({ kind: '#element', tag: 'div', attributes: { class: 'container' } })\n      body.appendChild(div)\n\n      const h1 = document.createNode({ kind: '#element', tag: 'h1', attributes: {} })\n      div.appendChild(h1)\n\n      const h1Text = document.createNode({ kind: '#text', textContent: 'Hello World' })\n      h1.appendChild(h1Text)\n\n      const p = document.createNode({ kind: '#element', tag: 'p', attributes: {} })\n      div.appendChild(p)\n\n      const pText = document.createNode({ kind: '#text', textContent: 'This is a test paragraph.' })\n      p.appendChild(pText)\n\n      const ul = document.createNode({ kind: '#element', tag: 'ul', attributes: {} })\n      div.appendChild(ul)\n\n      const li1 = document.createNode({ kind: '#element', tag: 'li', attributes: {} })\n      ul.appendChild(li1)\n\n      const li1Text = document.createNode({ kind: '#text', textContent: 'Item 1' })\n      li1.appendChild(li1Text)\n\n      const li2 = document.createNode({ kind: '#element', tag: 'li', attributes: {} })\n      ul.appendChild(li2)\n\n      const li2Text = document.createNode({ kind: '#text', textContent: 'Item 2' })\n      li2.appendChild(li2Text)\n\n      // Check that the rendering matches our expectations.\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            {\n              type: 2,\n              id: 1,\n              tagName: 'html',\n              attributes: {},\n              isSVG: undefined,\n              childNodes: [\n                {\n                  type: 2,\n                  id: 2,\n                  tagName: 'head',\n                  attributes: {},\n                  isSVG: undefined,\n                  childNodes: [\n                    {\n                      type: 2,\n                      id: 3,\n                      tagName: 'title',\n                      attributes: {},\n                      isSVG: undefined,\n                      childNodes: [{ type: 3, id: 4, textContent: 'Test Page' }],\n                    },\n                    {\n                      type: 2,\n                      id: 5,\n                      tagName: 'meta',\n                      attributes: { charset: 'utf-8' },\n                      isSVG: undefined,\n                      childNodes: [],\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  id: 6,\n                  tagName: 'body',\n                  attributes: {},\n                  isSVG: undefined,\n                  childNodes: [\n                    {\n                      type: 2,\n                      id: 7,\n                      tagName: 'div',\n                      attributes: { class: 'container' },\n                      isSVG: undefined,\n                      childNodes: [\n                        {\n                          type: 2,\n                          id: 8,\n                          tagName: 'h1',\n                          attributes: {},\n                          isSVG: undefined,\n                          childNodes: [{ type: 3, id: 9, textContent: 'Hello World' }],\n                        },\n                        {\n                          type: 2,\n                          id: 10,\n                          tagName: 'p',\n                          attributes: {},\n                          isSVG: undefined,\n                          childNodes: [{ type: 3, id: 11, textContent: 'This is a test paragraph.' }],\n                        },\n                        {\n                          type: 2,\n                          id: 12,\n                          tagName: 'ul',\n                          attributes: {},\n                          isSVG: undefined,\n                          childNodes: [\n                            {\n                              type: 2,\n                              id: 13,\n                              tagName: 'li',\n                              attributes: {},\n                              isSVG: undefined,\n                              childNodes: [{ type: 3, id: 14, textContent: 'Item 1' }],\n                            },\n                            {\n                              type: 2,\n                              id: 15,\n                              tagName: 'li',\n                              attributes: {},\n                              isSVG: undefined,\n                              childNodes: [{ type: 3, id: 16, textContent: 'Item 2' }],\n                            },\n                          ],\n                        },\n                      ],\n                    },\n                  ],\n                },\n              ],\n            },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n  })\n\n  describe('renderAsIncrementalSnapshot', () => {\n    it('can render nodes being added incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const head = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      html.appendChild(head)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      const div = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n      body.appendChild(div)\n\n      const span = document.createNode({ kind: '#element', tag: 'span', attributes: {} })\n      body.appendChild(span)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations.\n      const meta = document.createNode({ kind: '#element', tag: 'meta', attributes: {} })\n      head.appendChild(meta)\n\n      const p = document.createNode({ kind: '#element', tag: 'p', attributes: {} })\n      body.appendChild(p)\n\n      const pText = document.createNode({ kind: '#text', textContent: 'Content' })\n      div.appendChild(pText)\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [\n            {\n              nextId: null,\n              parentId: 3,\n              node: { type: 2, id: 7, tagName: 'p', attributes: {}, isSVG: undefined, childNodes: [] },\n            },\n            {\n              nextId: null,\n              parentId: 4,\n              node: { type: 3, id: 8, textContent: 'Content' },\n            },\n            {\n              nextId: null,\n              parentId: 2,\n              node: { type: 2, id: 6, tagName: 'meta', attributes: {}, isSVG: undefined, childNodes: [] },\n            },\n          ],\n          removes: [],\n          texts: [],\n          attributes: [],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'head',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [{ type: 2, id: 6, tagName: 'meta', attributes: {}, isSVG: undefined, childNodes: [] }],\n                  },\n                  {\n                    type: 2,\n                    id: 3,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      {\n                        type: 2,\n                        id: 4,\n                        tagName: 'div',\n                        attributes: {},\n                        isSVG: undefined,\n                        childNodes: [{ type: 3, id: 8, textContent: 'Content' }],\n                      },\n                      { type: 2, id: 5, tagName: 'span', attributes: {}, isSVG: undefined, childNodes: [] },\n                      { type: 2, id: 7, tagName: 'p', attributes: {}, isSVG: undefined, childNodes: [] },\n                    ],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n\n    it('can render siblings nodes being added incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations - add several sibling nodes.\n      const div1 = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'first' } })\n      body.appendChild(div1)\n\n      const div2 = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'second' } })\n      body.appendChild(div2)\n\n      const div3 = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'third' } })\n      body.appendChild(div3)\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [\n            {\n              nextId: null,\n              parentId: 2,\n              node: { type: 2, id: 5, tagName: 'div', attributes: { id: 'third' }, isSVG: undefined, childNodes: [] },\n            },\n            {\n              nextId: 5,\n              parentId: 2,\n              node: { type: 2, id: 4, tagName: 'div', attributes: { id: 'second' }, isSVG: undefined, childNodes: [] },\n            },\n            {\n              nextId: 4,\n              parentId: 2,\n              node: { type: 2, id: 3, tagName: 'div', attributes: { id: 'first' }, isSVG: undefined, childNodes: [] },\n            },\n          ],\n          removes: [],\n          texts: [],\n          attributes: [],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      { type: 2, id: 3, tagName: 'div', attributes: { id: 'first' }, isSVG: undefined, childNodes: [] },\n                      {\n                        type: 2,\n                        id: 4,\n                        tagName: 'div',\n                        attributes: { id: 'second' },\n                        isSVG: undefined,\n                        childNodes: [],\n                      },\n                      { type: 2, id: 5, tagName: 'div', attributes: { id: 'third' }, isSVG: undefined, childNodes: [] },\n                    ],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n\n    it('can render a node subtree being added incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations - add a node subtree.\n      const div = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n      body.appendChild(div)\n\n      const ul = document.createNode({ kind: '#element', tag: 'ul', attributes: {} })\n      div.appendChild(ul)\n\n      const li1 = document.createNode({ kind: '#element', tag: 'li', attributes: {} })\n      ul.appendChild(li1)\n\n      const li1Text = document.createNode({ kind: '#text', textContent: 'First item' })\n      li1.appendChild(li1Text)\n\n      const li2 = document.createNode({ kind: '#element', tag: 'li', attributes: {} })\n      ul.appendChild(li2)\n\n      const li2Text = document.createNode({ kind: '#text', textContent: 'Second item' })\n      li2.appendChild(li2Text)\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [\n            {\n              nextId: null,\n              parentId: 2,\n              node: {\n                type: 2,\n                id: 3,\n                tagName: 'div',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 4,\n                    tagName: 'ul',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      {\n                        type: 2,\n                        id: 5,\n                        tagName: 'li',\n                        attributes: {},\n                        isSVG: undefined,\n                        childNodes: [{ type: 3, id: 6, textContent: 'First item' }],\n                      },\n                      {\n                        type: 2,\n                        id: 7,\n                        tagName: 'li',\n                        attributes: {},\n                        isSVG: undefined,\n                        childNodes: [{ type: 3, id: 8, textContent: 'Second item' }],\n                      },\n                    ],\n                  },\n                ],\n              },\n            },\n          ],\n          removes: [],\n          texts: [],\n          attributes: [],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      {\n                        type: 2,\n                        id: 3,\n                        tagName: 'div',\n                        attributes: {},\n                        isSVG: undefined,\n                        childNodes: [\n                          {\n                            type: 2,\n                            id: 4,\n                            tagName: 'ul',\n                            attributes: {},\n                            isSVG: undefined,\n                            childNodes: [\n                              {\n                                type: 2,\n                                id: 5,\n                                tagName: 'li',\n                                attributes: {},\n                                isSVG: undefined,\n                                childNodes: [{ type: 3, id: 6, textContent: 'First item' }],\n                              },\n                              {\n                                type: 2,\n                                id: 7,\n                                tagName: 'li',\n                                attributes: {},\n                                isSVG: undefined,\n                                childNodes: [{ type: 3, id: 8, textContent: 'Second item' }],\n                              },\n                            ],\n                          },\n                        ],\n                      },\n                    ],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n\n    it('can render nodes being removed incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      const div1 = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'first' } })\n      body.appendChild(div1)\n\n      const div2 = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'second' } })\n      body.appendChild(div2)\n\n      const div3 = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'third' } })\n      body.appendChild(div3)\n\n      const span = document.createNode({ kind: '#element', tag: 'span', attributes: {} })\n      body.appendChild(span)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations - remove several nodes (but not ancestors and descendants).\n      div1.remove()\n      div3.remove()\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [],\n          removes: [\n            { parentId: 2, id: 3 },\n            { parentId: 2, id: 5 },\n          ],\n          texts: [],\n          attributes: [],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      {\n                        type: 2,\n                        id: 4,\n                        tagName: 'div',\n                        attributes: { id: 'second' },\n                        isSVG: undefined,\n                        childNodes: [],\n                      },\n                      { type: 2, id: 6, tagName: 'span', attributes: {}, isSVG: undefined, childNodes: [] },\n                    ],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n\n    it('can render a node subtree being removed incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      const div = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n      body.appendChild(div)\n\n      const ul = document.createNode({ kind: '#element', tag: 'ul', attributes: {} })\n      div.appendChild(ul)\n\n      const li1 = document.createNode({ kind: '#element', tag: 'li', attributes: {} })\n      ul.appendChild(li1)\n\n      const li1Text = document.createNode({ kind: '#text', textContent: 'First item' })\n      li1.appendChild(li1Text)\n\n      const li2 = document.createNode({ kind: '#element', tag: 'li', attributes: {} })\n      ul.appendChild(li2)\n\n      const li2Text = document.createNode({ kind: '#text', textContent: 'Second item' })\n      li2.appendChild(li2Text)\n\n      const span = document.createNode({ kind: '#element', tag: 'span', attributes: {} })\n      body.appendChild(span)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations - remove some descendant nodes, then remove the root of the subtree.\n      li1.remove()\n      li2.remove()\n      div.remove()\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [],\n          removes: [\n            { parentId: 4, id: 5 },\n            { parentId: 4, id: 7 },\n            { parentId: 2, id: 3 },\n          ],\n          texts: [],\n          attributes: [],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [{ type: 2, id: 9, tagName: 'span', attributes: {}, isSVG: undefined, childNodes: [] }],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n\n    it('can render attributes being changed incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      const div = document.createNode({ kind: '#element', tag: 'div', attributes: { id: 'container', class: 'old' } })\n      body.appendChild(div)\n\n      const span = document.createNode({ kind: '#element', tag: 'span', attributes: { title: 'hello' } })\n      body.appendChild(span)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations - change attributes on nodes.\n      div.setAttribute('class', 'new')\n      div.setAttribute('data-test', 'value')\n      span.setAttribute('title', null)\n      span.setAttribute('id', 'myspan')\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [],\n          removes: [],\n          texts: [],\n          attributes: [\n            { id: 3, attributes: { class: 'new', 'data-test': 'value' } },\n            { id: 4, attributes: { title: null, id: 'myspan' } },\n          ],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      {\n                        type: 2,\n                        id: 3,\n                        tagName: 'div',\n                        attributes: { id: 'container', class: 'new', 'data-test': 'value' },\n                        isSVG: undefined,\n                        childNodes: [],\n                      },\n                      {\n                        type: 2,\n                        id: 4,\n                        tagName: 'span',\n                        attributes: { id: 'myspan' },\n                        isSVG: undefined,\n                        childNodes: [],\n                      },\n                    ],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n\n    it('can render text content being changed incrementally', () => {\n      // Construct a document which resembles a very simple web page.\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      const html = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      root.appendChild(html)\n\n      const body = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      html.appendChild(body)\n\n      const p1 = document.createNode({ kind: '#element', tag: 'p', attributes: {} })\n      body.appendChild(p1)\n\n      const p1Text = document.createNode({ kind: '#text', textContent: 'Original text 1' })\n      p1.appendChild(p1Text)\n\n      const p2 = document.createNode({ kind: '#element', tag: 'p', attributes: {} })\n      body.appendChild(p2)\n\n      const p2Text = document.createNode({ kind: '#text', textContent: 'Original text 2' })\n      p2.appendChild(p2Text)\n\n      // Reset the mutation log. Beyond this point, any further changes will be treated\n      // as incremental mutations.\n      document.mutations.clear()\n\n      // Perform some mutations - change text content.\n      p1Text.setTextContent('Updated text 1')\n      p2Text.setTextContent('Updated text 2')\n\n      // Check that the rendering matches our expectations.\n      expectIncrementalSnapshotRendering(\n        document,\n        {\n          adds: [],\n          removes: [],\n          texts: [\n            { id: 4, value: 'Updated text 1' },\n            { id: 6, value: 'Updated text 2' },\n          ],\n          attributes: [],\n        },\n        {\n          node: {\n            type: 0,\n            id: 0,\n            childNodes: [\n              {\n                type: 2,\n                id: 1,\n                tagName: 'html',\n                attributes: {},\n                isSVG: undefined,\n                childNodes: [\n                  {\n                    type: 2,\n                    id: 2,\n                    tagName: 'body',\n                    attributes: {},\n                    isSVG: undefined,\n                    childNodes: [\n                      {\n                        type: 2,\n                        id: 3,\n                        tagName: 'p',\n                        attributes: {},\n                        isSVG: undefined,\n                        childNodes: [{ type: 3, id: 4, textContent: 'Updated text 1' }],\n                      },\n                      {\n                        type: 2,\n                        id: 5,\n                        tagName: 'p',\n                        attributes: {},\n                        isSVG: undefined,\n                        childNodes: [{ type: 3, id: 6, textContent: 'Updated text 2' }],\n                      },\n                    ],\n                  },\n                ],\n              },\n            ],\n            adoptedStyleSheets: undefined,\n          },\n          initialOffset: { left: 0, top: 0 },\n        }\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vDocument.ts",
    "content": "import type {\n  AddedNodeMutation,\n  AttributeMutation,\n  BrowserFullSnapshotRecord,\n  BrowserFullSnapshotV1Record,\n  BrowserIncrementalSnapshotRecord,\n  RemovedNodeMutation,\n  TextMutation,\n} from '../../../../types'\nimport { IncrementalSource, RecordType, SnapshotFormat } from '../../../../types'\nimport type { NodeId, StyleSheetId } from '../../itemIds'\nimport type { MutationLog } from './mutationLog'\nimport { createMutationLog } from './mutationLog'\nimport { createV1RenderOptions } from './renderOptions'\nimport type { V1RenderOptions } from './renderOptions'\nimport { createVNode } from './vNode'\nimport type { VNode, VNodeData } from './vNode'\nimport { createVStyleSheet } from './vStyleSheet'\nimport type { VStyleSheet, VStyleSheetData } from './vStyleSheet'\n\nexport interface VDocument {\n  createNode(data: VNodeData): VNode\n  getNodeById(id: NodeId): VNode\n\n  createStyleSheet(data: VStyleSheetData): VStyleSheet\n  getStyleSheetById(id: StyleSheetId): VStyleSheet\n\n  onAttributeChanged(node: VNode, name: string): void\n  onNodeConnected(node: VNode, parent: VNode | undefined): void\n  onNodeDisconnected(node: VNode, parent: VNode | undefined): void\n  onTextChanged(node: VNode): void\n\n  get mutations(): MutationLog\n\n  naturalRendering(): BrowserFullSnapshotRecord['type'] | BrowserIncrementalSnapshotRecord['type']\n  render(options?: Partial<V1RenderOptions>): BrowserFullSnapshotV1Record | BrowserIncrementalSnapshotRecord\n  renderAsFullSnapshot(options?: Partial<V1RenderOptions>): BrowserFullSnapshotV1Record\n  renderAsIncrementalSnapshot(options?: Partial<V1RenderOptions>): BrowserIncrementalSnapshotRecord\n\n  root: VNode | undefined\n}\n\nexport function createVDocument(): VDocument {\n  const mutations = createMutationLog()\n\n  let nextNodeId = 0 as NodeId\n  const nodesById = new Map<NodeId, VNode>()\n  let rootId: NodeId | undefined\n\n  let nextStyleSheetId = 0 as StyleSheetId\n  const styleSheetsById = new Map<StyleSheetId, VStyleSheet>()\n\n  const self: VDocument = {\n    createNode(data: VNodeData): VNode {\n      const id = nextNodeId++ as NodeId\n      const node = createVNode(self, id, data)\n      nodesById.set(id, node)\n      return node\n    },\n\n    getNodeById(id: NodeId): VNode {\n      const node = nodesById.get(id)\n      if (!node) {\n        throw new Error(`Reference to unknown node: ${id}`)\n      }\n      return node\n    },\n\n    createStyleSheet(data: VStyleSheetData): VStyleSheet {\n      const id = nextStyleSheetId++ as StyleSheetId\n      const sheet = createVStyleSheet(self, id, data)\n      styleSheetsById.set(id, sheet)\n      return sheet\n    },\n\n    getStyleSheetById(id: StyleSheetId): VStyleSheet {\n      const sheet = styleSheetsById.get(id)\n      if (!sheet) {\n        throw new Error(`Reference to unknown stylesheet: ${id}`)\n      }\n      return sheet\n    },\n\n    onAttributeChanged(node: VNode, name: string): void {\n      mutations.onAttributeChanged(node.id, name)\n    },\n\n    onNodeConnected(node: VNode, parent: VNode | undefined): void {\n      if (node.state !== 'new') {\n        throw new Error(`Moving connected node: ${node.id}`)\n      }\n\n      if (parent === undefined) {\n        if (rootId !== undefined) {\n          throw new Error('Replacing existing root node')\n        }\n        rootId = node.id\n      }\n\n      node.state = 'connected'\n      mutations.onNodeConnected(node.id)\n    },\n\n    onNodeDisconnected(node: VNode, parent: VNode | undefined): void {\n      node.forSelfAndEachDescendant((descendant: VNode): void => {\n        if (descendant.state === 'disconnected') {\n          throw new Error(`Disconnecting node which isn't connected: ${descendant.id}`)\n        }\n\n        descendant.state = 'disconnected'\n      })\n\n      if (!parent) {\n        throw new Error('Disconnecting the root node')\n      }\n\n      mutations.onNodeDisconnected(node.id, parent.id)\n    },\n\n    onTextChanged(node: VNode): void {\n      mutations.onTextChanged(node.id)\n    },\n\n    get mutations(): MutationLog {\n      return mutations\n    },\n\n    naturalRendering(): BrowserFullSnapshotRecord['type'] | BrowserIncrementalSnapshotRecord['type'] {\n      if (rootId !== undefined && mutations.nodeAdds.has(rootId)) {\n        return RecordType.FullSnapshot\n      }\n      return RecordType.IncrementalSnapshot\n    },\n\n    render(options?: Partial<V1RenderOptions>): BrowserFullSnapshotV1Record | BrowserIncrementalSnapshotRecord {\n      if (self.naturalRendering() === RecordType.FullSnapshot) {\n        return self.renderAsFullSnapshot(options)\n      }\n      return self.renderAsIncrementalSnapshot(options)\n    },\n\n    renderAsFullSnapshot(renderOptions: Partial<V1RenderOptions> = {}): BrowserFullSnapshotV1Record {\n      const options = createV1RenderOptions(renderOptions)\n\n      const root = self.root\n      if (!root) {\n        throw new Error('No root node found')\n      }\n\n      let scrollLeft = 0\n      let scrollTop = 0\n      if (root.data.kind === '#document' || root.data.kind === '#element') {\n        scrollLeft = root.data.scrollLeft ?? 0\n        scrollTop = root.data.scrollTop ?? 0\n      }\n\n      return {\n        data: {\n          node: root.render(options),\n          initialOffset: { left: scrollLeft, top: scrollTop },\n        },\n        format: SnapshotFormat.V1,\n        type: RecordType.FullSnapshot,\n        timestamp: options.timestamp,\n      }\n    },\n\n    renderAsIncrementalSnapshot(renderOptions: Partial<V1RenderOptions> = {}): BrowserIncrementalSnapshotRecord {\n      const options = createV1RenderOptions(renderOptions)\n\n      const root = self.root\n      if (!root) {\n        throw new Error('No root node found')\n      }\n\n      const remappedId = (id: NodeId): NodeId => options.nodeIdRemapper.remap(id)\n\n      const addMutations: AddedNodeMutation[] = []\n      root.forEachAddedNodeRoot(mutations.nodeAdds, (node) => {\n        if (!node.parent) {\n          throw new Error(`Can't render incremental add of root node ${node.id}`)\n        }\n        addMutations.push({\n          nextId: node.nextSibling?.id !== undefined ? remappedId(node.nextSibling.id) : null,\n          parentId: remappedId(node.parent.id),\n          node: node.render(options),\n        })\n      })\n\n      const removeMutations: RemovedNodeMutation[] = []\n      for (const [id, parentId] of mutations.nodeRemoves) {\n        removeMutations.push({ parentId: remappedId(parentId), id: remappedId(id) })\n      }\n\n      const textMutations: TextMutation[] = []\n      for (const id of mutations.textChanges) {\n        const node = self.getNodeById(id)\n        if (node.data.kind !== '#text') {\n          throw new Error(`Can't render incremental text mutation of ${node.data.kind} node ${id}`)\n        }\n        textMutations.push({ id: remappedId(id), value: node.data.textContent })\n      }\n\n      const attributeMutations: AttributeMutation[] = []\n      for (const [id, attrNames] of mutations.attributeChanges) {\n        const node = self.getNodeById(id)\n        if (node.data.kind !== '#element') {\n          throw new Error(`Can't render incremental attribute mutation of ${node.data.kind} node ${id}`)\n        }\n\n        const attributes: Record<string, string | null> = {}\n        for (const attrName of attrNames) {\n          attributes[attrName] = node.data.attributes[attrName] ?? null\n        }\n\n        attributeMutations.push({ id: remappedId(id), attributes })\n      }\n\n      return {\n        data: {\n          source: IncrementalSource.Mutation,\n          adds: addMutations,\n          removes: removeMutations,\n          texts: textMutations,\n          attributes: attributeMutations,\n        },\n        type: RecordType.IncrementalSnapshot,\n        timestamp: options.timestamp,\n      }\n    },\n\n    get root(): VNode | undefined {\n      return rootId === undefined ? undefined : self.getNodeById(rootId)\n    },\n    set root(node: VNode) {\n      self.onNodeConnected(node, undefined)\n    },\n  }\n\n  return self\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vDom.specHelper.ts",
    "content": "import type {\n  BrowserFullSnapshotRecord,\n  BrowserFullSnapshotV1Record,\n  BrowserIncrementalSnapshotRecord,\n  BrowserMutationPayload,\n  SerializedNodeWithId,\n} from '../../../../types'\nimport { IncrementalSource, RecordType, SnapshotFormat } from '../../../../types'\nimport type { NodeId } from '../../itemIds'\nimport { createV1RenderOptions } from './renderOptions'\nimport type { VDocument } from './vDocument'\nimport type { VNode, VNodeState } from './vNode'\n\nexport function expectConnections(\n  node: VNode,\n  connections: {\n    state?: VNodeState | undefined\n    firstChild?: VNode | undefined\n    lastChild?: VNode | undefined\n    previousSibling?: VNode | undefined\n    nextSibling?: VNode | undefined\n    parent?: VNode | undefined\n  }\n): void {\n  expect(node.state).toBe(connections.state ?? 'connected')\n  expect(node.firstChild).toBe(connections.firstChild)\n  expect(node.lastChild).toBe(connections.lastChild)\n  expect(node.previousSibling).toBe(connections.previousSibling)\n  expect(node.nextSibling).toBe(connections.nextSibling)\n  expect(node.parent).toBe(connections.parent)\n}\n\nexport function expectMutations(\n  document: VDocument,\n  mutations: {\n    attributeChanges?: Array<{ node: VNode; attributes: string[] }>\n    nodeAdds?: VNode[]\n    nodeRemoves?: Array<{ node: VNode; parent: VNode }>\n    textChanges?: VNode[]\n  }\n): void {\n  const expectedAttributeChanges: Array<{ node: NodeId; attributes: string[] }> =\n    mutations.attributeChanges?.map(({ node, attributes }) => ({ node: node.id, attributes })) ?? []\n  const actualAttributeChanges: Array<{ node: NodeId; attributes: string[] }> = [\n    ...document.mutations.attributeChanges,\n  ].map(([nodeId, attributes]) => ({ node: nodeId, attributes: [...attributes] }))\n  expect(actualAttributeChanges).toEqual(expectedAttributeChanges)\n\n  const expectedNodeAdds: NodeId[] = mutations.nodeAdds?.map((node) => node.id) ?? []\n  const actualNodeAdds: NodeId[] = [...document.mutations.nodeAdds]\n  expect(actualNodeAdds).toEqual(expectedNodeAdds)\n\n  const expectedNodeRemoves: Array<{ node: NodeId; parent: NodeId }> =\n    mutations.nodeRemoves?.map(({ node, parent }) => ({ node: node.id, parent: parent.id })) ?? []\n  const actualNodeRemoves: Array<{ node: NodeId; parent: NodeId }> = [...document.mutations.nodeRemoves].map(\n    ([node, parent]) => ({ node, parent })\n  )\n  expect(actualNodeRemoves).toEqual(expectedNodeRemoves)\n\n  const expectedTextChanges: NodeId[] = mutations.textChanges?.map((node) => node.id) ?? []\n  const actualTextChanges: NodeId[] = [...document.mutations.textChanges]\n  expect(actualTextChanges).toEqual(expectedTextChanges)\n}\n\nexport function expectFullSnapshotRendering(\n  document: VDocument,\n  data: BrowserFullSnapshotV1Record['data'],\n  naturalRendering:\n    | BrowserFullSnapshotRecord['type']\n    | BrowserIncrementalSnapshotRecord['type'] = RecordType.FullSnapshot\n): void {\n  expect(document.naturalRendering()).toBe(naturalRendering)\n\n  const expectedRecord: BrowserFullSnapshotV1Record = {\n    data,\n    format: SnapshotFormat.V1,\n    type: RecordType.FullSnapshot,\n    timestamp: 0,\n  }\n  const actualRecord = document.renderAsFullSnapshot()\n  expect(actualRecord).toEqual(expectedRecord)\n\n  const expectedSerialization = JSON.stringify(expectedRecord)\n  const actualSerialization = JSON.stringify(actualRecord)\n  const context = stringMismatchContext(expectedSerialization, actualSerialization)\n  expect(actualSerialization).withContext(context).toBe(expectedSerialization)\n}\n\nexport function expectIncrementalSnapshotRendering(\n  document: VDocument,\n  incrementalSnapshotPayload: BrowserMutationPayload,\n  fullSnapshotData: BrowserFullSnapshotV1Record['data']\n): void {\n  expect(document.naturalRendering()).toBe(RecordType.IncrementalSnapshot)\n\n  const expectedRecord: BrowserIncrementalSnapshotRecord = {\n    data: {\n      source: IncrementalSource.Mutation,\n      ...incrementalSnapshotPayload,\n    },\n    type: RecordType.IncrementalSnapshot,\n    timestamp: 0,\n  }\n  const actualRecord = document.render()\n  expect(actualRecord).toEqual(expectedRecord)\n\n  const expectedSerialization = JSON.stringify(expectedRecord)\n  const actualSerialization = JSON.stringify(actualRecord)\n  const context = stringMismatchContext(expectedSerialization, actualSerialization)\n  expect(actualSerialization).withContext(context).toBe(expectedSerialization)\n\n  expectFullSnapshotRendering(document, fullSnapshotData, RecordType.IncrementalSnapshot)\n}\n\nexport function expectNodeRendering(node: VNode, expectedSerializedNode: SerializedNodeWithId): void {\n  const actualSerializedNode = node.render(createV1RenderOptions())\n  expect(actualSerializedNode).toEqual(expectedSerializedNode)\n\n  const expectedSerialization = JSON.stringify(expectedSerializedNode)\n  const actualSerialization = JSON.stringify(actualSerializedNode)\n  const context = stringMismatchContext(expectedSerialization, actualSerialization)\n  expect(actualSerialization).withContext(context).toBe(expectedSerialization)\n}\n\nfunction stringMismatchContext(expected: string, actual: string): string {\n  if (expected === actual) {\n    return '(equal)'\n  }\n\n  let firstDifferenceIndex = 0\n  while (expected[firstDifferenceIndex] === actual[firstDifferenceIndex]) {\n    firstDifferenceIndex++\n  }\n\n  const expectedContext = getStringNearPosition(expected, firstDifferenceIndex)\n  const actualContext = getStringNearPosition(actual, firstDifferenceIndex)\n  return JSON.stringify({ expected: expectedContext, actual: actualContext }, null, 2)\n}\n\nfunction getStringNearPosition(str: string, index: number): string {\n  const leftContextStart = Math.max(index - 50, 0)\n  const rightContextEnd = Math.min(index + 150, str.length)\n  return `${str.substring(leftContextStart, index)}(!)${str.substring(index, rightContextEnd)}`\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vNode.spec.ts",
    "content": "import { PlaybackState } from '../../../../types'\nimport type { NodeId } from '../../itemIds'\nimport type { VDocument } from './vDocument'\nimport { createVDocument } from './vDocument'\nimport type { VNode, VNodeData } from './vNode'\nimport type { VStyleSheet } from './vStyleSheet'\n\nimport { expectConnections, expectFullSnapshotRendering, expectMutations, expectNodeRendering } from './vDom.specHelper'\n\ndescribe('VNode', () => {\n  let document: VDocument\n\n  beforeEach(() => {\n    document = createVDocument()\n  })\n\n  function expectThrowsForNode(nodeData: VNodeData, action: (node: VNode) => void): void {\n    const node = document.createNode(nodeData)\n    document.root = node\n\n    expect(() => {\n      action(node)\n    }).toThrow()\n  }\n\n  function expectThrowsForDisconnectedNodes(action: (node: VNode) => void): void {\n    const parent = document.createNode({ kind: '#document' })\n    document.root = parent\n\n    const removed = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n    parent.appendChild(removed)\n    removed.remove()\n    expect(() => {\n      action(removed)\n    }).toThrow()\n\n    const neverAttached = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n    expect(() => {\n      action(neverAttached)\n    }).toThrow()\n  }\n\n  it('has the expected state on creation', () => {\n    const nodeData: VNodeData = { kind: '#element', tag: 'div', attributes: {}, isSVG: false }\n    const node = document.createNode(nodeData)\n\n    expect(node.data).toEqual(nodeData)\n    expect(node.ownerDocument).toBe(document)\n    expect(node.id).toBe(0 as NodeId)\n    expectConnections(node, { state: 'new' })\n    expectMutations(document, {})\n  })\n\n  describe('after', () => {\n    it('can attach after an only child', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(firstChild)\n\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      firstChild.after(lastChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: firstChild })\n      expectMutations(document, { nodeAdds: [parent, firstChild, lastChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 1, tagName: 'html', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 2, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can attach at the end of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      parent.appendChild(middleChild)\n\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      middleChild.after(lastChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: middleChild })\n      expectConnections(middleChild, { parent, previousSibling: firstChild, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: middleChild })\n      expectMutations(document, { nodeAdds: [parent, firstChild, middleChild, lastChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            {\n              type: 2,\n              id: 1,\n              tagName: 'head',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n            {\n              type: 2,\n              id: 2,\n              tagName: 'style',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n            {\n              type: 2,\n              id: 3,\n              tagName: 'body',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can attach in the middle of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      firstChild.after(middleChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: middleChild })\n      expectConnections(middleChild, { parent, previousSibling: firstChild, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: middleChild })\n      expectMutations(document, { nodeAdds: [parent, firstChild, lastChild, middleChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            {\n              type: 2,\n              id: 1,\n              tagName: 'head',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n            {\n              type: 2,\n              id: 3,\n              tagName: 'style',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n            {\n              type: 2,\n              id: 2,\n              tagName: 'body',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot attach a node which is already connected', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const grandChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      child.appendChild(grandChild)\n\n      expect(() => {\n        child.after(grandChild)\n      }).toThrow()\n    })\n\n    it('cannot attach a node to a disconnected sibling', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const node = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n\n      const removed = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(removed)\n      removed.remove()\n      expect(() => {\n        removed.after(node)\n      }).toThrow()\n\n      const neverAttached = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      expect(() => {\n        neverAttached.after(node)\n      }).toThrow()\n    })\n\n    it('cannot attach a node which was previously removed', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const node = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      child.appendChild(node)\n      node.remove()\n\n      expect(() => {\n        child.after(node)\n      }).toThrow()\n    })\n\n    it('cannot attach a node as a sibling to the root node', () => {\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n      const node = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n\n      expect(() => {\n        root.after(node)\n      }).toThrow()\n    })\n  })\n\n  describe('appendChild', () => {\n    it('can attach the first child', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n\n      expectConnections(parent, { firstChild: child, lastChild: child })\n      expectConnections(child, { parent })\n      expectMutations(document, { nodeAdds: [parent, child] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            {\n              type: 2,\n              id: 1,\n              tagName: 'html',\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can attach two children', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: firstChild })\n      expectMutations(document, { nodeAdds: [parent, firstChild, lastChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 1, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 2, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can attach three children', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      parent.appendChild(middleChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: middleChild })\n      expectConnections(middleChild, { parent, previousSibling: firstChild, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: middleChild })\n      expectMutations(document, { nodeAdds: [parent, firstChild, middleChild, lastChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 1, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 2, tagName: 'style', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 3, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot attach a node which is already connected', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const grandChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      child.appendChild(grandChild)\n\n      expect(() => {\n        parent.appendChild(grandChild)\n      }).toThrow()\n    })\n\n    it('cannot attach a node to a disconnected parent', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n\n      const removed = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(removed)\n      removed.remove()\n      expect(() => {\n        removed.appendChild(child)\n      }).toThrow()\n\n      const neverAttached = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      expect(() => {\n        neverAttached.appendChild(child)\n      }).toThrow()\n    })\n\n    it('cannot attach a node which was previously removed', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const grandChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      child.appendChild(grandChild)\n      grandChild.remove()\n\n      expect(() => {\n        child.appendChild(grandChild)\n      }).toThrow()\n    })\n  })\n\n  describe('before', () => {\n    it('can attach before an only child', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const lastChild = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(lastChild)\n\n      const firstChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      lastChild.before(firstChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: firstChild })\n      expectMutations(document, { nodeAdds: [parent, lastChild, firstChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 2, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 1, tagName: 'html', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can attach at the beginning of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      parent.appendChild(middleChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(lastChild)\n\n      const firstChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      middleChild.before(firstChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: middleChild })\n      expectConnections(middleChild, { parent, previousSibling: firstChild, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: middleChild })\n      expectMutations(document, { nodeAdds: [parent, middleChild, lastChild, firstChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 3, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 1, tagName: 'style', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 2, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can attach in the middle of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      lastChild.before(middleChild)\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: middleChild })\n      expectConnections(middleChild, { parent, previousSibling: firstChild, nextSibling: lastChild })\n      expectConnections(lastChild, { parent, previousSibling: middleChild })\n      expectMutations(document, { nodeAdds: [parent, firstChild, lastChild, middleChild] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 1, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 3, tagName: 'style', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 2, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot attach a node which is already connected', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const grandChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      child.appendChild(grandChild)\n\n      expect(() => {\n        child.before(grandChild)\n      }).toThrow()\n    })\n\n    it('cannot attach a node to a disconnected sibling', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const node = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n\n      const removed = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(removed)\n      removed.remove()\n      expect(() => {\n        removed.before(node)\n      }).toThrow()\n\n      const neverAttached = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      expect(() => {\n        neverAttached.before(node)\n      }).toThrow()\n    })\n\n    it('cannot attach a node which was previously removed', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n      const node = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      child.appendChild(node)\n      node.remove()\n\n      expect(() => {\n        child.before(node)\n      }).toThrow()\n    })\n\n    it('cannot attach a node as a sibling to the root node', () => {\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n      const node = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n\n      expect(() => {\n        root.before(node)\n      }).toThrow()\n    })\n  })\n\n  describe('remove', () => {\n    it('can remove an only child', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const child = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(child)\n\n      child.remove()\n\n      expectConnections(parent, {})\n      expectConnections(child, { state: 'disconnected' })\n      expectMutations(document, { nodeAdds: [parent, child], nodeRemoves: [{ node: child, parent }] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can remove a node from the end of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      lastChild.remove()\n\n      expectConnections(parent, { firstChild, lastChild: firstChild })\n      expectConnections(firstChild, { parent })\n      expectConnections(lastChild, { state: 'disconnected' })\n      expectMutations(document, {\n        nodeAdds: [parent, firstChild, lastChild],\n        nodeRemoves: [{ node: lastChild, parent }],\n      })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [{ type: 2, id: 1, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined }],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can remove a node from the beginning of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      firstChild.remove()\n\n      expectConnections(parent, { firstChild: lastChild, lastChild })\n      expectConnections(firstChild, { state: 'disconnected' })\n      expectConnections(lastChild, { parent })\n      expectMutations(document, {\n        nodeAdds: [parent, firstChild, lastChild],\n        nodeRemoves: [{ node: firstChild, parent }],\n      })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [{ type: 2, id: 2, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined }],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can remove a node from the middle of a child list', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      parent.appendChild(middleChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n\n      middleChild.remove()\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: lastChild })\n      expectConnections(middleChild, { state: 'disconnected' })\n      expectConnections(lastChild, { parent, previousSibling: firstChild })\n      expectMutations(document, {\n        nodeAdds: [parent, firstChild, middleChild, lastChild],\n        nodeRemoves: [{ node: middleChild, parent }],\n      })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 1, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 3, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can remove a node with descendants', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n      const firstChild = document.createNode({ kind: '#element', tag: 'head', attributes: {} })\n      parent.appendChild(firstChild)\n      const middleChild = document.createNode({ kind: '#element', tag: 'style', attributes: {} })\n      parent.appendChild(middleChild)\n      const lastChild = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      parent.appendChild(lastChild)\n      const middleFirstChild = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n      middleChild.appendChild(middleFirstChild)\n      const middleLastChild = document.createNode({ kind: '#element', tag: 'span', attributes: {} })\n      middleChild.appendChild(middleLastChild)\n\n      middleChild.remove()\n\n      expectConnections(parent, { firstChild, lastChild })\n      expectConnections(firstChild, { parent, nextSibling: lastChild })\n      expectConnections(middleChild, {\n        state: 'disconnected',\n        firstChild: middleFirstChild,\n        lastChild: middleLastChild,\n      })\n      expectConnections(lastChild, { parent, previousSibling: firstChild })\n      expectConnections(middleFirstChild, { state: 'disconnected', parent: middleChild, nextSibling: middleLastChild })\n      expectConnections(middleLastChild, {\n        state: 'disconnected',\n        parent: middleChild,\n        previousSibling: middleFirstChild,\n      })\n      expectMutations(document, {\n        nodeAdds: [parent, firstChild, middleChild, lastChild, middleFirstChild, middleLastChild],\n        nodeRemoves: [{ node: middleChild, parent }],\n      })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 0,\n          id: 0,\n          childNodes: [\n            { type: 2, id: 1, tagName: 'head', attributes: {}, childNodes: [], isSVG: undefined },\n            { type: 2, id: 3, tagName: 'body', attributes: {}, childNodes: [], isSVG: undefined },\n          ],\n          adoptedStyleSheets: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can remove a node which has already been removed', () => {\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      const removed = document.createNode({ kind: '#element', tag: 'html', attributes: {} })\n      parent.appendChild(removed)\n      removed.remove()\n      expect(() => {\n        removed.remove()\n      }).not.toThrow()\n    })\n\n    it('cannot remove a node which has never been attached', () => {\n      const neverAttached = document.createNode({ kind: '#element', tag: 'body', attributes: {} })\n      expect(() => {\n        neverAttached.remove()\n      }).toThrow()\n    })\n\n    it('cannot remove the root node', () => {\n      const root = document.createNode({ kind: '#document' })\n      document.root = root\n\n      expect(() => {\n        root.remove()\n      }).toThrow()\n    })\n  })\n\n  describe('setAttachedStyleSheets', () => {\n    let sheet: VStyleSheet\n\n    beforeEach(() => {\n      sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: 'div { color: blue }',\n      })\n    })\n\n    function expectCanAttachStyleSheet(nodeData: VNodeData & { attachedStyleSheets?: [VStyleSheet] }): void {\n      const node = document.createNode(nodeData)\n      document.root = node\n\n      node.setAttachedStyleSheets([sheet])\n\n      expect(nodeData.attachedStyleSheets).toEqual([sheet])\n\n      // Incremental mutations for stylesheet attachment aren't supported yet.\n      expectMutations(document, { nodeAdds: [node] })\n    }\n\n    it('cannot attach stylesheets to #cdata-section nodes', () => {\n      expectThrowsForNode({ kind: '#cdata-section' }, (node) => node.setAttachedStyleSheets([sheet]))\n    })\n\n    it('cannot attach stylesheets to #doctype nodes', () => {\n      expectThrowsForNode({ kind: '#doctype', name: '', publicId: '', systemId: '' }, (node) =>\n        node.setAttachedStyleSheets([sheet])\n      )\n    })\n\n    it('can attach stylesheets to #document nodes', () => {\n      expectCanAttachStyleSheet({ kind: '#document' })\n    })\n\n    it('can attach stylesheets to #element nodes', () => {\n      expectCanAttachStyleSheet({ kind: '#element', tag: 'style', attributes: {} })\n    })\n\n    it('can attach stylesheets to #document-fragment nodes', () => {\n      expectCanAttachStyleSheet({ kind: '#document-fragment' })\n    })\n\n    it('can attach stylesheets to #shadow-root nodes', () => {\n      expectCanAttachStyleSheet({ kind: '#shadow-root' })\n    })\n\n    it('cannot attach stylesheets to #text', () => {\n      expectThrowsForNode({ kind: '#text', textContent: '' }, (node) => node.setAttachedStyleSheets([sheet]))\n    })\n\n    it('cannot attach stylesheets to a node which is not connected', () => {\n      expectThrowsForDisconnectedNodes((node: VNode) => {\n        node.setAttachedStyleSheets([sheet])\n      })\n    })\n  })\n\n  describe('setAttribute', () => {\n    it('cannot set an attribute on #cdata-section nodes', () => {\n      expectThrowsForNode({ kind: '#cdata-section' }, (node) => node.setAttribute('foo', 'bar'))\n    })\n\n    it('cannot set an attribute on #doctype nodes', () => {\n      expectThrowsForNode({ kind: '#doctype', name: '', publicId: '', systemId: '' }, (node) =>\n        node.setAttribute('foo', 'bar')\n      )\n    })\n\n    it('cannot set an attribute on #document nodes', () => {\n      expectThrowsForNode({ kind: '#document' }, (node) => node.setAttribute('foo', 'bar'))\n    })\n\n    it('cannot set an attribute on #document-fragment nodes', () => {\n      expectThrowsForNode({ kind: '#document-fragment' }, (node) => node.setAttribute('foo', 'bar'))\n    })\n\n    it('can set an attribute on #element nodes', () => {\n      const elementData: VNodeData = { kind: '#element', tag: 'div', attributes: {} }\n      const element = document.createNode(elementData)\n      document.root = element\n\n      element.setAttribute('foo', 'bar')\n\n      expect(elementData.attributes).toEqual({ foo: 'bar' })\n      expectMutations(document, { attributeChanges: [{ node: element, attributes: ['foo'] }], nodeAdds: [element] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 2,\n          id: 0,\n          tagName: 'div',\n          attributes: { foo: 'bar' },\n          childNodes: [],\n          isSVG: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can set multiple attributes on #element nodes', () => {\n      const elementData: VNodeData = { kind: '#element', tag: 'div', attributes: {} }\n      const element = document.createNode(elementData)\n      document.root = element\n\n      element.setAttribute('foo', 'bar')\n      element.setAttribute('baz', 'bat')\n\n      expect(elementData.attributes).toEqual({ foo: 'bar', baz: 'bat' })\n      expectMutations(document, {\n        attributeChanges: [{ node: element, attributes: ['foo', 'baz'] }],\n        nodeAdds: [element],\n      })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 2,\n          id: 0,\n          tagName: 'div',\n          attributes: { foo: 'bar', baz: 'bat' },\n          childNodes: [],\n          isSVG: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can clear an attribute on #element nodes', () => {\n      const elementData: VNodeData = { kind: '#element', tag: 'div', attributes: {} }\n      const element = document.createNode(elementData)\n      document.root = element\n\n      element.setAttribute('foo', 'bar')\n      element.setAttribute('foo', null)\n\n      expect(elementData.attributes).toEqual({})\n      expectMutations(document, { attributeChanges: [{ node: element, attributes: ['foo'] }], nodeAdds: [element] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 2,\n          id: 0,\n          tagName: 'div',\n          attributes: {},\n          childNodes: [],\n          isSVG: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('can clear an attribute on #element nodes which was not already set', () => {\n      const elementData: VNodeData = { kind: '#element', tag: 'div', attributes: {} }\n      const element = document.createNode(elementData)\n      document.root = element\n\n      element.setAttribute('foo', null)\n\n      expect(elementData.attributes).toEqual({})\n      expectMutations(document, { attributeChanges: [{ node: element, attributes: ['foo'] }], nodeAdds: [element] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 2,\n          id: 0,\n          tagName: 'div',\n          attributes: {},\n          childNodes: [],\n          isSVG: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot set an attribute on #shadow-root nodes', () => {\n      expectThrowsForNode({ kind: '#shadow-root' }, (node) => node.setAttribute('foo', 'bar'))\n    })\n\n    it('cannot set an attribute on #text nodes', () => {\n      expectThrowsForNode({ kind: '#text', textContent: '' }, (node) => node.setAttribute('foo', 'bar'))\n    })\n\n    it('cannot set an attribute on a node which is not connected', () => {\n      expectThrowsForDisconnectedNodes((node: VNode) => {\n        node.setAttribute('foo', 'bar')\n      })\n    })\n  })\n\n  describe('setPlaybackState', () => {\n    it('cannot set playback state on #cdata-section nodes', () => {\n      expectThrowsForNode({ kind: '#cdata-section' }, (node) => node.setPlaybackState(PlaybackState.Playing))\n    })\n\n    it('cannot set playback state on #doctype nodes', () => {\n      expectThrowsForNode({ kind: '#doctype', name: '', publicId: '', systemId: '' }, (node) =>\n        node.setPlaybackState(PlaybackState.Playing)\n      )\n    })\n\n    it('cannot set playback state on #document nodes', () => {\n      expectThrowsForNode({ kind: '#document' }, (node) => node.setPlaybackState(PlaybackState.Playing))\n    })\n\n    it('cannot set playback state on #document-fragment nodes', () => {\n      expectThrowsForNode({ kind: '#document-fragment' }, (node) => node.setPlaybackState(PlaybackState.Playing))\n    })\n\n    it('can set playback state on #element nodes', () => {\n      const elementData: VNodeData = { kind: '#element', tag: 'div', attributes: {} }\n      const element = document.createNode(elementData)\n      document.root = element\n      expect(elementData.playbackState).toBe(undefined)\n\n      element.setPlaybackState(PlaybackState.Playing)\n      expect(elementData.playbackState).toBe(PlaybackState.Playing)\n\n      element.setPlaybackState(PlaybackState.Paused)\n      expect(elementData.playbackState).toBe(PlaybackState.Paused)\n\n      // Incremental mutations for playback state aren't supported yet.\n      expectMutations(document, { nodeAdds: [element] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 2,\n          id: 0,\n          tagName: 'div',\n          attributes: { rr_mediaState: 'paused' },\n          childNodes: [],\n          isSVG: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot set playback state on #shadow-root nodes', () => {\n      expectThrowsForNode({ kind: '#shadow-root' }, (node) => node.setPlaybackState(PlaybackState.Playing))\n    })\n\n    it('cannot set playback state on #text nodes', () => {\n      expectThrowsForNode({ kind: '#text', textContent: '' }, (node) => node.setPlaybackState(PlaybackState.Playing))\n    })\n\n    it('cannot set playback state on a node which is not connected', () => {\n      expectThrowsForDisconnectedNodes((node: VNode) => {\n        node.setPlaybackState(PlaybackState.Paused)\n      })\n    })\n  })\n\n  describe('setScrollPosition', () => {\n    function describeScrollPositionBehavior(\n      createNodeData: () => VNodeData & { scrollLeft?: number; scrollTop?: number }\n    ): void {\n      it('can set scroll position', () => {\n        const nodeData = createNodeData()\n        const node = document.createNode(nodeData)\n        document.root = node\n        expect(nodeData.scrollLeft).toBe(undefined)\n        expect(nodeData.scrollTop).toBe(undefined)\n\n        node.setScrollPosition(5, 10)\n        expect(nodeData.scrollLeft).toBe(5)\n        expect(nodeData.scrollTop).toBe(10)\n\n        node.setScrollPosition(10, 20)\n        expect(nodeData.scrollLeft).toBe(10)\n        expect(nodeData.scrollTop).toBe(20)\n\n        // Incremental mutations for scroll position aren't supported yet.\n        expectMutations(document, { nodeAdds: [node] })\n\n        if (nodeData.kind === '#element') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 2,\n              id: 0,\n              tagName: nodeData.tag,\n              attributes: { rr_scrollLeft: 10, rr_scrollTop: 20 },\n              childNodes: [],\n              isSVG: undefined,\n            },\n            initialOffset: { left: 10, top: 20 },\n          })\n        } else if (nodeData.kind === '#document') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 0,\n              id: 0,\n              childNodes: [],\n              adoptedStyleSheets: undefined,\n            },\n            initialOffset: { left: 10, top: 20 },\n          })\n        }\n      })\n\n      it('ignores zero initial scroll coordinates', () => {\n        const nodeData = createNodeData()\n        const node = document.createNode(nodeData)\n        document.root = node\n        expect(nodeData.scrollLeft).toBe(undefined)\n        expect(nodeData.scrollTop).toBe(undefined)\n\n        node.setScrollPosition(0, 0)\n        expect(nodeData.scrollLeft).toBe(undefined)\n        expect(nodeData.scrollTop).toBe(undefined)\n\n        // Incremental mutations for scroll position aren't supported yet.\n        expectMutations(document, { nodeAdds: [node] })\n\n        if (nodeData.kind === '#element') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 2,\n              id: 0,\n              tagName: nodeData.tag,\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n            initialOffset: { left: 0, top: 0 },\n          })\n        } else if (nodeData.kind === '#document') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 0,\n              id: 0,\n              childNodes: [],\n              adoptedStyleSheets: undefined,\n            },\n            initialOffset: { left: 0, top: 0 },\n          })\n        }\n      })\n\n      it('sets zero scroll coordinates on #element nodes if they were previously non-zero', () => {\n        const nodeData = createNodeData()\n        const node = document.createNode(nodeData)\n        document.root = node\n        expect(nodeData.scrollLeft).toBe(undefined)\n        expect(nodeData.scrollTop).toBe(undefined)\n\n        node.setScrollPosition(10, 20)\n        expect(nodeData.scrollLeft).toBe(10)\n        expect(nodeData.scrollTop).toBe(20)\n\n        node.setScrollPosition(0, 0)\n        expect(nodeData.scrollLeft).toBe(0)\n        expect(nodeData.scrollTop).toBe(0)\n\n        // Incremental mutations for scroll position aren't supported yet.\n        expectMutations(document, { nodeAdds: [node] })\n\n        if (nodeData.kind === '#element') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 2,\n              id: 0,\n              tagName: nodeData.tag,\n              attributes: {},\n              childNodes: [],\n              isSVG: undefined,\n            },\n            initialOffset: { left: 0, top: 0 },\n          })\n        } else if (nodeData.kind === '#document') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 0,\n              id: 0,\n              childNodes: [],\n              adoptedStyleSheets: undefined,\n            },\n            initialOffset: { left: 0, top: 0 },\n          })\n        }\n      })\n\n      it('ignores zero initial scroll coordinates on #element nodes independently for each coordinate', () => {\n        const node1Data = createNodeData()\n        const node1 = document.createNode(node1Data)\n        document.root = node1\n        const node2Data = createNodeData()\n        const node2 = document.createNode(node2Data)\n        node1.appendChild(node2)\n\n        expect(node1Data.scrollLeft).toBe(undefined)\n        expect(node1Data.scrollTop).toBe(undefined)\n        expect(node2Data.scrollLeft).toBe(undefined)\n        expect(node2Data.scrollTop).toBe(undefined)\n\n        node1.setScrollPosition(0, 20)\n        expect(node1Data.scrollLeft).toBe(undefined)\n        expect(node1Data.scrollTop).toBe(20)\n\n        node2.setScrollPosition(10, 0)\n        expect(node2Data.scrollLeft).toBe(10)\n        expect(node2Data.scrollTop).toBe(undefined)\n\n        // Incremental mutations for scroll position aren't supported yet.\n        expectMutations(document, { nodeAdds: [node1, node2] })\n\n        if (node1Data.kind === '#element' && node2Data.kind === '#element') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 2,\n              id: 0,\n              tagName: node1Data.tag,\n              attributes: { rr_scrollTop: 20 },\n              childNodes: [\n                {\n                  type: 2,\n                  id: 1,\n                  tagName: node2Data.tag,\n                  attributes: { rr_scrollLeft: 10 },\n                  childNodes: [],\n                  isSVG: undefined,\n                },\n              ],\n              isSVG: undefined,\n            },\n            initialOffset: { left: 0, top: 20 },\n          })\n        } else if (node1Data.kind === '#document' && node2Data.kind === '#document') {\n          expectFullSnapshotRendering(document, {\n            node: {\n              type: 0,\n              id: 0,\n              childNodes: [\n                {\n                  type: 0,\n                  id: 1,\n                  childNodes: [],\n                  adoptedStyleSheets: undefined,\n                },\n              ],\n              adoptedStyleSheets: undefined,\n            },\n            initialOffset: { left: 0, top: 20 },\n          })\n        }\n      })\n    }\n\n    it('cannot set scroll position on #cdata-section nodes', () => {\n      expectThrowsForNode({ kind: '#cdata-section' }, (node) => node.setScrollPosition(10, 20))\n    })\n\n    describe('for #element nodes', () => {\n      describeScrollPositionBehavior(() => ({\n        kind: '#element',\n        tag: 'div',\n        attributes: {},\n      }))\n    })\n\n    it('cannot set scroll position on #doctype nodes', () => {\n      expectThrowsForNode({ kind: '#doctype', name: '', publicId: '', systemId: '' }, (node) =>\n        node.setScrollPosition(10, 20)\n      )\n    })\n\n    describe('for #document nodes', () => {\n      describeScrollPositionBehavior(() => ({ kind: '#document' }))\n    })\n\n    it('cannot set scroll position on #document-fragment nodes', () => {\n      expectThrowsForNode({ kind: '#document-fragment' }, (node) => node.setScrollPosition(10, 20))\n    })\n\n    it('cannot set scroll position on #shadow-root nodes', () => {\n      expectThrowsForNode({ kind: '#shadow-root' }, (node) => node.setScrollPosition(10, 20))\n    })\n\n    it('cannot set scroll position on #text nodes', () => {\n      expectThrowsForNode({ kind: '#text', textContent: '' }, (node) => node.setScrollPosition(10, 20))\n    })\n\n    it('cannot set scroll position on a node which is not connected', () => {\n      expectThrowsForDisconnectedNodes((node: VNode) => {\n        node.setScrollPosition(10, 20)\n      })\n    })\n  })\n\n  describe('setSize', () => {\n    it('cannot set size on #cdata-section nodes', () => {\n      expectThrowsForNode({ kind: '#cdata-section' }, (node) => node.setSize(10, 20))\n    })\n\n    it('cannot set size on #doctype nodes', () => {\n      expectThrowsForNode({ kind: '#doctype', name: '', publicId: '', systemId: '' }, (node) => node.setSize(10, 20))\n    })\n\n    it('cannot set size on #document nodes', () => {\n      expectThrowsForNode({ kind: '#document' }, (node) => node.setSize(10, 20))\n    })\n\n    it('cannot set size on #document-fragment nodes', () => {\n      expectThrowsForNode({ kind: '#document-fragment' }, (node) => node.setSize(10, 20))\n    })\n\n    it('can set size on #element nodes', () => {\n      const elementData: VNodeData = { kind: '#element', tag: 'div', attributes: {} }\n      const element = document.createNode(elementData)\n      document.root = element\n      expect(elementData.width).toBe(undefined)\n      expect(elementData.height).toBe(undefined)\n\n      element.setSize(1, 2)\n      expect(elementData.width).toBe(1)\n      expect(elementData.height).toBe(2)\n\n      element.setSize(10, 20)\n      expect(elementData.width).toBe(10)\n      expect(elementData.height).toBe(20)\n\n      // Incremental mutations for size aren't supported yet.\n      expectMutations(document, { nodeAdds: [element] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 2,\n          id: 0,\n          tagName: 'div',\n          attributes: { rr_width: '10px', rr_height: '20px' },\n          childNodes: [],\n          isSVG: undefined,\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot set size on #shadow-root nodes', () => {\n      expectThrowsForNode({ kind: '#shadow-root' }, (node) => node.setSize(10, 20))\n    })\n\n    it('cannot set size on #text nodes', () => {\n      expectThrowsForNode({ kind: '#text', textContent: '' }, (node) => node.setSize(10, 20))\n    })\n\n    it('cannot set size on a node which is not connected', () => {\n      expectThrowsForDisconnectedNodes((node: VNode) => {\n        node.setSize(10, 20)\n      })\n    })\n  })\n\n  describe('setTextContent', () => {\n    it('cannot set text content on #cdata-section nodes', () => {\n      expectThrowsForNode({ kind: '#cdata-section' }, (node) => node.setTextContent(''))\n    })\n\n    it('cannot set text content on #doctype nodes', () => {\n      expectThrowsForNode({ kind: '#doctype', name: '', publicId: '', systemId: '' }, (node) => node.setTextContent(''))\n    })\n\n    it('cannot set text content on #document nodes', () => {\n      expectThrowsForNode({ kind: '#document' }, (node) => node.setTextContent(''))\n    })\n\n    it('cannot set text content on #document-fragment nodes', () => {\n      expectThrowsForNode({ kind: '#document-fragment' }, (node) => node.setTextContent(''))\n    })\n\n    it('cannot set text content on #element nodes', () => {\n      expectThrowsForNode({ kind: '#element', tag: 'div', attributes: {} }, (node) => node.setTextContent(''))\n    })\n\n    it('cannot set text content on #shadow-root nodes', () => {\n      expectThrowsForNode({ kind: '#shadow-root' }, (node) => node.setTextContent(''))\n    })\n\n    it('can set text content on #text nodes', () => {\n      const textData: VNodeData = { kind: '#text', textContent: '' }\n      const text = document.createNode(textData)\n      document.root = text\n      expect(textData.textContent).toBe('')\n\n      text.setTextContent('foo')\n      expect(textData.textContent).toBe('foo')\n\n      text.setTextContent('bar')\n      expect(textData.textContent).toBe('bar')\n\n      expectMutations(document, { nodeAdds: [text], textChanges: [text] })\n\n      expectFullSnapshotRendering(document, {\n        node: {\n          type: 3,\n          id: 0,\n          textContent: 'bar',\n        },\n        initialOffset: { left: 0, top: 0 },\n      })\n    })\n\n    it('cannot set text content on a node which is not connected', () => {\n      expectThrowsForDisconnectedNodes((node: VNode) => {\n        node.setTextContent('')\n      })\n    })\n  })\n\n  describe('render', () => {\n    it('can render a #cdata-section node', () => {\n      // Create a parent node to hold both test nodes\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      // Minimal #cdata-section node (no optional properties)\n      const minimalNode = document.createNode({ kind: '#cdata-section' })\n      parent.appendChild(minimalNode)\n      expectNodeRendering(minimalNode, {\n        type: 4,\n        id: 1,\n        textContent: '',\n      })\n\n      // Maximal #cdata-section node (same as minimal - no optional properties)\n      const maximalNode = document.createNode({ kind: '#cdata-section' })\n      parent.appendChild(maximalNode)\n      expectNodeRendering(maximalNode, {\n        type: 4,\n        id: 2,\n        textContent: '',\n      })\n    })\n\n    it('can render a #doctype node', () => {\n      // Create a parent node to hold both test nodes\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      // Minimal #doctype node (empty strings)\n      const minimalNode = document.createNode({ kind: '#doctype', name: '', publicId: '', systemId: '' })\n      parent.appendChild(minimalNode)\n      expectNodeRendering(minimalNode, {\n        type: 1,\n        id: 1,\n        name: '',\n        publicId: '',\n        systemId: '',\n      })\n\n      // Maximal #doctype node (all properties set)\n      const maximalNode = document.createNode({\n        kind: '#doctype',\n        name: 'html',\n        publicId: '-//W3C//DTD XHTML 1.0 Strict//EN',\n        systemId: 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd',\n      })\n      parent.appendChild(maximalNode)\n      expectNodeRendering(maximalNode, {\n        type: 1,\n        id: 2,\n        name: 'html',\n        publicId: '-//W3C//DTD XHTML 1.0 Strict//EN',\n        systemId: 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd',\n      })\n    })\n\n    it('can render a #document node', () => {\n      // Minimal #document node (no optional properties)\n      const minimalNode = document.createNode({ kind: '#document' })\n      document.root = minimalNode\n      expectNodeRendering(minimalNode, {\n        type: 0,\n        id: 0,\n        childNodes: [],\n        adoptedStyleSheets: undefined,\n      })\n\n      // Maximal #document node (all optional properties set)\n      const styleSheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: ['screen', 'print'],\n        rules: 'div { color: red }',\n      })\n      const maximalData: VNodeData = { kind: '#document' }\n      const maximalNode = document.createNode(maximalData)\n      minimalNode.appendChild(maximalNode)\n      maximalNode.setAttachedStyleSheets([styleSheet])\n      expectNodeRendering(maximalNode, {\n        type: 0,\n        id: 1,\n        childNodes: [],\n        adoptedStyleSheets: [\n          {\n            cssRules: ['div { color: red }'],\n            disabled: true,\n            media: ['screen', 'print'],\n          },\n        ],\n      })\n    })\n\n    it('can render a #document-fragment node', () => {\n      // Create a parent node to hold both test nodes\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      // Minimal #document-fragment node (no optional properties)\n      const minimalNode = document.createNode({ kind: '#document-fragment' })\n      parent.appendChild(minimalNode)\n      expectNodeRendering(minimalNode, {\n        type: 11,\n        id: 1,\n        childNodes: [],\n        adoptedStyleSheets: undefined,\n        isShadowRoot: false,\n      })\n\n      // Maximal #document-fragment node (all optional properties set)\n      const styleSheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: ['screen', 'print'],\n        rules: 'span { background: yellow }',\n      })\n      const maximalData: VNodeData = { kind: '#document-fragment' }\n      const maximalNode = document.createNode(maximalData)\n      parent.appendChild(maximalNode)\n      maximalNode.setAttachedStyleSheets([styleSheet])\n      expectNodeRendering(maximalNode, {\n        type: 11,\n        id: 2,\n        childNodes: [],\n        adoptedStyleSheets: [\n          {\n            cssRules: ['span { background: yellow }'],\n            disabled: true,\n            media: ['screen', 'print'],\n          },\n        ],\n        isShadowRoot: false,\n      })\n    })\n\n    it('can render a #element node', () => {\n      // Create a parent node to hold both test nodes\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      // Minimal #element node (no optional properties)\n      const minimalNode = document.createNode({ kind: '#element', tag: 'div', attributes: {} })\n      parent.appendChild(minimalNode)\n      expectNodeRendering(minimalNode, {\n        type: 2,\n        id: 1,\n        tagName: 'div',\n        attributes: {},\n        childNodes: [],\n        isSVG: undefined,\n      })\n\n      // Maximal #element node (all optional properties set)\n      const styleSheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: 'p { font-size: 14px }',\n      })\n      const maximalData: VNodeData = {\n        kind: '#element',\n        tag: 'svg',\n        attributes: { id: 'test', class: 'foo' },\n        isSVG: true,\n      }\n      const maximalNode = document.createNode(maximalData)\n      parent.appendChild(maximalNode)\n      maximalNode.setPlaybackState(PlaybackState.Playing)\n      maximalNode.setScrollPosition(10, 20)\n      maximalNode.setSize(100, 200)\n      maximalNode.setAttachedStyleSheets([styleSheet])\n      expectNodeRendering(maximalNode, {\n        type: 2,\n        id: 2,\n        tagName: 'svg',\n        attributes: {\n          rr_width: '100px',\n          rr_height: '200px',\n          id: 'test',\n          class: 'foo',\n          _cssText: 'p { font-size: 14px }',\n          rr_mediaState: 'played',\n          rr_scrollLeft: 10,\n          rr_scrollTop: 20,\n        },\n        childNodes: [],\n        isSVG: true,\n      })\n    })\n\n    it('can render a #shadow-root node', () => {\n      // Create a parent node to hold both test nodes\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      // Minimal #shadow-root node (no optional properties)\n      const minimalNode = document.createNode({ kind: '#shadow-root' })\n      parent.appendChild(minimalNode)\n      expectNodeRendering(minimalNode, {\n        type: 11,\n        id: 1,\n        childNodes: [],\n        adoptedStyleSheets: undefined,\n        isShadowRoot: true,\n      })\n\n      // Maximal #shadow-root node (all optional properties set)\n      const styleSheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: ['screen'],\n        rules: 'h1 { color: blue }',\n      })\n      const maximalData: VNodeData = { kind: '#shadow-root' }\n      const maximalNode = document.createNode(maximalData)\n      parent.appendChild(maximalNode)\n      maximalNode.setAttachedStyleSheets([styleSheet])\n      expectNodeRendering(maximalNode, {\n        type: 11,\n        id: 2,\n        childNodes: [],\n        adoptedStyleSheets: [\n          {\n            cssRules: ['h1 { color: blue }'],\n            disabled: true,\n            media: ['screen'],\n          },\n        ],\n        isShadowRoot: true,\n      })\n    })\n\n    it('can render a #text node', () => {\n      // Create a parent node to hold both test nodes\n      const parent = document.createNode({ kind: '#document' })\n      document.root = parent\n\n      // Minimal #text node (empty textContent)\n      const minimalNode = document.createNode({ kind: '#text', textContent: '' })\n      parent.appendChild(minimalNode)\n      expectNodeRendering(minimalNode, {\n        type: 3,\n        id: 1,\n        textContent: '',\n      })\n\n      // Maximal #text node (non-empty textContent)\n      const maximalNode = document.createNode({ kind: '#text', textContent: 'Hello, world!' })\n      parent.appendChild(maximalNode)\n      expectNodeRendering(maximalNode, {\n        type: 3,\n        id: 2,\n        textContent: 'Hello, world!',\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vNode.ts",
    "content": "import type { SerializedNodeWithId } from '../../../../types'\nimport { PlaybackState, NodeType } from '../../../../types'\nimport type { NodeId } from '../../itemIds'\nimport type { V1RenderOptions } from './renderOptions'\nimport type { VDocument } from './vDocument'\nimport type { VStyleSheet } from './vStyleSheet'\n\nexport interface VNode {\n  after(node: VNode): void\n  appendChild(node: VNode): void\n  before(node: VNode): void\n  remove(): void\n\n  setAttachedStyleSheets(sheets: VStyleSheet[]): void\n  setAttribute(name: string, value: string | null): void\n  setPlaybackState(state: PlaybackState): void\n  setScrollPosition(left: number, top: number): void\n  setSize(width: number, height: number): void\n  setTextContent(value: string): void\n\n  forEachAddedNodeRoot(nodeAdds: Set<NodeId>, action: (node: VNode) => void): void\n  forSelfAndEachDescendant(action: (node: VNode) => void): void\n  mapChildren<Result>(action: (node: VNode) => Result): Result[]\n\n  render(options: V1RenderOptions): SerializedNodeWithId\n\n  get data(): VNodeData\n  get id(): NodeId\n  get ownerDocument(): VDocument\n\n  state: VNodeState\n  firstChild: VNode | undefined\n  lastChild: VNode | undefined\n  previousSibling: VNode | undefined\n  nextSibling: VNode | undefined\n  parent: VNode | undefined\n}\n\nexport type VNodeState = 'new' | 'connected' | 'disconnected'\n\nexport type VNodeData =\n  | {\n      kind: '#cdata-section'\n    }\n  | {\n      kind: '#document'\n      attachedStyleSheets?: VStyleSheet[] | undefined\n      scrollLeft?: number\n      scrollTop?: number\n    }\n  | {\n      kind: '#doctype'\n      name: string\n      publicId: string\n      systemId: string\n    }\n  | {\n      kind: '#document-fragment'\n      attachedStyleSheets?: VStyleSheet[] | undefined\n    }\n  | {\n      kind: '#element'\n      tag: string\n      attachedStyleSheets?: VStyleSheet[] | undefined\n      attributes: Record<string, string>\n      isSVG?: boolean\n      playbackState?: PlaybackState\n      scrollLeft?: number\n      scrollTop?: number\n      width?: number\n      height?: number\n    }\n  | {\n      kind: '#shadow-root'\n      attachedStyleSheets?: VStyleSheet[] | undefined\n    }\n  | {\n      kind: '#text'\n      textContent: string\n    }\n\nexport function createVNode(document: VDocument, id: NodeId, data: VNodeData): VNode {\n  let state: VNodeState = 'new'\n\n  const assertConnectedCorrectly = (): void => {\n    if (self.state !== 'connected') {\n      throw new Error(`Expected node ${self.id} to be connected, not ${self.state}`)\n    }\n\n    for (const connection of ['firstChild', 'lastChild', 'previousSibling', 'nextSibling', 'parent'] as const) {\n      const connectedNode = self[connection]\n      if (connectedNode && connectedNode.state !== 'connected') {\n        throw new Error(`Expected node ${self.id}'s ${connection} to be connected, not ${connectedNode.state}`)\n      }\n    }\n  }\n\n  const self: VNode = {\n    after(node: VNode): void {\n      node.parent = self.parent\n      node.previousSibling = self\n\n      if (self.nextSibling) {\n        self.nextSibling.previousSibling = node\n      }\n      node.nextSibling = self.nextSibling\n      self.nextSibling = node\n\n      if (self.parent?.lastChild === self) {\n        self.parent.lastChild = node\n      }\n\n      document.onNodeConnected(node, self.parent)\n      assertConnectedCorrectly()\n    },\n\n    appendChild(node: VNode): void {\n      if (self.lastChild) {\n        self.lastChild.after(node)\n        return\n      }\n\n      node.parent = self\n      self.firstChild = node\n      self.lastChild = node\n\n      document.onNodeConnected(node, self)\n      assertConnectedCorrectly()\n    },\n\n    before(node: VNode): void {\n      node.parent = self.parent\n      node.nextSibling = self\n\n      if (self.previousSibling) {\n        self.previousSibling.nextSibling = node\n      }\n      node.previousSibling = self.previousSibling\n      self.previousSibling = node\n\n      if (self.parent?.firstChild === self) {\n        self.parent.firstChild = node\n      }\n\n      document.onNodeConnected(node, self.parent)\n      assertConnectedCorrectly()\n    },\n\n    remove(): void {\n      if (self.state === 'disconnected') {\n        return // This is a redundant remove.\n      }\n\n      if (self.parent?.firstChild === self) {\n        self.parent.firstChild = self.nextSibling\n      }\n      if (self.parent?.lastChild === self) {\n        self.parent.lastChild = self.previousSibling\n      }\n      if (self.previousSibling) {\n        self.previousSibling.nextSibling = self.nextSibling\n      }\n      if (self.nextSibling) {\n        self.nextSibling.previousSibling = self.previousSibling\n      }\n\n      const parent = self.parent\n      self.parent = undefined\n      self.previousSibling = undefined\n      self.nextSibling = undefined\n\n      document.onNodeDisconnected(self, parent)\n    },\n\n    setAttachedStyleSheets(sheets: VStyleSheet[]): void {\n      assertConnectedCorrectly()\n\n      switch (data.kind) {\n        case '#document':\n        case '#document-fragment':\n        case '#element':\n        case '#shadow-root':\n          data.attachedStyleSheets = sheets\n          break\n\n        default:\n          throw new Error(`Cannot attach stylesheets to ${data.kind} node ${id}`)\n      }\n    },\n\n    setAttribute(name: string, value: string | null): void {\n      assertConnectedCorrectly()\n\n      if (data.kind !== '#element') {\n        throw new Error(`Cannot set attribute ${name} on ${data.kind} node ${id}`)\n      }\n\n      if (value === null) {\n        delete data.attributes[name]\n      } else {\n        data.attributes[name] = value\n      }\n\n      document.onAttributeChanged(self, name)\n    },\n\n    setPlaybackState(state: PlaybackState): void {\n      assertConnectedCorrectly()\n\n      if (data.kind !== '#element') {\n        throw new Error(`Cannot set media playback state of ${data.kind} node ${id}`)\n      }\n\n      data.playbackState = state\n    },\n\n    setScrollPosition(left: number, top: number): void {\n      assertConnectedCorrectly()\n\n      if (data.kind !== '#document' && data.kind !== '#element') {\n        throw new Error(`Cannot set scroll position on ${data.kind} node ${id}`)\n      }\n\n      // Treat zero coordinates as 'not scrolled' unless this element has scrolled in the past.\n      if (left !== 0 || data.scrollLeft !== undefined) {\n        data.scrollLeft = left\n      }\n      if (top !== 0 || data.scrollTop !== undefined) {\n        data.scrollTop = top\n      }\n    },\n\n    setSize(width: number, height: number): void {\n      assertConnectedCorrectly()\n\n      if (data.kind !== '#element') {\n        throw new Error(`Cannot set size of ${data.kind} node ${id}`)\n      }\n\n      data.width = width\n      data.height = height\n    },\n\n    setTextContent(value: string): void {\n      assertConnectedCorrectly()\n\n      if (data.kind !== '#text') {\n        throw new Error(`Cannot set text on ${data.kind} node ${id}`)\n      }\n\n      data.textContent = value\n\n      document.onTextChanged(self)\n    },\n\n    forEachAddedNodeRoot(nodeAdds: Set<NodeId>, action: (node: VNode) => void): void {\n      if (nodeAdds.has(id)) {\n        // This is the root of a newly-added subtree.\n        action(self)\n        return\n      }\n\n      // This is an existing node, but there may be new nodes among our descendants. Visit\n      // children in reverse order to match the ordering that the V1 serialization\n      // algorithm would use.\n      for (let child = self.lastChild; child; child = child.previousSibling) {\n        child.forEachAddedNodeRoot(nodeAdds, action)\n      }\n    },\n\n    forSelfAndEachDescendant(action: (node: VNode) => void): void {\n      action(self)\n      for (let child = self.firstChild; child; child = child.nextSibling) {\n        child.forSelfAndEachDescendant(action)\n      }\n    },\n\n    mapChildren<Result>(action: (node: VNode) => Result): Result[] {\n      const results: Result[] = []\n      for (let child = self.firstChild; child; child = child.nextSibling) {\n        results.push(action(child))\n      }\n      return results\n    },\n\n    render(options: V1RenderOptions): SerializedNodeWithId {\n      assertConnectedCorrectly()\n\n      const id = options.nodeIdRemapper?.remap(self.id) ?? self.id\n\n      switch (data.kind) {\n        case '#cdata-section':\n          return {\n            type: NodeType.CDATA,\n            id,\n            textContent: '',\n          }\n\n        case '#doctype':\n          return {\n            type: NodeType.DocumentType,\n            id,\n            name: data.name,\n            publicId: data.publicId,\n            systemId: data.systemId,\n          }\n\n        case '#document':\n          return {\n            type: NodeType.Document,\n            id,\n            childNodes: self.mapChildren((node) => node.render(options)),\n            adoptedStyleSheets: data.attachedStyleSheets?.map((sheet) => sheet.renderAsAdoptedStyleSheet()),\n          }\n\n        case '#document-fragment':\n          return {\n            type: NodeType.DocumentFragment,\n            id,\n            childNodes: self.mapChildren((node) => node.render(options)),\n            adoptedStyleSheets: data.attachedStyleSheets?.map((sheet) => sheet.renderAsAdoptedStyleSheet()),\n            isShadowRoot: false,\n          }\n\n        case '#element': {\n          const attributes: Record<string, string | number> = {}\n\n          // Add size-related virtual attributes before the real DOM attributes, to match\n          // the ordering used in the V1 format.\n          if (data.width !== undefined && data.height !== undefined) {\n            attributes.rr_width = `${data.width}px`\n            attributes.rr_height = `${data.height}px`\n          }\n\n          // Add DOM attributes.\n          Object.assign(attributes, data.attributes)\n\n          // Add other virtual attributes after the real DOM attributes, to match the\n          // ordering used in the V1 format.\n          if (data.attachedStyleSheets !== undefined) {\n            attributes._cssText = data.attachedStyleSheets.map((sheet) => sheet.renderAsCssText()).join('')\n          }\n          if (data.playbackState !== undefined) {\n            attributes.rr_mediaState = data.playbackState === PlaybackState.Paused ? 'paused' : 'played'\n          }\n          if (data.scrollLeft) {\n            attributes.rr_scrollLeft = data.scrollLeft\n          }\n          if (data.scrollTop) {\n            attributes.rr_scrollTop = data.scrollTop\n          }\n\n          return {\n            type: NodeType.Element,\n            id,\n            tagName: data.tag,\n            attributes,\n            childNodes: self.mapChildren((node) => node.render(options)),\n            isSVG: data.isSVG === true ? true : undefined,\n          }\n        }\n\n        case '#shadow-root':\n          return {\n            type: NodeType.DocumentFragment,\n            id,\n            childNodes: self.mapChildren((node) => node.render(options)),\n            adoptedStyleSheets: data.attachedStyleSheets?.map((sheet) => sheet.renderAsAdoptedStyleSheet()),\n            isShadowRoot: true,\n          }\n\n        case '#text':\n          return {\n            type: NodeType.Text,\n            id,\n            textContent: data.textContent,\n          }\n\n        default:\n          data satisfies never\n          throw new Error(`Rendering not implemented for ${self.data.kind} node ${id}`)\n      }\n    },\n\n    get data(): VNodeData {\n      return data\n    },\n    get ownerDocument(): VDocument {\n      return document\n    },\n    get id(): NodeId {\n      return id\n    },\n\n    get state(): VNodeState {\n      return state\n    },\n    set state(value: VNodeState) {\n      if (\n        (state === 'new' && value !== 'connected') ||\n        (state === 'connected' && value !== 'disconnected') ||\n        state === 'disconnected'\n      ) {\n        throw new Error(`Invalid state transition from ${state} to ${value}`)\n      }\n      state = value\n    },\n\n    firstChild: undefined,\n    lastChild: undefined,\n    previousSibling: undefined,\n    nextSibling: undefined,\n    parent: undefined,\n  }\n\n  return self\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vStyleSheet.spec.ts",
    "content": "import type { StyleSheetId } from '../../itemIds'\nimport type { VDocument } from './vDocument'\nimport { createVDocument } from './vDocument'\n\ndescribe('VStyleSheet', () => {\n  let document: VDocument\n\n  beforeEach(() => {\n    document = createVDocument()\n  })\n\n  it('has the expected state on creation', () => {\n    const sheet = document.createStyleSheet({\n      disabled: false,\n      mediaList: [],\n      rules: 'div { color: red }',\n    })\n\n    expect(sheet.id).toBe(0 as StyleSheetId)\n    expect(sheet.ownerDocument).toBe(document)\n    expect(sheet.data).toEqual({\n      disabled: false,\n      mediaList: [],\n      rules: 'div { color: red }',\n    })\n  })\n\n  describe('renderAsAdoptedStyleSheet', () => {\n    it('converts string rules to array', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: ['div { color: red }'],\n        disabled: undefined,\n        media: undefined,\n      })\n    })\n\n    it('preserves array rules', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: ['div { color: red }', 'span { color: blue }'],\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: ['div { color: red }', 'span { color: blue }'],\n        disabled: undefined,\n        media: undefined,\n      })\n    })\n\n    it('renders disabled as true when data.disabled is true', () => {\n      const sheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: [],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result.disabled).toBe(true)\n    })\n\n    it('renders disabled as undefined when data.disabled is false', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result.disabled).toBe(undefined)\n    })\n\n    it('renders media when mediaList has elements', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: ['screen', 'print'],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result.media).toEqual(['screen', 'print'])\n    })\n\n    it('renders media as undefined when mediaList is empty', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result.media).toBe(undefined)\n    })\n\n    it('renders media when mediaList has a single element', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: ['screen'],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result.media).toEqual(['screen'])\n    })\n\n    it('handles empty string rules', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: '',\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: [''],\n        disabled: undefined,\n        media: undefined,\n      })\n    })\n\n    it('handles empty array rules', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: [],\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: [],\n        disabled: undefined,\n        media: undefined,\n      })\n    })\n\n    it('renders all properties when all are set', () => {\n      const sheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: ['screen', 'print'],\n        rules: ['div { color: red }', 'span { color: blue }', 'p { font-size: 14px }'],\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: ['div { color: red }', 'span { color: blue }', 'p { font-size: 14px }'],\n        disabled: true,\n        media: ['screen', 'print'],\n      })\n    })\n\n    it('handles complex CSS rules as string', () => {\n      const complexCSS = `\n        @media screen and (min-width: 768px) {\n          .container {\n            max-width: 1200px;\n          }\n        }\n        @keyframes fade {\n          from { opacity: 0; }\n          to { opacity: 1; }\n        }\n      `\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: complexCSS,\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: [complexCSS],\n        disabled: undefined,\n        media: undefined,\n      })\n    })\n\n    it('handles complex CSS rules as array', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: [\n          '@media screen { div { color: red } }',\n          '@keyframes fade { from { opacity: 0 } }',\n          '.class { background: blue }',\n        ],\n      })\n\n      const result = sheet.renderAsAdoptedStyleSheet()\n\n      expect(result).toEqual({\n        cssRules: [\n          '@media screen { div { color: red } }',\n          '@keyframes fade { from { opacity: 0 } }',\n          '.class { background: blue }',\n        ],\n        disabled: undefined,\n        media: undefined,\n      })\n    })\n  })\n\n  describe('renderAsCssText', () => {\n    it('returns string rules directly', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('div { color: red }')\n    })\n\n    it('joins array rules with empty string', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: ['div { color: red }', 'span { color: blue }'],\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('div { color: red }span { color: blue }')\n    })\n\n    it('handles empty string rules', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: '',\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('')\n    })\n\n    it('handles empty array rules', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: [],\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('')\n    })\n\n    it('handles array with single rule', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: ['div { color: red }'],\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('div { color: red }')\n    })\n\n    it('handles array with multiple rules', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: ['rule1', 'rule2', 'rule3'],\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('rule1rule2rule3')\n    })\n\n    it('preserves whitespace and formatting in string rules', () => {\n      const formattedCSS = `\ndiv {\n  color: red;\n  background: blue;\n}\n\nspan {\n  font-size: 14px;\n}\n      `.trim()\n\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: formattedCSS,\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe(formattedCSS)\n    })\n\n    it('concatenates array rules without separator', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: ['div { color: red; }', 'span { color: blue; }', 'p { font-size: 14px; }'],\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('div { color: red; }span { color: blue; }p { font-size: 14px; }')\n    })\n\n    it('handles complex CSS as string', () => {\n      const complexCSS = `\n        @media screen and (min-width: 768px) {\n          .container {\n            max-width: 1200px;\n          }\n        }\n        @keyframes fade {\n          from { opacity: 0; }\n          to { opacity: 1; }\n        }\n      `\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: complexCSS,\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe(complexCSS)\n    })\n\n    it('does not include disabled or mediaList properties', () => {\n      const sheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: ['screen', 'print'],\n        rules: 'div { color: red }',\n      })\n\n      const result = sheet.renderAsCssText()\n\n      expect(result).toBe('div { color: red }')\n      expect(typeof result).toBe('string')\n    })\n  })\n\n  describe('data getter', () => {\n    it('returns the stylesheet data', () => {\n      const data = {\n        disabled: true,\n        mediaList: ['screen'],\n        rules: ['rule1', 'rule2'],\n      }\n      const sheet = document.createStyleSheet(data)\n\n      expect(sheet.data).toBe(data)\n    })\n\n    it('allows access to individual data properties', () => {\n      const sheet = document.createStyleSheet({\n        disabled: true,\n        mediaList: ['screen', 'print'],\n        rules: 'div { color: red }',\n      })\n\n      expect(sheet.data.disabled).toBe(true)\n      expect(sheet.data.mediaList).toEqual(['screen', 'print'])\n      expect(sheet.data.rules).toBe('div { color: red }')\n    })\n  })\n\n  describe('id getter', () => {\n    it('returns the stylesheet id', () => {\n      const sheet1 = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: '',\n      })\n      const sheet2 = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: '',\n      })\n\n      expect(sheet1.id).toBe(0 as StyleSheetId)\n      expect(sheet2.id).toBe(1 as StyleSheetId)\n    })\n  })\n\n  describe('ownerDocument getter', () => {\n    it('returns the owner document', () => {\n      const sheet = document.createStyleSheet({\n        disabled: false,\n        mediaList: [],\n        rules: '',\n      })\n\n      expect(sheet.ownerDocument).toBe(document)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/conversions/vStyleSheet.ts",
    "content": "import type { StyleSheet } from '../../../../types'\nimport type { StyleSheetId } from '../../itemIds'\nimport type { VDocument } from './vDocument'\n\nexport interface VStyleSheet {\n  renderAsAdoptedStyleSheet(): StyleSheet\n  renderAsCssText(): string\n\n  get data(): VStyleSheetData\n  get id(): StyleSheetId\n  get ownerDocument(): VDocument\n}\n\nexport interface VStyleSheetData {\n  disabled: boolean\n  mediaList: string[]\n  rules: string | string[]\n}\n\nexport function createVStyleSheet(document: VDocument, id: StyleSheetId, data: VStyleSheetData): VStyleSheet {\n  const self: VStyleSheet = {\n    renderAsAdoptedStyleSheet(): StyleSheet {\n      const cssRules = typeof data.rules === 'string' ? [data.rules] : data.rules\n      return {\n        cssRules,\n        disabled: data.disabled ? true : undefined,\n        media: data.mediaList.length > 0 ? data.mediaList : undefined,\n      }\n    },\n\n    renderAsCssText(): string {\n      return typeof data.rules === 'string' ? data.rules : data.rules.join('')\n    },\n\n    get data(): VStyleSheetData {\n      return data\n    },\n    get id(): StyleSheetId {\n      return id\n    },\n    get ownerDocument(): VDocument {\n      return document\n    },\n  }\n\n  return self\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/experimentalFeatures.ts",
    "content": "import { ExperimentalFeature, isExperimentalFeatureEnabled } from '@datadog/browser-core'\n\nexport function isFullSnapshotChangeRecordsEnabled(): boolean {\n  // We don't want to have to support the case where full snapshots use the old format and\n  // incremental snapshots use the new one, so we should generate full snapshot Change\n  // records if either feature flag is enabled.\n  return (\n    isExperimentalFeatureEnabled(ExperimentalFeature.USE_CHANGE_RECORDS) ||\n    isExperimentalFeatureEnabled(ExperimentalFeature.USE_INCREMENTAL_CHANGE_RECORDS)\n  )\n}\n\nexport function isIncrementalSnapshotChangeRecordsEnabled(): boolean {\n  return isExperimentalFeatureEnabled(ExperimentalFeature.USE_INCREMENTAL_CHANGE_RECORDS)\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/htmlAst.specHelper.ts",
    "content": "import { NodePrivacyLevel, PRIVACY_ATTR_NAME } from '@datadog/browser-rum-core'\nimport { display, objectValues } from '@datadog/browser-core'\nimport type { SerializedNodeWithId } from '../../../types'\nimport {\n  createSerializationTransactionForTesting,\n  serializeNodeAndVerifyChangeRecord as serializeNode,\n} from '../test/serialization.specHelper'\n\nexport const makeHtmlDoc = (htmlContent: string, privacyTag: string) => {\n  try {\n    const newDoc = document.implementation.createHTMLDocument('new doc')\n    newDoc.documentElement.innerHTML = htmlContent\n    newDoc.documentElement.setAttribute(PRIVACY_ATTR_NAME, privacyTag)\n    return newDoc\n  } catch (e) {\n    display.error('Failed to set innerHTML of new doc:', e)\n    return document\n  }\n}\n\nexport const removeIdFieldsRecursivelyClone = (thing: Record<string, unknown>): Record<string, unknown> => {\n  if (thing && typeof thing === 'object') {\n    const object = thing\n    delete object.id\n    objectValues(object).forEach((value) => removeIdFieldsRecursivelyClone(value as Record<string, unknown>))\n    return object\n  }\n  return thing\n}\n\nexport const generateLeanSerializedDoc = (htmlContent: string, privacyTag: string) => {\n  const transaction = createSerializationTransactionForTesting()\n  const newDoc = makeHtmlDoc(htmlContent, privacyTag)\n  const serializedDoc = removeIdFieldsRecursivelyClone(\n    serializeNode(newDoc, NodePrivacyLevel.ALLOW, transaction) as unknown as Record<string, unknown>\n  ) as unknown as SerializedNodeWithId\n  return serializedDoc\n}\n\nexport const HTML = `\n<head>\n    <link href=\"https://public.com/path/nested?query=param#hash\" rel=\"stylesheet\">\n    <style>\n      .example {color: red;}\n    </style>\n    <script>private</script>\n    <meta>\n    <base>\n    <title>private title</title>\n</head>\n<body>\n    <h1>hello private world</h1>\n    <p>Loreum ipsum private text</p>\n    <noscript>hello private world</noscript>\n    <a href='https://private.com/path/nested?query=param#hash'>\n      Click https://private.com/path/nested?query=param#hash\n    </a>\n    <img src='https://private.com/path/nested?query=param#hash'>\n    <video controls>\n      <source src=\"https://private.com/path/nested?query=param#hash\" type=\"video/webm\">\n      <source src=\"https://private.com/path/nested?query=param#hash\" type=\"video/mp4\">\n      <p>Your browser cannot play the provided video file.</p>\n    </video>\n    <select>\n      <option aria-label='A'>private option A</option>\n      <option aria-label='B'>private option B</option>\n      <option aria-label='C'>private option C</option>\n    </select>\n    <input type=\"password\">\n    <input type=\"text\">\n    <input type=\"checkbox\" id=\"inputFoo\" name=\"inputFoo\" checked>\n    <label for=\"inputFoo\">inputFoo label</label>\n\n    <input type=\"radio\" id=\"bar-private\" name=\"radioGroup\" value=\"bar-private\">\n\n    <textarea id=\"baz\" name=\"baz\" rows=\"2\" cols=\"20\">\n      Loreum Ipsum private ...\n    </textarea>\n\n    <div contentEditable>editable private div</div>\n</body>`\n\nexport const AST_HIDDEN = {\n  type: 0,\n  childNodes: [\n    {\n      type: 1,\n      name: 'html',\n      publicId: '',\n      systemId: '',\n    },\n    {\n      type: 2,\n      tagName: 'html',\n      attributes: {\n        rr_width: '0px',\n        rr_height: '0px',\n        'data-dd-privacy': 'hidden',\n      },\n      childNodes: [],\n    },\n  ],\n}\n\nexport const AST_MASK = {\n  type: 0,\n  childNodes: [\n    {\n      type: 1,\n      name: 'html',\n      publicId: '',\n      systemId: '',\n    },\n    {\n      type: 2,\n      tagName: 'html',\n      attributes: {\n        'data-dd-privacy': 'mask',\n      },\n      childNodes: [\n        {\n          type: 2,\n          tagName: 'head',\n          attributes: {},\n          childNodes: [\n            {\n              type: 2,\n              tagName: 'link',\n              attributes: {\n                href: 'https://public.com/path/nested?query=param#hash',\n                rel: 'stylesheet',\n              },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'style',\n              attributes: { _cssText: '.example { color: red; }' },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'meta',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'base',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'title',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxxx xxxxx',\n                },\n              ],\n            },\n          ],\n        },\n        {\n          type: 3,\n          textContent: '\\n',\n        },\n        {\n          type: 2,\n          tagName: 'body',\n          attributes: {},\n          childNodes: [\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'h1',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxx xxxxxxx xxxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'p',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxx xxxxx xxxxxxx xxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'noscript',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxx xxxxxxx xxxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'a',\n              attributes: {\n                href: '***',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'img',\n              attributes: {\n                src: 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'video',\n              attributes: {\n                controls: '',\n                rr_mediaState: 'paused',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==',\n                    type: 'video/webm',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==',\n                    type: 'video/mp4',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'p',\n                  attributes: {},\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'xxxx xxxxxxx xxxxxx xxxx xxx xxxxxxxx xxxxx xxxxx',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'select',\n              attributes: {\n                value: '***',\n              },\n              childNodes: [\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': '***',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': '***',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': '***',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'password',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'text',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'checkbox',\n                name: '***',\n                value: '***',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'label',\n              attributes: {\n                for: 'inputFoo',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxxxx xxxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'radio',\n                name: '***',\n                value: '***',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'textarea',\n              attributes: {\n                name: '***',\n                rows: '2',\n                cols: '20',\n                value: '***',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '      xxxxxx xxxxx xxxxxxx xxx\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'div',\n              attributes: {\n                contenteditable: '',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxxxx xxxxxxx xxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n',\n            },\n          ],\n        },\n      ],\n    },\n  ],\n}\n\nexport const AST_MASK_USER_INPUT = {\n  type: 0,\n  childNodes: [\n    {\n      type: 1,\n      name: 'html',\n      publicId: '',\n      systemId: '',\n    },\n    {\n      type: 2,\n      tagName: 'html',\n      attributes: {\n        'data-dd-privacy': 'mask-user-input',\n      },\n      childNodes: [\n        {\n          type: 2,\n          tagName: 'head',\n          attributes: {},\n          childNodes: [\n            {\n              type: 2,\n              tagName: 'link',\n              attributes: {\n                href: 'https://public.com/path/nested?query=param#hash',\n                rel: 'stylesheet',\n              },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'style',\n              attributes: { _cssText: '.example { color: red; }' },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'meta',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'base',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'title',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'private title',\n                },\n              ],\n            },\n          ],\n        },\n        {\n          type: 3,\n          textContent: '\\n',\n        },\n        {\n          type: 2,\n          tagName: 'body',\n          attributes: {},\n          childNodes: [\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'h1',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'hello private world',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'p',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'Loreum ipsum private text',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'noscript',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'hello private world',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'a',\n              attributes: {\n                href: 'https://private.com/path/nested?query=param#hash',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      Click https://private.com/path/nested?query=param#hash\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'img',\n              attributes: {\n                src: 'https://private.com/path/nested?query=param#hash',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'video',\n              attributes: {\n                controls: '',\n                rr_mediaState: 'paused',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'https://private.com/path/nested?query=param#hash',\n                    type: 'video/webm',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'https://private.com/path/nested?query=param#hash',\n                    type: 'video/mp4',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'p',\n                  attributes: {},\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'Your browser cannot play the provided video file.',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'select',\n              attributes: {\n                value: '***',\n              },\n              childNodes: [\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': 'A',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': 'B',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': 'C',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'password',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'text',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'checkbox',\n                name: 'inputFoo',\n                value: '***',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'label',\n              attributes: {\n                for: 'inputFoo',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'inputFoo label',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'radio',\n                name: 'radioGroup',\n                value: '***',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'textarea',\n              attributes: {\n                name: 'baz',\n                rows: '2',\n                cols: '20',\n                value: '***',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '      xxxxxx xxxxx xxxxxxx xxx\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'div',\n              attributes: {\n                contenteditable: '',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'editable private div',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n',\n            },\n          ],\n        },\n      ],\n    },\n  ],\n}\n\nexport const AST_MASK_UNLESS_ALLOWLISTED = {\n  type: 0,\n  childNodes: [\n    {\n      type: 1,\n      name: 'html',\n      publicId: '',\n      systemId: '',\n    },\n    {\n      type: 2,\n      tagName: 'html',\n      attributes: {\n        'data-dd-privacy': 'mask-unless-allowlisted',\n      },\n      childNodes: [\n        {\n          type: 2,\n          tagName: 'head',\n          attributes: {},\n          childNodes: [\n            {\n              type: 2,\n              tagName: 'link',\n              attributes: {\n                href: 'https://public.com/path/nested?query=param#hash',\n                rel: 'stylesheet',\n              },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'style',\n              attributes: { _cssText: '.example { color: red; }' },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'meta',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'base',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'title',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxxx xxxxx',\n                },\n              ],\n            },\n          ],\n        },\n        {\n          type: 3,\n          textContent: '\\n',\n        },\n        {\n          type: 2,\n          tagName: 'body',\n          attributes: {},\n          childNodes: [\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'h1',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxx xxxxxxx xxxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'p',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxx xxxxx xxxxxxx xxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'noscript',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxx xxxxxxx xxxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'a',\n              attributes: {\n                href: '***',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'img',\n              attributes: {\n                src: 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'video',\n              attributes: {\n                controls: '',\n                rr_mediaState: 'paused',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==',\n                    type: 'video/webm',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==',\n                    type: 'video/mp4',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'p',\n                  attributes: {},\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'xxxx xxxxxxx xxxxxx xxxx xxx xxxxxxxx xxxxx xxxxx',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'select',\n              attributes: {\n                value: '***',\n              },\n              childNodes: [\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': '***',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': '***',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': '***',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: '***',\n                    },\n                  ],\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'password',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'text',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'checkbox',\n                name: '***',\n                value: '***',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'label',\n              attributes: {\n                for: 'inputFoo',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxxxx xxxxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'radio',\n                name: '***',\n                value: '***',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'textarea',\n              attributes: {\n                name: '***',\n                rows: '2',\n                cols: '20',\n                value: '***',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '      xxxxxx xxxxx xxxxxxx xxx\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'div',\n              attributes: {\n                contenteditable: '',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'xxxxxxxx xxxxxxx xxx',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n',\n            },\n          ],\n        },\n      ],\n    },\n  ],\n}\n\nexport const AST_ALLOW = {\n  type: 0,\n  childNodes: [\n    {\n      type: 1,\n      name: 'html',\n      publicId: '',\n      systemId: '',\n    },\n    {\n      type: 2,\n      tagName: 'html',\n      attributes: {\n        'data-dd-privacy': 'allow',\n      },\n      childNodes: [\n        {\n          type: 2,\n          tagName: 'head',\n          attributes: {},\n          childNodes: [\n            {\n              type: 2,\n              tagName: 'link',\n              attributes: {\n                href: 'https://public.com/path/nested?query=param#hash',\n                rel: 'stylesheet',\n              },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'style',\n              attributes: { _cssText: '.example { color: red; }' },\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'meta',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'base',\n              attributes: {},\n              childNodes: [],\n            },\n            {\n              type: 2,\n              tagName: 'title',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'private title',\n                },\n              ],\n            },\n          ],\n        },\n        {\n          type: 3,\n          textContent: '\\n',\n        },\n        {\n          type: 2,\n          tagName: 'body',\n          attributes: {},\n          childNodes: [\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'h1',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'hello private world',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'p',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'Loreum ipsum private text',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'noscript',\n              attributes: {},\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'hello private world',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'a',\n              attributes: {\n                href: 'https://private.com/path/nested?query=param#hash',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      Click https://private.com/path/nested?query=param#hash\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'img',\n              attributes: {\n                src: 'https://private.com/path/nested?query=param#hash',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'video',\n              attributes: {\n                controls: '',\n                rr_mediaState: 'paused',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'https://private.com/path/nested?query=param#hash',\n                    type: 'video/webm',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'source',\n                  attributes: {\n                    src: 'https://private.com/path/nested?query=param#hash',\n                    type: 'video/mp4',\n                  },\n                  childNodes: [],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'p',\n                  attributes: {},\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'Your browser cannot play the provided video file.',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'select',\n              attributes: {\n                value: 'private option A',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    selected: '',\n                    'aria-label': 'A',\n                    value: 'private option A',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'private option A',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': 'B',\n                    value: 'private option B',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'private option B',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n      ',\n                },\n                {\n                  type: 2,\n                  tagName: 'option',\n                  attributes: {\n                    'aria-label': 'C',\n                    value: 'private option C',\n                  },\n                  childNodes: [\n                    {\n                      type: 3,\n                      textContent: 'private option C',\n                    },\n                  ],\n                },\n                {\n                  type: 3,\n                  textContent: '\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'password',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'text',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'checkbox',\n                name: 'inputFoo',\n                value: 'on',\n                checked: '',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'label',\n              attributes: {\n                for: 'inputFoo',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'inputFoo label',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'input',\n              attributes: {\n                type: 'radio',\n                name: 'radioGroup',\n                value: 'bar-private',\n              },\n              childNodes: [],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'textarea',\n              attributes: {\n                name: 'baz',\n                rows: '2',\n                cols: '20',\n                value: '      Loreum Ipsum private ...\\n    ',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: '      Loreum Ipsum private ...\\n    ',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n\\n    ',\n            },\n            {\n              type: 2,\n              tagName: 'div',\n              attributes: {\n                contenteditable: '',\n              },\n              childNodes: [\n                {\n                  type: 3,\n                  textContent: 'editable private div',\n                },\n              ],\n            },\n            {\n              type: 3,\n              textContent: '\\n',\n            },\n          ],\n        },\n      ],\n    },\n  ],\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/index.ts",
    "content": "export type { ChangeConverter, ChangeDecoder, MutationLog, NodeIdRemapper } from './conversions'\nexport {\n  createChangeConverter,\n  createChangeDecoder,\n  createCopyingNodeIdRemapper,\n  createIdentityNodeIdRemapper,\n} from './conversions'\nexport { isFullSnapshotChangeRecordsEnabled, isIncrementalSnapshotChangeRecordsEnabled } from './experimentalFeatures'\nexport { createChildInsertionCursor, createRootInsertionCursor } from './insertionCursor'\nexport { getElementInputValue } from './serializationUtils'\nexport { serializeFullSnapshot } from './serializeFullSnapshot'\nexport { serializeFullSnapshotAsChange } from './serializeFullSnapshotAsChange'\nexport { serializeMutations } from './serializeMutations'\nexport { serializeMutationsAsChange } from './serializeMutationsAsChange'\nexport { serializeNode } from './serializeNode'\nexport { serializeNodeAsChange } from './serializeNodeAsChange'\nexport { serializeAttribute } from './serializeAttribute'\nexport { createSerializationStats, updateSerializationStats, aggregateSerializationStats } from './serializationStats'\nexport type { SerializationMetric, SerializationStats } from './serializationStats'\nexport { serializeChangesInTransaction, serializeInTransaction, SerializationKind } from './serializationTransaction'\nexport type {\n  ChangeSerializationTransaction,\n  SerializationTransaction,\n  SerializationTransactionCallback,\n} from './serializationTransaction'\nexport type { ParentNodePrivacyLevel } from './serialization.types'\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/insertionCursor.spec.ts",
    "content": "import type { InsertionPoint } from '../../../types'\nimport type { NodeId, NodeIds } from '../itemIds'\nimport { createNodeIds } from '../itemIds'\nimport { createChildInsertionCursor, createRootInsertionCursor } from './insertionCursor'\n\ndescribe('InsertionCursor', () => {\n  let nodeIds: NodeIds\n\n  beforeEach(() => {\n    nodeIds = createNodeIds()\n  })\n\n  function createNode(): Node {\n    return document.createElement('div')\n  }\n\n  type DecodedInsertionPoint =\n    | {\n        type: 'root'\n      }\n    | {\n        type: 'after'\n        previous: NodeId\n      }\n    | {\n        type: 'appendChild'\n        parent: NodeId\n      }\n    | {\n        type: 'insertBefore'\n        nextSibling: NodeId\n      }\n\n  function decodeInsertionPoint({\n    nodeId,\n    insertionPoint,\n  }: {\n    nodeId: NodeId\n    insertionPoint: InsertionPoint\n  }): DecodedInsertionPoint {\n    if (insertionPoint === null) {\n      return { type: 'root' }\n    }\n    if (insertionPoint === 0) {\n      const previous = (nodeId - 1) as NodeId\n      return { type: 'after', previous }\n    }\n    if (insertionPoint < 0) {\n      const nextSibling = (nodeId + insertionPoint) as NodeId\n      return { type: 'insertBefore', nextSibling }\n    }\n    const parent = (nodeId - insertionPoint) as NodeId\n    return { type: 'appendChild', parent }\n  }\n\n  it('can generate insertion points for a realistic DOM structure', () => {\n    const cursor = createRootInsertionCursor(nodeIds)\n    const document = createNode()\n    const documentResult = cursor.advance(document)\n    expect(documentResult.nodeId).toBe(0 as NodeId)\n    expect(decodeInsertionPoint(documentResult)).toEqual({ type: 'root' })\n\n    {\n      cursor.descend()\n\n      const head = createNode()\n      const headResult = cursor.advance(head)\n      expect(headResult.nodeId).toBe(1 as NodeId)\n      expect(decodeInsertionPoint(headResult)).toEqual({ type: 'appendChild', parent: documentResult.nodeId })\n\n      {\n        cursor.descend()\n\n        const title = createNode()\n        const titleResult = cursor.advance(title)\n        expect(titleResult.nodeId).toBe(2 as NodeId)\n        expect(decodeInsertionPoint(titleResult)).toEqual({ type: 'appendChild', parent: headResult.nodeId })\n\n        const style = createNode()\n        const styleResult = cursor.advance(style)\n        expect(styleResult.nodeId).toBe(3 as NodeId)\n        expect(decodeInsertionPoint(styleResult)).toEqual({ type: 'after', previous: titleResult.nodeId })\n\n        cursor.ascend()\n      }\n\n      const body = createNode()\n      const bodyResult = cursor.advance(body)\n      expect(bodyResult.nodeId).toBe(4 as NodeId)\n      expect(decodeInsertionPoint(bodyResult)).toEqual({ type: 'appendChild', parent: documentResult.nodeId })\n\n      {\n        cursor.descend()\n\n        const div = createNode()\n        const divResult = cursor.advance(div)\n        expect(divResult.nodeId).toBe(5 as NodeId)\n        expect(decodeInsertionPoint(divResult)).toEqual({ type: 'appendChild', parent: bodyResult.nodeId })\n\n        const p = createNode()\n        const pResult = cursor.advance(p)\n        expect(pResult.nodeId).toBe(6 as NodeId)\n        expect(decodeInsertionPoint(pResult)).toEqual({ type: 'after', previous: divResult.nodeId })\n\n        const span = createNode()\n        const spanResult = cursor.advance(span)\n        expect(spanResult.nodeId).toBe(7 as NodeId)\n        expect(decodeInsertionPoint(spanResult)).toEqual({ type: 'after', previous: pResult.nodeId })\n\n        cursor.ascend()\n      }\n\n      cursor.ascend()\n    }\n  })\n\n  describe('createRootInsertionCursor', () => {\n    it('can create a cursor that starts at the root of the document', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n\n      // We should generate a RootInsertionPoint for the root node.\n      const root = createNode()\n      const rootResult = cursor.advance(root)\n      expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n      // We should use an AppendAfterPreviousInsertionPoint for subsequent siblings.\n      // (Obviously siblings of the root node don't make sense, but we tolerate this\n      // situation nonetheless.)\n      const nextSibling = createNode()\n      const nextSiblingResult = cursor.advance(nextSibling)\n      expect(decodeInsertionPoint(nextSiblingResult)).toEqual({ type: 'after', previous: rootResult.nodeId })\n    })\n  })\n\n  describe('createChildInsertionCursor', () => {\n    it('can create a cursor that starts at the end of the child list', () => {\n      const rootCursor = createRootInsertionCursor(nodeIds)\n      const parentNode = createNode()\n      const { nodeId: parentId } = rootCursor.advance(parentNode)\n\n      // Passing 'undefined' for nextSiblingId means that we should insert the new child\n      // at the end of the child list.\n      const cursor = createChildInsertionCursor(parentId, undefined, nodeIds)\n\n      // We should generate an AppendChildInsertionPoint for the first child.\n      const firstChild = createNode()\n      const firstChildResult = cursor.advance(firstChild)\n      expect(decodeInsertionPoint(firstChildResult)).toEqual({ type: 'appendChild', parent: parentId })\n\n      // We should use an AppendAfterPreviousInsertionPoint for subsequent children.\n      const secondChild = createNode()\n      const secondChildResult = cursor.advance(secondChild)\n      expect(decodeInsertionPoint(secondChildResult)).toEqual({ type: 'after', previous: firstChildResult.nodeId })\n    })\n\n    it('can create a cursor that starts before another node in the child list', () => {\n      const rootCursor = createRootInsertionCursor(nodeIds)\n      const parentNode = createNode()\n      const { nodeId: parentId } = rootCursor.advance(parentNode)\n\n      rootCursor.descend()\n      const nextSiblingNode = createNode()\n      const { nodeId: nextSiblingId } = rootCursor.advance(nextSiblingNode)\n\n      // Passing a nextSiblingId value means we should insert the new node before the\n      // given sibling.\n      const cursor = createChildInsertionCursor(parentId, nextSiblingId, nodeIds)\n\n      // We should generate an InsertBeforeInsertionPoint for the first new child.\n      const firstChild = createNode()\n      const firstChildResult = cursor.advance(firstChild)\n      expect(decodeInsertionPoint(firstChildResult)).toEqual({ type: 'insertBefore', nextSibling: nextSiblingId })\n\n      // We should use an AppendAfterPreviousInsertionPoint for subsequent children.\n      const secondChild = createNode()\n      const secondChildResult = cursor.advance(secondChild)\n      expect(decodeInsertionPoint(secondChildResult)).toEqual({ type: 'after', previous: firstChildResult.nodeId })\n    })\n  })\n\n  describe('advance', () => {\n    it('returns a RootInsertionPoint for the root node', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const root = createNode()\n      const result = cursor.advance(root)\n      expect(result.nodeId).toBe(0 as NodeId)\n      expect(result.insertionPoint).toBe(null)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'root' })\n    })\n\n    it('returns an AppendChildInsertionPoint for the first child inserted after descending', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const root = createNode()\n      const { nodeId: rootNodeId } = cursor.advance(root)\n\n      // Descend; the cursor now points to the beginning of a new child list.\n      cursor.descend()\n\n      const firstSibling = createNode()\n      const result = cursor.advance(firstSibling)\n      expect(result.nodeId).toBe(1 as NodeId)\n      expect(result.insertionPoint).toBe(1)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'appendChild', parent: rootNodeId })\n    })\n\n    it('returns an AppendChildInsertionPoint for a new child appended via createChildInsertionCursor', () => {\n      const rootCursor = createRootInsertionCursor(nodeIds)\n      const parentNode = createNode()\n      const { nodeId: parentNodeId } = rootCursor.advance(parentNode)\n\n      // Create an insertion cursor pointing to the end of an existing child list.\n      const cursor = createChildInsertionCursor(parentNodeId, undefined, nodeIds)\n\n      const appendedNode = createNode()\n      const result = cursor.advance(appendedNode)\n      expect(result.nodeId).toBe(1 as NodeId)\n      expect(result.insertionPoint).toBe(1)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'appendChild', parent: parentNodeId })\n    })\n\n    it('returns an InsertBeforeInsertionPoint for a new child inserted via createChildInsertionCursor', () => {\n      const rootCursor = createRootInsertionCursor(nodeIds)\n      const parentNode = createNode()\n      const { nodeId: parentNodeId } = rootCursor.advance(parentNode)\n\n      rootCursor.descend()\n      const existingSiblingNode = createNode()\n      const { nodeId: existingSiblingId } = rootCursor.advance(existingSiblingNode)\n\n      // Create an insertion cursor pointing inside an existing child list, directly\n      // before existingSiblingNode.\n      const cursor = createChildInsertionCursor(parentNodeId, existingSiblingId, nodeIds)\n\n      const insertedNode = createNode()\n      const result = cursor.advance(insertedNode)\n      expect(result.nodeId).toBe(2 as NodeId)\n      expect(result.insertionPoint).toBe(-1)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'insertBefore', nextSibling: existingSiblingId })\n    })\n\n    it('returns an InsertAfterPreviousInsertionPoint for sibling nodes', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const siblingNodes = [createNode(), createNode(), createNode(), createNode()]\n      for (let index = 0; index < siblingNodes.length; index++) {\n        const result = cursor.advance(siblingNodes[index])\n        expect(result.nodeId).toBe(index as NodeId)\n\n        if (index === 0) {\n          expect(result.insertionPoint).toBe(null)\n          expect(decodeInsertionPoint(result)).toEqual({ type: 'root' })\n        } else {\n          expect(result.insertionPoint).toBe(0)\n          const previous = (index - 1) as NodeId\n          expect(decodeInsertionPoint(result)).toEqual({ type: 'after', previous })\n        }\n      }\n    })\n\n    it('reuses existing node ids for the same node', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const node = createNode()\n      const firstNodeId = cursor.advance(node).nodeId\n      const secondNodeId = cursor.advance(node).nodeId\n      expect(firstNodeId).toBe(secondNodeId)\n    })\n  })\n\n  describe('descend', () => {\n    it('updates insertion point to target the most deeply nested node', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const root = createNode()\n      const rootResult = cursor.advance(root)\n      expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n      cursor.descend()\n\n      const child = createNode()\n      const childResult = cursor.advance(child)\n      expect(decodeInsertionPoint(childResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n      cursor.descend()\n\n      const grandchild = createNode()\n      const grandchildResult = cursor.advance(grandchild)\n      expect(decodeInsertionPoint(grandchildResult)).toEqual({ type: 'appendChild', parent: childResult.nodeId })\n    })\n\n    it('has no effect if called without a previous advance', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      cursor.descend() // Should have no effect.\n\n      // When we advance, the result should be the same as if descend() was never called.\n      const root = createNode()\n      const result = cursor.advance(root)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'root' })\n    })\n\n    it('has no effect if called multiple times without advancing', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const root = createNode()\n      const rootResult = cursor.advance(root)\n      expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n      cursor.descend()\n      cursor.descend() // Should have no additional effect.\n      cursor.descend() // Should have no additional effect.\n\n      // When we advance, the result should be the same as if descend() was only called once.\n      const child = createNode()\n      const childResult = cursor.advance(child)\n      expect(decodeInsertionPoint(childResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n    })\n  })\n\n  describe('ascend', () => {\n    describe('after a subtree containing at least one node', () => {\n      describe(\"if ascending to a child list that's new\", () => {\n        it('triggers an AppendChildInsertionPoint at the next advance', () => {\n          const cursor = createRootInsertionCursor(nodeIds)\n          const root = createNode()\n          const rootResult = cursor.advance(root)\n          expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n          cursor.descend() // Descend into the root node's child list.\n\n          const parent = createNode()\n          const parentResult = cursor.advance(parent)\n          expect(decodeInsertionPoint(parentResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n\n          cursor.descend() // Descend into the parent node's child list.\n\n          const child1 = createNode()\n          const child1Result = cursor.advance(child1)\n          expect(decodeInsertionPoint(child1Result)).toEqual({ type: 'appendChild', parent: parentResult.nodeId })\n\n          const child2 = createNode()\n          const child2Result = cursor.advance(child2)\n          expect(decodeInsertionPoint(child2Result)).toEqual({ type: 'after', previous: child1Result.nodeId })\n\n          cursor.ascend() // Ascend out of the parent node's child list.\n\n          // We should use an AppendChildInsertionPoint; an InsertAfterPreviousInsertionPoint\n          // would insert the new node as a sibling of `child2`, which is not where it belongs.\n          const parentSibling = createNode()\n          const parentSiblingResult = cursor.advance(parentSibling)\n          expect(decodeInsertionPoint(parentSiblingResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n        })\n      })\n\n      describe(\"if ascending to an existing child list that's being appended to\", () => {\n        it('triggers an AppendChildInsertionPoint at the next advance', () => {\n          // Use a root InsertionCursor to construct the root node.\n          const rootCursor = createRootInsertionCursor(nodeIds)\n          const root = createNode()\n          const rootResult = rootCursor.advance(root)\n          expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n          // Create a new InsertionCursor that appends to the root node's child list.\n          const cursor = createChildInsertionCursor(rootResult.nodeId, undefined, nodeIds)\n\n          // Create the parent node using the new InsertionCursor, appending it to the child\n          // list of the root node.\n          const parent = createNode()\n          const parentResult = cursor.advance(parent)\n          expect(decodeInsertionPoint(parentResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n\n          cursor.descend() // Descend into the parent node's child list.\n\n          const child1 = createNode()\n          const child1Result = cursor.advance(child1)\n          expect(decodeInsertionPoint(child1Result)).toEqual({ type: 'appendChild', parent: parentResult.nodeId })\n\n          const child2 = createNode()\n          const child2Result = cursor.advance(child2)\n          expect(decodeInsertionPoint(child2Result)).toEqual({ type: 'after', previous: child1Result.nodeId })\n\n          cursor.ascend() // Ascend out of the parent node's child list.\n\n          // We should use an AppendChildInsertionPoint; an InsertAfterPreviousInsertionPoint\n          // would insert the new node as a sibling of `child2`, which is not where it belongs.\n          const parentSibling = createNode()\n          const parentSiblingResult = cursor.advance(parentSibling)\n          expect(decodeInsertionPoint(parentSiblingResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n        })\n      })\n\n      describe(\"if ascending to an existing child list that's being inserted into\", () => {\n        it('triggers an InsertBeforeInsertionPoint at the next advance', () => {\n          // Use a root InsertionCursor to construct the root node and a first child which\n          // will end up becoming the parent node's next sibling.\n          const rootCursor = createRootInsertionCursor(nodeIds)\n          const root = createNode()\n          const rootResult = rootCursor.advance(root)\n          expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n          rootCursor.descend()\n          const parentNextSibling = createNode()\n          const parentNextSiblingResult = rootCursor.advance(parentNextSibling)\n          expect(decodeInsertionPoint(parentNextSiblingResult)).toEqual({\n            type: 'appendChild',\n            parent: rootResult.nodeId,\n          })\n\n          // Create a new InsertionCursor that inserts into the root node's child list.\n          const cursor = createChildInsertionCursor(rootResult.nodeId, parentNextSiblingResult.nodeId, nodeIds)\n\n          // Create the parent node using the new InsertionCursor, inserting it as the first\n          // child of the root node.\n          const parent = createNode()\n          const parentResult = cursor.advance(parent)\n          expect(decodeInsertionPoint(parentResult)).toEqual({\n            type: 'insertBefore',\n            nextSibling: parentNextSiblingResult.nodeId,\n          })\n\n          cursor.descend() // Descend into the parent node's child list.\n\n          const child1 = createNode()\n          const child1Result = cursor.advance(child1)\n          expect(decodeInsertionPoint(child1Result)).toEqual({ type: 'appendChild', parent: parentResult.nodeId })\n\n          const child2 = createNode()\n          const child2Result = cursor.advance(child2)\n          expect(decodeInsertionPoint(child2Result)).toEqual({ type: 'after', previous: child1Result.nodeId })\n\n          cursor.ascend() // Ascend out of the parent node's child list.\n\n          // We should use an InsertionBeforeInsertionPoint. An InsertAfterPreviousInsertionPoint\n          // would insert the new node as a sibling of `child2`, which is not where it\n          // belongs. An AppendChildInsertionPoint would insert the new node after\n          // `parentNodeNextSibling`, which is again not where it belongs.\n          const parentPreviousSibling = createNode()\n          const parentPreviousSiblingResult = cursor.advance(parentPreviousSibling)\n          expect(decodeInsertionPoint(parentPreviousSiblingResult)).toEqual({\n            type: 'insertBefore',\n            nextSibling: parentNextSiblingResult.nodeId,\n          })\n        })\n      })\n    })\n\n    describe('after an empty subtree', () => {\n      describe(\"if ascending to a child list that's new\", () => {\n        it('triggers an InsertAfterPreviousInsertionPoint at the next advance', () => {\n          // Use a root InsertionCursor to construct the root node.\n          const rootCursor = createRootInsertionCursor(nodeIds)\n          const root = createNode()\n          const rootResult = rootCursor.advance(root)\n          expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n          // Create a new InsertionCursor that appends to the root node's child list.\n          const cursor = createChildInsertionCursor(rootResult.nodeId, undefined, nodeIds)\n\n          const parent = createNode()\n          const parentResult = cursor.advance(parent)\n          expect(decodeInsertionPoint(parentResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n\n          cursor.descend() // Descend into the parent node's child list.\n          // Do nothing, simulating an empty subtree.\n          cursor.ascend() // Ascend out of the parent node's child list.\n\n          // We should use an InsertAfterPreviousInsertionPoint, just as if descend() and\n          // ascend() had not been called, because the new node is a sibling of the previous\n          // node, `parent`.\n          const parentSibling = createNode()\n          const parentSiblingResult = cursor.advance(parentSibling)\n          expect(decodeInsertionPoint(parentSiblingResult)).toEqual({ type: 'after', previous: parentResult.nodeId })\n        })\n      })\n\n      describe(\"if ascending to an existing child list that's being appended to\", () => {\n        it('triggers an InsertAfterPreviousInsertionPoint at the next advance', () => {\n          const cursor = createRootInsertionCursor(nodeIds)\n          const root = createNode()\n          const rootResult = cursor.advance(root)\n          expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n          cursor.descend() // Descend into the root node's child list.\n\n          // Create the parent node using the new InsertionCursor, appending it to the child\n          // list of the root node.\n          const parent = createNode()\n          const parentResult = cursor.advance(parent)\n          expect(decodeInsertionPoint(parentResult)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n\n          cursor.descend() // Descend into the parent node's child list.\n          // Do nothing, simulating an empty subtree.\n          cursor.ascend() // Ascend out of the parent node's child list.\n\n          // We should use an InsertAfterPreviousInsertionPoint, just as if descend() and\n          // ascend() had not been called, because the new node is a sibling of the previous\n          // node, `parent`.\n          const parentSibling = createNode()\n          const parentSiblingResult = cursor.advance(parentSibling)\n          expect(decodeInsertionPoint(parentSiblingResult)).toEqual({ type: 'after', previous: parentResult.nodeId })\n        })\n      })\n\n      describe(\"if ascending to an existing child list that's being inserted into\", () => {\n        it('triggers an InsertAfterPreviousInsertionPoint at the next advance', () => {\n          // Use a root InsertionCursor to construct the root node and a first child which\n          // will end up becoming the parent node's next sibling.\n          const rootCursor = createRootInsertionCursor(nodeIds)\n          const root = createNode()\n          const rootResult = rootCursor.advance(root)\n          expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n          rootCursor.descend()\n          const parentNextSibling = createNode()\n          const parentNextSiblingResult = rootCursor.advance(parentNextSibling)\n          expect(decodeInsertionPoint(parentNextSiblingResult)).toEqual({\n            type: 'appendChild',\n            parent: rootResult.nodeId,\n          })\n\n          // Create a new InsertionCursor that inserts into the root node's child list.\n          const cursor = createChildInsertionCursor(rootResult.nodeId, parentNextSiblingResult.nodeId, nodeIds)\n\n          // Create the parent node using the new InsertionCursor, inserting it as the first\n          // child of the root node.\n          const parent = createNode()\n          const parentResult = cursor.advance(parent)\n          expect(decodeInsertionPoint(parentResult)).toEqual({\n            type: 'insertBefore',\n            nextSibling: parentNextSiblingResult.nodeId,\n          })\n\n          cursor.descend() // Descend into the parent node's child list.\n          // Do nothing, simulating an empty subtree.\n          cursor.ascend() // Ascend out of the parent node's child list.\n\n          // We should use an InsertAfterPreviousInsertionPoint, just as if descend() and\n          // ascend() had not been called, because the new node is a sibling of the previous\n          // node, `parent`.\n          const parentSibling = createNode()\n          const parentSiblingResult = cursor.advance(parentSibling)\n          expect(decodeInsertionPoint(parentSiblingResult)).toEqual({ type: 'after', previous: parentResult.nodeId })\n        })\n      })\n    })\n\n    it('has no effect if called at the root level', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      cursor.ascend() // Should have no effect.\n\n      // When we advance, the result should be the same as if ascend() was never called.\n      const root = createNode()\n      const result = cursor.advance(root)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'root' })\n    })\n\n    it('has no effect if called when within the initial child list of a child insertion cursor', () => {\n      const rootCursor = createRootInsertionCursor(nodeIds)\n      const root = createNode()\n      const rootResult = rootCursor.advance(root)\n      expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n      const cursor = createChildInsertionCursor(rootResult.nodeId, undefined, nodeIds)\n      cursor.ascend() // Should have no effect.\n\n      // When we advance, the result should be the same as if ascend() was never called.\n      const child = createNode()\n      const result = cursor.advance(child)\n      expect(decodeInsertionPoint(result)).toEqual({ type: 'appendChild', parent: rootResult.nodeId })\n    })\n\n    it('has no effect if called without a matching descend', () => {\n      const cursor = createRootInsertionCursor(nodeIds)\n      const root = createNode()\n      const rootResult = cursor.advance(root)\n      expect(decodeInsertionPoint(rootResult)).toEqual({ type: 'root' })\n\n      cursor.descend() // Descend into the root node's child list.\n      cursor.ascend() // Ascend back to the root level.\n      cursor.ascend() // Should have no effect.\n      cursor.ascend() // Should have no effect.\n\n      // We should insert this node as a sibling of the root, just as if ascend() had only\n      // been called once.\n      const rootSibling = createNode()\n      const rootSiblingResult = cursor.advance(rootSibling)\n      expect(decodeInsertionPoint(rootSiblingResult)).toEqual({ type: 'after', previous: rootResult.nodeId })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/insertionCursor.ts",
    "content": "import type { InsertionPoint } from '../../../types'\nimport type { NodeId, NodeIds } from '../itemIds'\n\n/**\n * InsertionCursor tracks the point at which the next node will be inserted during\n * Change-style DOM serialization.\n *\n * When a new node is added to the document, we use an InsertionPoint to encode its\n * position. There are often multiple equally-valid ways to express the same insertion\n * point; we generally want to favor encodings that use as few characters as possible (to\n * reduce uncompressed size) and that are as repetitive as possible (to reduce compressed\n * size). InsertionCursor's purpose is to heuristically pick an efficient encoding based\n * on the nodes we've recently serialized, while doing as little work as possible. The\n * results are not optimal, but should be close to it in most situations.\n *\n * At the beginning of the serialization process, use a factory function like\n * createRootInsertionCursor() to create a new cursor with an appropriate initial\n * position.\n *\n * When visiting a node, the expected usage pattern is as follows:\n * 1. Call advance() to get a node id and insertion point for the node.\n * 2. Serialize the node.\n * 3. If the node has no children, we're done; continue to the node's next\n * sibling and apply this algorithm again.\n * 4. Otherwise, call descend() to move the cursor into the node's child list.\n * 5. Recursively apply this algorithm.\n * 6. Call ascend() to move the cursor out of the node's child list. We're done;\n * continue to the node's next sibling and apply this algorithm again.\n */\nexport interface InsertionCursor {\n  /**\n   * Given the node id for a new node, returns the InsertionPoint for that node.\n   * Updates the cursor to point to the new node's next sibling.\n   */\n  advance(node: Node): { nodeId: NodeId; insertionPoint: InsertionPoint }\n\n  /**\n   * Ascends out of the current child list and updates the cursor to point to the parent\n   * node's next sibling.\n   */\n  ascend(): void\n\n  /**\n   * Descends into the child list of the last node we inserted and updates the cursor to\n   * point to the node's first child.\n   */\n  descend(): void\n}\n\n/** Returns an InsertionCursor which starts positioned at the root of the document. */\nexport function createRootInsertionCursor(nodeIds: NodeIds): InsertionCursor {\n  return createInsertionCursor(undefined, undefined, nodeIds)\n}\n\n/**\n * Returns an InsertionCursor which starts positioned in the child list of the given\n * parent node. If a next sibling is provided, the cursor points to the position\n * immediately before the next sibling; otherwise, the cursor points to the end of the\n * child list.\n */\nexport function createChildInsertionCursor(\n  parentId: NodeId,\n  nextSiblingId: NodeId | undefined,\n  nodeIds: NodeIds\n): InsertionCursor {\n  return createInsertionCursor(parentId, nextSiblingId, nodeIds)\n}\n\nfunction createInsertionCursor(\n  parentId: NodeId | undefined,\n  nextSiblingId: NodeId | undefined,\n  nodeIds: NodeIds\n): InsertionCursor {\n  interface ChildListCursor {\n    container: ChildListCursor | undefined\n    parentId: NodeId | undefined\n    previousSiblingId: NodeId | undefined\n    nextSiblingId: NodeId | undefined\n  }\n\n  let cursor: ChildListCursor = {\n    container: undefined,\n    parentId,\n    previousSiblingId: undefined,\n    nextSiblingId,\n  }\n\n  const computeInsertionPoint = (nodeId: NodeId): InsertionPoint => {\n    if (cursor.previousSiblingId === nodeId - 1) {\n      // Use an AppendAfterPreviousInsertionPoint. (i.e., 0)\n      return 0\n    }\n    if (cursor.nextSiblingId !== undefined) {\n      // Use an InsertBeforeInsertionPoint. We identify the next sibling using a\n      // negative integer indicating the difference between the new node's id and its next\n      // sibling's id.\n      return cursor.nextSiblingId - nodeId\n    }\n    if (cursor.parentId !== undefined) {\n      // Use an AppendChildInsertionPoint. We identify the parent node using a positive\n      // integer indicating the difference between the new node's id and its parent's id.\n      return nodeId - cursor.parentId\n    }\n    // There's no parent. Use a RootInsertionPoint. (i.e., null)\n    return null\n  }\n\n  return {\n    advance(node: Node): { nodeId: NodeId; insertionPoint: InsertionPoint } {\n      const nodeId = nodeIds.getOrInsert(node)\n      const insertionPoint = computeInsertionPoint(nodeId)\n      cursor.previousSiblingId = nodeId\n      return { nodeId, insertionPoint }\n    },\n    ascend(): void {\n      if (cursor.container) {\n        cursor = cursor.container\n      }\n    },\n    descend(): void {\n      if (cursor.previousSiblingId !== undefined) {\n        cursor = {\n          container: cursor,\n          parentId: cursor.previousSiblingId,\n          previousSiblingId: undefined,\n          nextSiblingId: undefined,\n        }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serialization.types.ts",
    "content": "import type { NodePrivacyLevel } from '@datadog/browser-rum-core'\n\n// Those values are the only one that can be used when inheriting privacy levels from parent to\n// children during serialization, since HIDDEN and IGNORE shouldn't serialize their children. This\n// ensures that no children are serialized when they shouldn't.\nexport type ParentNodePrivacyLevel =\n  | typeof NodePrivacyLevel.ALLOW\n  | typeof NodePrivacyLevel.MASK\n  | typeof NodePrivacyLevel.MASK_USER_INPUT\n  | typeof NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED\n\n/**\n * Virtual attributes. These attributes appear in the serialized attribute map of\n * elements, but they're not actually derived from the DOM; they're used to represent\n * metadata about the element they're attached to.\n */\nexport interface VirtualAttributes {\n  /**\n   * For <style> and <link> elements, the rules in the element's stylesheet, extracted\n   * from the CSSOM.\n   */\n  _cssText?: string\n\n  /** For <audio> and <video> elements, the playback state of the element's media. */\n  rr_mediaState?: 'paused' | 'played'\n\n  /** For elements which are scroll containers, the element's X scroll position, if non-zero. */\n  rr_scrollLeft?: number\n\n  /** For elements which are scroll containers, the element's Y scroll position, if non-zero. */\n  rr_scrollTop?: number\n\n  /** For HIDDEN elements, the width of the element's bounding client rect. */\n  rr_width?: string\n\n  /** For HIDDEN elements, the height of the element's bounding client rect. */\n  rr_height?: string\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializationStats.spec.ts",
    "content": "import { aggregateSerializationStats, createSerializationStats, updateSerializationStats } from './serializationStats'\n\ndescribe('serializationStats', () => {\n  describe('stats for _cssText', () => {\n    it('can be updated', () => {\n      const stats = createSerializationStats()\n\n      updateSerializationStats(stats, 'cssText', 'div { color: blue; }'.length)\n      expect(stats.cssText.count).toBe(1)\n      expect(stats.cssText.max).toBe(20)\n      expect(stats.cssText.sum).toBe(20)\n\n      updateSerializationStats(stats, 'cssText', 'span { background-color: red; }'.length)\n      expect(stats.cssText.count).toBe(2)\n      expect(stats.cssText.max).toBe(31)\n      expect(stats.cssText.sum).toBe(51)\n    })\n  })\n\n  describe('stats for serialization duration', () => {\n    it('can be updated', () => {\n      const stats = createSerializationStats()\n\n      updateSerializationStats(stats, 'serializationDuration', 30)\n      expect(stats.serializationDuration.count).toBe(1)\n      expect(stats.serializationDuration.max).toBe(30)\n      expect(stats.serializationDuration.sum).toBe(30)\n\n      updateSerializationStats(stats, 'serializationDuration', 60)\n      expect(stats.serializationDuration.count).toBe(2)\n      expect(stats.serializationDuration.max).toBe(60)\n      expect(stats.serializationDuration.sum).toBe(90)\n    })\n  })\n\n  it('can be aggregated', () => {\n    const aggregateStats = createSerializationStats()\n\n    const stats1 = createSerializationStats()\n    updateSerializationStats(stats1, 'cssText', 'div { color: blue; }'.length)\n    updateSerializationStats(stats1, 'serializationDuration', 16)\n    updateSerializationStats(stats1, 'cssText', 'span { background-color: red; }'.length)\n    updateSerializationStats(stats1, 'serializationDuration', 32)\n    aggregateSerializationStats(aggregateStats, stats1)\n\n    const stats2 = createSerializationStats()\n    updateSerializationStats(stats2, 'cssText', 'p { width: 100%; }'.length)\n    updateSerializationStats(stats2, 'serializationDuration', 18)\n    updateSerializationStats(stats2, 'serializationDuration', 9)\n    aggregateSerializationStats(aggregateStats, stats2)\n\n    expect(aggregateStats.cssText.count).toBe(3)\n    expect(aggregateStats.cssText.max).toBe(31)\n    expect(aggregateStats.cssText.sum).toBe(69)\n    expect(aggregateStats.serializationDuration.count).toBe(4)\n    expect(aggregateStats.serializationDuration.max).toBe(32)\n    expect(aggregateStats.serializationDuration.sum).toBe(75)\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializationStats.ts",
    "content": "export interface SerializationMetric {\n  count: number\n  max: number\n  sum: number\n}\n\nexport interface SerializationStats {\n  cssText: SerializationMetric\n  serializationDuration: SerializationMetric\n}\n\nexport function createSerializationStats(): SerializationStats {\n  return {\n    cssText: {\n      count: 0,\n      max: 0,\n      sum: 0,\n    },\n    serializationDuration: {\n      count: 0,\n      max: 0,\n      sum: 0,\n    },\n  }\n}\n\nexport function updateSerializationStats(\n  stats: SerializationStats,\n  metric: keyof SerializationStats,\n  value: number\n): void {\n  stats[metric].count += 1\n  stats[metric].max = Math.max(stats[metric].max, value)\n  stats[metric].sum += value\n}\n\nexport function aggregateSerializationStats(aggregateStats: SerializationStats, stats: SerializationStats) {\n  for (const metric of ['cssText', 'serializationDuration'] as const) {\n    aggregateStats[metric].count += stats[metric].count\n    aggregateStats[metric].max = Math.max(aggregateStats[metric].max, stats[metric].max)\n    aggregateStats[metric].sum += stats[metric].sum\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializationTransaction.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport { elapsed, timeStampNow } from '@datadog/browser-core'\n\nimport { ChangeType, RecordType, SnapshotFormat } from '../../../types'\nimport type {\n  AddCDataSectionNodeChange,\n  AddDocTypeNodeChange,\n  AddDocumentFragmentNodeChange,\n  AddDocumentNodeChange,\n  AddElementNodeChange,\n  AddNodeChange,\n  AddShadowRootNodeChange,\n  AddTextNodeChange,\n  AttachedStyleSheetsChange,\n  AttributeChange,\n  BrowserRecord,\n  InsertionPoint,\n  MediaInteractionType,\n  StyleSheetMediaList,\n  StyleSheetRules,\n} from '../../../types'\nimport type { NodeId, StyleSheetId } from '../itemIds'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { SerializationStats } from './serializationStats'\nimport { createSerializationStats, updateSerializationStats } from './serializationStats'\nimport { createChangeEncoder } from './changeEncoder'\n\nexport type SerializationTransactionCallback = (transaction: SerializationTransaction) => void\n\nexport const enum SerializationKind {\n  INITIAL_FULL_SNAPSHOT,\n  SUBSEQUENT_FULL_SNAPSHOT,\n  INCREMENTAL_SNAPSHOT,\n}\n\n/**\n * A serialization transaction is used to build and emit a sequence of session replay\n * records containing a serialized snapshot of the DOM.\n */\nexport interface SerializationTransaction {\n  /** Add a record to the transaction. It will be emitted when the transaction ends. */\n  add(record: BrowserRecord): void\n\n  /**\n   * Add a metric to the transaction's statistics. The aggregated statistics will be\n   * emitted when the transaction ends.\n   */\n  addMetric(metric: keyof SerializationStats, value: number): void\n\n  /**\n   * Assign and return an id to the given node. If the node has previously been assigned\n   * an id, the existing id will be reused.\n   */\n  assignId(node: Node): NodeId\n\n  /** The kind of serialization being performed in this transaction. */\n  kind: SerializationKind\n\n  /**\n   * A set used to track nodes which have been serialized in the current transaction. If\n   * undefined, this feature is disabled; this is the default state in new transactions\n   * for performance reasons. Set the property to a non-undefined value if you need this\n   * capability.\n   */\n  serializedNodeIds?: Set<NodeId>\n\n  /** The recording scope in which this transaction is occurring. */\n  scope: RecordingScope\n}\n\n/**\n * Perform serialization within a transaction. At the end of the transaction, the\n * generated records and statistics will be emitted.\n */\nexport function serializeInTransaction(\n  kind: SerializationKind,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope,\n  serialize: SerializationTransactionCallback\n): void {\n  const records: BrowserRecord[] = []\n  const stats = createSerializationStats()\n\n  const transaction: SerializationTransaction = {\n    add(record: BrowserRecord): void {\n      records.push(record)\n    },\n    addMetric(metric: keyof SerializationStats, value: number): void {\n      updateSerializationStats(stats, metric, value)\n    },\n    assignId(node: Node): NodeId {\n      const id = scope.nodeIds.getOrInsert(node)\n      if (transaction.serializedNodeIds) {\n        transaction.serializedNodeIds.add(id)\n      }\n      return id\n    },\n    kind,\n    scope,\n  }\n\n  const start = timeStampNow()\n  serialize(transaction)\n  updateSerializationStats(stats, 'serializationDuration', elapsed(start, timeStampNow()))\n\n  for (const record of records) {\n    emitRecord(record)\n  }\n\n  emitStats(stats)\n}\n\ntype AddNodeParams<NodeChange extends AddNodeChange> = NodeChange extends [any, any, ...infer Params] ? Params : never\n\nexport type ChangeSerializationTransactionCallback = (transaction: ChangeSerializationTransaction) => void\n\n/**\n * ChangeSerializationTransaction is used to build and emit a BrowserChangeRecord\n * containing a serialized snapshot of the DOM. Unlike SerializationTransaction, it\n * doesn't support emitting arbitrary BrowserRecords; instead, the builder methods it\n * exposes are used to construct a single BrowserChangeRecord which is emitted at the end\n * of the transaction.\n */\nexport interface ChangeSerializationTransaction {\n  /**\n   * Add a metric to the transaction's statistics. The aggregated statistics will be\n   * emitted when the transaction ends.\n   */\n  addMetric(metric: keyof SerializationStats, value: number): void\n\n  /** Add a node to the document at the given insertion point. */\n  addNode(pos: InsertionPoint, nodeName: '#cdata-section', ...params: AddNodeParams<AddCDataSectionNodeChange>): void\n  addNode(pos: InsertionPoint, nodeName: '#doctype', ...params: AddNodeParams<AddDocTypeNodeChange>): void\n  addNode(pos: InsertionPoint, nodeName: '#document', ...params: AddNodeParams<AddDocumentNodeChange>): void\n  addNode(\n    pos: InsertionPoint,\n    nodeName: '#document-fragment',\n    ...params: AddNodeParams<AddDocumentFragmentNodeChange>\n  ): void\n  addNode(pos: InsertionPoint, nodeName: '#shadow-root', ...params: AddNodeParams<AddShadowRootNodeChange>): void\n  addNode(pos: InsertionPoint, nodeName: '#text', ...params: AddNodeParams<AddTextNodeChange>): void\n  addNode(\n    pos: InsertionPoint,\n    nodeName: Exclude<string, `#${string}`>,\n    ...params: AddNodeParams<AddElementNodeChange>\n  ): void\n  addNode(pos: InsertionPoint, nodeName: string, ...params: AddNodeParams<AddNodeChange>): void\n\n  /** Add a stylesheet to the document. */\n  addStyleSheet(rules: StyleSheetRules, mediaList?: StyleSheetMediaList, disabled?: boolean): void\n\n  /**\n   * Attach one or more stylesheets to a <link>, <style>, #document, #document-fragment,\n   * or #shadow-root node.\n   */\n  attachStyleSheets(nodeId: NodeId, sheetIds: StyleSheetId[]): void\n\n  /** Remove a node from the document. */\n  removeNode(nodeId: NodeId): void\n\n  /** Set a node's attributes to the given values. */\n  setAttributes(change: AttributeChange): void\n\n  /** Set the media playback state of an <audio> or <video> element. */\n  setMediaPlaybackState(nodeId: NodeId, state: MediaInteractionType): void\n\n  /** Set the given node's scroll position in CSS pixels. */\n  setScrollPosition(nodeId: NodeId, x: number, y: number): void\n\n  /** Set the given node's size in CSS pixels. */\n  setSize(nodeId: NodeId, width: number, height: number): void\n\n  /** Set the given node's text content. */\n  setText(nodeId: NodeId, content: string): void\n\n  /** The kind of serialization being performed in this transaction. */\n  kind: SerializationKind\n\n  /** The recording scope in which this transaction is occurring. */\n  scope: RecordingScope\n}\n\nexport function serializeChangesInTransaction(\n  kind: SerializationKind,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope,\n  timestamp: TimeStamp,\n  serialize: ChangeSerializationTransactionCallback\n): void {\n  const encoder = createChangeEncoder(scope.stringIds)\n  const stats = createSerializationStats()\n\n  const transaction: ChangeSerializationTransaction = {\n    addMetric(metric: keyof SerializationStats, value: number): void {\n      updateSerializationStats(stats, metric, value)\n    },\n    addNode(...change): void {\n      encoder.add(ChangeType.AddNode, change as AddNodeChange)\n    },\n    addStyleSheet(rules: StyleSheetRules, mediaList?: StyleSheetMediaList, disabled?: boolean): void {\n      if (disabled) {\n        encoder.add(ChangeType.AddStyleSheet, [rules, mediaList || [], disabled])\n      } else if (mediaList) {\n        encoder.add(ChangeType.AddStyleSheet, [rules, mediaList])\n      } else {\n        encoder.add(ChangeType.AddStyleSheet, [rules])\n      }\n    },\n    attachStyleSheets(nodeId: NodeId, sheetIds: StyleSheetId[]): void {\n      const change: AttachedStyleSheetsChange = [nodeId]\n      for (const sheetId of sheetIds) {\n        change.push(sheetId)\n      }\n      encoder.add(ChangeType.AttachedStyleSheets, change)\n    },\n    removeNode(nodeId: NodeId): void {\n      encoder.add(ChangeType.RemoveNode, nodeId)\n    },\n    setAttributes(change: AttributeChange): void {\n      encoder.add(ChangeType.Attribute, change)\n    },\n    setMediaPlaybackState(nodeId: NodeId, state: MediaInteractionType): void {\n      encoder.add(ChangeType.MediaPlaybackState, [nodeId, state])\n    },\n    setScrollPosition(nodeId: NodeId, x: number, y: number): void {\n      encoder.add(ChangeType.ScrollPosition, [nodeId, x, y])\n    },\n    setSize(nodeId: NodeId, width: number, height: number): void {\n      encoder.add(ChangeType.Size, [nodeId, width, height])\n    },\n    setText(nodeId: NodeId, content: string): void {\n      encoder.add(ChangeType.Text, [nodeId, content])\n    },\n    kind,\n    scope,\n  }\n\n  const start = timeStampNow()\n  serialize(transaction)\n  updateSerializationStats(stats, 'serializationDuration', elapsed(start, timeStampNow()))\n\n  const changes = encoder.flush()\n  if (changes.length > 0) {\n    if (kind === SerializationKind.INITIAL_FULL_SNAPSHOT || kind === SerializationKind.SUBSEQUENT_FULL_SNAPSHOT) {\n      emitRecord({\n        data: changes,\n        format: SnapshotFormat.Change,\n        type: RecordType.FullSnapshot,\n        timestamp,\n      })\n    } else {\n      emitRecord({\n        data: changes,\n        type: RecordType.Change,\n        timestamp,\n      })\n    }\n  }\n\n  emitStats(stats)\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializationUtils.spec.ts",
    "content": "import { NodePrivacyLevel } from '@datadog/browser-rum-core'\nimport { getElementInputValue, switchToAbsoluteUrl } from './serializationUtils'\n\ndescribe('getElementInputValue', () => {\n  it('returns \"undefined\" for a non-input element', () => {\n    expect(getElementInputValue(document.createElement('div'), NodePrivacyLevel.ALLOW)).toBeUndefined()\n  })\n\n  it('returns the value of a <input>', () => {\n    const input = document.createElement('input')\n    input.value = 'foo'\n    expect(getElementInputValue(input, NodePrivacyLevel.ALLOW)).toBe('foo')\n  })\n\n  describe('when asked to return a masked value', () => {\n    it('does not return the value of a <input type=\"password\">', () => {\n      const input = document.createElement('input')\n      input.type = 'password'\n      input.value = 'foo'\n      // Serializing a `Hidden` element (which input[type=password] is by current spec) will only\n      // return special allow listed attributes and `getElementInputValue` is never called.\n      // But to be paranoid, we defensively check the case if it was called\n      expect(getElementInputValue(input, NodePrivacyLevel.MASK)).toBe('***')\n    })\n\n    it('does not return the value of a <input> with a IGNORED privacy mode', () => {\n      const input = document.createElement('input')\n      input.value = 'foo'\n      expect(getElementInputValue(input, NodePrivacyLevel.IGNORE)).toBe('***')\n    })\n\n    it('never returns the value of a <select>', () => {\n      const select = document.createElement('select')\n      const option = document.createElement('option')\n      option.value = 'foo'\n      select.appendChild(option)\n      select.value = 'foo'\n      expect(getElementInputValue(option, NodePrivacyLevel.MASK)).toBeUndefined()\n    })\n\n    it('always returns the value of a <input type=\"button\">', () => {\n      const input = document.createElement('input')\n      input.value = 'foo'\n      input.type = 'button'\n      expect(getElementInputValue(input, NodePrivacyLevel.MASK)).toBe('foo')\n    })\n\n    it('always returns the value of a <input type=\"submit\">', () => {\n      const input = document.createElement('input')\n      input.value = 'foo'\n      input.type = 'submit'\n      expect(getElementInputValue(input, NodePrivacyLevel.MASK)).toBe('foo')\n    })\n\n    it('always returns the value of a <input type=\"reset\">', () => {\n      const input = document.createElement('input')\n      input.value = 'foo'\n      input.type = 'reset'\n      expect(getElementInputValue(input, NodePrivacyLevel.MASK)).toBe('foo')\n    })\n  })\n})\n\ndescribe('switchToAbsoluteUrl', () => {\n  const cssHref = 'https://site.web/app-name/static/assets/resource.min.css'\n  const resolvedUrl = 'https://site.web/app-name/static/assets/fonts/fontawesome-webfont.eot'\n\n  describe('convert relative url to absolute', () => {\n    it('should replace url when wrapped in single quote', () => {\n      const cssText = \"{ font-family: FontAwesome; src: url('./fonts/fontawesome-webfont.eot'); }\"\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(`{ font-family: FontAwesome; src: url('${resolvedUrl}'); }`)\n    })\n    it('should replace url when wrapped in double quote', () => {\n      const cssText = '{ font-family: FontAwesome; src: url(\"./fonts/fontawesome-webfont.eot\"); }'\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(`{ font-family: FontAwesome; src: url(\"${resolvedUrl}\"); }`)\n    })\n    it('should replace url when not in any quote', () => {\n      const cssText = '{ font-family: FontAwesome; src: url(./fonts/fontawesome-webfont.eot); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(`{ font-family: FontAwesome; src: url(${resolvedUrl}); }`)\n    })\n    it('should replace url when url is relative', () => {\n      const cssText = '{ font-family: FontAwesome; src: url(fonts/fontawesome-webfont.eot); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(`{ font-family: FontAwesome; src: url(${resolvedUrl}); }`)\n    })\n    it('should replace url when url is at parent level', () => {\n      const cssText = \"{ font-family: FontAwesome; src: url('../fonts/fontawesome-webfont.eot'); }\"\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(\n        \"{ font-family: FontAwesome; src: url('https://site.web/app-name/static/fonts/fontawesome-webfont.eot'); }\"\n      )\n    })\n    it('should replace multiple urls at the same time', () => {\n      const cssText =\n        '{ background-image: url(../images/pic.png); src: url(\"fonts/fantasticfont.woff\"); content: url(\"./icons/icon.jpg\");}'\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(\n        '{ background-image: url(https://site.web/app-name/static/images/pic.png); src: url(\"https://site.web/app-name/static/assets/fonts/fantasticfont.woff\"); content: url(\"https://site.web/app-name/static/assets/icons/icon.jpg\");}'\n      )\n    })\n  })\n\n  describe('keep urls in css text unchanged', () => {\n    it('should not replace url if baseUrl is null', () => {\n      const cssText = '{ font-family: FontAwesome; src: url(./fonts/fontawesome-webfont.eot); }'\n\n      expect(switchToAbsoluteUrl(cssText, null)).toEqual(cssText)\n    })\n    it('should not replace url if it is empty', () => {\n      const cssText = '{ font-family: FontAwesome; src: url(); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n    it('should not replace url if already absolute', () => {\n      const cssText =\n        '{ font-family: FontAwesome; src: url(https://site.web/app-name/static/assets/fonts/fontawesome-webfont.eot); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n    it('should not replace url if it starts with //', () => {\n      const cssText =\n        '{ font-family: FontAwesome; src: url(//site.web/app-name/static/assets/fonts/fontawesome-webfont.eot); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n\n    it('should not replace url if data uri: lower case', () => {\n      const cssText =\n        '{ font-family: FontAwesome; src: url(data:image/png;base64,iVBORNSUhEUgAAVR42mP8z/C/HgwJ/lK3Q6wAkJggg==); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n\n    it('should not replace url if data uri contains escaped quotes', () => {\n      const cssText = '{ src: url(\"data:image/svg+xml;utf8,<svg xmlns=\\\\\"http://www.w3.org/2000/svg\\\\\"></svg>\"); }'\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n\n    it('should not replace url if data uri contains closing paren', () => {\n      const cssText =\n        '{ src: url(\"data:image/svg+xml;utf8,<svg xmlns=\\\\\"http://www.w3.org/2000/svg\\\\\" style=\\\\\"color: rgb(0, 0, 0)\\\\\"></svg>\"); }'\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n\n    it('should not replace url if data uri: not lower case', () => {\n      const cssText =\n        '{ font-family: FontAwesome; src: url(DaTa:image/png;base64,iVBORNSUhEUgAAVR42mP8z/C/HgwJ/lK3Q6wAkJggg==); }'\n\n      expect(switchToAbsoluteUrl(cssText, cssHref)).toEqual(cssText)\n    })\n\n    it('should not replace url if error is thrown when building absolute url', () => {\n      const cssText =\n        '{ font-family: FontAwesome; src: url(https://site.web/app-name/static/assets/fonts/fontawesome-webfont.eot); }'\n      expect(switchToAbsoluteUrl(cssText, 'hello-world')).toEqual(cssText)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializationUtils.ts",
    "content": "import { buildUrl } from '@datadog/browser-core'\nimport { CENSORED_STRING_MARK, shouldMaskNode } from '@datadog/browser-rum-core'\nimport type { NodePrivacyLevel } from '@datadog/browser-rum-core'\n\n/**\n * Get the element \"value\" to be serialized as an attribute or an input update record. It respects\n * the input privacy mode of the element.\n * PERFROMANCE OPTIMIZATION: Assumes that privacy level `HIDDEN` is never encountered because of earlier checks.\n */\nexport function getElementInputValue(element: Element, nodePrivacyLevel: NodePrivacyLevel) {\n  /*\n   BROWSER SPEC NOTE: <input>, <select>\n   For some <input> elements, the `value` is an exceptional property/attribute that has the\n   value synced between el.value and el.getAttribute()\n   input[type=button,checkbox,hidden,image,radio,reset,submit]\n   */\n  const tagName = element.tagName\n  const value = (element as HTMLInputElement | HTMLTextAreaElement).value\n\n  if (shouldMaskNode(element, nodePrivacyLevel)) {\n    const type = (element as HTMLInputElement | HTMLTextAreaElement).type\n    if (tagName === 'INPUT' && (type === 'button' || type === 'submit' || type === 'reset')) {\n      // Overrule `MASK` privacy level for button-like element values, as they are used during replay\n      // to display their label. They can still be hidden via the \"hidden\" privacy attribute or class name.\n      return value\n    } else if (!value || tagName === 'OPTION') {\n      // <Option> value provides no benefit\n      return\n    }\n    return CENSORED_STRING_MARK\n  }\n\n  if (tagName === 'OPTION' || tagName === 'SELECT') {\n    return (element as HTMLOptionElement | HTMLSelectElement).value\n  }\n\n  if (tagName !== 'INPUT' && tagName !== 'TEXTAREA') {\n    return\n  }\n\n  return value\n}\n\nexport const URL_IN_CSS_REF = /url\\((?:(')([^']*)'|(\")([^\"]*)\"|([^)]*))\\)/gm\nexport const ABSOLUTE_URL = /^[A-Za-z]+:|^\\/\\//\nexport const DATA_URI = /^[\"']?data:.*,/i\n\nexport function switchToAbsoluteUrl(cssText: string, cssHref: string | null): string {\n  return cssText.replace(\n    URL_IN_CSS_REF,\n    (\n      matchingSubstring: string,\n      singleQuote: string | undefined,\n      urlWrappedInSingleQuotes: string | undefined,\n      doubleQuote: string | undefined,\n      urlWrappedInDoubleQuotes: string | undefined,\n      urlNotWrappedInQuotes: string | undefined\n    ) => {\n      const url = urlWrappedInSingleQuotes || urlWrappedInDoubleQuotes || urlNotWrappedInQuotes\n\n      if (!cssHref || !url || ABSOLUTE_URL.test(url) || DATA_URI.test(url)) {\n        return matchingSubstring\n      }\n\n      const quote = singleQuote || doubleQuote || ''\n      return `url(${quote}${makeUrlAbsolute(url, cssHref)}${quote})`\n    }\n  )\n}\n\nfunction makeUrlAbsolute(url: string, baseUrl: string): string {\n  try {\n    return buildUrl(url, baseUrl).href\n  } catch {\n    return url\n  }\n}\n\nconst TAG_NAME_REGEX = /[^a-z1-6-_]/\nexport function getValidTagName(tagName: string): string {\n  const processedTagName = tagName.toLowerCase().trim()\n\n  if (TAG_NAME_REGEX.test(processedTagName)) {\n    // if the tag name is odd and we cannot extract\n    // anything from the string, then we return a\n    // generic div\n    return 'div'\n  }\n\n  return processedTagName\n}\n\n/**\n * Returns the tag name of the given element, normalized to ensure a consistent lowercase\n * representation regardless of whether the element is HTML, XHTML, or SVG.\n */\nexport function normalizedTagName(element: Element): string {\n  return element.tagName.toLowerCase()\n}\n\nexport function censoredImageForSize(width: number, height: number) {\n  return `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${width}' height='${height}' style='background-color:silver'%3E%3C/svg%3E`\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeAttribute.spec.ts",
    "content": "import type { RumConfiguration } from '@datadog/browser-rum-core'\nimport {\n  STABLE_ATTRIBUTES,\n  DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE,\n  NodePrivacyLevel,\n  PRIVACY_ATTR_NAME,\n} from '@datadog/browser-rum-core'\nimport { serializeAttribute, MAX_ATTRIBUTE_VALUE_CHAR_LENGTH } from './serializeAttribute'\n\nconst DEFAULT_CONFIGURATION = {} as RumConfiguration\n\ndescribe('serializeAttribute', () => {\n  it('truncates \"data:\" URIs after long string length', () => {\n    const node = document.createElement('p')\n\n    const longString = new Array(MAX_ATTRIBUTE_VALUE_CHAR_LENGTH - 5).join('a')\n    const maxAttributeValue = `data:,${longString}`\n    const exceededAttributeValue = `data:,${longString}aa`\n    const dataUrlAttributeValue = `data:,${longString}a`\n    const truncatedValue = 'data:,[...]'\n    const ignoredAttributeValue = `foos:,${longString}`\n\n    node.setAttribute('test-okay', maxAttributeValue)\n    node.setAttribute('test-truncate', exceededAttributeValue)\n    node.setAttribute('test-truncate', dataUrlAttributeValue)\n    node.setAttribute('test-ignored', ignoredAttributeValue)\n\n    expect(serializeAttribute(node, NodePrivacyLevel.ALLOW, 'test-okay', DEFAULT_CONFIGURATION)).toBe(maxAttributeValue)\n    expect(serializeAttribute(node, NodePrivacyLevel.MASK, 'test-okay', DEFAULT_CONFIGURATION)).toBe(maxAttributeValue)\n\n    expect(serializeAttribute(node, NodePrivacyLevel.MASK, 'test-ignored', DEFAULT_CONFIGURATION)).toBe(\n      ignoredAttributeValue\n    )\n\n    expect(serializeAttribute(node, NodePrivacyLevel.ALLOW, 'test-truncate', DEFAULT_CONFIGURATION)).toBe(\n      truncatedValue\n    )\n    expect(serializeAttribute(node, NodePrivacyLevel.MASK, 'test-truncate', DEFAULT_CONFIGURATION)).toBe(truncatedValue)\n    expect(serializeAttribute(node, NodePrivacyLevel.MASK, 'test-truncate', DEFAULT_CONFIGURATION)).toBe(truncatedValue)\n  })\n\n  it('does not mask the privacy attribute', () => {\n    const node = document.createElement('div')\n    node.setAttribute(PRIVACY_ATTR_NAME, NodePrivacyLevel.MASK)\n    expect(serializeAttribute(node, NodePrivacyLevel.MASK, PRIVACY_ATTR_NAME, DEFAULT_CONFIGURATION)).toBe('mask')\n  })\n\n  it('masks data attributes', () => {\n    const node = document.createElement('div')\n    node.setAttribute('data-foo', 'bar')\n    expect(serializeAttribute(node, NodePrivacyLevel.MASK, 'data-foo', DEFAULT_CONFIGURATION)).toBe('***')\n  })\n\n  describe('attributes used to generate CSS selectors', () => {\n    it('does not mask the default programmatic action name attributes', () => {\n      const node = document.createElement('div')\n      node.setAttribute(DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE, 'foo')\n      expect(\n        serializeAttribute(\n          node,\n          NodePrivacyLevel.MASK,\n          DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE,\n          DEFAULT_CONFIGURATION\n        )\n      ).toBe('foo')\n    })\n\n    it('does not mask the user-supplied programmatic action name attributes when it is a data attribute', () => {\n      const node = document.createElement('div')\n      node.setAttribute('data-my-custom-action-name', 'foo')\n      expect(\n        serializeAttribute(node, NodePrivacyLevel.MASK, 'data-my-custom-action-name', {\n          ...DEFAULT_CONFIGURATION,\n          actionNameAttribute: 'data-my-custom-action-name',\n        })\n      ).toBe('foo')\n    })\n\n    it('does not mask the user-supplied programmatic action name attributes when it not a data attribute', () => {\n      const node = document.createElement('div')\n      node.setAttribute('my-custom-action-name', 'foo')\n      expect(\n        serializeAttribute(node, NodePrivacyLevel.MASK, 'my-custom-action-name', {\n          ...DEFAULT_CONFIGURATION,\n          actionNameAttribute: 'my-custom-action-name',\n        })\n      ).toBe('foo')\n    })\n\n    it('does not mask other attributes used to generate CSS selectors', () => {\n      const node = document.createElement('div')\n      node.setAttribute(STABLE_ATTRIBUTES[0], 'foo')\n      expect(serializeAttribute(node, NodePrivacyLevel.MASK, STABLE_ATTRIBUTES[0], DEFAULT_CONFIGURATION)).toBe('foo')\n    })\n  })\n\n  describe('image masking', () => {\n    let image: Partial<Element> & { width: number; height: number; naturalWidth: number; naturalHeight: number }\n\n    beforeEach(() => {\n      image = {\n        width: 0,\n        height: 0,\n        naturalWidth: 0,\n        naturalHeight: 0,\n        tagName: 'IMG',\n        getAttribute() {\n          return 'http://foo.bar/image.png'\n        },\n        getBoundingClientRect() {\n          return { width: this.width, height: this.height } as DOMRect\n        },\n      }\n    })\n\n    it('should use an image with same natural dimension than the original one', () => {\n      image.naturalWidth = 2000\n      image.naturalHeight = 1000\n      expect(serializeAttribute(image as Element, NodePrivacyLevel.MASK, 'src', DEFAULT_CONFIGURATION)).toBe(\n        \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2000' height='1000' style='background-color:silver'%3E%3C/svg%3E\"\n      )\n    })\n\n    it('should use an image with same rendering dimension than the original one', () => {\n      image.width = 200\n      image.height = 100\n      expect(serializeAttribute(image as Element, NodePrivacyLevel.MASK, 'src', DEFAULT_CONFIGURATION)).toBe(\n        \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='100' style='background-color:silver'%3E%3C/svg%3E\"\n      )\n    })\n\n    it(\"should use the censored image when original image size can't be computed\", () => {\n      expect(serializeAttribute(image as Element, NodePrivacyLevel.MASK, 'src', DEFAULT_CONFIGURATION)).toBe(\n        'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='\n      )\n    })\n  })\n\n  describe('iframe srcdoc masking', () => {\n    it('should mask the srcdoc when privacy override set to mask', () => {\n      const node = document.createElement('iframe')\n      node.srcdoc = '<html><body>data-foo</body></html>\">'\n      node.setAttribute(PRIVACY_ATTR_NAME, 'mask')\n      expect(serializeAttribute(node, NodePrivacyLevel.MASK, 'srcdoc', DEFAULT_CONFIGURATION)).toBe('***')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeAttribute.ts",
    "content": "import {\n  NodePrivacyLevel,\n  CENSORED_STRING_MARK,\n  CENSORED_IMG_MARK,\n  sanitizeIfLongDataUrl,\n  shouldMaskAttribute,\n} from '@datadog/browser-rum-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { censoredImageForSize } from './serializationUtils'\n\n// TODO: temporarily bump the Session Replay limit to 1Mb for dataUrls\n// This limit should be removed after [PANA-2843] is implemented\nexport const MAX_ATTRIBUTE_VALUE_CHAR_LENGTH = 1_000_000\n\nexport function serializeAttribute(\n  element: Element,\n  nodePrivacyLevel: NodePrivacyLevel,\n  attributeName: string,\n  configuration: RumConfiguration\n): string | null {\n  if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n    // dup condition for direct access case\n    return null\n  }\n\n  const attributeValue = element.getAttribute(attributeName)\n  const tagName = element.tagName\n  if (shouldMaskAttribute(tagName, attributeName, attributeValue, nodePrivacyLevel, configuration)) {\n    // mask image URLs\n    if (tagName === 'IMG') {\n      // generate image with similar dimension than the original to have the same rendering behaviour\n      const image = element as HTMLImageElement\n      if (image.naturalWidth > 0) {\n        return censoredImageForSize(image.naturalWidth, image.naturalHeight)\n      }\n      const { width, height } = element.getBoundingClientRect()\n      if (width > 0 || height > 0) {\n        return censoredImageForSize(width, height)\n      }\n      // if we can't get the image size, fallback to the censored image\n      return CENSORED_IMG_MARK\n    }\n    if (tagName === 'SOURCE') {\n      return CENSORED_IMG_MARK\n    }\n\n    return CENSORED_STRING_MARK\n  }\n\n  if (!attributeValue) {\n    return attributeValue\n  }\n\n  return sanitizeIfLongDataUrl(attributeValue, MAX_ATTRIBUTE_VALUE_CHAR_LENGTH)\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeAttributes.spec.ts",
    "content": "import { isSafari } from '@datadog/browser-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport {\n  CENSORED_IMG_MARK,\n  CENSORED_STRING_MARK,\n  NodePrivacyLevel,\n  PRIVACY_ATTR_NAME,\n  shouldMaskNode,\n  STABLE_ATTRIBUTES,\n} from '@datadog/browser-rum-core'\nimport { appendElement } from '@datadog/browser-rum-core/test'\nimport { createSerializationTransactionForTesting } from '../test/serialization.specHelper'\nimport type { ScrollPositions } from '../elementsScrollPositions'\nimport { getCssRulesString, serializeDOMAttributes, serializeVirtualAttributes } from './serializeAttributes'\nimport { SerializationKind, type SerializationTransaction } from './serializationTransaction'\nimport type { VirtualAttributes } from './serialization.types'\nimport type { SerializationMetric, SerializationStats } from './serializationStats'\nimport { createSerializationStats } from './serializationStats'\n\nconst CSS_FILE_URL = '/base/packages/rum/test/record/toto.css'\n\nconst PRIVACY_LEVELS = Object.keys({\n  [NodePrivacyLevel.ALLOW]: true,\n  [NodePrivacyLevel.HIDDEN]: true,\n  [NodePrivacyLevel.IGNORE]: true,\n  [NodePrivacyLevel.MASK]: true,\n  [NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED]: true,\n  [NodePrivacyLevel.MASK_USER_INPUT]: true,\n} satisfies Record<NodePrivacyLevel, true>) as NodePrivacyLevel[]\n\ndescribe('serializeDOMAttributes', () => {\n  let transaction: SerializationTransaction\n\n  beforeEach(() => {\n    transaction = createSerializationTransactionForTesting()\n  })\n\n  it('serializes attribute values', () => {\n    interface TestCase {\n      // A snippet of HTML containing an attribute we should serialize.\n      // For example: `<div attr=\"foo\">`\n      html: string\n\n      // By default, the attribute that should be serialized is determined automatically,\n      // but you can override the default behavior by specifying an attribute manually.\n      attrName?: string\n\n      // By default, the attribute value that should be serialized is determined automatically,\n      // but you can override the default behavior by specifying a value manually.\n      attrValue?: string\n\n      // The serialization behavior we expect. There are several options:\n      // - 'always-unmasked': We expect the value to be unmasked regardless of privacy\n      // level. For HIDDEN, we expect the value not to be serialized.\n      // - 'maskable': We expect the value to be masked or unmasked, depending on the\n      // privacy level. For HIDDEN, we expect the value not to be serialized.\n      // - 'maskable-form': Behaves like 'maskable' for truthy attribute values and like\n      // 'always-unmasked' for falsy ones. Used for most form elements.\n      // - 'maskable-form-boolean': The attribute as boolean true or false, depending on\n      // whether it's present, when unmasked. If it's masked, the attribute is not\n      // serialized at all. Used for boolean form element attributes like `<option selected>`.\n      // - 'maskable-image': Like 'maskable', except that we expect the masked\n      // representation to be a data URL image.\n      // TODO: Reduce the complexity here by aligning 'maskable-form' and\n      // 'maskable-form-boolean'.\n      expectedBehavior: 'always-unmasked' | 'maskable' | 'maskable-form' | 'maskable-form-boolean' | 'maskable-image'\n\n      // How to treat the IGNORE privacy level. The default is 'unmasked'.\n      // TODO: Eliminate this inconsistency by always masking for IGNORE.\n      ignoreBehavior?: 'masked' | 'unmasked'\n\n      // How to treat the MASK_UNLESS_ALLOWLISTED privacy level. The default is 'default'.\n      // TODO: Eliminate this inconsistency by fixing <input type=\"color\">, which behaves\n      // differently than any other kind of input.\n      maskUnlessAllowlistedBehavior?: 'default' | 'unmasked'\n    }\n\n    const testCases: TestCase[] = [\n      // Privacy attributes should always be unmasked.\n      { html: `<div ${PRIVACY_ATTR_NAME}=\"value\">`, expectedBehavior: 'always-unmasked' },\n\n      // Stable attributes should always be unmasked.\n      ...STABLE_ATTRIBUTES.map(\n        (attribute: string): TestCase => ({\n          html: `<div ${attribute}=\"value\">`,\n          expectedBehavior: 'always-unmasked',\n        })\n      ),\n\n      // Most data attributes should be maskable.\n      { html: '<div data-foo=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<div data-any-attribute=\"value\">', expectedBehavior: 'maskable' },\n\n      // Data attributes with no values should always be unmasked.\n      { html: '<div data-empty-attribute>', expectedBehavior: 'always-unmasked' },\n\n      // Attributes which are likely to contain human-readable text should be maskable.\n      { html: '<div title=\"value\">', expectedBehavior: 'maskable' },\n      {\n        html: '<img alt=\"value\">',\n        // TODO: This is a bug! This should just be 'maskable'.\n        expectedBehavior: 'maskable-image',\n      },\n      { html: '<div alt=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<input type=\"text\" placeholder=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<div placeholder=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<div aria-label=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<input name=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<div name=\"value\">', expectedBehavior: 'maskable' },\n\n      // Element/attribute combinations which may contain user-identifying ids and tokens\n      // should be maskable. The same attributes should always be unmasked in other\n      // contexts.\n      { html: '<a href=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<div href=\"value\">', expectedBehavior: 'always-unmasked' },\n      { html: '<iframe srcdoc=\"value\">', expectedBehavior: 'maskable' },\n      { html: '<div srcdoc=\"value\">', expectedBehavior: 'always-unmasked' },\n      { html: '<img src=\"value\">', expectedBehavior: 'maskable-image' },\n      { html: '<img srcset=\"value\">', expectedBehavior: 'maskable-image' },\n      { html: '<source src=\"value\">', expectedBehavior: 'maskable-image' },\n      { html: '<source srcset=\"value\">', expectedBehavior: 'maskable-image' },\n      { html: '<div src=\"value\">', expectedBehavior: 'always-unmasked' },\n      { html: '<div srcset=\"value\">', expectedBehavior: 'always-unmasked' },\n\n      // The value attributes of button-like form elements should always be unmasked.\n      { html: '<input type=\"button\" value=\"value\">', expectedBehavior: 'always-unmasked' },\n      { html: '<input type=\"reset\" value=\"value\">', expectedBehavior: 'always-unmasked' },\n      { html: '<input type=\"submit\" value=\"value\">', expectedBehavior: 'always-unmasked' },\n\n      // The value attributes of other form elements should be maskable.\n      { html: '<input type=\"checkbox\" value=\"value\">', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"checkbox\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      {\n        html: '<input type=\"color\" value=\"#e66465\">',\n        expectedBehavior: 'maskable',\n        ignoreBehavior: 'masked',\n        // TODO: This is almost certainly a bug; it's quite odd that only <input\n        // type=\"color\"> behaves this way. The intention was probably to make it behave\n        // like the maskable-form input elements, but the implementation was incomplete.\n        maskUnlessAllowlistedBehavior: 'unmasked',\n      },\n      {\n        html: '<input type=\"color\" value>',\n        attrValue: '#000000', // This is the value returned by HTMLInputElement#value for this test case.\n        expectedBehavior: 'maskable',\n        ignoreBehavior: 'masked',\n        maskUnlessAllowlistedBehavior: 'unmasked',\n      },\n      {\n        html: '<input type=\"date\" value=\"2018-06-12\">',\n        expectedBehavior: 'maskable',\n        ignoreBehavior: 'masked',\n      },\n      {\n        html: '<input type=\"date\" value>',\n        expectedBehavior: 'maskable-form',\n        ignoreBehavior: 'masked',\n      },\n      {\n        html: '<input type=\"datetime-local\" value=\"2018-06-12T19:30\">',\n        expectedBehavior: 'maskable',\n        ignoreBehavior: 'masked',\n      },\n      {\n        html: '<input type=\"datetime-local\" value>',\n        expectedBehavior: 'maskable-form',\n        ignoreBehavior: 'masked',\n      },\n      { html: '<input type=\"email\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"email\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      {\n        html: '<input type=\"file\" value=\"C:\\\\fakepath\\\\file.txt\">',\n        // TODO: This is a bug! It happens because HTMLInputElement#value is falsy until\n        // the user has actually selected a file, causing us to ignore the result of\n        // getElementInputValue() and fall back to the DOM attribute value.\n        expectedBehavior: 'always-unmasked',\n      },\n      {\n        html: '<input type=\"file\" value>',\n        expectedBehavior: 'maskable-form',\n      },\n      { html: '<input type=\"hidden\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"hidden\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"image\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"image\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"month\" value=\"2018-05\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"month\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"number\" value=\"42\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"number\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"password\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"password\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"radio\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"radio\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"range\" value=\"99\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      {\n        html: '<input type=\"range\" value>',\n        attrValue: '50', // This is the value returned by HTMLInputElement#value for this test case.\n        expectedBehavior: 'maskable',\n        ignoreBehavior: 'masked',\n      },\n      { html: '<input type=\"search\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"search\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"tel\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"tel\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"text\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"text\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"time\" value=\"13:30\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"time\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"url\" value=\"value\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"url\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n      { html: '<input type=\"week\" value=\"2017-W01\">', expectedBehavior: 'maskable', ignoreBehavior: 'masked' },\n      { html: '<input type=\"week\" value>', expectedBehavior: 'maskable-form', ignoreBehavior: 'masked' },\n\n      // Boolean form element attributes should be maskable, but with special behavior:\n      // when masked, the entire attribute should not be serialized.\n      {\n        html: '<option selected>',\n        expectedBehavior: 'maskable-form-boolean',\n        ignoreBehavior: 'masked',\n      },\n      {\n        html: '<input type=\"checkbox\" checked>',\n        expectedBehavior: 'maskable-form-boolean',\n        ignoreBehavior: 'masked',\n      },\n      {\n        html: '<input type=\"radio\" checked>',\n        expectedBehavior: 'maskable-form-boolean',\n        ignoreBehavior: 'masked',\n      },\n    ]\n\n    for (const testCase of testCases) {\n      const element = appendElement(testCase.html)\n      const attribute = getAttributeToSerialize(element, testCase.attrName)\n\n      // Remove the element from the document so that 'maskable-image' elements all have a zero\n      // size, giving all such attributes the same expected value.\n      element.remove()\n\n      for (const privacyLevel of PRIVACY_LEVELS) {\n        const attributes = serializeDOMAttributes(element, privacyLevel, transaction)\n        const actual = attributes[attribute.name] as boolean | string | undefined\n        const expected = expectedValueForPrivacyLevel(testCase, element, attribute, privacyLevel)\n        expect(actual).withContext(`${testCase.html} for ${privacyLevel}`).toEqual(expected)\n      }\n    }\n\n    function getAttributeToSerialize(\n      element: HTMLElement,\n      attrName: string | undefined\n    ): { name: string; value: string | undefined } {\n      if (attrName) {\n        // The attribute to serialize was explicitly specified.\n        return { name: attrName, value: element.getAttribute(attrName) || undefined }\n      }\n\n      // Infer the attribute to serialize. We use the first attribute that isn't 'type'.\n      for (let i = 0; i < element.attributes.length; i++) {\n        const attr = element.attributes.item(i)\n        if (attr && attr.name !== 'type') {\n          return attr\n        }\n      }\n\n      throw new Error(\"Couldn't determine test attribute\")\n    }\n\n    function expectedValueForPrivacyLevel(\n      testCase: TestCase,\n      element: Element,\n      attribute: { name: string; value: string | undefined },\n      privacyLevel: NodePrivacyLevel\n    ): boolean | string | undefined {\n      const unmaskedValue: boolean | string | undefined = testCase.attrValue ?? attribute.value\n\n      let maskedValue: boolean | string | undefined\n      if (testCase.expectedBehavior === 'maskable-form') {\n        maskedValue = !unmaskedValue ? unmaskedValue : CENSORED_STRING_MARK\n      } else if (testCase.expectedBehavior === 'maskable-form-boolean') {\n        maskedValue = undefined\n      } else if (testCase.expectedBehavior === 'maskable-image') {\n        maskedValue = CENSORED_IMG_MARK\n      } else {\n        maskedValue = CENSORED_STRING_MARK\n      }\n\n      if (testCase.expectedBehavior === 'always-unmasked') {\n        return privacyLevel === NodePrivacyLevel.HIDDEN ? undefined : unmaskedValue\n      }\n\n      switch (privacyLevel) {\n        case NodePrivacyLevel.ALLOW:\n          return unmaskedValue\n        case NodePrivacyLevel.HIDDEN:\n          return undefined\n        case NodePrivacyLevel.IGNORE:\n          return testCase.ignoreBehavior === 'masked' ? maskedValue : unmaskedValue\n        case NodePrivacyLevel.MASK:\n          return maskedValue\n        case NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED:\n          if (testCase.maskUnlessAllowlistedBehavior === 'unmasked') {\n            return unmaskedValue\n          }\n          return maskedValue\n        case NodePrivacyLevel.MASK_USER_INPUT:\n          return ['checked', 'selected', 'value'].includes(attribute.name) &&\n            shouldMaskNode(element, NodePrivacyLevel.MASK_USER_INPUT)\n            ? maskedValue\n            : unmaskedValue\n        default:\n          privacyLevel satisfies never\n          return undefined\n      }\n    }\n  })\n\n  it('normalizes tag names', () => {\n    // Create an <option> element in the SVG namespace. This makes it an XML element;\n    // among other things, this results in a lowercase Element#tagName.\n    const element = document.createElementNS('http://www.w3.org/2000/svg', 'option')\n    expect(element.tagName).toBe('option')\n\n    // Check that serializeDOMAttributes() still executes <option>-specific serialization\n    // behavior; it shouldn't behave differently because Element#tagName is lowercase.\n    ;(element as any).selected = true\n    const attributes = serializeDOMAttributes(element, NodePrivacyLevel.ALLOW, transaction)\n    expect(attributes['selected']).toBe('')\n  })\n})\n\ndescribe('serializeVirtualAttributes', () => {\n  let stats: SerializationStats\n  let transaction: SerializationTransaction\n\n  beforeEach(() => {\n    stats = createSerializationStats()\n    transaction = createSerializationTransactionForTesting({ stats })\n  })\n\n  function expectVirtualAttributes(\n    element: Element,\n    expectedWhenNotHidden: VirtualAttributes,\n    after?: (privacyLevel: NodePrivacyLevel) => void\n  ): void {\n    for (const privacyLevel of PRIVACY_LEVELS) {\n      const actual = serializeVirtualAttributes(element, privacyLevel, transaction)\n      const expected = privacyLevel === NodePrivacyLevel.HIDDEN ? {} : expectedWhenNotHidden\n      expect(actual).withContext(`${element.tagName} ${privacyLevel}`).toEqual(expected)\n      after?.(privacyLevel)\n    }\n  }\n\n  describe('when serializing CSS text', () => {\n    const cssText = 'div { background-color: green; top: 5px; }'\n    const cssTextStats: SerializationMetric = { count: 1, max: 42, sum: 42 }\n    const emptyStats: SerializationMetric = { count: 0, max: 0, sum: 0 }\n\n    function checkStats(privacyLevel: NodePrivacyLevel): void {\n      expect(stats.cssText).toEqual(privacyLevel === NodePrivacyLevel.HIDDEN ? emptyStats : cssTextStats)\n      stats.cssText = { ...emptyStats }\n    }\n\n    it('handles link element stylesheets', async () => {\n      const cssBlob = new Blob([cssText], { type: 'text/css' })\n      const cssUrl = URL.createObjectURL(cssBlob)\n\n      const link = document.createElement('link')\n      registerCleanupTask(() => {\n        link.parentNode?.removeChild(link)\n      })\n\n      link.setAttribute('rel', 'stylesheet')\n      link.setAttribute('href', cssUrl)\n\n      const linkLoaded = new Promise((resolve) => link.addEventListener('load', resolve))\n      document.body.appendChild(link)\n      await linkLoaded\n\n      if (isSafari() && !Array.from(document.styleSheets).find((sheet) => sheet.href === link.href)) {\n        // Safari 12 fails to load the stylesheet from the blob URL.\n        return\n      }\n\n      expectVirtualAttributes(link, { _cssText: cssText }, checkStats)\n    })\n\n    it('handles style element stylesheets', () => {\n      const style = appendElement(`<style>${cssText}</style>`)\n      expectVirtualAttributes(style, { _cssText: cssText }, checkStats)\n    })\n  })\n\n  it('serializes media element playback state', () => {\n    for (const tag of ['audio', 'video']) {\n      const media = appendElement(`<${tag}>`)\n\n      let isPaused: boolean\n      Object.defineProperty(media, 'paused', { get: () => isPaused })\n\n      isPaused = true\n      expectVirtualAttributes(media, { rr_mediaState: 'paused' })\n\n      isPaused = false\n      expectVirtualAttributes(media, { rr_mediaState: 'played' })\n    }\n  })\n\n  describe('when serializing scroll state', () => {\n    it('reads from the DOM for the initial full snapshot', () => {\n      transaction.kind = SerializationKind.INITIAL_FULL_SNAPSHOT\n\n      const div = appendElement('<div>')\n\n      const expected: ScrollPositions = {\n        scrollLeft: 0,\n        scrollTop: 0,\n      }\n      Object.defineProperty(div, 'scrollLeft', { get: () => expected.scrollLeft })\n      Object.defineProperty(div, 'scrollTop', { get: () => expected.scrollTop })\n\n      // For the initial full snapshot, we should read these values from the DOM. Store\n      // unexpected values in ElementScrollPositions so that we can detect if they're\n      // mistakenly used. Note that serializeVirtualAttributes() will write updated values\n      // into ElementScrollPositions, so we need to reset it for each expectation.\n      const poisonedScrollPositions = { scrollLeft: 9999, scrollTop: 9999 }\n      transaction.scope.elementsScrollPositions.set(div, poisonedScrollPositions)\n\n      const resetPoisonedScrollPositions = (privacyLevel: NodePrivacyLevel) => {\n        const expectedStoredPositionsToChange =\n          privacyLevel !== NodePrivacyLevel.HIDDEN && (expected.scrollLeft || expected.scrollTop)\n        const expectedStoredPositions = expectedStoredPositionsToChange ? expected : poisonedScrollPositions\n        expect(transaction.scope.elementsScrollPositions.get(div)).toEqual(expectedStoredPositions)\n        transaction.scope.elementsScrollPositions.set(div, poisonedScrollPositions)\n      }\n\n      expected.scrollLeft = 1\n      expected.scrollTop = 2\n      expectVirtualAttributes(div, { rr_scrollLeft: 1, rr_scrollTop: 2 }, resetPoisonedScrollPositions)\n\n      expected.scrollLeft = 0\n      expected.scrollTop = 3\n      expectVirtualAttributes(div, { rr_scrollTop: 3 }, resetPoisonedScrollPositions)\n\n      expected.scrollLeft = 4\n      expected.scrollTop = 0\n      expectVirtualAttributes(div, { rr_scrollLeft: 4 }, resetPoisonedScrollPositions)\n\n      expected.scrollLeft = 0\n      expected.scrollTop = 0\n      expectVirtualAttributes(div, {}, resetPoisonedScrollPositions)\n    })\n\n    it('reads from ElementsScrollPositions for subsequent full snapshots', () => {\n      transaction.kind = SerializationKind.SUBSEQUENT_FULL_SNAPSHOT\n\n      const div = appendElement('<div>')\n\n      // For subsequent full snapshots, we should read these values from\n      // ElementScrollPositions. Store unexpected values in the DOM so that we can detect\n      // if they're mistakenly used.\n      Object.defineProperty(div, 'scrollLeft', { value: 9999 })\n      Object.defineProperty(div, 'scrollTop', { value: 9999 })\n\n      const expected: ScrollPositions = {\n        scrollLeft: 0,\n        scrollTop: 0,\n      }\n      transaction.scope.elementsScrollPositions.set(div, expected)\n\n      const checkElementScrollPositions = () => {\n        expect(transaction.scope.elementsScrollPositions.get(div)).toEqual(expected)\n      }\n\n      expected.scrollLeft = 1\n      expected.scrollTop = 2\n      expectVirtualAttributes(div, { rr_scrollLeft: 1, rr_scrollTop: 2 }, checkElementScrollPositions)\n\n      expected.scrollLeft = 0\n      expected.scrollTop = 3\n      expectVirtualAttributes(div, { rr_scrollTop: 3 }, checkElementScrollPositions)\n\n      expected.scrollLeft = 4\n      expected.scrollTop = 0\n      expectVirtualAttributes(div, { rr_scrollLeft: 4 }, checkElementScrollPositions)\n\n      expected.scrollLeft = 0\n      expected.scrollTop = 0\n      expectVirtualAttributes(div, {}, checkElementScrollPositions)\n    })\n  })\n\n  it('normalizes tag names', () => {\n    // Create an <audio> element in the SVG namespace. This makes it an XML element;\n    // among other things, this results in a lowercase Element#tagName.\n    const element = document.createElementNS('http://www.w3.org/2000/svg', 'audio')\n    expect(element.tagName).toBe('audio')\n\n    // Check that serializeVirtualAttributes() still executes <audio>-specific serialization\n    // behavior; it shouldn't behave differently because Element#tagName is lowercase.\n    ;(element as any).paused = true\n    const attributes = serializeVirtualAttributes(element, NodePrivacyLevel.ALLOW, transaction)\n    expect(attributes.rr_mediaState).toBe('paused')\n  })\n})\n\ndescribe('getCssRulesString', () => {\n  let styleNode: HTMLStyleElement\n\n  beforeEach(() => {\n    styleNode = document.createElement('style')\n    document.body.appendChild(styleNode)\n\n    registerCleanupTask(() => {\n      document.body.removeChild(styleNode)\n    })\n  })\n\n  it('returns the CSS rules as a string', () => {\n    styleNode.sheet!.insertRule('body { color: red; }')\n\n    expect(getCssRulesString(styleNode.sheet)).toBe('body { color: red; }')\n  })\n\n  it('properly escapes CSS rules selectors containing a colon', () => {\n    styleNode.sheet!.insertRule('[foo\\\\:bar] { display: none; }')\n\n    expect(getCssRulesString(styleNode.sheet)).toBe('[foo\\\\:bar] { display: none; }')\n  })\n\n  it('inlines imported external stylesheets', () => {\n    styleNode.sheet!.insertRule(`@import url(\"${CSS_FILE_URL}\");`)\n\n    // Simulates an accessible external stylesheet\n    spyOnProperty(styleNode.sheet!.cssRules[0] as CSSImportRule, 'styleSheet').and.returnValue({\n      cssRules: [{ cssText: 'p { margin: 0; }' } as CSSRule] as unknown as CSSRuleList,\n    } as CSSStyleSheet)\n\n    expect(getCssRulesString(styleNode.sheet)).toBe('p { margin: 0; }')\n  })\n\n  it('does not skip the @import rules if the external stylesheet is inaccessible', () => {\n    styleNode.sheet!.insertRule(`@import url(\"${CSS_FILE_URL}\");`)\n\n    // Simulates an inaccessible external stylesheet\n    spyOnProperty(styleNode.sheet!.cssRules[0] as CSSImportRule, 'styleSheet').and.returnValue({\n      get cssRules(): CSSRuleList {\n        throw new Error('Cannot access rules')\n      },\n    } as CSSStyleSheet)\n\n    expect(getCssRulesString(styleNode.sheet)).toBe(`@import url(\"${CSS_FILE_URL}\");`)\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeAttributes.ts",
    "content": "import { NodePrivacyLevel, shouldMaskNode } from '@datadog/browser-rum-core'\nimport { isSafari } from '@datadog/browser-core'\nimport { getElementInputValue, normalizedTagName, switchToAbsoluteUrl } from './serializationUtils'\nimport { serializeAttribute } from './serializeAttribute'\nimport type { ChangeSerializationTransaction, SerializationTransaction } from './serializationTransaction'\nimport { SerializationKind } from './serializationTransaction'\nimport type { VirtualAttributes } from './serialization.types'\n\nexport function serializeAttributes(\n  element: Element,\n  nodePrivacyLevel: NodePrivacyLevel,\n  transaction: ChangeSerializationTransaction | SerializationTransaction\n): Record<string, number | string> {\n  return {\n    ...serializeDOMAttributes(element, nodePrivacyLevel, transaction),\n    ...serializeVirtualAttributes(element, nodePrivacyLevel, transaction),\n  }\n}\n\nexport function serializeDOMAttributes(\n  element: Element,\n  nodePrivacyLevel: NodePrivacyLevel,\n  transaction: ChangeSerializationTransaction | SerializationTransaction\n): Record<string, string> {\n  if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n    return {}\n  }\n\n  const attrs: Record<string, string> = {}\n  const tagName = normalizedTagName(element)\n\n  for (let i = 0; i < element.attributes.length; i += 1) {\n    const attribute = element.attributes.item(i)!\n    const attributeName = attribute.name\n    const attributeValue = serializeAttribute(element, nodePrivacyLevel, attributeName, transaction.scope.configuration)\n    if (attributeValue !== null) {\n      attrs[attributeName] = attributeValue\n    }\n  }\n\n  if (\n    (element as HTMLInputElement).value &&\n    (tagName === 'textarea' || tagName === 'select' || tagName === 'option' || tagName === 'input')\n  ) {\n    const formValue = getElementInputValue(element, nodePrivacyLevel)\n    if (formValue !== undefined) {\n      attrs.value = formValue\n    }\n  }\n\n  /**\n   * <Option> can be selected, which occurs if its `value` matches ancestor `<Select>.value`\n   */\n  if (tagName === 'option') {\n    const optionElement = element as HTMLOptionElement\n    if (optionElement.selected && !shouldMaskNode(optionElement, nodePrivacyLevel)) {\n      attrs.selected = ''\n    } else {\n      delete attrs.selected\n    }\n  }\n\n  /**\n   * Forms: input[type=checkbox,radio]\n   * The `checked` property for <input> is a little bit special:\n   * 1. el.checked is a setter that returns if truthy.\n   * 2. getAttribute returns the string value\n   * getAttribute('checked') does not sync with `Element.checked`, so use JS property\n   * NOTE: `checked` property exists on `HTMLInputElement`. For serializer assumptions, we check for type=radio|check.\n   */\n  const inputElement = element as HTMLInputElement\n  if (tagName === 'input' && (inputElement.type === 'radio' || inputElement.type === 'checkbox')) {\n    if (inputElement.checked && !shouldMaskNode(inputElement, nodePrivacyLevel)) {\n      attrs.checked = ''\n    } else {\n      delete attrs.checked\n    }\n  }\n\n  return attrs\n}\n\nexport function serializeVirtualAttributes(\n  element: Element,\n  nodePrivacyLevel: NodePrivacyLevel,\n  transaction: ChangeSerializationTransaction | SerializationTransaction\n): VirtualAttributes {\n  if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n    return {}\n  }\n\n  const attrs: VirtualAttributes = {}\n  const doc = element.ownerDocument\n  const tagName = normalizedTagName(element)\n\n  // remote css\n  if (tagName === 'link') {\n    const stylesheet = Array.from(doc.styleSheets).find((s) => s.href === (element as HTMLLinkElement).href)\n    const cssText = getCssRulesString(stylesheet)\n    if (cssText && stylesheet) {\n      transaction.addMetric('cssText', cssText.length)\n      attrs._cssText = cssText\n    }\n  }\n\n  // dynamic stylesheet\n  if (tagName === 'style' && (element as HTMLStyleElement).sheet) {\n    const cssText = getCssRulesString((element as HTMLStyleElement).sheet)\n    if (cssText) {\n      transaction.addMetric('cssText', cssText.length)\n      attrs._cssText = cssText\n    }\n  }\n\n  /**\n   * Serialize the media playback state\n   */\n  if (tagName === 'audio' || tagName === 'video') {\n    const mediaElement = element as HTMLMediaElement\n    attrs.rr_mediaState = mediaElement.paused ? 'paused' : 'played'\n  }\n\n  /**\n   * Serialize the scroll state for each element only for full snapshot\n   */\n  let scrollTop: number | undefined\n  let scrollLeft: number | undefined\n  switch (transaction.kind) {\n    case SerializationKind.INITIAL_FULL_SNAPSHOT:\n      scrollTop = Math.round(element.scrollTop)\n      scrollLeft = Math.round(element.scrollLeft)\n      if (scrollTop || scrollLeft) {\n        transaction.scope.elementsScrollPositions.set(element, { scrollTop, scrollLeft })\n      }\n      break\n    case SerializationKind.SUBSEQUENT_FULL_SNAPSHOT:\n      if (transaction.scope.elementsScrollPositions.has(element)) {\n        ;({ scrollTop, scrollLeft } = transaction.scope.elementsScrollPositions.get(element)!)\n      }\n      break\n  }\n  if (scrollLeft) {\n    attrs.rr_scrollLeft = scrollLeft\n  }\n  if (scrollTop) {\n    attrs.rr_scrollTop = scrollTop\n  }\n\n  return attrs\n}\n\nexport function getCssRulesString(cssStyleSheet: CSSStyleSheet | undefined | null): string | null {\n  if (!cssStyleSheet) {\n    return null\n  }\n  let rules: CSSRuleList | undefined\n  try {\n    rules = cssStyleSheet.rules || cssStyleSheet.cssRules\n  } catch {\n    // if css is protected by CORS we cannot access cssRules see: https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface\n  }\n  if (!rules) {\n    return null\n  }\n  const styleSheetCssText = Array.from(rules, isSafari() ? getCssRuleStringForSafari : getCssRuleString).join('')\n  return switchToAbsoluteUrl(styleSheetCssText, cssStyleSheet.href)\n}\n\nfunction getCssRuleStringForSafari(rule: CSSRule): string {\n  // Safari does not escape attribute selectors containing : properly\n  // https://bugs.webkit.org/show_bug.cgi?id=184604\n  if (isCSSStyleRule(rule) && rule.selectorText.includes(':')) {\n    // This regex replaces [foo:bar] by [foo\\\\:bar]\n    const escapeColon = /(\\[[\\w-]+[^\\\\])(:[^\\]]+\\])/g\n    return rule.cssText.replace(escapeColon, '$1\\\\$2')\n  }\n\n  return getCssRuleString(rule)\n}\n\nfunction getCssRuleString(rule: CSSRule): string {\n  // If it's an @import rule, try to inline sub-rules recursively with `getCssRulesString`. This\n  // operation can fail if the imported stylesheet is protected by CORS, in which case we fallback\n  // to the @import rule CSS text.\n  return (isCSSImportRule(rule) && getCssRulesString(rule.styleSheet)) || rule.cssText\n}\n\nfunction isCSSImportRule(rule: CSSRule): rule is CSSImportRule {\n  return 'styleSheet' in rule\n}\n\nfunction isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {\n  return 'selectorText' in rule\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeFullSnapshot.ts",
    "content": "import { getScrollX, getScrollY } from '@datadog/browser-rum-core'\nimport type { TimeStamp } from '@datadog/browser-core'\nimport type { BrowserFullSnapshotRecord } from '../../../types'\nimport { RecordType, SnapshotFormat } from '../../../types'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport { serializeNode } from './serializeNode'\nimport { serializeInTransaction } from './serializationTransaction'\nimport type { SerializationKind, SerializationTransaction } from './serializationTransaction'\n\nexport function serializeFullSnapshot(\n  timestamp: TimeStamp,\n  kind: SerializationKind,\n  document: Document,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope\n): void {\n  serializeInTransaction(kind, emitRecord, emitStats, scope, (transaction: SerializationTransaction) => {\n    const defaultPrivacyLevel = transaction.scope.configuration.defaultPrivacyLevel\n\n    // We are sure that Documents are never ignored, so this function never returns null.\n    const node = serializeNode(document, defaultPrivacyLevel, transaction)!\n\n    const record: BrowserFullSnapshotRecord = {\n      data: {\n        node,\n        initialOffset: {\n          left: getScrollX(),\n          top: getScrollY(),\n        },\n      },\n      format: SnapshotFormat.V1,\n      type: RecordType.FullSnapshot,\n      timestamp,\n    }\n    transaction.add(record)\n\n    scope.serializeObservable.notify({\n      type: 'full',\n      kind,\n      target: document,\n      timestamp,\n      v1: record,\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeFullSnapshotAsChange.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport { serializeChangesInTransaction } from './serializationTransaction'\nimport type { ChangeSerializationTransaction, SerializationKind } from './serializationTransaction'\nimport { serializeNodeAsChange } from './serializeNodeAsChange'\nimport { createRootInsertionCursor } from './insertionCursor'\n\nexport function serializeFullSnapshotAsChange(\n  timestamp: TimeStamp,\n  kind: SerializationKind,\n  document: Document,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope\n): void {\n  scope.resetIds()\n  serializeChangesInTransaction(\n    kind,\n    emitRecord,\n    emitStats,\n    scope,\n    timestamp,\n    (transaction: ChangeSerializationTransaction) => {\n      serializeNodeAsChange(\n        createRootInsertionCursor(scope.nodeIds),\n        document,\n        scope.configuration.defaultPrivacyLevel,\n        transaction\n      )\n    }\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeHtml.specHelper.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { forEachChildNodes, getNodePrivacyLevel } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../../../core/test'\nimport type { BrowserFullSnapshotChangeRecord, BrowserChangeRecord, BrowserRecord } from '../../../types'\nimport { RecordType, SnapshotFormat } from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport type { ChangeSerializationTransaction } from './serializationTransaction'\nimport { SerializationKind, serializeChangesInTransaction } from './serializationTransaction'\nimport { createRootInsertionCursor } from './insertionCursor'\nimport { serializeNodeAsChange } from './serializeNodeAsChange'\nimport { createChangeDecoder } from './conversions'\nimport type { SerializationStats } from './serializationStats'\nimport { aggregateSerializationStats, createSerializationStats } from './serializationStats'\n\n/**\n * A wrapper for serializeNodeAsChange() that parses HTML in an isolated context, selects\n * a target node from the resulting subtree (by default, the subtree root), and serializes\n * it using serializeNodeAsChange().\n *\n * @param html - The HTML to parse.\n * @param options - Options to customize the serialization process.\n * @param options.after - A callback to run against the target node after serialization; use this\n * to make assertions that require the target node as context.\n * @param options.before - A callback to run against the target node before serialization; use this\n * to perform mutations that affect serialization but can't be expressed directly in the HTML.\n * @param options.configuration - A custom RumConfiguration to use for serialization.\n * @param options.input - Whether the HTML input represents a subtree or an entire\n * document. The default is 'subtree'.\n * @param options.kind - The kind of serialization to perform. The default is\n * SerializationKind.INITIAL_FULL_SNAPSHOT.\n * @param options.target - A callback which is passed the subtree root and can return a different\n * node to use as a serialization target.\n * @param options.whitespace - Whether to keep or discard whitespace-only text nodes. The default\n * is to discard them, which gives you more freedom when formatting the HTML.\n */\nexport async function serializeHtmlAsChange(\n  html: string,\n  {\n    after,\n    before,\n    configuration,\n    input,\n    kind,\n    target,\n    whitespace,\n  }: {\n    after?: (target: Node, scope: RecordingScope, stats: SerializationStats) => void\n    before?: (target: Node, scope: RecordingScope) => void\n    configuration?: Partial<RumConfiguration>\n    input?: 'document' | 'subtree'\n    kind?: SerializationKind\n    target?: (defaultTarget: Node) => Node\n    whitespace?: 'discard' | 'keep'\n  } = {}\n): Promise<BrowserChangeRecord | BrowserFullSnapshotChangeRecord | undefined> {\n  const content =\n    input === 'document'\n      ? html\n      : `<!doctype HTML><html style=\"width: 100%; height: 100%;\"><head></head><body>${html}</body></html>`\n  const container = await createFreshIFrame(content)\n  registerCleanupTask(() => {\n    container.remove()\n  })\n\n  const iframeDoc = container.contentDocument\n  if (!iframeDoc) {\n    throw new Error('Expected a loaded iframe document')\n  }\n\n  if (whitespace !== 'keep') {\n    removeWhiteSpaceOnlyNodesInSubtree(iframeDoc)\n  }\n\n  const subtreeRoot = input === 'document' ? iframeDoc : iframeDoc.body.firstChild\n  if (!subtreeRoot) {\n    throw new Error('Expected a subtree containing at least one node')\n  }\n\n  const targetNode = target?.(subtreeRoot) ?? subtreeRoot\n\n  const scope = createRecordingScopeForTesting({ configuration })\n\n  let emittedRecord: BrowserRecord | undefined\n  const emitRecord = (record: BrowserRecord): void => {\n    emittedRecord = record\n  }\n\n  const emittedStats = createSerializationStats()\n  const emitStats = (stats: SerializationStats): void => {\n    aggregateSerializationStats(emittedStats, stats)\n  }\n\n  before?.(targetNode, scope)\n\n  serializeChangesInTransaction(\n    kind ?? SerializationKind.INITIAL_FULL_SNAPSHOT,\n    emitRecord,\n    emitStats,\n    scope,\n    0 as TimeStamp,\n    (transaction: ChangeSerializationTransaction) => {\n      const insertionCursor = createRootInsertionCursor(scope.nodeIds)\n      const defaultPrivacyLevel = transaction.scope.configuration.defaultPrivacyLevel\n      const parentNodePrivacyLevel = !targetNode.parentNode\n        ? defaultPrivacyLevel\n        : getNodePrivacyLevel(targetNode.parentNode, defaultPrivacyLevel)\n      serializeNodeAsChange(insertionCursor, targetNode, parentNodePrivacyLevel, transaction)\n    }\n  )\n\n  after?.(targetNode, scope, emittedStats)\n\n  if (!emittedRecord) {\n    return undefined\n  }\n\n  if (\n    emittedRecord.type !== RecordType.Change &&\n    (emittedRecord.type !== RecordType.FullSnapshot || emittedRecord.format !== SnapshotFormat.Change)\n  ) {\n    throw new Error('Expected serialization to yield a BrowserChangeRecord')\n  }\n\n  const changeDecoder = createChangeDecoder()\n  return changeDecoder.decode(emittedRecord)\n}\n\n// The size of the iframes we render test content into. The same size is used for both\n// width and height.\nconst IFRAME_SIZE_PX = '500'\n\nasync function createFreshIFrame(content: string): Promise<HTMLIFrameElement> {\n  const iframe = document.createElement('iframe')\n  iframe.width = IFRAME_SIZE_PX\n  iframe.height = IFRAME_SIZE_PX\n  iframe.style.border = '0'\n  iframe.style.boxSizing = 'border-box'\n  iframe.style.margin = '0'\n  iframe.style.width = `${IFRAME_SIZE_PX}px`\n  iframe.style.height = `${IFRAME_SIZE_PX}px`\n  iframe.srcdoc = content\n\n  const loadEvent = waitForLoadEvent(iframe)\n  document.body.appendChild(iframe)\n  await loadEvent\n\n  return iframe\n}\n\nfunction waitForLoadEvent(iframe: HTMLIFrameElement): Promise<void> {\n  return new Promise((resolve, reject) => {\n    iframe.addEventListener('load', () => {\n      resolve()\n    })\n    iframe.addEventListener('error', reject)\n  })\n}\n\nfunction removeWhiteSpaceOnlyNodesInSubtree(subtreeRoot: Node): void {\n  const descendantsToRemove = new Set<Node>()\n\n  const collectWhiteSpaceOnlyDescendants = (node: Node) => {\n    forEachChildNodes(node, (child: Node) => {\n      if (child.nodeType === child.TEXT_NODE && !child.textContent?.trim()) {\n        descendantsToRemove.add(child)\n      }\n      collectWhiteSpaceOnlyDescendants(child)\n    })\n  }\n\n  collectWhiteSpaceOnlyDescendants(subtreeRoot)\n\n  for (const descendant of descendantsToRemove) {\n    descendant.parentNode?.removeChild(descendant)\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeMutations.spec.ts",
    "content": "import type { RecordingScope } from '../recordingScope'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { idsAreAssignedForNodeAndAncestors, sortAddedAndMovedNodes } from './serializeMutations'\n\ndescribe('idsAreAssignedForNodeAndAncestors', () => {\n  let scope: RecordingScope\n\n  beforeEach(() => {\n    scope = createRecordingScopeForTesting()\n  })\n\n  it('returns false for DOM Nodes that have not been assigned an id', () => {\n    expect(idsAreAssignedForNodeAndAncestors(document.createElement('div'), scope.nodeIds)).toBe(false)\n  })\n\n  it('returns true for DOM Nodes that have been assigned an id', () => {\n    const node = document.createElement('div')\n    scope.nodeIds.getOrInsert(node)\n    expect(idsAreAssignedForNodeAndAncestors(node, scope.nodeIds)).toBe(true)\n  })\n\n  it('returns false for DOM Nodes when an ancestor has not been assigned an id', () => {\n    const node = document.createElement('div')\n    scope.nodeIds.getOrInsert(node)\n\n    const parent = document.createElement('div')\n    parent.appendChild(node)\n    scope.nodeIds.getOrInsert(parent)\n\n    const grandparent = document.createElement('div')\n    grandparent.appendChild(parent)\n\n    expect(idsAreAssignedForNodeAndAncestors(node, scope.nodeIds)).toBe(false)\n  })\n\n  it('returns true for DOM Nodes when all ancestors have been assigned an id', () => {\n    const node = document.createElement('div')\n    scope.nodeIds.getOrInsert(node)\n\n    const parent = document.createElement('div')\n    parent.appendChild(node)\n    scope.nodeIds.getOrInsert(parent)\n\n    const grandparent = document.createElement('div')\n    grandparent.appendChild(parent)\n    scope.nodeIds.getOrInsert(grandparent)\n\n    expect(idsAreAssignedForNodeAndAncestors(node, scope.nodeIds)).toBe(true)\n  })\n\n  it('returns true for DOM Nodes in shadow subtrees', () => {\n    const node = document.createElement('div')\n    scope.nodeIds.getOrInsert(node)\n\n    const parent = document.createElement('div')\n    parent.appendChild(node)\n    scope.nodeIds.getOrInsert(parent)\n\n    const grandparent = document.createElement('div')\n    const shadowRoot = grandparent.attachShadow({ mode: 'open' })\n    shadowRoot.appendChild(parent)\n    scope.nodeIds.getOrInsert(grandparent)\n\n    expect(idsAreAssignedForNodeAndAncestors(node, scope.nodeIds)).toBe(true)\n  })\n})\n\ndescribe('sortAddedAndMovedNodes', () => {\n  let parent: Node\n  let a: Node\n  let aa: Node\n  let b: Node\n  let c: Node\n  let d: Node\n\n  beforeEach(() => {\n    // Create a tree like this:\n    //     parent\n    //     / | \\ \\\n    //    a  b c d\n    //    |\n    //    aa\n    a = document.createElement('a')\n    aa = document.createElement('aa')\n    b = document.createElement('b')\n    c = document.createElement('c')\n    d = document.createElement('d')\n    parent = document.createElement('parent')\n    parent.appendChild(a)\n    a.appendChild(aa)\n    parent.appendChild(b)\n    parent.appendChild(c)\n    parent.appendChild(d)\n  })\n\n  it('sorts siblings in reverse order', () => {\n    const nodes = [c, b, d, a]\n    sortAddedAndMovedNodes(nodes)\n    expect(nodes).toEqual([d, c, b, a])\n  })\n\n  it('sorts parents', () => {\n    const nodes = [a, parent, aa]\n    sortAddedAndMovedNodes(nodes)\n    expect(nodes).toEqual([parent, a, aa])\n  })\n\n  it('sorts parents first then siblings', () => {\n    const nodes = [c, aa, b, parent, d, a]\n    sortAddedAndMovedNodes(nodes)\n    expect(nodes).toEqual([parent, d, c, b, a, aa])\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeMutations.ts",
    "content": "import type {\n  NodePrivacyLevelCache,\n  RumMutationRecord,\n  RumChildListMutationRecord,\n  RumCharacterDataMutationRecord,\n  RumAttributesMutationRecord,\n} from '@datadog/browser-rum-core'\nimport {\n  isNodeShadowHost,\n  getParentNode,\n  forEachChildNodes,\n  getNodePrivacyLevel,\n  getTextContent,\n  NodePrivacyLevel,\n  isNodeShadowRoot,\n} from '@datadog/browser-rum-core'\nimport type { TimeStamp } from '@datadog/browser-core'\nimport { IncrementalSource } from '../../../types'\nimport type {\n  BrowserMutationData,\n  AddedNodeMutation,\n  AttributeMutation,\n  RemovedNodeMutation,\n  TextMutation,\n} from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { RemoveShadowRootCallBack } from '../shadowRootsController'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport type { NodeId, NodeIds } from '../itemIds'\nimport type { SerializationTransaction } from './serializationTransaction'\nimport { SerializationKind, serializeInTransaction } from './serializationTransaction'\nimport { serializeNode } from './serializeNode'\nimport { serializeAttribute } from './serializeAttribute'\nimport { getElementInputValue } from './serializationUtils'\n\nexport type NodeWithSerializedNode = Node & { __brand: 'NodeWithSerializedNode' }\ntype WithSerializedTarget<T> = T & { target: NodeWithSerializedNode }\n\nexport function serializeMutations(\n  timestamp: TimeStamp,\n  mutations: RumMutationRecord[],\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope\n): void {\n  serializeInTransaction(\n    SerializationKind.INCREMENTAL_SNAPSHOT,\n    emitRecord,\n    emitStats,\n    scope,\n    (transaction: SerializationTransaction) => processMutations(timestamp, mutations, transaction)\n  )\n}\n\nfunction processMutations(\n  timestamp: TimeStamp,\n  mutations: RumMutationRecord[],\n  transaction: SerializationTransaction\n): void {\n  const nodePrivacyLevelCache: NodePrivacyLevelCache = new Map()\n\n  mutations\n    .filter((mutation): mutation is RumChildListMutationRecord => mutation.type === 'childList')\n    .forEach((mutation) => {\n      mutation.removedNodes.forEach((removedNode) => {\n        traverseRemovedShadowDom(removedNode, transaction.scope.shadowRootsController.removeShadowRoot)\n      })\n    })\n\n  // Discard any mutation with a 'target' node that:\n  // * isn't injected in the current document or isn't known/serialized yet: those nodes are likely\n  // part of a mutation occurring in a parent Node\n  // * should be hidden or ignored\n  const filteredMutations = mutations.filter(\n    (mutation): mutation is WithSerializedTarget<RumMutationRecord> =>\n      mutation.target.isConnected &&\n      idsAreAssignedForNodeAndAncestors(mutation.target, transaction.scope.nodeIds) &&\n      getNodePrivacyLevel(\n        mutation.target,\n        transaction.scope.configuration.defaultPrivacyLevel,\n        nodePrivacyLevelCache\n      ) !== NodePrivacyLevel.HIDDEN\n  )\n\n  const { adds, removes, hasBeenSerialized } = processChildListMutations(\n    filteredMutations.filter(\n      (mutation): mutation is WithSerializedTarget<RumChildListMutationRecord> => mutation.type === 'childList'\n    ),\n    nodePrivacyLevelCache,\n    transaction\n  )\n\n  const texts = processCharacterDataMutations(\n    filteredMutations.filter(\n      (mutation): mutation is WithSerializedTarget<RumCharacterDataMutationRecord> =>\n        mutation.type === 'characterData' && !hasBeenSerialized(mutation.target)\n    ),\n    nodePrivacyLevelCache,\n    transaction\n  )\n\n  const attributes = processAttributesMutations(\n    filteredMutations.filter(\n      (mutation): mutation is WithSerializedTarget<RumAttributesMutationRecord> =>\n        mutation.type === 'attributes' && !hasBeenSerialized(mutation.target)\n    ),\n    nodePrivacyLevelCache,\n    transaction\n  )\n\n  if (!texts.length && !attributes.length && !removes.length && !adds.length) {\n    return\n  }\n\n  const record = assembleIncrementalSnapshot<BrowserMutationData>(\n    IncrementalSource.Mutation,\n    {\n      adds,\n      removes,\n      texts,\n      attributes,\n    },\n    timestamp\n  )\n  transaction.add(record)\n\n  transaction.scope.serializeObservable.notify({\n    type: 'incremental',\n    target: mutations,\n    timestamp,\n    v1: record,\n  })\n}\n\nfunction processChildListMutations(\n  mutations: Array<WithSerializedTarget<RumChildListMutationRecord>>,\n  nodePrivacyLevelCache: NodePrivacyLevelCache,\n  transaction: SerializationTransaction\n) {\n  // First, we iterate over mutations to collect:\n  //\n  // * nodes that have been added in the document and not removed by a subsequent mutation\n  // * nodes that have been removed from the document but were not added in a previous mutation\n  //\n  // For this second category, we also collect their previous parent (mutation.target) because we'll\n  // need it to emit a 'remove' mutation.\n  //\n  // Those two categories may overlap: if a node moved from a position to another, it is reported as\n  // two mutation records, one with a \"removedNodes\" and the other with \"addedNodes\". In this case,\n  // the node will be in both sets.\n  const addedAndMovedNodes = new Set<Node>()\n  const removedNodes = new Map<Node, NodeWithSerializedNode>()\n  for (const mutation of mutations) {\n    mutation.addedNodes.forEach((node) => {\n      addedAndMovedNodes.add(node)\n    })\n    mutation.removedNodes.forEach((node) => {\n      if (!addedAndMovedNodes.has(node)) {\n        removedNodes.set(node, mutation.target)\n      }\n      addedAndMovedNodes.delete(node)\n    })\n  }\n\n  // Then, we sort nodes that are still in the document by topological order, for two reasons:\n  //\n  // * We will serialize each added nodes with their descendants. We don't want to serialize a node\n  // twice, so we need to iterate over the parent nodes first and skip any node that is contained in\n  // a precedent node.\n  //\n  // * To emit \"add\" mutations, we need references to the parent and potential next sibling of each\n  // added node. So we need to iterate over the parent nodes first, and when multiple nodes are\n  // siblings, we want to iterate from last to first. This will ensure that any \"next\" node is\n  // already serialized and have an id.\n  const sortedAddedAndMovedNodes = Array.from(addedAndMovedNodes)\n  sortAddedAndMovedNodes(sortedAddedAndMovedNodes)\n\n  // Then, we iterate over our sorted node sets to emit mutations. We collect the newly serialized\n  // node ids in a set to be able to skip subsequent related mutations.\n  transaction.serializedNodeIds = new Set<NodeId>()\n\n  const addedNodeMutations: AddedNodeMutation[] = []\n  for (const node of sortedAddedAndMovedNodes) {\n    if (hasBeenSerialized(node)) {\n      continue\n    }\n\n    const parentNodePrivacyLevel = getNodePrivacyLevel(\n      node.parentNode!,\n      transaction.scope.configuration.defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n    if (parentNodePrivacyLevel === NodePrivacyLevel.HIDDEN || parentNodePrivacyLevel === NodePrivacyLevel.IGNORE) {\n      continue\n    }\n\n    const serializedNode = serializeNode(node, parentNodePrivacyLevel, transaction)\n    if (!serializedNode) {\n      continue\n    }\n\n    const parentNode = getParentNode(node)!\n    addedNodeMutations.push({\n      nextId: getNextSibling(node),\n      parentId: transaction.scope.nodeIds.get(parentNode)!,\n      node: serializedNode,\n    })\n  }\n  // Finally, we emit remove mutations.\n  const removedNodeMutations: RemovedNodeMutation[] = []\n  removedNodes.forEach((parent, node) => {\n    const parentId = transaction.scope.nodeIds.get(parent)\n    const id = transaction.scope.nodeIds.get(node)\n    if (parentId !== undefined && id !== undefined) {\n      removedNodeMutations.push({ parentId, id })\n    }\n  })\n\n  return { adds: addedNodeMutations, removes: removedNodeMutations, hasBeenSerialized }\n\n  function hasBeenSerialized(node: Node) {\n    const id = transaction.scope.nodeIds.get(node)\n    return id !== undefined && transaction.serializedNodeIds?.has(id)\n  }\n\n  function getNextSibling(node: Node): null | number {\n    let nextSibling = node.nextSibling\n    while (nextSibling) {\n      const id = transaction.scope.nodeIds.get(nextSibling)\n      if (id !== undefined) {\n        return id\n      }\n      nextSibling = nextSibling.nextSibling\n    }\n\n    return null\n  }\n}\n\nfunction processCharacterDataMutations(\n  mutations: Array<WithSerializedTarget<RumCharacterDataMutationRecord>>,\n  nodePrivacyLevelCache: NodePrivacyLevelCache,\n  transaction: SerializationTransaction\n) {\n  const textMutations: TextMutation[] = []\n\n  // Deduplicate mutations based on their target node\n  const handledNodes = new Set<Node>()\n  const filteredMutations = mutations.filter((mutation) => {\n    if (handledNodes.has(mutation.target)) {\n      return false\n    }\n    handledNodes.add(mutation.target)\n    return true\n  })\n\n  // Emit mutations\n  for (const mutation of filteredMutations) {\n    const value = mutation.target.textContent\n    if (value === mutation.oldValue) {\n      continue\n    }\n\n    const id = transaction.scope.nodeIds.get(mutation.target)\n    if (id === undefined) {\n      continue\n    }\n\n    const parentNodePrivacyLevel = getNodePrivacyLevel(\n      getParentNode(mutation.target)!,\n      transaction.scope.configuration.defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n    if (parentNodePrivacyLevel === NodePrivacyLevel.HIDDEN || parentNodePrivacyLevel === NodePrivacyLevel.IGNORE) {\n      continue\n    }\n\n    textMutations.push({\n      id,\n      value: getTextContent(mutation.target, parentNodePrivacyLevel) ?? null,\n    })\n  }\n\n  return textMutations\n}\n\nfunction processAttributesMutations(\n  mutations: Array<WithSerializedTarget<RumAttributesMutationRecord>>,\n  nodePrivacyLevelCache: NodePrivacyLevelCache,\n  transaction: SerializationTransaction\n) {\n  const attributeMutations: AttributeMutation[] = []\n\n  // Deduplicate mutations based on their target node and changed attribute\n  const handledElements = new Map<Element, Set<string>>()\n  const filteredMutations = mutations.filter((mutation) => {\n    const handledAttributes = handledElements.get(mutation.target)\n    if (handledAttributes && handledAttributes.has(mutation.attributeName)) {\n      return false\n    }\n    if (!handledAttributes) {\n      handledElements.set(mutation.target, new Set([mutation.attributeName]))\n    } else {\n      handledAttributes.add(mutation.attributeName)\n    }\n    return true\n  })\n\n  // Emit mutations\n  const emittedMutations = new Map<Element, AttributeMutation>()\n  for (const mutation of filteredMutations) {\n    const uncensoredValue = mutation.target.getAttribute(mutation.attributeName)\n    if (uncensoredValue === mutation.oldValue) {\n      continue\n    }\n\n    const id = transaction.scope.nodeIds.get(mutation.target)\n    if (id === undefined) {\n      continue\n    }\n\n    const privacyLevel = getNodePrivacyLevel(\n      mutation.target,\n      transaction.scope.configuration.defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n    const attributeValue = serializeAttribute(\n      mutation.target,\n      privacyLevel,\n      mutation.attributeName,\n      transaction.scope.configuration\n    )\n\n    let transformedValue: string | null\n    if (mutation.attributeName === 'value') {\n      const inputValue = getElementInputValue(mutation.target, privacyLevel)\n      if (inputValue === undefined) {\n        continue\n      }\n      transformedValue = inputValue\n    } else if (typeof attributeValue === 'string') {\n      transformedValue = attributeValue\n    } else {\n      transformedValue = null\n    }\n\n    let emittedMutation = emittedMutations.get(mutation.target)\n    if (!emittedMutation) {\n      emittedMutation = { id, attributes: {} }\n      attributeMutations.push(emittedMutation)\n      emittedMutations.set(mutation.target, emittedMutation)\n    }\n\n    emittedMutation.attributes[mutation.attributeName] = transformedValue\n  }\n\n  return attributeMutations\n}\n\nexport function sortAddedAndMovedNodes(nodes: Node[]) {\n  nodes.sort((a, b) => {\n    const position = a.compareDocumentPosition(b)\n    /* eslint-disable no-bitwise */\n    if (position & Node.DOCUMENT_POSITION_CONTAINED_BY) {\n      return -1\n    } else if (position & Node.DOCUMENT_POSITION_CONTAINS) {\n      return 1\n    } else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {\n      return 1\n    } else if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n      return -1\n    }\n    /* eslint-enable no-bitwise */\n    return 0\n  })\n}\n\nfunction traverseRemovedShadowDom(removedNode: Node, shadowDomRemovedCallback: RemoveShadowRootCallBack) {\n  if (isNodeShadowHost(removedNode)) {\n    shadowDomRemovedCallback(removedNode.shadowRoot)\n  }\n  forEachChildNodes(removedNode, (childNode) => traverseRemovedShadowDom(childNode, shadowDomRemovedCallback))\n}\n\nexport function idsAreAssignedForNodeAndAncestors(node: Node, nodeIds: NodeIds): node is NodeWithSerializedNode {\n  let current: Node | null = node\n  while (current) {\n    if (nodeIds.get(current) === undefined && !isNodeShadowRoot(current)) {\n      return false\n    }\n    current = getParentNode(current)\n  }\n  return true\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeMutationsAsChange.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport type { NodePrivacyLevelCache, RumMutationRecord } from '@datadog/browser-rum-core'\nimport {\n  isNodeShadowHost,\n  getParentNode,\n  forEachChildNodes,\n  getNodePrivacyLevel,\n  getTextContent,\n  NodePrivacyLevel,\n} from '@datadog/browser-rum-core'\nimport type { AttributeChange } from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport type { NodeId, NodeIds } from '../itemIds'\nimport type { ChangeSerializationTransaction } from './serializationTransaction'\nimport { SerializationKind, serializeChangesInTransaction } from './serializationTransaction'\nimport { serializeNodeAsChange } from './serializeNodeAsChange'\nimport { createChildInsertionCursor } from './insertionCursor'\nimport { getElementInputValue } from './serializationUtils'\nimport { serializeAttribute } from './serializeAttribute'\n\nexport function serializeMutationsAsChange(\n  timestamp: TimeStamp,\n  mutations: RumMutationRecord[],\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope\n): void {\n  serializeChangesInTransaction(\n    SerializationKind.INCREMENTAL_SNAPSHOT,\n    emitRecord,\n    emitStats,\n    scope,\n    timestamp,\n    (transaction: ChangeSerializationTransaction) => processMutations(mutations, transaction)\n  )\n}\n\ntype AttributeName = string\ntype OldValue = string | null\n\nfunction processMutations(mutations: RumMutationRecord[], transaction: ChangeSerializationTransaction): void {\n  const addedNodes = new Set<Node>()\n  const attributeMutations = new Map<Element, Map<AttributeName, OldValue>>()\n  const characterDataMutations = new Map<Node, OldValue>()\n  const removedNodes = new Set<Node>()\n\n  // Collect the changes made by this sequence of mutations. It's important to think of\n  // the mutations as telling us which parts of the tree are dirty, but not necessarily as\n  // specifying exactly which changes have occurred; trying to be too clever will result\n  // in incorrect behavior. For example, if we see a sequence of mutations where a node is\n  // removed and then added back in the same position, one might be tempted to \"cancel\n  // out\" these two changes and ignore both mutations, but that could cause us to miss\n  // changes to the node that occurred while it was detached.\n  for (const mutation of mutations) {\n    switch (mutation.type) {\n      case 'attributes': {\n        const node = mutation.target\n        let attributes = attributeMutations.get(node)\n        if (!attributes) {\n          attributes = new Map<AttributeName, OldValue>()\n          attributeMutations.set(node, attributes)\n        }\n        const attributeName = mutation.attributeName\n        if (!attributes.has(attributeName)) {\n          attributes.set(attributeName, mutation.oldValue)\n        }\n        break\n      }\n\n      case 'characterData':\n        if (!characterDataMutations.has(mutation.target)) {\n          characterDataMutations.set(mutation.target, mutation.oldValue)\n        }\n        break\n\n      case 'childList':\n        for (let index = 0; index < mutation.addedNodes.length; index++) {\n          addedNodes.add(mutation.addedNodes[index])\n        }\n        for (let index = 0; index < mutation.removedNodes.length; index++) {\n          removedNodes.add(mutation.removedNodes[index])\n        }\n        break\n    }\n  }\n\n  // Before we process any mutations, snapshot the id that the next newly-added node will\n  // receive. We know that any node with an id greater than or equal to this one is new\n  // and will have been serialized in its entirety in processAddedNodes(), so we can skip\n  // processing more fine-grained mutations for these nodes.\n  const firstNewNodeId = transaction.scope.nodeIds.nextId\n\n  // Because we process incremental mutations synchronously, we know that privacy levels\n  // cannot change during the process, so we use a single, shared privacy level cache.\n  const nodePrivacyLevelCache: NodePrivacyLevelCache = new Map()\n\n  processRemovedNodes(removedNodes, transaction)\n  processAddedNodes(addedNodes, nodePrivacyLevelCache, transaction)\n  processCharacterDataMutations(characterDataMutations, firstNewNodeId, nodePrivacyLevelCache, transaction)\n  processAttributeMutations(attributeMutations, firstNewNodeId, nodePrivacyLevelCache, transaction)\n}\n\nfunction processRemovedNodes(nodes: Set<Node>, transaction: ChangeSerializationTransaction): void {\n  const nodeIds = transaction.scope.nodeIds\n\n  for (const node of nodes) {\n    const nodeId = nodeIds.get(node)\n    if (nodeId === undefined) {\n      continue // This node wasn't serialized.\n    }\n\n    forNodeAndDescendants(node, (node: Node) => {\n      if (isNodeShadowHost(node)) {\n        transaction.scope.shadowRootsController.removeShadowRoot(node.shadowRoot)\n      }\n\n      // Forget this node's identity. If it's added to the DOM again in another mutation,\n      // we'll treat it as a new node. This reduces the number of edge cases that we need\n      // to deal with; for example, changes in privacy level as a result of the different\n      // ancestor chain in the new position are handled without any special effort on our\n      // part.\n      nodeIds.delete(node)\n    })\n\n    transaction.removeNode(nodeId)\n  }\n}\n\nfunction processAddedNodes(\n  nodes: Set<Node>,\n  nodePrivacyLevelCache: NodePrivacyLevelCache,\n  transaction: ChangeSerializationTransaction\n): void {\n  const nodeIds = transaction.scope.nodeIds\n\n  for (const node of nodes) {\n    if (!node.isConnected) {\n      continue // This node is not in the DOM.\n    }\n\n    const existingNodeId = nodeIds.get(node)\n    if (existingNodeId !== undefined) {\n      continue // This node has already been serialized.\n    }\n\n    const parentNode = getParentNode(node)\n    if (!parentNode) {\n      continue // This node has no parent.\n    }\n\n    const parentId = nodeIds.get(parentNode)\n    if (parentId === undefined) {\n      // This node's parent hasn't been serialized (e.g. because it has privacy level\n      // HIDDEN), so we shouldn't serialize this node either.\n      continue\n    }\n\n    const parentNodePrivacyLevel = getNodePrivacyLevel(\n      parentNode,\n      transaction.scope.configuration.defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n\n    const nextSiblingId = getNextSiblingId(node, nodeIds)\n\n    serializeNodeAsChange(\n      createChildInsertionCursor(parentId, nextSiblingId, nodeIds),\n      node,\n      parentNodePrivacyLevel,\n      transaction\n    )\n  }\n}\n\nfunction processCharacterDataMutations(\n  mutations: Map<Node, OldValue>,\n  firstNewNodeId: NodeId,\n  nodePrivacyLevelCache: NodePrivacyLevelCache,\n  transaction: ChangeSerializationTransaction\n): void {\n  const nodeIds = transaction.scope.nodeIds\n\n  for (const [node, oldValue] of mutations) {\n    if (node.textContent === oldValue) {\n      continue // No change since the last snapshot.\n    }\n\n    if (!node.isConnected) {\n      continue // This node is not in the DOM.\n    }\n\n    const nodeId = nodeIds.get(node)\n    if (nodeId === undefined) {\n      continue // This node was never serialized.\n    }\n    if (nodeId >= firstNewNodeId) {\n      // This node was just serialized, so we've already got an up-to-date copy of its\n      // text content.\n      continue\n    }\n\n    const parentNode = getParentNode(node)\n    if (!parentNode) {\n      continue // This node has no parent.\n    }\n\n    const parentNodePrivacyLevel = getNodePrivacyLevel(\n      parentNode,\n      transaction.scope.configuration.defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n    if (parentNodePrivacyLevel === NodePrivacyLevel.HIDDEN || parentNodePrivacyLevel === NodePrivacyLevel.IGNORE) {\n      continue // Mutations to this node should be ignored.\n    }\n\n    const content = getTextContent(node, parentNodePrivacyLevel) ?? ''\n    transaction.setText(nodeId, content)\n  }\n}\n\nfunction processAttributeMutations(\n  mutations: Map<Element, Map<AttributeName, OldValue>>,\n  firstNewNodeId: NodeId,\n  nodePrivacyLevelCache: NodePrivacyLevelCache,\n  transaction: ChangeSerializationTransaction\n): void {\n  const nodeIds = transaction.scope.nodeIds\n\n  for (const [node, attributeNames] of mutations) {\n    if (!node.isConnected) {\n      continue // This node is not in the DOM.\n    }\n\n    const nodeId = nodeIds.get(node)\n    if (nodeId === undefined) {\n      continue // This node was never serialized.\n    }\n    if (nodeId >= firstNewNodeId) {\n      // This node was just serialized, so we've already got an up-to-date copy of its\n      // attributes.\n      continue\n    }\n\n    const privacyLevel = getNodePrivacyLevel(\n      node,\n      transaction.scope.configuration.defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n    if (privacyLevel === NodePrivacyLevel.HIDDEN || privacyLevel === NodePrivacyLevel.IGNORE) {\n      continue // Mutations to this node should be ignored.\n    }\n\n    const change: AttributeChange = [nodeId]\n    for (const [attributeName, oldValue] of attributeNames) {\n      if (node.getAttribute(attributeName) === oldValue) {\n        continue // No change since the last snapshot.\n      }\n\n      if (attributeName === 'value') {\n        const attributeValue = getElementInputValue(node, privacyLevel)\n        if (attributeValue !== undefined) {\n          change.push([attributeName, attributeValue])\n        }\n        continue\n      }\n\n      const attributeValue = serializeAttribute(node, privacyLevel, attributeName, transaction.scope.configuration)\n      if (attributeValue === null) {\n        change.push([attributeName])\n      } else {\n        change.push([attributeName, attributeValue])\n      }\n    }\n\n    if (change.length > 1) {\n      transaction.setAttributes(change)\n    }\n  }\n}\n\nfunction getNextSiblingId(node: Node, nodeIds: NodeIds): NodeId | undefined {\n  let nextSibling = node.nextSibling\n  while (nextSibling) {\n    const id = nodeIds.get(nextSibling)\n    if (id !== undefined) {\n      return id\n    }\n    nextSibling = nextSibling.nextSibling\n  }\n\n  return undefined\n}\n\nfunction forNodeAndDescendants(node: Node, action: (node: Node) => void): void {\n  action(node)\n  forEachChildNodes(node, (childNode) => forNodeAndDescendants(childNode, action))\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNode.spec.ts",
    "content": "import type { BrowserWindow } from '@datadog/browser-rum-core'\nimport { isAdoptedStyleSheetsSupported, registerCleanupTask } from '@datadog/browser-core/test'\nimport {\n  NodePrivacyLevel,\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_ALLOW,\n  PRIVACY_ATTR_VALUE_HIDDEN,\n  PRIVACY_ATTR_VALUE_MASK,\n  PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n  PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED,\n  isAllowlisted,\n} from '@datadog/browser-rum-core'\nimport type { SerializedNodeWithId } from '../../../types'\nimport { NodeType } from '../../../types'\nimport { appendElement } from '../../../../../rum-core/test'\nimport type { AddShadowRootCallBack } from '../shadowRootsController'\nimport {\n  createSerializationTransactionForTesting,\n  serializeNodeAndVerifyChangeRecord as serializeNode,\n} from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport {\n  HTML,\n  generateLeanSerializedDoc,\n  AST_HIDDEN,\n  AST_MASK,\n  AST_MASK_USER_INPUT,\n  AST_MASK_UNLESS_ALLOWLISTED,\n  AST_ALLOW,\n} from './htmlAst.specHelper'\nimport { serializeChildNodes, serializeDocumentNode } from './serializeNode'\nimport type { SerializationStats } from './serializationStats'\nimport { createSerializationStats } from './serializationStats'\nimport type { SerializationTransaction } from './serializationTransaction'\nimport { serializeInTransaction, SerializationKind } from './serializationTransaction'\n\ndescribe('serializeNode', () => {\n  let addShadowRootSpy: jasmine.Spy<AddShadowRootCallBack>\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let emitStatsCallback: jasmine.Spy<EmitStatsCallback>\n  let scope: RecordingScope\n  let transaction: SerializationTransaction\n\n  beforeEach(() => {\n    addShadowRootSpy = jasmine.createSpy()\n    emitRecordCallback = jasmine.createSpy()\n    emitStatsCallback = jasmine.createSpy()\n    scope = createRecordingScopeForTesting({ addShadowRoot: addShadowRootSpy })\n    transaction = createSerializationTransactionForTesting({ scope })\n  })\n\n  describe('document serialization', () => {\n    it('serializes a document', () => {\n      const document = new DOMParser().parseFromString('<!doctype html><html>foo</html>', 'text/html')\n      expect(serializeNode(document, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Document,\n        childNodes: [\n          jasmine.objectContaining({ type: NodeType.DocumentType, name: 'html', publicId: '', systemId: '' }),\n          jasmine.objectContaining({ type: NodeType.Element, tagName: 'html' }),\n        ],\n        adoptedStyleSheets: undefined,\n        id: jasmine.any(Number) as unknown as number,\n      })\n    })\n  })\n\n  describe('elements serialization', () => {\n    it('serializes a div', () => {\n      expect(serializeNode(document.createElement('div'), NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Element,\n        tagName: 'div',\n        attributes: {},\n        isSVG: undefined,\n        childNodes: [],\n        id: jasmine.any(Number),\n      })\n    })\n\n    it('serializes SVG elements', () => {\n      const svgElement = appendSubtree(\n        `\n          <svg viewBox=\"0 0 100 100\">\n            <clipPath id=\"myClip\">\n              <circle cx=\"40\" cy=\"35\" r=\"35\" />\n            </clipPath>\n            <path\n              id=\"heart\"\n              d=\"M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z\" />\n            <use clip-path=\"url(#myClip)\" href=\"#heart\" fill=\"red\" />\n          </svg>\n        `\n      )\n      expect(serializeNode(svgElement, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Element,\n        id: 0,\n        tagName: 'svg',\n        attributes: { viewBox: '0 0 100 100' },\n        isSVG: true,\n        childNodes: [\n          {\n            type: NodeType.Element,\n            id: 1,\n            tagName: 'clippath',\n            attributes: { id: 'myClip' },\n            isSVG: true,\n            childNodes: [\n              {\n                type: NodeType.Element,\n                id: 2,\n                tagName: 'circle',\n                attributes: { cx: '40', cy: '35', r: '35' },\n                isSVG: true,\n                childNodes: [],\n              },\n            ],\n          },\n          {\n            type: NodeType.Element,\n            id: 3,\n            tagName: 'path',\n            attributes: {\n              id: 'heart',\n              d: 'M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z',\n            },\n            isSVG: true,\n            childNodes: [],\n          },\n          {\n            type: NodeType.Element,\n            id: 4,\n            tagName: 'use',\n            attributes: {\n              'clip-path': 'url(#myClip)',\n              href: '#heart',\n              fill: 'red',\n            },\n            isSVG: true,\n            childNodes: [],\n          },\n        ],\n      })\n    })\n\n    it('serializes hidden elements', () => {\n      const element = document.createElement('div')\n      element.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_HIDDEN)\n\n      expect(serializeNode(element, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Element,\n        tagName: 'div',\n        attributes: {\n          rr_width: '0px',\n          rr_height: '0px',\n          [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_HIDDEN,\n        },\n        isSVG: undefined,\n        childNodes: [],\n        id: jasmine.any(Number),\n      })\n    })\n\n    it('does not serialize hidden element children', () => {\n      const element = document.createElement('div')\n      element.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_HIDDEN)\n      element.appendChild(document.createElement('hr'))\n      expect(serializeNode(element, NodePrivacyLevel.ALLOW, transaction)?.childNodes).toEqual([])\n    })\n\n    it('serializes attributes', () => {\n      const element = appendElement('<div foo=\"bar\" data-foo=\"data-bar\"></div>')\n      element.className = 'zog'\n      element.style.width = '10px'\n\n      expect(serializeNode(element, NodePrivacyLevel.ALLOW, transaction)?.attributes).toEqual({\n        foo: 'bar',\n        'data-foo': 'data-bar',\n        class: 'zog',\n        style: 'width: 10px;',\n      })\n    })\n\n    describe('rr scroll attributes', () => {\n      const elementStyle = 'width: 100px; height: 100px; overflow: scroll'\n      const createScrolledElement = (x: number, y: number): Element => {\n        const element = appendElement(\n          `<div style=\"${elementStyle}\"><div style=\"width: 200px; height: 200px\"></div></div>`\n        )\n        element.scrollBy(x, y)\n        return element\n      }\n\n      it('should be retrieved from attributes during initial full snapshot', () => {\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.INITIAL_FULL_SNAPSHOT,\n          scope,\n        })\n        const element = createScrolledElement(10, 20)\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes).toEqual(\n          jasmine.objectContaining({\n            rr_scrollLeft: 10,\n            rr_scrollTop: 20,\n          })\n        )\n        expect(scope.elementsScrollPositions.get(element)).toEqual({ scrollLeft: 10, scrollTop: 20 })\n      })\n\n      it('does not serialize rr_scrollLeft if it would be zero', () => {\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.INITIAL_FULL_SNAPSHOT,\n          scope,\n        })\n        const element = createScrolledElement(0, 20)\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes).toEqual({\n          rr_scrollTop: 20,\n          style: elementStyle,\n        })\n        expect(scope.elementsScrollPositions.get(element)).toEqual({ scrollLeft: 0, scrollTop: 20 })\n      })\n\n      it('does not serialize rr_scrollTop if it would be zero', () => {\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.INITIAL_FULL_SNAPSHOT,\n          scope,\n        })\n        const element = createScrolledElement(10, 0)\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes).toEqual({\n          rr_scrollLeft: 10,\n          style: elementStyle,\n        })\n        expect(scope.elementsScrollPositions.get(element)).toEqual({ scrollLeft: 10, scrollTop: 0 })\n      })\n\n      it('does not serialize any rr_scroll attributes if the element is not scrolled', () => {\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.INITIAL_FULL_SNAPSHOT,\n          scope,\n        })\n        const element = createScrolledElement(0, 0)\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes).toEqual({\n          style: elementStyle,\n        })\n        expect(scope.elementsScrollPositions.get(element)).toEqual(undefined)\n      })\n\n      it('should not be retrieved from attributes during subsequent full snapshot', () => {\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.SUBSEQUENT_FULL_SNAPSHOT,\n          scope,\n        })\n        const element = createScrolledElement(10, 20)\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes.rr_scrollLeft).toBeUndefined()\n        expect(serializedNode?.attributes.rr_scrollTop).toBeUndefined()\n        expect(scope.elementsScrollPositions.get(element)).toBeUndefined()\n      })\n\n      it('should be retrieved from elementsScrollPositions during subsequent full snapshot', () => {\n        const element = createScrolledElement(10, 20)\n        scope.elementsScrollPositions.set(element, { scrollLeft: 10, scrollTop: 20 })\n\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.SUBSEQUENT_FULL_SNAPSHOT,\n          scope,\n        })\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes).toEqual(\n          jasmine.objectContaining({\n            rr_scrollLeft: 10,\n            rr_scrollTop: 20,\n          })\n        )\n      })\n\n      it('should not be retrieved during mutation', () => {\n        const element = createScrolledElement(10, 20)\n        scope.elementsScrollPositions.set(element, { scrollLeft: 10, scrollTop: 20 })\n\n        const transaction = createSerializationTransactionForTesting({\n          kind: SerializationKind.INCREMENTAL_SNAPSHOT,\n          scope,\n        })\n        const serializedNode = serializeNode(element, NodePrivacyLevel.ALLOW, transaction)\n\n        expect(serializedNode?.attributes.rr_scrollLeft).toBeUndefined()\n        expect(serializedNode?.attributes.rr_scrollTop).toBeUndefined()\n      })\n    })\n\n    it('ignores white space in <head>', () => {\n      const head = document.createElement('head')\n      head.innerHTML = '  <title>  foo </title>  '\n\n      expect(serializeNode(head, NodePrivacyLevel.ALLOW, transaction)?.childNodes).toEqual([\n        jasmine.objectContaining({\n          type: NodeType.Element,\n          tagName: 'title',\n          childNodes: [jasmine.objectContaining({ type: NodeType.Text, textContent: '  foo ' })],\n        }),\n      ])\n    })\n\n    it('serializes <input> text elements value', () => {\n      const input = document.createElement('input')\n      input.value = 'toto'\n\n      expect(serializeNode(input, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: { value: 'toto' },\n        })\n      )\n    })\n\n    it('serializes <textarea> elements value', () => {\n      const textarea = document.createElement('textarea')\n      textarea.value = 'toto'\n\n      expect(serializeNode(textarea, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: { value: 'toto' },\n        })\n      )\n    })\n\n    it('serializes <select> elements value and selected state', () => {\n      const select = document.createElement('select')\n      const option1 = document.createElement('option')\n      option1.value = 'foo'\n      select.appendChild(option1)\n      const option2 = document.createElement('option')\n      option2.value = 'bar'\n      select.appendChild(option2)\n      select.options.selectedIndex = 1\n\n      expect(serializeNode(select, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: { value: 'bar' },\n          childNodes: [\n            jasmine.objectContaining({\n              attributes: {\n                value: 'foo',\n              },\n            }),\n            jasmine.objectContaining({\n              attributes: {\n                value: 'bar',\n                selected: '',\n              },\n            }),\n          ],\n        })\n      )\n    })\n\n    it('does not serialize <input type=\"password\"> values set via property setter', () => {\n      const input = document.createElement('input')\n      input.type = 'password'\n      input.value = 'toto'\n\n      expect(serializeNode(input, NodePrivacyLevel.ALLOW, transaction)).toEqual(jasmine.objectContaining({}))\n    })\n\n    it('does not serialize <input type=\"password\"> values set via attribute setter', () => {\n      const input = document.createElement('input')\n      input.type = 'password'\n      input.setAttribute('value', 'toto')\n\n      expect(serializeNode(input, NodePrivacyLevel.ALLOW, transaction)).toEqual(jasmine.objectContaining({}))\n    })\n\n    it('serializes <input type=\"checkbox\"> elements checked state', () => {\n      const checkbox = document.createElement('input')\n      checkbox.type = 'checkbox'\n      expect(serializeNode(checkbox, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: {\n            type: 'checkbox',\n            value: 'on',\n          },\n        })\n      )\n\n      checkbox.checked = true\n\n      expect(serializeNode(checkbox, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: {\n            type: 'checkbox',\n            value: 'on',\n            checked: '',\n          },\n        })\n      )\n    })\n\n    it('serializes <input type=\"radio\"> elements checked state', () => {\n      const radio = document.createElement('input')\n      radio.type = 'radio'\n      expect(serializeNode(radio, NodePrivacyLevel.ALLOW, transaction)?.attributes).toEqual({\n        type: 'radio',\n        value: 'on',\n      })\n\n      radio.checked = true\n\n      expect(serializeNode(radio, NodePrivacyLevel.ALLOW, transaction)?.attributes).toEqual({\n        type: 'radio',\n        value: 'on',\n        checked: '',\n      })\n    })\n\n    it('serializes <audio> elements paused state', () => {\n      const audio = document.createElement('audio')\n\n      expect(serializeNode(audio, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: { rr_mediaState: 'paused' },\n        })\n      )\n\n      // Emulate a playing audio file\n      Object.defineProperty(audio, 'paused', { value: false })\n\n      expect(serializeNode(audio, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: { rr_mediaState: 'played' },\n        })\n      )\n    })\n\n    describe('input privacy mode mask-user-input', () => {\n      it('replaces <input> values with asterisks', () => {\n        const input = document.createElement('input')\n        input.value = 'toto'\n        input.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n        expect(serializeNode(input, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n          jasmine.objectContaining({\n            attributes: {\n              [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n              value: '***',\n            },\n          })\n        )\n      })\n\n      it('respects ancestor privacy mode', () => {\n        const parent = document.createElement('div')\n        const input = document.createElement('input')\n        input.value = 'toto'\n        parent.appendChild(input)\n        parent.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n        expect(serializeNode(parent, NodePrivacyLevel.ALLOW, transaction)?.childNodes[0]).toEqual(\n          jasmine.objectContaining({\n            attributes: { value: '***' },\n          })\n        )\n      })\n\n      it('does not apply mask for <input type=\"button\">', () => {\n        const button = document.createElement('input')\n        button.type = 'button'\n        button.value = 'toto'\n        button.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n        expect(serializeNode(button, NodePrivacyLevel.ALLOW, transaction)?.attributes.value).toEqual('toto')\n      })\n\n      it('does not apply mask for <input type=\"submit\"> contained in a masked ancestor', () => {\n        const button = document.createElement('input')\n        button.type = 'submit'\n        button.value = 'toto'\n        button.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n        expect(serializeNode(button, NodePrivacyLevel.ALLOW, transaction)?.attributes.value).toEqual('toto')\n      })\n\n      it('serializes <input type=\"radio\"> elements without checked property', () => {\n        const radio = document.createElement('input')\n        radio.type = 'radio'\n        radio.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n        expect(serializeNode(radio, NodePrivacyLevel.ALLOW, transaction)?.attributes).toEqual({\n          type: 'radio',\n          value: '***',\n          'data-dd-privacy': 'mask-user-input',\n        })\n\n        radio.checked = true\n\n        expect(serializeNode(radio, NodePrivacyLevel.ALLOW, transaction)?.attributes).toEqual({\n          type: 'radio',\n          value: '***',\n          'data-dd-privacy': 'mask-user-input',\n        })\n      })\n    })\n\n    describe('input privacy mode mask', () => {\n      it('applies mask for <input placeholder=\"someValue\" /> value', () => {\n        const input = document.createElement('input')\n        input.placeholder = 'someValue'\n        input.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n\n        expect(serializeNode(input, NodePrivacyLevel.ALLOW, transaction)?.attributes.placeholder).toEqual('***')\n      })\n    })\n\n    describe('input privacy mode mask-unless-allowlisted', () => {\n      beforeEach(() => {\n        ;(window as BrowserWindow).$DD_ALLOW = new Set(['allowlisted value', 'hello'])\n      })\n\n      afterEach(() => {\n        ;(window as BrowserWindow).$DD_ALLOW = undefined\n      })\n\n      it('should behave like mask-user-input', () => {\n        const input = document.createElement('input')\n        input.value = 'toto'\n        input.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED)\n\n        expect(serializeNode(input, NodePrivacyLevel.ALLOW, transaction)).toEqual(jasmine.objectContaining({}))\n      })\n    })\n\n    describe('shadow dom', () => {\n      it('serializes a shadow host', () => {\n        const div = document.createElement('div')\n        div.attachShadow({ mode: 'open' })\n        expect(serializeNode(div, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'div',\n          attributes: {},\n          isSVG: undefined,\n          childNodes: [\n            {\n              type: NodeType.DocumentFragment,\n              isShadowRoot: true,\n              childNodes: [],\n              id: jasmine.any(Number) as unknown as number,\n              adoptedStyleSheets: undefined,\n            },\n          ],\n          id: jasmine.any(Number) as unknown as number,\n        })\n      })\n\n      it('serializes a shadow host with children', () => {\n        const div = document.createElement('div')\n        const shadowRoot = div.attachShadow({ mode: 'open' })\n        shadowRoot.appendChild(document.createElement('hr'))\n\n        expect(serializeNode(div, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'div',\n          attributes: {},\n          isSVG: undefined,\n          childNodes: [\n            {\n              type: NodeType.DocumentFragment,\n              isShadowRoot: true,\n              adoptedStyleSheets: undefined,\n              childNodes: [\n                {\n                  type: NodeType.Element,\n                  tagName: 'hr',\n                  attributes: {},\n                  isSVG: undefined,\n                  childNodes: [],\n                  id: jasmine.any(Number) as unknown as number,\n                },\n              ],\n              id: jasmine.any(Number) as unknown as number,\n            },\n          ],\n          id: jasmine.any(Number) as unknown as number,\n        })\n        expect(addShadowRootSpy).toHaveBeenCalledWith(shadowRoot, jasmine.anything())\n      })\n\n      it('propagates the privacy mode to the shadow root children', () => {\n        const div = document.createElement('div')\n        div.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n        const shadowRoot = div.attachShadow({ mode: 'open' })\n        shadowRoot.appendChild(document.createTextNode('foo'))\n\n        expect(serializeNode(div, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n          jasmine.objectContaining({\n            attributes: {\n              [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_MASK,\n            },\n            childNodes: [\n              jasmine.objectContaining({\n                childNodes: [\n                  jasmine.objectContaining({\n                    textContent: 'xxx',\n                  }),\n                ],\n              }),\n            ],\n          })\n        )\n      })\n    })\n\n    describe('<style> elements', () => {\n      let stats: SerializationStats\n      let transaction: SerializationTransaction\n\n      beforeEach(() => {\n        stats = createSerializationStats()\n        transaction = createSerializationTransactionForTesting({ stats, scope })\n      })\n\n      it('serializes a node with dynamically edited CSS rules', () => {\n        const styleNode = appendElement('<style></style>', document.head) as HTMLStyleElement\n        styleNode.sheet!.insertRule('body { width: 100%; }')\n\n        expect(serializeNode(styleNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'style',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: { _cssText: 'body { width: 100%; }' },\n          childNodes: [],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 1, max: 21, sum: 21 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n\n      it('serializes a node with CSS rules specified as inner text', () => {\n        const styleNode = appendElement('<style>body { width: 100%; }</style>', document.head) as HTMLStyleElement\n\n        expect(serializeNode(styleNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'style',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: { _cssText: 'body { width: 100%; }' },\n          childNodes: [],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 1, max: 21, sum: 21 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n\n      it('serializes a node with CSS rules specified as inner text then dynamically edited', () => {\n        const styleNode = appendElement('<style>body { width: 100%; }</style>', document.head) as HTMLStyleElement\n        styleNode.sheet!.insertRule('body { color: red; }')\n\n        expect(serializeNode(styleNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'style',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: { _cssText: 'body { color: red; }body { width: 100%; }' },\n          childNodes: [],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 1, max: 41, sum: 41 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n\n      it('serializes a subtree with multiple nodes', () => {\n        const containerNode = appendElement('<div></div>', document.body) as HTMLDivElement\n\n        const cssText1 = 'body { width: 100%; }'\n        appendElement(`<style>${cssText1}</style>`, containerNode) as HTMLStyleElement\n\n        const cssText2 = 'body { background-color: green; }'\n        appendElement(`<style>${cssText2}</style>`, containerNode) as HTMLStyleElement\n\n        expect(serializeNode(containerNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'div',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: {},\n          childNodes: [\n            {\n              type: NodeType.Element,\n              tagName: 'style',\n              id: jasmine.any(Number) as unknown as number,\n              isSVG: undefined,\n              attributes: { _cssText: cssText1 },\n              childNodes: [],\n            },\n            {\n              type: NodeType.Element,\n              tagName: 'style',\n              id: jasmine.any(Number) as unknown as number,\n              isSVG: undefined,\n              attributes: { _cssText: cssText2 },\n              childNodes: [],\n            },\n          ],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 2, max: 33, sum: 54 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n    })\n\n    describe('<link rel=\"stylesheet\"> elements', () => {\n      let stats: SerializationStats\n      let transaction: SerializationTransaction\n\n      beforeEach(() => {\n        stats = createSerializationStats()\n        transaction = createSerializationTransactionForTesting({ stats, scope })\n      })\n\n      afterEach(() => {\n        // styleSheets is part of the document prototype so we can safely delete it\n        delete (document as { styleSheets?: StyleSheetList }).styleSheets\n      })\n\n      it('does not inline external CSS if it cannot be fetched', () => {\n        const linkNode = appendElement(\n          \"<link rel='stylesheet' href='https://datadoghq.com/some/style.css' />\",\n          document.head\n        )\n\n        expect(serializeNode(linkNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'link',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: { rel: 'stylesheet', href: 'https://datadoghq.com/some/style.css' },\n          childNodes: [],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 0, max: 0, sum: 0 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n\n      it('inlines external CSS it can be fetched', () => {\n        const linkNode = appendElement(\n          \"<link rel='stylesheet' href='https://datadoghq.com/some/style.css' />\",\n          document.head\n        )\n\n        const styleSheet = {\n          href: 'https://datadoghq.com/some/style.css',\n          cssRules: [{ cssText: 'body { width: 100%; }' }],\n        }\n        Object.defineProperty(document, 'styleSheets', {\n          value: [styleSheet],\n          configurable: true,\n        })\n        Object.defineProperty(linkNode, 'sheet', {\n          value: styleSheet,\n          configurable: true,\n        })\n\n        expect(serializeNode(linkNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'link',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: {\n            _cssText: 'body { width: 100%; }',\n            rel: 'stylesheet',\n            href: 'https://datadoghq.com/some/style.css',\n          },\n          childNodes: [],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 1, max: 21, sum: 21 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n\n      it('does not inline external CSS if the style sheet is behind CORS', () => {\n        const linkNode = appendElement(\n          \"<link rel='stylesheet' href='https://datadoghq.com/some/style.css' />\",\n          document.head\n        )\n        class FakeCSSStyleSheet {\n          get cssRules() {\n            return []\n          }\n        }\n        const styleSheet = new FakeCSSStyleSheet()\n        spyOnProperty(styleSheet, 'cssRules', 'get').and.throwError(new DOMException('cors issue', 'SecurityError'))\n\n        Object.defineProperty(document, 'styleSheets', {\n          value: [styleSheet],\n          configurable: true,\n        })\n\n        expect(serializeNode(linkNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n          type: NodeType.Element,\n          tagName: 'link',\n          id: jasmine.any(Number) as unknown as number,\n          isSVG: undefined,\n          attributes: {\n            rel: 'stylesheet',\n            href: 'https://datadoghq.com/some/style.css',\n          },\n          childNodes: [],\n        })\n        expect(stats).toEqual({\n          cssText: { count: 0, max: 0, sum: 0 },\n          serializationDuration: jasmine.anything(),\n        })\n      })\n    })\n  })\n\n  describe('text nodes serialization', () => {\n    it('serializes a text node', () => {\n      const parentEl = document.createElement('bar')\n      parentEl.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_ALLOW)\n      const textNode = document.createTextNode('foo')\n      parentEl.appendChild(textNode)\n      expect(serializeNode(textNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Text,\n        id: jasmine.any(Number) as unknown as number,\n        textContent: 'foo',\n      })\n    })\n\n    it('serializes an empty text node', () => {\n      const parentEl = document.createElement('bar')\n      const textNode = document.createTextNode('')\n      parentEl.appendChild(textNode)\n      expect(serializeNode(textNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Text,\n        id: jasmine.any(Number) as unknown as number,\n        textContent: '',\n      })\n    })\n\n    it('does not serialize text nodes with only white space if the parent is a HEAD element', () => {\n      const head = document.getElementsByTagName('head')[0]\n      const textNode = document.createTextNode('   ')\n      head.appendChild(textNode)\n      expect(serializeNode(textNode, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n      head.removeChild(textNode)\n    })\n  })\n\n  describe('CDATA nodes serialization', () => {\n    it('serializes a CDATA node', () => {\n      const xmlDocument = new DOMParser().parseFromString('<root></root>', 'text/xml')\n      const cdataNode = xmlDocument.createCDATASection('foo')\n      expect(serializeNode(cdataNode, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.CDATA,\n        id: jasmine.any(Number) as unknown as number,\n        textContent: '',\n      })\n    })\n  })\n\n  it('adds serialized node ids to the provided Set', () => {\n    serializeInTransaction(\n      SerializationKind.INITIAL_FULL_SNAPSHOT,\n      emitRecordCallback,\n      emitStatsCallback,\n      scope,\n      (transaction) => {\n        transaction.serializedNodeIds = new Set()\n        const node = serializeNode(document.createElement('div'), NodePrivacyLevel.ALLOW, transaction)!\n        expect(transaction.serializedNodeIds).toEqual(new Set([node.id]))\n        return []\n      }\n    )\n  })\n\n  describe('ignores some nodes', () => {\n    it('does not save ignored nodes in the serializedNodeIds set', () => {\n      serializeInTransaction(\n        SerializationKind.INITIAL_FULL_SNAPSHOT,\n        emitRecordCallback,\n        emitStatsCallback,\n        scope,\n        (transaction) => {\n          transaction.serializedNodeIds = new Set()\n          serializeNode(document.createElement('script'), NodePrivacyLevel.ALLOW, transaction)\n          expect(transaction.serializedNodeIds.size).toBe(0)\n          return []\n        }\n      )\n    })\n\n    it('does not serialize ignored nodes', () => {\n      const scriptElement = document.createElement('script')\n      expect(serializeNode(scriptElement, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n      expect(scope.nodeIds.get(scriptElement)).toBe(undefined)\n    })\n\n    it('ignores script tags', () => {\n      const scriptElement = document.createElement('script')\n      expect(serializeNode(scriptElement, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n    })\n\n    it('ignores comments', () => {\n      const commentNode = document.createComment('foo')\n      expect(serializeNode(commentNode, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n    })\n\n    it('ignores link favicons', () => {\n      const linkElement = document.createElement('link')\n      linkElement.setAttribute('rel', 'shortcut icon')\n      expect(serializeNode(linkElement, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n    })\n\n    it('ignores meta keywords', () => {\n      const metaElement = document.createElement('meta')\n      metaElement.setAttribute('name', 'keywords')\n      expect(serializeNode(metaElement, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n    })\n\n    it('ignores meta name attribute casing', () => {\n      const metaElement = document.createElement('meta')\n      metaElement.setAttribute('name', 'KeYwOrDs')\n      expect(serializeNode(metaElement, NodePrivacyLevel.ALLOW, transaction)).toBeNull()\n    })\n  })\n\n  describe('handles privacy', () => {\n    describe('for privacy tag `hidden`, a DOM tree', () => {\n      it('does not include any private info', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'hidden')\n        expect(JSON.stringify(serializedDoc)).not.toContain('private')\n      })\n    })\n\n    describe('for privacy tag `mask`, a DOM tree', () => {\n      it('obfuscates all text content', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask')\n        for (const textContents of getAllTextContents(serializedDoc)) {\n          expect(textContents).toEqual(jasmine.stringMatching(/^[*x\\s]*$/))\n        }\n      })\n\n      it('obfuscates attributes and text content', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask')\n        expect(JSON.stringify(serializedDoc)).not.toContain('private')\n      })\n    })\n\n    describe('for privacy tag `mask-user-input`, a DOM tree', () => {\n      it('does not obfuscate text content', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-user-input')\n        expect(JSON.stringify(serializedDoc)).not.toContain('᙮᙮')\n      })\n\n      it('obfuscates input fields', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-user-input')\n        expect(JSON.stringify(serializedDoc)).toContain('**')\n      })\n    })\n\n    describe('for privacy tag `mask-unless-allowlisted`, a DOM tree', () => {\n      beforeEach(() => {\n        ;(window as BrowserWindow).$DD_ALLOW = new Set(['private title', 'hello private world'])\n      })\n\n      afterEach(() => {\n        ;(window as BrowserWindow).$DD_ALLOW = undefined\n      })\n\n      it('obfuscates text content not in allowlist', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n        const textContents = getAllTextContents(serializedDoc)\n        for (const textContent of textContents) {\n          if (isAllowlisted(textContent)) {\n            expect(textContent).not.toEqual(jasmine.stringMatching(/^[x*]+$/))\n          } else {\n            expect(textContent).toEqual(jasmine.stringMatching(/^[x\\s*]*$/))\n          }\n        }\n      })\n\n      it('preserves text content in allowlist', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n        // Allowlisted content should be preserved\n        expect(JSON.stringify(serializedDoc)).toContain('private title')\n        expect(JSON.stringify(serializedDoc)).toContain('hello private world')\n      })\n\n      it('obfuscates input fields not in allowlist', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n        expect(JSON.stringify(serializedDoc)).toContain('***')\n      })\n\n      it('obfuscates attributes and non-allowlisted text content', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n        const attributeValues = getAllAttributeValues(serializedDoc)\n        for (const attributeValue of attributeValues) {\n          if (isAllowlisted(attributeValue)) {\n            expect(attributeValue).not.toEqual(jasmine.stringMatching(/^[x\\s*]*$/))\n          } else {\n            expect(attributeValue).toEqual(jasmine.stringMatching(/^[x\\s*]*$/))\n          }\n        }\n      })\n\n      it('fails closed when allowlist is empty', () => {\n        ;(window as BrowserWindow).$DD_ALLOW = new Set()\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n\n        // All text content should be masked\n        const textContents = getAllTextContents(serializedDoc)\n        for (const textContent of textContents) {\n          if (textContent.trim()) {\n            expect(textContent).toEqual(jasmine.stringMatching(/^[x\\s*]*$/))\n          }\n        }\n      })\n\n      it('fails closed when allowlist is undefined', () => {\n        ;(window as BrowserWindow).$DD_ALLOW = undefined\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n\n        // All text content should be masked\n        const textContents = getAllTextContents(serializedDoc)\n        for (const textContent of textContents) {\n          expect(textContent).toEqual(jasmine.stringMatching(/^[x\\s*]*$/))\n        }\n      })\n    })\n\n    describe('for privacy tag `allow`, a DOM tree', () => {\n      it('does not obfuscate anything', () => {\n        const serializedDoc = generateLeanSerializedDoc(HTML, 'allow')\n        expect(JSON.stringify(serializedDoc)).not.toContain('*')\n        expect(JSON.stringify(serializedDoc)).not.toContain('xx')\n      })\n    })\n\n    function getAllTextContents(serializedNode: SerializedNodeWithId): string[] {\n      if (serializedNode.type === NodeType.Text) {\n        return [serializedNode.textContent.trim()]\n      }\n      if ('childNodes' in serializedNode) {\n        return serializedNode.childNodes.reduce<string[]>(\n          (result, child) => result.concat(getAllTextContents(child)),\n          []\n        )\n      }\n      return []\n    }\n\n    function getAllAttributeValues(serializedNode: SerializedNodeWithId): string[] {\n      if (serializedNode.type === NodeType.Element) {\n        // Exclude attributes that are privacy tags\n        return Object.entries(serializedNode.attributes)\n          .filter(([key]) => !key.startsWith(PRIVACY_ATTR_NAME))\n          .map(([, value]) => String(value))\n      }\n      if ('childNodes' in serializedNode) {\n        return serializedNode.childNodes.reduce<string[]>(\n          (result, child) => result.concat(getAllAttributeValues(child)),\n          []\n        )\n      }\n      return []\n    }\n  })\n})\n\ndescribe('serializeDocumentNode handles', function testAllowDomTree() {\n  const toJSONObj = (data: any) => JSON.parse(JSON.stringify(data)) as unknown\n  let stats: SerializationStats\n  let transaction: SerializationTransaction\n\n  beforeEach(() => {\n    stats = createSerializationStats()\n    transaction = createSerializationTransactionForTesting({ stats })\n    registerCleanupTask(() => {\n      if (isAdoptedStyleSheetsSupported()) {\n        document.adoptedStyleSheets = []\n      }\n    })\n  })\n\n  describe('with dynamic stylesheet', () => {\n    it('serializes a document with adoptedStyleSheets', () => {\n      if (!isAdoptedStyleSheetsSupported()) {\n        pending('no adoptedStyleSheets support')\n      }\n\n      const styleSheet = new window.CSSStyleSheet()\n      styleSheet.insertRule('div { width: 100%; }')\n      document.adoptedStyleSheets = [styleSheet]\n\n      expect(serializeDocumentNode(document, NodePrivacyLevel.ALLOW, transaction)).toEqual({\n        type: NodeType.Document,\n        id: 0,\n        childNodes: [\n          jasmine.objectContaining({ type: NodeType.DocumentType }),\n          jasmine.objectContaining({ type: NodeType.Element, tagName: 'html' }),\n        ],\n        adoptedStyleSheets: [\n          {\n            cssRules: ['div { width: 100%; }'],\n            disabled: undefined,\n            media: undefined,\n          },\n        ],\n      })\n      expect(stats.cssText).toEqual({ count: 1, max: 20, sum: 20 })\n    })\n  })\n\n  it('a masked DOM Document itself is still serialized ', () => {\n    expect(serializeDocumentNode(document, NodePrivacyLevel.MASK, transaction)).toEqual({\n      type: NodeType.Document,\n      id: 0,\n      childNodes: serializeChildNodes(document, NodePrivacyLevel.MASK, transaction),\n      adoptedStyleSheets: undefined,\n    })\n  })\n\n  describe('for privacy tag `hidden`, a DOM tree', function testHiddenDomTree() {\n    it('is serialized correctly', () => {\n      const serializedDoc = generateLeanSerializedDoc(HTML, 'hidden')\n      expect(toJSONObj(serializedDoc)).toEqual(AST_HIDDEN)\n    })\n  })\n\n  describe('for privacy tag `mask`, a DOM tree', function testMaskDomTree() {\n    it('is serialized correctly', () => {\n      const serializedDoc = generateLeanSerializedDoc(HTML, 'mask')\n      expect(toJSONObj(serializedDoc)).toEqual(AST_MASK)\n    })\n  })\n\n  describe('for privacy tag `mask-user-input`, a DOM tree', function testMaskFormsOnlyDomTree() {\n    it('is serialized correctly', () => {\n      const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-user-input')\n      expect(toJSONObj(serializedDoc)).toEqual(AST_MASK_USER_INPUT)\n    })\n  })\n\n  describe('for privacy tag `mask-unless-allowlisted`, a DOM tree', function testMaskUnlessAllowlistedDomTree() {\n    it('is serialized correctly when no allowlist is provided', () => {\n      const serializedDoc = generateLeanSerializedDoc(HTML, 'mask-unless-allowlisted')\n      expect(toJSONObj(serializedDoc)).toEqual(AST_MASK_UNLESS_ALLOWLISTED)\n    })\n  })\n\n  describe('for privacy tag `allow`, a DOM tree', function testAllowDomTree() {\n    it('is serialized correctly', () => {\n      const serializedDoc = generateLeanSerializedDoc(HTML, 'allow')\n      expect(toJSONObj(serializedDoc)).toEqual(AST_ALLOW)\n    })\n  })\n})\n\nfunction appendSubtree(html: string): Element {\n  return appendElement(html.replace(/(^|\\n)\\s+/g, ' ').replace(/> </g, '><'))\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNode.ts",
    "content": "import {\n  reducePrivacyLevel,\n  getNodeSelfPrivacyLevel,\n  getTextContent,\n  isNodeShadowRoot,\n  hasChildNodes,\n  forEachChildNodes,\n  NodePrivacyLevel,\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_HIDDEN,\n} from '@datadog/browser-rum-core'\nimport type {\n  DocumentFragmentNode,\n  DocumentNode,\n  SerializedNodeWithId,\n  CDataNode,\n  DocumentTypeNode,\n  ElementNode,\n  TextNode,\n} from '../../../types'\nimport { NodeType } from '../../../types'\nimport { getValidTagName } from './serializationUtils'\nimport type { ParentNodePrivacyLevel } from './serialization.types'\nimport { serializeStyleSheets } from './serializeStyleSheets'\nimport { serializeAttributes } from './serializeAttributes'\nimport type { SerializationTransaction } from './serializationTransaction'\n\nexport function serializeNode(\n  node: Element,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): (SerializedNodeWithId & ElementNode) | null\nexport function serializeNode(\n  node: Node,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): SerializedNodeWithId | null\nexport function serializeNode(\n  node: Node,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): SerializedNodeWithId | null {\n  switch (node.nodeType) {\n    case node.DOCUMENT_NODE:\n      return serializeDocumentNode(node as Document, parentNodePrivacyLevel, transaction)\n    case node.DOCUMENT_FRAGMENT_NODE:\n      return serializeDocumentFragmentNode(node as DocumentFragment, parentNodePrivacyLevel, transaction)\n    case node.DOCUMENT_TYPE_NODE:\n      return serializeDocumentTypeNode(node as DocumentType, transaction)\n    case node.ELEMENT_NODE:\n      return serializeElementNode(node as Element, parentNodePrivacyLevel, transaction)\n    case node.TEXT_NODE:\n      return serializeTextNode(node as Text, parentNodePrivacyLevel, transaction)\n    case node.CDATA_SECTION_NODE:\n      return serializeCDataNode(node as CDATASection, transaction)\n    default:\n      return null\n  }\n}\n\nexport function serializeChildNodes(\n  node: Node,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): SerializedNodeWithId[] {\n  const result: SerializedNodeWithId[] = []\n  forEachChildNodes(node, (childNode) => {\n    const serializedChildNode = serializeNode(childNode, parentNodePrivacyLevel, transaction)\n    if (serializedChildNode) {\n      result.push(serializedChildNode)\n    }\n  })\n  return result\n}\n\nexport function serializeDocumentNode(\n  document: Document,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): DocumentNode & SerializedNodeWithId {\n  return {\n    type: NodeType.Document,\n    id: transaction.assignId(document),\n    childNodes: serializeChildNodes(document, parentNodePrivacyLevel, transaction),\n    adoptedStyleSheets: serializeStyleSheets(document.adoptedStyleSheets, transaction),\n  }\n}\n\nfunction serializeDocumentFragmentNode(\n  element: DocumentFragment,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): DocumentFragmentNode & SerializedNodeWithId {\n  const isShadowRoot = isNodeShadowRoot(element)\n  if (isShadowRoot) {\n    transaction.scope.shadowRootsController.addShadowRoot(element, transaction.scope)\n  }\n\n  return {\n    type: NodeType.DocumentFragment,\n    id: transaction.assignId(element),\n    childNodes: serializeChildNodes(element, parentNodePrivacyLevel, transaction),\n    isShadowRoot,\n    adoptedStyleSheets: isShadowRoot ? serializeStyleSheets(element.adoptedStyleSheets, transaction) : undefined,\n  }\n}\n\nfunction serializeDocumentTypeNode(\n  documentType: DocumentType,\n  transaction: SerializationTransaction\n): DocumentTypeNode & SerializedNodeWithId {\n  return {\n    type: NodeType.DocumentType,\n    id: transaction.assignId(documentType),\n    name: documentType.name,\n    publicId: documentType.publicId,\n    systemId: documentType.systemId,\n  }\n}\n\n/**\n * Serializing Element nodes involves capturing:\n * 1. HTML ATTRIBUTES:\n * 2. JS STATE:\n * - scroll offsets\n * - Form fields (input value, checkbox checked, option selection, range)\n * - Canvas state,\n * - Media (video/audio) play mode + currentTime\n * - iframe contents\n * - webcomponents\n * 3. CUSTOM PROPERTIES:\n * - height+width for when `hidden` to cover the element\n * 4. EXCLUDED INTERACTION STATE:\n * - focus (possible, but not worth perf impact)\n * - hover (tracked only via mouse activity)\n * - fullscreen mode\n */\n\nfunction serializeElementNode(\n  element: Element,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): (ElementNode & SerializedNodeWithId) | null {\n  const tagName = getValidTagName(element.tagName)\n  const isSVG = isSVGElement(element) || undefined\n\n  // For performance reason, we don't use getNodePrivacyLevel directly: we leverage the\n  // parentNodePrivacyLevel option to avoid iterating over all parents\n  const nodePrivacyLevel = reducePrivacyLevel(getNodeSelfPrivacyLevel(element), parentNodePrivacyLevel)\n\n  if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n    const { width, height } = element.getBoundingClientRect()\n    return {\n      type: NodeType.Element,\n      id: transaction.assignId(element),\n      tagName,\n      attributes: {\n        rr_width: `${width}px`,\n        rr_height: `${height}px`,\n        [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_HIDDEN,\n      },\n      childNodes: [],\n      isSVG,\n    }\n  }\n\n  // Ignore Elements like Script and some Link, Metas\n  if (nodePrivacyLevel === NodePrivacyLevel.IGNORE) {\n    return null\n  }\n\n  const id = transaction.assignId(element)\n  const attributes = serializeAttributes(element, nodePrivacyLevel, transaction)\n\n  let childNodes: SerializedNodeWithId[] = []\n  if (\n    hasChildNodes(element) &&\n    // Do not serialize style children as the css rules are already in the _cssText attribute\n    tagName !== 'style'\n  ) {\n    childNodes = serializeChildNodes(element, nodePrivacyLevel, transaction)\n  }\n\n  return {\n    type: NodeType.Element,\n    id,\n    tagName,\n    attributes,\n    childNodes,\n    isSVG,\n  }\n}\n\nfunction isSVGElement(el: Element): boolean {\n  return el.tagName === 'svg' || el instanceof SVGElement\n}\n\n/**\n * Text Nodes are dependant on Element nodes\n * Privacy levels are set on elements so we check the parentElement of a text node\n * for privacy level.\n */\n\nfunction serializeTextNode(\n  textNode: Text,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): (TextNode & SerializedNodeWithId) | null {\n  const textContent = getTextContent(textNode, parentNodePrivacyLevel)\n  if (textContent === undefined) {\n    return null\n  }\n  return {\n    type: NodeType.Text,\n    id: transaction.assignId(textNode),\n    textContent,\n  }\n}\n\nfunction serializeCDataNode(\n  node: CDATASection,\n  transaction: SerializationTransaction\n): CDataNode & SerializedNodeWithId {\n  return {\n    type: NodeType.CDATA,\n    id: transaction.assignId(node),\n    textContent: '',\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNodeAsChange.form.spec.ts",
    "content": "import type { BrowserWindow } from '@datadog/browser-rum-core'\nimport {\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_MASK,\n  PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED,\n  PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n} from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../../../core/test'\nimport { ChangeType } from '../../../types'\n\nimport { serializeHtmlAsChange } from './serializeHtml.specHelper'\n\ndescribe('serializeNodeAsChange for form elements', () => {\n  let originalTimeout: number\n\n  beforeAll(() => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000\n  })\n\n  afterAll(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout\n  })\n\n  describe('<input type=\"button\">', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange('<input type=\"button\" value=\"Click here\"></input>')\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'button'], ['value', 'Click here']]]])\n    })\n\n    it('does not mask the value if the <input> has privacy level MASK_USER_INPUT', async () => {\n      const record = await serializeHtmlAsChange(`\n          <input\n            ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n            type=\"button\"\n            value=\"Click here\"\n          ></input>\n        `)\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [\n            null,\n            'INPUT',\n            [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n            ['type', 'button'],\n            ['value', 'Click here'],\n          ],\n        ],\n      ])\n    })\n\n    it('does not mask the value if an ancestor has privacy level MASK_USER_INPUT', async () => {\n      // Check that the ancestor's privacy level takes effect when we serialize\n      // a descendant <input> directly.\n      const record = await serializeHtmlAsChange(\n        `\n          <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">\n            <input type=\"button\" value=\"Click here\"></input>\n          </div>\n        `,\n        {\n          target: (node: Node): Node => node.firstChild!,\n        }\n      )\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'button'], ['value', 'Click here']]]])\n    })\n\n    it('does not mask the value when serializing an ancestor with privacy level MASK_USER_INPUT', async () => {\n      // Check that the ancestor's privacy level takes effect when we serialize\n      // the ancestor and the <input> appears within the serialized subtree.\n      const record = await serializeHtmlAsChange(`\n          <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">\n            <input type=\"button\" value=\"Click here\"></input>\n          </div>\n        `)\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'DIV', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT]],\n          [1, 'INPUT', ['type', 'button'], ['value', 'Click here']],\n        ],\n      ])\n    })\n  })\n\n  describe('<input type=\"checkbox\">', () => {\n    describe('which is unchecked', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"checkbox\" value=\"on\"></input>')\n        expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'checkbox'], ['value', 'on']]]])\n      })\n\n      it('serializes a MASK_USER_INPUT element', async () => {\n        const record = await serializeHtmlAsChange(`\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"checkbox\"\n              value=\"on\"\n            ></input>\n          `)\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'checkbox'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n\n    describe('which is checked by default', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"checkbox\" value=\"on\" checked></input>')\n        expect(record?.data).toEqual([\n          [ChangeType.AddNode, [null, 'INPUT', ['type', 'checkbox'], ['value', 'on'], ['checked', '']]],\n        ])\n      })\n\n      it('serializes a MASK_USER_INPUT element without the \"checked\" attribute', async () => {\n        const record = await serializeHtmlAsChange(`\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"checkbox\"\n              value=\"on\"\n              checked\n            ></input>\n          `)\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'checkbox'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n\n    describe('which is checked by property setter', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"checkbox\" value=\"on\"></input>', {\n          before(target: Node): void {\n            ;(target as HTMLInputElement).checked = true\n          },\n        })\n        expect(record?.data).toEqual([\n          [ChangeType.AddNode, [null, 'INPUT', ['type', 'checkbox'], ['value', 'on'], ['checked', '']]],\n        ])\n      })\n\n      it('serializes a MASK_USER_INPUT element without the \"checked\" attribute', async () => {\n        const record = await serializeHtmlAsChange(\n          `\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"checkbox\"\n              value=\"on\"\n            ></input>\n            `,\n          {\n            before(target: Node): void {\n              ;(target as HTMLInputElement).checked = true\n            },\n          }\n        )\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'checkbox'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n\n    describe('which is unchecked by property setter', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"checkbox\" value=\"on\" checked></input>', {\n          before(target: Node): void {\n            ;(target as HTMLInputElement).checked = false\n          },\n        })\n        expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'checkbox'], ['value', 'on']]]])\n      })\n\n      it('serializes a MASK_USER_INPUT element without the \"checked\" attribute', async () => {\n        const record = await serializeHtmlAsChange(\n          `\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"checkbox\"\n              value=\"on\"\n              checked\n            ></input>\n            `,\n          {\n            before(target: Node): void {\n              ;(target as HTMLInputElement).checked = false\n            },\n          }\n        )\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'checkbox'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n  })\n\n  describe('<input type=\"password\">', () => {\n    it('does not serialize a value set via property setter', async () => {\n      const record = await serializeHtmlAsChange('<input type=\"password\"></input>', {\n        before(target: Node): void {\n          ;(target as HTMLInputElement).value = 'toto'\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'password'], ['value', '***']]]])\n    })\n\n    it('does not serialize a value set via attribute setter', async () => {\n      const record = await serializeHtmlAsChange('<input type=\"password\"></input>', {\n        before(target: Node): void {\n          ;(target as HTMLInputElement).setAttribute('value', 'toto')\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'password'], ['value', '***']]]])\n    })\n  })\n\n  describe('<input type=\"radio\">', () => {\n    describe('which is unchecked', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"radio\" value=\"on\"></input>')\n        expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'radio'], ['value', 'on']]]])\n      })\n\n      it('serializes a MASK_USER_INPUT element', async () => {\n        const record = await serializeHtmlAsChange(`\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"radio\"\n              value=\"on\"\n            ></input>\n          `)\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'radio'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n\n    describe('which is checked by default', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"radio\" value=\"on\" checked></input>')\n        expect(record?.data).toEqual([\n          [ChangeType.AddNode, [null, 'INPUT', ['type', 'radio'], ['value', 'on'], ['checked', '']]],\n        ])\n      })\n\n      it('serializes a MASK_USER_INPUT element without the \"checked\" attribute', async () => {\n        const record = await serializeHtmlAsChange(`\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"radio\"\n              value=\"on\"\n              checked\n            ></input>\n          `)\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'radio'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n\n    describe('which is checked by property setter', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"radio\" value=\"on\"></input>', {\n          before(target: Node): void {\n            ;(target as HTMLInputElement).checked = true\n          },\n        })\n        expect(record?.data).toEqual([\n          [ChangeType.AddNode, [null, 'INPUT', ['type', 'radio'], ['value', 'on'], ['checked', '']]],\n        ])\n      })\n\n      it('serializes a MASK_USER_INPUT element without the \"checked\" attribute', async () => {\n        const record = await serializeHtmlAsChange(\n          `\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"radio\"\n              value=\"on\"\n            ></input>\n            `,\n          {\n            before(target: Node): void {\n              ;(target as HTMLInputElement).checked = true\n            },\n          }\n        )\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'radio'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n\n    describe('which is unchecked by property setter', () => {\n      it('serializes the element', async () => {\n        const record = await serializeHtmlAsChange('<input type=\"radio\" value=\"on\" checked></input>', {\n          before(target: Node): void {\n            ;(target as HTMLInputElement).checked = false\n          },\n        })\n        expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'radio'], ['value', 'on']]]])\n      })\n\n      it('serializes a MASK_USER_INPUT element without the \"checked\" attribute', async () => {\n        const record = await serializeHtmlAsChange(\n          `\n            <input\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n              type=\"radio\"\n              value=\"on\"\n              checked\n            ></input>\n            `,\n          {\n            before(target: Node): void {\n              ;(target as HTMLInputElement).checked = false\n            },\n          }\n        )\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [\n              null,\n              'INPUT',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['type', 'radio'],\n              ['value', '***'],\n            ],\n          ],\n        ])\n      })\n    })\n  })\n\n  describe('<input type=\"submit\">', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange('<input type=\"submit\" value=\"Click here\"></input>')\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'submit'], ['value', 'Click here']]]])\n    })\n\n    it('does not mask the value if the <input> has privacy level MASK_USER_INPUT', async () => {\n      const record = await serializeHtmlAsChange(`\n          <input\n            ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n            type=\"submit\"\n            value=\"Click here\"\n          ></input>\n        `)\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [\n            null,\n            'INPUT',\n            [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n            ['type', 'submit'],\n            ['value', 'Click here'],\n          ],\n        ],\n      ])\n    })\n\n    it('does not mask the value if an ancestor has privacy level MASK_USER_INPUT', async () => {\n      // Check that the ancestor's privacy level takes effect when we serialize\n      // a descendant <input> directly.\n      const record = await serializeHtmlAsChange(\n        `\n          <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">\n            <input type=\"submit\" value=\"Click here\"></input>\n          </div>\n        `,\n        {\n          target: (node: Node): Node => node.firstChild!,\n        }\n      )\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ['type', 'submit'], ['value', 'Click here']]]])\n    })\n\n    it('does not mask the value when serializing an ancestor with privacy level MASK_USER_INPUT', async () => {\n      // Check that the ancestor's privacy level takes effect when we serialize\n      // the ancestor and the <input> appears within the serialized subtree.\n      const record = await serializeHtmlAsChange(`\n          <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">\n            <input type=\"submit\" value=\"Click here\"></input>\n          </div>\n        `)\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'DIV', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT]],\n          [1, 'INPUT', ['type', 'submit'], ['value', 'Click here']],\n        ],\n      ])\n    })\n  })\n\n  describe('<input type=\"text\">', () => {\n    for (const { typeAttributeDescription, typeAttribute, serializedTypeAttribute } of [\n      {\n        typeAttributeDescription: 'explicit \"type\" attribute',\n        typeAttribute: 'type=\"text\"',\n        serializedTypeAttribute: [['type', 'text']] as Array<[string, string]>,\n      },\n      { typeAttributeDescription: 'implicit type', typeAttribute: '', serializedTypeAttribute: [] },\n    ]) {\n      describe(`with ${typeAttributeDescription}`, () => {\n        it('serializes the element', async () => {\n          const record = await serializeHtmlAsChange(`<input ${typeAttribute}></input>`)\n          expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'INPUT', ...serializedTypeAttribute]]])\n        })\n\n        it('serializes the placeholder', async () => {\n          const record = await serializeHtmlAsChange(`<input ${typeAttribute} placeholder=\"placeholder\"></input>`)\n          expect(record?.data).toEqual([\n            [ChangeType.AddNode, [null, 'INPUT', ...serializedTypeAttribute, ['placeholder', 'placeholder']]],\n          ])\n        })\n\n        it('serializes the element with a value set by attribute', async () => {\n          const record = await serializeHtmlAsChange(`<input ${typeAttribute} value=\"toto\"></input>`)\n          expect(record?.data).toEqual([\n            [ChangeType.AddNode, [null, 'INPUT', ...serializedTypeAttribute, ['value', 'toto']]],\n          ])\n        })\n\n        it('serializes the element with a value set by property setter', async () => {\n          const record = await serializeHtmlAsChange(`<input ${typeAttribute}></input>`, {\n            before(target: Node): void {\n              ;(target as HTMLInputElement).value = 'toto'\n            },\n          })\n          expect(record?.data).toEqual([\n            [ChangeType.AddNode, [null, 'INPUT', ...serializedTypeAttribute, ['value', 'toto']]],\n          ])\n        })\n\n        it('masks the value and placeholder if the element has privacy level MASK', async () => {\n          const record = await serializeHtmlAsChange(\n            `\n            <input\n              ${typeAttribute}\n              placeholder=\"placeholder\"\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK}\"\n            ></input>\n            `,\n            {\n              before(target: Node): void {\n                ;(target as HTMLInputElement).value = 'toto'\n              },\n            }\n          )\n          expect(record?.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [\n                null,\n                'INPUT',\n                ...serializedTypeAttribute,\n                ['placeholder', '***'],\n                [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK],\n                ['value', '***'],\n              ],\n            ],\n          ])\n        })\n\n        it('masks the value if the element has privacy level MASK_USER_INPUT', async () => {\n          const record = await serializeHtmlAsChange(\n            `\n            <input\n              ${typeAttribute}\n              placeholder=\"placeholder\"\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\"\n            ></input>\n            `,\n            {\n              before(target: Node): void {\n                ;(target as HTMLInputElement).value = 'toto'\n              },\n            }\n          )\n          expect(record?.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [\n                null,\n                'INPUT',\n                ...serializedTypeAttribute,\n                ['placeholder', 'placeholder'],\n                [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n                ['value', '***'],\n              ],\n            ],\n          ])\n        })\n\n        it('masks the value if an ancestor has privacy level MASK_USER_INPUT', async () => {\n          // Check that the ancestor's privacy level takes effect when we serialize\n          // a descendant <input> directly.\n          const record = await serializeHtmlAsChange(\n            `\n            <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">\n              <input ${typeAttribute} placeholder=\"placeholder\"></input>\n            </div>\n            `,\n            {\n              target(defaultTarget: Node): Node {\n                return defaultTarget.firstChild!\n              },\n              before(target: Node): void {\n                ;(target as HTMLInputElement).value = 'toto'\n              },\n            }\n          )\n          expect(record?.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [null, 'INPUT', ...serializedTypeAttribute, ['placeholder', 'placeholder'], ['value', '***']],\n            ],\n          ])\n        })\n\n        it('masks the value when serializing an ancestor with privacy level MASK_USER_INPUT', async () => {\n          // Check that the ancestor's privacy level takes effect when we serialize\n          // the ancestor and the <input> appears within the serialized subtree.\n          const record = await serializeHtmlAsChange(\n            `\n            <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">\n              <input ${typeAttribute} placeholder=\"placeholder\"></input>\n            </div>\n            `,\n            {\n              before(target: Node): void {\n                ;(target.firstChild as HTMLInputElement).value = 'toto'\n              },\n            }\n          )\n          expect(record?.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [null, 'DIV', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT]],\n              [1, 'INPUT', ...serializedTypeAttribute, ['placeholder', 'placeholder'], ['value', '***']],\n            ],\n          ])\n        })\n\n        it('masks the placeholder and value if the element has privacy level MASK_UNLESS_ALLOWLISTED', async () => {\n          const record = await serializeHtmlAsChange(\n            `\n            <input\n              ${typeAttribute}\n              placeholder=\"placeholder\"\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED}\"\n            ></input>\n            `,\n            {\n              before(target: Node): void {\n                ;(target as HTMLInputElement).value = 'toto'\n              },\n            }\n          )\n          expect(record?.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [\n                null,\n                'INPUT',\n                ...serializedTypeAttribute,\n                ['placeholder', '***'],\n                [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED],\n                ['value', '***'],\n              ],\n            ],\n          ])\n        })\n\n        it('does not permit allowlisting the placeholder or the value if the element has privacy level MASK_UNLESS_ALLOWLISTED', async () => {\n          ;(window as BrowserWindow).$DD_ALLOW = new Set(['allowlisted-string'])\n          registerCleanupTask(() => {\n            delete (window as BrowserWindow).$DD_ALLOW\n          })\n\n          const record = await serializeHtmlAsChange(\n            `\n            <input\n              ${typeAttribute}\n              placeholder=\"allowlisted-string\"\n              ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED}\"\n            ></input>\n            `,\n            {\n              before(target: Node): void {\n                ;(target as HTMLInputElement).value = 'allowlisted-string'\n              },\n            }\n          )\n          expect(record?.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [\n                null,\n                'INPUT',\n                ...serializedTypeAttribute,\n                ['placeholder', '***'],\n                [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED],\n                ['value', '***'],\n              ],\n            ],\n          ])\n        })\n      })\n    }\n  })\n\n  /*\n  describe('<select>', () => {\n    it('serializes <select> elements value and selected state', async () => {\n      const select = document.createElement('select')\n      const option1 = document.createElement('option')\n      option1.value = 'foo'\n      select.appendChild(option1)\n      const option2 = document.createElement('option')\n      option2.value = 'bar'\n      select.appendChild(option2)\n      select.options.selectedIndex = 1\n\n      expect(await serializeHtmlAsChangeNode(select, NodePrivacyLevel.ALLOW, transaction)).toEqual(\n        jasmine.objectContaining({\n          attributes: { value: 'bar' },\n          childNodes: [\n            jasmine.objectContaining({\n              attributes: {\n                value: 'foo',\n              },\n            }),\n            jasmine.objectContaining({\n              attributes: {\n                value: 'bar',\n                selected: '',\n              },\n            }),\n          ],\n        })\n      )\n    })\n  })\n  */\n\n  describe('<textarea>', () => {\n    it('serializes the value', async () => {\n      const record = await serializeHtmlAsChange('<textarea>toto</textarea>', {\n        before(target: Node): void {\n          ;(target as HTMLTextAreaElement).value = 'some text'\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'TEXTAREA', ['value', 'some text']], [1, '#text', 'toto']],\n      ])\n    })\n\n    it('serializes the default value', async () => {\n      const record = await serializeHtmlAsChange('<textarea>toto</textarea>')\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'TEXTAREA', ['value', 'toto']], [1, '#text', 'toto']]])\n    })\n\n    it('masks the value if the element has privacy level MASK', async () => {\n      const record = await serializeHtmlAsChange(\n        `<textarea ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK}\">toto</textarea>`,\n        {\n          before(target: Node): void {\n            ;(target as HTMLTextAreaElement).value = 'some text'\n          },\n        }\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'TEXTAREA', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK], ['value', '***']],\n          [1, '#text', 'xxxx'],\n        ],\n      ])\n    })\n\n    it('masks the default value if the element has privacy level MASK', async () => {\n      const record = await serializeHtmlAsChange(\n        `<textarea ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK}\">toto</textarea>`\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'TEXTAREA', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK], ['value', '***']],\n          [1, '#text', 'xxxx'],\n        ],\n      ])\n    })\n\n    it('masks the value if the element has privacy level MASK_USER_INPUT', async () => {\n      const record = await serializeHtmlAsChange(\n        `<textarea ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">toto</textarea>`,\n        {\n          before(target: Node): void {\n            ;(target as HTMLTextAreaElement).value = 'some text'\n          },\n        }\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'TEXTAREA', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT], ['value', '***']],\n          [1, '#text', 'xxxx'],\n        ],\n      ])\n    })\n\n    it('masks the default value if the element has privacy level MASK_USER_INPUT', async () => {\n      const record = await serializeHtmlAsChange(\n        `<textarea ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_USER_INPUT}\">toto</textarea>`\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'TEXTAREA', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT], ['value', '***']],\n          [1, '#text', 'xxxx'],\n        ],\n      ])\n    })\n\n    it('does not permit allowlisting the value or the default value if the element has privacy level MASK_UNLESS_ALLOWLISTED', async () => {\n      ;(window as BrowserWindow).$DD_ALLOW = new Set(['allowlisted-default', 'allowlisted-value'])\n      registerCleanupTask(() => {\n        delete (window as BrowserWindow).$DD_ALLOW\n      })\n\n      const record = await serializeHtmlAsChange(\n        `\n        <textarea\n          ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED}\"\n        >allowlisted-default</textarea>\n        `,\n        {\n          before(target: Node): void {\n            ;(target as HTMLTextAreaElement).value = 'allowlisted-value'\n          },\n        }\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'TEXTAREA', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED], ['value', '***']],\n          [1, '#text', 'xxxxxxxxxxxxxxxxxxx'],\n        ],\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNodeAsChange.node.spec.ts",
    "content": "import { PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_HIDDEN, PRIVACY_ATTR_VALUE_MASK } from '@datadog/browser-rum-core'\nimport { DefaultPrivacyLevel } from '@datadog/browser-core'\nimport type { BrowserChangeRecord, BrowserFullSnapshotChangeRecord } from '../../../types'\nimport { ChangeType, PlaybackState } from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { ScrollPositions } from '../elementsScrollPositions'\nimport { SerializationKind } from './serializationTransaction'\n\nimport { serializeHtmlAsChange } from './serializeHtml.specHelper'\n\ndescribe('serializeNodeAsChange for DOM nodes', () => {\n  let originalTimeout: number\n\n  beforeAll(() => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000\n  })\n\n  afterAll(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout\n  })\n\n  describe('for #cdata-section nodes', () => {\n    it('serializes the node', async () => {\n      const record = await serializeHtmlAsChange('<div></div>', {\n        target: (node: Node) => {\n          // It's surprisingly tricky to create a CDATA section, since HTML documents are\n          // not allowed to contain them in normal circumstances; the HTML parser will\n          // convert them into comments, and calling createCDATASection() throws unless\n          // it's invoked on an XML document. That's why this test uses this hacky\n          // approach.\n          const doc = new DOMParser().parseFromString('<xml></xml>', 'application/xml')\n          const cdata = doc.createCDATASection('cdata')\n          node.appendChild(node.ownerDocument!.importNode(cdata))\n          return node.firstChild!\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, '#cdata-section']]])\n    })\n  })\n\n  describe('for #comment nodes', () => {\n    it('does not serialize the node', async () => {\n      const record = await serializeHtmlAsChange('<!-- comment -->')\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for #document nodes', () => {\n    it('serializes the #document node', async () => {\n      const record = await serializeHtmlAsChange('<!doctype html><html>foo</html>', { input: 'document' })\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, '#document'],\n          [1, '#doctype', 'html', '', ''],\n          [0, 'HTML'],\n          [1, 'HEAD'],\n          [0, 'BODY'],\n          [1, '#text', 'foo'],\n        ],\n        [ChangeType.ScrollPosition, [0, 0, 0]],\n      ])\n    })\n\n    it('serializes the #document node when the default privacy level is MASK', async () => {\n      const record = await serializeHtmlAsChange('<!doctype html><html>foo</html>', {\n        configuration: { defaultPrivacyLevel: DefaultPrivacyLevel.MASK },\n        input: 'document',\n      })\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, '#document'],\n          [1, '#doctype', 'html', '', ''],\n          [0, 'HTML'],\n          [1, 'HEAD'],\n          [0, 'BODY'],\n          [1, '#text', 'xxx'],\n        ],\n        [ChangeType.ScrollPosition, [0, 0, 0]],\n      ])\n    })\n  })\n\n  describe('for #text nodes', () => {\n    it('serializes the node', async () => {\n      const record = await serializeHtmlAsChange('<div>text content</div>', {\n        target: (node: Node) => node.firstChild!,\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, '#text', 'text content']]])\n    })\n\n    it('serializes a node with no text content', async () => {\n      const record = await serializeHtmlAsChange('<div>xxx</div>', {\n        before(target: Node): void {\n          target.textContent = ''\n        },\n        target(defaultTarget: Node): Node {\n          return defaultTarget.firstChild!\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, '#text', '']]])\n    })\n\n    it('does not serialize a whitespace-only node if the parent is a <head> element', async () => {\n      const record = await serializeHtmlAsChange('<!doctype HTML><head>    </head>', {\n        input: 'document',\n        target: (node: Node) => (node as Document).head.firstChild!,\n        whitespace: 'keep',\n      })\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for HTML elements', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange('<div>')\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'DIV']]])\n    })\n\n    it(\"serializes the HTML element's attributes\", async () => {\n      const record = await serializeHtmlAsChange(\n        '<div foo=\"bar\" data-foo=\"data-bar\" class=\"zog\" style=\"width: 10px;\"></div>'\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'DIV', ['foo', 'bar'], ['data-foo', 'data-bar'], ['class', 'zog'], ['style', 'width: 10px;']],\n        ],\n      ])\n    })\n  })\n\n  describe('for SVG elements', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange(`\n        <svg viewBox=\"0 0 100 100\">\n          <clipPath id=\"myClip\">\n            <circle cx=\"40\" cy=\"35\" r=\"35\" />\n          </clipPath>\n          <path\n            id=\"heart\"\n            d=\"M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z\" />\n          <use clip-path=\"url(#myClip)\" href=\"#heart\" fill=\"red\" />\n        </svg>\n      `)\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'svg>svg', ['viewBox', '0 0 100 100']],\n          [1, 'svg>clipPath', ['id', 'myClip']],\n          [1, 'svg>circle', ['cx', '40'], ['cy', '35'], ['r', '35']],\n          [\n            3,\n            'svg>path',\n            ['id', 'heart'],\n            ['d', 'M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z'],\n          ],\n          [0, 'svg>use', ['clip-path', 'url(#myClip)'], ['href', '#heart'], ['fill', 'red']],\n        ],\n      ])\n    })\n  })\n\n  describe('for <audio> elements', () => {\n    it(\"serializes the <audio> element's playback state when paused\", async () => {\n      const record = await serializeHtmlAsChange('<audio></audio>')\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'AUDIO']],\n        [ChangeType.MediaPlaybackState, [0, PlaybackState.Paused]],\n      ])\n    })\n\n    it(\"serializes the <audio> element's playback state when playing\", async () => {\n      const record = await serializeHtmlAsChange('<audio></audio>', {\n        before(target: Node): void {\n          // Emulate a playing audio file.\n          Object.defineProperty(target, 'paused', { value: false })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'AUDIO']],\n        [ChangeType.MediaPlaybackState, [0, PlaybackState.Playing]],\n      ])\n    })\n  })\n\n  describe('for <head> elements', () => {\n    it('does not serialize whitespace', async () => {\n      const record = await serializeHtmlAsChange('<!doctype HTML><head>  <title>  foo </title>  </head>', {\n        input: 'document',\n        whitespace: 'keep',\n      })\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, '#document'],\n          [1, '#doctype', 'html', '', ''],\n          [0, 'HTML'],\n          [1, 'HEAD'],\n          [1, 'TITLE'],\n          [1, '#text', '  foo '],\n          [4, 'BODY'],\n        ],\n        [ChangeType.ScrollPosition, [0, 0, 0]],\n      ])\n    })\n  })\n\n  describe('for <link> elements', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange(`\n        <link rel=\"alternate\" type=\"application/atom+xml\" href=\"posts.xml\" title=\"Blog\">\n      `)\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [\n            null,\n            'LINK',\n            ['rel', 'alternate'],\n            ['type', 'application/atom+xml'],\n            ['href', 'posts.xml'],\n            ['title', 'Blog'],\n          ],\n        ],\n      ])\n    })\n\n    it('does not serialize <link rel=\"shortcut icon\">', async () => {\n      const record = await serializeHtmlAsChange('<link rel=\"shortcut icon\">')\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for <meta> elements', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange(`\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n      `)\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'META', ['name', 'viewport'], ['content', 'width=device-width, initial-scale=1']]],\n      ])\n    })\n\n    it('does not serialize <meta name=\"keywords\">', async () => {\n      const record = await serializeHtmlAsChange(`\n        <meta name=\"keywords\" content=\"products\" lang=\"en\">\n      `)\n      expect(record?.data).toBeUndefined()\n    })\n\n    it('does not serialize <meta name=\"KeYwOrDs\">', async () => {\n      const record = await serializeHtmlAsChange(`\n        <meta name=\"KeYwOrDs\" content=\"products\" lang=\"en\">\n      `)\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for <script> elements', () => {\n    it('does not serialize the element', async () => {\n      const record = await serializeHtmlAsChange('<script></script>')\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for children of <script> elements', () => {\n    it('does not serialize them', async () => {\n      const record = await serializeHtmlAsChange('<script>foo</script>', {\n        target: (node: Node) => node.firstChild!,\n      })\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for <video> elements', () => {\n    it(\"serializes the <video> element's playback state when paused\", async () => {\n      const record = await serializeHtmlAsChange('<video></video>')\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'VIDEO']],\n        [ChangeType.MediaPlaybackState, [0, PlaybackState.Paused]],\n      ])\n    })\n\n    it(\"serializes the <video> element's playback state when playing\", async () => {\n      const record = await serializeHtmlAsChange('<video></video>', {\n        before(target: Node): void {\n          // Emulate a playing video.\n          Object.defineProperty(target, 'paused', { value: false })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'VIDEO']],\n        [ChangeType.MediaPlaybackState, [0, PlaybackState.Playing]],\n      ])\n    })\n  })\n\n  describe('for elements with NodePrivacyLevel.HIDDEN', () => {\n    it('generates a placeholder', async () => {\n      const record = await serializeHtmlAsChange(`\n        <div\n          ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_HIDDEN}\"\n          style=\"width: 200px; height: 100px;\"\n          data-attribute=\"foo\"\n        >\n          <span>Foo</span>\n        </div>\n      `)\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'DIV', ['data-dd-privacy', 'hidden']]],\n        [ChangeType.Size, [0, jasmine.any(Number), jasmine.any(Number)]],\n      ])\n    })\n  })\n\n  describe('for children of elements with NodePrivacyLevel.HIDDEN', () => {\n    it('does not serialize them', async () => {\n      const record = await serializeHtmlAsChange(\n        `\n        <div ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_HIDDEN}\">\n          <span>Foo</span>\n        </div>\n        `,\n        {\n          target: (node: Node) => node.firstChild!,\n        }\n      )\n      expect(record?.data).toBeUndefined()\n    })\n  })\n\n  describe('for scrollable elements', () => {\n    const scrollableElement = `\n      <div style=\"width: 100px; height: 100px; overflow: scroll\">\n        <div style=\"width: 200px; height: 200px\"></div>\n      </div>\n    `\n\n    function serializeScrollableElement(\n      scrollPositions: ScrollPositions | undefined\n    ): Promise<BrowserChangeRecord | BrowserFullSnapshotChangeRecord | undefined> {\n      return serializeHtmlAsChange(scrollableElement, {\n        before(target: Node): void {\n          if (scrollPositions) {\n            ;(target as Element).scrollBy(scrollPositions.scrollLeft, scrollPositions.scrollTop)\n          }\n        },\n        after(target: Node, scope: RecordingScope): void {\n          expect(scope.elementsScrollPositions.get(target as Element)).toEqual(scrollPositions)\n        },\n      })\n    }\n\n    describe('during the initial full snapshot', () => {\n      it('reads the scroll position from the DOM and serializes it', async () => {\n        const record = await serializeScrollableElement({ scrollLeft: 10, scrollTop: 20 })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, 'DIV', ['style', 'width: 100px; height: 100px; overflow: scroll']],\n            [1, 'DIV', ['style', 'width: 200px; height: 200px']],\n          ],\n          [ChangeType.ScrollPosition, [0, 10, 20]],\n        ])\n      })\n\n      it('does not serialize the scroll position if the element has not been scrolled', async () => {\n        const record = await serializeScrollableElement(undefined)\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, 'DIV', ['style', 'width: 100px; height: 100px; overflow: scroll']],\n            [1, 'DIV', ['style', 'width: 200px; height: 200px']],\n          ],\n        ])\n      })\n    })\n\n    describe('during subsequent full snapshots', () => {\n      it('reads the scroll position from ElementScrollPositions and serializes it', async () => {\n        const record = await serializeHtmlAsChange(scrollableElement, {\n          before(target: Node, scope: RecordingScope): void {\n            scope.elementsScrollPositions.set(target as Element, { scrollLeft: 10, scrollTop: 20 })\n          },\n          kind: SerializationKind.SUBSEQUENT_FULL_SNAPSHOT,\n        })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, 'DIV', ['style', 'width: 100px; height: 100px; overflow: scroll']],\n            [1, 'DIV', ['style', 'width: 200px; height: 200px']],\n          ],\n          [ChangeType.ScrollPosition, [0, 10, 20]],\n        ])\n      })\n\n      it('does not read the scroll position from the DOM', async () => {\n        const record = await serializeHtmlAsChange(scrollableElement, {\n          before(target: Node): void {\n            ;(target as Element).scrollBy(10, 20)\n          },\n          after(target: Node, scope: RecordingScope): void {\n            expect(scope.elementsScrollPositions.get(target as Element)).toBeUndefined()\n          },\n          kind: SerializationKind.SUBSEQUENT_FULL_SNAPSHOT,\n        })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, 'DIV', ['style', 'width: 100px; height: 100px; overflow: scroll']],\n            [1, 'DIV', ['style', 'width: 200px; height: 200px']],\n          ],\n        ])\n      })\n    })\n\n    describe('during incremental mutations', () => {\n      it('does not serialize the scroll position', async () => {\n        const record = await serializeHtmlAsChange(scrollableElement, {\n          before(target: Node, scope: RecordingScope): void {\n            ;(target as Element).scrollBy(10, 20)\n            scope.elementsScrollPositions.set(target as Element, { scrollLeft: 10, scrollTop: 20 })\n          },\n          kind: SerializationKind.INCREMENTAL_SNAPSHOT,\n        })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, 'DIV', ['style', 'width: 100px; height: 100px; overflow: scroll']],\n            [1, 'DIV', ['style', 'width: 200px; height: 200px']],\n          ],\n        ])\n      })\n    })\n  })\n\n  describe('for shadow hosts', () => {\n    it('serializes the element and its shadow root', async () => {\n      const record = await serializeHtmlAsChange('<div id=\"shadow-host\"></div>', {\n        before(target: Node): void {\n          ;(target as Element).attachShadow({ mode: 'open' })\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'DIV', ['id', 'shadow-host']], [1, '#shadow-root']]])\n    })\n\n    it('serializes elements within the shadow subtree', async () => {\n      const record = await serializeHtmlAsChange('<div id=\"shadow-host\"></div>', {\n        before(target: Node): void {\n          const shadowRoot = (target as Element).attachShadow({ mode: 'open' })\n          shadowRoot.appendChild(target.ownerDocument!.createElement('hr'))\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'DIV', ['id', 'shadow-host']], [1, '#shadow-root'], [1, 'HR']],\n      ])\n    })\n\n    it(\"propagates the element's privacy level to its shadow subtree\", async () => {\n      const record = await serializeHtmlAsChange(\n        `\n        <div\n          id=\"shadow-host\"\n          ${PRIVACY_ATTR_NAME}=\"${PRIVACY_ATTR_VALUE_MASK}\"\n        ></input>\n        `,\n        {\n          before(target: Node): void {\n            const shadowRoot = (target as Element).attachShadow({ mode: 'open' })\n            shadowRoot.appendChild(target.ownerDocument!.createTextNode('foo'))\n          },\n        }\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, 'DIV', ['id', 'shadow-host'], [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK]],\n          [1, '#shadow-root'],\n          [1, '#text', 'xxx'],\n        ],\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNodeAsChange.snapshot.spec.ts",
    "content": "import type { BrowserWindow } from '@datadog/browser-rum-core'\nimport {\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_ALLOW,\n  PRIVACY_ATTR_VALUE_HIDDEN,\n  PRIVACY_ATTR_VALUE_MASK,\n  PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED,\n  PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n} from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../../../core/test'\nimport { ChangeType, PlaybackState } from '../../../types'\n\nimport { serializeHtmlAsChange } from './serializeHtml.specHelper'\n\ndescribe('serializeNodeAsChange for snapshotted documents', () => {\n  let originalTimeout: number\n\n  beforeAll(() => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000\n  })\n\n  afterAll(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout\n  })\n\n  describe('for a simple document', () => {\n    const GREEN_PNG =\n      'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA1BMVEUA/wA0XsCoAAAADElEQVR4nGNgIA0AAAAwAAEWiZrRAAAAAElFTkSuQmCC'\n\n    function createHtmlWithPrivacyAttributeValue(privacyAttributeValue: string): string {\n      return `\n        <!doctype HTML>\n        <html ${PRIVACY_ATTR_NAME}=\"${privacyAttributeValue}\" style=\"width: 100%; height: 100%;\">\n          <head>\n              <link href=\"https://public.com/path/nested?query=param#hash\" rel=\"stylesheet\">\n              <style>\n                .example {color: red;}\n              </style>\n              <script>private</script>\n              <meta>\n              <base>\n              <title>private title</title>\n          </head>\n          <body>\n              <h1>hello private world</h1>\n              <p>Loreum ipsum private text</p>\n              <noscript>hello private world</noscript>\n              <a href=\"https://private.com/path/nested?query=param#hash\">\n                Click https://private.com/path/nested?query=param#hash\n              </a>\n              <img src=\"${GREEN_PNG}\">\n              <video controls>\n                <source src=\"https://private.com/path/nested?query=param#hash\" type=\"video/webm\">\n                <source src=\"https://private.com/path/nested?query=param#hash\" type=\"video/mp4\">\n                <p>Your browser cannot play the provided video file.</p>\n              </video>\n              <select>\n                <option aria-label=\"A\">private option A</option>\n                <option aria-label=\"B\">private option B</option>\n                <option aria-label=\"C\">private option C</option>\n              </select>\n              <input type=\"password\">\n              <input type=\"text\">\n              <input type=\"checkbox\" id=\"inputFoo\" name=\"inputFoo\" checked>\n              <label for=\"inputFoo\">inputFoo label</label>\n\n              <input type=\"radio\" id=\"bar-private\" name=\"radioGroup\" value=\"bar-private\">\n\n              <textarea id=\"baz\" name=\"baz\" rows=\"2\" cols=\"20\">\n                Loreum Ipsum private ...\n              </textarea>\n\n              <div contentEditable>editable private div</div>\n          </body>\n        </html>\n      `\n    }\n\n    describe(\"when the <html> element's privacy level is ALLOW\", () => {\n      it('matches the snapshot', async () => {\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_ALLOW)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [0, 'HTML', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_ALLOW], ['style', 'width: 100%; height: 100%;']],\n            [1, 'HEAD'],\n            [1, 'LINK', ['href', 'https://public.com/path/nested?query=param#hash'], ['rel', 'stylesheet']],\n            [0, 'STYLE'],\n            [0, 'META'],\n            [0, 'BASE'],\n            [0, 'TITLE'],\n            [1, '#text', 'private title'],\n            [8, 'BODY'],\n            [1, 'H1'],\n            [1, '#text', 'hello private world'],\n            [3, 'P'],\n            [1, '#text', 'Loreum ipsum private text'],\n            [5, 'NOSCRIPT'],\n            [1, '#text', 'hello private world'],\n            [7, 'A', ['href', 'https://private.com/path/nested?query=param#hash']],\n            [1, '#text', '\\n                Click https://private.com/path/nested?query=param#hash\\n              '],\n            [9, 'IMG', ['src', GREEN_PNG]],\n            [0, 'VIDEO', ['controls', '']],\n            [1, 'SOURCE', ['src', 'https://private.com/path/nested?query=param#hash'], ['type', 'video/webm']],\n            [0, 'SOURCE', ['src', 'https://private.com/path/nested?query=param#hash'], ['type', 'video/mp4']],\n            [0, 'P'],\n            [1, '#text', 'Your browser cannot play the provided video file.'],\n            [15, 'SELECT', ['value', 'private option A']],\n            [1, 'OPTION', ['aria-label', 'A'], ['value', 'private option A'], ['selected', '']],\n            [1, '#text', 'private option A'],\n            [3, 'OPTION', ['aria-label', 'B'], ['value', 'private option B']],\n            [1, '#text', 'private option B'],\n            [5, 'OPTION', ['aria-label', 'C'], ['value', 'private option C']],\n            [1, '#text', 'private option C'],\n            [22, 'INPUT', ['type', 'password']],\n            [0, 'INPUT', ['type', 'text']],\n            [\n              0,\n              'INPUT',\n              ['type', 'checkbox'],\n              ['id', 'inputFoo'],\n              ['name', 'inputFoo'],\n              ['checked', ''],\n              ['value', 'on'],\n            ],\n            [0, 'LABEL', ['for', 'inputFoo']],\n            [1, '#text', 'inputFoo label'],\n            [27, 'INPUT', ['type', 'radio'], ['id', 'bar-private'], ['name', 'radioGroup'], ['value', 'bar-private']],\n            [\n              0,\n              'TEXTAREA',\n              ['id', 'baz'],\n              ['name', 'baz'],\n              ['rows', '2'],\n              ['cols', '20'],\n              ['value', '                Loreum Ipsum private ...\\n              '],\n            ],\n            [1, '#text', '                Loreum Ipsum private ...\\n              '],\n            [30, 'DIV', ['contenteditable', '']],\n            [1, '#text', 'editable private div'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, ['.example { color: red; }']],\n          [ChangeType.AttachedStyleSheets, [5, 0]],\n          [ChangeType.MediaPlaybackState, [20, PlaybackState.Paused]],\n        ])\n      })\n    })\n\n    describe(\"when the <html> element's privacy level is HIDDEN\", () => {\n      it('matches the snapshot', async () => {\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_HIDDEN)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [0, 'HTML', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_HIDDEN]],\n          ],\n          [ChangeType.Size, [2, jasmine.any(Number), jasmine.any(Number)]],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n        ])\n      })\n    })\n\n    describe(\"when the <html> element's privacy level is MASK\", () => {\n      it('matches the snapshot', async () => {\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_MASK)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [0, 'HTML', [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK], ['style', 'width: 100%; height: 100%;']],\n            [1, 'HEAD'],\n            [1, 'LINK', ['href', 'https://public.com/path/nested?query=param#hash'], ['rel', 'stylesheet']],\n            [0, 'STYLE'],\n            [0, 'META'],\n            [0, 'BASE'],\n            [0, 'TITLE'],\n            [1, '#text', 'xxxxxxx xxxxx'],\n            [8, 'BODY'],\n            [1, 'H1'],\n            [1, '#text', 'xxxxx xxxxxxx xxxxx'],\n            [3, 'P'],\n            [1, '#text', 'xxxxxx xxxxx xxxxxxx xxxx'],\n            [5, 'NOSCRIPT'],\n            [1, '#text', 'xxxxx xxxxxxx xxxxx'],\n            [7, 'A', ['href', '***']],\n            [1, '#text', '\\n                xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n              '],\n            [\n              9,\n              'IMG',\n              [\n                'src',\n                \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' style='background-color:silver'%3E%3C/svg%3E\",\n              ],\n            ],\n            [0, 'VIDEO', ['controls', '']],\n            [\n              1,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/webm'],\n            ],\n            [\n              0,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/mp4'],\n            ],\n            [0, 'P'],\n            [1, '#text', 'xxxx xxxxxxx xxxxxx xxxx xxx xxxxxxxx xxxxx xxxxx'],\n            [15, 'SELECT', ['value', '***']],\n            [1, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [3, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [5, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [22, 'INPUT', ['type', 'password']],\n            [0, 'INPUT', ['type', 'text']],\n            [0, 'INPUT', ['type', 'checkbox'], ['id', 'inputFoo'], ['name', '***'], ['value', '***']],\n            [0, 'LABEL', ['for', 'inputFoo']],\n            [1, '#text', 'xxxxxxxx xxxxx'],\n            [27, 'INPUT', ['type', 'radio'], ['id', 'bar-private'], ['name', '***'], ['value', '***']],\n            [0, 'TEXTAREA', ['id', 'baz'], ['name', '***'], ['rows', '2'], ['cols', '20'], ['value', '***']],\n            [1, '#text', '                xxxxxx xxxxx xxxxxxx xxx\\n              '],\n            [30, 'DIV', ['contenteditable', '']],\n            [1, '#text', 'xxxxxxxx xxxxxxx xxx'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, ['.example { color: red; }']],\n          [ChangeType.AttachedStyleSheets, [5, 0]],\n          [ChangeType.MediaPlaybackState, [20, PlaybackState.Paused]],\n        ])\n      })\n    })\n\n    describe(\"when the <html> element's privacy level is MASK_USER_INPUT\", () => {\n      it('matches the snapshot', async () => {\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [\n              0,\n              'HTML',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT],\n              ['style', 'width: 100%; height: 100%;'],\n            ],\n            [1, 'HEAD'],\n            [1, 'LINK', ['href', 'https://public.com/path/nested?query=param#hash'], ['rel', 'stylesheet']],\n            [0, 'STYLE'],\n            [0, 'META'],\n            [0, 'BASE'],\n            [0, 'TITLE'],\n            [1, '#text', 'private title'],\n            [8, 'BODY'],\n            [1, 'H1'],\n            [1, '#text', 'hello private world'],\n            [3, 'P'],\n            [1, '#text', 'Loreum ipsum private text'],\n            [5, 'NOSCRIPT'],\n            [1, '#text', 'hello private world'],\n            [7, 'A', ['href', 'https://private.com/path/nested?query=param#hash']],\n            [1, '#text', '\\n                Click https://private.com/path/nested?query=param#hash\\n              '],\n            [9, 'IMG', ['src', GREEN_PNG]],\n            [0, 'VIDEO', ['controls', '']],\n            [1, 'SOURCE', ['src', 'https://private.com/path/nested?query=param#hash'], ['type', 'video/webm']],\n            [0, 'SOURCE', ['src', 'https://private.com/path/nested?query=param#hash'], ['type', 'video/mp4']],\n            [0, 'P'],\n            [1, '#text', 'Your browser cannot play the provided video file.'],\n            [15, 'SELECT', ['value', '***']],\n            [1, 'OPTION', ['aria-label', 'A']],\n            [1, '#text', '***'],\n            [3, 'OPTION', ['aria-label', 'B']],\n            [1, '#text', '***'],\n            [5, 'OPTION', ['aria-label', 'C']],\n            [1, '#text', '***'],\n            [22, 'INPUT', ['type', 'password']],\n            [0, 'INPUT', ['type', 'text']],\n            [0, 'INPUT', ['type', 'checkbox'], ['id', 'inputFoo'], ['name', 'inputFoo'], ['value', '***']],\n            [0, 'LABEL', ['for', 'inputFoo']],\n            [1, '#text', 'inputFoo label'],\n            [27, 'INPUT', ['type', 'radio'], ['id', 'bar-private'], ['name', 'radioGroup'], ['value', '***']],\n            [0, 'TEXTAREA', ['id', 'baz'], ['name', 'baz'], ['rows', '2'], ['cols', '20'], ['value', '***']],\n            [1, '#text', '                xxxxxx xxxxx xxxxxxx xxx\\n              '],\n            [30, 'DIV', ['contenteditable', '']],\n            [1, '#text', 'editable private div'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, ['.example { color: red; }']],\n          [ChangeType.AttachedStyleSheets, [5, 0]],\n          [ChangeType.MediaPlaybackState, [20, PlaybackState.Paused]],\n        ])\n      })\n    })\n\n    describe(\"when the <html> element's privacy level is MASK_UNLESS_ALLOWLISTED\", () => {\n      it('matches the snapshot when the allowlist is populated', async () => {\n        ;(window as BrowserWindow).$DD_ALLOW = new Set(['private title', 'hello private world'])\n        registerCleanupTask(() => {\n          delete (window as BrowserWindow).$DD_ALLOW\n        })\n\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [\n              0,\n              'HTML',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED],\n              ['style', 'width: 100%; height: 100%;'],\n            ],\n            [1, 'HEAD'],\n            [1, 'LINK', ['href', 'https://public.com/path/nested?query=param#hash'], ['rel', 'stylesheet']],\n            [0, 'STYLE'],\n            [0, 'META'],\n            [0, 'BASE'],\n            [0, 'TITLE'],\n            [1, '#text', 'private title'], // Unmasked because this string appears in the allowlist.\n            [8, 'BODY'],\n            [1, 'H1'],\n            [1, '#text', 'hello private world'], // Unmasked because this string appears in the allowlist.\n            [3, 'P'],\n            [1, '#text', 'xxxxxx xxxxx xxxxxxx xxxx'],\n            [5, 'NOSCRIPT'],\n            [1, '#text', 'hello private world'], // Unmasked because this string appears in the allowlist.\n            [7, 'A', ['href', '***']],\n            [1, '#text', '\\n                xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n              '],\n            [\n              9,\n              'IMG',\n              [\n                'src',\n                \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' style='background-color:silver'%3E%3C/svg%3E\",\n              ],\n            ],\n            [0, 'VIDEO', ['controls', '']],\n            [\n              1,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/webm'],\n            ],\n            [\n              0,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/mp4'],\n            ],\n            [0, 'P'],\n            [1, '#text', 'xxxx xxxxxxx xxxxxx xxxx xxx xxxxxxxx xxxxx xxxxx'],\n            [15, 'SELECT', ['value', '***']],\n            [1, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [3, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [5, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [22, 'INPUT', ['type', 'password']],\n            [0, 'INPUT', ['type', 'text']],\n            [0, 'INPUT', ['type', 'checkbox'], ['id', 'inputFoo'], ['name', '***'], ['value', '***']],\n            [0, 'LABEL', ['for', 'inputFoo']],\n            [1, '#text', 'xxxxxxxx xxxxx'],\n            [27, 'INPUT', ['type', 'radio'], ['id', 'bar-private'], ['name', '***'], ['value', '***']],\n            [0, 'TEXTAREA', ['id', 'baz'], ['name', '***'], ['rows', '2'], ['cols', '20'], ['value', '***']],\n            [1, '#text', '                xxxxxx xxxxx xxxxxxx xxx\\n              '],\n            [30, 'DIV', ['contenteditable', '']],\n            [1, '#text', 'xxxxxxxx xxxxxxx xxx'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, ['.example { color: red; }']],\n          [ChangeType.AttachedStyleSheets, [5, 0]],\n          [ChangeType.MediaPlaybackState, [20, PlaybackState.Paused]],\n        ])\n      })\n\n      it('matches the snapshot when the allowlist is empty', async () => {\n        ;(window as BrowserWindow).$DD_ALLOW = new Set()\n        registerCleanupTask(() => {\n          delete (window as BrowserWindow).$DD_ALLOW\n        })\n\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [\n              0,\n              'HTML',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED],\n              ['style', 'width: 100%; height: 100%;'],\n            ],\n            [1, 'HEAD'],\n            [1, 'LINK', ['href', 'https://public.com/path/nested?query=param#hash'], ['rel', 'stylesheet']],\n            [0, 'STYLE'],\n            [0, 'META'],\n            [0, 'BASE'],\n            [0, 'TITLE'],\n            [1, '#text', 'xxxxxxx xxxxx'], // Masked because this string does not appear in the allowlist.\n            [8, 'BODY'],\n            [1, 'H1'],\n            [1, '#text', 'xxxxx xxxxxxx xxxxx'], // Masked because this string does not appear in the allowlist.\n            [3, 'P'],\n            [1, '#text', 'xxxxxx xxxxx xxxxxxx xxxx'],\n            [5, 'NOSCRIPT'],\n            [1, '#text', 'xxxxx xxxxxxx xxxxx'], // Masked because this string does not appear in the allowlist.\n            [7, 'A', ['href', '***']],\n            [1, '#text', '\\n                xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n              '],\n            [\n              9,\n              'IMG',\n              [\n                'src',\n                \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' style='background-color:silver'%3E%3C/svg%3E\",\n              ],\n            ],\n            [0, 'VIDEO', ['controls', '']],\n            [\n              1,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/webm'],\n            ],\n            [\n              0,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/mp4'],\n            ],\n            [0, 'P'],\n            [1, '#text', 'xxxx xxxxxxx xxxxxx xxxx xxx xxxxxxxx xxxxx xxxxx'],\n            [15, 'SELECT', ['value', '***']],\n            [1, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [3, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [5, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [22, 'INPUT', ['type', 'password']],\n            [0, 'INPUT', ['type', 'text']],\n            [0, 'INPUT', ['type', 'checkbox'], ['id', 'inputFoo'], ['name', '***'], ['value', '***']],\n            [0, 'LABEL', ['for', 'inputFoo']],\n            [1, '#text', 'xxxxxxxx xxxxx'],\n            [27, 'INPUT', ['type', 'radio'], ['id', 'bar-private'], ['name', '***'], ['value', '***']],\n            [0, 'TEXTAREA', ['id', 'baz'], ['name', '***'], ['rows', '2'], ['cols', '20'], ['value', '***']],\n            [1, '#text', '                xxxxxx xxxxx xxxxxxx xxx\\n              '],\n            [30, 'DIV', ['contenteditable', '']],\n            [1, '#text', 'xxxxxxxx xxxxxxx xxx'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, ['.example { color: red; }']],\n          [ChangeType.AttachedStyleSheets, [5, 0]],\n          [ChangeType.MediaPlaybackState, [20, PlaybackState.Paused]],\n        ])\n      })\n\n      it('matches the snapshot when the allowlist is not defined', async () => {\n        const html = createHtmlWithPrivacyAttributeValue(PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED)\n        const record = await serializeHtmlAsChange(html, { input: 'document' })\n        expect(record?.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [\n              0,\n              'HTML',\n              [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED],\n              ['style', 'width: 100%; height: 100%;'],\n            ],\n            [1, 'HEAD'],\n            [1, 'LINK', ['href', 'https://public.com/path/nested?query=param#hash'], ['rel', 'stylesheet']],\n            [0, 'STYLE'],\n            [0, 'META'],\n            [0, 'BASE'],\n            [0, 'TITLE'],\n            [1, '#text', 'xxxxxxx xxxxx'], // Masked because this string does not appear in the allowlist.\n            [8, 'BODY'],\n            [1, 'H1'],\n            [1, '#text', 'xxxxx xxxxxxx xxxxx'], // Masked because this string does not appear in the allowlist.\n            [3, 'P'],\n            [1, '#text', 'xxxxxx xxxxx xxxxxxx xxxx'],\n            [5, 'NOSCRIPT'],\n            [1, '#text', 'xxxxx xxxxxxx xxxxx'], // Masked because this string does not appear in the allowlist.\n            [7, 'A', ['href', '***']],\n            [1, '#text', '\\n                xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n              '],\n            [\n              9,\n              'IMG',\n              [\n                'src',\n                \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' style='background-color:silver'%3E%3C/svg%3E\",\n              ],\n            ],\n            [0, 'VIDEO', ['controls', '']],\n            [\n              1,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/webm'],\n            ],\n            [\n              0,\n              'SOURCE',\n              ['src', 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='],\n              ['type', 'video/mp4'],\n            ],\n            [0, 'P'],\n            [1, '#text', 'xxxx xxxxxxx xxxxxx xxxx xxx xxxxxxxx xxxxx xxxxx'],\n            [15, 'SELECT', ['value', '***']],\n            [1, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [3, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [5, 'OPTION', ['aria-label', '***']],\n            [1, '#text', '***'],\n            [22, 'INPUT', ['type', 'password']],\n            [0, 'INPUT', ['type', 'text']],\n            [0, 'INPUT', ['type', 'checkbox'], ['id', 'inputFoo'], ['name', '***'], ['value', '***']],\n            [0, 'LABEL', ['for', 'inputFoo']],\n            [1, '#text', 'xxxxxxxx xxxxx'],\n            [27, 'INPUT', ['type', 'radio'], ['id', 'bar-private'], ['name', '***'], ['value', '***']],\n            [0, 'TEXTAREA', ['id', 'baz'], ['name', '***'], ['rows', '2'], ['cols', '20'], ['value', '***']],\n            [1, '#text', '                xxxxxx xxxxx xxxxxxx xxx\\n              '],\n            [30, 'DIV', ['contenteditable', '']],\n            [1, '#text', 'xxxxxxxx xxxxxxx xxx'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, ['.example { color: red; }']],\n          [ChangeType.AttachedStyleSheets, [5, 0]],\n          [ChangeType.MediaPlaybackState, [20, PlaybackState.Paused]],\n        ])\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNodeAsChange.stylesheet.spec.ts",
    "content": "import { isAdoptedStyleSheetsSupported } from '../../../../../core/test'\nimport { ChangeType } from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { SerializationStats } from './serializationStats'\n\nimport { serializeHtmlAsChange } from './serializeHtml.specHelper'\n\ndescribe('serializeNodeAsChange for stylesheets', () => {\n  let originalTimeout: number\n\n  beforeAll(() => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000\n  })\n\n  afterAll(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout\n  })\n\n  const css = 'div { color: green; }'\n  const dynamicCss = 'span { color: red; }'\n\n  describe('for <style> elements', () => {\n    it('serializes the element', async () => {\n      const record = await serializeHtmlAsChange('<style id=\"foo\"></style>', {\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 0, max: 0, sum: 0 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'STYLE', ['id', 'foo']]]])\n    })\n\n    it('serializes multiple elements and aggregates their statistics', async () => {\n      const record = await serializeHtmlAsChange(\n        `\n        <div>\n          <style id=\"foo\">${css}</style>\n          <style id=\"bar\">${css}</style>\n        </div>\n        `,\n        {\n          after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n            expect(stats).toEqual({\n              cssText: { count: 2, max: 21, sum: 42 },\n              serializationDuration: jasmine.anything(),\n            })\n          },\n        }\n      )\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'DIV'], [1, 'STYLE', ['id', 'foo']], [0, 'STYLE', ['id', 'bar']]],\n        [ChangeType.AddStyleSheet, ['div { color: green; }'], ['div { color: green; }']],\n        [ChangeType.AttachedStyleSheets, [1, 0], [2, 1]],\n      ])\n    })\n\n    it('serializes the contents of the associated stylesheet', async () => {\n      const record = await serializeHtmlAsChange(`<style>${css}</style>`, {\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 1, max: 21, sum: 21 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'STYLE']],\n        [ChangeType.AddStyleSheet, [css]],\n        [ChangeType.AttachedStyleSheets, [0, 0]],\n      ])\n    })\n\n    it('serializes dynamically inserted CSS rules', async () => {\n      const record = await serializeHtmlAsChange('<style></style>', {\n        before(target: Node): void {\n          ;(target as HTMLStyleElement).sheet!.insertRule(dynamicCss)\n        },\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 1, max: 20, sum: 20 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'STYLE']],\n        [ChangeType.AddStyleSheet, [dynamicCss]],\n        [ChangeType.AttachedStyleSheets, [0, 0]],\n      ])\n    })\n\n    it('serializes a mix of static and dynamic CSS rules', async () => {\n      const record = await serializeHtmlAsChange(`<style>${css}</style>`, {\n        before(target: Node): void {\n          ;(target as HTMLStyleElement).sheet!.insertRule(dynamicCss)\n        },\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 1, max: 41, sum: 41 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'STYLE']],\n        [ChangeType.AddStyleSheet, [`${dynamicCss}${css}`]],\n        [ChangeType.AttachedStyleSheets, [0, 0]],\n      ])\n    })\n\n    it('serializes dynamically modified CSS rules', async () => {\n      const record = await serializeHtmlAsChange(`<style>${css}</style>`, {\n        before(target: Node): void {\n          const sheet = (target as HTMLStyleElement).sheet!\n          const rule = sheet.cssRules[0] as CSSStyleRule\n          rule.selectorText = 'span'\n          rule.style.color = 'red'\n        },\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 1, max: 20, sum: 20 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'STYLE']],\n        [ChangeType.AddStyleSheet, [dynamicCss]],\n        [ChangeType.AttachedStyleSheets, [0, 0]],\n      ])\n    })\n  })\n\n  describe('for <style> element children', () => {\n    it('does not serialize them', async () => {\n      const record = await serializeHtmlAsChange(`<style>${css}</style>`, { target: (node: Node) => node.firstChild! })\n      expect(record).toBeUndefined()\n    })\n  })\n\n  describe('for <link rel=\"stylesheet\"> elements', () => {\n    const sheet = {\n      href: 'https://datadoghq.invalid/some/style.css',\n      cssRules: [{ cssText: css }],\n    }\n\n    it('serializes the element when the sheet is accessible', async () => {\n      const record = await serializeHtmlAsChange(`<link rel=\"stylesheet\" href=\"${sheet.href}\">`, {\n        before(target: Node): void {\n          // Simulate a successful fetch of the stylesheet. (In reality, the fetch will\n          // fail, so `target.sheet` won't be populated by the browser.)\n          Object.defineProperty(target.ownerDocument, 'styleSheets', {\n            value: [sheet],\n            configurable: true,\n          })\n          Object.defineProperty(target, 'sheet', {\n            value: sheet,\n            configurable: true,\n          })\n        },\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 1, max: 21, sum: 21 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'LINK', ['rel', 'stylesheet'], ['href', sheet.href]]],\n        [ChangeType.AddStyleSheet, [css]],\n        [ChangeType.AttachedStyleSheets, [0, 0]],\n      ])\n    })\n\n    it('serializes the element when the sheet is unavailable', async () => {\n      const record = await serializeHtmlAsChange(`<link rel=\"stylesheet\" href=\"${sheet.href}\">`, {\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 0, max: 0, sum: 0 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([[ChangeType.AddNode, [null, 'LINK', ['rel', 'stylesheet'], ['href', sheet.href]]]])\n    })\n\n    it('serializes the element when the sheet is unreadable due to CORS', async () => {\n      const unreadableSheet = { ...sheet }\n      Object.defineProperty(unreadableSheet, 'cssRules', {\n        get() {\n          throw new Error('SecurityError')\n        },\n      })\n\n      const record = await serializeHtmlAsChange(`<link rel=\"stylesheet\" href=\"${sheet.href}\">`, {\n        before(target: Node): void {\n          // Simulate a successful fetch of the stylesheet which is unreadable due to CORS.\n          Object.defineProperty(target.ownerDocument, 'styleSheets', {\n            value: [unreadableSheet],\n            configurable: true,\n          })\n          Object.defineProperty(target, 'sheet', {\n            value: unreadableSheet,\n            configurable: true,\n          })\n        },\n        after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n          expect(stats).toEqual({\n            cssText: { count: 0, max: 0, sum: 0 },\n            serializationDuration: jasmine.anything(),\n          })\n        },\n      })\n      expect(record?.data).toEqual([\n        [ChangeType.AddNode, [null, 'LINK', ['rel', 'stylesheet'], ['href', unreadableSheet.href]]],\n      ])\n    })\n  })\n\n  describe('for documents with adopted stylesheets', () => {\n    it('serializes the stylesheet', async () => {\n      if (!isAdoptedStyleSheetsSupported()) {\n        pending('No adoptedStyleSheets support.')\n      }\n\n      const record = await serializeHtmlAsChange(\n        `\n        <!doctype HTML>\n        <div></div>\n        `,\n        {\n          input: 'document',\n          before(target: Node): void {\n            const document = target as Document\n            const window = document.defaultView!\n            const sheet = new window.CSSStyleSheet()\n            sheet.insertRule(css)\n            document.adoptedStyleSheets = [sheet]\n          },\n          after(_target: Node, _scope: RecordingScope, stats: SerializationStats): void {\n            expect(stats).toEqual({\n              cssText: { count: 1, max: 21, sum: 21 },\n              serializationDuration: jasmine.anything(),\n            })\n          },\n        }\n      )\n      expect(record?.data).toEqual([\n        [\n          ChangeType.AddNode,\n          [null, '#document'],\n          [1, '#doctype', 'html', '', ''],\n          [0, 'HTML'],\n          [1, 'HEAD'],\n          [0, 'BODY'],\n          [1, 'DIV'],\n        ],\n        [ChangeType.ScrollPosition, [0, 0, 0]],\n        [ChangeType.AddStyleSheet, [[css]]],\n        [ChangeType.AttachedStyleSheets, [0, 0]],\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeNodeAsChange.ts",
    "content": "import {\n  reducePrivacyLevel,\n  getNodeSelfPrivacyLevel,\n  getTextContent,\n  isNodeShadowRoot,\n  forEachChildNodes,\n  NodePrivacyLevel,\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_HIDDEN,\n  getScrollX,\n  getScrollY,\n  isElementNode,\n} from '@datadog/browser-rum-core'\nimport { MediaInteractionType } from '../../../types'\nimport type { NodeId, StyleSheetId } from '../itemIds'\nimport type { InsertionCursor } from './insertionCursor'\nimport type { ChangeSerializationTransaction } from './serializationTransaction'\nimport { serializeDOMAttributes, serializeVirtualAttributes } from './serializeAttributes'\n\nexport function serializeNodeAsChange(\n  cursor: InsertionCursor,\n  node: Node,\n  parentPrivacyLevel: NodePrivacyLevel,\n  transaction: ChangeSerializationTransaction\n): void {\n  // Ignore the children of <style> elements; the CSS rules they contain are already\n  // serialized as StyleSheetSnapshots.\n  if (node.parentNode?.nodeName === 'STYLE') {\n    return\n  }\n\n  // Never serialize the descendants of HIDDEN or IGNORE'd elements.\n  if (parentPrivacyLevel === NodePrivacyLevel.HIDDEN || parentPrivacyLevel === NodePrivacyLevel.IGNORE) {\n    return\n  }\n\n  let privacyLevel: NodePrivacyLevel\n\n  const selfPrivacyLevel = getNodeSelfPrivacyLevel(node)\n  if (selfPrivacyLevel) {\n    privacyLevel = reducePrivacyLevel(selfPrivacyLevel, parentPrivacyLevel)\n  } else {\n    privacyLevel = parentPrivacyLevel\n  }\n\n  if (privacyLevel === NodePrivacyLevel.HIDDEN) {\n    serializeHiddenNodePlaceholder(cursor, node, transaction)\n    return\n  }\n\n  // Totally ignore risky or unwanted elements. (e.g. <script>, some <link> and <meta> elements)\n  if (privacyLevel === NodePrivacyLevel.IGNORE) {\n    return\n  }\n\n  switch (node.nodeType) {\n    case node.CDATA_SECTION_NODE:\n      serializeCDataNodeAsChange(cursor, node as CDATASection, transaction)\n      break\n    case node.DOCUMENT_NODE:\n      serializeDocumentNodeAsChange(cursor, node as Document, transaction)\n      break\n    case node.DOCUMENT_FRAGMENT_NODE:\n      serializeDocumentFragmentNodeAsChange(cursor, node as DocumentFragment, transaction)\n      break\n    case node.DOCUMENT_TYPE_NODE:\n      serializeDocumentTypeNodeAsChange(cursor, node as DocumentType, transaction)\n      break\n    case node.ELEMENT_NODE:\n      serializeElementNodeAsChange(cursor, node as Element, privacyLevel, transaction)\n      break\n    case node.TEXT_NODE:\n      serializeTextNodeAsChange(cursor, node as Text, privacyLevel, transaction)\n      break\n    default:\n      return\n  }\n\n  // If this node can't have children, we're done.\n  switch (node.nodeType) {\n    case node.CDATA_SECTION_NODE:\n    case node.DOCUMENT_TYPE_NODE:\n    case node.TEXT_NODE:\n      return\n  }\n\n  cursor.descend()\n  forEachChildNodes(node, (childNode) => {\n    serializeNodeAsChange(cursor, childNode, privacyLevel, transaction)\n  })\n  cursor.ascend()\n}\n\nfunction serializeDocumentNodeAsChange(\n  cursor: InsertionCursor,\n  document: Document,\n  transaction: ChangeSerializationTransaction\n): void {\n  const { nodeId, insertionPoint } = cursor.advance(document)\n  transaction.addNode(insertionPoint, '#document')\n  transaction.setScrollPosition(nodeId, getScrollX(), getScrollY())\n  serializeStyleSheetsAsChange(document.adoptedStyleSheets, nodeId, transaction)\n}\n\nfunction serializeDocumentFragmentNodeAsChange(\n  cursor: InsertionCursor,\n  documentFragment: DocumentFragment,\n  transaction: ChangeSerializationTransaction\n): void {\n  const { nodeId, insertionPoint } = cursor.advance(documentFragment)\n  const isShadowRoot = isNodeShadowRoot(documentFragment)\n  if (!isShadowRoot) {\n    transaction.addNode(insertionPoint, '#document-fragment')\n    return\n  }\n\n  transaction.addNode(insertionPoint, '#shadow-root')\n  transaction.scope.shadowRootsController.addShadowRoot(documentFragment, transaction.scope)\n  serializeStyleSheetsAsChange(documentFragment.adoptedStyleSheets, nodeId, transaction)\n}\n\nfunction serializeDocumentTypeNodeAsChange(\n  cursor: InsertionCursor,\n  documentType: DocumentType,\n  transaction: ChangeSerializationTransaction\n): void {\n  const { insertionPoint } = cursor.advance(documentType)\n  transaction.addNode(insertionPoint, '#doctype', documentType.name, documentType.publicId, documentType.systemId)\n}\n\nfunction serializeElementNodeAsChange(\n  cursor: InsertionCursor,\n  element: Element,\n  privacyLevel: NodePrivacyLevel,\n  transaction: ChangeSerializationTransaction\n): void {\n  const { nodeId, insertionPoint } = cursor.advance(element)\n  const domAttributes = Object.entries(serializeDOMAttributes(element, privacyLevel, transaction))\n  transaction.addNode(insertionPoint, encodedElementName(element), ...domAttributes)\n\n  const {\n    _cssText: cssText,\n    rr_mediaState: mediaState,\n    rr_scrollLeft: scrollLeft,\n    rr_scrollTop: scrollTop,\n  } = serializeVirtualAttributes(element, privacyLevel, transaction)\n\n  const linkOrStyle = element as HTMLLinkElement | HTMLStyleElement\n  if (cssText !== undefined && linkOrStyle.sheet) {\n    const sheetId = transaction.scope.styleSheetIds.getOrInsert(linkOrStyle.sheet)\n    transaction.addStyleSheet(cssText)\n    transaction.attachStyleSheets(nodeId, [sheetId])\n  }\n\n  if (mediaState === 'played') {\n    transaction.setMediaPlaybackState(nodeId, MediaInteractionType.Play)\n  } else if (mediaState === 'paused') {\n    transaction.setMediaPlaybackState(nodeId, MediaInteractionType.Pause)\n  }\n\n  if (scrollLeft !== undefined || scrollTop !== undefined) {\n    transaction.setScrollPosition(nodeId, scrollLeft || 0, scrollTop || 0)\n  }\n}\n\nfunction serializeTextNodeAsChange(\n  cursor: InsertionCursor,\n  textNode: Text,\n  privacyLevel: NodePrivacyLevel,\n  transaction: ChangeSerializationTransaction\n): void {\n  const textContent = getTextContent(textNode, privacyLevel)\n  if (textContent === undefined) {\n    return\n  }\n  const { insertionPoint } = cursor.advance(textNode)\n  transaction.addNode(insertionPoint, '#text', textContent)\n}\n\nfunction serializeCDataNodeAsChange(\n  cursor: InsertionCursor,\n  cdataNode: CDATASection,\n  transaction: ChangeSerializationTransaction\n): void {\n  const { insertionPoint } = cursor.advance(cdataNode)\n  transaction.addNode(insertionPoint, '#cdata-section')\n}\n\nfunction serializeHiddenNodePlaceholder(\n  cursor: InsertionCursor,\n  node: Node,\n  transaction: ChangeSerializationTransaction\n): void {\n  // We only generate placeholders for element nodes; other hidden nodes are simply not\n  // serialized.\n  if (!isElementNode(node)) {\n    return\n  }\n\n  const { nodeId, insertionPoint } = cursor.advance(node)\n  transaction.addNode(insertionPoint, encodedElementName(node), [PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_HIDDEN])\n  const { width, height } = node.getBoundingClientRect()\n  transaction.setSize(nodeId, width, height)\n}\n\nfunction serializeStyleSheetsAsChange(\n  sheets: CSSStyleSheet[] | undefined,\n  nodeId: NodeId,\n  transaction: ChangeSerializationTransaction\n): void {\n  if (!sheets || sheets.length === 0) {\n    return undefined\n  }\n\n  transaction.attachStyleSheets(\n    nodeId,\n    sheets.map((sheet) => serializeStyleSheetAsChange(sheet, transaction))\n  )\n}\n\nfunction serializeStyleSheetAsChange(sheet: CSSStyleSheet, transaction: ChangeSerializationTransaction): StyleSheetId {\n  const rules = Array.from(sheet.cssRules || sheet.rules, (rule) => rule.cssText)\n  const mediaList = sheet.media.length > 0 ? Array.from(sheet.media) : undefined\n  transaction.addMetric(\n    'cssText',\n    rules.reduce((totalLength, rule) => totalLength + rule.length, 0)\n  )\n  transaction.addStyleSheet(rules, mediaList, sheet.disabled)\n  return transaction.scope.styleSheetIds.getOrInsert(sheet)\n}\n\nfunction encodedElementName(element: Element): Exclude<string, `#${string}`> {\n  const nodeName = element.nodeName\n  if (isSVGElement(element)) {\n    return `svg>${nodeName}`\n  }\n  return nodeName\n}\n\nfunction isSVGElement(element: Element): element is SVGElement {\n  return element.namespaceURI === 'http://www.w3.org/2000/svg'\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeStyleSheets.spec.ts",
    "content": "import { isAdoptedStyleSheetsSupported } from '@datadog/browser-core/test'\nimport { createSerializationTransactionForTesting } from '../test/serialization.specHelper'\nimport { serializeStyleSheets } from './serializeStyleSheets'\nimport type { SerializationStats } from './serializationStats'\nimport { createSerializationStats } from './serializationStats'\nimport type { SerializationTransaction } from './serializationTransaction'\n\ndescribe('serializeStyleSheets', () => {\n  let stats: SerializationStats\n  let transaction: SerializationTransaction\n\n  beforeEach(() => {\n    if (!isAdoptedStyleSheetsSupported()) {\n      pending('no adoptedStyleSheets support')\n    }\n    stats = createSerializationStats()\n    transaction = createSerializationTransactionForTesting({ stats })\n  })\n\n  it('should return undefined if no stylesheets', () => {\n    expect(serializeStyleSheets(undefined, transaction)).toBe(undefined)\n    expect(stats.cssText).toEqual({ count: 0, max: 0, sum: 0 })\n    expect(serializeStyleSheets([], transaction)).toBe(undefined)\n    expect(stats.cssText).toEqual({ count: 0, max: 0, sum: 0 })\n  })\n\n  it('should return serialized stylesheet', () => {\n    const disabledStylesheet = new CSSStyleSheet({ disabled: true })\n    disabledStylesheet.insertRule('div { width: 100%; }')\n    const printStylesheet = new CSSStyleSheet({ disabled: false, media: 'print' })\n    printStylesheet.insertRule('a { color: red; }')\n\n    expect(serializeStyleSheets([disabledStylesheet, printStylesheet], transaction)).toEqual([\n      { cssRules: ['div { width: 100%; }'], disabled: true, media: undefined },\n      { cssRules: ['a { color: red; }'], disabled: undefined, media: ['print'] },\n    ])\n    expect(stats.cssText).toEqual({ count: 2, max: 20, sum: 37 })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/serialization/serializeStyleSheets.ts",
    "content": "import type { StyleSheet } from '../../../types'\nimport type { SerializationTransaction } from './serializationTransaction'\n\nexport function serializeStyleSheets(\n  cssStyleSheets: CSSStyleSheet[] | undefined,\n  transaction: SerializationTransaction\n): StyleSheet[] | undefined {\n  if (cssStyleSheets === undefined || cssStyleSheets.length === 0) {\n    return undefined\n  }\n  const serializeStylesheet = (cssStyleSheet: CSSStyleSheet) => {\n    const rules = cssStyleSheet.cssRules || cssStyleSheet.rules\n    const cssRules = Array.from(rules, (cssRule) => cssRule.cssText)\n    transaction.addMetric(\n      'cssText',\n      cssRules.reduce((totalLength, rule) => totalLength + rule.length, 0)\n    )\n\n    const styleSheet: StyleSheet = {\n      cssRules,\n      disabled: cssStyleSheet.disabled || undefined,\n      media: cssStyleSheet.media.length > 0 ? Array.from(cssStyleSheet.media) : undefined,\n    }\n    return styleSheet\n  }\n  // Safari iOS 16.x implements adoptedStyleSheets as a FrozenArray that:\n  // - can't be iterated over through map or for...of\n  // - can't be converted to regular array with Array.from\n  // - can't be detected with Array.isArray or Object.isFrozen\n  // Use index access to avoid the issue\n  const styleSheets: StyleSheet[] = []\n  for (let index = 0; index < cssStyleSheets.length; index++) {\n    styleSheets.push(serializeStylesheet(cssStyleSheets[index]))\n  }\n  return styleSheets\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/serializationVerifier.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport { IncrementalSource, RecordType } from '../../types'\nimport type {\n  AttributeMutation,\n  BrowserChangeRecord,\n  BrowserFullSnapshotRecord,\n  BrowserIncrementalSnapshotRecord,\n  BrowserRecord,\n  RemovedNodeMutation,\n} from '../../types'\nimport type { EmitRecordCallback, SerializeEvent } from './record.types'\nimport { createRecordingScope } from './recordingScope'\nimport type { RecordingScope } from './recordingScope'\nimport type { ShadowRootsController } from './shadowRootsController'\nimport {\n  createChangeConverter,\n  createCopyingNodeIdRemapper,\n  serializeFullSnapshotAsChange,\n  serializeMutationsAsChange,\n} from './serialization'\nimport type { NodeId } from './itemIds'\n\n/**\n * SerializationVerifier compares the output of the V1 and Change serialization\n * algorithms. It's designed to seamlessly add verification to existing test suites which\n * are written against the V1 serialization algorithm.\n *\n * To use it, create a SerializationVerifier configured with the same RecordingScope used\n * by the current test. The SerializationVerifier will automatically listen for V1\n * serializations being performed by the test code and will perform the corresponding\n * Change serialization. It will then convert the resulting BrowserChangeRecord to the old\n * V1 format and compare the results to verify that the two algorithms produce the same\n * output.\n */\nexport interface SerializationVerifier {\n  stop(this: void): void\n}\n\nexport type OnVerificationError = (message: string, context?: any) => void\n\nexport function createSerializationVerifier(\n  scope: RecordingScope,\n  onError: OnVerificationError\n): SerializationVerifier {\n  // Node id numbering differs between the V1 and Change serialization\n  // algorithms, so if we want to be able to compare their output, we need to replace the\n  // 'input' node ids in each Change record with the 'output' node ids produced by the V1\n  // serialization algorithm. This NodeIdRemapper will handle that task.\n  const nodeIdRemapper = createCopyingNodeIdRemapper()\n  scope.nodeIds = nodeIdRemapper.outputNodeIds\n\n  // Create a separate recording scope to use for Change serialization.\n  const changeScope = createRecordingScope(scope.configuration, scope.elementsScrollPositions, {\n    addShadowRoot: noop,\n    removeShadowRoot: noop,\n    flush: noop,\n    stop: noop,\n  } as ShadowRootsController)\n  changeScope.nodeIds = nodeIdRemapper.inputNodeIds\n\n  // Create the converter that we'll use to transform the records generated by Change\n  // serialization into the V1 format.\n  let converter = createChangeConverter()\n\n  const { unsubscribe } = scope.serializeObservable.subscribe((event: SerializeEvent) => {\n    let changeRecord: BrowserRecord | undefined\n    const emitRecord: EmitRecordCallback = (record: BrowserRecord): void => {\n      changeRecord = record\n    }\n\n    switch (event.type) {\n      case 'full':\n        // Create a new converter since we've transitioned to a new view.\n        converter = createChangeConverter()\n\n        serializeFullSnapshotAsChange(event.timestamp, event.kind, event.target, emitRecord, noop, changeScope)\n        break\n\n      case 'incremental':\n        serializeMutationsAsChange(event.timestamp, event.target, emitRecord, noop, changeScope)\n        break\n\n      default:\n        event satisfies never\n        return\n    }\n\n    if (!changeRecord) {\n      onError('No change record serialized', event)\n      return\n    }\n\n    try {\n      const v1Record = event.v1\n      const convertedChangeRecord = converter.convert(changeRecord as BrowserChangeRecord, {\n        nodeIdRemapper,\n        timestamp: v1Record.timestamp,\n      })\n\n      verifySnapshotsMatch(v1Record, convertedChangeRecord, onError)\n    } catch (error) {\n      onError('Error verifying change record', error)\n    }\n  })\n\n  return {\n    stop: unsubscribe,\n  }\n}\n\nfunction verifySnapshotsMatch(\n  expectedRecord: BrowserFullSnapshotRecord | BrowserIncrementalSnapshotRecord,\n  actualRecord: BrowserFullSnapshotRecord | BrowserIncrementalSnapshotRecord,\n  onError: OnVerificationError\n): void {\n  if (\n    expectedRecord.type !== RecordType.IncrementalSnapshot ||\n    expectedRecord.data.source !== IncrementalSource.Mutation ||\n    actualRecord.type !== RecordType.IncrementalSnapshot ||\n    actualRecord.data.source !== IncrementalSource.Mutation\n  ) {\n    // We expect full snapshots to be byte-for-byte equivalent, full stop.\n    verifyByteForByteEquivalence('full snapshot', expectedRecord, actualRecord, onError)\n    return\n  }\n\n  // Verify that everything but the data is byte-for-byte equivalent.\n  verifyByteForByteEquivalence(\n    'incremental snapshot wrapper',\n    { ...expectedRecord, data: null },\n    { ...actualRecord, data: null },\n    onError\n  )\n\n  // Within the data, verify that everything but attribute mutations and node remove\n  // mutations are byte-for-byte equivalent.\n  verifyByteForByteEquivalence(\n    'incremental snapshot data (without attributes and removes)',\n    { ...expectedRecord.data, attributes: null, removes: null },\n    { ...actualRecord.data, attributes: null, removes: null },\n    onError\n  )\n\n  // Verify that the attribute mutations are byte-for-byte equivalent except for order.\n  const orderAttributeMutations = (a: AttributeMutation, b: AttributeMutation): number => a.id - b.id\n  verifyByteForByteEquivalence(\n    'incremental snapshot attribute mutations',\n    expectedRecord.data.attributes.sort(orderAttributeMutations),\n    actualRecord.data.attributes.sort(orderAttributeMutations),\n    onError\n  )\n\n  // Gather the set of removes performed by V1 serialization.\n  const expectedRemoves = expectedRecord.data.removes\n  const expectedRemovedNodes = new Set<NodeId>()\n  for (const remove of expectedRemoves) {\n    expectedRemovedNodes.add(remove.id as NodeId)\n  }\n\n  // Gather the set of removes performed by Change serialization. Change serialization is\n  // more conservative about remove reporting, so it will report some removes that V1\n  // serialization deliberately skips. To paper over that difference, we filter out\n  // removes that V1 serialization didn't also report.\n  const actualRemoves: RemovedNodeMutation[] = actualRecord.data.removes.filter((remove) =>\n    expectedRemovedNodes.has(remove.id as NodeId)\n  )\n\n  // Verify that the removes that remain are byte-for-byte equivalent.\n  verifyByteForByteEquivalence('incremental snapshot removes', expectedRemoves, actualRemoves, onError)\n}\n\nfunction verifyByteForByteEquivalence(\n  context: string,\n  expected: unknown,\n  actual: unknown,\n  onError: OnVerificationError\n): void {\n  const expectedString = JSON.stringify(expected)\n  const actualString = JSON.stringify(actual)\n  if (actualString !== expectedString) {\n    onError('Serialization mismatch', {\n      context,\n      mismatch: createSerializationMismatchContext(expectedString, actualString),\n    })\n  }\n}\n\nfunction createSerializationMismatchContext(expected: string, actual: string): Record<string, string> {\n  const length = Math.min(expected.length, actual.length)\n  try {\n    let firstDifferenceIndex = 0\n    while (firstDifferenceIndex < length && expected[firstDifferenceIndex] === actual[firstDifferenceIndex]) {\n      firstDifferenceIndex++\n    }\n    return {\n      expected: getStringNearPosition(expected, firstDifferenceIndex),\n      actual: getStringNearPosition(actual, firstDifferenceIndex),\n    }\n  } catch (e) {\n    return { firstDifferenceError: JSON.stringify(e) }\n  }\n}\n\nfunction getStringNearPosition(str: string, index: number): string {\n  const leftContextStart = Math.max(index - 50, 0)\n  const rightContextEnd = Math.min(index + 150, str.length)\n  return `${str.substring(leftContextStart, index)}(!)${str.substring(index, rightContextEnd)}`\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/shadowRootsController.ts",
    "content": "import type { RecordingScope } from './recordingScope.ts'\nimport type { EmitRecordCallback, EmitStatsCallback } from './record.types'\nimport { trackInput, trackMutation, trackScroll } from './trackers'\n\ninterface ShadowRootController {\n  stop: () => void\n  flush: () => void\n}\n\nexport type AddShadowRootCallBack = (shadowRoot: ShadowRoot, scope: RecordingScope) => void\nexport type RemoveShadowRootCallBack = (shadowRoot: ShadowRoot) => void\n\nexport interface ShadowRootsController {\n  addShadowRoot: AddShadowRootCallBack\n  removeShadowRoot: RemoveShadowRootCallBack\n  stop: () => void\n  flush: () => void\n}\n\nexport const initShadowRootsController = (\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback\n): ShadowRootsController => {\n  const controllerByShadowRoot = new Map<ShadowRoot, ShadowRootController>()\n\n  const shadowRootsController: ShadowRootsController = {\n    addShadowRoot: (shadowRoot: ShadowRoot, scope: RecordingScope) => {\n      if (controllerByShadowRoot.has(shadowRoot)) {\n        return\n      }\n      const mutationTracker = trackMutation(shadowRoot, emitRecord, emitStats, scope)\n      // The change event does not bubble up across the shadow root, we have to listen on the shadow root\n      const inputTracker = trackInput(shadowRoot, emitRecord, scope)\n      // The scroll event does not bubble up across the shadow root, we have to listen on the shadow root\n      const scrollTracker = trackScroll(shadowRoot, emitRecord, scope)\n      controllerByShadowRoot.set(shadowRoot, {\n        flush: () => mutationTracker.flush(),\n        stop: () => {\n          mutationTracker.stop()\n          inputTracker.stop()\n          scrollTracker.stop()\n        },\n      })\n    },\n    removeShadowRoot: (shadowRoot: ShadowRoot) => {\n      const entry = controllerByShadowRoot.get(shadowRoot)\n      if (!entry) {\n        // unidentified root cause: observed in some cases with shadow DOM added by browser extensions\n        return\n      }\n      entry.stop()\n      controllerByShadowRoot.delete(shadowRoot)\n    },\n    stop: () => {\n      controllerByShadowRoot.forEach(({ stop }) => stop())\n    },\n    flush: () => {\n      controllerByShadowRoot.forEach(({ flush }) => flush())\n    },\n  }\n  return shadowRootsController\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/startFullSnapshots.spec.ts",
    "content": "import type { ViewCreatedEvent } from '@datadog/browser-rum-core'\nimport { LifeCycle, LifeCycleEventType } from '@datadog/browser-rum-core'\nimport type { TimeStamp } from '@datadog/browser-core'\nimport { addExperimentalFeatures, ExperimentalFeature, noop } from '@datadog/browser-core'\nimport type { BrowserRecord } from '../../types'\nimport { RecordType, SnapshotFormat } from '../../types'\nimport { appendElement } from '../../../../rum-core/test'\nimport { startFullSnapshots } from './startFullSnapshots'\nimport type { EmitRecordCallback, EmitStatsCallback } from './record.types'\nimport { createRecordingScopeForTesting } from './test/recordingScope.specHelper'\n\nconst describeStartFullSnapshotsWithExpectedSnapshot = (fullSnapshotRecord: jasmine.Expected<BrowserRecord>) => {\n  const viewStartClock = { relative: 1, timeStamp: 1 as TimeStamp }\n  let lifeCycle: LifeCycle\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let emitStatsCallback: jasmine.Spy<EmitStatsCallback>\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    emitRecordCallback = jasmine.createSpy()\n    emitStatsCallback = jasmine.createSpy()\n\n    appendElement('<style>body { width: 100%; }</style>', document.head)\n\n    const scope = createRecordingScopeForTesting()\n    startFullSnapshots(lifeCycle, emitRecordCallback, emitStatsCallback, noop, scope)\n  })\n\n  it('takes a full snapshot when startFullSnapshots is called', () => {\n    expect(emitRecordCallback).toHaveBeenCalled()\n  })\n\n  it('takes a full snapshot when the view changes', () => {\n    emitRecordCallback.calls.reset()\n\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, {\n      startClocks: viewStartClock,\n    } as Partial<ViewCreatedEvent> as any)\n\n    expect(emitRecordCallback).toHaveBeenCalled()\n  })\n\n  it('full snapshot related records should have the view change date', () => {\n    emitRecordCallback.calls.reset()\n\n    lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, {\n      startClocks: viewStartClock,\n    } as Partial<ViewCreatedEvent> as any)\n\n    const records = emitRecordCallback.calls.allArgs().map((args) => args[0])\n    expect(records[0].timestamp).toEqual(1)\n    expect(records[1].timestamp).toEqual(1)\n    expect(records[2].timestamp).toEqual(1)\n  })\n\n  it('full snapshot records should contain Meta, Focus, FullSnapshot', () => {\n    const records = emitRecordCallback.calls.allArgs().map((args) => args[0])\n\n    expect(records).toEqual(\n      jasmine.arrayContaining([\n        {\n          data: {\n            height: jasmine.any(Number),\n            href: window.location.href,\n            width: jasmine.any(Number),\n          },\n          type: RecordType.Meta,\n          timestamp: jasmine.any(Number),\n        },\n        {\n          data: {\n            has_focus: document.hasFocus(),\n          },\n          type: RecordType.Focus,\n          timestamp: jasmine.any(Number),\n        },\n        fullSnapshotRecord,\n      ])\n    )\n  })\n\n  it('full snapshot records should contain visualViewport when supported', () => {\n    if (!window.visualViewport) {\n      pending('visualViewport not supported')\n    }\n    const record = emitRecordCallback.calls.mostRecent().args[0]\n\n    expect(record).toEqual({\n      data: jasmine.any(Object),\n      type: RecordType.VisualViewport,\n      timestamp: jasmine.any(Number),\n    })\n  })\n\n  it('full snapshot records should be emitted with serialization stats', () => {\n    expect(emitStatsCallback.calls.mostRecent().args[0]).toEqual({\n      cssText: { count: 1, max: 21, sum: 21 },\n      serializationDuration: jasmine.anything(),\n    })\n  })\n}\n\ndescribe('startFullSnapshots', () => {\n  describe('when generating BrowserFullSnapshotV1Record', () => {\n    describeStartFullSnapshotsWithExpectedSnapshot({\n      data: {\n        node: jasmine.any(Object),\n        initialOffset: {\n          left: jasmine.any(Number),\n          top: jasmine.any(Number),\n        },\n      },\n      format: SnapshotFormat.V1,\n      type: RecordType.FullSnapshot,\n      timestamp: jasmine.any(Number),\n    })\n  })\n\n  describe('when generating BrowserFullSnapshotChangeRecord', () => {\n    beforeEach(() => {\n      addExperimentalFeatures([ExperimentalFeature.USE_CHANGE_RECORDS])\n    })\n\n    describeStartFullSnapshotsWithExpectedSnapshot({\n      data: jasmine.any(Array),\n      format: SnapshotFormat.Change,\n      type: RecordType.FullSnapshot,\n      timestamp: jasmine.any(Number),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/startFullSnapshots.ts",
    "content": "import { LifeCycleEventType, getViewportDimension } from '@datadog/browser-rum-core'\nimport type { LifeCycle } from '@datadog/browser-rum-core'\nimport { timeStampNow } from '@datadog/browser-core'\nimport type { TimeStamp } from '@datadog/browser-core'\nimport { RecordType } from '../../types'\nimport {\n  isFullSnapshotChangeRecordsEnabled,\n  SerializationKind,\n  serializeFullSnapshotAsChange,\n  serializeFullSnapshot,\n} from './serialization'\nimport { getVisualViewport } from './viewports'\nimport type { RecordingScope } from './recordingScope'\nimport type { EmitRecordCallback, EmitStatsCallback } from './record.types'\n\nexport type SerializeFullSnapshotCallback = (\n  timestamp: TimeStamp,\n  kind: SerializationKind,\n  document: Document,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope\n) => void\n\nexport function startFullSnapshots(\n  lifeCycle: LifeCycle,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  flushMutations: () => void,\n  scope: RecordingScope,\n  serialize: SerializeFullSnapshotCallback = defaultSerializeFullSnapshotCallback()\n) {\n  takeFullSnapshot(timeStampNow(), SerializationKind.INITIAL_FULL_SNAPSHOT, emitRecord, emitStats, scope, serialize)\n\n  const { unsubscribe } = lifeCycle.subscribe(LifeCycleEventType.VIEW_CREATED, (view) => {\n    flushMutations()\n    takeFullSnapshot(\n      view.startClocks.timeStamp,\n      SerializationKind.SUBSEQUENT_FULL_SNAPSHOT,\n      emitRecord,\n      emitStats,\n      scope,\n      serialize\n    )\n  })\n\n  return {\n    stop: unsubscribe,\n  }\n}\n\nexport function takeFullSnapshot(\n  timestamp: TimeStamp,\n  kind: SerializationKind,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope,\n  serialize: SerializeFullSnapshotCallback = defaultSerializeFullSnapshotCallback()\n): void {\n  const { width, height } = getViewportDimension()\n  emitRecord({\n    data: {\n      height,\n      href: window.location.href,\n      width,\n    },\n    type: RecordType.Meta,\n    timestamp,\n  })\n\n  emitRecord({\n    data: {\n      has_focus: document.hasFocus(),\n    },\n    type: RecordType.Focus,\n    timestamp,\n  })\n\n  serialize(timestamp, kind, document, emitRecord, emitStats, scope)\n\n  if (window.visualViewport) {\n    emitRecord({\n      data: getVisualViewport(window.visualViewport),\n      type: RecordType.VisualViewport,\n      timestamp,\n    })\n  }\n}\n\nfunction defaultSerializeFullSnapshotCallback(): SerializeFullSnapshotCallback {\n  return isFullSnapshotChangeRecordsEnabled() ? serializeFullSnapshotAsChange : serializeFullSnapshot\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/test/recordingScope.specHelper.ts",
    "content": "import type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { noop } from '@datadog/browser-core'\nimport { createElementsScrollPositions } from '../elementsScrollPositions'\nimport type { RecordingScope } from '../recordingScope'\nimport { createRecordingScope } from '../recordingScope'\nimport type { AddShadowRootCallBack, RemoveShadowRootCallBack } from '../shadowRootsController'\nimport { DEFAULT_CONFIGURATION } from './rumConfiguration.specHelper'\nimport { DEFAULT_SHADOW_ROOT_CONTROLLER } from './shadowRootsController.specHelper'\n\nexport function createRecordingScopeForTesting({\n  configuration,\n  addShadowRoot,\n  removeShadowRoot,\n}: {\n  configuration?: Partial<RumConfiguration>\n  addShadowRoot?: AddShadowRootCallBack\n  removeShadowRoot?: RemoveShadowRootCallBack\n} = {}): RecordingScope {\n  return createRecordingScope(\n    (configuration as RumConfiguration) || { ...DEFAULT_CONFIGURATION },\n    createElementsScrollPositions(),\n    {\n      ...DEFAULT_SHADOW_ROOT_CONTROLLER,\n      addShadowRoot: addShadowRoot || noop,\n      removeShadowRoot: removeShadowRoot || noop,\n    }\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/test/rumConfiguration.specHelper.ts",
    "content": "import { NodePrivacyLevel } from '@datadog/browser-rum-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\n\nexport const DEFAULT_CONFIGURATION = { defaultPrivacyLevel: NodePrivacyLevel.ALLOW } as RumConfiguration\n"
  },
  {
    "path": "packages/rum/src/domain/record/test/serialization.specHelper.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport { noop, timeStampNow } from '@datadog/browser-core'\nimport { RecordType, SnapshotFormat } from '../../../types'\nimport type {\n  BrowserChangeRecord,\n  BrowserFullSnapshotChangeRecord,\n  BrowserFullSnapshotRecord,\n  BrowserFullSnapshotV1Record,\n  BrowserRecord,\n  DocumentNode,\n  ElementNode,\n  SerializedNodeWithId,\n} from '../../../types'\nimport type { NodeId } from '../itemIds'\nimport type { RecordingScope } from '../recordingScope'\nimport type {\n  ChangeSerializationTransaction,\n  ParentNodePrivacyLevel,\n  SerializationStats,\n  SerializationTransaction,\n} from '../serialization'\nimport {\n  serializeNode,\n  SerializationKind,\n  serializeFullSnapshot,\n  updateSerializationStats,\n  serializeChangesInTransaction,\n  createRootInsertionCursor,\n  serializeNodeAsChange,\n  createChangeConverter,\n} from '../serialization'\nimport { createRecordingScopeForTesting } from './recordingScope.specHelper'\n\nexport function createSerializationTransactionForTesting({\n  kind,\n  scope,\n  stats,\n}: {\n  kind?: SerializationKind\n  scope?: RecordingScope\n  stats?: SerializationStats\n} = {}): SerializationTransaction {\n  const transactionScope = scope || createRecordingScopeForTesting()\n  return {\n    add(): void {\n      throw new Error('Use serializeInTransaction normally to test code that generates BrowserRecords.')\n    },\n    addMetric(metric: keyof SerializationStats, value: number): void {\n      if (stats) {\n        updateSerializationStats(stats, metric, value)\n      }\n    },\n    assignId(node: Node): NodeId {\n      return transactionScope.nodeIds.getOrInsert(node)\n    },\n    kind: kind ?? SerializationKind.INITIAL_FULL_SNAPSHOT,\n    scope: transactionScope,\n  }\n}\n\nexport function takeFullSnapshotForTesting(scope: RecordingScope): DocumentNode & SerializedNodeWithId {\n  let node: DocumentNode & SerializedNodeWithId\n  const emitRecord = (record: BrowserRecord) => {\n    // Tests want to assert against the serialized node representation of the document,\n    // not the record that would contain it if we emitted it, so we just extract it here.\n    const fullSnapshotRecord = record as BrowserFullSnapshotRecord\n    if (fullSnapshotRecord.format === SnapshotFormat.Change) {\n      throw new Error('Full snapshot has unexpected format')\n    }\n    node = fullSnapshotRecord.data.node as DocumentNode & SerializedNodeWithId\n  }\n\n  serializeFullSnapshot(0 as TimeStamp, SerializationKind.INITIAL_FULL_SNAPSHOT, document, emitRecord, noop, scope)\n\n  return node!\n}\n\n/**\n * A drop-in replacement for serializeNode() that verifies that serializeNodeAsChange()\n * produces an identical result, failing the running test if it does not.\n */\nexport function serializeNodeAndVerifyChangeRecord(\n  node: Element,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): (SerializedNodeWithId & ElementNode) | null\nexport function serializeNodeAndVerifyChangeRecord(\n  node: Node,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): SerializedNodeWithId | null\nexport function serializeNodeAndVerifyChangeRecord(\n  node: Node,\n  parentNodePrivacyLevel: ParentNodePrivacyLevel,\n  transaction: SerializationTransaction\n): SerializedNodeWithId | null {\n  const serializedNode = serializeNode(node, parentNodePrivacyLevel, transaction)\n\n  // Create an isolated recording scope for calling serializeNodeAsChange(). We do need to\n  // share the ElementsScrollPositions value, because some serialization tests manually\n  // manipulate its contents.\n  const changeScope = createRecordingScopeForTesting()\n  changeScope.elementsScrollPositions = transaction.scope.elementsScrollPositions\n\n  let changeRecord: BrowserChangeRecord | BrowserFullSnapshotChangeRecord | undefined\n  serializeChangesInTransaction(\n    transaction.kind,\n    (record: BrowserRecord): void => {\n      if (\n        record.type !== RecordType.Change &&\n        (record.type !== RecordType.FullSnapshot || record.format !== SnapshotFormat.Change)\n      ) {\n        throw new Error(`Received unexpected record type: ${record.type}`)\n      }\n      changeRecord = record\n    },\n    noop,\n    changeScope,\n    timeStampNow(),\n    (transaction: ChangeSerializationTransaction) => {\n      const cursor = createRootInsertionCursor(changeScope.nodeIds)\n      serializeNodeAsChange(cursor, node, parentNodePrivacyLevel, transaction)\n    }\n  )\n\n  if (serializedNode === null) {\n    // If serializeNode() didn't serialize anything, neither should\n    // serializeNodeAsChange().\n    expect(changeRecord).toBeUndefined()\n  } else {\n    // When converted to a FullSnapshot record, serializeNodeAsChange()'s output should\n    // match serializeNode() exactly.\n    expect(changeRecord).not.toBeUndefined()\n    const converter = createChangeConverter()\n    const convertedRecord = converter.convert(changeRecord!) as BrowserFullSnapshotV1Record\n    const convertedNode = convertedRecord.data.node\n    expect(convertedNode).toEqual(serializedNode)\n\n    // When stringified, serializeNodeAsChange()'s converted output should be\n    // byte-for-byte identical to serializeNode()'s. (This test is stricter than the one\n    // above, but produces error messages which are a lot harder to read, so it's worth\n    // having both.)\n    expect(JSON.stringify(convertedNode)).toEqual(JSON.stringify(serializedNode))\n  }\n\n  return serializedNode\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/test/shadowRootsController.specHelper.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { ShadowRootsController } from '../shadowRootsController'\n\nexport const DEFAULT_SHADOW_ROOT_CONTROLLER: ShadowRootsController = {\n  flush: noop,\n  stop: noop,\n  addShadowRoot: noop,\n  removeShadowRoot: noop,\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/index.ts",
    "content": "export { trackMove } from './trackMove'\nexport { trackMouseInteraction } from './trackMouseInteraction'\nexport { trackScroll } from './trackScroll'\nexport { trackViewportResize, trackVisualViewportResize } from './trackViewportResize'\nexport { trackMediaInteraction } from './trackMediaInteraction'\nexport { trackStyleSheet } from './trackStyleSheet'\nexport { trackFocus } from './trackFocus'\nexport { trackViewEnd } from './trackViewEnd'\nexport { trackInput } from './trackInput'\nexport { trackMutation } from './trackMutation'\nexport type { Tracker } from './tracker.types'\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackFocus.spec.ts",
    "content": "import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackFocus } from './trackFocus'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackFocus', () => {\n  let focusTracker: Tracker\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n\n  beforeEach(() => {\n    emitRecordCallback = jasmine.createSpy()\n    focusTracker = trackFocus(emitRecordCallback, createRecordingScopeForTesting())\n    registerCleanupTask(() => {\n      focusTracker.stop()\n    })\n  })\n\n  it('collects focus', () => {\n    spyOn(document, 'hasFocus').and.returnValue(true)\n    window.dispatchEvent(createNewEvent('focus'))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      data: { has_focus: true },\n      type: RecordType.Focus,\n      timestamp: jasmine.any(Number),\n    })\n  })\n\n  it('collects blur', () => {\n    spyOn(document, 'hasFocus').and.returnValue(false)\n    window.dispatchEvent(createNewEvent('blur'))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      data: { has_focus: false },\n      type: RecordType.Focus,\n      timestamp: jasmine.any(Number),\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackFocus.ts",
    "content": "import { DOM_EVENT, addEventListeners, timeStampNow } from '@datadog/browser-core'\nimport type { FocusRecord } from '../../../types'\nimport { RecordType } from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { Tracker } from './tracker.types'\n\nexport function trackFocus(emitRecord: EmitRecordCallback<FocusRecord>, scope: RecordingScope): Tracker {\n  return addEventListeners(scope.configuration, window, [DOM_EVENT.FOCUS, DOM_EVENT.BLUR], () => {\n    emitRecord({\n      data: { has_focus: document.hasFocus() },\n      type: RecordType.Focus,\n      timestamp: timeStampNow(),\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackInput.spec.ts",
    "content": "import { DefaultPrivacyLevel } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { createNewEvent, mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport { PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT } from '@datadog/browser-rum-core'\nimport { appendElement } from '../../../../../rum-core/test'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { BrowserIncrementalSnapshotRecord, InputData } from '../../../types'\nimport { IncrementalSource, RecordType } from '../../../types'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackInput } from './trackInput'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackInput', () => {\n  let inputTracker: Tracker\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let input: HTMLInputElement\n  let clock: Clock | undefined\n  let scope: RecordingScope\n\n  beforeEach(() => {\n    input = appendElement('<div><input target /></div>') as HTMLInputElement\n\n    emitRecordCallback = jasmine.createSpy()\n    scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    registerCleanupTask(() => {\n      inputTracker.stop()\n    })\n  })\n\n  function getLatestInputPayload(): InputData & { text?: string } {\n    const latestRecord = emitRecordCallback.calls.mostRecent()?.args[0] as BrowserIncrementalSnapshotRecord\n    return latestRecord.data as InputData\n  }\n\n  it('collects input values when an \"input\" event is dispatched', () => {\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n    dispatchInputEvent('foo')\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.Input,\n        text: 'foo',\n        id: jasmine.any(Number) as unknown as number,\n      },\n    })\n  })\n\n  it('collects input values when a property setter is used', () => {\n    clock = mockClock()\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n    input.value = 'foo'\n\n    clock.tick(0)\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.Input,\n        text: 'foo',\n        id: jasmine.any(Number) as unknown as number,\n      },\n    })\n  })\n\n  it('does not invoke callback when the value does not change', () => {\n    clock = mockClock()\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n    input.value = 'foo'\n    clock.tick(0)\n\n    dispatchInputEvent('foo')\n\n    expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n  })\n\n  it('does not instrument setters when observing a shadow DOM', () => {\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    const originalSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.set\n    const host = document.createElement('div')\n    host.attachShadow({ mode: 'open' })\n\n    inputTracker = trackInput(host.shadowRoot!, emitRecordCallback, scope)\n\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    expect(Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.set).toBe(originalSetter)\n  })\n\n  // cannot trigger an event in a Shadow DOM because event with `isTrusted:false` do not cross the root\n  it('collects input values when an \"input\" event is composed', () => {\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n    dispatchInputEventWithInShadowDom('foo')\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.Input,\n        text: 'foo',\n        id: jasmine.any(Number) as unknown as number,\n      },\n    })\n  })\n\n  it('masks input values according to the element privacy level', () => {\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n    input.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n    dispatchInputEvent('foo')\n\n    expect(getLatestInputPayload().text).toBe('***')\n  })\n\n  it('masks input values according to a parent element privacy level', () => {\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n    input.parentElement!.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n\n    dispatchInputEvent('foo')\n\n    expect(getLatestInputPayload().text).toBe('***')\n  })\n\n  it('masks input values according to a the default privacy level', () => {\n    scope.configuration.defaultPrivacyLevel = DefaultPrivacyLevel.MASK\n    inputTracker = trackInput(document, emitRecordCallback, scope)\n\n    dispatchInputEvent('foo')\n\n    expect(getLatestInputPayload().text).toBe('***')\n  })\n\n  function dispatchInputEvent(newValue: string) {\n    input.value = newValue\n    input.dispatchEvent(createNewEvent('input', { target: input }))\n  }\n\n  function dispatchInputEventWithInShadowDom(newValue: string) {\n    input.value = newValue\n    const host = document.createElement('div')\n    host.attachShadow({ mode: 'open' })\n    const event = createNewEvent('input', { target: host, composed: true })\n    event.composedPath = () => [input, host, input.parentElement!, document.body]\n    input.dispatchEvent(event)\n  }\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackInput.ts",
    "content": "import { instrumentSetter, DOM_EVENT, addEventListeners, noop } from '@datadog/browser-core'\nimport { NodePrivacyLevel, getNodePrivacyLevel, shouldMaskNode } from '@datadog/browser-rum-core'\nimport { IncrementalSource } from '../../../types'\nimport type { InputData, InputState } from '../../../types'\nimport { getEventTarget } from '../eventsUtils'\nimport type { RecordingScope } from '../recordingScope'\nimport { getElementInputValue } from '../serialization'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { Tracker } from './tracker.types'\n\nexport function trackInput(\n  target: Document | ShadowRoot,\n  emitRecord: EmitRecordCallback,\n  scope: RecordingScope\n): Tracker {\n  const defaultPrivacyLevel = scope.configuration.defaultPrivacyLevel\n  const lastInputStateMap: WeakMap<Node, InputState> = new WeakMap()\n\n  const isShadowRoot = target !== document\n\n  const { stop: stopEventListeners } = addEventListeners(\n    scope.configuration,\n    target,\n    // The 'input' event bubbles across shadow roots, so we don't have to listen for it on shadow\n    // roots since it will be handled by the event listener that we did add to the document. Only\n    // the 'change' event is blocked and needs to be handled on shadow roots.\n    isShadowRoot ? [DOM_EVENT.CHANGE] : [DOM_EVENT.INPUT, DOM_EVENT.CHANGE],\n    (event) => {\n      const target = getEventTarget(event)\n      if (\n        target instanceof HTMLInputElement ||\n        target instanceof HTMLTextAreaElement ||\n        target instanceof HTMLSelectElement\n      ) {\n        onElementChange(target)\n      }\n    },\n    {\n      capture: true,\n      passive: true,\n    }\n  )\n\n  let stopPropertySetterInstrumentation: () => void\n  if (!isShadowRoot) {\n    const instrumentationStoppers = [\n      instrumentSetter(HTMLInputElement.prototype, 'value', onElementChange),\n      instrumentSetter(HTMLInputElement.prototype, 'checked', onElementChange),\n      instrumentSetter(HTMLSelectElement.prototype, 'value', onElementChange),\n      instrumentSetter(HTMLTextAreaElement.prototype, 'value', onElementChange),\n      instrumentSetter(HTMLSelectElement.prototype, 'selectedIndex', onElementChange),\n    ]\n    stopPropertySetterInstrumentation = () => {\n      instrumentationStoppers.forEach((stopper) => stopper.stop())\n    }\n  } else {\n    stopPropertySetterInstrumentation = noop\n  }\n\n  return {\n    stop: () => {\n      stopPropertySetterInstrumentation()\n      stopEventListeners()\n    },\n  }\n\n  function onElementChange(target: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement) {\n    const nodePrivacyLevel = getNodePrivacyLevel(target, defaultPrivacyLevel)\n    if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n      return\n    }\n\n    const type = target.type\n\n    let inputState: InputState\n    if (type === 'radio' || type === 'checkbox') {\n      if (shouldMaskNode(target, nodePrivacyLevel)) {\n        return\n      }\n      inputState = { isChecked: (target as HTMLInputElement).checked }\n    } else {\n      const value = getElementInputValue(target, nodePrivacyLevel)\n      if (value === undefined) {\n        return\n      }\n      inputState = { text: value }\n    }\n\n    // Can be multiple changes on the same node within the same batched mutation observation.\n    createRecordIfStateChanged(target, inputState)\n\n    // If a radio was checked, other radios with the same name attribute will be unchecked.\n    const name = target.name\n    if (type === 'radio' && name && (target as HTMLInputElement).checked) {\n      document.querySelectorAll(`input[type=\"radio\"][name=\"${CSS.escape(name)}\"]`).forEach((el: Element) => {\n        if (el !== target) {\n          // TODO: Consider the privacy implications for various differing input privacy levels\n          createRecordIfStateChanged(el, { isChecked: false })\n        }\n      })\n    }\n  }\n\n  /**\n   * There can be multiple changes on the same node within the same batched mutation observation.\n   */\n  function createRecordIfStateChanged(target: Node, inputState: InputState) {\n    const id = scope.nodeIds.get(target)\n    if (id === undefined) {\n      return\n    }\n    const lastInputState = lastInputStateMap.get(target)\n    if (\n      !lastInputState ||\n      (lastInputState as { text?: string }).text !== (inputState as { text?: string }).text ||\n      (lastInputState as { isChecked?: boolean }).isChecked !== (inputState as { isChecked?: boolean }).isChecked\n    ) {\n      lastInputStateMap.set(target, inputState)\n      emitRecord(\n        assembleIncrementalSnapshot<InputData>(IncrementalSource.Input, {\n          id,\n          ...inputState,\n        })\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMediaInteraction.spec.ts",
    "content": "import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { appendElement } from '../../../../../rum-core/test'\nimport { IncrementalSource, MediaInteractionType, RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackMediaInteraction } from './trackMediaInteraction'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackMediaInteraction', () => {\n  let mediaInteractionTracker: Tracker\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let audio: HTMLAudioElement\n\n  beforeEach(() => {\n    audio = appendElement('<audio controls autoplay target></audio>') as HTMLAudioElement\n\n    const scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    emitRecordCallback = jasmine.createSpy()\n    mediaInteractionTracker = trackMediaInteraction(emitRecordCallback, scope)\n    registerCleanupTask(() => {\n      mediaInteractionTracker.stop()\n    })\n  })\n\n  it('collects play interactions', () => {\n    audio.dispatchEvent(createNewEvent('play', { target: audio }))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.MediaInteraction,\n        id: jasmine.any(Number) as unknown as number,\n        type: MediaInteractionType.Play,\n      },\n    })\n  })\n\n  it('collects pause interactions', () => {\n    audio.dispatchEvent(createNewEvent('pause', { target: audio }))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.MediaInteraction,\n        id: jasmine.any(Number) as unknown as number,\n        type: MediaInteractionType.Pause,\n      },\n    })\n  })\n\n  it('do no collect media interactions if the privacy is \"hidden\"', () => {\n    audio.setAttribute('data-dd-privacy', 'hidden')\n\n    audio.dispatchEvent(createNewEvent('play', { target: audio }))\n    audio.dispatchEvent(createNewEvent('pause', { target: audio }))\n\n    expect(emitRecordCallback).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMediaInteraction.ts",
    "content": "import { DOM_EVENT, addEventListeners } from '@datadog/browser-core'\nimport { NodePrivacyLevel, getNodePrivacyLevel } from '@datadog/browser-rum-core'\nimport type { MediaInteractionData, BrowserIncrementalSnapshotRecord } from '../../../types'\nimport { IncrementalSource, MediaInteractionType } from '../../../types'\nimport { getEventTarget } from '../eventsUtils'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { Tracker } from './tracker.types'\n\nexport function trackMediaInteraction(\n  emitRecord: EmitRecordCallback<BrowserIncrementalSnapshotRecord>,\n  scope: RecordingScope\n): Tracker {\n  return addEventListeners(\n    scope.configuration,\n    document,\n    [DOM_EVENT.PLAY, DOM_EVENT.PAUSE],\n    (event) => {\n      const target = getEventTarget(event)\n      if (!target) {\n        return\n      }\n      const id = scope.nodeIds.get(target)\n      if (\n        id === undefined ||\n        getNodePrivacyLevel(target, scope.configuration.defaultPrivacyLevel) === NodePrivacyLevel.HIDDEN\n      ) {\n        return\n      }\n      emitRecord(\n        assembleIncrementalSnapshot<MediaInteractionData>(IncrementalSource.MediaInteraction, {\n          id,\n          type: event.type === DOM_EVENT.PLAY ? MediaInteractionType.Play : MediaInteractionType.Pause,\n        })\n      )\n    },\n    {\n      capture: true,\n      passive: true,\n    }\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMouseInteraction.spec.ts",
    "content": "import { DOM_EVENT } from '@datadog/browser-core'\nimport { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { appendElement } from '../../../../../rum-core/test'\nimport { IncrementalSource, MouseInteractionType, RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackMouseInteraction } from './trackMouseInteraction'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackMouseInteraction', () => {\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let mouseInteractionTracker: Tracker\n  let scope: RecordingScope\n  let a: HTMLAnchorElement\n\n  beforeEach(() => {\n    a = appendElement('<a tabindex=\"0\"></a>') as HTMLAnchorElement // tabindex 0 makes the element focusable\n    a.dispatchEvent(createNewEvent(DOM_EVENT.FOCUS))\n\n    scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    emitRecordCallback = jasmine.createSpy()\n    mouseInteractionTracker = trackMouseInteraction(emitRecordCallback, scope)\n    registerCleanupTask(() => {\n      mouseInteractionTracker.stop()\n    })\n  })\n\n  it('should generate click record', () => {\n    a.dispatchEvent(createNewEvent(DOM_EVENT.CLICK, { clientX: 0, clientY: 0 }))\n\n    expect(emitRecordCallback).toHaveBeenCalledWith({\n      id: jasmine.any(Number),\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.MouseInteraction,\n        type: MouseInteractionType.Click,\n        id: jasmine.any(Number),\n        x: jasmine.any(Number),\n        y: jasmine.any(Number),\n      },\n    })\n  })\n\n  it('should generate mouseup record on pointerup DOM event', () => {\n    const pointerupEvent = createNewEvent(DOM_EVENT.POINTER_UP, { clientX: 1, clientY: 2 })\n    a.dispatchEvent(pointerupEvent)\n\n    expect(emitRecordCallback).toHaveBeenCalledWith({\n      id: scope.eventIds.getOrInsert(pointerupEvent),\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.MouseInteraction,\n        type: MouseInteractionType.MouseUp,\n        id: jasmine.any(Number),\n        x: jasmine.any(Number),\n        y: jasmine.any(Number),\n      },\n    })\n  })\n\n  it('should not generate click record if x/y are missing', () => {\n    const clickEvent = createNewEvent(DOM_EVENT.CLICK)\n    a.dispatchEvent(clickEvent)\n\n    expect(emitRecordCallback).not.toHaveBeenCalled()\n  })\n\n  it('should generate blur record', () => {\n    a.dispatchEvent(createNewEvent(DOM_EVENT.BLUR))\n\n    expect(emitRecordCallback).toHaveBeenCalledWith({\n      id: jasmine.any(Number),\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.MouseInteraction,\n        type: MouseInteractionType.Blur,\n        id: jasmine.any(Number),\n      },\n    })\n  })\n\n  // related to safari issue, see RUMF-1450\n  describe('forced layout issue', () => {\n    let coordinatesComputed: boolean\n\n    beforeEach(() => {\n      if (!window.visualViewport) {\n        pending('no visualViewport')\n      }\n\n      coordinatesComputed = false\n      Object.defineProperty(window.visualViewport, 'offsetTop', {\n        get() {\n          coordinatesComputed = true\n          return 0\n        },\n        configurable: true,\n      })\n    })\n\n    afterEach(() => {\n      if (!window.visualViewport) {\n        return\n      }\n\n      delete (window.visualViewport as any).offsetTop\n    })\n\n    it('should compute x/y coordinates for click record', () => {\n      a.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n      expect(coordinatesComputed).toBeTrue()\n    })\n\n    it('should not compute x/y coordinates for blur record', () => {\n      a.dispatchEvent(createNewEvent(DOM_EVENT.BLUR))\n      expect(coordinatesComputed).toBeFalse()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMouseInteraction.ts",
    "content": "import { addEventListeners, DOM_EVENT } from '@datadog/browser-core'\nimport { getNodePrivacyLevel, NodePrivacyLevel } from '@datadog/browser-rum-core'\nimport type { MouseInteraction, MouseInteractionData, BrowserIncrementalSnapshotRecord } from '../../../types'\nimport { IncrementalSource, MouseInteractionType } from '../../../types'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport { getEventTarget } from '../eventsUtils'\nimport type { RecordingScope } from '../recordingScope'\nimport type { EmitRecordCallback } from '../record.types'\nimport { tryToComputeCoordinates } from './trackMove'\nimport type { Tracker } from './tracker.types'\n\nconst eventTypeToMouseInteraction = {\n  // Listen for pointerup DOM events instead of mouseup for MouseInteraction/MouseUp records. This\n  // allows to reference such records from Frustration records.\n  //\n  // In the context of supporting Mobile Session Replay, we introduced `PointerInteraction` records\n  // used by the Mobile SDKs in place of `MouseInteraction`. In the future, we should replace\n  // `MouseInteraction` by `PointerInteraction` in the Browser SDK so we have an uniform way to\n  // convey such interaction. This would cleanly solve the issue since we would have\n  // `PointerInteraction/Up` records that we could reference from `Frustration` records.\n  [DOM_EVENT.POINTER_UP]: MouseInteractionType.MouseUp,\n\n  [DOM_EVENT.MOUSE_DOWN]: MouseInteractionType.MouseDown,\n  [DOM_EVENT.CLICK]: MouseInteractionType.Click,\n  [DOM_EVENT.CONTEXT_MENU]: MouseInteractionType.ContextMenu,\n  [DOM_EVENT.DBL_CLICK]: MouseInteractionType.DblClick,\n  [DOM_EVENT.FOCUS]: MouseInteractionType.Focus,\n  [DOM_EVENT.BLUR]: MouseInteractionType.Blur,\n  [DOM_EVENT.TOUCH_START]: MouseInteractionType.TouchStart,\n  [DOM_EVENT.TOUCH_END]: MouseInteractionType.TouchEnd,\n}\n\nexport function trackMouseInteraction(\n  emitRecord: EmitRecordCallback<BrowserIncrementalSnapshotRecord>,\n  scope: RecordingScope\n): Tracker {\n  const handler = (event: MouseEvent | TouchEvent | FocusEvent) => {\n    const target = getEventTarget(event)\n    const id = scope.nodeIds.get(target)\n    if (\n      id === undefined ||\n      getNodePrivacyLevel(target, scope.configuration.defaultPrivacyLevel) === NodePrivacyLevel.HIDDEN\n    ) {\n      return\n    }\n    const type = eventTypeToMouseInteraction[event.type as keyof typeof eventTypeToMouseInteraction]\n\n    let interaction: MouseInteraction\n    if (type !== MouseInteractionType.Blur && type !== MouseInteractionType.Focus) {\n      const coordinates = tryToComputeCoordinates(event as MouseEvent | TouchEvent)\n      if (!coordinates) {\n        return\n      }\n      interaction = { id, type, x: coordinates.x, y: coordinates.y }\n    } else {\n      interaction = { id, type }\n    }\n\n    emitRecord({\n      id: scope.eventIds.getOrInsert(event),\n      ...assembleIncrementalSnapshot<MouseInteractionData>(IncrementalSource.MouseInteraction, interaction),\n    })\n  }\n  return addEventListeners(\n    scope.configuration,\n    document,\n    Object.keys(eventTypeToMouseInteraction) as Array<keyof typeof eventTypeToMouseInteraction>,\n    handler,\n    {\n      capture: true,\n      passive: true,\n    }\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMove.spec.ts",
    "content": "import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { IncrementalSource, RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackMove } from './trackMove'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackMove', () => {\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let moveTracker: Tracker\n\n  beforeEach(() => {\n    const scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    emitRecordCallback = jasmine.createSpy()\n    moveTracker = trackMove(emitRecordCallback, scope)\n    registerCleanupTask(() => {\n      moveTracker.stop()\n    })\n  })\n\n  it('should generate mouse move record', () => {\n    const event = createNewEvent('mousemove', { clientX: 1, clientY: 2 })\n    document.body.dispatchEvent(event)\n\n    expect(emitRecordCallback).toHaveBeenCalledWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.MouseMove,\n        positions: [\n          {\n            x: 1,\n            y: 2,\n            id: jasmine.any(Number),\n            timeOffset: 0,\n          },\n        ],\n      },\n    })\n  })\n\n  it('should generate touch move record', () => {\n    const event = createNewEvent('touchmove', { changedTouches: [{ clientX: 1, clientY: 2 }] })\n    document.body.dispatchEvent(event)\n\n    expect(emitRecordCallback).toHaveBeenCalledWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.TouchMove,\n        positions: [\n          {\n            x: 1,\n            y: 2,\n            id: jasmine.any(Number),\n            timeOffset: 0,\n          },\n        ],\n      },\n    })\n  })\n\n  it('should not generate mouse move record if x/y are missing', () => {\n    const mouseMove = createNewEvent('mousemove')\n    document.body.dispatchEvent(mouseMove)\n\n    expect(emitRecordCallback).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMove.ts",
    "content": "import { addEventListeners, DOM_EVENT, throttle } from '@datadog/browser-core'\nimport type { BrowserIncrementalSnapshotRecord, MousemoveData, MousePosition } from '../../../types'\nimport { IncrementalSource } from '../../../types'\nimport { getEventTarget, isTouchEvent } from '../eventsUtils'\nimport { convertMouseEventToLayoutCoordinates } from '../viewports'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { RecordingScope } from '../recordingScope'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { Tracker } from './tracker.types'\n\nconst MOUSE_MOVE_OBSERVER_THRESHOLD = 50\n\nexport function trackMove(\n  emitRecord: EmitRecordCallback<BrowserIncrementalSnapshotRecord>,\n  scope: RecordingScope\n): Tracker {\n  const { throttled: updatePosition, cancel: cancelThrottle } = throttle(\n    (event: MouseEvent | TouchEvent) => {\n      const target = getEventTarget(event)\n      const id = scope.nodeIds.get(target)\n      if (id === undefined) {\n        return\n      }\n      const coordinates = tryToComputeCoordinates(event)\n      if (!coordinates) {\n        return\n      }\n      const position: MousePosition = {\n        id,\n        timeOffset: 0,\n        x: coordinates.x,\n        y: coordinates.y,\n      }\n\n      emitRecord(\n        assembleIncrementalSnapshot<MousemoveData>(\n          isTouchEvent(event) ? IncrementalSource.TouchMove : IncrementalSource.MouseMove,\n          { positions: [position] }\n        )\n      )\n    },\n    MOUSE_MOVE_OBSERVER_THRESHOLD,\n    {\n      trailing: false,\n    }\n  )\n\n  const { stop: removeListener } = addEventListeners(\n    scope.configuration,\n    document,\n    [DOM_EVENT.MOUSE_MOVE, DOM_EVENT.TOUCH_MOVE],\n    updatePosition,\n    {\n      capture: true,\n      passive: true,\n    }\n  )\n\n  return {\n    stop: () => {\n      removeListener()\n      cancelThrottle()\n    },\n  }\n}\n\nexport function tryToComputeCoordinates(event: MouseEvent | TouchEvent) {\n  let { clientX: x, clientY: y } = isTouchEvent(event) ? event.changedTouches[0] : event\n  if (window.visualViewport) {\n    const { visualViewportX, visualViewportY } = convertMouseEventToLayoutCoordinates(x, y)\n    x = visualViewportX\n    y = visualViewportY\n  }\n  if (!Number.isFinite(x) || !Number.isFinite(y)) {\n    return undefined\n  }\n  return { x, y }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMutation.spec.ts",
    "content": "import { DefaultPrivacyLevel } from '@datadog/browser-core'\nimport { collectAsyncCalls, registerCleanupTask } from '@datadog/browser-core/test'\nimport {\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_ALLOW,\n  PRIVACY_ATTR_VALUE_MASK,\n  PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n} from '@datadog/browser-rum-core'\nimport { createMutationPayloadValidator } from '../../../../test'\nimport type {\n  AttributeMutation,\n  Attributes,\n  BrowserIncrementalSnapshotRecord,\n  BrowserMutationPayload,\n  DocumentNode,\n  SerializedNodeWithId,\n} from '../../../types'\nimport { NodeType } from '../../../types'\nimport type { RecordingScope } from '../recordingScope'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport type { AddShadowRootCallBack, RemoveShadowRootCallBack } from '../shadowRootsController'\nimport { appendElement, appendText } from '../../../../../rum-core/test'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { serializeMutations } from '../serialization'\nimport { createSerializationVerifier } from '../serializationVerifier'\nimport { trackMutation } from './trackMutation'\nimport type { MutationTracker } from './trackMutation'\n\ndescribe('trackMutation', () => {\n  let sandbox: HTMLElement\n\n  let addShadowRootSpy: jasmine.Spy<AddShadowRootCallBack>\n  let removeShadowRootSpy: jasmine.Spy<RemoveShadowRootCallBack>\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let emitStatsCallback: jasmine.Spy<EmitStatsCallback>\n\n  beforeEach(() => {\n    sandbox = appendElement('<div id=\"sandbox\"></div>')\n\n    addShadowRootSpy = jasmine.createSpy()\n    removeShadowRootSpy = jasmine.createSpy()\n    emitRecordCallback = jasmine.createSpy()\n    emitStatsCallback = jasmine.createSpy()\n  })\n\n  function getRecordingScope(defaultPrivacyLevel: DefaultPrivacyLevel = DefaultPrivacyLevel.ALLOW): RecordingScope {\n    return createRecordingScopeForTesting({\n      configuration: { defaultPrivacyLevel },\n      addShadowRoot: addShadowRootSpy,\n      removeShadowRoot: removeShadowRootSpy,\n    })\n  }\n\n  function getLatestMutationPayload(): BrowserMutationPayload {\n    const latestRecord = emitRecordCallback.calls.mostRecent()?.args[0] as BrowserIncrementalSnapshotRecord\n    return latestRecord.data as BrowserMutationPayload\n  }\n\n  function recordMutation(\n    mutation: () => void,\n    options: {\n      mutationBeforeTrackingStarts?: () => void\n      scope?: RecordingScope\n      skipFlush?: boolean\n    } = {}\n  ): {\n    mutationTracker: MutationTracker\n    serializedDocument: DocumentNode & SerializedNodeWithId\n  } {\n    const scope = options.scope || getRecordingScope()\n\n    const { stop: stopSerializationVerifier } = createSerializationVerifier(scope, (error, context) => {\n      fail({ error, ...context })\n    })\n    registerCleanupTask(stopSerializationVerifier)\n\n    const serializedDocument = takeFullSnapshotForTesting(scope)\n\n    if (options.mutationBeforeTrackingStarts) {\n      options.mutationBeforeTrackingStarts()\n    }\n\n    const mutationTracker = trackMutation(document, emitRecordCallback, emitStatsCallback, scope, serializeMutations)\n    registerCleanupTask(() => {\n      mutationTracker.stop()\n    })\n\n    mutation()\n\n    if (!options.skipFlush) {\n      mutationTracker.flush()\n    }\n\n    return { mutationTracker, serializedDocument }\n  }\n\n  describe('childList mutation records', () => {\n    it('emits a mutation when a node is appended to a known node', () => {\n      const { serializedDocument } = recordMutation(() => {\n        appendElement('<div></div>', sandbox)\n      })\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n\n      const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectNewNode({ type: NodeType.Element, tagName: 'div' }),\n          },\n        ],\n      })\n    })\n\n    it('emits add node mutations in the expected order', () => {\n      const a = appendElement('<a></a>', sandbox)\n      const aa = appendElement('<aa></aa>', a)\n      const b = appendElement('<b></b>', sandbox)\n      const bb = appendElement('<bb></bb>', b)\n      const c = appendElement('<c></c>', sandbox)\n      const cc = appendElement('<cc></cc>', c)\n\n      const { serializedDocument } = recordMutation(() => {\n        const ab = document.createElement('ab')\n        const ac = document.createElement('ac')\n        const ba = document.createElement('ba')\n        const bc = document.createElement('bc')\n        const ca = document.createElement('ca')\n        const cb = document.createElement('cb')\n\n        cc.before(cb)\n        aa.after(ac)\n        bb.before(ba)\n        aa.after(ab)\n        cb.before(ca)\n        bb.after(bc)\n      })\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n\n      const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      const cb = expectNewNode({ type: NodeType.Element, tagName: 'cb' })\n      const ca = expectNewNode({ type: NodeType.Element, tagName: 'ca' })\n      const bc = expectNewNode({ type: NodeType.Element, tagName: 'bc' })\n      const ba = expectNewNode({ type: NodeType.Element, tagName: 'ba' })\n      const ac = expectNewNode({ type: NodeType.Element, tagName: 'ac' })\n      const ab = expectNewNode({ type: NodeType.Element, tagName: 'ab' })\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ tag: 'c' }),\n            node: cb,\n            next: expectInitialNode({ tag: 'cc' }),\n          },\n          {\n            parent: expectInitialNode({ tag: 'c' }),\n            node: ca,\n            next: cb,\n          },\n          {\n            parent: expectInitialNode({ tag: 'b' }),\n            node: bc,\n          },\n          {\n            parent: expectInitialNode({ tag: 'b' }),\n            node: ba,\n            next: expectInitialNode({ tag: 'bb' }),\n          },\n          {\n            parent: expectInitialNode({ tag: 'a' }),\n            node: ac,\n          },\n          {\n            parent: expectInitialNode({ tag: 'a' }),\n            node: ab,\n            next: ac,\n          },\n        ],\n      })\n    })\n\n    it('emits serialization stats with mutations', () => {\n      const cssText = 'body { width: 100%; }'\n\n      const { serializedDocument } = recordMutation(() => {\n        appendElement(`<style>${cssText}</style>`, sandbox)\n      })\n\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n\n      const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectNewNode({\n              type: NodeType.Element,\n              tagName: 'style',\n              attributes: { _cssText: cssText },\n            }),\n          },\n        ],\n      })\n\n      expect(emitStatsCallback.calls.mostRecent().args[0]).toEqual({\n        cssText: { count: 1, max: 21, sum: 21 },\n        serializationDuration: jasmine.anything(),\n      })\n    })\n\n    it('processes mutations asynchronously', async () => {\n      recordMutation(\n        () => {\n          appendElement('<div></div>', sandbox)\n        },\n        { skipFlush: true }\n      )\n\n      expect(emitRecordCallback).not.toHaveBeenCalled()\n\n      await collectAsyncCalls(emitRecordCallback)\n    })\n\n    it('does not emit a mutation when a node is appended to a unknown node', () => {\n      const unknownNode = document.createElement('div')\n      registerCleanupTask(() => {\n        unknownNode.remove()\n      })\n\n      recordMutation(\n        () => {\n          appendElement('<div></div>', unknownNode)\n        },\n        {\n          mutationBeforeTrackingStarts() {\n            // Append the node after the full snapshot, but before tracking starts,\n            // rendering it 'unknown'.\n            sandbox.appendChild(unknownNode)\n          },\n        }\n      )\n\n      expect(emitRecordCallback).not.toHaveBeenCalled()\n    })\n\n    it('emits buffered mutation records on flush', () => {\n      const { mutationTracker } = recordMutation(\n        () => {\n          appendElement('<div></div>', sandbox)\n        },\n        {\n          skipFlush: true,\n        }\n      )\n\n      expect(emitRecordCallback).toHaveBeenCalledTimes(0)\n\n      mutationTracker.flush()\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n    })\n\n    describe('does not emit mutations on removed nodes and their descendants', () => {\n      it('attribute mutations', () => {\n        const element = appendElement('<div></div>', sandbox)\n\n        recordMutation(() => {\n          element.setAttribute('foo', 'bar')\n          sandbox.remove()\n        })\n\n        expect(getLatestMutationPayload().attributes).toEqual([])\n      })\n\n      it('text mutations', () => {\n        const textNode = appendText('text', sandbox)\n\n        recordMutation(() => {\n          textNode.data = 'bar'\n          sandbox.remove()\n        })\n\n        expect(getLatestMutationPayload().texts).toEqual([])\n      })\n\n      it('add mutations', () => {\n        recordMutation(() => {\n          appendElement('<div><hr /></div>', sandbox)\n          sandbox.remove()\n        })\n\n        expect(getLatestMutationPayload().adds).toEqual([])\n      })\n\n      it('remove mutations', () => {\n        const element = appendElement('<div></div>', sandbox)\n\n        const { serializedDocument } = recordMutation(() => {\n          element.remove()\n          sandbox.remove()\n        })\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          removes: [\n            {\n              parent: expectInitialNode({ tag: 'body' }),\n              node: expectInitialNode({ idAttribute: 'sandbox' }),\n            },\n          ],\n        })\n      })\n    })\n\n    describe('does not emit mutations on freshly re-serialized nodes and their descendants', () => {\n      // Note about those tests: any mutation with a not-yet-serialized 'target' will be trivially\n      // ignored. We want to focus on mutations with a 'target' that have already been serialized\n      // (during the document serialization for example), and re-serialized (by being added in the\n      // document) during the processed mutation batched.\n\n      it('attribute mutations', () => {\n        const element = appendElement('<div></div>', sandbox)\n\n        recordMutation(() => {\n          element.remove()\n          sandbox.appendChild(element)\n          element.setAttribute('foo', 'bar')\n        })\n\n        expect(getLatestMutationPayload().attributes).toEqual([])\n      })\n\n      it('text mutations', () => {\n        const textNode = appendText('foo', sandbox)\n\n        recordMutation(() => {\n          textNode.remove()\n          sandbox.appendChild(textNode)\n          textNode.data = 'bar'\n        })\n\n        expect(getLatestMutationPayload().texts).toEqual([])\n      })\n\n      it('add mutations', () => {\n        const child = appendElement('<a><b target/></a>', sandbox)\n        const parent = child.parentElement!\n\n        const { serializedDocument } = recordMutation(() => {\n          // Generate a mutation on 'child'\n          child.remove()\n          parent.appendChild(child)\n          // Generate a mutation on 'parent'\n          parent.remove()\n          sandbox.appendChild(parent)\n        })\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n\n        // Even if the mutation on 'child' comes first, we only take the 'parent' mutation into\n        // account since it is embeds an up-to-date serialization of 'parent'\n        validate(getLatestMutationPayload(), {\n          adds: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ tag: 'a' }).withChildren(expectInitialNode({ tag: 'b' })),\n            },\n          ],\n          removes: [\n            {\n              parent: expectInitialNode({ tag: 'a' }),\n              node: expectInitialNode({ tag: 'b' }),\n            },\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ tag: 'a' }),\n            },\n          ],\n        })\n      })\n\n      it('remove mutations', () => {\n        const { serializedDocument } = recordMutation(() => {\n          const child = appendElement('<a><b target/></a>', sandbox)\n          child.remove()\n        })\n\n        const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          adds: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectNewNode({ type: NodeType.Element, tagName: 'a' }),\n            },\n          ],\n        })\n      })\n    })\n\n    it('emits only an \"add\" mutation when adding, removing then re-adding a child', () => {\n      const { serializedDocument } = recordMutation(() => {\n        const element = appendElement('<a></a>', sandbox)\n        element.remove()\n        sandbox.appendChild(element)\n      })\n\n      const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectNewNode({ type: NodeType.Element, tagName: 'a' }),\n          },\n        ],\n      })\n    })\n\n    it('emits an \"add\" and a \"remove\" mutation when moving a node', () => {\n      const a = appendElement('<a></a><b/>', sandbox)\n\n      const { serializedDocument } = recordMutation(() => {\n        // Moves 'a' after 'b'\n        sandbox.appendChild(a)\n      })\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectInitialNode({ tag: 'a' }),\n          },\n        ],\n        removes: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectInitialNode({ tag: 'a' }),\n          },\n        ],\n      })\n    })\n\n    it('uses the initial parent id when removing a node from multiple places', () => {\n      const span = appendElement(\n        `<span></span>\n         <a></a>\n         <b></b>`,\n        sandbox\n      )\n      const a = span.nextElementSibling!\n      const b = a.nextElementSibling!\n\n      const { serializedDocument } = recordMutation(() => {\n        a.appendChild(span)\n        b.appendChild(span)\n      })\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ tag: 'b' }),\n            node: expectInitialNode({ tag: 'span' }),\n          },\n        ],\n        removes: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectInitialNode({ tag: 'span' }),\n          },\n        ],\n      })\n    })\n\n    it('keep nodes order when adding multiple sibling nodes', () => {\n      const { serializedDocument } = recordMutation(() => {\n        appendElement('<a></a><b></b><c></c>', sandbox)\n      })\n\n      const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidator(serializedDocument)\n      const c = expectNewNode({ type: NodeType.Element, tagName: 'c' })\n      const b = expectNewNode({ type: NodeType.Element, tagName: 'b' })\n      const a = expectNewNode({ type: NodeType.Element, tagName: 'a' })\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: c,\n          },\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: b,\n            next: c,\n          },\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: a,\n            next: b,\n          },\n        ],\n      })\n    })\n\n    it('respects the default privacy level setting', () => {\n      const { serializedDocument } = recordMutation(\n        () => {\n          sandbox.innerText = 'foo bar'\n        },\n        { scope: getRecordingScope(DefaultPrivacyLevel.MASK) }\n      )\n\n      const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectNewNode({\n              type: NodeType.Text,\n              textContent: 'xxx xxx',\n            }),\n          },\n        ],\n      })\n    })\n\n    describe('for shadow DOM', () => {\n      it('should call addShadowRoot when host is added', () => {\n        let shadowRoot: ShadowRoot\n        const { serializedDocument } = recordMutation(() => {\n          const host = appendElement('<div></div>', sandbox)\n          shadowRoot = host.attachShadow({ mode: 'open' })\n          appendElement('<span></span>', shadowRoot)\n        })\n\n        expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n        const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n\n        const expectedHost = expectNewNode({ type: NodeType.Element, tagName: 'div' })\n        const shadowRootNode = expectNewNode({ type: NodeType.DocumentFragment, isShadowRoot: true })\n        const child = expectNewNode({ type: NodeType.Element, tagName: 'span' })\n        validate(getLatestMutationPayload(), {\n          adds: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectedHost.withChildren(shadowRootNode.withChildren(child)),\n            },\n          ],\n        })\n        expect(addShadowRootSpy).toHaveBeenCalledOnceWith(shadowRoot!, jasmine.anything())\n        expect(removeShadowRootSpy).not.toHaveBeenCalled()\n      })\n\n      it('should call removeShadowRoot when host is removed', () => {\n        const host = appendElement('<div id=\"host\"></div>', sandbox)\n        const shadowRoot = host.attachShadow({ mode: 'open' })\n        appendElement('<span></span>', shadowRoot)\n\n        const { serializedDocument } = recordMutation(() => {\n          host.remove()\n        })\n\n        expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n        expect(addShadowRootSpy).toHaveBeenCalledTimes(1)\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          removes: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ idAttribute: 'host' }),\n            },\n          ],\n        })\n        expect(addShadowRootSpy).toHaveBeenCalledTimes(1)\n        expect(removeShadowRootSpy).toHaveBeenCalledOnceWith(shadowRoot)\n      })\n\n      it('should call removeShadowRoot when parent of host is removed', () => {\n        const host = appendElement('<div id=\"parent\"><div id=\"host\" target></div></div>', sandbox)\n        const shadowRoot = host.attachShadow({ mode: 'open' })\n        appendElement('<span></span>', shadowRoot)\n\n        const { serializedDocument } = recordMutation(() => {\n          host.parentElement!.remove()\n        })\n\n        expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n        expect(addShadowRootSpy).toHaveBeenCalledTimes(1)\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          removes: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ idAttribute: 'parent' }),\n            },\n          ],\n        })\n        expect(addShadowRootSpy).toHaveBeenCalledTimes(1)\n        expect(removeShadowRootSpy).toHaveBeenCalledOnceWith(shadowRoot)\n      })\n\n      it('should call removeShadowRoot when removing a host containing other hosts in its children', () => {\n        const parentHost = appendElement('<div id=\"host\"><p></p></div>', sandbox)\n        const parentShadowRoot = parentHost.attachShadow({ mode: 'open' })\n        const childHost = appendElement('<span></span>', parentHost.querySelector('p')!)\n        const childShadowRoot = childHost.attachShadow({ mode: 'open' })\n\n        const { serializedDocument } = recordMutation(() => {\n          parentHost.remove()\n        })\n\n        expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n        expect(addShadowRootSpy).toHaveBeenCalledTimes(2)\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          removes: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ idAttribute: 'host' }),\n            },\n          ],\n        })\n        expect(addShadowRootSpy).toHaveBeenCalledTimes(2)\n        expect(removeShadowRootSpy).toHaveBeenCalledTimes(2)\n        // Note: `toHaveBeenCalledWith` does not assert strict equality, we need to actually\n        // retrieve the argument and using `toBe` to make sure the spy has been called with both\n        // shadow roots.\n        expect(removeShadowRootSpy.calls.argsFor(0)[0]).toBe(parentShadowRoot)\n        expect(removeShadowRootSpy.calls.argsFor(1)[0]).toBe(childShadowRoot)\n      })\n    })\n  })\n\n  describe('characterData mutations', () => {\n    let textNode: Text\n\n    beforeEach(() => {\n      textNode = appendText('foo', sandbox)\n    })\n\n    it('emits a mutation when a text node is changed', () => {\n      const { serializedDocument } = recordMutation(() => {\n        textNode.data = 'bar'\n      })\n\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        texts: [\n          {\n            node: expectInitialNode({ text: 'foo' }),\n            value: 'bar',\n          },\n        ],\n      })\n    })\n\n    it('emits a mutation when an empty text node is changed', () => {\n      textNode.data = ''\n\n      recordMutation(() => {\n        textNode.data = 'bar'\n      })\n\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n    })\n\n    it('does not emit a mutation when a text node keeps the same value', () => {\n      recordMutation(() => {\n        textNode.data = 'bar'\n        textNode.data = 'foo'\n      })\n\n      expect(emitRecordCallback).not.toHaveBeenCalled()\n    })\n\n    it('respects the default privacy level setting', () => {\n      const scope = getRecordingScope()\n      const { serializedDocument } = recordMutation(\n        () => {\n          scope.configuration.defaultPrivacyLevel = DefaultPrivacyLevel.MASK\n          textNode.data = 'foo bar'\n        },\n        { scope }\n      )\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        texts: [\n          {\n            node: expectInitialNode({ text: 'foo' }),\n            value: 'xxx xxx',\n          },\n        ],\n      })\n    })\n\n    it('respects the parent privacy level when emitting a text node mutation', () => {\n      sandbox.setAttribute('data-dd-privacy', 'allow')\n      const div = appendElement('<div>foo 81</div>', sandbox)\n\n      const { serializedDocument } = recordMutation(\n        () => {\n          div.firstChild!.textContent = 'bazz 7'\n        },\n        { scope: getRecordingScope(DefaultPrivacyLevel.MASK) }\n      )\n\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        texts: [\n          {\n            node: expectInitialNode({ text: 'foo 81' }),\n            value: 'bazz 7',\n          },\n        ],\n      })\n    })\n  })\n\n  describe('attributes mutations', () => {\n    it('emits a mutation when an attribute is changed', () => {\n      const { serializedDocument } = recordMutation(() => {\n        sandbox.setAttribute('foo', 'bar')\n      })\n\n      expect(emitRecordCallback).toHaveBeenCalledTimes(1)\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        attributes: [\n          {\n            node: expectInitialNode({ idAttribute: 'sandbox' }),\n            attributes: { foo: 'bar' },\n          },\n        ],\n      })\n    })\n\n    it('emits a mutation with an empty string when an attribute is changed to an empty string', () => {\n      const { serializedDocument } = recordMutation(() => {\n        sandbox.setAttribute('foo', '')\n      })\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        attributes: [\n          {\n            node: expectInitialNode({ idAttribute: 'sandbox' }),\n            attributes: { foo: '' },\n          },\n        ],\n      })\n    })\n\n    it('emits a mutation with `null` when an attribute is removed', () => {\n      sandbox.setAttribute('foo', 'bar')\n\n      const { serializedDocument } = recordMutation(() => {\n        sandbox.removeAttribute('foo')\n      })\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        attributes: [\n          {\n            node: expectInitialNode({ idAttribute: 'sandbox' }),\n            attributes: { foo: null },\n          },\n        ],\n      })\n    })\n\n    it('does not emit a mutation when an attribute keeps the same value', () => {\n      sandbox.setAttribute('foo', 'bar')\n\n      recordMutation(() => {\n        sandbox.setAttribute('foo', 'biz')\n        sandbox.setAttribute('foo', 'bar')\n      })\n\n      expect(emitRecordCallback).not.toHaveBeenCalled()\n    })\n\n    it('reuse the same mutation when multiple attributes are changed', () => {\n      const { serializedDocument } = recordMutation(() => {\n        sandbox.setAttribute('foo1', 'biz')\n        sandbox.setAttribute('foo2', 'bar')\n      })\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        attributes: [\n          {\n            node: expectInitialNode({ idAttribute: 'sandbox' }),\n            attributes: { foo1: 'biz', foo2: 'bar' },\n          },\n        ],\n      })\n    })\n\n    it('respects the default privacy level setting', () => {\n      const { serializedDocument } = recordMutation(\n        () => {\n          sandbox.setAttribute('data-foo', 'biz')\n        },\n        { scope: getRecordingScope(DefaultPrivacyLevel.MASK) }\n      )\n\n      const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        attributes: [\n          {\n            node: expectInitialNode({ idAttribute: 'sandbox' }),\n            attributes: { 'data-foo': '***' },\n          },\n        ],\n      })\n    })\n  })\n\n  describe('ignored nodes', () => {\n    let ignoredElement: HTMLElement\n\n    beforeEach(() => {\n      ignoredElement = appendElement('<script></script>', sandbox)\n    })\n\n    it('skips ignored nodes when looking for the next id', () => {\n      const { serializedDocument } = recordMutation(() => {\n        sandbox.insertBefore(document.createElement('a'), ignoredElement)\n      })\n\n      const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidator(serializedDocument)\n      validate(getLatestMutationPayload(), {\n        adds: [\n          {\n            parent: expectInitialNode({ idAttribute: 'sandbox' }),\n            node: expectNewNode({ type: NodeType.Element, tagName: 'a' }),\n          },\n        ],\n      })\n    })\n\n    describe('does not emit mutations occurring in ignored node', () => {\n      it('when adding an ignored node', () => {\n        ignoredElement.remove()\n\n        recordMutation(() => {\n          sandbox.appendChild(ignoredElement)\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n\n      it('when changing the attributes of an ignored node', () => {\n        recordMutation(() => {\n          ignoredElement.setAttribute('foo', 'bar')\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n\n      it('when adding a new child node', () => {\n        recordMutation(() => {\n          appendElement(\"'function foo() {}'\", ignoredElement)\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n\n      it('when mutating a known child node', () => {\n        const textNode = appendText('function foo() {}', sandbox)\n        ignoredElement.appendChild(textNode)\n\n        recordMutation(() => {\n          textNode.data = 'function bar() {}'\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n\n      it('when adding a known child node', () => {\n        const textNode = appendText('function foo() {}', sandbox)\n\n        const { serializedDocument } = recordMutation(() => {\n          ignoredElement.appendChild(textNode)\n        })\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          removes: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ text: 'function foo() {}' }),\n            },\n          ],\n        })\n      })\n\n      it('when moving an ignored node', () => {\n        const script = appendElement('<a></a><script target></script><b><b/>', sandbox)\n\n        recordMutation(() => {\n          sandbox.appendChild(script)\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n    })\n  })\n\n  describe('hidden nodes', () => {\n    let hiddenElement: HTMLElement\n    beforeEach(() => {\n      hiddenElement = appendElement(\"<div data-dd-privacy='hidden'></div>\", sandbox)\n    })\n\n    it('does not emit attribute mutations on hidden nodes', () => {\n      recordMutation(() => {\n        hiddenElement.setAttribute('foo', 'bar')\n      })\n\n      expect(emitRecordCallback).not.toHaveBeenCalled()\n    })\n\n    describe('does not emit mutations occurring in hidden node', () => {\n      it('when adding a new node', () => {\n        recordMutation(() => {\n          appendElement('function foo() {}', hiddenElement)\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n\n      it('when mutating a known child node', () => {\n        const textNode = appendText('function foo() {}', sandbox)\n        hiddenElement.appendChild(textNode)\n\n        recordMutation(() => {\n          textNode.data = 'function bar() {}'\n        })\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n\n      it('when moving a known node into an hidden node', () => {\n        const textNode = appendText('function foo() {}', sandbox)\n\n        const { serializedDocument } = recordMutation(() => {\n          hiddenElement.appendChild(textNode)\n        })\n\n        const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n        validate(getLatestMutationPayload(), {\n          removes: [\n            {\n              parent: expectInitialNode({ idAttribute: 'sandbox' }),\n              node: expectInitialNode({ text: 'function foo() {}' }),\n            },\n          ],\n        })\n      })\n    })\n  })\n\n  describe('inputs privacy', () => {\n    const testsVariations: Array<{\n      privacyAttributeValue: string\n      privacyAttributeOn: 'input' | 'ancestor'\n      expectedSerializedAttributes: Attributes\n      expectedAttributesMutation: AttributeMutation['attributes'] | null\n    }> = [\n      {\n        privacyAttributeValue: PRIVACY_ATTR_VALUE_MASK,\n        privacyAttributeOn: 'input',\n        expectedSerializedAttributes: {\n          [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_MASK,\n          value: '***',\n        },\n        expectedAttributesMutation: { value: '***' },\n      },\n      {\n        privacyAttributeValue: PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n        privacyAttributeOn: 'input',\n        expectedSerializedAttributes: {\n          [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n          value: '***',\n        },\n        expectedAttributesMutation: { value: '***' },\n      },\n      {\n        privacyAttributeValue: PRIVACY_ATTR_VALUE_ALLOW,\n        privacyAttributeOn: 'input',\n        expectedSerializedAttributes: {\n          [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_ALLOW,\n          value: 'foo',\n        },\n        expectedAttributesMutation: { value: 'foo' },\n      },\n      {\n        privacyAttributeValue: PRIVACY_ATTR_VALUE_MASK,\n        privacyAttributeOn: 'ancestor',\n        expectedSerializedAttributes: { value: '***' },\n        expectedAttributesMutation: { value: '***' },\n      },\n      {\n        privacyAttributeValue: PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n        privacyAttributeOn: 'ancestor',\n        expectedSerializedAttributes: { value: '***' },\n        expectedAttributesMutation: { value: '***' },\n      },\n      {\n        privacyAttributeValue: PRIVACY_ATTR_VALUE_ALLOW,\n        privacyAttributeOn: 'ancestor',\n        expectedSerializedAttributes: { value: 'foo' },\n        expectedAttributesMutation: { value: 'foo' },\n      },\n    ]\n\n    for (const {\n      privacyAttributeValue,\n      privacyAttributeOn,\n      expectedSerializedAttributes,\n      expectedAttributesMutation,\n    } of testsVariations) {\n      describe(`${privacyAttributeValue} mode on ${privacyAttributeOn} element`, () => {\n        it('respects the privacy mode for newly added inputs', () => {\n          const input = document.createElement('input')\n          input.value = 'foo'\n          if (privacyAttributeOn === 'input') {\n            input.setAttribute(PRIVACY_ATTR_NAME, privacyAttributeValue)\n          } else {\n            sandbox.setAttribute(PRIVACY_ATTR_NAME, privacyAttributeValue)\n          }\n\n          const { serializedDocument } = recordMutation(() => {\n            sandbox.appendChild(input)\n          })\n\n          const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n          validate(getLatestMutationPayload(), {\n            adds: [\n              {\n                parent: expectInitialNode({ idAttribute: 'sandbox' }),\n                node: expectNewNode({\n                  type: NodeType.Element,\n                  tagName: 'input',\n                  attributes: expectedSerializedAttributes,\n                }),\n              },\n            ],\n          })\n        })\n\n        it('respects the privacy mode for attribute mutations', () => {\n          const input = document.createElement('input')\n          input.value = 'foo'\n          if (privacyAttributeOn === 'input') {\n            input.setAttribute(PRIVACY_ATTR_NAME, privacyAttributeValue)\n          } else {\n            sandbox.setAttribute(PRIVACY_ATTR_NAME, privacyAttributeValue)\n          }\n          sandbox.appendChild(input)\n\n          const { serializedDocument } = recordMutation(() => {\n            input.setAttribute('value', 'bar')\n          })\n\n          if (expectedAttributesMutation) {\n            const { validate, expectInitialNode } = createMutationPayloadValidator(serializedDocument)\n            validate(getLatestMutationPayload(), {\n              attributes: [{ node: expectInitialNode({ tag: 'input' }), attributes: expectedAttributesMutation }],\n            })\n          } else {\n            expect(emitRecordCallback).not.toHaveBeenCalled()\n          }\n        })\n      })\n    }\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackMutation.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport { monitor, noop, timeStampNow } from '@datadog/browser-core'\nimport type { RumMutationRecord } from '@datadog/browser-rum-core'\nimport { getMutationObserverConstructor } from '@datadog/browser-rum-core'\nimport type { RecordingScope } from '../recordingScope'\nimport { createMutationBatch } from '../mutationBatch'\nimport type { EmitRecordCallback, EmitStatsCallback } from '../record.types'\nimport {\n  isIncrementalSnapshotChangeRecordsEnabled,\n  serializeMutations,\n  serializeMutationsAsChange,\n} from '../serialization'\nimport type { Tracker } from './tracker.types'\n\nexport type MutationTracker = Tracker & { flush: () => void }\n\nexport type SerializeMutationsCallback = (\n  timestamp: TimeStamp,\n  mutations: RumMutationRecord[],\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope\n) => void\n\n/**\n * Buffers and aggregate mutations generated by a MutationObserver into MutationPayload\n */\nexport function trackMutation(\n  target: Node,\n  emitRecord: EmitRecordCallback,\n  emitStats: EmitStatsCallback,\n  scope: RecordingScope,\n  serialize: SerializeMutationsCallback = defaultSerializeMutationsCallback()\n): MutationTracker {\n  const MutationObserver = getMutationObserverConstructor()\n  if (!MutationObserver) {\n    return { stop: noop, flush: noop }\n  }\n\n  const mutationBatch = createMutationBatch((mutations) => {\n    serialize(\n      timeStampNow(),\n      mutations.concat(observer.takeRecords() as RumMutationRecord[]),\n      emitRecord,\n      emitStats,\n      scope\n    )\n  })\n\n  const observer = new MutationObserver(monitor(mutationBatch.addMutations) as (callback: RumMutationRecord[]) => void)\n\n  observer.observe(target, {\n    attributeOldValue: true,\n    attributes: true,\n    characterData: true,\n    characterDataOldValue: true,\n    childList: true,\n    subtree: true,\n  })\n\n  return {\n    stop: () => {\n      observer.disconnect()\n      mutationBatch.stop()\n    },\n    flush: () => {\n      mutationBatch.flush()\n    },\n  }\n}\n\nfunction defaultSerializeMutationsCallback(): SerializeMutationsCallback {\n  return isIncrementalSnapshotChangeRecordsEnabled() ? serializeMutationsAsChange : serializeMutations\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackScroll.spec.ts",
    "content": "import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { appendElement } from '../../../../../rum-core/test'\nimport { IncrementalSource, RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackScroll } from './trackScroll'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackScroll', () => {\n  let scrollTracker: Tracker\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let div: HTMLDivElement\n\n  beforeEach(() => {\n    div = appendElement('<div target></div>') as HTMLDivElement\n\n    const scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    emitRecordCallback = jasmine.createSpy()\n    scrollTracker = trackScroll(document, emitRecordCallback, scope)\n    registerCleanupTask(() => {\n      scrollTracker.stop()\n    })\n  })\n\n  it('collects scrolls', () => {\n    div.dispatchEvent(createNewEvent('scroll', { target: div }))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.IncrementalSnapshot,\n      timestamp: jasmine.any(Number),\n      data: {\n        source: IncrementalSource.Scroll,\n        id: jasmine.any(Number),\n        x: jasmine.any(Number),\n        y: jasmine.any(Number),\n      },\n    })\n  })\n\n  it('do no collects scrolls if the privacy is \"hidden\"', () => {\n    div.setAttribute('data-dd-privacy', 'hidden')\n\n    div.dispatchEvent(createNewEvent('scroll', { target: div }))\n\n    expect(emitRecordCallback).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackScroll.ts",
    "content": "import { DOM_EVENT, throttle, addEventListener } from '@datadog/browser-core'\nimport { getScrollX, getScrollY, getNodePrivacyLevel, NodePrivacyLevel } from '@datadog/browser-rum-core'\nimport { getEventTarget } from '../eventsUtils'\nimport { IncrementalSource } from '../../../types'\nimport type { BrowserIncrementalSnapshotRecord, ScrollData } from '../../../types'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { RecordingScope } from '../recordingScope'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { Tracker } from './tracker.types'\n\nconst SCROLL_OBSERVER_THRESHOLD = 100\n\nexport function trackScroll(\n  target: Document | ShadowRoot,\n  emitRecord: EmitRecordCallback<BrowserIncrementalSnapshotRecord>,\n  scope: RecordingScope\n): Tracker {\n  const { throttled: updatePosition, cancel: cancelThrottle } = throttle((event: Event) => {\n    const target = getEventTarget(event) as HTMLElement | Document\n    if (!target) {\n      return\n    }\n    const id = scope.nodeIds.get(target)\n    if (\n      id === undefined ||\n      getNodePrivacyLevel(target, scope.configuration.defaultPrivacyLevel) === NodePrivacyLevel.HIDDEN\n    ) {\n      return\n    }\n    const scrollPositions =\n      target === document\n        ? {\n            scrollTop: getScrollY(),\n            scrollLeft: getScrollX(),\n          }\n        : {\n            scrollTop: Math.round((target as HTMLElement).scrollTop),\n            scrollLeft: Math.round((target as HTMLElement).scrollLeft),\n          }\n    scope.elementsScrollPositions.set(target, scrollPositions)\n    emitRecord(\n      assembleIncrementalSnapshot<ScrollData>(IncrementalSource.Scroll, {\n        id,\n        x: scrollPositions.scrollLeft,\n        y: scrollPositions.scrollTop,\n      })\n    )\n  }, SCROLL_OBSERVER_THRESHOLD)\n\n  const { stop: removeListener } = addEventListener(scope.configuration, target, DOM_EVENT.SCROLL, updatePosition, {\n    capture: true,\n    passive: true,\n  })\n\n  return {\n    stop: () => {\n      removeListener()\n      cancelThrottle()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackStyleSheet.spec.ts",
    "content": "import { isFirefox, registerCleanupTask } from '@datadog/browser-core/test'\nimport { IncrementalSource, RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackStyleSheet, getPathToNestedCSSRule } from './trackStyleSheet'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackStyleSheet', () => {\n  let scope: RecordingScope\n  let styleSheetTracker: Tracker\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let styleElement: HTMLStyleElement\n  let styleSheet: CSSStyleSheet\n  const styleRule = '.selector-1 { color: #fff }'\n\n  beforeEach(() => {\n    styleElement = document.createElement('style')\n    document.head.appendChild(styleElement)\n    styleSheet = styleElement.sheet!\n\n    emitRecordCallback = jasmine.createSpy()\n    scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    registerCleanupTask(() => {\n      styleSheetTracker?.stop()\n      styleElement.remove()\n    })\n  })\n\n  describe('observing high level css stylesheet', () => {\n    describe('when inserting rules into stylesheet', () => {\n      it('should capture CSSStyleRule insertion when no index is provided', () => {\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        styleSheet.insertRule(styleRule)\n\n        expect(emitRecordCallback).toHaveBeenCalledWith({\n          type: RecordType.IncrementalSnapshot,\n          timestamp: jasmine.any(Number),\n          data: {\n            id: jasmine.any(Number),\n            source: IncrementalSource.StyleSheetRule,\n            adds: [jasmine.objectContaining({ index: undefined })],\n          },\n        })\n      })\n\n      it('should capture CSSStyleRule insertion when index is provided', () => {\n        const index = 0\n\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        styleSheet.insertRule(styleRule, index)\n\n        expect(emitRecordCallback).toHaveBeenCalledWith({\n          type: RecordType.IncrementalSnapshot,\n          timestamp: jasmine.any(Number),\n          data: {\n            id: jasmine.any(Number),\n            source: IncrementalSource.StyleSheetRule,\n            adds: [jasmine.objectContaining({ index })],\n          },\n        })\n      })\n    })\n\n    describe('when removing rules from stylesheet', () => {\n      it('should capture CSSStyleRule removal with the correct index', () => {\n        styleSheet.insertRule(styleRule)\n        const index = 0\n\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        styleSheet.deleteRule(index)\n\n        expect(emitRecordCallback).toHaveBeenCalledWith({\n          type: RecordType.IncrementalSnapshot,\n          timestamp: jasmine.any(Number),\n          data: {\n            id: jasmine.any(Number),\n            source: IncrementalSource.StyleSheetRule,\n            removes: [jasmine.objectContaining({ index })],\n          },\n        })\n      })\n    })\n  })\n\n  describe('observing CSSGroupingRules inside a CSSStyleSheet', () => {\n    describe('when inserting CSSRules inside a CSSGroupingRule', () => {\n      it('should capture CSSRule with the correct path when no index is provided', () => {\n        styleSheet.insertRule('@media cond-2 { @media cond-1 { .nest-1 { color: #ccc } } }')\n        styleSheet.insertRule('.main {opacity: 0}')\n        const groupingRule = (styleSheet.cssRules[1] as CSSGroupingRule).cssRules[0] as CSSGroupingRule\n\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        groupingRule.insertRule(styleRule, 1)\n\n        expect(emitRecordCallback).toHaveBeenCalledWith({\n          type: RecordType.IncrementalSnapshot,\n          timestamp: jasmine.any(Number),\n          data: {\n            id: jasmine.any(Number),\n            source: IncrementalSource.StyleSheetRule,\n            adds: [jasmine.objectContaining({ index: [1, 0, 1] })],\n          },\n        })\n      })\n\n      it('should not create record when inserting into a detached CSSGroupingRule', () => {\n        if (isFirefox()) {\n          pending('Firefox does not support inserting rules in detached group')\n        }\n\n        styleSheet.insertRule('@media cond-2 { @media cond-1 { .nest-1 { color: #ccc } } }')\n\n        const parentRule = styleSheet.cssRules[0] as CSSGroupingRule\n        const groupingRule = parentRule.cssRules[0] as CSSGroupingRule\n        parentRule.deleteRule(0)\n\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        groupingRule.insertRule(styleRule, 0)\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n    })\n\n    describe('when removing CSSRules from a CSSGroupingRule', () => {\n      it('should capture CSSRule removal with the correct path', () => {\n        styleSheet.insertRule('@media cond-2 { @media cond-1 { .nest-1 { color: #ccc } } }')\n        styleSheet.insertRule('.main {opacity: 0}')\n        const groupingRule = (styleSheet.cssRules[1] as CSSGroupingRule).cssRules[0] as CSSGroupingRule\n\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        groupingRule.deleteRule(0)\n\n        expect(emitRecordCallback).toHaveBeenCalledWith({\n          type: RecordType.IncrementalSnapshot,\n          timestamp: jasmine.any(Number),\n          data: {\n            id: jasmine.any(Number),\n            source: IncrementalSource.StyleSheetRule,\n            removes: [jasmine.objectContaining({ index: [1, 0, 0] })],\n          },\n        })\n      })\n\n      it('should not create record when removing from a detached CSSGroupingRule', () => {\n        if (isFirefox()) {\n          pending('Firefox does not support inserting rules in detached group')\n        }\n\n        styleSheet.insertRule('@media cond-2 { @media cond-1 { .nest-1 { color: #ccc } } }')\n\n        const parentRule = styleSheet.cssRules[0] as CSSGroupingRule\n        const groupingRule = parentRule.cssRules[0] as CSSGroupingRule\n        parentRule.deleteRule(0)\n\n        styleSheetTracker = trackStyleSheet(emitRecordCallback, scope)\n        groupingRule.deleteRule(0)\n\n        expect(emitRecordCallback).not.toHaveBeenCalled()\n      })\n    })\n  })\n})\n\nconst firstStyleRule = '.selector-1 { color: #aaa }'\nconst secondStyleRule = '.selector-2 { color: #bbb }'\nconst firstMediaRule = `\n    @media cond-1 {\n        .selector-3-1 { color: #ccc }\n        .selector-3-2 { color: #ddd }\n        .selector-3-3 { color: #eee }\n    }`\nconst secondMediaRule = `\n    @media cond-2 {\n        @media cond-2-1 {.selector-2-1-1 { display: none }}\n        @media cond-2-2 {.selector-2-2-1 { display: clock }}\n    }`\n\ndescribe('StyleSheetObserver > getPathToNestedCSSRule', () => {\n  let styleSheet: CSSStyleSheet\n  let styleElement: HTMLStyleElement\n  beforeEach(() => {\n    styleElement = document.createElement('style')\n    document.head.appendChild(styleElement)\n    styleSheet = styleElement.sheet!\n\n    styleSheet.insertRule(secondMediaRule)\n    styleSheet.insertRule(firstMediaRule)\n    styleSheet.insertRule(secondStyleRule)\n    styleSheet.insertRule(firstStyleRule)\n\n    registerCleanupTask(() => {\n      styleElement.remove()\n    })\n  })\n\n  it('should return undefined if the rule is not attached to a parent StyleSheet', () => {\n    const groupingRule = styleSheet.cssRules[3]\n    expect(groupingRule.parentStyleSheet).toBeDefined()\n    // Removing rule from CSSStyleSheet\n    styleSheet.deleteRule(3)\n\n    expect(groupingRule.parentStyleSheet).toEqual(null)\n    expect(getPathToNestedCSSRule(groupingRule)).toBeUndefined()\n  })\n\n  it('should return path to high level CSSStyleRule', () => {\n    expect(getPathToNestedCSSRule(styleSheet.cssRules[1])).toEqual([1])\n  })\n\n  it('should return path to high level CSSGroupingRule', () => {\n    expect(getPathToNestedCSSRule(styleSheet.cssRules[3])).toEqual([3])\n  })\n\n  it('should return path to nested CSSStyleRule', () => {\n    const rule = (styleSheet.cssRules[2] as CSSGroupingRule).cssRules[1]\n    expect(getPathToNestedCSSRule(rule)).toEqual([2, 1])\n  })\n\n  it('should return path to nested CSSGroupingRule', () => {\n    const rule = (styleSheet.cssRules[3] as CSSGroupingRule).cssRules[0]\n    expect(getPathToNestedCSSRule(rule)).toEqual([3, 0])\n  })\n\n  it('should return path to leaf CSSRule', () => {\n    const rule = ((styleSheet.cssRules[3] as CSSGroupingRule).cssRules[1] as CSSGroupingRule).cssRules[0]\n    expect(getPathToNestedCSSRule(rule)).toEqual([3, 1, 0])\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackStyleSheet.ts",
    "content": "import { instrumentMethod } from '@datadog/browser-core'\nimport { IncrementalSource } from '../../../types'\nimport type { BrowserIncrementalSnapshotRecord, StyleSheetRuleData } from '../../../types'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { RecordingScope } from '../recordingScope'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { Tracker } from './tracker.types'\n\ntype GroupingCSSRuleTypes = typeof CSSGroupingRule | typeof CSSMediaRule | typeof CSSSupportsRule\n\nexport function trackStyleSheet(\n  emitRecord: EmitRecordCallback<BrowserIncrementalSnapshotRecord>,\n  scope: RecordingScope\n): Tracker {\n  function checkStyleSheetAndCallback(styleSheet: CSSStyleSheet | null, callback: (id: number) => void): void {\n    if (!styleSheet || !styleSheet.ownerNode) {\n      return\n    }\n    const id = scope.nodeIds.get(styleSheet.ownerNode)\n    if (id === undefined) {\n      return\n    }\n    callback(id)\n  }\n\n  const instrumentationStoppers = [\n    instrumentMethod(CSSStyleSheet.prototype, 'insertRule', ({ target: styleSheet, parameters: [rule, index] }) => {\n      checkStyleSheetAndCallback(styleSheet, (id) =>\n        emitRecord(\n          assembleIncrementalSnapshot<StyleSheetRuleData>(IncrementalSource.StyleSheetRule, {\n            id,\n            adds: [{ rule, index }],\n          })\n        )\n      )\n    }),\n\n    instrumentMethod(CSSStyleSheet.prototype, 'deleteRule', ({ target: styleSheet, parameters: [index] }) => {\n      checkStyleSheetAndCallback(styleSheet, (id) =>\n        emitRecord(\n          assembleIncrementalSnapshot<StyleSheetRuleData>(IncrementalSource.StyleSheetRule, {\n            id,\n            removes: [{ index }],\n          })\n        )\n      )\n    }),\n  ]\n\n  if (typeof CSSGroupingRule !== 'undefined') {\n    instrumentGroupingCSSRuleClass(CSSGroupingRule)\n  } else {\n    instrumentGroupingCSSRuleClass(CSSMediaRule)\n    instrumentGroupingCSSRuleClass(CSSSupportsRule)\n  }\n\n  function instrumentGroupingCSSRuleClass(cls: GroupingCSSRuleTypes) {\n    instrumentationStoppers.push(\n      instrumentMethod(cls.prototype, 'insertRule', ({ target: styleSheet, parameters: [rule, index] }) => {\n        checkStyleSheetAndCallback(styleSheet.parentStyleSheet, (id) => {\n          const path = getPathToNestedCSSRule(styleSheet)\n          if (path) {\n            path.push(index || 0)\n            emitRecord(\n              assembleIncrementalSnapshot<StyleSheetRuleData>(IncrementalSource.StyleSheetRule, {\n                id,\n                adds: [{ rule, index: path }],\n              })\n            )\n          }\n        })\n      }),\n\n      instrumentMethod(cls.prototype, 'deleteRule', ({ target: styleSheet, parameters: [index] }) => {\n        checkStyleSheetAndCallback(styleSheet.parentStyleSheet, (id) => {\n          const path = getPathToNestedCSSRule(styleSheet)\n          if (path) {\n            path.push(index)\n            emitRecord(\n              assembleIncrementalSnapshot<StyleSheetRuleData>(IncrementalSource.StyleSheetRule, {\n                id,\n                removes: [{ index: path }],\n              })\n            )\n          }\n        })\n      })\n    )\n  }\n\n  return {\n    stop: () => {\n      instrumentationStoppers.forEach((stopper) => stopper.stop())\n    },\n  }\n}\n\nexport function getPathToNestedCSSRule(rule: CSSRule): number[] | undefined {\n  const path: number[] = []\n  let currentRule = rule\n  while (currentRule.parentRule) {\n    const rules = Array.from((currentRule.parentRule as CSSGroupingRule).cssRules)\n    const index = rules.indexOf(currentRule)\n    path.unshift(index)\n    currentRule = currentRule.parentRule\n  }\n  // A rule may not be attached to a stylesheet\n  if (!currentRule.parentStyleSheet) {\n    return\n  }\n\n  const rules = Array.from(currentRule.parentStyleSheet.cssRules)\n  const index = rules.indexOf(currentRule)\n  path.unshift(index)\n\n  return path\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackViewEnd.spec.ts",
    "content": "import { LifeCycle, LifeCycleEventType } from '@datadog/browser-rum-core'\nimport { RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport { trackViewEnd } from './trackViewEnd'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackViewEnd', () => {\n  let lifeCycle: LifeCycle\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n  let flushMutationsCallback: jasmine.Spy<() => void>\n  let viewEndTracker: Tracker\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    emitRecordCallback = jasmine.createSpy()\n    flushMutationsCallback = jasmine.createSpy()\n    viewEndTracker = trackViewEnd(lifeCycle, emitRecordCallback, flushMutationsCallback)\n  })\n\n  afterEach(() => {\n    viewEndTracker.stop()\n  })\n\n  it('should generate view end record', () => {\n    lifeCycle.notify(LifeCycleEventType.VIEW_ENDED, {} as any)\n\n    expect(flushMutationsCallback).toHaveBeenCalledWith()\n    expect(emitRecordCallback).toHaveBeenCalledWith({\n      timestamp: jasmine.any(Number),\n      type: RecordType.ViewEnd,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackViewEnd.ts",
    "content": "import { timeStampNow } from '@datadog/browser-core'\nimport type { LifeCycle } from '@datadog/browser-rum-core'\nimport { LifeCycleEventType } from '@datadog/browser-rum-core'\nimport type { ViewEndRecord } from '../../../types'\nimport { RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { Tracker } from './tracker.types'\n\nexport function trackViewEnd(\n  lifeCycle: LifeCycle,\n  emitRecord: EmitRecordCallback<ViewEndRecord>,\n  flushMutations: () => void\n): Tracker {\n  const viewEndSubscription = lifeCycle.subscribe(LifeCycleEventType.VIEW_ENDED, () => {\n    flushMutations()\n    emitRecord({\n      timestamp: timeStampNow(),\n      type: RecordType.ViewEnd,\n    })\n  })\n\n  return {\n    stop: () => {\n      viewEndSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackViewportResize.spec.ts",
    "content": "import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { RecordType } from '../../../types'\nimport type { EmitRecordCallback } from '../record.types'\nimport { takeFullSnapshotForTesting } from '../test/serialization.specHelper'\nimport { createRecordingScopeForTesting } from '../test/recordingScope.specHelper'\nimport { trackVisualViewportResize } from './trackViewportResize'\nimport type { Tracker } from './tracker.types'\n\ndescribe('trackViewportResize', () => {\n  let viewportResizeTracker: Tracker\n  let emitRecordCallback: jasmine.Spy<EmitRecordCallback>\n\n  beforeEach(() => {\n    if (!window.visualViewport) {\n      pending('visualViewport not supported')\n    }\n\n    emitRecordCallback = jasmine.createSpy()\n    const scope = createRecordingScopeForTesting()\n    takeFullSnapshotForTesting(scope)\n\n    viewportResizeTracker = trackVisualViewportResize(emitRecordCallback, scope)\n    registerCleanupTask(() => {\n      viewportResizeTracker.stop()\n    })\n  })\n\n  it('collects visual viewport on resize', () => {\n    visualViewport!.dispatchEvent(createNewEvent('resize'))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.VisualViewport,\n      timestamp: jasmine.any(Number),\n      data: {\n        scale: jasmine.any(Number),\n        offsetLeft: jasmine.any(Number),\n        offsetTop: jasmine.any(Number),\n        pageLeft: jasmine.any(Number),\n        pageTop: jasmine.any(Number),\n        height: jasmine.any(Number),\n        width: jasmine.any(Number),\n      },\n    })\n  })\n\n  it('collects visual viewport on scroll', () => {\n    visualViewport!.dispatchEvent(createNewEvent('scroll'))\n\n    expect(emitRecordCallback).toHaveBeenCalledOnceWith({\n      type: RecordType.VisualViewport,\n      timestamp: jasmine.any(Number),\n      data: {\n        scale: jasmine.any(Number),\n        offsetLeft: jasmine.any(Number),\n        offsetTop: jasmine.any(Number),\n        pageLeft: jasmine.any(Number),\n        pageTop: jasmine.any(Number),\n        height: jasmine.any(Number),\n        width: jasmine.any(Number),\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/trackViewportResize.ts",
    "content": "import { throttle, DOM_EVENT, addEventListeners, timeStampNow, noop } from '@datadog/browser-core'\nimport type { ViewportDimension } from '@datadog/browser-rum-core'\nimport { initViewportObservable } from '@datadog/browser-rum-core'\nimport { IncrementalSource, RecordType } from '../../../types'\nimport type { BrowserIncrementalSnapshotRecord, ViewportResizeData, VisualViewportRecord } from '../../../types'\nimport { getVisualViewport } from '../viewports'\nimport { assembleIncrementalSnapshot } from '../assembly'\nimport type { EmitRecordCallback } from '../record.types'\nimport type { RecordingScope } from '../recordingScope'\nimport type { Tracker } from './tracker.types'\n\nconst VISUAL_VIEWPORT_OBSERVER_THRESHOLD = 200\n\nexport function trackViewportResize(\n  emitRecord: EmitRecordCallback<BrowserIncrementalSnapshotRecord>,\n  scope: RecordingScope\n): Tracker {\n  const viewportResizeSubscription = initViewportObservable(scope.configuration).subscribe(\n    (data: ViewportDimension) => {\n      emitRecord(assembleIncrementalSnapshot<ViewportResizeData>(IncrementalSource.ViewportResize, data))\n    }\n  )\n\n  return {\n    stop: () => {\n      viewportResizeSubscription.unsubscribe()\n    },\n  }\n}\n\nexport function trackVisualViewportResize(\n  emitRecord: EmitRecordCallback<VisualViewportRecord>,\n  scope: RecordingScope\n): Tracker {\n  const visualViewport = window.visualViewport\n  if (!visualViewport) {\n    return { stop: noop }\n  }\n  const { throttled: updateDimension, cancel: cancelThrottle } = throttle(\n    () => {\n      emitRecord({\n        data: getVisualViewport(visualViewport),\n        type: RecordType.VisualViewport,\n        timestamp: timeStampNow(),\n      })\n    },\n    VISUAL_VIEWPORT_OBSERVER_THRESHOLD,\n    {\n      trailing: false,\n    }\n  )\n  const { stop: removeListener } = addEventListeners(\n    scope.configuration,\n    visualViewport,\n    [DOM_EVENT.RESIZE, DOM_EVENT.SCROLL],\n    updateDimension,\n    {\n      capture: true,\n      passive: true,\n    }\n  )\n\n  return {\n    stop: () => {\n      removeListener()\n      cancelThrottle()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/trackers/tracker.types.ts",
    "content": "export interface Tracker {\n  stop: () => void\n}\n"
  },
  {
    "path": "packages/rum/src/domain/record/viewports.ts",
    "content": "/**\n * Browsers have not standardized various dimension properties. Mobile devices typically report\n * dimensions in reference to the visual viewport, while desktop uses the layout viewport. For example,\n * Mobile Chrome will change innerWidth when a pinch zoom takes place, while Chrome Desktop (mac) will not.\n *\n * With the new Viewport API, we now calculate and normalize dimension properties to the layout viewport.\n * If the VisualViewport API is not supported by a browser, it isn't reasonably possible to detect or normalize\n * which viewport is being measured. Therefore these exported functions will fallback to assuming that the layout\n * viewport is being measured by the browser\n */\n\nimport type { VisualViewportRecord } from '../../types'\n\n// Scrollbar widths vary across properties on different devices and browsers\nconst TOLERANCE = 25\n\n/**\n * Use the Visual Viewport API's properties to measure scrollX/Y in reference to the layout viewport\n * in order to determine if window.scrollX/Y is measuring the layout or visual viewport.\n * This finding corresponds to which viewport mouseEvent.clientX/Y and window.innerWidth/Height measures.\n */\nfunction isVisualViewportFactoredIn(visualViewport: VisualViewport) {\n  return (\n    Math.abs(visualViewport.pageTop - visualViewport.offsetTop - window.scrollY) > TOLERANCE ||\n    Math.abs(visualViewport.pageLeft - visualViewport.offsetLeft - window.scrollX) > TOLERANCE\n  )\n}\n\ninterface LayoutCoordinates {\n  layoutViewportX: number\n  layoutViewportY: number\n  visualViewportX: number\n  visualViewportY: number\n}\n\nexport const convertMouseEventToLayoutCoordinates = (clientX: number, clientY: number): LayoutCoordinates => {\n  const visualViewport = window.visualViewport\n  const normalized: LayoutCoordinates = {\n    layoutViewportX: clientX,\n    layoutViewportY: clientY,\n    visualViewportX: clientX,\n    visualViewportY: clientY,\n  }\n\n  if (!visualViewport) {\n    // On old browsers, we cannot normalize, so fallback to clientX/Y\n    return normalized\n  } else if (isVisualViewportFactoredIn(visualViewport)) {\n    // Typically Mobile Devices\n    normalized.layoutViewportX = Math.round(clientX + visualViewport.offsetLeft)\n    normalized.layoutViewportY = Math.round(clientY + visualViewport.offsetTop)\n  } else {\n    // Typically Desktop Devices\n    normalized.visualViewportX = Math.round(clientX - visualViewport.offsetLeft)\n    normalized.visualViewportY = Math.round(clientY - visualViewport.offsetTop)\n  }\n  return normalized\n}\n\nexport const getVisualViewport = (visualViewport: VisualViewport): VisualViewportRecord['data'] => ({\n  scale: visualViewport.scale,\n  offsetLeft: visualViewport.offsetLeft,\n  offsetTop: visualViewport.offsetTop,\n  pageLeft: visualViewport.pageLeft,\n  pageTop: visualViewport.pageTop,\n  height: visualViewport.height,\n  width: visualViewport.width,\n})\n"
  },
  {
    "path": "packages/rum/src/domain/replayStats.spec.ts",
    "content": "import { getReplayStats, MAX_STATS_HISTORY, addSegment, addRecord, addWroteData } from './replayStats'\n\ndescribe('replayStats', () => {\n  describe('getReplayStats', () => {\n    it('returns undefined for new views', () => {\n      expect(getReplayStats('view-id')).toBeUndefined()\n    })\n\n    it('returns existing replay stats', () => {\n      addRecord('view-id')\n      expect(getReplayStats('view-id')?.records_count).toBe(1)\n    })\n  })\n\n  describe('addSegment', () => {\n    it('increments the view segments count', () => {\n      addSegment('view-id')\n      addSegment('view-id')\n      expect(getReplayStats('view-id')!.segments_count).toBe(2)\n    })\n  })\n\n  describe('addRecord', () => {\n    it('increments the view records count', () => {\n      addRecord('view-id')\n      addRecord('view-id')\n      expect(getReplayStats('view-id')!.records_count).toBe(2)\n    })\n  })\n\n  describe('addWroteData', () => {\n    it('increments the view records count', () => {\n      addWroteData('view-id', 10)\n      addWroteData('view-id', 20)\n      expect(getReplayStats('view-id')!.segments_total_raw_size).toBe(30)\n    })\n  })\n\n  describe('garbage collection', () => {\n    it('cleans up old views when the history limit is reached', () => {\n      for (let i = 0; i < MAX_STATS_HISTORY + 1; i += 1) {\n        addSegment(`view-${i}`)\n      }\n      expect(getReplayStats('view-0')).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/replayStats.ts",
    "content": "import type { ReplayStats } from '@datadog/browser-rum-core'\n\nexport const MAX_STATS_HISTORY = 1000\nlet statsPerView: Map<string, ReplayStats> | undefined\n\nexport function getSegmentsCount(viewId: string) {\n  return getOrCreateReplayStats(viewId).segments_count\n}\n\nexport function addSegment(viewId: string) {\n  getOrCreateReplayStats(viewId).segments_count += 1\n}\n\nexport function addRecord(viewId: string) {\n  getOrCreateReplayStats(viewId).records_count += 1\n}\n\nexport function addWroteData(viewId: string, additionalBytesCount: number) {\n  getOrCreateReplayStats(viewId).segments_total_raw_size += additionalBytesCount\n}\n\nexport function getReplayStats(viewId: string) {\n  return statsPerView?.get(viewId)\n}\n\nexport function resetReplayStats() {\n  statsPerView = undefined\n}\n\nfunction getOrCreateReplayStats(viewId: string) {\n  if (!statsPerView) {\n    statsPerView = new Map()\n  }\n\n  let replayStats: ReplayStats\n  if (statsPerView.has(viewId)) {\n    replayStats = statsPerView.get(viewId)!\n  } else {\n    replayStats = {\n      records_count: 0,\n      segments_count: 0,\n      segments_total_raw_size: 0,\n    }\n    statsPerView.set(viewId, replayStats)\n    if (statsPerView.size > MAX_STATS_HISTORY) {\n      deleteOldestStats()\n    }\n  }\n\n  return replayStats\n}\n\nfunction deleteOldestStats() {\n  if (!statsPerView) {\n    return\n  }\n  const toDelete = statsPerView.keys().next().value\n  if (toDelete) {\n    statsPerView.delete(toDelete)\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/scriptLoadingError.ts",
    "content": "import { addTelemetryError, display, DOCS_ORIGIN } from '@datadog/browser-core'\n\nexport function reportScriptLoadingError({\n  configuredUrl,\n  error,\n  source,\n  scriptType,\n}: {\n  configuredUrl?: string | undefined\n  error: unknown\n  source: string\n  scriptType: 'module' | 'worker'\n}) {\n  display.error(`${source} failed to start: an error occurred while initializing the ${scriptType}:`, error)\n  if (error instanceof Event || (error instanceof Error && isMessageCspRelated(error.message))) {\n    let baseMessage\n    if (configuredUrl) {\n      baseMessage = `Please make sure the ${scriptType} URL ${configuredUrl} is correct and CSP is correctly configured.`\n    } else {\n      baseMessage = 'Please make sure CSP is correctly configured.'\n    }\n    display.error(\n      `${baseMessage} See documentation at ${DOCS_ORIGIN}/integrations/content_security_policy_logs/#use-csp-with-real-user-monitoring-and-session-replay`\n    )\n  } else if (scriptType === 'worker') {\n    addTelemetryError(error)\n  }\n}\n\nfunction isMessageCspRelated(message: string) {\n  return (\n    message.includes('Content Security Policy') ||\n    // Related to `require-trusted-types-for` CSP: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/require-trusted-types-for\n    message.includes(\"requires 'TrustedScriptURL'\")\n  )\n}\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/buildReplayPayload.spec.ts",
    "content": "import { deflate } from 'pako'\nimport type { Uint8ArrayBuffer } from '@datadog/browser-core'\nimport type { BrowserSegment, BrowserSegmentMetadata } from '../../types'\nimport { readReplayPayload } from '../../../test'\nimport type { SerializationStats } from '../record'\nimport { buildReplayPayload } from './buildReplayPayload'\n\ndescribe('buildReplayPayload', () => {\n  const SEGMENT = { foo: 'bar' } as unknown as BrowserSegment\n  const SERIALIZED_SEGMENT = JSON.stringify(SEGMENT)\n  const COMPRESSED_SEGMENT = deflate(SERIALIZED_SEGMENT) as Uint8ArrayBuffer\n  const METADATA: BrowserSegmentMetadata = {\n    application: { id: 'xxx' },\n    session: { id: 'xxx' },\n    view: { id: 'xxx' },\n    start: 1,\n    end: 2,\n    records_count: 10,\n    source: 'browser',\n    creation_reason: 'init',\n  }\n  const STATS: SerializationStats = {\n    cssText: {\n      count: 2,\n      max: 1000,\n      sum: 1500,\n    },\n    serializationDuration: {\n      count: 3,\n      max: 76,\n      sum: 103,\n    },\n  }\n  const METADATA_AND_SEGMENT_SIZES = {\n    ...METADATA,\n    raw_segment_size: SERIALIZED_SEGMENT.length,\n    compressed_segment_size: COMPRESSED_SEGMENT.byteLength,\n  }\n\n  it('adds the segment as a file', async () => {\n    const payload = buildReplayPayload(COMPRESSED_SEGMENT, METADATA, STATS, SERIALIZED_SEGMENT.length)\n    const segmentEntry = (payload.data as FormData).get('segment')! as File\n    expect(segmentEntry.size).toBe(COMPRESSED_SEGMENT.byteLength)\n    expect(segmentEntry.name).toBe('xxx-1')\n    expect(segmentEntry.type).toBe('application/octet-stream')\n    const { segment } = await readReplayPayload(payload)\n    expect(segment).toEqual(SEGMENT)\n  })\n\n  it('adds the metadata plus the segment sizes as the `event` entry', async () => {\n    const payload = buildReplayPayload(COMPRESSED_SEGMENT, METADATA, STATS, SERIALIZED_SEGMENT.length)\n    const eventEntry = (payload.data as FormData).get('event')! as File\n    expect(eventEntry.size).toBe(JSON.stringify(METADATA_AND_SEGMENT_SIZES).length)\n    expect(eventEntry.name).toBe('blob')\n    expect(eventEntry.type).toBe('application/json')\n    const { event } = await readReplayPayload(payload)\n    expect(event).toEqual(METADATA_AND_SEGMENT_SIZES)\n  })\n\n  it('returns the approximate byte counts of the request', () => {\n    const payload = buildReplayPayload(COMPRESSED_SEGMENT, METADATA, STATS, SERIALIZED_SEGMENT.length)\n    expect(payload.bytesCount).toBe(COMPRESSED_SEGMENT.byteLength)\n  })\n\n  it('includes statistics in the payload for segment telemetry', () => {\n    const payload = buildReplayPayload(COMPRESSED_SEGMENT, METADATA, STATS, SERIALIZED_SEGMENT.length)\n    expect(payload.cssText).toEqual({ count: 2, max: 1000, sum: 1500 })\n    expect(payload.isFullSnapshot).toBe(false)\n    expect(payload.rawSize).toBe(13)\n    expect(payload.recordCount).toBe(10)\n    expect(payload.serializationDuration).toEqual({ count: 3, max: 76, sum: 103 })\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/buildReplayPayload.ts",
    "content": "import type { Payload, Uint8ArrayBuffer } from '@datadog/browser-core'\nimport type { BrowserSegmentMetadata } from '../../types'\nimport type { SerializationMetric, SerializationStats } from '../record'\n\nexport type BrowserSegmentMetadataAndSegmentSizes = BrowserSegmentMetadata & {\n  raw_segment_size: number\n  compressed_segment_size: number\n}\n\nexport type ReplayPayload = Payload & {\n  cssText: SerializationMetric\n  isFullSnapshot: boolean\n  rawSize: number\n  recordCount: number\n  serializationDuration: SerializationMetric\n}\n\nexport function buildReplayPayload(\n  data: Uint8ArrayBuffer,\n  metadata: BrowserSegmentMetadata,\n  stats: SerializationStats,\n  rawSegmentBytesCount: number\n): ReplayPayload {\n  const formData = new FormData()\n\n  formData.append(\n    'segment',\n    new Blob([data], {\n      type: 'application/octet-stream',\n    }),\n    `${metadata.session.id}-${metadata.start}`\n  )\n\n  const metadataAndSegmentSizes: BrowserSegmentMetadataAndSegmentSizes = {\n    raw_segment_size: rawSegmentBytesCount,\n    compressed_segment_size: data.byteLength,\n    ...metadata,\n  }\n\n  const serializedMetadataAndSegmentSizes = JSON.stringify(metadataAndSegmentSizes)\n  formData.append('event', new Blob([serializedMetadataAndSegmentSizes], { type: 'application/json' }))\n\n  return {\n    data: formData,\n    bytesCount: data.byteLength,\n    cssText: stats.cssText,\n    isFullSnapshot: metadata.index_in_view === 0,\n    rawSize: rawSegmentBytesCount,\n    recordCount: metadata.records_count,\n    serializationDuration: stats.serializationDuration,\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/index.ts",
    "content": "export { startSegmentCollection, setSegmentBytesLimit } from './segmentCollection'\nexport { SEGMENT_BYTES_LIMIT } from './segmentCollection'\nexport type { BrowserSegmentMetadataAndSegmentSizes, ReplayPayload } from './buildReplayPayload'\nexport { startSegmentTelemetry } from './startSegmentTelemetry'\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/segment.spec.ts",
    "content": "import type { DeflateEncoder, TimeStamp, Uint8ArrayBuffer } from '@datadog/browser-core'\nimport { noop, setDebugMode, DeflateEncoderStreamId } from '@datadog/browser-core'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport { MockWorker } from '../../../test'\nimport type { CreationReason, BrowserRecord, SegmentContext, BrowserSegment, BrowserSegmentMetadata } from '../../types'\nimport { RecordType } from '../../types'\nimport { getReplayStats } from '../replayStats'\nimport { createDeflateEncoder } from '../deflate'\nimport type { SerializationStats } from '../record'\nimport type { AddRecordCallback, FlushCallback, Segment } from './segment'\nimport { createSegment } from './segment'\n\nconst CONTEXT: SegmentContext = { application: { id: 'a' }, view: { id: 'b' }, session: { id: 'c' } }\nconst RECORD_TIMESTAMP = 10 as TimeStamp\nconst RECORD: BrowserRecord = { type: RecordType.ViewEnd, timestamp: RECORD_TIMESTAMP }\nconst RECORD_STATS: SerializationStats = {\n  cssText: { count: 0, max: 0, sum: 0 },\n  serializationDuration: { count: 0, max: 0, sum: 0 },\n}\nconst FULL_SNAPSHOT_RECORD: BrowserRecord = {\n  type: RecordType.FullSnapshot,\n  timestamp: RECORD_TIMESTAMP,\n  data: {} as any,\n}\nconst CHANGE_RECORD: BrowserRecord = {\n  type: RecordType.Change,\n  timestamp: RECORD_TIMESTAMP,\n  data: [] as any,\n}\nconst ENCODED_SEGMENT_HEADER_BYTES_COUNT = 12 // {\"records\":[\nconst ENCODED_RECORD_BYTES_COUNT = 25\nconst ENCODED_META_BYTES_COUNT = 193 // this should stay accurate as long as less than 10 records are added\nconst TRAILER_BYTES_COUNT = 1\n\ndescribe('Segment', () => {\n  const configuration = {} as RumConfiguration\n  let worker: MockWorker\n  let encoder: DeflateEncoder\n\n  beforeEach(() => {\n    worker = new MockWorker()\n    encoder = createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n    setDebugMode(true)\n\n    registerCleanupTask(() => {\n      setDebugMode(false)\n    })\n  })\n\n  it('writes a segment', () => {\n    const addRecordCallbackSpy = jasmine.createSpy<AddRecordCallback>()\n    const flushCallbackSpy = jasmine.createSpy<FlushCallback>()\n    const segment = createTestSegment()\n    segment.addRecord(RECORD, addRecordCallbackSpy)\n\n    worker.processAllMessages()\n    expect(addRecordCallbackSpy).toHaveBeenCalledTimes(1)\n\n    segment.flush(flushCallbackSpy)\n\n    worker.processAllMessages()\n    expect(addRecordCallbackSpy).toHaveBeenCalledTimes(1)\n    expect(flushCallbackSpy).toHaveBeenCalledTimes(1)\n\n    expect(parseSegment(flushCallbackSpy.calls.mostRecent().args[2].output)).toEqual({\n      source: 'browser' as const,\n      creation_reason: 'init' as const,\n      end: 10,\n      has_full_snapshot: false,\n      records: [\n        {\n          timestamp: RECORD_TIMESTAMP,\n          type: RecordType.ViewEnd,\n        },\n      ],\n      records_count: 1,\n      start: 10,\n      index_in_view: 0,\n      ...CONTEXT,\n    })\n  })\n\n  it('compressed bytes count is updated when a record is added', () => {\n    const addRecordCallbackSpy = jasmine.createSpy<AddRecordCallback>()\n    const segment = createTestSegment()\n    segment.addRecord(RECORD, addRecordCallbackSpy)\n    worker.processAllMessages()\n    expect(addRecordCallbackSpy).toHaveBeenCalledOnceWith(\n      ENCODED_SEGMENT_HEADER_BYTES_COUNT + ENCODED_RECORD_BYTES_COUNT\n    )\n  })\n\n  it('calls the flush callback with metadata and encoder output as argument', () => {\n    const flushCallbackSpy = jasmine.createSpy<FlushCallback>()\n    const segment = createTestSegment()\n    segment.addRecord(RECORD, noop)\n    segment.flush(flushCallbackSpy)\n    worker.processAllMessages()\n    expect(flushCallbackSpy).toHaveBeenCalledOnceWith(\n      {\n        start: 10,\n        end: 10,\n        creation_reason: 'init',\n        has_full_snapshot: false,\n        index_in_view: 0,\n        source: 'browser',\n        records_count: 1,\n        ...CONTEXT,\n      },\n      RECORD_STATS,\n      {\n        output: jasmine.any(Uint8Array) as unknown as Uint8ArrayBuffer,\n        outputBytesCount:\n          ENCODED_SEGMENT_HEADER_BYTES_COUNT +\n          ENCODED_RECORD_BYTES_COUNT +\n          ENCODED_META_BYTES_COUNT +\n          TRAILER_BYTES_COUNT,\n        rawBytesCount: ENCODED_SEGMENT_HEADER_BYTES_COUNT + ENCODED_RECORD_BYTES_COUNT + ENCODED_META_BYTES_COUNT,\n        encoding: 'deflate',\n      }\n    )\n  })\n\n  it('resets the encoder when a segment is flushed', () => {\n    const flushCallbackSpy = jasmine.createSpy<FlushCallback>()\n\n    const segment1 = createTestSegment({ creationReason: 'init' })\n    const stats1: SerializationStats = {\n      cssText: { count: 1, max: 100, sum: 150 },\n      serializationDuration: { count: 1, max: 50, sum: 75 },\n    }\n    segment1.addRecord(RECORD, noop)\n    segment1.addStats(stats1)\n    segment1.flush(flushCallbackSpy)\n\n    const segment2 = createTestSegment({ creationReason: 'segment_duration_limit' })\n    const stats2: SerializationStats = {\n      cssText: { count: 2, max: 200, sum: 275 },\n      serializationDuration: { count: 2, max: 200, sum: 300 },\n    }\n    segment2.addRecord(FULL_SNAPSHOT_RECORD, noop)\n    segment2.addStats(stats2)\n    segment2.flush(flushCallbackSpy)\n\n    worker.processAllMessages()\n    expect(flushCallbackSpy.calls.argsFor(0)[1]).toEqual(stats1)\n    expect(parseSegment(flushCallbackSpy.calls.argsFor(0)[2].output).records.length).toBe(1)\n    expect(flushCallbackSpy.calls.argsFor(1)[1]).toEqual(stats2)\n    expect(parseSegment(flushCallbackSpy.calls.argsFor(1)[2].output).records.length).toBe(1)\n  })\n\n  it('throws when trying to flush an empty segment', () => {\n    const segment = createTestSegment()\n    expect(() => segment.flush(noop)).toThrowError('Empty segment flushed')\n  })\n\n  describe('metadata', () => {\n    describe('when adding a record', () => {\n      let segment: Segment\n      beforeEach(() => {\n        segment = createTestSegment()\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 10 as TimeStamp }, noop)\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 15 as TimeStamp }, noop)\n      })\n\n      it('does increment records_count', () => {\n        expect(flushAndGetMetadata(segment).records_count).toBe(2)\n      })\n\n      it('does not change start timestamp when receiving a later record', () => {\n        expect(flushAndGetMetadata(segment).start).toBe(10)\n      })\n\n      it('does change the start timestamp when receiving an earlier record', () => {\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 5 as TimeStamp }, noop)\n        expect(flushAndGetMetadata(segment).start).toBe(5)\n      })\n\n      it('does increase end timestamp when receiving a later record', () => {\n        expect(flushAndGetMetadata(segment).end).toBe(15)\n      })\n\n      it('does not change the end timestamp when receiving an earlier record', () => {\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 5 as TimeStamp }, noop)\n        expect(flushAndGetMetadata(segment).end).toBe(15)\n      })\n    })\n\n    describe('has_full_snapshot', () => {\n      it('sets has_full_snapshot to false if a segment has a no FullSnapshot', () => {\n        const segment = createTestSegment()\n        segment.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment).has_full_snapshot).toEqual(false)\n      })\n\n      it('sets has_full_snapshot to true if a segment has a FullSnapshot', () => {\n        const segment = createTestSegment()\n        segment.addRecord(FULL_SNAPSHOT_RECORD, noop)\n        expect(flushAndGetMetadata(segment).has_full_snapshot).toEqual(true)\n      })\n\n      it('sets has_full_snapshot to true if the first segment has a Change', () => {\n        const segment1 = createTestSegment()\n        segment1.addRecord(CHANGE_RECORD, noop)\n        expect(flushAndGetMetadata(segment1).has_full_snapshot).toEqual(true)\n\n        const segment2 = createTestSegment()\n        segment2.addRecord(CHANGE_RECORD, noop)\n        expect(flushAndGetMetadata(segment2).has_full_snapshot).toEqual(false)\n      })\n\n      it(\"doesn't overrides has_full_snapshot to false once it has been set to true\", () => {\n        const segment = createTestSegment()\n        segment.addRecord(FULL_SNAPSHOT_RECORD, noop)\n        segment.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment).has_full_snapshot).toEqual(true)\n      })\n    })\n\n    describe('index_in_view', () => {\n      it('increments index_in_view every time a segment is created for the same view', () => {\n        const segment1 = createTestSegment()\n        segment1.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment1).index_in_view).toBe(0)\n\n        const segment2 = createTestSegment()\n        segment2.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment2).index_in_view).toBe(1)\n\n        const segment3 = createTestSegment()\n        segment3.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment3).index_in_view).toBe(2)\n      })\n\n      it('resets segments_count when creating a segment for a new view', () => {\n        const segment1 = createTestSegment()\n        segment1.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment1).index_in_view).toBe(0)\n\n        const segment2 = createTestSegment({ context: { ...CONTEXT, view: { id: 'view-2' } } })\n        segment2.addRecord(RECORD, noop)\n        expect(flushAndGetMetadata(segment2).index_in_view).toBe(0)\n      })\n    })\n\n    function flushAndGetMetadata(segment: Segment) {\n      let metadata: BrowserSegmentMetadata\n      segment.flush((_metadata) => {\n        metadata = _metadata\n      })\n      worker.processAllMessages()\n      return metadata!\n    }\n  })\n\n  describe('serialization stats', () => {\n    describe('when adding a record', () => {\n      let segment: Segment\n      beforeEach(() => {\n        segment = createTestSegment()\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 10 as TimeStamp }, noop)\n        segment.addStats({\n          cssText: { count: 1, max: 50, sum: 50 },\n          serializationDuration: { count: 1, max: 20, sum: 20 },\n        })\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 15 as TimeStamp }, noop)\n        segment.addStats({\n          cssText: { count: 2, max: 150, sum: 250 },\n          serializationDuration: { count: 3, max: 35, sum: 65 },\n        })\n      })\n\n      it('aggregates stats', () => {\n        expect(flushAndGetSerializationStats(segment)).toEqual({\n          cssText: { count: 3, max: 150, sum: 300 },\n          serializationDuration: { count: 4, max: 35, sum: 85 },\n        })\n      })\n\n      it('does not change aggregated stats for records with no serialization stats', () => {\n        segment.addRecord({ type: RecordType.ViewEnd, timestamp: 5 as TimeStamp }, noop)\n        expect(flushAndGetSerializationStats(segment)).toEqual({\n          cssText: { count: 3, max: 150, sum: 300 },\n          serializationDuration: { count: 4, max: 35, sum: 85 },\n        })\n      })\n    })\n\n    function flushAndGetSerializationStats(segment: Segment) {\n      let stats: SerializationStats\n      segment.flush((_metadata, _stats) => {\n        stats = _stats\n      })\n      worker.processAllMessages()\n      return stats!\n    }\n  })\n\n  describe('updates segment replay stats', () => {\n    it('when creating a segment', () => {\n      createTestSegment()\n      worker.processAllMessages()\n      expect(getReplayStats('b')).toEqual(\n        jasmine.objectContaining({\n          segments_count: 1,\n          records_count: 0,\n          segments_total_raw_size: 0,\n        })\n      )\n    })\n\n    it('when flushing a segment', () => {\n      const segment = createTestSegment()\n      segment.addRecord(RECORD, noop)\n      segment.flush(noop)\n      worker.processAllMessages()\n      expect(getReplayStats('b')).toEqual(\n        jasmine.objectContaining({\n          segments_count: 1,\n          segments_total_raw_size:\n            ENCODED_SEGMENT_HEADER_BYTES_COUNT + ENCODED_RECORD_BYTES_COUNT + ENCODED_META_BYTES_COUNT,\n        })\n      )\n    })\n  })\n\n  function createTestSegment({\n    context = CONTEXT,\n    creationReason = 'init',\n  }: {\n    context?: SegmentContext\n    creationReason?: CreationReason\n  } = {}) {\n    return createSegment({ encoder, context, creationReason })\n  }\n})\n\nfunction parseSegment(bytes: Uint8Array) {\n  return JSON.parse(new TextDecoder().decode(bytes)) as BrowserSegment\n}\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/segment.ts",
    "content": "import type { Encoder, EncoderResult, Uint8ArrayBuffer } from '@datadog/browser-core'\nimport type { BrowserRecord, BrowserSegmentMetadata, CreationReason, SegmentContext } from '../../types'\nimport { RecordType } from '../../types'\nimport * as replayStats from '../replayStats'\nimport type { SerializationStats } from '../record'\nimport { aggregateSerializationStats, createSerializationStats } from '../record'\n\nexport type FlushReason = Exclude<CreationReason, 'init'> | 'stop'\nexport type FlushCallback = (\n  metadata: BrowserSegmentMetadata,\n  stats: SerializationStats,\n  encoderResult: EncoderResult<Uint8ArrayBuffer>\n) => void\nexport type AddRecordCallback = (encodedBytesCount: number) => void\n\nexport interface Segment {\n  addRecord: (record: BrowserRecord, callback: AddRecordCallback) => void\n  addStats: (stats: SerializationStats) => void\n  flush: (callback: FlushCallback) => void\n}\n\nexport function createSegment({\n  context,\n  creationReason,\n  encoder,\n}: {\n  context: SegmentContext\n  creationReason: CreationReason\n  encoder: Encoder<Uint8ArrayBuffer>\n}): Segment {\n  let encodedBytesCount = 0\n  const viewId = context.view.id\n  const indexInView = replayStats.getSegmentsCount(viewId)\n  const metadata: BrowserSegmentMetadata = {\n    start: Infinity,\n    end: -Infinity,\n    creation_reason: creationReason,\n    records_count: 0,\n    has_full_snapshot: false,\n    index_in_view: indexInView,\n    source: 'browser' as const,\n    ...context,\n  }\n\n  const serializationStats = createSerializationStats()\n  replayStats.addSegment(viewId)\n\n  function addRecord(record: BrowserRecord, callback: AddRecordCallback): void {\n    metadata.start = Math.min(metadata.start, record.timestamp)\n    metadata.end = Math.max(metadata.end, record.timestamp)\n    metadata.records_count += 1\n    metadata.has_full_snapshot ||=\n      record.type === RecordType.FullSnapshot || (record.type === RecordType.Change && metadata.index_in_view === 0)\n\n    const prefix = encoder.isEmpty ? '{\"records\":[' : ','\n    encoder.write(prefix + JSON.stringify(record), (additionalEncodedBytesCount) => {\n      encodedBytesCount += additionalEncodedBytesCount\n      callback(encodedBytesCount)\n    })\n  }\n\n  function addStats(stats: SerializationStats): void {\n    aggregateSerializationStats(serializationStats, stats)\n  }\n\n  function flush(callback: FlushCallback) {\n    if (encoder.isEmpty) {\n      throw new Error('Empty segment flushed')\n    }\n\n    encoder.write(`],${JSON.stringify(metadata).slice(1)}\\n`)\n    encoder.finish((encoderResult) => {\n      replayStats.addWroteData(metadata.view.id, encoderResult.rawBytesCount)\n      callback(metadata, serializationStats, encoderResult)\n    })\n  }\n\n  return { addRecord, addStats, flush }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/segmentCollection.spec.ts",
    "content": "import type { ClocksState, HttpRequest, HttpRequestEvent, TimeStamp } from '@datadog/browser-core'\nimport { DeflateEncoderStreamId, Observable, PageExitReason } from '@datadog/browser-core'\nimport type { ViewHistory, ViewHistoryEntry, RumConfiguration } from '@datadog/browser-rum-core'\nimport { LifeCycle, LifeCycleEventType } from '@datadog/browser-rum-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask, restorePageVisibility } from '@datadog/browser-core/test'\nimport { createRumSessionManagerMock } from '../../../../rum-core/test'\nimport type { BrowserRecord, SegmentContext } from '../../types'\nimport { RecordType } from '../../types'\nimport { MockWorker, readMetadataFromReplayPayload } from '../../../test'\nimport { createDeflateEncoder } from '../deflate'\nimport {\n  computeSegmentContext,\n  doStartSegmentCollection,\n  SEGMENT_BYTES_LIMIT,\n  SEGMENT_DURATION_LIMIT,\n} from './segmentCollection'\nimport type { ReplayPayload } from './buildReplayPayload'\n\nconst CONTEXT: SegmentContext = { application: { id: 'a' }, view: { id: 'b' }, session: { id: 'c' } }\nconst RECORD: BrowserRecord = { type: RecordType.ViewEnd, timestamp: 10 as TimeStamp }\n\n// A record that will make the segment size reach the SEGMENT_BYTES_LIMIT\nconst VERY_BIG_RECORD: BrowserRecord = {\n  type: RecordType.FullSnapshot,\n  timestamp: 10 as TimeStamp,\n  data: Array(SEGMENT_BYTES_LIMIT).join('a') as any,\n}\n\nconst BEFORE_SEGMENT_DURATION_LIMIT = SEGMENT_DURATION_LIMIT * 0.9\n\ndescribe('startSegmentCollection', () => {\n  let stopSegmentCollection: () => void\n  let clock: Clock\n  let lifeCycle: LifeCycle\n  let worker: MockWorker\n  let httpRequestSpy: {\n    observable: Observable<HttpRequestEvent<ReplayPayload>>\n    sendOnExit: jasmine.Spy<HttpRequest<ReplayPayload>['sendOnExit']>\n    send: jasmine.Spy<HttpRequest<ReplayPayload>['send']>\n  }\n  let addRecord: (record: BrowserRecord) => void\n  let context: SegmentContext | undefined\n  let configuration: RumConfiguration\n\n  function addRecordAndFlushSegment(flushStrategy: () => void = emulatePageUnload) {\n    // Make sure the segment is not empty\n    addRecord(RECORD)\n    // Flush segment\n    flushStrategy()\n    worker.processAllMessages()\n  }\n\n  function emulatePageUnload() {\n    lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.UNLOADING })\n  }\n\n  function readMostRecentMetadata(spy: jasmine.Spy<HttpRequest['send']>) {\n    return readMetadataFromReplayPayload(spy.calls.mostRecent().args[0])\n  }\n\n  beforeEach(() => {\n    configuration = {} as RumConfiguration\n    lifeCycle = new LifeCycle()\n    worker = new MockWorker()\n    httpRequestSpy = {\n      observable: new Observable<HttpRequestEvent<ReplayPayload>>(),\n      sendOnExit: jasmine.createSpy(),\n      send: jasmine.createSpy(),\n    }\n    context = CONTEXT\n    ;({ stop: stopSegmentCollection, addRecord } = doStartSegmentCollection(\n      lifeCycle,\n      () => context,\n      httpRequestSpy,\n      createDeflateEncoder(configuration, worker, DeflateEncoderStreamId.REPLAY)\n    ))\n\n    registerCleanupTask(() => {\n      stopSegmentCollection()\n    })\n  })\n\n  describe('initial segment', () => {\n    it('immediately starts a new segment', () => {\n      expect(worker.pendingData).toBe('')\n      addRecord(RECORD)\n      expect(worker.pendingData).toBe('{\"records\":[{\"type\":7,\"timestamp\":10}')\n      worker.processAllMessages()\n      expect(httpRequestSpy.send).not.toHaveBeenCalled()\n      expect(httpRequestSpy.sendOnExit).not.toHaveBeenCalled()\n    })\n\n    it('creation reason should reflect that it is the initial segment', async () => {\n      addRecordAndFlushSegment()\n      expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('init')\n    })\n  })\n\n  it('sends a segment', () => {\n    addRecordAndFlushSegment()\n    expect(httpRequestSpy.sendOnExit).toHaveBeenCalledTimes(1)\n  })\n\n  it(\"ignores calls to addRecord if context can't be get\", () => {\n    context = undefined\n    addRecord(RECORD)\n    emulatePageUnload()\n    expect(worker.pendingData).toBe('')\n    worker.processAllMessages()\n    expect(httpRequestSpy.send).not.toHaveBeenCalled()\n    expect(httpRequestSpy.sendOnExit).not.toHaveBeenCalled()\n  })\n\n  it('includes metadata for segment telemetry in the segment payload', () => {\n    addRecordAndFlushSegment()\n    expect(httpRequestSpy.sendOnExit.calls.mostRecent().args[0]).toEqual({\n      data: jasmine.anything(),\n      bytesCount: jasmine.anything(),\n      cssText: jasmine.anything(),\n      isFullSnapshot: jasmine.anything(),\n      rawSize: jasmine.anything(),\n      recordCount: jasmine.anything(),\n      serializationDuration: jasmine.anything(),\n    })\n  })\n\n  describe('segment flush strategy', () => {\n    afterEach(() => {\n      restorePageVisibility()\n    })\n\n    it('does not flush empty segments', () => {\n      emulatePageUnload()\n      worker.processAllMessages()\n      expect(httpRequestSpy.send).not.toHaveBeenCalled()\n      expect(httpRequestSpy.sendOnExit).not.toHaveBeenCalled()\n    })\n\n    describe('flush when the page exits because it is unloading', () => {\n      it('uses `httpRequest.sendOnExit` when sending the segment', () => {\n        addRecordAndFlushSegment(emulatePageUnload)\n        expect(httpRequestSpy.sendOnExit).toHaveBeenCalled()\n      })\n\n      it('next segment is created because of beforeunload event', async () => {\n        addRecordAndFlushSegment(emulatePageUnload)\n        addRecordAndFlushSegment()\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('before_unload')\n      })\n    })\n\n    describe('flush when the page exits because it gets hidden', () => {\n      function emulatePageHidden() {\n        lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.HIDDEN })\n      }\n\n      it('uses `httpRequest.sendOnExit` when sending the segment', () => {\n        addRecordAndFlushSegment(emulatePageHidden)\n        expect(httpRequestSpy.sendOnExit).toHaveBeenCalled()\n      })\n\n      it('next segment is created because of visibility hidden event', async () => {\n        addRecordAndFlushSegment(emulatePageHidden)\n        addRecordAndFlushSegment()\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('visibility_hidden')\n      })\n    })\n\n    describe('flush when the page exits because it gets frozen', () => {\n      function emulatePageFrozen() {\n        lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.FROZEN })\n      }\n\n      it('uses `httpRequest.sendOnExit` when sending the segment', () => {\n        addRecordAndFlushSegment(emulatePageFrozen)\n        expect(httpRequestSpy.sendOnExit).toHaveBeenCalled()\n      })\n\n      it('next segment is created because of page freeze event', async () => {\n        addRecordAndFlushSegment(emulatePageFrozen)\n        addRecordAndFlushSegment()\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('page_frozen')\n      })\n    })\n\n    describe('flush when the view changes', () => {\n      function emulateViewChange() {\n        lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, {} as any)\n      }\n\n      it('uses `httpRequest.send` when sending the segment', () => {\n        addRecordAndFlushSegment(emulateViewChange)\n        expect(httpRequestSpy.send).toHaveBeenCalled()\n      })\n\n      it('next segment is created because of view change', async () => {\n        addRecordAndFlushSegment(emulateViewChange)\n        addRecordAndFlushSegment()\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('view_change')\n      })\n    })\n\n    describe('flush when reaching a bytes limit', () => {\n      it('uses `httpRequest.send` when sending the segment', () => {\n        addRecordAndFlushSegment(() => {\n          addRecord(VERY_BIG_RECORD)\n        })\n        expect(httpRequestSpy.send).toHaveBeenCalled()\n      })\n\n      it('next segment is created because the bytes limit has been reached', async () => {\n        addRecordAndFlushSegment(() => {\n          addRecord(VERY_BIG_RECORD)\n        })\n        addRecordAndFlushSegment()\n\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('segment_bytes_limit')\n      })\n\n      it('continues to add records to the current segment while the worker is processing messages', async () => {\n        addRecord(VERY_BIG_RECORD)\n        addRecord(RECORD)\n        addRecord(RECORD)\n        addRecord(RECORD)\n        worker.processAllMessages()\n\n        expect(httpRequestSpy.send).toHaveBeenCalledTimes(1)\n        expect((await readMostRecentMetadata(httpRequestSpy.send)).records_count).toBe(4)\n      })\n\n      it('does not flush segment prematurely when records from the previous segment are still being processed', async () => {\n        // Add two records to the current segment\n        addRecord(VERY_BIG_RECORD)\n        addRecord(RECORD)\n\n        // Process only the first record. This should flush the current segment because it reached\n        // the segment bytes limit.\n        worker.processNextMessage()\n\n        // Add a record to the new segment, to make sure it is not flushed even if it is not empty\n        addRecord(RECORD)\n\n        worker.processAllMessages()\n\n        expect(httpRequestSpy.send).toHaveBeenCalledTimes(1)\n        expect((await readMostRecentMetadata(httpRequestSpy.send)).records_count).toBe(2)\n      })\n    })\n\n    describe('flush when a duration has been reached', () => {\n      it('uses `httpRequest.send` when sending the segment', () => {\n        clock = mockClock()\n        addRecordAndFlushSegment(() => {\n          clock!.tick(SEGMENT_DURATION_LIMIT)\n        })\n        expect(httpRequestSpy.send).toHaveBeenCalled()\n      })\n\n      it('next segment is created because of the segment duration limit has been reached', async () => {\n        clock = mockClock()\n        addRecordAndFlushSegment(() => {\n          clock!.tick(SEGMENT_DURATION_LIMIT)\n        })\n        addRecordAndFlushSegment()\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).toBe('segment_duration_limit')\n      })\n\n      it('does not flush a segment after SEGMENT_DURATION_LIMIT if a segment has been created in the meantime', async () => {\n        clock = mockClock()\n        addRecord(RECORD)\n        clock.tick(BEFORE_SEGMENT_DURATION_LIMIT)\n        emulatePageUnload()\n        addRecord(RECORD)\n        clock.tick(BEFORE_SEGMENT_DURATION_LIMIT)\n\n        worker.processAllMessages()\n        expect(httpRequestSpy.sendOnExit).toHaveBeenCalledTimes(1)\n        addRecordAndFlushSegment()\n        expect((await readMostRecentMetadata(httpRequestSpy.sendOnExit)).creation_reason).not.toBe(\n          'segment_duration_limit'\n        )\n      })\n    })\n\n    describe('flush when stopping segment collection', () => {\n      it('uses `httpRequest.send` when sending the segment', () => {\n        addRecordAndFlushSegment(stopSegmentCollection)\n        expect(httpRequestSpy.send).toHaveBeenCalled()\n      })\n    })\n  })\n})\n\ndescribe('computeSegmentContext', () => {\n  const DEFAULT_VIEW_CONTEXT: ViewHistoryEntry = { id: '123', startClocks: {} as ClocksState }\n  const DEFAULT_SESSION = createRumSessionManagerMock().setId('456')\n\n  it('returns a segment context', () => {\n    expect(computeSegmentContext('appid', DEFAULT_SESSION, mockViewHistory(DEFAULT_VIEW_CONTEXT))).toEqual({\n      application: { id: 'appid' },\n      session: { id: '456' },\n      view: { id: '123' },\n    })\n  })\n\n  it('returns undefined if there is no current view', () => {\n    expect(computeSegmentContext('appid', DEFAULT_SESSION, mockViewHistory(undefined))).toBeUndefined()\n  })\n\n  it('returns undefined if the session is not tracked', () => {\n    expect(\n      computeSegmentContext(\n        'appid',\n        createRumSessionManagerMock().setNotTracked(),\n        mockViewHistory(DEFAULT_VIEW_CONTEXT)\n      )\n    ).toBeUndefined()\n  })\n\n  function mockViewHistory(view: ViewHistoryEntry | undefined): ViewHistory {\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n    return {\n      findView() {\n        return view\n      },\n    } as any\n  }\n})\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/segmentCollection.ts",
    "content": "import type { DeflateEncoder, HttpRequest, TimeoutId } from '@datadog/browser-core'\nimport { isPageExitReason, ONE_SECOND, clearTimeout, setTimeout } from '@datadog/browser-core'\nimport type { LifeCycle, ViewHistory, RumSessionManager, RumConfiguration } from '@datadog/browser-rum-core'\nimport { LifeCycleEventType } from '@datadog/browser-rum-core'\nimport type { BrowserRecord, CreationReason, SegmentContext } from '../../types'\nimport type { SerializationStats } from '../record'\nimport type { ReplayPayload } from './buildReplayPayload'\nimport { buildReplayPayload } from './buildReplayPayload'\nimport type { FlushReason, Segment } from './segment'\nimport { createSegment } from './segment'\n\nexport const SEGMENT_DURATION_LIMIT = 5 * ONE_SECOND\n/**\n * beacon payload max queue size implementation is 64kb\n * ensure that we leave room for logs, rum and potential other users\n */\nexport let SEGMENT_BYTES_LIMIT = 60_000\n\n// Segments are the main data structure for session replays. They contain context information used\n// for indexing or UI needs, and a list of records (RRWeb 'events', renamed to avoid confusing\n// namings). They are stored without any processing from the intake, and fetched one after the\n// other while a session is being replayed. Their encoding (deflate) are carefully crafted to allow\n// concatenating multiple segments together. Segments have a size overhead (metadata), so our goal is to\n// build segments containing as many records as possible while complying with the various flush\n// strategies to guarantee a good replay quality.\n//\n// When the recording starts, a segment is initially created.  The segment is flushed (finalized and\n// sent) based on various events (non-exhaustive list):\n//\n// * the page visibility change or becomes to unload\n// * the segment duration reaches a limit\n// * the encoded segment bytes count reaches a limit\n// * ...\n//\n// A segment cannot be created without its context.  If the RUM session ends and no session id is\n// available when creating a new segment, records will be ignored, until the session is renewed and\n// a new session id is available.\n//\n// Empty segments (segments with no record) aren't useful and should be ignored.\n//\n// To help investigate session replays issues, each segment is created with a \"creation reason\",\n// indicating why the session has been created.\n\ninterface SegmentCollector {\n  addRecord(this: void, record: BrowserRecord): void\n  addStats(this: void, stats: SerializationStats): void\n  stop(this: void): void\n}\n\nexport function startSegmentCollection(\n  lifeCycle: LifeCycle,\n  configuration: RumConfiguration,\n  sessionManager: RumSessionManager,\n  viewHistory: ViewHistory,\n  httpRequest: HttpRequest<ReplayPayload>,\n  encoder: DeflateEncoder\n): SegmentCollector {\n  return doStartSegmentCollection(\n    lifeCycle,\n    () => computeSegmentContext(configuration.applicationId, sessionManager, viewHistory),\n    httpRequest,\n    encoder\n  )\n}\n\nconst enum SegmentCollectionStatus {\n  WaitingForInitialRecord,\n  SegmentPending,\n  Stopped,\n}\ntype SegmentCollectionState =\n  | {\n      status: SegmentCollectionStatus.WaitingForInitialRecord\n      nextSegmentCreationReason: CreationReason\n    }\n  | {\n      status: SegmentCollectionStatus.SegmentPending\n      segment: Segment\n      expirationTimeoutId: TimeoutId\n    }\n  | {\n      status: SegmentCollectionStatus.Stopped\n    }\n\nexport function doStartSegmentCollection(\n  lifeCycle: LifeCycle,\n  getSegmentContext: () => SegmentContext | undefined,\n  httpRequest: HttpRequest<ReplayPayload>,\n  encoder: DeflateEncoder\n): SegmentCollector {\n  let state: SegmentCollectionState = {\n    status: SegmentCollectionStatus.WaitingForInitialRecord,\n    nextSegmentCreationReason: 'init',\n  }\n\n  const { unsubscribe: unsubscribeViewCreated } = lifeCycle.subscribe(LifeCycleEventType.VIEW_CREATED, () => {\n    flushSegment('view_change')\n  })\n\n  const { unsubscribe: unsubscribePageMayExit } = lifeCycle.subscribe(\n    LifeCycleEventType.PAGE_MAY_EXIT,\n    (pageMayExitEvent) => {\n      flushSegment(pageMayExitEvent.reason as FlushReason)\n    }\n  )\n\n  function flushSegment(flushReason: FlushReason) {\n    if (state.status === SegmentCollectionStatus.SegmentPending) {\n      state.segment.flush((metadata, stats, encoderResult) => {\n        const payload = buildReplayPayload(encoderResult.output, metadata, stats, encoderResult.rawBytesCount)\n\n        if (isPageExitReason(flushReason)) {\n          httpRequest.sendOnExit(payload)\n        } else {\n          httpRequest.send(payload)\n        }\n      })\n      clearTimeout(state.expirationTimeoutId)\n    }\n\n    if (flushReason !== 'stop') {\n      state = {\n        status: SegmentCollectionStatus.WaitingForInitialRecord,\n        nextSegmentCreationReason: flushReason,\n      }\n    } else {\n      state = {\n        status: SegmentCollectionStatus.Stopped,\n      }\n    }\n  }\n\n  return {\n    addRecord: (record: BrowserRecord) => {\n      if (state.status === SegmentCollectionStatus.Stopped) {\n        return\n      }\n\n      if (state.status === SegmentCollectionStatus.WaitingForInitialRecord) {\n        const context = getSegmentContext()\n        if (!context) {\n          return\n        }\n\n        state = {\n          status: SegmentCollectionStatus.SegmentPending,\n          segment: createSegment({ encoder, context, creationReason: state.nextSegmentCreationReason }),\n          expirationTimeoutId: setTimeout(() => {\n            flushSegment('segment_duration_limit')\n          }, SEGMENT_DURATION_LIMIT),\n        }\n      }\n\n      state.segment.addRecord(record, (encodedBytesCount) => {\n        if (encodedBytesCount > SEGMENT_BYTES_LIMIT) {\n          flushSegment('segment_bytes_limit')\n        }\n      })\n    },\n\n    addStats: (stats: SerializationStats) => {\n      if (state.status === SegmentCollectionStatus.SegmentPending) {\n        state.segment.addStats(stats)\n      }\n    },\n\n    stop: () => {\n      flushSegment('stop')\n      unsubscribeViewCreated()\n      unsubscribePageMayExit()\n    },\n  }\n}\n\nexport function computeSegmentContext(\n  applicationId: string,\n  sessionManager: RumSessionManager,\n  viewHistory: ViewHistory\n) {\n  const session = sessionManager.findTrackedSession()\n  const viewContext = viewHistory.findView()\n  if (!session || !viewContext) {\n    return undefined\n  }\n  return {\n    application: {\n      id: applicationId,\n    },\n    session: {\n      id: session.id,\n    },\n    view: {\n      id: viewContext.id,\n    },\n  }\n}\n\nexport function setSegmentBytesLimit(newSegmentBytesLimit = 60_000) {\n  SEGMENT_BYTES_LIMIT = newSegmentBytesLimit\n}\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/startSegmentTelemetry.spec.ts",
    "content": "import type { Telemetry, HttpRequestEvent, BandwidthStats } from '@datadog/browser-core'\nimport { addExperimentalFeatures, ExperimentalFeature, Observable } from '@datadog/browser-core'\nimport type { MockTelemetry } from '@datadog/browser-core/test'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport { startMockTelemetry } from '../../../../core/test'\nimport { isFullSnapshotChangeRecordsEnabled, isIncrementalSnapshotChangeRecordsEnabled } from '../record'\nimport { startSegmentTelemetry } from './startSegmentTelemetry'\nimport type { ReplayPayload } from './buildReplayPayload'\n\ndescribe('segmentTelemetry', () => {\n  let requestObservable: Observable<HttpRequestEvent<ReplayPayload>>\n  let telemetry: MockTelemetry\n  let stopSegmentTelemetry: (() => void) | undefined\n\n  function generateReplayRequest({\n    result,\n    isFullSnapshot,\n  }: {\n    result: 'failure' | 'queue-full' | 'success'\n    isFullSnapshot: boolean\n  }) {\n    const bandwidth: BandwidthStats = {\n      ongoingByteCount: 3000,\n      ongoingRequestCount: 2,\n    }\n    const payload: ReplayPayload = {\n      data: '',\n      bytesCount: 1000,\n      cssText: {\n        count: 2,\n        max: 300,\n        sum: 500,\n      },\n      isFullSnapshot,\n      rawSize: 2000,\n      recordCount: 3,\n      serializationDuration: {\n        count: 3,\n        max: 65,\n        sum: 105,\n      },\n    }\n    requestObservable.notify({ type: result, bandwidth, payload })\n  }\n\n  function setupSegmentTelemetryCollection(metricsEnabled: boolean = true) {\n    requestObservable = new Observable()\n    telemetry = startMockTelemetry()\n    ;({ stop: stopSegmentTelemetry } = startSegmentTelemetry({ metricsEnabled } as Telemetry, requestObservable))\n    registerCleanupTask(stopSegmentTelemetry)\n  }\n\n  for (const [featureFlag, description] of [\n    [undefined, 'V1 records enabled'],\n    [ExperimentalFeature.USE_CHANGE_RECORDS, 'full snapshot Change records enabled'],\n    [ExperimentalFeature.USE_INCREMENTAL_CHANGE_RECORDS, 'incremental snapshot Change records enabled'],\n  ] as const) {\n    it(`with ${description}, should collect segment telemetry for all full snapshots`, async () => {\n      if (featureFlag) {\n        addExperimentalFeatures([featureFlag])\n      }\n\n      setupSegmentTelemetryCollection()\n\n      for (const result of ['failure', 'queue-full', 'success'] as const) {\n        generateReplayRequest({ result, isFullSnapshot: true })\n\n        expect(await telemetry.getEvents()).toEqual([\n          jasmine.objectContaining({\n            type: 'log',\n            status: 'debug',\n            message: 'Segment network request metrics',\n            metrics: {\n              cssText: {\n                count: 2,\n                max: 300,\n                sum: 500,\n              },\n              encoding: {\n                fullSnapshot: isFullSnapshotChangeRecordsEnabled() ? 'change' : 'v1',\n                incrementalSnapshot: isIncrementalSnapshotChangeRecordsEnabled() ? 'change' : 'v1',\n              },\n              isFullSnapshot: true,\n              ongoingRequests: {\n                count: 2,\n                totalSize: 3000,\n              },\n              recordCount: 3,\n              result,\n              size: {\n                compressed: 1000,\n                raw: 2000,\n              },\n              serializationDuration: {\n                count: 3,\n                max: 65,\n                sum: 105,\n              },\n            },\n          }),\n        ])\n\n        telemetry.reset()\n      }\n    })\n  }\n\n  it('should collect segment telemetry for failed incremental mutation requests', async () => {\n    setupSegmentTelemetryCollection()\n\n    for (const result of ['failure', 'queue-full'] as const) {\n      generateReplayRequest({ result, isFullSnapshot: false })\n\n      expect(await telemetry.getEvents()).toEqual([\n        jasmine.objectContaining({\n          type: 'log',\n          status: 'debug',\n          message: 'Segment network request metrics',\n          metrics: {\n            cssText: {\n              count: 2,\n              max: 300,\n              sum: 500,\n            },\n            encoding: {\n              fullSnapshot: 'v1',\n              incrementalSnapshot: 'v1',\n            },\n            isFullSnapshot: false,\n            ongoingRequests: {\n              count: 2,\n              totalSize: 3000,\n            },\n            recordCount: 3,\n            result,\n            size: {\n              compressed: 1000,\n              raw: 2000,\n            },\n            serializationDuration: {\n              count: 3,\n              max: 65,\n              sum: 105,\n            },\n          },\n        }),\n      ])\n\n      telemetry.reset()\n    }\n  })\n\n  it('should not collect segment telemetry for successful incremental mutation requests', async () => {\n    setupSegmentTelemetryCollection()\n    generateReplayRequest({ result: 'success', isFullSnapshot: false })\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n\n  it('should not collect segment when telemetry disabled', async () => {\n    setupSegmentTelemetryCollection(false)\n    generateReplayRequest({ result: 'success', isFullSnapshot: true })\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/rum/src/domain/segmentCollection/startSegmentTelemetry.ts",
    "content": "import type { BandwidthStats, Context, HttpRequestEvent, Observable, Telemetry } from '@datadog/browser-core'\nimport { TelemetryMetrics, addTelemetryMetrics, noop } from '@datadog/browser-core'\nimport { isFullSnapshotChangeRecordsEnabled, isIncrementalSnapshotChangeRecordsEnabled } from '../record'\nimport type { ReplayPayload } from './buildReplayPayload'\n\ninterface SegmentMetrics extends Context {\n  cssText: {\n    count: number\n    max: number\n    sum: number\n  }\n  encoding: {\n    fullSnapshot: 'v1' | 'change'\n    incrementalSnapshot: 'v1' | 'change'\n  }\n  isFullSnapshot: boolean\n  ongoingRequests: {\n    count: number\n    totalSize: number\n  }\n  recordCount: number\n  result: 'failure' | 'queue-full' | 'success'\n  serializationDuration: {\n    count: number\n    max: number\n    sum: number\n  }\n  size: {\n    compressed: number\n    raw: number\n  }\n}\n\nexport function startSegmentTelemetry(\n  telemetry: Telemetry,\n  requestObservable: Observable<HttpRequestEvent<ReplayPayload>>\n) {\n  if (!telemetry.metricsEnabled) {\n    return { stop: noop }\n  }\n\n  const { unsubscribe } = requestObservable.subscribe((requestEvent) => {\n    if (\n      requestEvent.type === 'failure' ||\n      requestEvent.type === 'queue-full' ||\n      (requestEvent.type === 'success' && requestEvent.payload.isFullSnapshot)\n    ) {\n      const metrics = createSegmentMetrics(requestEvent.type, requestEvent.bandwidth, requestEvent.payload)\n      // monitor-until: 2026-07-01\n      addTelemetryMetrics(TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, { metrics })\n    }\n  })\n\n  return {\n    stop: unsubscribe,\n  }\n}\n\nfunction createSegmentMetrics(\n  result: SegmentMetrics['result'],\n  bandwidthStats: BandwidthStats,\n  payload: ReplayPayload\n): SegmentMetrics {\n  return {\n    cssText: {\n      count: payload.cssText.count,\n      max: payload.cssText.max,\n      sum: payload.cssText.sum,\n    },\n    encoding: {\n      fullSnapshot: isFullSnapshotChangeRecordsEnabled() ? 'change' : 'v1',\n      incrementalSnapshot: isIncrementalSnapshotChangeRecordsEnabled() ? 'change' : 'v1',\n    },\n    isFullSnapshot: payload.isFullSnapshot,\n    ongoingRequests: {\n      count: bandwidthStats.ongoingRequestCount,\n      totalSize: bandwidthStats.ongoingByteCount,\n    },\n    recordCount: payload.recordCount,\n    result,\n    serializationDuration: {\n      count: payload.serializationDuration.count,\n      max: payload.serializationDuration.max,\n      sum: payload.serializationDuration.sum,\n    },\n    size: {\n      compressed: payload.bytesCount,\n      raw: payload.rawSize,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/startRecordBridge.ts",
    "content": "import { getEventBridge } from '@datadog/browser-core'\nimport type { ViewHistory } from '@datadog/browser-rum-core'\nimport type { BrowserRecord } from '../types'\n\nexport function startRecordBridge(viewHistory: ViewHistory) {\n  const bridge = getEventBridge<'record', BrowserRecord>()!\n\n  return {\n    addRecord: (record: BrowserRecord) => {\n      // Get the current active view, not at the time of the record, aligning with the segment logic.\n      // This approach could potentially associate the record to an incorrect view, in case the record date is in the past (e.g. frustration records).\n      // However the risk is minimal. We could address the issue when potential negative impact are identified.\n      const view = viewHistory.findView()!\n      bridge.send('record', record, view.id)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/startRecorderInitTelemetry.spec.ts",
    "content": "import type { Telemetry, RawTelemetryEvent } from '@datadog/browser-core'\nimport { Observable } from '@datadog/browser-core'\nimport type { MockTelemetry } from '@datadog/browser-core/test'\nimport { registerCleanupTask, startMockTelemetry } from '@datadog/browser-core/test'\nimport type { RecorderInitEvent } from '../boot/postStartStrategy'\nimport { type RecorderInitMetrics, startRecorderInitTelemetry } from './startRecorderInitTelemetry'\n\ndescribe('startRecorderInitTelemetry', () => {\n  let observable: Observable<RecorderInitEvent>\n  let telemetry: MockTelemetry\n\n  function startRecorderInitTelemetryCollection(metricsEnabled: boolean = true) {\n    observable = new Observable<RecorderInitEvent>()\n    telemetry = startMockTelemetry()\n    const { stop: stopRecorderInitTelemetry } = startRecorderInitTelemetry({ metricsEnabled } as Telemetry, observable)\n    registerCleanupTask(stopRecorderInitTelemetry)\n  }\n\n  it('should collect recorder init metrics telemetry', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.getEvents()).toEqual([expectedRecorderInitTelemetry()])\n  })\n\n  it('should not collect recorder init metrics telemetry twice', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.getEvents()).toEqual([expectedRecorderInitTelemetry()])\n\n    telemetry.reset()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.hasEvents()).toEqual(false)\n  })\n\n  it('should not collect recorder init metrics telemetry unless start time is known', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.hasEvents()).toEqual(false)\n  })\n\n  it('should collect recorder init metrics telemetry even without document-ready', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.getEvents()).toEqual([\n      expectedRecorderInitTelemetry({\n        waitForDocReadyDuration: undefined,\n      }),\n    ])\n  })\n\n  it('should collect recorder init metrics telemetry even without recorder-settled', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.getEvents()).toEqual([\n      expectedRecorderInitTelemetry({\n        loadRecorderModuleDuration: undefined,\n      }),\n    ])\n  })\n\n  it('should report if recording is aborted', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'aborted' })\n    expect(await telemetry.getEvents()).toEqual([\n      expectedRecorderInitTelemetry({\n        result: 'aborted',\n      }),\n    ])\n  })\n\n  it('should report if the deflate encoder fails to load', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'deflate-encoder-load-failed' })\n    expect(await telemetry.getEvents()).toEqual([\n      expectedRecorderInitTelemetry({\n        result: 'deflate-encoder-load-failed',\n      }),\n    ])\n  })\n\n  it('should report if the recorder module fails to load', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'recorder-load-failed' })\n    expect(await telemetry.getEvents()).toEqual([\n      expectedRecorderInitTelemetry({\n        result: 'recorder-load-failed',\n      }),\n    ])\n  })\n\n  it('should report if the recording was force-enabled', async () => {\n    startRecorderInitTelemetryCollection()\n    observable.notify({ type: 'start', forced: true })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.getEvents()).toEqual([\n      expectedRecorderInitTelemetry({\n        forced: true,\n      }),\n    ])\n  })\n\n  it('should not collect recorder init metrics telemetry when telemetry is disabled', async () => {\n    startRecorderInitTelemetryCollection(false)\n    observable.notify({ type: 'start', forced: false })\n    observable.notify({ type: 'recorder-settled' })\n    observable.notify({ type: 'document-ready' })\n    observable.notify({ type: 'succeeded' })\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n})\n\nfunction expectedRecorderInitTelemetry(overrides: Partial<RecorderInitMetrics> = {}): RawTelemetryEvent {\n  return {\n    type: 'log',\n    status: 'debug',\n    message: 'Recorder init metrics',\n    metrics: {\n      forced: false,\n      loadRecorderModuleDuration: jasmine.any(Number),\n      recorderInitDuration: jasmine.any(Number),\n      result: 'succeeded',\n      waitForDocReadyDuration: jasmine.any(Number),\n      ...overrides,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/domain/startRecorderInitTelemetry.ts",
    "content": "import type { Context, Duration, Telemetry, Observable, TimeStamp } from '@datadog/browser-core'\nimport { TelemetryMetrics, addTelemetryMetrics, noop, timeStampNow, elapsed } from '@datadog/browser-core'\nimport type { RecorderInitEvent } from '../boot/postStartStrategy'\n\ntype RecorderInitResult = 'aborted' | 'deflate-encoder-load-failed' | 'recorder-load-failed' | 'succeeded'\n\nexport interface RecorderInitMetrics extends Context {\n  forced: boolean\n  loadRecorderModuleDuration: number | undefined\n  recorderInitDuration: number\n  result: RecorderInitResult\n  waitForDocReadyDuration: number | undefined\n}\n\nexport function startRecorderInitTelemetry(telemetry: Telemetry, observable: Observable<RecorderInitEvent>) {\n  if (!telemetry.metricsEnabled) {\n    return { stop: noop }\n  }\n\n  let startContext:\n    | {\n        forced: boolean\n        timestamp: TimeStamp\n      }\n    | undefined\n\n  let documentReadyDuration: Duration | undefined\n  let recorderSettledDuration: Duration | undefined\n\n  const { unsubscribe } = observable.subscribe((event) => {\n    switch (event.type) {\n      case 'start':\n        startContext = { forced: event.forced, timestamp: timeStampNow() }\n        documentReadyDuration = undefined\n        recorderSettledDuration = undefined\n        break\n\n      case 'document-ready':\n        if (startContext) {\n          documentReadyDuration = elapsed(startContext.timestamp, timeStampNow())\n        }\n        break\n\n      case 'recorder-settled':\n        if (startContext) {\n          recorderSettledDuration = elapsed(startContext.timestamp, timeStampNow())\n        }\n        break\n\n      case 'aborted':\n      case 'deflate-encoder-load-failed':\n      case 'recorder-load-failed':\n      case 'succeeded':\n        // Only send metrics for the first attempt at starting the recorder.\n        unsubscribe()\n\n        if (startContext) {\n          // monitor-until: 2026-07-01\n          addTelemetryMetrics(TelemetryMetrics.RECORDER_INIT_METRICS_TELEMETRY_NAME, {\n            metrics: createRecorderInitMetrics(\n              startContext.forced,\n              recorderSettledDuration,\n              elapsed(startContext.timestamp, timeStampNow()),\n              event.type,\n              documentReadyDuration\n            ),\n          })\n        }\n        break\n    }\n  })\n\n  return { stop: unsubscribe }\n}\n\nfunction createRecorderInitMetrics(\n  forced: boolean,\n  loadRecorderModuleDuration: Duration | undefined,\n  recorderInitDuration: Duration,\n  result: RecorderInitResult,\n  waitForDocReadyDuration: Duration | undefined\n): RecorderInitMetrics {\n  return {\n    forced,\n    loadRecorderModuleDuration,\n    recorderInitDuration,\n    result,\n    waitForDocReadyDuration,\n  }\n}\n"
  },
  {
    "path": "packages/rum/src/entries/internal.ts",
    "content": "/**\n * Entry point consumed by the Datadog Web app to mutualize some types, constant and logic for\n * tests.\n *\n * WARNING: this module is not intended for public usages, and won't follow semver for breaking\n * changes.\n */\nexport type { TimeStamp } from '@datadog/browser-core'\nexport {\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_HIDDEN,\n  PRIVACY_CLASS_PREFIX,\n  NodePrivacyLevel,\n} from '@datadog/browser-rum-core'\n\nexport * from '../types'\n\nexport { takeFullSnapshot, takeNodeSnapshot, serializeNode as serializeNodeWithId } from '../domain/record'\n"
  },
  {
    "path": "packages/rum/src/entries/internalSynthetics.ts",
    "content": "/**\n * Entry point consumed by the Datadog Synthetics worker to automatically inject a RUM SDK instance\n * in test runs.\n *\n * WARNING: this module is not intended for public usages, and won't follow semver for breaking\n * changes.\n */\nimport { makeRumPublicApi } from '@datadog/browser-rum-core'\nimport { makeRecorderApi } from '../boot/recorderApi'\nimport { makeProfilerApi } from '../boot/profilerApi'\n\nexport { DefaultPrivacyLevel } from '@datadog/browser-core'\n\n// Disable the rule that forbids potential side effects, because we know that those functions don't\n// have side effects.\n/* eslint-disable local-rules/disallow-side-effects */\nconst recorderApi = makeRecorderApi()\nconst profilerApi = makeProfilerApi()\nexport const datadogRum = makeRumPublicApi(recorderApi, profilerApi, {\n  ignoreInitIfSyntheticsWillInjectRum: false,\n  sdkName: 'rum-synthetics',\n})\n/* eslint-enable local-rules/disallow-side-effects */\n"
  },
  {
    "path": "packages/rum/src/entries/main.ts",
    "content": "/**\n * Datadog Browser RUM SDK - Full version with Session Replay and Real User Profiling capabilities.\n * Use this package to monitor your web application's performance and user experience.\n *\n * @packageDocumentation\n * @see [RUM Browser Monitoring Setup](https://docs.datadoghq.com/real_user_monitoring/browser/)\n */\n\n// Keep the following in sync with packages/rum-slim/src/entries/main.ts\nimport { defineGlobal, getGlobalObject } from '@datadog/browser-core'\nimport type { RumPublicApi } from '@datadog/browser-rum-core'\nimport { makeRumPublicApi } from '@datadog/browser-rum-core'\nimport { makeRecorderApi } from '../boot/recorderApi'\nimport { createDeflateEncoder, startDeflateWorker } from '../domain/deflate'\nimport { makeProfilerApi } from '../boot/profilerApi'\n\nexport type {\n  User,\n  Account,\n  TraceContextInjection,\n  SessionPersistence,\n  TrackingConsent,\n  MatchOption,\n  ProxyFn,\n  Site,\n  Context,\n  ContextValue,\n  ContextArray,\n  RumInternalContext,\n} from '@datadog/browser-core'\nexport { DefaultPrivacyLevel } from '@datadog/browser-core'\n\n/**\n * @deprecated Use {@link DatadogRum} instead\n */\nexport type RumGlobal = RumPublicApi\n\nexport type {\n  RumPublicApi as DatadogRum,\n  RumInitConfiguration,\n  RumBeforeSend,\n  ViewOptions,\n  StartRecordingOptions,\n  AddDurationVitalOptions,\n  DurationVitalOptions,\n  DurationVitalReference,\n  TracingOption,\n  RumPlugin,\n  OnRumStartOptions,\n  PropagatorType,\n  FeatureFlagsForEvents,\n  MatchHeader,\n\n  // Events\n  CommonProperties,\n  RumEvent,\n  RumActionEvent,\n  RumErrorEvent,\n  RumLongTaskEvent,\n  RumResourceEvent,\n  RumViewEvent,\n  RumVitalEvent,\n\n  // Events context\n  RumEventDomainContext,\n  RumViewEventDomainContext,\n  RumErrorEventDomainContext,\n  RumActionEventDomainContext,\n  RumVitalEventDomainContext,\n  RumFetchResourceEventDomainContext,\n  RumXhrResourceEventDomainContext,\n  RumOtherResourceEventDomainContext,\n  RumLongTaskEventDomainContext,\n} from '@datadog/browser-rum-core'\n\nexport { DEFAULT_TRACKED_RESOURCE_HEADERS } from '@datadog/browser-rum-core'\n\nconst recorderApi = makeRecorderApi()\n\nconst profilerApi = makeProfilerApi()\n\n/**\n * The global RUM instance. Use this to call RUM methods.\n *\n * @category Main\n * @see {@link DatadogRum}\n * @see [RUM Browser Monitoring Setup](https://docs.datadoghq.com/real_user_monitoring/browser/)\n */\nexport const datadogRum = makeRumPublicApi(recorderApi, profilerApi, {\n  startDeflateWorker,\n  createDeflateEncoder,\n  sdkName: 'rum',\n})\n\ninterface BrowserWindow extends Window {\n  DD_RUM?: RumPublicApi\n}\ndefineGlobal(getGlobalObject<BrowserWindow>(), 'DD_RUM', datadogRum)\n"
  },
  {
    "path": "packages/rum/src/types/index.ts",
    "content": "export type * from './sessionReplay'\nexport * from './sessionReplayConstants'\nexport type * from './profiling'\n"
  },
  {
    "path": "packages/rum/src/types/profiling.ts",
    "content": "/**\n * DO NOT MODIFY IT BY HAND. Run `yarn json-schemas:sync` instead.\n */\n\n/**\n * Schema of Browser SDK Profiling types.\n */\nexport type BrowserProfiling = BrowserProfileEvent | BrowserProfilerTrace\n/**\n * Schema of the Browser SDK Profile Event payload.\n */\nexport type BrowserProfileEvent = ProfileCommonProperties & {\n  /**\n   * Profile data format.\n   */\n  readonly format: 'json'\n  /**\n   * Datadog internal metadata.\n   */\n  readonly _dd: {\n    /**\n     * Clock drift value. Used by Browser SDK.\n     */\n    readonly clock_drift: number\n  }\n  /**\n   * Action properties.\n   */\n  readonly action?: {\n    /**\n     * Array of action IDs.\n     */\n    readonly id: string[]\n    /**\n     * Array of action labels.\n     */\n    readonly label: string[]\n  }\n}\n\n/**\n * Schema of a Profile Event metadata. Contains attributes shared by all profiles.\n */\nexport interface ProfileCommonProperties {\n  /**\n   * Application properties.\n   */\n  readonly application: {\n    /**\n     * Application ID.\n     */\n    readonly id: string\n  }\n  /**\n   * Session properties.\n   */\n  readonly session?: {\n    /**\n     * Session ID.\n     */\n    readonly id: string\n  }\n  /**\n   * View properties.\n   */\n  readonly view?: {\n    /**\n     * Array of view IDs.\n     */\n    readonly id: string[]\n    /**\n     * Array of view names.\n     */\n    readonly name: string[]\n  }\n  /**\n   * Long task properties.\n   */\n  readonly long_task?: {\n    /**\n     * Array of long task IDs.\n     */\n    readonly id: string[]\n  }\n  /**\n   * Vital properties.\n   */\n  readonly vital?: {\n    /**\n     * Array of vital IDs.\n     */\n    readonly id: string[]\n    /**\n     * Array of vital labels.\n     */\n    readonly label: string[]\n  }\n  /**\n   * List of attachment filenames.\n   */\n  readonly attachments: string[]\n  /**\n   * Start time as ISO 8601 date string (yyyy-MM-dd'T'HH:mm:ss.SSS'Z').\n   */\n  readonly start: string\n  /**\n   * End time marking when the profile ended, as ISO 8601 date string (yyyy-MM-dd'T'HH:mm:ss.SSS'Z').\n   */\n  readonly end: string\n  /**\n   * Profiler family.\n   */\n  readonly family: 'android' | 'chrome' | 'ios'\n  /**\n   * Runtime environment.\n   */\n  readonly runtime: 'android' | 'chrome' | 'ios'\n  /**\n   * Profile ingestion event version.\n   */\n  readonly version: number\n  /**\n   * Comma-separated profiler tags.\n   */\n  readonly tags_profiler: string\n}\n/**\n * Schema of a RUM profiler trace containing profiling data enriched with RUM context.\n */\nexport interface BrowserProfilerTrace {\n  /**\n   * An array of profiler resources.\n   */\n  readonly resources: string[]\n  /**\n   * An array of profiler frames.\n   */\n  readonly frames: ProfilerFrame[]\n  /**\n   * An array of profiler stacks.\n   */\n  readonly stacks: ProfilerStack[]\n  /**\n   * An array of profiler samples.\n   */\n  readonly samples: ProfilerSample[]\n  startClocks: ClocksState\n  endClocks: ClocksState\n  clocksOrigin: ClocksState\n  /**\n   * Sample interval in milliseconds.\n   */\n  readonly sampleInterval: number\n  /**\n   * List of detected long tasks.\n   */\n  readonly longTasks: RumProfilerLongTaskEntry[]\n  /**\n   * List of detected vital entries.\n   */\n  readonly vitals?: RumProfilerVitalEntry[]\n  /**\n   * List of detected action entries.\n   */\n  readonly actions?: RumProfilerActionEntry[]\n  /**\n   * List of detected navigation entries.\n   */\n  readonly views: RumViewEntry[]\n}\n/**\n * Schema of a profiler frame from the JS Self-Profiling API.\n */\nexport interface ProfilerFrame {\n  /**\n   * A function instance name.\n   */\n  readonly name: string\n  /**\n   * Index in the trace.resources array.\n   */\n  readonly resourceId?: number\n  /**\n   * 1-based index of the line.\n   */\n  readonly line?: number\n  /**\n   * 1-based index of the column.\n   */\n  readonly column?: number\n}\n/**\n * Schema of a profiler stack from the JS Self-Profiling API.\n */\nexport interface ProfilerStack {\n  /**\n   * Index in the trace.stacks array.\n   */\n  readonly parentId?: number\n  /**\n   * Index in the trace.frames array.\n   */\n  readonly frameId: number\n}\n/**\n * Schema of a profiler sample from the JS Self-Profiling API.\n */\nexport interface ProfilerSample {\n  /**\n   * High resolution time relative to the profiling session's time origin.\n   */\n  readonly timestamp: number\n  /**\n   * Index in the trace.stacks array.\n   */\n  readonly stackId?: number\n}\n/**\n * Schema of timing state with both relative and absolute timestamps.\n */\nexport interface ClocksState {\n  /**\n   * Time relative to navigation start in milliseconds.\n   */\n  readonly relative: number\n  /**\n   * Epoch time in milliseconds.\n   */\n  readonly timeStamp: number\n}\n/**\n * Schema of a long task entry recorded during profiling.\n */\nexport interface RumProfilerLongTaskEntry {\n  /**\n   * RUM Long Task id.\n   */\n  readonly id?: string\n  /**\n   * Duration in ms of the long task or long animation frame.\n   */\n  readonly duration: number\n  /**\n   * Type of the event: long task or long animation frame\n   */\n  readonly entryType: 'longtask' | 'long-animation-frame'\n  startClocks: ClocksState\n}\n/**\n * Schema of a vital entry recorded during profiling.\n */\nexport interface RumProfilerVitalEntry {\n  /**\n   * RUM Vital id.\n   */\n  readonly id: string\n  /**\n   * RUM Vital label.\n   */\n  readonly label: string\n  /**\n   * Duration in ms of the vital.\n   */\n  readonly duration?: number\n  startClocks: ClocksState\n}\n/**\n * Schema of a action entry recorded during profiling.\n */\nexport interface RumProfilerActionEntry {\n  /**\n   * RUM Action id.\n   */\n  readonly id: string\n  /**\n   * RUM Action label.\n   */\n  readonly label: string\n  /**\n   * Duration in ms of the duration vital.\n   */\n  readonly duration?: number\n  startClocks: ClocksState\n}\n/**\n * Schema of a RUM view entry recorded during profiling.\n */\nexport interface RumViewEntry {\n  startClocks: ClocksState\n  /**\n   * RUM view id.\n   */\n  readonly viewId: string\n  /**\n   * RUM view name.\n   */\n  readonly viewName?: string\n}\n"
  },
  {
    "path": "packages/rum/src/types/sessionReplay.ts",
    "content": "/**\n * DO NOT MODIFY IT BY HAND. Run `yarn json-schemas:sync` instead.\n */\n\n/**\n * Browser-specific. Schema of a Session Replay data Segment.\n */\nexport type BrowserSegment = BrowserSegmentMetadata & {\n  /**\n   * The records contained by this Segment.\n   */\n  readonly records: BrowserRecord[]\n}\n/**\n * Browser-specific. Schema of a Session Replay Segment metadata.\n */\nexport type BrowserSegmentMetadata = SegmentContext &\n  CommonSegmentMetadataSchema & {\n    /**\n     * The source of this record\n     */\n    source: 'browser'\n    creation_reason: CreationReason\n  }\n/**\n * The reason this Segment was created. For mobile there is only one possible value for this, which is always the default value.\n */\nexport type CreationReason =\n  | 'init'\n  | 'segment_duration_limit'\n  | 'segment_bytes_limit'\n  | 'view_change'\n  | 'before_unload'\n  | 'visibility_hidden'\n  | 'page_frozen'\n/**\n * Browser-specific. Schema of a Session Replay Record.\n */\nexport type BrowserRecord =\n  | BrowserFullSnapshotRecord\n  | BrowserIncrementalSnapshotRecord\n  | MetaRecord\n  | FocusRecord\n  | ViewEndRecord\n  | VisualViewportRecord\n  | FrustrationRecord\n  | BrowserChangeRecord\n/**\n * Browser-specific. Schema of a Record type which contains a full snapshot of a document.\n */\nexport type BrowserFullSnapshotRecord = BrowserFullSnapshotV1Record | BrowserFullSnapshotChangeRecord\n/**\n * Browser-specific. Schema of a Record type which contains a full snapshot of a document in V1 format.\n */\nexport type BrowserFullSnapshotV1Record = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 2\n  readonly format?: SnapshotFormatV1\n  data: BrowserNode\n}\n/**\n * Schema of common properties for a Record event type that is supported by slots.\n */\nexport type SlotSupportedCommonRecordSchema = CommonRecordSchema & {\n  /**\n   * Unique ID of the slot that generated this record.\n   */\n  readonly slotId?: string\n}\n/**\n * The V1 snapshot format.\n */\nexport type SnapshotFormatV1 = 0\n/**\n * Serialized node contained by this Record.\n */\nexport type SerializedNodeWithId = {\n  id: number\n} & SerializedNode\n/**\n * Serialized node contained by this Record.\n */\nexport type SerializedNode = DocumentNode | DocumentFragmentNode | DocumentTypeNode | ElementNode | TextNode | CDataNode\n/**\n * Browser-specific. Schema of a Record type which contains a full snapshot of a document in Change format.\n */\nexport type BrowserFullSnapshotChangeRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 2\n  readonly format: SnapshotFormatChange\n  data: Change[]\n}\n/**\n * The Change snapshot format.\n */\nexport type SnapshotFormatChange = 1\n/**\n * Browser-specific. Schema representing an individual change within a BrowserChangeData collection.\n */\nexport type Change =\n  | [0, ...AddStringChange[]]\n  | [1, ...AddNodeChange[]]\n  | [2, ...RemoveNodeChange[]]\n  | [3, ...AttributeChange[]]\n  | [4, ...TextChange[]]\n  | [5, ...SizeChange[]]\n  | [6, ...ScrollPositionChange[]]\n  | [7, ...AddStyleSheetChange[]]\n  | [8, ...AttachedStyleSheetsChange[]]\n  | [9, ...MediaPlaybackStateChange[]]\n  | [10, ...VisualViewportChange[]]\n/**\n * Browser-specific. Schema representing the addition of a string to the string table.\n */\nexport type AddStringChange = string\n/**\n * Browser-specific. Schema representing the addition of a new node to the document.\n */\nexport type AddNodeChange =\n  | AddCDataSectionNodeChange\n  | AddDocTypeNodeChange\n  | AddDocumentNodeChange\n  | AddDocumentFragmentNodeChange\n  | AddElementNodeChange\n  | AddShadowRootNodeChange\n  | AddTextNodeChange\n/**\n * Schema representing the addition of a new #cdata-section node.\n *\n * @minItems 2\n */\nexport type AddCDataSectionNodeChange = [InsertionPoint, '#cdata-section' | StringReference]\n/**\n * Browser-specific. Schema representing the insertion point of a node which is being added to the document.\n */\nexport type InsertionPoint =\n  | AppendChildInsertionPoint\n  | InsertAfterPreviousInsertionPoint\n  | InsertBeforeInsertionPoint\n  | RootInsertionPoint\n/**\n * A positive integer insertion point. Inserting a node at positive integer N indicates that the new node's parent is the node with an id N lower than the new node, and that we should insert the new node at the end of its parent's child list, as if the DOM method appendChild() was being used.\n */\nexport type AppendChildInsertionPoint = number\n/**\n * A zero insertion point. Inserting a node at zero indicates that the new node should be inserted after the node with an id one lower than the new node, as if the DOM method after() is being used. Using a zero insertion point repeatedly is thus a quick way to insert a sequence of sibling elements.\n */\nexport type InsertAfterPreviousInsertionPoint = 0\n/**\n * A negative integer insertion point. Inserting a node at negative integer -N indicates that the new node's next sibling is the node with an id N lower than the new node, and that we should insert the new node before its next sibling, as if the DOM method insertBefore() was being used.\n */\nexport type InsertBeforeInsertionPoint = number\n/**\n * A null insertion point, indicating that the node should be inserted at the root of the document.\n */\nexport type RootInsertionPoint = null\n/**\n * Browser-specific. Schema representing a string, expressed as an index into the string table.\n */\nexport type StringReference = number\n/**\n * Schema representing the addition of a new #doctype node, using the format [#doctype, name, public ID, system ID].\n *\n * @minItems 5\n */\nexport type AddDocTypeNodeChange = [\n  InsertionPoint,\n  '#doctype' | StringReference,\n  StringOrStringReference,\n  StringOrStringReference,\n  StringOrStringReference,\n]\n/**\n * Browser-specific. Schema representing a string, either expressed as a literal or as an index into the string table.\n */\nexport type StringOrStringReference = string | StringReference\n/**\n * Schema representing the addition of a new #document node.\n *\n * @minItems 2\n */\nexport type AddDocumentNodeChange = [InsertionPoint, '#document' | StringReference]\n/**\n * Schema representing the addition of a new #document-fragment node.\n *\n * @minItems 2\n */\nexport type AddDocumentFragmentNodeChange = [InsertionPoint, '#document-fragment' | StringReference]\n/**\n * Schema representing the addition of a new element node.\n *\n * @minItems 2\n */\nexport type AddElementNodeChange = [InsertionPoint, string | StringReference, ...AttributeAssignment[]]\n/**\n * Schema representing an assignment of a value to an attribute. The format is [name, value].\n *\n * @minItems 2\n */\nexport type AttributeAssignment = [StringOrStringReference, StringOrStringReference]\n/**\n * Schema representing the addition of a new #shadow-root node.\n *\n * @minItems 2\n */\nexport type AddShadowRootNodeChange = [InsertionPoint, '#shadow-root' | StringReference]\n/**\n * Schema representing the addition of a new #text node.\n *\n * @minItems 3\n */\nexport type AddTextNodeChange = [InsertionPoint, '#text' | StringReference, StringOrStringReference]\n/**\n * Browser-specific. Schema representing the removal of a node from the document.\n */\nexport type RemoveNodeChange = number\n/**\n * Browser-specific. Schema representing a change to an node's attributes.\n *\n * @minItems 1\n */\nexport type AttributeChange = [NodeId, ...AttributeAssignmentOrDeletion[]]\n/**\n * Browser-specific. Schema representing the ID of a DOM node.\n */\nexport type NodeId = number\n/**\n * Schema representing a change to an attribute, either by assignment of a new value or by deletion of the attribute.\n */\nexport type AttributeAssignmentOrDeletion = AttributeAssignment | AttributeDeletion\n/**\n * Schema representing the deletion of an attribute.\n *\n * @minItems 1\n */\nexport type AttributeDeletion = [StringOrStringReference]\n/**\n * Browser-specific. Schema representing a change to the text content of a #text node.\n *\n * @minItems 2\n */\nexport type TextChange = [NodeId, StringOrStringReference]\n/**\n * Browser-specific. Schema representing a change in an element's size.\n *\n * @minItems 3\n */\nexport type SizeChange = [NodeId, number, number]\n/**\n * Browser-specific. Schema representing a scroll position change.\n *\n * @minItems 3\n */\nexport type ScrollPositionChange = [NodeId, number, number]\n/**\n * Browser-specific. Schema representing the addition of a new stylesheet to the document.\n */\nexport type AddStyleSheetChange = StyleSheetSnapshot\n/**\n * Schema representing a snapshot of a CSS stylesheet.\n *\n * @minItems 1\n */\nexport type StyleSheetSnapshot =\n  | [StyleSheetRules]\n  | [StyleSheetRules, StyleSheetMediaList]\n  | [StyleSheetRules, StyleSheetMediaList, boolean]\n/**\n * Schema representing a CSS stylesheet's rules, encoded either as a single string or as an array containing a separate string for each rule.\n */\nexport type StyleSheetRules = StringOrStringReference | StringOrStringReference[]\n/**\n * If non-empty, the list of medias for which this stylesheet is active. Defaults to the empty list if not present.\n */\nexport type StyleSheetMediaList = StringOrStringReference[]\n/**\n * Browser-specific. Schema representing a change to the stylesheets attached to a DOM node. For <link> or <style> elements, which use classic CSSOM APIs, at most one stylesheet can be attached. For #document, #document-fragment, or #shadow-root nodes, which use the `adoptedStyleSheets` API, any number of stylesheets can be attached.\n *\n * @minItems 1\n */\nexport type AttachedStyleSheetsChange = [NodeId, ...StyleSheetId[]]\n/**\n * Browser-specific. Schema representing the ID of a stylesheet.\n */\nexport type StyleSheetId = number\n/**\n * Browser-specific. Schema representing a change to the playback state of the media associated with an <audio> or <video> element.\n *\n * @minItems 2\n */\nexport type MediaPlaybackStateChange = [NodeId, PlaybackStatePlaying | PlaybackStatePaused]\n/**\n * A playback state indicating that the associated media is playing.\n */\nexport type PlaybackStatePlaying = 0\n/**\n * A playback state indicating that the associated media is paused.\n */\nexport type PlaybackStatePaused = 1\n/**\n * Browser-specific. Schema representing a change to the visual viewport, defined in terms of the web platform VisualViewport API.\n *\n * @minItems 7\n */\nexport type VisualViewportChange = [\n  VisualViewportOffsetLeft,\n  VisualViewportOffsetTop,\n  VisualViewportPageLeft,\n  VisualViewportPageTop,\n  VisualViewportWidth,\n  VisualViewportHeight,\n  VisualViewportScale,\n]\n/**\n * The offset of the left edge of the visual viewport from the left edge of the layout viewport in CSS pixels.\n */\nexport type VisualViewportOffsetLeft = number\n/**\n * The offset of the top edge of the visual viewport from the top edge of the layout viewport in CSS pixels.\n */\nexport type VisualViewportOffsetTop = number\n/**\n * The x coordinate of the visual viewport relative to the initial containing block origin of the top edge in CSS pixels.\n */\nexport type VisualViewportPageLeft = number\n/**\n * The y coordinate of the visual viewport relative to the initial containing block origin of the top edge in CSS pixels.\n */\nexport type VisualViewportPageTop = number\n/**\n * The width of the visual viewport in CSS pixels.\n */\nexport type VisualViewportWidth = number\n/**\n * The height of the visual viewport in CSS pixels.\n */\nexport type VisualViewportHeight = number\n/**\n * The pinch-zoom scaling factor applied to the visual viewport.\n */\nexport type VisualViewportScale = number\n/**\n * Browser-specific. Schema of a Record type which contains mutations of a screen.\n */\nexport type BrowserIncrementalSnapshotRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 3\n  data: BrowserIncrementalData\n  id?: number\n}\n/**\n * Browser-specific. Schema of a Session Replay IncrementalData type.\n */\nexport type BrowserIncrementalData =\n  | BrowserMutationData\n  | MousemoveData\n  | MouseInteractionData\n  | ScrollData\n  | InputData\n  | MediaInteractionData\n  | StyleSheetRuleData\n  | ViewportResizeData\n  | PointerInteractionData\n/**\n * Browser-specific. Schema of a MutationData.\n */\nexport type BrowserMutationData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 0\n} & BrowserMutationPayload\n/**\n * Browser-specific. Schema of a MutationPayload.\n */\nexport type BrowserMutationPayload = {\n  /**\n   * Contains the newly added nodes.\n   */\n  adds: AddedNodeMutation[]\n  /**\n   * Contains the removed nodes.\n   */\n  removes: RemovedNodeMutation[]\n  /**\n   * Contains the updated attribute mutations.\n   */\n  attributes: AttributeMutation[]\n  /**\n   * Contains the updated text mutations.\n   */\n  texts: TextMutation[]\n}\n/**\n * Browser-specific. Schema of a MouseInteractionData.\n */\nexport type MouseInteractionData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 2\n} & MouseInteraction\n/**\n * Browser-specific. Schema of a MouseInteraction.\n */\nexport type MouseInteraction =\n  | {\n      /**\n       * The type of MouseInteraction: 0=mouseup, 1=mousedown, 2=click, 3=contextmenu, 4=dblclick, 7=touchstart, 9=touchend\n       */\n      readonly type: 0 | 1 | 2 | 3 | 4 | 7 | 9\n      /**\n       * Id for the target node for this MouseInteraction.\n       */\n      id: number\n      /**\n       * X-axis coordinate for this MouseInteraction.\n       */\n      x: number\n      /**\n       * Y-axis coordinate for this MouseInteraction.\n       */\n      y: number\n    }\n  | {\n      /**\n       * The type of MouseInteraction: 5=focus, 6=blur\n       */\n      readonly type: 5 | 6\n      /**\n       * Id for the target node for this MouseInteraction.\n       */\n      id: number\n    }\n/**\n * Browser-specific. Schema of a ScrollData.\n */\nexport type ScrollData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 3\n} & ScrollPosition\n/**\n * Browser-specific. Schema of an InputData.\n */\nexport type InputData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 5\n  /**\n   * Id for the target node for this InputData.\n   */\n  id: number\n} & InputState\n/**\n * Browser-specific. Schema of an InputState.\n */\nexport type InputState =\n  | {\n      /**\n       * Text value for this InputState.\n       */\n      text: string\n    }\n  | {\n      /**\n       * Checked state for this InputState.\n       */\n      isChecked: boolean\n    }\n/**\n * Browser-specific. Schema of a MediaInteractionData.\n */\nexport type MediaInteractionData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 7\n} & MediaInteraction\n/**\n * Browser-specific. Schema of a StyleSheetRuleData.\n */\nexport type StyleSheetRuleData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 8\n} & StyleSheetRule\n/**\n * Schema of a ViewportResizeData.\n */\nexport type ViewportResizeData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 4\n} & ViewportResizeDimension\n/**\n * Schema of a PointerInteractionData.\n */\nexport type PointerInteractionData = {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 9\n} & PointerInteraction\n/**\n * Schema of a Record which contains the screen properties.\n */\nexport type MetaRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 4\n  /**\n   * The data contained by this record.\n   */\n  data: {\n    /**\n     * The width of the screen in pixels, normalized based on the device pixels per inch density (DPI). Example: if a device has a DPI = 2, the normalized width is the current width divided by 2.\n     */\n    width: number\n    /**\n     * The height of the screen in pixels, normalized based on the device pixels per inch density (DPI). Example: if a device has a DPI = 2, the normalized height is the current height divided by 2.\n     */\n    height: number\n    /**\n     * Browser-specific. URL of the view described by this record.\n     */\n    href?: string\n  }\n}\n/**\n * Schema of a Record type which contains focus information.\n */\nexport type FocusRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 6\n  data: {\n    /**\n     * Whether this screen has a focus or not. For now it will always be true for mobile.\n     */\n    readonly has_focus: boolean\n  }\n}\n/**\n * Schema of a Record which signifies that view lifecycle ended.\n */\nexport type ViewEndRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 7\n}\n/**\n * Schema of a Record which signifies that the viewport properties have changed.\n */\nexport type VisualViewportRecord = SlotSupportedCommonRecordSchema & {\n  data: {\n    height: number\n    offsetLeft: number\n    offsetTop: number\n    pageLeft: number\n    pageTop: number\n    scale: number\n    width: number\n  }\n  /**\n   * The type of this Record.\n   */\n  readonly type: 8\n}\n/**\n * Schema of a Record which signifies a collection of frustration signals.\n */\nexport type FrustrationRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 9\n  /**\n   * Schema of a Session Replay FrustrationRecord data structure type.\n   */\n  data: {\n    /**\n     * Collection of frustration signal types.\n     */\n    frustrationTypes: ('rage_click' | 'error_click' | 'dead_click')[]\n    /**\n     * Collection of frustration signal event IDs.\n     */\n    recordIds: number[]\n  }\n}\n/**\n * Browser-specific. Schema of a record type which represents changes using a compact encoding. (Experimental; subject to change.)\n */\nexport type BrowserChangeRecord = SlotSupportedCommonRecordSchema & {\n  /**\n   * The type of this Record.\n   */\n  readonly type: 12\n  data: Change[]\n  id?: number\n}\n\n/**\n * Schema of a Session Replay Segment context.\n */\nexport interface SegmentContext {\n  /**\n   * Application properties\n   */\n  application: {\n    /**\n     * UUID of the application\n     */\n    id: string\n  }\n  /**\n   * Session properties\n   */\n  session: {\n    /**\n     * UUID of the session\n     */\n    id: string\n  }\n  /**\n   * View properties\n   */\n  view: {\n    /**\n     * UUID of the view\n     */\n    id: string\n  }\n}\n/**\n * Schema of common properties for a Segment Metadata type.\n */\nexport interface CommonSegmentMetadataSchema {\n  /**\n   * The start UTC timestamp in milliseconds corresponding to the first record in the Segment data. Each timestamp is computed as the UTC interval since 00:00:00.000 01.01.1970.\n   */\n  start: number\n  /**\n   * The end UTC timestamp in milliseconds corresponding to the last record in the Segment data. Each timestamp is computed as the UTC interval since 00:00:00.000 01.01.1970.\n   */\n  end: number\n  /**\n   * The number of records in this Segment.\n   */\n  records_count: number\n  /**\n   * The index of this Segment in the segments list that was recorded for this view ID. Starts from 0.\n   */\n  index_in_view?: number\n  /**\n   * Whether this Segment contains a full snapshot record or not.\n   */\n  has_full_snapshot?: boolean\n}\n/**\n * Schema of common properties for a Record event type.\n */\nexport interface CommonRecordSchema {\n  /**\n   * Defines the UTC time in milliseconds when this Record was performed.\n   */\n  timestamp: number\n}\n/**\n * Schema of a Node type.\n */\nexport interface BrowserNode {\n  node: SerializedNodeWithId\n  /**\n   * Initial node offset position.\n   */\n  initialOffset: {\n    /**\n     * Top position offset for this node.\n     */\n    top: number\n    /**\n     * Left position offset for this node.\n     */\n    left: number\n  }\n}\n/**\n * Schema of a Document Node.\n */\nexport interface DocumentNode {\n  /**\n   * The type of this Node.\n   */\n  readonly type: 0\n  /**\n   * Stylesheet added dynamically\n   */\n  readonly adoptedStyleSheets?: StyleSheet[]\n  childNodes: SerializedNodeWithId[]\n}\n/**\n * Browser-specific. Schema of a StyleSheet\n */\nexport interface StyleSheet {\n  /**\n   * CSS rules applied (rule.cssText)\n   */\n  cssRules: string[]\n  /**\n   * MediaList of the stylesheet\n   */\n  media?: string[]\n  /**\n   * Is the stylesheet disabled\n   */\n  disabled?: boolean\n}\n/**\n * Schema of a Document FragmentNode.\n */\nexport interface DocumentFragmentNode {\n  /**\n   * The type of this Node.\n   */\n  readonly type: 11\n  /**\n   * Stylesheet added dynamically\n   */\n  readonly adoptedStyleSheets?: StyleSheet[]\n  /**\n   * Is this node a shadow root or not\n   */\n  readonly isShadowRoot: boolean\n  childNodes: SerializedNodeWithId[]\n}\n/**\n * Schema of a Document Type Node.\n */\nexport interface DocumentTypeNode {\n  /**\n   * The type of this Node.\n   */\n  readonly type: 1\n  /**\n   * Name for this DocumentType\n   */\n  name: string\n  /**\n   * PublicId for this DocumentType\n   */\n  publicId: string\n  /**\n   * SystemId for this DocumentType\n   */\n  systemId: string\n}\n/**\n * Schema of an Element Node.\n */\nexport interface ElementNode {\n  /**\n   * The type of this Node.\n   */\n  readonly type: 2\n  /**\n   * TagName for this Node\n   */\n  tagName: string\n  attributes: Attributes\n  childNodes: SerializedNodeWithId[]\n  /**\n   * Is this node a SVG instead of a HTML\n   */\n  isSVG?: true\n}\n/**\n * Schema of an Attributes type.\n */\nexport interface Attributes {\n  [k: string]: string | number | boolean\n}\n/**\n * Schema of a Text Node.\n */\nexport interface TextNode {\n  /**\n   * The type of this Node.\n   */\n  readonly type: 3\n  /**\n   * Text value for this Text Node\n   */\n  textContent: string\n  isStyle?: true\n}\n/**\n * Schema of a CData Node.\n */\nexport interface CDataNode {\n  /**\n   * The type of this Node.\n   */\n  readonly type: 4\n  textContent: ''\n}\n/**\n * Schema of an AddedNodeMutation.\n */\nexport interface AddedNodeMutation {\n  node: SerializedNodeWithId\n  /**\n   * Id for the parent node for this AddedNodeMutation.\n   */\n  parentId: number\n  nextId: number | null\n  previousId?: number | null\n}\n/**\n * Schema of a RemovedNodeMutation.\n */\nexport interface RemovedNodeMutation {\n  /**\n   * Id of the mutated node.\n   */\n  id: number\n  /**\n   * Id for the parent node for this RemovedNodeMutation\n   */\n  parentId: number\n}\n/**\n * Schema of an AttributeMutation.\n */\nexport interface AttributeMutation {\n  /**\n   * Id of the mutated node.\n   */\n  id: number\n  /**\n   * Attributes for this AttributeMutation\n   */\n  attributes: {\n    [k: string]: string | null\n  }\n}\n/**\n * Schema of a TextMutation.\n */\nexport interface TextMutation {\n  /**\n   * Id of the mutated node.\n   */\n  id: number\n  /**\n   * Value for this TextMutation\n   */\n  value: null | string\n}\n/**\n * Browser-specific. Schema of a MousemoveData.\n */\nexport interface MousemoveData {\n  /**\n   * The source of this type of incremental data.\n   */\n  readonly source: 1 | 6\n  /**\n   * Positions reported for this MousemoveData.\n   */\n  positions: MousePosition[]\n}\n/**\n * Browser-specific. Schema of a MousePosition.\n */\nexport interface MousePosition {\n  /**\n   * X-axis coordinate for this MousePosition.\n   */\n  x: number\n  /**\n   * Y-axis coordinate for this MousePosition.\n   */\n  y: number\n  /**\n   * Id for the target node for this MousePosition.\n   */\n  id: number\n  /**\n   * Observed time offset for this MousePosition.\n   */\n  timeOffset: number\n}\n/**\n * Browser-specific. Schema of a ScrollPosition.\n */\nexport interface ScrollPosition {\n  /**\n   * Id for the target node for this ScrollPosition.\n   */\n  id: number\n  /**\n   * X-axis coordinate for this ScrollPosition.\n   */\n  x: number\n  /**\n   * Y-axis coordinate for this ScrollPosition.\n   */\n  y: number\n}\n/**\n * Browser-specific. Schema of a MediaInteraction.\n */\nexport interface MediaInteraction {\n  /**\n   * Id for the target node for this MediaInteraction.\n   */\n  id: number\n  /**\n   * The type of MediaInteraction.\n   */\n  readonly type: 0 | 1\n}\n/**\n * Browser-specific. Schema of a StyleSheetRule.\n */\nexport interface StyleSheetRule {\n  /**\n   * Id of the owner node for this StyleSheetRule.\n   */\n  readonly id: number\n  /**\n   * Rules added to this StyleSheetRule.\n   */\n  adds?: StyleSheetAddRule[]\n  /**\n   * Rules deleted from this StyleSheetRule.\n   */\n  removes?: StyleSheetDeleteRule[]\n}\n/**\n * Browser-specific. Schema of a StyleSheetAddRule.\n */\nexport interface StyleSheetAddRule {\n  /**\n   * Text content for this StyleSheetAddRule.\n   */\n  rule: string\n  /**\n   * Index of this StyleSheetAddRule in its StyleSheet.\n   */\n  index?: number | number[]\n}\n/**\n * Browser-specific. Schema of a StyleSheetDeleteRule.\n */\nexport interface StyleSheetDeleteRule {\n  /**\n   * Index of this StyleSheetDeleteRule in its StyleSheet.\n   */\n  index: number | number[]\n}\n/**\n * Schema of a ViewportResizeDimension.\n */\nexport interface ViewportResizeDimension {\n  /**\n   * The new width of the screen in pixels, normalized based on the device pixels per inch density (DPI). Example: if a device has a DPI = 2, the width is divided by 2 to get a normalized width.\n   */\n  width: number\n  /**\n   * The new height of the screen in pixels, normalized based on the device pixels per inch density (DPI). Example: if a device has a DPI = 2, the height is divided by 2 to get a normalized height.\n   */\n  height: number\n}\n/**\n * Schema of a PointerInteraction.\n */\nexport interface PointerInteraction {\n  /**\n   * Schema of an PointerEventType\n   */\n  readonly pointerEventType: 'down' | 'up' | 'move'\n  /**\n   * Schema of an PointerType\n   */\n  readonly pointerType: 'mouse' | 'touch' | 'pen'\n  /**\n   * Id of the pointer of this PointerInteraction.\n   */\n  pointerId: number\n  /**\n   * X-axis coordinate for this PointerInteraction.\n   */\n  x: number\n  /**\n   * Y-axis coordinate for this PointerInteraction.\n   */\n  y: number\n}\n"
  },
  {
    "path": "packages/rum/src/types/sessionReplayConstants.ts",
    "content": "import type * as SessionReplay from './sessionReplay'\n\nexport const RecordType: {\n  FullSnapshot: SessionReplay.BrowserFullSnapshotRecord['type']\n  IncrementalSnapshot: SessionReplay.BrowserIncrementalSnapshotRecord['type']\n  Meta: SessionReplay.MetaRecord['type']\n  Focus: SessionReplay.FocusRecord['type']\n  ViewEnd: SessionReplay.ViewEndRecord['type']\n  VisualViewport: SessionReplay.VisualViewportRecord['type']\n  FrustrationRecord: SessionReplay.FrustrationRecord['type']\n  Change: SessionReplay.BrowserChangeRecord['type']\n} = {\n  FullSnapshot: 2,\n  IncrementalSnapshot: 3,\n  Meta: 4,\n  Focus: 6,\n  ViewEnd: 7,\n  VisualViewport: 8,\n  FrustrationRecord: 9,\n  Change: 12,\n} as const\n\nexport type RecordType = (typeof RecordType)[keyof typeof RecordType]\n\nexport const NodeType: {\n  Document: SessionReplay.DocumentNode['type']\n  DocumentType: SessionReplay.DocumentTypeNode['type']\n  Element: SessionReplay.ElementNode['type']\n  Text: SessionReplay.TextNode['type']\n  CDATA: SessionReplay.CDataNode['type']\n  DocumentFragment: SessionReplay.DocumentFragmentNode['type']\n} = {\n  Document: 0,\n  DocumentType: 1,\n  Element: 2,\n  Text: 3,\n  CDATA: 4,\n  DocumentFragment: 11,\n} as const\n\nexport type NodeType = (typeof NodeType)[keyof typeof NodeType]\n\n// ChangeTypeId evaluates to Id if [Id, ...Data[]] is a valid variant of Change;\n// otherwise, it triggers a compile-time error.\ntype ChangeTypeId<Id, Data> = [Id, ...Data[]] extends SessionReplay.Change ? Id : never\n\nexport const ChangeType: {\n  AddString: ChangeTypeId<0, SessionReplay.AddStringChange>\n  AddNode: ChangeTypeId<1, SessionReplay.AddNodeChange>\n  RemoveNode: ChangeTypeId<2, SessionReplay.RemoveNodeChange>\n  Attribute: ChangeTypeId<3, SessionReplay.AttributeChange>\n  Text: ChangeTypeId<4, SessionReplay.TextChange>\n  Size: ChangeTypeId<5, SessionReplay.SizeChange>\n  ScrollPosition: ChangeTypeId<6, SessionReplay.ScrollPositionChange>\n  AddStyleSheet: ChangeTypeId<7, SessionReplay.AddStyleSheetChange>\n  AttachedStyleSheets: ChangeTypeId<8, SessionReplay.AttachedStyleSheetsChange>\n  MediaPlaybackState: ChangeTypeId<9, SessionReplay.MediaPlaybackStateChange>\n  VisualViewport: ChangeTypeId<10, SessionReplay.VisualViewportChange>\n} = {\n  AddString: 0,\n  AddNode: 1,\n  RemoveNode: 2,\n  Attribute: 3,\n  Text: 4,\n  Size: 5,\n  ScrollPosition: 6,\n  AddStyleSheet: 7,\n  AttachedStyleSheets: 8,\n  MediaPlaybackState: 9,\n  VisualViewport: 10,\n} as const\n\nexport type ChangeType = (typeof ChangeType)[keyof typeof ChangeType]\n\nexport const PlaybackState: {\n  Playing: SessionReplay.PlaybackStatePlaying\n  Paused: SessionReplay.PlaybackStatePaused\n} = {\n  Playing: 0,\n  Paused: 1,\n} as const\n\nexport type PlaybackState = (typeof PlaybackState)[keyof typeof PlaybackState]\n\nexport const IncrementalSource: {\n  Mutation: SessionReplay.BrowserMutationData['source']\n  MouseMove: Exclude<SessionReplay.MousemoveData['source'], 6>\n  MouseInteraction: SessionReplay.MouseInteractionData['source']\n  Scroll: SessionReplay.ScrollData['source']\n  ViewportResize: SessionReplay.ViewportResizeData['source']\n  Input: SessionReplay.InputData['source']\n  TouchMove: Exclude<SessionReplay.MousemoveData['source'], 1>\n  MediaInteraction: SessionReplay.MediaInteractionData['source']\n  StyleSheetRule: SessionReplay.StyleSheetRuleData['source']\n} = {\n  Mutation: 0,\n  MouseMove: 1,\n  MouseInteraction: 2,\n  Scroll: 3,\n  ViewportResize: 4,\n  Input: 5,\n  TouchMove: 6,\n  MediaInteraction: 7,\n  StyleSheetRule: 8,\n  // CanvasMutation : 9,\n  // Font : 10,\n} as const\n\nexport type IncrementalSource = (typeof IncrementalSource)[keyof typeof IncrementalSource]\n\nexport const MouseInteractionType = {\n  MouseUp: 0,\n  MouseDown: 1,\n  Click: 2,\n  ContextMenu: 3,\n  DblClick: 4,\n  Focus: 5,\n  Blur: 6,\n  TouchStart: 7,\n  TouchEnd: 9,\n} as const\n\nexport type MouseInteractionType = (typeof MouseInteractionType)[keyof typeof MouseInteractionType]\n\nexport const MediaInteractionType = {\n  Play: 0,\n  Pause: 1,\n} as const\n\nexport type MediaInteractionType = (typeof MediaInteractionType)[keyof typeof MediaInteractionType]\n\nexport const SnapshotFormat: {\n  V1: SessionReplay.SnapshotFormatV1\n  Change: SessionReplay.SnapshotFormatChange\n} = {\n  V1: 0,\n  Change: 1,\n} as const\n\nexport type SnapshotFormat = (typeof SnapshotFormat)[keyof typeof SnapshotFormat]\n"
  },
  {
    "path": "packages/rum/test/index.ts",
    "content": "export * from './mockWorker'\nexport * from './record'\nexport * from './rumFrustrationEvent'\nexport * from './mockProfiler'\n"
  },
  {
    "path": "packages/rum/test/mockProfiler.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\nimport { getGlobalObject } from '@datadog/browser-core'\nimport type { Profiler, ProfilerTrace, ProfilerInitOptions } from '../src/domain/profiling/types'\n\nexport function mockProfiler(mockedTrace: ProfilerTrace) {\n  const globalThis = getGlobalObject()\n  // Save original Profiler class to restore it during cleanup.\n  const originalProfiler = (globalThis as any).Profiler\n\n  // Store all instances of the MockProfiler class. May be useful for testing.\n  const instances = new Set<MockProfiler>()\n\n  class MockProfiler implements Omit<Profiler, 'new'> {\n    /** Sample interval in ms. */\n    readonly sampleInterval: number\n    /** True if profiler is stopped. */\n    readonly stopped: boolean\n\n    constructor(options: ProfilerInitOptions) {\n      this.sampleInterval = options.sampleInterval\n      this.stopped = false\n\n      return this\n    }\n\n    stop(): Promise<ProfilerTrace> {\n      return Promise.resolve(mockedTrace)\n    }\n\n    addEventListener(): void {\n      return\n    }\n\n    removeEventListener(): void {\n      return\n    }\n\n    dispatchEvent(): boolean {\n      return true\n    }\n  }\n\n  // Mock the Profiler class\n  ;(globalThis as any).Profiler = MockProfiler\n\n  registerCleanupTask(() => {\n    // Restore the Profiler class.\n    ;(globalThis as any).Profiler = originalProfiler\n    instances.clear()\n  })\n\n  return {\n    instances,\n  }\n}\n"
  },
  {
    "path": "packages/rum/test/mockWorker.ts",
    "content": "import type { DeflateWorker, DeflateWorkerAction } from '@datadog/browser-core'\nimport { string2buf } from '../../worker/src/domain/deflate'\nimport { createNewEvent, MockEventTarget } from '../../core/test'\n\nexport class MockWorker extends MockEventTarget implements DeflateWorker {\n  public onmessage = null\n  public onmessageerror = null\n  public onerror = null\n\n  readonly pendingMessages: DeflateWorkerAction[] = []\n\n  private streams = new Map<number, Uint8Array[]>()\n\n  postMessage(message: DeflateWorkerAction): void {\n    this.pendingMessages.push(message)\n  }\n\n  terminate(): void {\n    // do nothing\n  }\n\n  get pendingData() {\n    return this.pendingMessages.map((message) => ('data' in message ? message.data : '')).join('')\n  }\n\n  get messageListenersCount() {\n    return this.listeners.message.length\n  }\n\n  processAllMessages(): void {\n    while (this.pendingMessages.length) {\n      this.processNextMessage()\n    }\n  }\n\n  dropNextMessage(): void {\n    this.pendingMessages.shift()\n  }\n\n  processNextMessage(): void {\n    const message = this.pendingMessages.shift()\n    if (message) {\n      switch (message.action) {\n        case 'init':\n          this.dispatchEvent(\n            createNewEvent('message', {\n              data: {\n                type: 'initialized',\n                version: 'dev',\n              },\n            })\n          )\n          break\n        case 'write':\n          {\n            let stream = this.streams.get(message.streamId)\n            if (!stream) {\n              stream = []\n              this.streams.set(message.streamId, stream)\n            }\n            // In the mock worker, for simplicity, we'll just use the UTF-8 encoded string instead of deflating it.\n            const binaryData = string2buf(message.data)\n            stream.push(binaryData)\n            this.dispatchEvent(\n              createNewEvent('message', {\n                data: {\n                  type: 'wrote',\n                  id: message.id,\n                  streamId: message.streamId,\n                  result: binaryData,\n                  trailer: new Uint8Array([32]), // emulate a trailer with a single space\n                  additionalBytesCount: binaryData.length,\n                },\n              })\n            )\n          }\n          break\n        case 'reset':\n          this.streams.delete(message.streamId)\n          break\n      }\n    }\n  }\n\n  dispatchErrorEvent() {\n    const error = createNewEvent('error')\n    this.dispatchEvent(error)\n  }\n\n  dispatchErrorMessage(error: Error | string, streamId?: number) {\n    this.dispatchEvent(createNewEvent('message', { data: { type: 'errored', error, streamId } }))\n  }\n}\n"
  },
  {
    "path": "packages/rum/test/record/changes.ts",
    "content": "import type { BrowserChangeRecord, BrowserFullSnapshotChangeRecord, BrowserRecord } from '../../src/types'\nimport { RecordType, SnapshotFormat } from '../../src/types'\nimport { createChangeDecoder } from '../../src/domain/record'\n\nexport function decodeChangeRecords(\n  records: Array<BrowserChangeRecord | BrowserFullSnapshotChangeRecord>\n): Array<BrowserChangeRecord | BrowserFullSnapshotChangeRecord> {\n  const changeDecoder = createChangeDecoder()\n  return records.map((record) => changeDecoder.decode(record))\n}\n\nexport function decodeFullSnapshotChangeRecord(\n  record: BrowserFullSnapshotChangeRecord\n): BrowserFullSnapshotChangeRecord {\n  const changeDecoder = createChangeDecoder()\n  return changeDecoder.decode(record) as BrowserFullSnapshotChangeRecord\n}\n\nexport function findChangeRecords(\n  records: BrowserRecord[]\n): Array<BrowserChangeRecord | BrowserFullSnapshotChangeRecord> {\n  return records.filter(\n    (record) =>\n      record.type === RecordType.Change ||\n      (record.type === RecordType.FullSnapshot && record.format === SnapshotFormat.Change)\n  )\n}\n"
  },
  {
    "path": "packages/rum/test/record/elements.ts",
    "content": "import type {\n  AddElementNodeChange,\n  AddNodeChange,\n  BrowserFullSnapshotChangeRecord,\n  BrowserFullSnapshotRecord,\n  BrowserFullSnapshotV1Record,\n  ScrollPositionChange,\n  SerializedNodeWithId,\n} from '../../src/types'\nimport { ChangeType, NodeType, SnapshotFormat } from '../../src/types'\nimport { decodeFullSnapshotChangeRecord } from './changes'\n\n/**\n * Given a full snapshot, locates elements with HTML id attributes and returns a map from\n * each id attribute value to the corresponding element's node id.\n */\nexport function getElementIdsFromFullSnapshot(record: BrowserFullSnapshotRecord): Map<string, number> {\n  if (record.format === SnapshotFormat.Change) {\n    return getElementIdsFromFullSnapshotChange(record)\n  }\n  return getElementIdsFromFullSnapshotV1(record)\n}\n\nfunction getElementIdsFromFullSnapshotChange(rawRecord: BrowserFullSnapshotChangeRecord): Map<string, number> {\n  const elementIds = new Map<string, number>()\n\n  let nextId = 0\n  for (const change of decodeFullSnapshotChangeRecord(rawRecord).data) {\n    if (change[0] !== ChangeType.AddNode) {\n      continue\n    }\n\n    for (let i = 1; i < change.length; i++) {\n      const id = nextId++\n      const addedNode = change[i] as AddNodeChange\n      const nodeName = addedNode[1]\n\n      switch (nodeName) {\n        case '#cdata-section':\n        case '#doctype':\n        case '#document':\n        case '#document-fragment':\n        case '#shadow-root':\n        case '#text':\n          continue\n\n        default: {\n          const [, , ...attributeAssignments] = addedNode as AddElementNodeChange\n          for (const [name, value] of attributeAssignments) {\n            if (name === 'id') {\n              elementIds.set(String(value), id)\n            }\n          }\n        }\n      }\n    }\n  }\n\n  return elementIds\n}\n\nfunction getElementIdsFromFullSnapshotV1(record: BrowserFullSnapshotV1Record): Map<string, number> {\n  const elementIds = new Map<string, number>()\n\n  const collectIds = (node: SerializedNodeWithId) => {\n    if (node.type === NodeType.Element && node.attributes.id) {\n      elementIds.set(String(node.attributes.id), node.id)\n    }\n\n    if ('childNodes' in node) {\n      for (const child of node.childNodes) {\n        collectIds(child)\n      }\n    }\n  }\n\n  collectIds(record.data.node)\n  return elementIds\n}\n\nexport interface ScrollPosition {\n  left: number\n  top: number\n}\n\n/**\n * Given a full snapshot, locates elements with non-zero scroll positions and returns a\n * map from each node id to the corresponding element's scroll position.\n */\nexport function getScrollPositionsFromFullSnapshot(record: BrowserFullSnapshotRecord): Map<number, ScrollPosition> {\n  if (record.format === SnapshotFormat.Change) {\n    return getScrollPositionsFromFullSnapshotChange(record)\n  }\n  return getScrollPositionsFromFullSnapshotV1(record)\n}\n\nfunction getScrollPositionsFromFullSnapshotChange(\n  record: BrowserFullSnapshotChangeRecord\n): Map<number, ScrollPosition> {\n  const scrollPositions = new Map<number, ScrollPosition>()\n\n  for (const change of record.data) {\n    if (change[0] !== ChangeType.ScrollPosition) {\n      continue\n    }\n\n    for (let i = 1; i < change.length; i++) {\n      const [nodeId, left, top] = change[i] as ScrollPositionChange\n      scrollPositions.set(nodeId, { left, top })\n    }\n  }\n\n  return scrollPositions\n}\n\nfunction getScrollPositionsFromFullSnapshotV1(record: BrowserFullSnapshotV1Record): Map<number, ScrollPosition> {\n  const scrollPositions = new Map<number, ScrollPosition>()\n\n  const collectScrollPositions = (node: SerializedNodeWithId) => {\n    if (node.type === NodeType.Element && (node.attributes.rr_scrollLeft || node.attributes.rr_scrollTop)) {\n      const left = node.attributes.rr_scrollLeft ?? 0\n      const top = node.attributes.rr_scrollTop ?? 0\n      scrollPositions.set(node.id, { left: Number(left), top: Number(top) })\n    }\n\n    if ('childNodes' in node) {\n      for (const child of node.childNodes) {\n        collectScrollPositions(child)\n      }\n    }\n  }\n\n  collectScrollPositions(record.data.node)\n  return scrollPositions\n}\n"
  },
  {
    "path": "packages/rum/test/record/index.ts",
    "content": "export * from './changes'\nexport * from './elements'\nexport * from './recordsPerFullSnapshot'\nexport * from './mutationPayloadValidator'\nexport * from './nodes'\nexport * from './segments'\nexport * from './readReplayPayload'\n"
  },
  {
    "path": "packages/rum/test/record/mutationPayloadValidator.ts",
    "content": "import { getGlobalObject } from '@datadog/browser-core'\nimport { NodeType, IncrementalSource, SnapshotFormat } from '../../src/types'\nimport type {\n  SerializedNodeWithId,\n  ElementNode,\n  TextNode,\n  DocumentFragmentNode,\n  SerializedNode,\n  BrowserMutationPayload,\n  BrowserSegment,\n  BrowserMutationData,\n} from '../../src/types'\nimport { findAllIncrementalSnapshots, findFullSnapshotInFormat } from './segments'\nimport { findTextNode, findElementWithTagName, findElementWithIdAttribute } from './nodes'\n\n// Should match both jasmine and playwright 'expect' functions\ntype Expect = (actual: any) => { toEqual(expected: any): void }\n\ninterface NodeSelector {\n  // Select the first node with the given tag name from the initial full snapshot\n  tag?: string\n  // Select the first node with the given id attribute from the initial full snapshot\n  idAttribute?: string\n  // Select the first node with the given text content from the initial full snapshot\n  text?: string\n}\n\ninterface ExpectedTextMutation {\n  // Reference to the node where the mutation happens\n  node: ExpectedNode\n  // New text value\n  value: string\n}\n\ninterface ExpectedAttributeMutation {\n  // Reference to the node where the mutation happens\n  node: ExpectedNode\n  // Updated attributes\n  attributes: {\n    [key: string]: string | null\n  }\n}\n\ninterface ExpectedRemoveMutation {\n  // Reference to the removed node\n  node: ExpectedNode\n  // Reference to the parent of the removed node\n  parent: ExpectedNode\n}\n\ninterface ExpectedAddMutation {\n  // Partially check for the added node properties.\n  node: ExpectedNode\n  // Reference to the parent of the added node\n  parent: ExpectedNode\n  // Reference to the sibling of the added node\n  next?: ExpectedNode\n}\n\ninterface ExpectedMutationsPayload {\n  texts?: ExpectedTextMutation[]\n  attributes?: ExpectedAttributeMutation[]\n  removes?: ExpectedRemoveMutation[]\n  adds?: ExpectedAddMutation[]\n}\n\n/**\n * ExpectedNode is a helper class to build a serialized Node tree to be used to validate mutations.\n * For now, its purpose is limited to specifying child nodes.\n */\nclass ExpectedNode {\n  constructor(private node: Omit<SerializedNodeWithId, 'childNodes'> & { childNodes?: ExpectedNode[] }) {}\n\n  withChildren(...childNodes: ExpectedNode[]): ExpectedNode {\n    return new ExpectedNode({ ...this.node, childNodes })\n  }\n\n  getId() {\n    return this.node.id\n  }\n\n  toSerializedNodeWithId() {\n    const { childNodes, ...result } = this.node\n    if (childNodes) {\n      ;(result as any).childNodes = childNodes.map((node) => node.toSerializedNodeWithId())\n    }\n    return result as SerializedNodeWithId\n  }\n}\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\n/**\n * Based on an serialized initial document, it returns:\n *\n * * a set of utilities functions to expect nodes by selecting initial nodes from the initial\n * document (expectInitialNode) or creating new nodes (expectNewNode)\n *\n * * a 'validate' function to actually validate a mutation payload against an expected mutation\n * object.\n */\nexport function createMutationPayloadValidator(initialDocument: SerializedNodeWithId) {\n  let maxNodeId = findMaxNodeId(initialDocument)\n\n  /**\n   * Creates a new node based on input parameter, with sensible default properties, and an\n   * automatically computed 'id' attribute based on the previously created nodes.\n   */\n  function expectNewNode(node: Optional<ElementNode, 'childNodes' | 'attributes'>): ExpectedNode\n  function expectNewNode(node: TextNode): ExpectedNode\n  function expectNewNode(node: Partial<DocumentFragmentNode>): ExpectedNode\n  function expectNewNode(node: Partial<SerializedNode>) {\n    maxNodeId += 1\n    if (node.type === NodeType.Element) {\n      node.attributes ||= {}\n      node.childNodes = []\n    }\n    return new ExpectedNode({\n      ...node,\n      id: maxNodeId,\n    } as any)\n  }\n\n  return {\n    /**\n     * Validates the mutation payload against the expected text, attribute, add and remove mutations.\n     */\n    validate: (\n      payload: BrowserMutationPayload,\n      expected: ExpectedMutationsPayload,\n      { expect = getGlobalObject<{ expect: Expect }>().expect }: { expect?: Expect } = {}\n    ) => {\n      payload = removeUndefinedValues(payload)\n\n      expect(payload.adds).toEqual(\n        (expected.adds || []).map(({ node, parent, next }) => ({\n          node: node.toSerializedNodeWithId(),\n          parentId: parent.getId(),\n          nextId: next ? next.getId() : null,\n        }))\n      )\n      expect(payload.texts).toEqual((expected.texts || []).map(({ node, value }) => ({ id: node.getId(), value })))\n      expect(payload.removes).toEqual(\n        (expected.removes || []).map(({ node, parent }) => ({\n          id: node.getId(),\n          parentId: parent.getId(),\n        }))\n      )\n      expect(payload.attributes).toEqual(\n        (expected.attributes || []).map(({ node, attributes }) => ({\n          id: node.getId(),\n          attributes,\n        }))\n      )\n    },\n\n    expectNewNode,\n\n    /**\n     * Selects a node from the initially serialized document. Nodes can be selected via their 'tag'\n     * name, 'id' attribute or 'text' content.\n     */\n    expectInitialNode: (selector: NodeSelector) => {\n      let node\n      if (selector.text) {\n        node = findTextNode(initialDocument, selector.text)\n      } else if (selector.idAttribute) {\n        node = findElementWithIdAttribute(initialDocument, selector.idAttribute)\n      } else if (selector.tag) {\n        node = findElementWithTagName(initialDocument, selector.tag)\n      } else {\n        throw new Error('Empty selector')\n      }\n\n      if (!node) {\n        throw new Error(`Cannot find node from selector ${JSON.stringify(selector)}`)\n      }\n\n      if ('childNodes' in node) {\n        node = { ...node, childNodes: [] }\n      }\n\n      return new ExpectedNode(removeUndefinedValues(node))\n    },\n  }\n\n  function findMaxNodeId(root: SerializedNodeWithId): number {\n    if ('childNodes' in root) {\n      return Math.max(root.id, ...root.childNodes.map((child) => findMaxNodeId(child)))\n    }\n\n    return root.id\n  }\n\n  /**\n   * When serializing a Node, some properties like 'isSVG' may be undefined, and they are not\n   * sent to the intake.\n   *\n   * To be able to validate mutations from E2E and Unit tests, we prefer to keep a single\n   * format. Thus, we serialize and deserialize objects to drop undefined\n   * properties, so they don't interferes during unit tests.\n   */\n  function removeUndefinedValues<T>(object: T) {\n    return JSON.parse(JSON.stringify(object)) as T\n  }\n}\n\n/**\n * Validate the first and only mutation record of a segment against the expected text, attribute,\n * add and remove mutations.\n */\nexport function createMutationPayloadValidatorFromSegment(segment: BrowserSegment, options?: { expect?: Expect }) {\n  const fullSnapshot = findFullSnapshotInFormat(SnapshotFormat.V1, segment)!\n  if (!fullSnapshot) {\n    throw new Error('Full snapshot not found')\n  }\n\n  const mutations = findAllIncrementalSnapshots(segment, IncrementalSource.Mutation) as Array<{\n    data: BrowserMutationData\n  }>\n  if (mutations.length !== 1) {\n    throw new Error(`Expected 1 mutation, found ${mutations.length}`)\n  }\n\n  const mutationPayloadValidator = createMutationPayloadValidator(fullSnapshot.data.node)\n  return {\n    ...mutationPayloadValidator,\n    validate: (expected: ExpectedMutationsPayload) =>\n      mutationPayloadValidator.validate(mutations[0].data, expected, options),\n  }\n}\n"
  },
  {
    "path": "packages/rum/test/record/nodes.ts",
    "content": "// Returns the textContent of a ElementNode, if any.\nimport type { SerializedNodeWithId, ElementNode, SerializedNode, TextNode } from '../../src/types'\nimport { NodeType } from '../../src/types'\n\nexport function findTextContent(elem: ElementNode): string | null {\n  const text = elem.childNodes.find((child) => child.type === NodeType.Text) as TextNode\n  return text ? text.textContent : null\n}\n\n// Returns the first ElementNode with the given ID attribute contained in a node, if any.\nexport function findElementWithIdAttribute(root: SerializedNodeWithId, id: string) {\n  return findElement(root, (node) => node.attributes.id === id)\n}\n\n// Returns the first ElementNode with the given tag name contained in a node, if any.\nexport function findElementWithTagName(root: SerializedNodeWithId, tagName: string) {\n  return findElement(root, (node) => node.tagName === tagName)\n}\n\n// Returns the first TextNode with the given content contained in a node, if any.\nexport function findTextNode(root: SerializedNodeWithId, textContent: string) {\n  return findNode(root, (node) => isTextNode(node) && node.textContent === textContent) as\n    | (TextNode & { id: number })\n    | null\n}\n\n// Returns the first ElementNode matching the predicate\nexport function findElement(root: SerializedNodeWithId, predicate: (node: ElementNode) => boolean) {\n  return findNode(root, (node) => isElementNode(node) && predicate(node)) as (ElementNode & { id: number }) | null\n}\n\n// Returns the first SerializedNodeWithId matching the predicate\nexport function findNode(\n  node: SerializedNodeWithId,\n  predicate: (node: SerializedNodeWithId) => boolean\n): SerializedNodeWithId | null {\n  if (predicate(node)) {\n    return node\n  }\n\n  if ('childNodes' in node) {\n    for (const child of node.childNodes) {\n      const node = findNode(child, predicate)\n      if (node !== null) {\n        return node\n      }\n    }\n  }\n  return null\n}\n\nfunction isElementNode(node: SerializedNode): node is ElementNode {\n  return node.type === NodeType.Element\n}\n\nfunction isTextNode(node: SerializedNode): node is TextNode {\n  return node.type === NodeType.Text\n}\n"
  },
  {
    "path": "packages/rum/test/record/readReplayPayload.ts",
    "content": "import type { Payload } from '@datadog/browser-core'\nimport type { BrowserSegment } from '../../src/types'\nimport type { BrowserSegmentMetadataAndSegmentSizes } from '../../src/domain/segmentCollection'\nimport { readFormData } from '../../../core/test'\n\nexport function readReplayPayload(payload: Payload) {\n  return readFormData<{\n    segment: BrowserSegment\n    event: BrowserSegmentMetadataAndSegmentSizes\n  }>(payload.data as FormData)\n}\n\nexport async function readMetadataFromReplayPayload(payload: Payload) {\n  return (await readReplayPayload(payload)).event\n}\n"
  },
  {
    "path": "packages/rum/test/record/recordsPerFullSnapshot.ts",
    "content": "/**\n * Simplify asserting record lengths across multiple devices when not all record types are supported\n */\nexport const recordsPerFullSnapshot = () =>\n  // Meta, Focus, FullSnapshot, VisualViewport (support limited)\n  window.visualViewport ? 4 : 3\n"
  },
  {
    "path": "packages/rum/test/record/segments.ts",
    "content": "// Returns the first MetaRecord in a Segment, if any.\nimport type {\n  BrowserSegment,\n  MetaRecord,\n  BrowserRecord,\n  BrowserFullSnapshotRecord,\n  MouseInteractionType,\n  BrowserIncrementalSnapshotRecord,\n  VisualViewportRecord,\n  FrustrationRecord,\n  SnapshotFormatV1,\n  BrowserFullSnapshotV1Record,\n  BrowserFullSnapshotChangeRecord,\n  SnapshotFormatChange,\n} from '../../src/types'\nimport { IncrementalSource, RecordType, SnapshotFormat } from '../../src/types'\n\nexport function findMeta(segment: BrowserSegment): MetaRecord | null {\n  return segment.records.find((record) => record.type === RecordType.Meta) as MetaRecord\n}\n\n// Returns the first FullSnapshotRecord in a Segment, if any.\nexport function findFullSnapshot({ records }: { records: BrowserRecord[] }): BrowserFullSnapshotRecord | null {\n  return records.find((record) => record.type === RecordType.FullSnapshot) as BrowserFullSnapshotRecord\n}\n\n/** Returns the FullSnapshotRecord in the given format in a Segment, if any. */\nexport function findFullSnapshotInFormat(\n  format: SnapshotFormatV1,\n  { records }: { records: BrowserRecord[] }\n): BrowserFullSnapshotV1Record | null\nexport function findFullSnapshotInFormat(\n  format: SnapshotFormatChange,\n  { records }: { records: BrowserRecord[] }\n): BrowserFullSnapshotChangeRecord | null\nexport function findFullSnapshotInFormat(\n  format: SnapshotFormat,\n  { records }: { records: BrowserRecord[] }\n): BrowserFullSnapshotRecord | null {\n  return records.find(\n    (record) => record.type === RecordType.FullSnapshot && (record.format ?? SnapshotFormat.V1) === format\n  ) as BrowserFullSnapshotRecord\n}\n\n// Returns all the VisualViewportRecords in a Segment, if any.\nexport function findAllVisualViewports(segment: BrowserSegment): VisualViewportRecord[] {\n  return segment.records.filter((record) => record.type === RecordType.VisualViewport)\n}\n\n// Returns the first IncrementalSnapshotRecord of a given source in a Segment, if any.\nexport function findIncrementalSnapshot(\n  segment: BrowserSegment,\n  source: IncrementalSource\n): BrowserIncrementalSnapshotRecord | null {\n  return segment.records.find(\n    (record) => record.type === RecordType.IncrementalSnapshot && record.data.source === source\n  ) as BrowserIncrementalSnapshotRecord\n}\n\n// Returns all the IncrementalSnapshotRecord of a given source in a Segment, if any.\nexport function findAllIncrementalSnapshots(\n  { records }: { records: BrowserRecord[] },\n  source: IncrementalSource\n): BrowserIncrementalSnapshotRecord[] {\n  return records.filter(\n    (record) => record.type === RecordType.IncrementalSnapshot && record.data.source === source\n  ) as BrowserIncrementalSnapshotRecord[]\n}\n\n// Returns all the FrustrationRecords in the given Segment, if any.\nexport function findAllFrustrationRecords(segment: BrowserSegment): FrustrationRecord[] {\n  return segment.records.filter((record) => record.type === RecordType.FrustrationRecord)\n}\n\n// Returns all the IncrementalSnapshotRecords of the given MouseInteraction source, if any\nexport function findMouseInteractionRecords(\n  segment: BrowserSegment,\n  source: MouseInteractionType\n): BrowserIncrementalSnapshotRecord[] {\n  return findAllIncrementalSnapshots(segment, IncrementalSource.MouseInteraction).filter(\n    (record) => 'type' in record.data && record.data.type === source\n  )\n}\n"
  },
  {
    "path": "packages/rum/test/record/toto.css",
    "content": "/* avoid warning in unit test */\n"
  },
  {
    "path": "packages/rum/test/rumFrustrationEvent.ts",
    "content": "import { clocksNow, timeStampNow } from '@datadog/browser-core'\nimport type { RawRumActionEvent, RawRumEventCollectedData } from '@datadog/browser-rum-core'\nimport { ActionType, FrustrationType, RumEventType } from '@datadog/browser-rum-core'\n\nexport function createRumFrustrationEvent(mouseEvent: MouseEvent): RawRumEventCollectedData<RawRumActionEvent> {\n  return {\n    startClocks: clocksNow(),\n    rawRumEvent: {\n      date: timeStampNow(),\n      type: RumEventType.ACTION,\n      action: {\n        id: '123e4567-e89b-12d3-a456-426614174000',\n        type: ActionType.CLICK,\n        frustration: {\n          type: [FrustrationType.DEAD_CLICK],\n        },\n        target: {\n          name: '123e4567-e89b-12d3-a456-426614174000',\n        },\n      },\n    },\n    domainContext: { events: [mouseEvent] },\n  }\n}\n"
  },
  {
    "path": "packages/rum/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/entries/main.ts\"]\n}\n"
  },
  {
    "path": "packages/rum-angular/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-angular/README.md",
    "content": "# RUM Browser Monitoring - Angular integration\n\n> **Note**: This integration is in beta. Features and configuration may change.\n\n## Overview\n\nWith the Datadog RUM Angular integration, resolve performance issues quickly in Angular applications by:\n\n- Debugging the root cause of performance bottlenecks, such as a slow server response time, render-blocking resource, or an error inside a component\n- Automatically correlating web performance data with user journeys, HTTP calls, and logs\n- Alerting your engineering teams when crucial web performance metrics (such as Core Web Vitals) fall below a threshold that results in a poor user experience\n\nMonitor your Angular applications from end-to-end by:\n\n- Tracking and visualizing user journeys across your entire stack\n- Debugging the root cause of slow load times, which may be an issue with your Angular code, network performance, or underlying infrastructure\n- Analyzing and contextualizing every user session with attributes such as user ID, email, name, and more\n- Unifying full-stack monitoring in one platform for frontend and backend development teams\n\n## Setup\n\nStart by setting up [Datadog RUM][1] in your Angular application. If you're creating a new RUM application in the Datadog App, select Angular as the application type. If you already have an existing RUM application, you can update its type to Angular instead. Once configured, the Datadog App will provide instructions for integrating the [RUM-Angular plugin][2] with the Browser SDK. If Angular is not available as an option, follow the steps below to integrate the plugin manually.\n\n## Usage\n\n### 1. Initialize the Datadog RUM SDK with the Angular plugin\n\n```typescript\nimport { datadogRum } from '@datadog/browser-rum'\nimport { angularPlugin } from '@datadog/browser-rum-angular'\n\ndatadogRum.init({\n  applicationId: '<APP_ID>',\n  clientToken: '<CLIENT_TOKEN>',\n  site: 'datadoghq.com',\n  plugins: [angularPlugin()],\n})\n```\n\n## Error Tracking\n\nTo track errors that occur inside Angular components, you can either use the built-in provider or report errors manually from your own error handler.\n\n### `provideDatadogErrorHandler` usage\n\n`provideDatadogErrorHandler()` replaces Angular's default `ErrorHandler` with one that reports errors to Datadog RUM. It preserves the default `console.error` behavior.\n\n**Standalone setup:**\n\n```typescript\nimport { bootstrapApplication } from '@angular/platform-browser'\nimport { angularPlugin, provideDatadogErrorHandler } from '@datadog/browser-rum-angular'\nimport { datadogRum } from '@datadog/browser-rum'\n\ndatadogRum.init({\n  ...\n  plugins: [angularPlugin()],\n})\n\nbootstrapApplication(AppComponent, {\n  providers: [provideDatadogErrorHandler()],\n})\n```\n\n**NgModule setup:**\n\n```typescript\nimport { angularPlugin, provideDatadogErrorHandler } from '@datadog/browser-rum-angular'\nimport { datadogRum } from '@datadog/browser-rum'\n\ndatadogRum.init({\n  ...\n  plugins: [angularPlugin()],\n})\n\n@NgModule({\n  providers: [provideDatadogErrorHandler()],\n})\nexport class AppModule {}\n```\n\n### Reporting Angular errors from your own `ErrorHandler`\n\nIf you already have a custom `ErrorHandler`, use `addAngularError` to report errors to Datadog without replacing your handler:\n\n```typescript\nimport { ErrorHandler } from '@angular/core'\nimport { addAngularError } from '@datadog/browser-rum-angular'\n\nclass MyCustomErrorHandler implements ErrorHandler {\n  handleError(error: unknown): void {\n    addAngularError(error)\n    // ... custom logic (show toast, log to service, etc.)\n  }\n}\n```\n\n## Angular Router Integration\n\nTo track route changes with Angular's built-in router, initialize the `angularPlugin` with the `router: true` option and add `provideDatadogRouter()` to your providers.\n\n**Standalone setup:**\n\n```typescript\nimport { bootstrapApplication } from '@angular/platform-browser'\nimport { provideRouter } from '@angular/router'\nimport { angularPlugin, provideDatadogRouter } from '@datadog/browser-rum-angular'\nimport { datadogRum } from '@datadog/browser-rum'\n\ndatadogRum.init({\n  ...\n  plugins: [angularPlugin({ router: true })],\n})\n\nbootstrapApplication(AppComponent, {\n  providers: [provideRouter(routes), provideDatadogRouter()],\n})\n```\n\n**NgModule setup:**\n\n```typescript\nimport { angularPlugin, provideDatadogRouter } from '@datadog/browser-rum-angular'\nimport { datadogRum } from '@datadog/browser-rum'\n\ndatadogRum.init({\n  ...\n  plugins: [angularPlugin({ router: true })],\n})\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  providers: [provideDatadogRouter()],\n})\nexport class AppModule {}\n```\n\nWhen enabled, the integration uses route patterns as view names instead of resolved URLs. For example, navigating to `/article/2` generates a view named `/article/:articleId` instead.\n\n## Go Further with Datadog Angular Integration\n\n### Traces\n\nConnect your RUM and trace data to get a complete view of your application's performance. See [Connect RUM and Traces][3].\n\n### Logs\n\nTo start forwarding your Angular application's logs to Datadog, see [JavaScript Log Collection][4].\n\n### Metrics\n\nTo generate custom metrics from your RUM application, see [Generate Metrics][5].\n\n## Troubleshooting\n\nNeed help? Contact [Datadog Support][6].\n\n[1]: https://docs.datadoghq.com/real_user_monitoring/browser/setup/client\n[2]: https://www.npmjs.com/package/@datadog/browser-rum-angular\n[3]: https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum\n[4]: https://docs.datadoghq.com/logs/log_collection/javascript/\n[5]: https://docs.datadoghq.com/real_user_monitoring/generate_metrics\n[6]: https://docs.datadoghq.com/help/\n"
  },
  {
    "path": "packages/rum-angular/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-angular\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"npm run build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"@angular/core\": \">=15 <=21\",\n    \"@angular/router\": \">=15 <=21\",\n    \"rxjs\": \">=7\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-angular\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"devDependencies\": {\n    \"@angular/common\": \"21.2.8\",\n    \"@angular/compiler\": \"21.2.8\",\n    \"@angular/core\": \"21.2.8\",\n    \"@angular/platform-browser\": \"21.2.8\",\n    \"@angular/router\": \"21.2.8\",\n    \"rxjs\": \"7.8.2\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-angular/src/domain/angularPlugin.spec.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../core/test'\nimport { angularPlugin, onRumInit, onRumStart, resetAngularPlugin } from './angularPlugin'\n\nconst PUBLIC_API = {} as RumPublicApi\nconst INIT_CONFIGURATION = {} as RumInitConfiguration\n\ndescribe('angularPlugin', () => {\n  beforeEach(() => {\n    registerCleanupTask(() => {\n      resetAngularPlugin()\n    })\n  })\n\n  it('returns a plugin object', () => {\n    const plugin = angularPlugin()\n    expect(plugin).toEqual(\n      jasmine.objectContaining({\n        name: 'angular',\n        onInit: jasmine.any(Function),\n        onRumStart: jasmine.any(Function),\n      })\n    )\n  })\n\n  it('calls callbacks registered with onRumInit during onInit', () => {\n    const callbackSpy = jasmine.createSpy()\n    const pluginConfiguration = {}\n    onRumInit(callbackSpy)\n\n    expect(callbackSpy).not.toHaveBeenCalled()\n\n    angularPlugin(pluginConfiguration).onInit!({\n      publicApi: PUBLIC_API,\n      initConfiguration: INIT_CONFIGURATION,\n    })\n\n    expect(callbackSpy).toHaveBeenCalledTimes(1)\n    expect(callbackSpy.calls.mostRecent().args[0]).toBe(pluginConfiguration)\n    expect(callbackSpy.calls.mostRecent().args[1]).toBe(PUBLIC_API)\n  })\n\n  it('calls callbacks immediately if onInit was already invoked', () => {\n    const callbackSpy = jasmine.createSpy()\n    const pluginConfiguration = {}\n    angularPlugin(pluginConfiguration).onInit!({\n      publicApi: PUBLIC_API,\n      initConfiguration: INIT_CONFIGURATION,\n    })\n\n    onRumInit(callbackSpy)\n\n    expect(callbackSpy).toHaveBeenCalledTimes(1)\n    expect(callbackSpy.calls.mostRecent().args[0]).toBe(pluginConfiguration)\n    expect(callbackSpy.calls.mostRecent().args[1]).toBe(PUBLIC_API)\n  })\n\n  it('enforce manual view tracking when router is enabled', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    angularPlugin({ router: true }).onInit!({ publicApi: PUBLIC_API, initConfiguration })\n\n    expect(initConfiguration.trackViewsManually).toBe(true)\n  })\n\n  it('does not enforce manual view tracking when router is disabled', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    angularPlugin({ router: false }).onInit!({ publicApi: PUBLIC_API, initConfiguration })\n\n    expect(initConfiguration.trackViewsManually).toBeUndefined()\n  })\n\n  it('returns the configuration telemetry', () => {\n    const pluginConfiguration = { router: true }\n    const plugin = angularPlugin(pluginConfiguration)\n\n    expect(plugin.getConfigurationTelemetry!()).toEqual({ router: true })\n  })\n\n  it('calls onRumStart subscribers during onRumStart', () => {\n    const callbackSpy = jasmine.createSpy()\n    const addErrorSpy = jasmine.createSpy()\n    onRumStart(callbackSpy)\n\n    angularPlugin().onRumStart!({ addError: addErrorSpy })\n\n    expect(callbackSpy).toHaveBeenCalledWith(addErrorSpy)\n  })\n\n  it('calls onRumStart subscribers immediately if already started', () => {\n    const addErrorSpy = jasmine.createSpy()\n    angularPlugin().onRumStart!({ addError: addErrorSpy })\n\n    const callbackSpy = jasmine.createSpy()\n    onRumStart(callbackSpy)\n\n    expect(callbackSpy).toHaveBeenCalledWith(addErrorSpy)\n  })\n})\n"
  },
  {
    "path": "packages/rum-angular/src/domain/angularPlugin.ts",
    "content": "import type { RumPlugin, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\n\ntype InitSubscriber = (configuration: AngularPluginConfiguration, rumPublicApi: RumPublicApi) => void\ntype StartSubscriber = (addError: StartRumResult['addError']) => void\n\nlet globalPublicApi: RumPublicApi | undefined\nlet globalConfiguration: AngularPluginConfiguration | undefined\nlet globalAddError: StartRumResult['addError'] | undefined\n\nconst onRumInitSubscribers: InitSubscriber[] = []\nconst onRumStartSubscribers: StartSubscriber[] = []\n\n/**\n * Angular plugin configuration.\n *\n * @category Main\n */\nexport interface AngularPluginConfiguration {\n  /**\n   * Enable Angular Router integration. Make sure to use `provideDatadogRouter()` in your\n   * application providers.\n   */\n  router?: boolean\n}\n\n/**\n * Angular plugin constructor.\n *\n * @category Main\n * @example\n * ```ts\n * import { datadogRum } from '@datadog/browser-rum'\n * import { angularPlugin } from '@datadog/browser-rum-angular'\n *\n * datadogRum.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   site: '<DATADOG_SITE>',\n *   plugins: [angularPlugin({ router: true })],\n *   // ...\n * })\n * ```\n */\nexport function angularPlugin(configuration: AngularPluginConfiguration = {}): RumPlugin {\n  return {\n    name: 'angular',\n    onInit({ publicApi, initConfiguration }) {\n      globalPublicApi = publicApi\n      globalConfiguration = configuration\n      for (const subscriber of onRumInitSubscribers) {\n        subscriber(globalConfiguration, globalPublicApi)\n      }\n      if (configuration.router) {\n        initConfiguration.trackViewsManually = true\n      }\n    },\n    onRumStart({ addError }) {\n      globalAddError = addError\n      if (addError) {\n        for (const subscriber of onRumStartSubscribers) {\n          subscriber(addError)\n        }\n      }\n    },\n    getConfigurationTelemetry() {\n      return { router: !!configuration.router }\n    },\n  } satisfies RumPlugin\n}\n\nexport function onRumInit(callback: InitSubscriber) {\n  if (globalConfiguration && globalPublicApi) {\n    callback(globalConfiguration, globalPublicApi)\n  } else {\n    onRumInitSubscribers.push(callback)\n  }\n}\n\nexport function onRumStart(callback: StartSubscriber) {\n  if (globalAddError) {\n    callback(globalAddError)\n  } else {\n    onRumStartSubscribers.push(callback)\n  }\n}\n\nexport function resetAngularPlugin() {\n  globalPublicApi = undefined\n  globalConfiguration = undefined\n  globalAddError = undefined\n  onRumInitSubscribers.length = 0\n  onRumStartSubscribers.length = 0\n}\n"
  },
  {
    "path": "packages/rum-angular/src/domain/angularRouter/provideDatadogRouter.ts",
    "content": "import type { EnvironmentProviders } from '@angular/core'\nimport { ENVIRONMENT_INITIALIZER, inject, makeEnvironmentProviders } from '@angular/core'\nimport { GuardsCheckEnd, Router } from '@angular/router'\nimport { filter } from 'rxjs'\nimport { startAngularView } from './startAngularView'\n\n/**\n * Angular provider that subscribes to Router events and starts a new RUM view\n * on each GuardsCheckEnd, using the matched route template as the view name.\n *\n * GuardsCheckEnd fires after guards pass but before resolvers run, so data\n * fetches from resolvers are correctly attributed to the new view.\n *\n * @category Main\n * @example\n * ```ts\n * import { bootstrapApplication } from '@angular/platform-browser'\n * import { provideRouter } from '@angular/router'\n * import { provideDatadogRouter } from '@datadog/browser-rum-angular'\n *\n * bootstrapApplication(AppComponent, {\n *   providers: [\n *     provideRouter(routes),\n *     provideDatadogRouter(),\n *   ],\n * })\n * ```\n */\nexport function provideDatadogRouter(): EnvironmentProviders {\n  return makeEnvironmentProviders([\n    {\n      // Needed for Angular v15 support (provideEnvironmentInitializer requires v16+)\n      provide: ENVIRONMENT_INITIALIZER,\n      multi: true,\n      useFactory: () => {\n        const router = inject(Router)\n\n        return () => {\n          let currentPath: string | undefined\n\n          // No unsubscribe needed as its for the full app lifecycle and because DestroyRef requires v16+\n          router.events\n            .pipe(filter((event): event is GuardsCheckEnd => event instanceof GuardsCheckEnd))\n            .subscribe((event) => {\n              if (!event.shouldActivate) {\n                return\n              }\n\n              const url = event.urlAfterRedirects\n              const path = url.replace(/[?#].*$/, '')\n\n              if (path === currentPath) {\n                return\n              }\n              currentPath = path\n\n              const root = event.state.root\n              startAngularView(root, url)\n            })\n        }\n      },\n    },\n  ])\n}\n"
  },
  {
    "path": "packages/rum-angular/src/domain/angularRouter/startAngularView.spec.ts",
    "content": "import { computeViewName } from './startAngularView'\nimport type { RouteSnapshot } from './types'\n\nfunction createSnapshot(\n  path: string | undefined,\n  children: RouteSnapshot[] = [],\n  outlet: string = 'primary',\n  url: Array<{ path: string }> = []\n): RouteSnapshot {\n  return {\n    routeConfig: path !== undefined ? { path } : null,\n    children,\n    outlet,\n    url,\n  }\n}\n\n/**\n * Build a RouteSnapshot tree from a compact route string and an actual path.\n *\n * Route string format mirrors the React Router test convention:\n * 'foo > bar > :id' represents nested routes { path: 'foo', children: [{ path: 'bar', children: [{ path: ':id' }] }] }\n *\n * The actualPath is used to compute the URL segments matched by '**' wildcards,\n * since Angular stores the matched segments on the wildcard node's `url` property.\n */\nfunction buildSnapshot(routePaths: string, actualPath: string): RouteSnapshot {\n  const paths = routePaths.split(' > ')\n\n  // Compute prefix consumed before the wildcard to derive matched URL segments\n  const wildcardIndex = paths.indexOf('**')\n  let wildcardUrl: Array<{ path: string }> = []\n  if (wildcardIndex !== -1) {\n    const prefixSegments = paths.slice(0, wildcardIndex).filter((p) => p !== '')\n    let remaining = actualPath.startsWith('/') ? actualPath.slice(1) : actualPath\n    for (const prefix of prefixSegments) {\n      if (remaining.startsWith(prefix)) {\n        remaining = remaining.slice(prefix.length)\n        if (remaining.startsWith('/')) {\n          remaining = remaining.slice(1)\n        }\n      }\n    }\n    wildcardUrl = remaining ? remaining.split('/').map((s) => ({ path: s })) : []\n  }\n\n  // Build snapshot chain from right to left\n  let current: RouteSnapshot | undefined\n  for (let i = paths.length - 1; i >= 0; i--) {\n    const path = paths[i]\n    const url = path === '**' ? wildcardUrl : []\n    current = createSnapshot(path, current ? [current] : [], 'primary', url)\n  }\n\n  // Wrap in root node (null routeConfig), matching Angular's ActivatedRouteSnapshot tree\n  return createSnapshot(undefined, current ? [current] : [])\n}\n\ndescribe('computeViewName', () => {\n  it('returns / when root has no children', () => {\n    expect(computeViewName(createSnapshot(undefined))).toBe('/')\n  })\n\n  it('follows primary outlet only, ignoring named outlets', () => {\n    const primaryChild = createSnapshot('users', [], 'primary')\n    const namedChild = createSnapshot('sidebar', [], 'sidebar')\n    const root = createSnapshot(undefined, [namedChild, primaryChild])\n    expect(computeViewName(root)).toBe('/users')\n  })\n\n  // prettier-ignore\n  const cases = [\n    // route paths,                  actual path,        expected view name\n\n    // Simple paths\n    ['',                             '/',                '/'],\n    ['users',                        '/users',           '/users'],\n    ['users > :id',                  '/users/42',        '/users/:id'],\n    ['users > :id > posts > :postId','/users/1/posts/2', '/users/:id/posts/:postId'],\n    ['users/list',                   '/users/list',      '/users/list'],\n\n    // Empty-path wrappers (layout routes)\n    [' > users > :id',              '/users/42',         '/users/:id'],\n    [' >  > users',                 '/users',            '/users'],\n\n    // Lazy-loaded routes (same shape post-resolution)\n    ['admin > settings',            '/admin/settings',   '/admin/settings'],\n\n    // Wildcards\n    ['**',                          '/foo/bar',          '/foo/bar'],\n    ['**',                          '/',                 '/'],\n    ['admin > **',                  '/admin/foo',        '/admin/foo'],\n  ] as const\n\n  cases.forEach(([routePaths, path, expectedViewName]) => {\n    it(`returns \"${expectedViewName}\" for path \"${path}\" with routes \"${routePaths}\"`, () => {\n      const root = buildSnapshot(routePaths, path)\n      expect(computeViewName(root)).toBe(expectedViewName)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-angular/src/domain/angularRouter/startAngularView.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport { onRumInit } from '../angularPlugin'\nimport type { RouteSnapshot } from './types'\n\nconst PRIMARY_OUTLET = 'primary'\n\nexport function startAngularView(root: RouteSnapshot, url: string) {\n  onRumInit((configuration, rumPublicApi) => {\n    if (!configuration.router) {\n      display.warn('`router: true` is missing from the react plugin configuration, the view will not be tracked.')\n      return\n    }\n\n    const viewName = computeViewName(root)\n\n    rumPublicApi.startView({ name: viewName, url })\n  })\n}\n\nexport function computeViewName(root: RouteSnapshot): string {\n  const segments: string[] = []\n  let current: RouteSnapshot | undefined = root\n\n  while (current) {\n    const path = current.routeConfig?.path\n\n    if (path === '**') {\n      for (const segment of current.url) {\n        segments.push(segment.path)\n      }\n      break\n    }\n\n    if (path) {\n      segments.push(path)\n    }\n\n    // Follow primary outlet only — named outlets (e.g. sidebar) are excluded\n    current = current.children.find((child) => child.outlet === PRIMARY_OUTLET)\n  }\n\n  return `/${segments.join('/')}`\n}\n"
  },
  {
    "path": "packages/rum-angular/src/domain/angularRouter/types.ts",
    "content": "/**\n * Minimal interface matching the shape of Angular's ActivatedRouteSnapshot\n * that we need for view name computation. Avoids importing @angular/router at runtime.\n */\nexport interface RouteSnapshot {\n  routeConfig: { path?: string } | null\n  children: RouteSnapshot[]\n  outlet: string\n  url: Array<{ path: string }>\n}\n"
  },
  {
    "path": "packages/rum-angular/src/domain/error/addAngularError.spec.ts",
    "content": "import { initializeAngularPlugin } from '../../../test/initializeAngularPlugin'\nimport { addAngularError } from './addAngularError'\n\ndescribe('addAngularError', () => {\n  it('delegates the error to addError', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeAngularPlugin({\n      addError: addErrorSpy,\n    })\n    const originalError = new Error('error message')\n\n    addAngularError(originalError)\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith({\n      error: originalError,\n      handlingStack: jasmine.any(String),\n      startClocks: jasmine.any(Object),\n      context: {\n        framework: 'angular',\n      },\n    })\n  })\n\n  it('should merge dd_context from the original error with angular error context', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeAngularPlugin({\n      addError: addErrorSpy,\n    })\n    const originalError = new Error('error message')\n    ;(originalError as any).dd_context = { component: 'UserList', param: 42 }\n\n    addAngularError(originalError)\n\n    expect(addErrorSpy).toHaveBeenCalledWith(\n      jasmine.objectContaining({\n        error: originalError,\n        context: {\n          framework: 'angular',\n          component: 'UserList',\n          param: 42,\n        },\n      })\n    )\n  })\n\n  it('handles non-Error values', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeAngularPlugin({\n      addError: addErrorSpy,\n    })\n\n    addAngularError('string error')\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith(\n      jasmine.objectContaining({\n        error: 'string error',\n        handlingStack: jasmine.any(String),\n        startClocks: jasmine.any(Object),\n        context: { framework: 'angular' },\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-angular/src/domain/error/addAngularError.ts",
    "content": "import type { Context } from '@datadog/browser-core'\nimport { callMonitored, clocksNow, createHandlingStack } from '@datadog/browser-core'\nimport { onRumStart } from '../angularPlugin'\n\n/**\n * Add an Angular error to the RUM session.\n *\n * This function is used internally by `provideDatadogErrorHandler()`, but can also be called\n * directly to report errors caught by custom error handling logic.\n *\n * @category Error\n * @example\n * ```ts\n * import { addAngularError } from '@datadog/browser-rum-angular'\n *\n * // In a custom ErrorHandler\n * handleError(error: any) {\n *   addAngularError(error)\n *   // your own error handling...\n * }\n * ```\n */\nexport function addAngularError(error: unknown) {\n  const handlingStack = createHandlingStack('angular error')\n  const startClocks = clocksNow()\n  onRumStart((addError) => {\n    callMonitored(() => {\n      addError({\n        error,\n        handlingStack,\n        startClocks,\n        context: {\n          ...(typeof error === 'object' && error !== null ? (error as { dd_context?: Context }).dd_context : undefined),\n          framework: 'angular',\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum-angular/src/domain/error/index.ts",
    "content": "export { addAngularError } from './addAngularError'\nexport { provideDatadogErrorHandler } from './provideDatadogErrorHandler'\n"
  },
  {
    "path": "packages/rum-angular/src/domain/error/provideDatadogErrorHandler.spec.ts",
    "content": "import type { EnvironmentInjector } from '@angular/core'\nimport { ErrorHandler, Injector, createEnvironmentInjector } from '@angular/core'\nimport { initializeAngularPlugin } from '../../../test/initializeAngularPlugin'\nimport { provideDatadogErrorHandler } from './provideDatadogErrorHandler'\n\nfunction createErrorHandler(): ErrorHandler {\n  const injector = createEnvironmentInjector([provideDatadogErrorHandler()], Injector.NULL as EnvironmentInjector)\n  return injector.get(ErrorHandler)\n}\n\ndescribe('provideDatadogErrorHandler', () => {\n  it('provides an ErrorHandler that reports errors to Datadog', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeAngularPlugin({ addError: addErrorSpy })\n\n    spyOn(console, 'error') // Mute console.errors\n    const handler = createErrorHandler()\n    handler.handleError(new Error('test error'))\n\n    expect(addErrorSpy).toHaveBeenCalled()\n  })\n\n  it('still logs the error to the console via default ErrorHandler', () => {\n    initializeAngularPlugin()\n\n    const consoleErrorSpy = spyOn(console, 'error')\n    const handler = createErrorHandler()\n    handler.handleError(new Error('test error'))\n\n    expect(consoleErrorSpy).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum-angular/src/domain/error/provideDatadogErrorHandler.ts",
    "content": "import type { EnvironmentProviders } from '@angular/core'\nimport { ErrorHandler, makeEnvironmentProviders } from '@angular/core'\nimport { addAngularError } from './addAngularError'\n\n// eslint-disable-next-line no-restricted-syntax\nclass DatadogErrorHandler extends ErrorHandler {\n  override handleError(error: unknown): void {\n    addAngularError(error)\n    super.handleError(error)\n  }\n}\n\n/**\n * Provides a Datadog-instrumented Angular ErrorHandler that reports errors to RUM.\n *\n * @category Error\n * @example\n * ```ts\n * import { provideDatadogErrorHandler } from '@datadog/browser-rum-angular'\n *\n * bootstrapApplication(AppComponent, {\n *   providers: [provideDatadogErrorHandler()],\n * })\n * ```\n */\nexport function provideDatadogErrorHandler(): EnvironmentProviders {\n  return makeEnvironmentProviders([{ provide: ErrorHandler, useClass: DatadogErrorHandler }])\n}\n"
  },
  {
    "path": "packages/rum-angular/src/entries/main.ts",
    "content": "export { angularPlugin } from '../domain/angularPlugin'\nexport type { AngularPluginConfiguration } from '../domain/angularPlugin'\nexport { provideDatadogRouter } from '../domain/angularRouter/provideDatadogRouter'\nexport { addAngularError, provideDatadogErrorHandler } from '../domain/error'\n"
  },
  {
    "path": "packages/rum-angular/test/initializeAngularPlugin.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\nimport { noop } from '@datadog/browser-core'\nimport { angularPlugin, resetAngularPlugin } from '../src/domain/angularPlugin'\nimport { registerCleanupTask } from '../../core/test'\n\nexport function initializeAngularPlugin({\n  addError = noop,\n}: {\n  addError?: StartRumResult['addError']\n} = {}) {\n  resetAngularPlugin()\n  const plugin = angularPlugin()\n\n  plugin.onInit!({\n    publicApi: {} as RumPublicApi,\n    initConfiguration: {} as RumInitConfiguration,\n  })\n  plugin.onRumStart!({ addError })\n\n  registerCleanupTask(() => {\n    resetAngularPlugin()\n  })\n}\n"
  },
  {
    "path": "packages/rum-angular/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"jasmine\"],\n    \"allowImportingTsExtensions\": true,\n    \"noEmit\": true\n  },\n  \"include\": [\"src\", \"test\"]\n}\n"
  },
  {
    "path": "packages/rum-core/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/rum-core/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-core/README.md",
    "content": "# `rum-core`\n\nDatadog browser RUM core utilities.\n"
  },
  {
    "path": "packages/rum-core/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-core\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/index.js\",\n  \"module\": \"esm/index.js\",\n  \"types\": \"cjs/index.d.ts\",\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\"\n  },\n  \"devDependencies\": {\n    \"ajv\": \"8.18.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-core\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/boot/preStartRum.spec.ts",
    "content": "import type { DeflateWorker, Duration, TimeStamp, TrackingConsentState } from '@datadog/browser-core'\nimport {\n  display,\n  getTimeStamp,\n  noop,\n  relativeToClocks,\n  clocksNow,\n  TrackingConsent,\n  createTrackingConsentState,\n  DefaultPrivacyLevel,\n  ExperimentalFeature,\n  startTelemetry,\n  addExperimentalFeatures,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport {\n  callbackAddsInstrumentation,\n  interceptRequests,\n  mockClock,\n  mockEventBridge,\n  mockSyntheticsWorkerValues,\n  createFakeTelemetryObject,\n  replaceMockableWithSpy,\n} from '@datadog/browser-core/test'\nimport type { HybridInitConfiguration, RumInitConfiguration } from '../domain/configuration'\nimport type { ViewOptions } from '../domain/view/trackViews'\nimport { ActionType, VitalType } from '../rawRumEvent.types'\nimport type { RumPlugin } from '../domain/plugins'\nimport { createCustomVitalsState } from '../domain/vital/vitalCollection'\nimport type { ManualAction } from '../domain/action/trackManualActions'\nimport type { RumPublicApi, RumPublicApiOptions, Strategy } from './rumPublicApi'\nimport type { StartRumResult } from './startRum'\nimport type { DoStartRum } from './preStartRum'\nimport { createPreStartStrategy } from './preStartRum'\n\nconst DEFAULT_INIT_CONFIGURATION = { applicationId: 'xxx', clientToken: 'xxx' }\nconst INVALID_INIT_CONFIGURATION = { clientToken: 'yes' } as RumInitConfiguration\nconst AUTO_CONFIGURATION = { ...DEFAULT_INIT_CONFIGURATION }\nconst MANUAL_CONFIGURATION = { ...AUTO_CONFIGURATION, trackViewsManually: true }\nconst FAKE_WORKER = {} as DeflateWorker\nconst PUBLIC_API = {} as RumPublicApi\n\ndescribe('preStartRum', () => {\n  describe('configuration validation', () => {\n    let strategy: Strategy\n    let doStartRumSpy: jasmine.Spy<DoStartRum>\n    let displaySpy: jasmine.Spy\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'error')\n      ;({ strategy, doStartRumSpy } = createPreStartStrategyWithDefaults())\n    })\n\n    it('should start when the configuration is valid', () => {\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(displaySpy).not.toHaveBeenCalled()\n      expect(doStartRumSpy).toHaveBeenCalled()\n    })\n\n    it('should not start when the configuration is missing', () => {\n      ;(strategy.init as () => void)()\n      expect(displaySpy).toHaveBeenCalled()\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n    })\n\n    it('should not start when the configuration is invalid', () => {\n      strategy.init(INVALID_INIT_CONFIGURATION, PUBLIC_API)\n      expect(displaySpy).toHaveBeenCalled()\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n    })\n\n    describe('multiple init', () => {\n      it('should log an error if init is called several times', () => {\n        strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n        expect(displaySpy).toHaveBeenCalledTimes(0)\n\n        strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n        expect(displaySpy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should not log an error if init is called several times and silentMultipleInit is true', () => {\n        strategy.init(\n          {\n            ...DEFAULT_INIT_CONFIGURATION,\n            silentMultipleInit: true,\n          },\n          PUBLIC_API\n        )\n        expect(displaySpy).toHaveBeenCalledTimes(0)\n\n        strategy.init(\n          {\n            ...DEFAULT_INIT_CONFIGURATION,\n            silentMultipleInit: true,\n          },\n          PUBLIC_API\n        )\n        expect(displaySpy).toHaveBeenCalledTimes(0)\n      })\n    })\n\n    describe('if event bridge present', () => {\n      it('init should accept empty application id and client token', () => {\n        mockEventBridge()\n        const hybridInitConfiguration: HybridInitConfiguration = {}\n        strategy.init(hybridInitConfiguration as RumInitConfiguration, PUBLIC_API)\n        expect(display.error).not.toHaveBeenCalled()\n      })\n\n      it('should force session sample rate to 100', () => {\n        mockEventBridge()\n        const invalidConfiguration: HybridInitConfiguration = { sessionSampleRate: 50 }\n        strategy.init(invalidConfiguration as RumInitConfiguration, PUBLIC_API)\n        expect(strategy.initConfiguration?.sessionSampleRate).toEqual(100)\n      })\n\n      it('should set the default privacy level received from the bridge if the not provided in the init configuration', () => {\n        mockEventBridge({ privacyLevel: DefaultPrivacyLevel.ALLOW })\n        const hybridInitConfiguration: HybridInitConfiguration = {}\n        strategy.init(hybridInitConfiguration as RumInitConfiguration, PUBLIC_API)\n        expect((strategy.initConfiguration as RumInitConfiguration)?.defaultPrivacyLevel).toEqual(\n          DefaultPrivacyLevel.ALLOW\n        )\n      })\n\n      it('should set the default privacy level from the init configuration if provided', () => {\n        mockEventBridge({ privacyLevel: DefaultPrivacyLevel.ALLOW })\n        const hybridInitConfiguration: HybridInitConfiguration = { defaultPrivacyLevel: DefaultPrivacyLevel.MASK }\n        strategy.init(hybridInitConfiguration as RumInitConfiguration, PUBLIC_API)\n        expect((strategy.initConfiguration as RumInitConfiguration)?.defaultPrivacyLevel).toEqual(\n          hybridInitConfiguration.defaultPrivacyLevel\n        )\n      })\n\n      it('should set the default privacy level to \"mask\" if not provided in init configuration nor the bridge', () => {\n        mockEventBridge({ privacyLevel: undefined })\n        const hybridInitConfiguration: HybridInitConfiguration = {}\n        strategy.init(hybridInitConfiguration as RumInitConfiguration, PUBLIC_API)\n        expect((strategy.initConfiguration as RumInitConfiguration)?.defaultPrivacyLevel).toEqual(\n          DefaultPrivacyLevel.MASK\n        )\n      })\n\n      it('should initialize even if session cannot be handled', () => {\n        mockEventBridge()\n        spyOnProperty(document, 'cookie', 'get').and.returnValue('')\n        strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n        expect(doStartRumSpy).toHaveBeenCalled()\n      })\n    })\n  })\n\n  describe('init', () => {\n    it('should not initialize if session cannot be handled and bridge is not present', () => {\n      spyOnProperty(document, 'cookie', 'get').and.returnValue('')\n      const displaySpy = spyOn(display, 'warn')\n      const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults()\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n      expect(displaySpy).toHaveBeenCalled()\n    })\n\n    describe('skipInitIfSyntheticsWillInjectRum option', () => {\n      it('when true, ignores init() call if Synthetics will inject its own instance of RUM', () => {\n        mockSyntheticsWorkerValues({ injectsRum: true })\n\n        const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults({\n          rumPublicApiOptions: {\n            ignoreInitIfSyntheticsWillInjectRum: true,\n          },\n        })\n        strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n\n        expect(doStartRumSpy).not.toHaveBeenCalled()\n      })\n\n      it('when undefined, ignores init() call if Synthetics will inject its own instance of RUM', () => {\n        mockSyntheticsWorkerValues({ injectsRum: true })\n\n        const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults()\n        strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n\n        expect(doStartRumSpy).not.toHaveBeenCalled()\n      })\n\n      it('when false, does not ignore init() call even if Synthetics will inject its own instance of RUM', () => {\n        mockSyntheticsWorkerValues({ injectsRum: true })\n\n        const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults({\n          rumPublicApiOptions: {\n            ignoreInitIfSyntheticsWillInjectRum: false,\n          },\n        })\n        strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n\n        expect(doStartRumSpy).toHaveBeenCalled()\n      })\n    })\n\n    describe('deflate worker', () => {\n      let strategy: Strategy\n      let startDeflateWorkerSpy: jasmine.Spy\n      let doStartRumSpy: jasmine.Spy<DoStartRum>\n\n      beforeEach(() => {\n        startDeflateWorkerSpy = jasmine.createSpy().and.returnValue(FAKE_WORKER)\n        ;({ strategy, doStartRumSpy } = createPreStartStrategyWithDefaults({\n          rumPublicApiOptions: {\n            startDeflateWorker: startDeflateWorkerSpy,\n            createDeflateEncoder: noop as any,\n          },\n        }))\n      })\n\n      describe('with compressIntakeRequests: false', () => {\n        it('does not create a deflate worker', () => {\n          strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n\n          expect(startDeflateWorkerSpy).not.toHaveBeenCalled()\n          const worker: DeflateWorker | undefined = doStartRumSpy.calls.mostRecent().args[1]\n          expect(worker).toBeUndefined()\n        })\n      })\n\n      describe('with compressIntakeRequests: true', () => {\n        it('creates a deflate worker instance', () => {\n          strategy.init(\n            {\n              ...DEFAULT_INIT_CONFIGURATION,\n              compressIntakeRequests: true,\n            },\n            PUBLIC_API\n          )\n\n          expect(startDeflateWorkerSpy).toHaveBeenCalledTimes(1)\n          const worker: DeflateWorker | undefined = doStartRumSpy.calls.mostRecent().args[1]\n          expect(worker).toBeDefined()\n        })\n\n        it('aborts the initialization if it fails to create a deflate worker', () => {\n          startDeflateWorkerSpy.and.returnValue(undefined)\n\n          strategy.init(\n            {\n              ...DEFAULT_INIT_CONFIGURATION,\n              compressIntakeRequests: true,\n            },\n            PUBLIC_API\n          )\n\n          expect(doStartRumSpy).not.toHaveBeenCalled()\n        })\n\n        it('if message bridge is present, does not create a deflate worker instance', () => {\n          mockEventBridge()\n\n          strategy.init(\n            {\n              ...DEFAULT_INIT_CONFIGURATION,\n              compressIntakeRequests: true,\n            },\n            PUBLIC_API\n          )\n\n          expect(startDeflateWorkerSpy).not.toHaveBeenCalled()\n          expect(doStartRumSpy).toHaveBeenCalledTimes(1)\n        })\n      })\n    })\n\n    describe('trackViews mode', () => {\n      let clock: Clock | undefined\n      let strategy: Strategy\n      let doStartRumSpy: jasmine.Spy<DoStartRum>\n      let startViewSpy: jasmine.Spy<StartRumResult['startView']>\n      let addTimingSpy: jasmine.Spy<StartRumResult['addTiming']>\n      let setViewNameSpy: jasmine.Spy<StartRumResult['setViewName']>\n\n      beforeEach(() => {\n        startViewSpy = jasmine.createSpy('startView')\n        addTimingSpy = jasmine.createSpy('addTiming')\n        setViewNameSpy = jasmine.createSpy('setViewName')\n        ;({ strategy, doStartRumSpy } = createPreStartStrategyWithDefaults())\n        doStartRumSpy.and.returnValue({\n          startView: startViewSpy,\n          addTiming: addTimingSpy,\n          setViewName: setViewNameSpy,\n        } as unknown as StartRumResult)\n      })\n\n      describe('when auto', () => {\n        it('should start rum at init', () => {\n          strategy.init(AUTO_CONFIGURATION, PUBLIC_API)\n\n          expect(doStartRumSpy).toHaveBeenCalled()\n        })\n\n        it('before init startView should be handled after init', () => {\n          clock = mockClock()\n\n          clock.tick(10)\n          strategy.startView({ name: 'foo' })\n\n          expect(startViewSpy).not.toHaveBeenCalled()\n\n          clock.tick(20)\n          strategy.init(AUTO_CONFIGURATION, PUBLIC_API)\n\n          expect(startViewSpy).toHaveBeenCalled()\n          expect(startViewSpy.calls.argsFor(0)[0]).toEqual({ name: 'foo' })\n          expect(startViewSpy.calls.argsFor(0)[1]).toEqual({\n            relative: clock.relative(10),\n            timeStamp: clock.timeStamp(10),\n          })\n        })\n      })\n\n      describe('when views are tracked manually', () => {\n        it('should not start rum at init', () => {\n          strategy.init(MANUAL_CONFIGURATION, PUBLIC_API)\n\n          expect(doStartRumSpy).not.toHaveBeenCalled()\n        })\n\n        it('calling startView then init should start rum', () => {\n          strategy.startView({ name: 'foo' })\n          expect(doStartRumSpy).not.toHaveBeenCalled()\n          expect(startViewSpy).not.toHaveBeenCalled()\n\n          strategy.init(MANUAL_CONFIGURATION, PUBLIC_API)\n          expect(doStartRumSpy).toHaveBeenCalled()\n          const initialViewOptions: ViewOptions | undefined = doStartRumSpy.calls.argsFor(0)[2]\n          expect(initialViewOptions).toEqual({ name: 'foo' })\n          expect(startViewSpy).not.toHaveBeenCalled()\n        })\n\n        it('calling startView then init does not start rum if tracking consent is not granted', () => {\n          strategy.startView({ name: 'foo' })\n          strategy.init(\n            {\n              ...MANUAL_CONFIGURATION,\n              trackingConsent: TrackingConsent.NOT_GRANTED,\n            },\n            PUBLIC_API\n          )\n          expect(doStartRumSpy).not.toHaveBeenCalled()\n        })\n\n        it('calling startView twice before init should start rum and create a new view', () => {\n          clock = mockClock()\n          clock.tick(10)\n          strategy.startView({ name: 'foo' })\n\n          clock.tick(10)\n          strategy.startView({ name: 'bar' })\n\n          clock.tick(10)\n          strategy.init(MANUAL_CONFIGURATION, PUBLIC_API)\n\n          expect(doStartRumSpy).toHaveBeenCalled()\n          const initialViewOptions: ViewOptions | undefined = doStartRumSpy.calls.argsFor(0)[2]\n          expect(initialViewOptions).toEqual({ name: 'foo' })\n          expect(startViewSpy).toHaveBeenCalledOnceWith({ name: 'bar' }, relativeToClocks(clock.relative(20)))\n        })\n\n        it('calling init then startView should start rum', () => {\n          strategy.init(MANUAL_CONFIGURATION, PUBLIC_API)\n          expect(doStartRumSpy).not.toHaveBeenCalled()\n          expect(startViewSpy).not.toHaveBeenCalled()\n\n          strategy.startView({ name: 'foo' })\n          expect(doStartRumSpy).toHaveBeenCalled()\n          const initialViewOptions: ViewOptions | undefined = doStartRumSpy.calls.argsFor(0)[2]\n          expect(initialViewOptions).toEqual({ name: 'foo' })\n          expect(startViewSpy).not.toHaveBeenCalled()\n        })\n\n        it('API calls should be handled in order', () => {\n          clock = mockClock()\n\n          clock.tick(10)\n          strategy.addTiming('first')\n\n          clock.tick(10)\n          strategy.startView({ name: 'foo' })\n\n          clock.tick(10)\n          strategy.addTiming('second')\n\n          clock.tick(10)\n          strategy.init(MANUAL_CONFIGURATION, PUBLIC_API)\n\n          expect(addTimingSpy).toHaveBeenCalledTimes(2)\n\n          expect(addTimingSpy.calls.argsFor(0)[0]).toEqual('first')\n          expect(addTimingSpy.calls.argsFor(0)[1]).toEqual(getTimeStamp(clock.relative(10)))\n\n          expect(addTimingSpy.calls.argsFor(1)[0]).toEqual('second')\n          expect(addTimingSpy.calls.argsFor(1)[1]).toEqual(getTimeStamp(clock.relative(30)))\n        })\n      })\n    })\n\n    describe('remote configuration', () => {\n      let interceptor: ReturnType<typeof interceptRequests>\n\n      beforeEach(() => {\n        interceptor = interceptRequests()\n      })\n\n      it('should start with the remote configuration when a remoteConfigurationId is provided', (done) => {\n        interceptor.withFetch(() =>\n          Promise.resolve({\n            ok: true,\n            json: () => Promise.resolve({ rum: { sessionSampleRate: 50 } }),\n          })\n        )\n        const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults()\n        doStartRumSpy.and.callFake((configuration) => {\n          expect(configuration.sessionSampleRate).toEqual(50)\n          done()\n          return {} as StartRumResult\n        })\n        strategy.init(\n          {\n            ...DEFAULT_INIT_CONFIGURATION,\n            remoteConfigurationId: '123',\n          },\n          PUBLIC_API\n        )\n      })\n    })\n\n    describe('plugins', () => {\n      it('calls the onInit method on provided plugins', () => {\n        const plugin = { name: 'a', onInit: jasmine.createSpy() }\n        const { strategy } = createPreStartStrategyWithDefaults()\n        const initConfiguration: RumInitConfiguration = { ...DEFAULT_INIT_CONFIGURATION, plugins: [plugin] }\n        strategy.init(initConfiguration, PUBLIC_API)\n\n        expect(plugin.onInit).toHaveBeenCalledWith({\n          initConfiguration,\n          publicApi: PUBLIC_API,\n        })\n      })\n\n      it('plugins can edit the init configuration prior to validation', () => {\n        const plugin: RumPlugin = {\n          name: 'a',\n          onInit: ({ initConfiguration }) => {\n            initConfiguration.clientToken = 'client-token'\n            initConfiguration.applicationId = 'application-id'\n          },\n        }\n        const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults()\n        strategy.init(\n          {\n            plugins: [plugin],\n          } as RumInitConfiguration,\n          PUBLIC_API\n        )\n\n        expect(doStartRumSpy).toHaveBeenCalled()\n        expect(doStartRumSpy.calls.mostRecent().args[0].applicationId).toBe('application-id')\n      })\n    })\n  })\n\n  describe('getInternalContext', () => {\n    it('returns undefined', () => {\n      const { strategy } = createPreStartStrategyWithDefaults()\n      expect(strategy.getInternalContext()).toBe(undefined)\n    })\n  })\n\n  describe('getViewContext', () => {\n    it('returns empty object', () => {\n      const { strategy } = createPreStartStrategyWithDefaults()\n      expect(strategy.getViewContext()).toEqual({})\n    })\n  })\n\n  describe('stopSession', () => {\n    it('does not buffer the call before starting RUM', () => {\n      const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults()\n      const stopSessionSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ stopSession: stopSessionSpy } as unknown as StartRumResult)\n\n      strategy.stopSession()\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(stopSessionSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('initConfiguration', () => {\n    let initConfiguration: RumInitConfiguration\n    let interceptor: ReturnType<typeof interceptRequests>\n\n    beforeEach(() => {\n      interceptor = interceptRequests()\n      initConfiguration = { ...DEFAULT_INIT_CONFIGURATION, service: 'my-service', version: '1.4.2', env: 'dev' }\n    })\n\n    it('is undefined before init', () => {\n      const { strategy } = createPreStartStrategyWithDefaults()\n      expect(strategy.initConfiguration).toBe(undefined)\n    })\n\n    it('returns the user configuration after init', () => {\n      const { strategy } = createPreStartStrategyWithDefaults()\n      strategy.init(initConfiguration, PUBLIC_API)\n\n      expect(strategy.initConfiguration).toEqual(initConfiguration)\n    })\n\n    it('returns the user configuration even if skipInitIfSyntheticsWillInjectRum is true', () => {\n      mockSyntheticsWorkerValues({ injectsRum: true })\n\n      const { strategy } = createPreStartStrategyWithDefaults({\n        rumPublicApiOptions: {\n          ignoreInitIfSyntheticsWillInjectRum: true,\n        },\n      })\n      strategy.init(initConfiguration, PUBLIC_API)\n\n      expect(strategy.initConfiguration).toEqual(initConfiguration)\n    })\n\n    it('returns the initConfiguration with the remote configuration when a remoteConfigurationId is provided', (done) => {\n      interceptor.withFetch(() =>\n        Promise.resolve({\n          ok: true,\n          json: () => Promise.resolve({ rum: { sessionSampleRate: 50 } }),\n        })\n      )\n      const { strategy, doStartRumSpy } = createPreStartStrategyWithDefaults()\n      doStartRumSpy.and.callFake(() => {\n        expect(strategy.initConfiguration?.sessionSampleRate).toEqual(50)\n        done()\n        return {} as StartRumResult\n      })\n      strategy.init(\n        {\n          ...DEFAULT_INIT_CONFIGURATION,\n          remoteConfigurationId: '123',\n        },\n        PUBLIC_API\n      )\n    })\n  })\n\n  describe('buffers API calls before starting RUM', () => {\n    let strategy: Strategy\n    let doStartRumSpy: jasmine.Spy<DoStartRum>\n\n    beforeEach(() => {\n      ;({ strategy, doStartRumSpy } = createPreStartStrategyWithDefaults())\n    })\n\n    it('addAction', () => {\n      const addActionSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ addAction: addActionSpy } as unknown as StartRumResult)\n\n      const manualAction: Omit<ManualAction, 'id' | 'duration' | 'counts' | 'frustrationTypes'> = {\n        name: 'foo',\n        type: ActionType.CUSTOM,\n        startClocks: clocksNow(),\n      }\n      strategy.addAction(manualAction)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addActionSpy).toHaveBeenCalledOnceWith(manualAction)\n    })\n\n    it('addError', () => {\n      const addErrorSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ addError: addErrorSpy } as unknown as StartRumResult)\n\n      const error = {\n        error: new Error('foo'),\n        handlingStack: '',\n        context: {},\n        startClocks: clocksNow(),\n      }\n      strategy.addError(error)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addErrorSpy).toHaveBeenCalledOnceWith(error)\n    })\n\n    it('startView', () => {\n      const startViewSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ startView: startViewSpy } as unknown as StartRumResult)\n\n      const options = { name: 'foo' }\n      const clockState = clocksNow()\n      strategy.startView(options, clockState)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(startViewSpy).toHaveBeenCalledOnceWith(options, clockState)\n    })\n\n    it('addTiming', () => {\n      const addTimingSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ addTiming: addTimingSpy } as unknown as StartRumResult)\n\n      const name = 'foo'\n      const time = 123 as TimeStamp\n      strategy.addTiming(name, time)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addTimingSpy).toHaveBeenCalledOnceWith(name, time)\n    })\n\n    it('setLoadingTime', () => {\n      const setLoadingTimeSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ setLoadingTime: setLoadingTimeSpy } as unknown as StartRumResult)\n\n      const timestamp = 123 as TimeStamp\n      strategy.setLoadingTime(timestamp)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(setLoadingTimeSpy).toHaveBeenCalledOnceWith(timestamp)\n    })\n\n    it('setLoadingTime should preserve call timestamp', () => {\n      const clock = mockClock()\n      const setLoadingTimeSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ setLoadingTime: setLoadingTimeSpy } as unknown as StartRumResult)\n\n      clock.tick(10)\n      strategy.setLoadingTime(clock.timeStamp(10))\n\n      clock.tick(20)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n\n      expect(setLoadingTimeSpy).toHaveBeenCalledOnceWith(jasmine.any(Number))\n      // Verify the timestamp was captured at call time (tick 10), not at drain time (tick 30)\n      const capturedTimestamp = setLoadingTimeSpy.calls.argsFor(0)[0] as number\n      expect(capturedTimestamp).toBe(clock.timeStamp(10))\n    })\n\n    it('setViewContext', () => {\n      const setViewContextSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ setViewContext: setViewContextSpy } as unknown as StartRumResult)\n\n      strategy.setViewContext({ foo: 'bar' })\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(setViewContextSpy).toHaveBeenCalledOnceWith({ foo: 'bar' })\n    })\n\n    it('setViewContextProperty', () => {\n      const setViewContextPropertySpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ setViewContextProperty: setViewContextPropertySpy } as unknown as StartRumResult)\n\n      strategy.setViewContextProperty('foo', 'bar')\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(setViewContextPropertySpy).toHaveBeenCalledOnceWith('foo', 'bar')\n    })\n\n    it('setViewName', () => {\n      const setViewNameSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({ setViewName: setViewNameSpy } as unknown as StartRumResult)\n\n      const name = 'foo'\n      strategy.setViewName(name)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(setViewNameSpy).toHaveBeenCalledOnceWith(name)\n    })\n\n    it('addFeatureFlagEvaluation', () => {\n      const addFeatureFlagEvaluationSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({\n        addFeatureFlagEvaluation: addFeatureFlagEvaluationSpy,\n      } as unknown as StartRumResult)\n\n      const key = 'foo'\n      const value = 'bar'\n      strategy.addFeatureFlagEvaluation(key, value)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addFeatureFlagEvaluationSpy).toHaveBeenCalledOnceWith(key, value)\n    })\n\n    it('startDurationVital', () => {\n      const addDurationVitalSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({\n        addDurationVital: addDurationVitalSpy,\n      } as unknown as StartRumResult)\n\n      strategy.startDurationVital('timing')\n      strategy.stopDurationVital('timing')\n\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addDurationVitalSpy).toHaveBeenCalled()\n    })\n\n    it('addDurationVital', () => {\n      const addDurationVitalSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({\n        addDurationVital: addDurationVitalSpy,\n      } as unknown as StartRumResult)\n\n      const vitalAdd = {\n        id: 'id',\n        name: 'timing',\n        type: VitalType.DURATION,\n        startClocks: clocksNow(),\n        duration: 100 as Duration,\n      }\n      strategy.addDurationVital(vitalAdd)\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addDurationVitalSpy).toHaveBeenCalledOnceWith(vitalAdd)\n    })\n\n    it('addOperationStepVital', () => {\n      const addOperationStepVitalSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({\n        addOperationStepVital: addOperationStepVitalSpy,\n      } as unknown as StartRumResult)\n\n      strategy.addOperationStepVital('foo', 'start')\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(addOperationStepVitalSpy).toHaveBeenCalledOnceWith('foo', 'start', undefined, undefined)\n    })\n\n    it('startAction / stopAction', () => {\n      addExperimentalFeatures([ExperimentalFeature.START_STOP_ACTION])\n\n      const startActionSpy = jasmine.createSpy()\n      const stopActionSpy = jasmine.createSpy()\n      doStartRumSpy.and.returnValue({\n        startAction: startActionSpy,\n        stopAction: stopActionSpy,\n      } as unknown as StartRumResult)\n\n      strategy.startAction('user_login', { type: ActionType.CUSTOM })\n      strategy.stopAction('user_login')\n\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n\n      expect(startActionSpy).toHaveBeenCalledWith(\n        'user_login',\n        jasmine.objectContaining({\n          type: ActionType.CUSTOM,\n        }),\n        jasmine.objectContaining({\n          relative: jasmine.any(Number),\n          timeStamp: jasmine.any(Number),\n        })\n      )\n      expect(stopActionSpy).toHaveBeenCalledWith(\n        'user_login',\n        undefined,\n        jasmine.objectContaining({\n          relative: jasmine.any(Number),\n          timeStamp: jasmine.any(Number),\n        })\n      )\n    })\n  })\n\n  describe('tracking consent', () => {\n    let strategy: Strategy\n    let doStartRumSpy: jasmine.Spy<DoStartRum>\n    let trackingConsentState: TrackingConsentState\n\n    beforeEach(() => {\n      trackingConsentState = createTrackingConsentState()\n      ;({ strategy, doStartRumSpy } = createPreStartStrategyWithDefaults({ trackingConsentState }))\n    })\n\n    describe('basic methods instrumentation', () => {\n      it('should instrument fetch even if tracking consent is not granted', () => {\n        expect(\n          callbackAddsInstrumentation(() => {\n            strategy.init(\n              {\n                ...DEFAULT_INIT_CONFIGURATION,\n                trackingConsent: TrackingConsent.NOT_GRANTED,\n              },\n              PUBLIC_API\n            )\n          })\n            .toMethod(window, 'fetch')\n            .whenCalled()\n        ).toBeTrue()\n      })\n    })\n\n    it('does not start rum if tracking consent is not granted at init', () => {\n      strategy.init(\n        {\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackingConsent: TrackingConsent.NOT_GRANTED,\n        },\n        PUBLIC_API\n      )\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n    })\n\n    it('starts rum if tracking consent is granted before init', () => {\n      trackingConsentState.update(TrackingConsent.GRANTED)\n      strategy.init(\n        {\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackingConsent: TrackingConsent.NOT_GRANTED,\n        },\n        PUBLIC_API\n      )\n      expect(doStartRumSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('does not start rum if tracking consent is withdrawn before init', () => {\n      trackingConsentState.update(TrackingConsent.NOT_GRANTED)\n      strategy.init(\n        {\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackingConsent: TrackingConsent.GRANTED,\n        },\n        PUBLIC_API\n      )\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not start rum if no view is started', () => {\n      trackingConsentState.update(TrackingConsent.GRANTED)\n      strategy.init(\n        {\n          ...MANUAL_CONFIGURATION,\n          trackingConsent: TrackingConsent.NOT_GRANTED,\n        },\n        PUBLIC_API\n      )\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n    })\n\n    it('do not call startRum when tracking consent state is updated after init', () => {\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      doStartRumSpy.calls.reset()\n\n      trackingConsentState.update(TrackingConsent.GRANTED)\n\n      expect(doStartRumSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('telemetry', () => {\n    it('starts telemetry during init() by default', () => {\n      const { strategy, startTelemetrySpy } = createPreStartStrategyWithDefaults()\n      strategy.init(DEFAULT_INIT_CONFIGURATION, PUBLIC_API)\n      expect(startTelemetrySpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('does not start telemetry until consent is granted', () => {\n      const trackingConsentState = createTrackingConsentState()\n      const { strategy, startTelemetrySpy } = createPreStartStrategyWithDefaults({\n        trackingConsentState,\n      })\n\n      strategy.init(\n        {\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackingConsent: TrackingConsent.NOT_GRANTED,\n        },\n        PUBLIC_API\n      )\n\n      expect(startTelemetrySpy).not.toHaveBeenCalled()\n\n      trackingConsentState.update(TrackingConsent.GRANTED)\n\n      expect(startTelemetrySpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('starts telemetry only once', () => {\n      const trackingConsentState = createTrackingConsentState()\n      const { strategy, startTelemetrySpy } = createPreStartStrategyWithDefaults({\n        trackingConsentState,\n      })\n\n      strategy.init(MANUAL_CONFIGURATION, PUBLIC_API)\n\n      expect(startTelemetrySpy).toHaveBeenCalledTimes(1)\n\n      strategy.startView({ name: 'foo' })\n\n      expect(startTelemetrySpy).toHaveBeenCalledTimes(1)\n    })\n  })\n})\n\nfunction createPreStartStrategyWithDefaults({\n  rumPublicApiOptions = {},\n  trackingConsentState = createTrackingConsentState(),\n}: {\n  rumPublicApiOptions?: RumPublicApiOptions\n  trackingConsentState?: TrackingConsentState\n} = {}) {\n  const doStartRumSpy = jasmine.createSpy<DoStartRum>()\n  const startTelemetrySpy = replaceMockableWithSpy(startTelemetry).and.callFake(createFakeTelemetryObject)\n  return {\n    strategy: createPreStartStrategy(\n      rumPublicApiOptions,\n      trackingConsentState,\n      createCustomVitalsState(),\n      doStartRumSpy\n    ),\n    doStartRumSpy,\n    startTelemetrySpy,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/boot/preStartRum.ts",
    "content": "import type {\n  TrackingConsentState,\n  DeflateWorker,\n  Context,\n  ContextManager,\n  BoundedBuffer,\n  Telemetry,\n  TimeStamp,\n} from '@datadog/browser-core'\nimport {\n  createBoundedBuffer,\n  display,\n  canUseEventBridge,\n  displayAlreadyInitializedError,\n  willSyntheticsInjectRum,\n  noop,\n  timeStampNow,\n  clocksNow,\n  getEventBridge,\n  initFeatureFlags,\n  addTelemetryConfiguration,\n  initFetchObservable,\n  CustomerContextKey,\n  buildAccountContextManager,\n  buildGlobalContextManager,\n  buildUserContextManager,\n  monitorError,\n  sanitize,\n  startTelemetry,\n  TelemetryService,\n  mockable,\n} from '@datadog/browser-core'\nimport type { Hooks } from '../domain/hooks'\nimport { createHooks } from '../domain/hooks'\nimport type { RumConfiguration, RumInitConfiguration } from '../domain/configuration'\nimport {\n  validateAndBuildRumConfiguration,\n  fetchAndApplyRemoteConfiguration,\n  serializeRumConfiguration,\n} from '../domain/configuration'\nimport type { ViewOptions } from '../domain/view/trackViews'\nimport type {\n  DurationVital,\n  CustomVitalsState,\n  FeatureOperationOptions,\n  FailureReason,\n} from '../domain/vital/vitalCollection'\nimport { startDurationVital, stopDurationVital } from '../domain/vital/vitalCollection'\nimport { callPluginsMethod } from '../domain/plugins'\nimport type { StartRumResult } from './startRum'\nimport type { RumPublicApiOptions, Strategy } from './rumPublicApi'\n\nexport type DoStartRum = (\n  configuration: RumConfiguration,\n  deflateWorker: DeflateWorker | undefined,\n  initialViewOptions: ViewOptions | undefined,\n  telemetry: Telemetry,\n  hooks: Hooks\n) => StartRumResult\n\nexport function createPreStartStrategy(\n  { ignoreInitIfSyntheticsWillInjectRum = true, startDeflateWorker }: RumPublicApiOptions,\n  trackingConsentState: TrackingConsentState,\n  customVitalsState: CustomVitalsState,\n  doStartRum: DoStartRum\n): Strategy {\n  const bufferApiCalls = createBoundedBuffer<StartRumResult>()\n\n  // TODO next major: remove the globalContextManager, userContextManager and accountContextManager from preStartStrategy and use an empty context instead\n  const globalContext = buildGlobalContextManager()\n  bufferContextCalls(globalContext, CustomerContextKey.globalContext, bufferApiCalls)\n\n  const userContext = buildUserContextManager()\n  bufferContextCalls(userContext, CustomerContextKey.userContext, bufferApiCalls)\n\n  const accountContext = buildAccountContextManager()\n  bufferContextCalls(accountContext, CustomerContextKey.accountContext, bufferApiCalls)\n\n  let firstStartViewCall:\n    | { options: ViewOptions | undefined; callback: (startRumResult: StartRumResult) => void }\n    | undefined\n  let deflateWorker: DeflateWorker | undefined\n\n  let cachedInitConfiguration: RumInitConfiguration | undefined\n  let cachedConfiguration: RumConfiguration | undefined\n  let telemetry: Telemetry | undefined\n  const hooks = createHooks()\n\n  const trackingConsentStateSubscription = trackingConsentState.observable.subscribe(tryStartRum)\n\n  const emptyContext: Context = {}\n\n  function tryStartRum() {\n    if (!cachedInitConfiguration || !cachedConfiguration || !trackingConsentState.isGranted()) {\n      return\n    }\n\n    // Start telemetry only once, when we have consent and configuration\n    if (!telemetry) {\n      telemetry = mockable(startTelemetry)(TelemetryService.RUM, cachedConfiguration, hooks)\n    }\n\n    trackingConsentStateSubscription.unsubscribe()\n\n    let initialViewOptions: ViewOptions | undefined\n\n    if (cachedConfiguration.trackViewsManually) {\n      if (!firstStartViewCall) {\n        return\n      }\n      // An initial view is always created when starting RUM.\n      // When tracking views automatically, any startView call before RUM start creates an extra\n      // view.\n      // When tracking views manually, we use the ViewOptions from the first startView call as the\n      // initial view options, and we remove the actual startView call so we don't create an extra\n      // view.\n      bufferApiCalls.remove(firstStartViewCall.callback)\n      initialViewOptions = firstStartViewCall.options\n    }\n\n    const startRumResult = doStartRum(cachedConfiguration, deflateWorker, initialViewOptions, telemetry, hooks)\n\n    bufferApiCalls.drain(startRumResult)\n  }\n\n  function doInit(initConfiguration: RumInitConfiguration, errorStack?: string) {\n    const eventBridgeAvailable = canUseEventBridge()\n    if (eventBridgeAvailable) {\n      initConfiguration = overrideInitConfigurationForBridge(initConfiguration)\n    }\n\n    // Update the exposed initConfiguration to reflect the bridge and remote configuration overrides\n    cachedInitConfiguration = initConfiguration\n    addTelemetryConfiguration(serializeRumConfiguration(initConfiguration))\n\n    if (cachedConfiguration) {\n      displayAlreadyInitializedError('DD_RUM', initConfiguration)\n      return\n    }\n\n    const configuration = validateAndBuildRumConfiguration(initConfiguration, errorStack)\n    if (!configuration) {\n      return\n    }\n\n    if (!eventBridgeAvailable && !configuration.sessionStoreStrategyType) {\n      display.warn('No storage available for session. We will not send any data.')\n      return\n    }\n\n    if (configuration.compressIntakeRequests && !eventBridgeAvailable && startDeflateWorker) {\n      deflateWorker = startDeflateWorker(\n        configuration,\n        'Datadog RUM',\n        // Worker initialization can fail asynchronously, especially in Firefox where even CSP\n        // issues are reported asynchronously. For now, the SDK will continue its execution even if\n        // data won't be sent to Datadog. We could improve this behavior in the future.\n        noop\n      )\n      if (!deflateWorker) {\n        // `startDeflateWorker` should have logged an error message explaining the issue\n        return\n      }\n    }\n\n    cachedConfiguration = configuration\n\n    // Instrument fetch to track network requests\n    // This is needed in case the consent is not granted and some customer\n    // library (Apollo Client) is storing uninstrumented fetch to be used later\n    // The subscription is needed so that the instrumentation process is completed\n    initFetchObservable().subscribe(noop)\n\n    trackingConsentState.tryToInit(configuration.trackingConsent)\n    tryStartRum()\n  }\n\n  const addDurationVital = (vital: DurationVital) => {\n    bufferApiCalls.add((startRumResult) => startRumResult.addDurationVital(vital))\n  }\n\n  const addOperationStepVital = (\n    name: string,\n    stepType: 'start' | 'end',\n    options?: FeatureOperationOptions,\n    failureReason?: FailureReason\n  ) => {\n    bufferApiCalls.add((startRumResult) =>\n      startRumResult.addOperationStepVital(\n        sanitize(name)!,\n        stepType,\n        sanitize(options) as FeatureOperationOptions,\n        sanitize(failureReason) as FailureReason | undefined\n      )\n    )\n  }\n\n  const strategy: Strategy = {\n    init(initConfiguration, publicApi, errorStack) {\n      if (!initConfiguration) {\n        display.error('Missing configuration')\n        return\n      }\n      // Set the experimental feature flags as early as possible, so we can use them in most places\n      initFeatureFlags(initConfiguration.enableExperimentalFeatures)\n\n      // Expose the initial configuration regardless of initialization success.\n      cachedInitConfiguration = initConfiguration\n\n      // If we are in a Synthetics test configured to automatically inject a RUM instance, we want\n      // to completely discard the customer application RUM instance by ignoring their init() call.\n      // But, we should not ignore the init() call from the Synthetics-injected RUM instance, so the\n      // internal `ignoreInitIfSyntheticsWillInjectRum` option is here to bypass this condition.\n      if (ignoreInitIfSyntheticsWillInjectRum && willSyntheticsInjectRum()) {\n        return\n      }\n\n      callPluginsMethod(initConfiguration.plugins, 'onInit', { initConfiguration, publicApi })\n\n      if (initConfiguration.remoteConfigurationId) {\n        fetchAndApplyRemoteConfiguration(initConfiguration, { user: userContext, context: globalContext })\n          .then((initConfiguration) => {\n            if (initConfiguration) {\n              doInit(initConfiguration, errorStack)\n            }\n          })\n          .catch(monitorError)\n      } else {\n        doInit(initConfiguration, errorStack)\n      }\n    },\n\n    get initConfiguration() {\n      return cachedInitConfiguration\n    },\n\n    getInternalContext: noop as () => undefined,\n\n    stopSession: noop,\n\n    addTiming(name, time = timeStampNow()) {\n      bufferApiCalls.add((startRumResult) => startRumResult.addTiming(name, time))\n    },\n\n    setLoadingTime: ((callTimestamp: TimeStamp) => {\n      bufferApiCalls.add((startRumResult) => startRumResult.setLoadingTime(callTimestamp))\n    }) as Strategy['setLoadingTime'],\n\n    startView(options, startClocks = clocksNow()) {\n      const callback = (startRumResult: StartRumResult) => {\n        startRumResult.startView(options, startClocks)\n      }\n      bufferApiCalls.add(callback)\n\n      if (!firstStartViewCall) {\n        firstStartViewCall = { options, callback }\n        tryStartRum()\n      }\n    },\n\n    setViewName(name) {\n      bufferApiCalls.add((startRumResult) => startRumResult.setViewName(name))\n    },\n\n    // View context APIs\n\n    setViewContext(context) {\n      bufferApiCalls.add((startRumResult) => startRumResult.setViewContext(context))\n    },\n\n    setViewContextProperty(key, value) {\n      bufferApiCalls.add((startRumResult) => startRumResult.setViewContextProperty(key, value))\n    },\n\n    getViewContext: () => emptyContext,\n\n    globalContext,\n    userContext,\n    accountContext,\n\n    addAction(action) {\n      bufferApiCalls.add((startRumResult) => startRumResult.addAction(action))\n    },\n\n    startAction(name, options) {\n      const startClocks = clocksNow()\n      bufferApiCalls.add((startRumResult) => startRumResult.startAction(name, options, startClocks))\n    },\n\n    stopAction(name, options) {\n      const stopClocks = clocksNow()\n      bufferApiCalls.add((startRumResult) => startRumResult.stopAction(name, options, stopClocks))\n    },\n\n    startResource(url, options) {\n      const startClocks = clocksNow()\n      bufferApiCalls.add((startRumResult) => startRumResult.startResource(url, options, startClocks))\n    },\n\n    stopResource(url, options) {\n      const stopClocks = clocksNow()\n      bufferApiCalls.add((startRumResult) => startRumResult.stopResource(url, options, stopClocks))\n    },\n\n    addError(providedError) {\n      bufferApiCalls.add((startRumResult) => startRumResult.addError(providedError))\n    },\n\n    addFeatureFlagEvaluation(key, value) {\n      bufferApiCalls.add((startRumResult) => startRumResult.addFeatureFlagEvaluation(key, value))\n    },\n\n    startDurationVital(name, options) {\n      return startDurationVital(customVitalsState, name, options)\n    },\n\n    stopDurationVital(name, options) {\n      stopDurationVital(addDurationVital, customVitalsState, name, options)\n    },\n\n    addDurationVital,\n    addOperationStepVital,\n  }\n\n  return strategy\n}\n\nfunction overrideInitConfigurationForBridge(initConfiguration: RumInitConfiguration): RumInitConfiguration {\n  return {\n    ...initConfiguration,\n    applicationId: '00000000-aaaa-0000-aaaa-000000000000',\n    clientToken: 'empty',\n    sessionSampleRate: 100,\n    defaultPrivacyLevel: initConfiguration.defaultPrivacyLevel ?? getEventBridge()?.getPrivacyLevel(),\n  }\n}\n\nfunction bufferContextCalls(\n  preStartContextManager: ContextManager,\n  name: CustomerContextKey,\n  bufferApiCalls: BoundedBuffer<StartRumResult>\n) {\n  preStartContextManager.changeObservable.subscribe(() => {\n    const context = preStartContextManager.getContext()\n    bufferApiCalls.add((startRumResult) => startRumResult[name].setContext(context))\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/boot/rumPublicApi.spec.ts",
    "content": "import type { RelativeTime, DeflateWorker, TimeStamp } from '@datadog/browser-core'\nimport {\n  ONE_SECOND,\n  display,\n  DefaultPrivacyLevel,\n  timeStampToClocks,\n  ExperimentalFeature,\n  ResourceType,\n  startTelemetry,\n  addExperimentalFeatures,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { createFakeTelemetryObject, mockClock, replaceMockableWithSpy } from '@datadog/browser-core/test'\nimport { noopRecorderApi, noopProfilerApi } from '../../test'\nimport { ActionType, VitalType } from '../rawRumEvent.types'\nimport type { DurationVitalReference } from '../domain/vital/vitalCollection'\nimport type { RumPublicApi, RecorderApi, ProfilerApi, RumPublicApiOptions } from './rumPublicApi'\nimport { makeRumPublicApi } from './rumPublicApi'\nimport type { StartRum } from './startRum'\nimport { startRum } from './startRum'\n\nconst noopStartRum = (): ReturnType<StartRum> => ({\n  addAction: () => undefined,\n  addError: () => undefined,\n  addEvent: () => undefined,\n  addTiming: () => undefined,\n  setLoadingTime: () => undefined,\n  addFeatureFlagEvaluation: () => undefined,\n  startView: () => undefined,\n  setViewContext: () => undefined,\n  setViewContextProperty: () => undefined,\n  setViewName: () => undefined,\n  getViewContext: () => ({}),\n  getInternalContext: () => undefined,\n  lifeCycle: {} as any,\n  viewHistory: {} as any,\n  session: {} as any,\n  stopSession: () => undefined,\n  startDurationVital: () => ({}) as DurationVitalReference,\n  stopDurationVital: () => undefined,\n  addDurationVital: () => undefined,\n  stop: () => undefined,\n  globalContext: {} as any,\n  userContext: {} as any,\n  accountContext: {} as any,\n  hooks: {} as any,\n  telemetry: {} as any,\n  addOperationStepVital: () => undefined,\n  startAction: () => undefined,\n  stopAction: () => undefined,\n  startResource: () => undefined,\n  stopResource: () => undefined,\n})\nconst DEFAULT_INIT_CONFIGURATION = { applicationId: 'xxx', clientToken: 'xxx' }\nconst FAKE_WORKER = {} as DeflateWorker\n\ndescribe('rum public api', () => {\n  describe('init', () => {\n    describe('deflate worker', () => {\n      let rumPublicApi: RumPublicApi\n      let recorderApiOnRumStartSpy: jasmine.Spy<RecorderApi['onRumStart']>\n\n      beforeEach(() => {\n        recorderApiOnRumStartSpy = jasmine.createSpy()\n        ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n          recorderApi: {\n            onRumStart: recorderApiOnRumStartSpy,\n          },\n          rumPublicApiOptions: {\n            startDeflateWorker: () => FAKE_WORKER,\n          },\n        }))\n      })\n\n      it('passes addError to plugins on rum start', () => {\n        const plugin = { name: 'test-plugin', onRumStart: jasmine.createSpy() }\n\n        rumPublicApi.init({\n          ...DEFAULT_INIT_CONFIGURATION,\n          plugins: [plugin],\n        })\n\n        expect(plugin.onRumStart).toHaveBeenCalledWith(\n          jasmine.objectContaining({\n            addError: jasmine.any(Function),\n          })\n        )\n      })\n\n      it('pass the worker to the recorder API', () => {\n        rumPublicApi.init({\n          ...DEFAULT_INIT_CONFIGURATION,\n          compressIntakeRequests: true,\n        })\n        expect(recorderApiOnRumStartSpy.calls.mostRecent().args[4]).toBe(FAKE_WORKER)\n      })\n    })\n  })\n\n  describe('getInternalContext', () => {\n    let getInternalContextSpy: jasmine.Spy<ReturnType<StartRum>['getInternalContext']>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      getInternalContextSpy = jasmine.createSpy().and.callFake(() => ({\n        application_id: '123',\n        session_id: '123',\n      }))\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          getInternalContext: getInternalContextSpy,\n        },\n      }))\n    })\n\n    it('returns the internal context after init', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(rumPublicApi.getInternalContext()).toEqual({ application_id: '123', session_id: '123' })\n      expect(getInternalContextSpy).toHaveBeenCalled()\n    })\n\n    it('uses the startTime if specified', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      const startTime = 234832890\n      expect(rumPublicApi.getInternalContext(startTime)).toEqual({ application_id: '123', session_id: '123' })\n      expect(getInternalContextSpy).toHaveBeenCalledWith(startTime)\n    })\n  })\n\n  describe('getInitConfiguration', () => {\n    it('clones the init configuration', () => {\n      const { rumPublicApi } = makeRumPublicApiWithDefaults()\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(rumPublicApi.getInitConfiguration()).toEqual(DEFAULT_INIT_CONFIGURATION)\n      expect(rumPublicApi.getInitConfiguration()).not.toBe(DEFAULT_INIT_CONFIGURATION)\n    })\n  })\n\n  describe('addAction', () => {\n    let addActionSpy: jasmine.Spy<ReturnType<StartRum>['addAction']>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      addActionSpy = jasmine.createSpy()\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addAction: addActionSpy,\n        },\n      }))\n      mockClock()\n    })\n\n    it('allows sending actions before init', () => {\n      rumPublicApi.addAction('foo', { bar: 'baz' })\n\n      expect(addActionSpy).not.toHaveBeenCalled()\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(addActionSpy).toHaveBeenCalledTimes(1)\n      expect(addActionSpy.calls.argsFor(0)).toEqual([\n        {\n          context: { bar: 'baz' },\n          name: 'foo',\n          startClocks: jasmine.any(Object),\n          type: ActionType.CUSTOM,\n          handlingStack: jasmine.any(String),\n        },\n      ])\n    })\n\n    it('should generate a handling stack', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      function triggerAction() {\n        rumPublicApi.addAction('foo', { bar: 'baz' })\n      }\n\n      triggerAction()\n\n      expect(addActionSpy).toHaveBeenCalledTimes(1)\n      const stacktrace = addActionSpy.calls.argsFor(0)[0].handlingStack\n      expect(stacktrace).toMatch(/^HandlingStack: action\\s+at triggerAction @/)\n    })\n  })\n\n  describe('addError', () => {\n    let addErrorSpy: jasmine.Spy<ReturnType<StartRum>['addError']>\n    let rumPublicApi: RumPublicApi\n    let clock: Clock\n\n    beforeEach(() => {\n      addErrorSpy = jasmine.createSpy()\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addError: addErrorSpy,\n        },\n      }))\n      clock = mockClock()\n    })\n\n    it('allows capturing an error before init', () => {\n      rumPublicApi.addError(new Error('foo'))\n\n      expect(addErrorSpy).not.toHaveBeenCalled()\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(addErrorSpy).toHaveBeenCalledTimes(1)\n      expect(addErrorSpy.calls.argsFor(0)).toEqual([\n        {\n          context: undefined,\n          error: new Error('foo'),\n          handlingStack: jasmine.any(String),\n          startClocks: jasmine.any(Object),\n        },\n      ])\n    })\n\n    it('should generate a handling stack', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      function triggerError() {\n        rumPublicApi.addError(new Error('message'))\n      }\n\n      triggerError()\n      expect(addErrorSpy).toHaveBeenCalledTimes(1)\n      const stacktrace = addErrorSpy.calls.argsFor(0)[0].handlingStack\n      expect(stacktrace).toMatch(/^HandlingStack: error\\s+at triggerError (.|\\n)*$/)\n    })\n\n    describe('save context when capturing an error', () => {\n      it('saves the date', () => {\n        clock.tick(ONE_SECOND)\n        rumPublicApi.addError(new Error('foo'))\n\n        clock.tick(ONE_SECOND)\n        rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n        expect(addErrorSpy.calls.argsFor(0)[0].startClocks.relative as number).toEqual(clock.relative(ONE_SECOND))\n      })\n    })\n  })\n\n  describe('setUser', () => {\n    let addActionSpy: jasmine.Spy<ReturnType<StartRum>['addAction']>\n    let displaySpy: jasmine.Spy<() => void>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      addActionSpy = jasmine.createSpy()\n      displaySpy = spyOn(display, 'error')\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addAction: addActionSpy,\n        },\n      }))\n    })\n\n    it('should attach valid objects', () => {\n      const user = { id: 'foo', name: 'bar', email: 'qux', foo: { bar: 'qux' } }\n      rumPublicApi.setUser(user)\n\n      expect(rumPublicApi.getUser()).toEqual({\n        email: 'qux',\n        foo: { bar: 'qux' },\n        id: 'foo',\n        name: 'bar',\n      })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('should sanitize predefined properties', () => {\n      const user = { id: false, name: 2, email: { bar: 'qux' } }\n      rumPublicApi.setUser(user as any)\n      rumPublicApi.addAction('message')\n\n      expect(rumPublicApi.getUser()).toEqual({\n        email: '[object Object]',\n        id: 'false',\n        name: '2',\n      })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('should remove the user', () => {\n      const user = { id: 'foo', name: 'bar', email: 'qux' }\n      rumPublicApi.setUser(user)\n      rumPublicApi.clearUser()\n      rumPublicApi.addAction('message')\n\n      expect(rumPublicApi.getUser()).toEqual({})\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('should reject non object input', () => {\n      rumPublicApi.setUser(2 as any)\n      rumPublicApi.setUser(null as any)\n      rumPublicApi.setUser(undefined as any)\n      expect(displaySpy).toHaveBeenCalledTimes(3)\n    })\n  })\n\n  describe('getUser', () => {\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults())\n    })\n\n    it('should return empty object if no user has been set', () => {\n      const userClone = rumPublicApi.getUser()\n      expect(userClone).toEqual({})\n    })\n\n    it('should return a clone of the original object if set', () => {\n      const user = { id: 'foo', name: 'bar', email: 'qux', foo: { bar: 'qux' } }\n      rumPublicApi.setUser(user)\n      const userClone = rumPublicApi.getUser()\n      const userClone2 = rumPublicApi.getUser()\n\n      expect(userClone).not.toBe(user)\n      expect(userClone).not.toBe(userClone2)\n      expect(userClone).toEqual(user)\n    })\n  })\n\n  describe('setUserProperty', () => {\n    const user = { id: 'foo', name: 'bar', email: 'qux', foo: { bar: 'qux' } }\n    const addressAttribute = { city: 'Paris' }\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults())\n    })\n\n    it('should add attribute', () => {\n      rumPublicApi.setUser(user)\n      rumPublicApi.setUserProperty('address', addressAttribute)\n      const userClone = rumPublicApi.getUser()\n\n      expect(userClone.address).toEqual(addressAttribute)\n    })\n\n    it('should not contain original reference to object', () => {\n      const userDetails: { [key: string]: any } = { name: 'john' }\n      rumPublicApi.setUser(user)\n      rumPublicApi.setUserProperty('userDetails', userDetails)\n      userDetails.DOB = '11/11/1999'\n      const userClone = rumPublicApi.getUser()\n\n      expect(userClone.userDetails).not.toBe(userDetails)\n    })\n\n    it('should override attribute', () => {\n      rumPublicApi.setUser(user)\n      rumPublicApi.setUserProperty('foo', addressAttribute)\n      const userClone = rumPublicApi.getUser()\n\n      expect(userClone).toEqual({ ...user, foo: addressAttribute })\n    })\n\n    it('should sanitize properties', () => {\n      rumPublicApi.setUserProperty('id', 123)\n      rumPublicApi.setUserProperty('name', ['Adam', 'Smith'])\n      rumPublicApi.setUserProperty('email', { foo: 'bar' })\n      const userClone = rumPublicApi.getUser()\n\n      expect(userClone.id).toEqual('123')\n      expect(userClone.name).toEqual('Adam,Smith')\n      expect(userClone.email).toEqual('[object Object]')\n    })\n  })\n\n  describe('removeUserProperty', () => {\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults())\n    })\n\n    it('should remove property', () => {\n      const user = { id: 'foo', name: 'bar', email: 'qux', foo: { bar: 'qux' } }\n\n      rumPublicApi.setUser(user)\n      rumPublicApi.removeUserProperty('foo')\n      const userClone = rumPublicApi.getUser()\n      expect(userClone.foo).toBeUndefined()\n    })\n  })\n\n  describe('setAccount', () => {\n    let addActionSpy: jasmine.Spy<ReturnType<StartRum>['addAction']>\n    let displaySpy: jasmine.Spy<() => void>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      addActionSpy = jasmine.createSpy()\n      displaySpy = spyOn(display, 'error')\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addAction: addActionSpy,\n        },\n      }))\n    })\n\n    it('should attach valid objects', () => {\n      const account = { id: 'foo', name: 'bar', foo: { bar: 'qux' } }\n      rumPublicApi.setAccount(account)\n      rumPublicApi.addAction('message')\n\n      expect(rumPublicApi.getAccount()).toEqual({\n        foo: { bar: 'qux' },\n        id: 'foo',\n        name: 'bar',\n      })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('should sanitize predefined properties', () => {\n      const account = { id: false, name: 2 }\n      rumPublicApi.setAccount(account as any)\n      rumPublicApi.addAction('message')\n\n      expect(rumPublicApi.getAccount()).toEqual({\n        id: 'false',\n        name: '2',\n      })\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('should remove the account', () => {\n      const account = { id: 'foo', name: 'bar' }\n      rumPublicApi.setAccount(account)\n      rumPublicApi.clearAccount()\n      rumPublicApi.addAction('message')\n\n      expect(rumPublicApi.getAccount()).toEqual({})\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('should reject non object input', () => {\n      rumPublicApi.setAccount(2 as any)\n      rumPublicApi.setAccount(null as any)\n      rumPublicApi.setAccount(undefined as any)\n      expect(displaySpy).toHaveBeenCalledTimes(3)\n    })\n  })\n\n  describe('getAccount', () => {\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults())\n    })\n\n    it('should return empty object if no account has been set', () => {\n      const accountClone = rumPublicApi.getAccount()\n      expect(accountClone).toEqual({})\n    })\n\n    it('should return a clone of the original object if set', () => {\n      const account = { id: 'foo', name: 'bar', foo: { bar: 'qux' } }\n      rumPublicApi.setAccount(account)\n      const accountClone = rumPublicApi.getAccount()\n      const accountClone2 = rumPublicApi.getAccount()\n\n      expect(accountClone).not.toBe(account)\n      expect(accountClone).not.toBe(accountClone2)\n      expect(accountClone).toEqual(account)\n    })\n  })\n\n  describe('setAccountProperty', () => {\n    const account = { id: 'foo', name: 'bar', foo: { bar: 'qux' } }\n    const addressAttribute = { city: 'Paris' }\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults())\n    })\n\n    it('should add attribute', () => {\n      rumPublicApi.setAccount(account)\n      rumPublicApi.setAccountProperty('address', addressAttribute)\n      const accountClone = rumPublicApi.getAccount()\n\n      expect(accountClone.address).toEqual(addressAttribute)\n    })\n\n    it('should not contain original reference to object', () => {\n      const accountDetails: { [key: string]: any } = { name: 'company' }\n      rumPublicApi.setAccount(account)\n      rumPublicApi.setAccountProperty('accountDetails', accountDetails)\n      const accountClone = rumPublicApi.getAccount()\n\n      expect(accountClone.accountDetails).not.toBe(accountDetails)\n    })\n\n    it('should override attribute', () => {\n      rumPublicApi.setAccount(account)\n      rumPublicApi.setAccountProperty('foo', addressAttribute)\n      const accountClone = rumPublicApi.getAccount()\n\n      expect(accountClone).toEqual({ ...account, foo: addressAttribute })\n    })\n\n    it('should sanitize properties', () => {\n      rumPublicApi.setAccountProperty('id', 123)\n      rumPublicApi.setAccountProperty('name', ['My', 'Company'])\n      const accountClone = rumPublicApi.getAccount()\n\n      expect(accountClone.id).toEqual('123')\n      expect(accountClone.name).toEqual('My,Company')\n    })\n  })\n\n  describe('removeAccountProperty', () => {\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults())\n    })\n\n    it('should remove property', () => {\n      const account = { id: 'foo', name: 'bar', email: 'qux', foo: { bar: 'qux' } }\n\n      rumPublicApi.setAccount(account)\n      rumPublicApi.removeAccountProperty('foo')\n      const accountClone = rumPublicApi.getAccount()\n      expect(accountClone.foo).toBeUndefined()\n    })\n  })\n\n  describe('addTiming', () => {\n    let addTimingSpy: jasmine.Spy<ReturnType<StartRum>['addTiming']>\n    let displaySpy: jasmine.Spy<() => void>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      addTimingSpy = jasmine.createSpy()\n      displaySpy = spyOn(display, 'error')\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addTiming: addTimingSpy,\n        },\n      }))\n    })\n\n    it('should add custom timings', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      rumPublicApi.addTiming('foo')\n\n      expect(addTimingSpy.calls.argsFor(0)[0]).toEqual('foo')\n      expect(addTimingSpy.calls.argsFor(0)[1]).toBeUndefined()\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n\n    it('adds custom timing with provided time', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      rumPublicApi.addTiming('foo', 12)\n\n      expect(addTimingSpy.calls.argsFor(0)[0]).toEqual('foo')\n      expect(addTimingSpy.calls.argsFor(0)[1]).toBe(12 as RelativeTime)\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('setViewLoadingTime', () => {\n    let setLoadingTimeSpy: jasmine.Spy<ReturnType<StartRum>['setLoadingTime']>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      setLoadingTimeSpy = jasmine.createSpy()\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          setLoadingTime: setLoadingTimeSpy,\n        },\n      }))\n    })\n\n    it('should call setLoadingTime with timestamp', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      rumPublicApi.setViewLoadingTime()\n\n      expect(setLoadingTimeSpy).toHaveBeenCalledOnceWith(jasmine.any(Number))\n    })\n\n    it('should not throw when called before init', () => {\n      expect(() => rumPublicApi.setViewLoadingTime()).not.toThrow()\n\n      expect(setLoadingTimeSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('addFeatureFlagEvaluation', () => {\n    let addFeatureFlagEvaluationSpy: jasmine.Spy<ReturnType<StartRum>['addFeatureFlagEvaluation']>\n    let displaySpy: jasmine.Spy<() => void>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      addFeatureFlagEvaluationSpy = jasmine.createSpy()\n      displaySpy = spyOn(display, 'error')\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addFeatureFlagEvaluation: addFeatureFlagEvaluationSpy,\n        },\n      }))\n    })\n\n    it('should add feature flag evaluation when ff feature_flags enabled', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      rumPublicApi.addFeatureFlagEvaluation('feature', 'foo')\n\n      expect(addFeatureFlagEvaluationSpy.calls.argsFor(0)).toEqual(['feature', 'foo'])\n      expect(displaySpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('stopSession', () => {\n    it('calls stopSession on the startRum result', () => {\n      const stopSessionSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          stopSession: stopSessionSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.stopSession()\n      expect(stopSessionSpy).toHaveBeenCalled()\n    })\n  })\n\n  describe('startView', () => {\n    it('should call RUM results startView with the view name', () => {\n      const startViewSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startView: startViewSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startView('foo')\n      expect(startViewSpy.calls.argsFor(0)[0]).toEqual({ name: 'foo', handlingStack: jasmine.any(String) })\n    })\n\n    it('should call RUM results startView with the view options', () => {\n      const startViewSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startView: startViewSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startView({ name: 'foo', service: 'bar', version: 'baz', context: { foo: 'bar' } })\n      expect(startViewSpy.calls.argsFor(0)[0]).toEqual({\n        name: 'foo',\n        service: 'bar',\n        version: 'baz',\n        context: { foo: 'bar' },\n        handlingStack: jasmine.any(String),\n      })\n    })\n  })\n\n  describe('recording', () => {\n    let rumPublicApi: RumPublicApi\n    let recorderApi: {\n      onRumStart: jasmine.Spy<RecorderApi['onRumStart']>\n      start: jasmine.Spy\n      stop: jasmine.Spy\n      getSessionReplayLink: jasmine.Spy\n    }\n\n    beforeEach(() => {\n      recorderApi = {\n        onRumStart: jasmine.createSpy(),\n        start: jasmine.createSpy(),\n        stop: jasmine.createSpy(),\n        getSessionReplayLink: jasmine.createSpy(),\n      }\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({ recorderApi }))\n    })\n\n    it('is started with the default defaultPrivacyLevel', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      expect(recorderApi.onRumStart.calls.mostRecent().args[1].defaultPrivacyLevel).toBe(DefaultPrivacyLevel.MASK)\n    })\n\n    it('is started with the configured defaultPrivacyLevel', () => {\n      rumPublicApi.init({\n        ...DEFAULT_INIT_CONFIGURATION,\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK_USER_INPUT,\n      })\n      expect(recorderApi.onRumStart.calls.mostRecent().args[1].defaultPrivacyLevel).toBe(\n        DefaultPrivacyLevel.MASK_USER_INPUT\n      )\n    })\n\n    it('public api calls are forwarded to the recorder api', () => {\n      rumPublicApi.startSessionReplayRecording()\n      rumPublicApi.stopSessionReplayRecording()\n      rumPublicApi.getSessionReplayLink()\n\n      expect(recorderApi.start).toHaveBeenCalledTimes(1)\n      expect(recorderApi.stop).toHaveBeenCalledTimes(1)\n      expect(recorderApi.getSessionReplayLink).toHaveBeenCalledTimes(1)\n    })\n\n    it('is started with the default startSessionReplayRecordingManually', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      expect(recorderApi.onRumStart.calls.mostRecent().args[1].startSessionReplayRecordingManually).toBe(true)\n    })\n\n    it('is started with the configured startSessionReplayRecordingManually', () => {\n      rumPublicApi.init({\n        ...DEFAULT_INIT_CONFIGURATION,\n        startSessionReplayRecordingManually: false,\n      })\n      expect(recorderApi.onRumStart.calls.mostRecent().args[1].startSessionReplayRecordingManually).toBe(false)\n    })\n  })\n\n  describe('startDurationVital', () => {\n    it('should call startDurationVital on the startRum result', () => {\n      const startDurationVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startDurationVital: startDurationVitalSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startDurationVital('foo', { context: { foo: 'bar' }, description: 'description-value' })\n      expect(startDurationVitalSpy).toHaveBeenCalledWith('foo', {\n        description: 'description-value',\n        context: { foo: 'bar' },\n        handlingStack: jasmine.any(String),\n      })\n    })\n  })\n\n  describe('stopDurationVital', () => {\n    it('should call stopDurationVital with a name on the startRum result', () => {\n      const stopDurationVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          stopDurationVital: stopDurationVitalSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startDurationVital('foo', { context: { foo: 'bar' }, description: 'description-value' })\n      rumPublicApi.stopDurationVital('foo', { context: { foo: 'bar' }, description: 'description-value' })\n      expect(stopDurationVitalSpy).toHaveBeenCalledWith('foo', {\n        description: 'description-value',\n        context: { foo: 'bar' },\n      })\n    })\n\n    it('should call stopDurationVital with a reference on the startRum result', () => {\n      const stopDurationVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          stopDurationVital: stopDurationVitalSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      const ref = rumPublicApi.startDurationVital('foo', { context: { foo: 'bar' }, description: 'description-value' })\n      rumPublicApi.stopDurationVital(ref, { context: { foo: 'bar' }, description: 'description-value' })\n      expect(stopDurationVitalSpy).toHaveBeenCalledWith(ref, {\n        description: 'description-value',\n        context: { foo: 'bar' },\n      })\n    })\n  })\n\n  describe('startAction / stopAction', () => {\n    it('should call startAction and stopAction on the strategy', () => {\n      addExperimentalFeatures([ExperimentalFeature.START_STOP_ACTION])\n\n      const startActionSpy = jasmine.createSpy()\n      const stopActionSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startAction: startActionSpy,\n          stopAction: stopActionSpy,\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startAction('purchase', {\n        type: ActionType.CUSTOM,\n        context: { cart: 'abc' },\n      })\n      rumPublicApi.stopAction('purchase', {\n        context: { total: 100 },\n      })\n\n      expect(startActionSpy).toHaveBeenCalledWith(\n        'purchase',\n        jasmine.objectContaining({\n          type: ActionType.CUSTOM,\n          context: { cart: 'abc' },\n        })\n      )\n      expect(stopActionSpy).toHaveBeenCalledWith(\n        'purchase',\n        jasmine.objectContaining({\n          context: { total: 100 },\n        })\n      )\n    })\n\n    it('should sanitize startAction and stopAction inputs', () => {\n      addExperimentalFeatures([ExperimentalFeature.START_STOP_ACTION])\n\n      const startActionSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startAction: startActionSpy,\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startAction('action_name', {\n        type: ActionType.CUSTOM,\n        context: { count: 123, nested: { foo: 'bar' } } as any,\n        actionKey: 'action_key',\n      })\n\n      expect(startActionSpy.calls.argsFor(0)[1]).toEqual(\n        jasmine.objectContaining({\n          type: ActionType.CUSTOM,\n          context: { count: 123, nested: { foo: 'bar' } },\n          actionKey: 'action_key',\n        })\n      )\n    })\n\n    it('should not call startAction/stopAction when feature flag is disabled', () => {\n      const startActionSpy = jasmine.createSpy()\n      const stopActionSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startAction: startActionSpy,\n          stopAction: stopActionSpy,\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startAction('purchase', { type: ActionType.CUSTOM })\n      rumPublicApi.stopAction('purchase')\n\n      expect(startActionSpy).not.toHaveBeenCalled()\n      expect(stopActionSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('startResource / stopResource', () => {\n    it('should call startResource and stopResource on the strategy', () => {\n      addExperimentalFeatures([ExperimentalFeature.START_STOP_RESOURCE])\n\n      const startResourceSpy = jasmine.createSpy()\n      const stopResourceSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startResource: startResourceSpy,\n          stopResource: stopResourceSpy,\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startResource('https://api.example.com/data', {\n        type: ResourceType.FETCH,\n        method: 'POST',\n        context: { requestId: 'abc' },\n      })\n      rumPublicApi.stopResource('https://api.example.com/data', {\n        type: ResourceType.XHR,\n        statusCode: 200,\n        size: 1024,\n        context: { requestId: 'abc' },\n      })\n\n      expect(startResourceSpy).toHaveBeenCalledWith(\n        'https://api.example.com/data',\n        jasmine.objectContaining({\n          type: ResourceType.FETCH,\n          method: 'POST',\n          context: { requestId: 'abc' },\n        })\n      )\n      expect(stopResourceSpy).toHaveBeenCalledWith(\n        'https://api.example.com/data',\n        jasmine.objectContaining({\n          type: ResourceType.XHR,\n          statusCode: 200,\n          size: 1024,\n          context: { requestId: 'abc' },\n        })\n      )\n    })\n\n    it('should sanitize startResource and stopResource inputs', () => {\n      addExperimentalFeatures([ExperimentalFeature.START_STOP_RESOURCE])\n\n      const startResourceSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startResource: startResourceSpy,\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startResource('https://api.example.com/data', {\n        type: ResourceType.XHR,\n        method: 'GET',\n        context: { count: 123, nested: { foo: 'bar' } } as any,\n        resourceKey: 'resource_key',\n      })\n\n      expect(startResourceSpy.calls.argsFor(0)[1]).toEqual(\n        jasmine.objectContaining({\n          type: ResourceType.XHR,\n          method: 'GET',\n          context: { count: 123, nested: { foo: 'bar' } },\n          resourceKey: 'resource_key',\n        })\n      )\n    })\n\n    it('should not call startResource/stopResource when feature flag is disabled', () => {\n      const startResourceSpy = jasmine.createSpy()\n      const stopResourceSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          startResource: startResourceSpy,\n          stopResource: stopResourceSpy,\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startResource('https://api.example.com/data', { type: ResourceType.FETCH })\n      rumPublicApi.stopResource('https://api.example.com/data')\n\n      expect(startResourceSpy).not.toHaveBeenCalled()\n      expect(stopResourceSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('addDurationVital', () => {\n    it('should call addDurationVital on the startRum result', () => {\n      const addDurationVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addDurationVital: addDurationVitalSpy,\n        },\n      })\n      const startTime = 1707755888000 as TimeStamp\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.addDurationVital('foo', {\n        startTime,\n        duration: 100,\n        context: { foo: 'bar' },\n        description: 'description-value',\n      })\n      expect(addDurationVitalSpy).toHaveBeenCalledWith({\n        id: jasmine.any(String),\n        name: 'foo',\n        startClocks: timeStampToClocks(startTime),\n        duration: 100,\n        context: { foo: 'bar' },\n        description: 'description-value',\n        handlingStack: jasmine.any(String),\n        type: VitalType.DURATION,\n      })\n    })\n  })\n\n  describe('startFeatureOperation', () => {\n    it('should call addOperationStepVital on the startRum result with start status', () => {\n      const addOperationStepVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addOperationStepVital: addOperationStepVitalSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.startFeatureOperation('foo', { operationKey: '00000000-0000-0000-0000-000000000000' })\n      expect(addOperationStepVitalSpy).toHaveBeenCalledWith('foo', 'start', {\n        operationKey: '00000000-0000-0000-0000-000000000000',\n        handlingStack: jasmine.any(String),\n      })\n    })\n  })\n\n  describe('succeedFeatureOperation', () => {\n    it('should call addOperationStepVital on the startRum result with end status', () => {\n      const addOperationStepVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addOperationStepVital: addOperationStepVitalSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.succeedFeatureOperation('foo', { operationKey: '00000000-0000-0000-0000-000000000000' })\n      expect(addOperationStepVitalSpy).toHaveBeenCalledWith('foo', 'end', {\n        operationKey: '00000000-0000-0000-0000-000000000000',\n      })\n    })\n  })\n\n  describe('failFeatureOperation', () => {\n    it('should call addOperationStepVital on the startRum result with end status and failure reason', () => {\n      const addOperationStepVitalSpy = jasmine.createSpy()\n      const { rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          addOperationStepVital: addOperationStepVitalSpy,\n        },\n      })\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.failFeatureOperation('foo', 'error', { operationKey: '00000000-0000-0000-0000-000000000000' })\n      expect(addOperationStepVitalSpy).toHaveBeenCalledWith(\n        'foo',\n        'end',\n        { operationKey: '00000000-0000-0000-0000-000000000000' },\n        'error'\n      )\n    })\n  })\n\n  it('should provide sdk version', () => {\n    const { rumPublicApi } = makeRumPublicApiWithDefaults()\n    expect(rumPublicApi.version).toBe('test')\n  })\n\n  describe('setViewName', () => {\n    let setViewNameSpy: jasmine.Spy<ReturnType<StartRum>['setViewName']>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      setViewNameSpy = jasmine.createSpy()\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          setViewName: setViewNameSpy,\n        },\n      }))\n    })\n\n    it('should set the view name', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      rumPublicApi.setViewName('foo')\n\n      expect(setViewNameSpy).toHaveBeenCalledWith('foo')\n    })\n  })\n\n  describe('set view specific context', () => {\n    let rumPublicApi: RumPublicApi\n    let setViewContextSpy: jasmine.Spy<ReturnType<StartRum>['setViewContext']>\n    let setViewContextPropertySpy: jasmine.Spy<ReturnType<StartRum>['setViewContextProperty']>\n    beforeEach(() => {\n      setViewContextSpy = jasmine.createSpy()\n      setViewContextPropertySpy = jasmine.createSpy()\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          setViewContext: setViewContextSpy,\n          setViewContextProperty: setViewContextPropertySpy,\n        },\n      }))\n    })\n\n    it('should set view specific context with setViewContext', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      /* eslint-disable @typescript-eslint/no-unsafe-call */\n      ;(rumPublicApi as any).setViewContext({ foo: 'bar' })\n\n      expect(setViewContextSpy).toHaveBeenCalledWith({ foo: 'bar' })\n    })\n\n    it('should set view specific context with setViewContextProperty', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      /* eslint-disable @typescript-eslint/no-unsafe-call */\n      ;(rumPublicApi as any).setViewContextProperty('foo', 'bar')\n\n      expect(setViewContextPropertySpy).toHaveBeenCalledWith('foo', 'bar')\n    })\n  })\n\n  describe('getViewContext', () => {\n    let getViewContextSpy: jasmine.Spy<ReturnType<StartRum>['getViewContext']>\n    let rumPublicApi: RumPublicApi\n\n    beforeEach(() => {\n      getViewContextSpy = jasmine.createSpy().and.callFake(() => ({\n        foo: 'bar',\n      }))\n      ;({ rumPublicApi } = makeRumPublicApiWithDefaults({\n        startRumResult: {\n          getViewContext: getViewContextSpy,\n        },\n      }))\n    })\n\n    it('should return the view context after init', () => {\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n\n      expect(rumPublicApi.getViewContext()).toEqual({ foo: 'bar' })\n      expect(getViewContextSpy).toHaveBeenCalled()\n    })\n\n    it('should return an empty object before init', () => {\n      expect(rumPublicApi.getViewContext()).toEqual({})\n      expect(getViewContextSpy).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('it should pass down the sdk name to startRum', () => {\n    it('should return the sdk name', () => {\n      const { rumPublicApi, startRumSpy } = makeRumPublicApiWithDefaults({\n        rumPublicApiOptions: {\n          sdkName: 'rum-slim',\n        },\n      })\n\n      rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)\n      const sdkName = startRumSpy.calls.argsFor(0)[10]\n      expect(sdkName).toBe('rum-slim')\n    })\n  })\n})\n\nfunction makeRumPublicApiWithDefaults({\n  recorderApi,\n  profilerApi,\n  startRumResult,\n  rumPublicApiOptions = {},\n}: {\n  recorderApi?: Partial<RecorderApi>\n  profilerApi?: Partial<ProfilerApi>\n  startRumResult?: Partial<ReturnType<StartRum>>\n  rumPublicApiOptions?: RumPublicApiOptions\n} = {}) {\n  const startRumSpy = replaceMockableWithSpy(startRum).and.callFake(() => ({\n    ...noopStartRum(),\n    ...startRumResult,\n  }))\n  replaceMockableWithSpy(startTelemetry).and.callFake(createFakeTelemetryObject)\n  return {\n    startRumSpy,\n    rumPublicApi: makeRumPublicApi(\n      { ...noopRecorderApi, ...recorderApi },\n      { ...noopProfilerApi, ...profilerApi },\n      rumPublicApiOptions\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/boot/rumPublicApi.ts",
    "content": "import type {\n  Context,\n  TimeStamp,\n  RelativeTime,\n  DeflateWorker,\n  DeflateEncoderStreamId,\n  DeflateEncoder,\n  PublicApi,\n  Duration,\n  ContextManager,\n  TrackingConsent,\n  User,\n  Account,\n  RumInternalContext,\n  Telemetry,\n  Encoder,\n  ResourceType,\n} from '@datadog/browser-core'\nimport {\n  ContextManagerMethod,\n  addTelemetryUsage,\n  deepClone,\n  makePublicApi,\n  monitor,\n  clocksNow,\n  callMonitored,\n  createHandlingStack,\n  sanitize,\n  createIdentityEncoder,\n  displayAlreadyInitializedError,\n  createTrackingConsentState,\n  timeStampToClocks,\n  CustomerContextKey,\n  defineContextMethod,\n  startBufferingData,\n  isExperimentalFeatureEnabled,\n  ExperimentalFeature,\n  mockable,\n  generateUUID,\n  timeStampNow,\n} from '@datadog/browser-core'\n\nimport type { LifeCycle } from '../domain/lifeCycle'\nimport type { ViewHistory } from '../domain/contexts/viewHistory'\nimport type { RumSessionManager } from '../domain/rumSessionManager'\nimport type { ReplayStats } from '../rawRumEvent.types'\nimport { ActionType, VitalType } from '../rawRumEvent.types'\nimport type { RumConfiguration, RumInitConfiguration } from '../domain/configuration'\nimport type { ViewOptions } from '../domain/view/trackViews'\nimport type {\n  AddDurationVitalOptions,\n  DurationVitalReference,\n  DurationVitalOptions,\n  FeatureOperationOptions,\n  FailureReason,\n} from '../domain/vital/vitalCollection'\nimport { createCustomVitalsState } from '../domain/vital/vitalCollection'\nimport { callPluginsMethod } from '../domain/plugins'\nimport type { Hooks } from '../domain/hooks'\nimport type { SdkName } from '../domain/contexts/defaultContext'\nimport type { ActionOptions } from '../domain/action/trackManualActions'\nimport type { ResourceOptions, ResourceStopOptions } from '../domain/resource/trackManualResources'\nimport { createPreStartStrategy } from './preStartRum'\nimport type { StartRumResult } from './startRum'\nimport { startRum } from './startRum'\n\nexport interface StartRecordingOptions {\n  force: boolean\n}\n\n/**\n * Public API for the RUM browser SDK.\n *\n * See [RUM Browser Monitoring Setup](https://docs.datadoghq.com/real_user_monitoring/browser) for further information.\n *\n * @category Main\n */\nexport interface RumPublicApi extends PublicApi {\n  /**\n   * Init the RUM browser SDK.\n   *\n   * See [RUM Browser Monitoring Setup](https://docs.datadoghq.com/real_user_monitoring/browser) for further information.\n   *\n   * @category Init\n   * @param initConfiguration - Configuration options of the SDK\n   * @example\n   * ```ts\n   * datadogRum.init({\n   *   applicationId: '<DATADOG_APPLICATION_ID>',\n   *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n   *   site: '<DATADOG_SITE>',\n   *   // ...\n   * })\n   * ```\n   */\n  init: (initConfiguration: RumInitConfiguration) => void\n\n  /**\n   * Set the tracking consent of the current user.\n   *\n   * Data will be sent only if it is set to \"granted\". This value won't be stored by the library\n   * across page loads: you will need to call this method or set the appropriate `trackingConsent`\n   * field in the init() method at each page load.\n   *\n   * If this method is called before the init() method, the provided value will take precedence\n   * over the one provided as initialization parameter.\n   *\n   * See [User tracking consent](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#user-tracking-consent) for further information.\n   *\n   * @category Privacy\n   * @param trackingConsent - The user tracking consent\n   */\n  setTrackingConsent: (trackingConsent: TrackingConsent) => void\n\n  /**\n   * Set View Name.\n   *\n   * Enable to manually change the name of the current view.\n   * See [Override default RUM view names](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#override-default-rum-view-names) for further information.\n   *\n   * @category Context - View\n   * @param name - Name of the view\n   */\n  setViewName: (name: string) => void\n\n  /**\n   * Set View Context.\n   *\n   * Enable to manually set the context of the current view.\n   *\n   * @category Context - View\n   * @param context - Context of the view\n   */\n  setViewContext: (context: Context) => void\n  /**\n   * Set View Context Property.\n   *\n   * Enable to manually set a property of the context of the current view.\n   *\n   * @category Context - View\n   * @param key - key of the property\n   * @param value - value of the property\n   */\n  setViewContextProperty: (key: string, value: any) => void\n\n  /**\n   * Get View Context.\n   *\n   * @category Context - View\n   */\n  getViewContext(): Context\n\n  /**\n   * [Internal API] Get the internal SDK context\n   *\n   * @internal\n   */\n  getInternalContext: (startTime?: number) => RumInternalContext | undefined\n\n  /**\n   * Get the init configuration\n   *\n   * @category Init\n   * @returns RumInitConfiguration | undefined\n   */\n  getInitConfiguration: () => RumInitConfiguration | undefined\n\n  /**\n   * Add a custom action, stored in `@action`\n   *\n   * See [Send RUM Custom Actions](https://docs.datadoghq.com/real_user_monitoring/guide/send-rum-custom-actions) for further information.\n   *\n   * @category Data Collection\n   * @param name - Name of the action\n   * @param context - Context of the action\n   */\n  addAction: (name: string, context?: object) => void\n\n  /**\n   * [Experimental] Start an action, stored in `@action`\n   *\n   * @category Data Collection\n   * @param name - Name of the action\n   * @param options - Options of the action (@default type: 'custom')\n   */\n  startAction: (name: string, options?: ActionOptions) => void\n\n  /**\n   * [Experimental] Stop an action, stored in `@action`\n   *\n   * @category Data Collection\n   * @param name - Name of the action\n   * @param options - Options of the action\n   */\n  stopAction: (name: string, options?: ActionOptions) => void\n\n  /**\n   * [Experimental] Start tracking a resource, stored in `@resource`\n   *\n   * @category Data Collection\n   * @param url - URL of the resource\n   * @param options - Options of the resource (@default type: 'other')\n   */\n  startResource: (url: string, options?: ResourceOptions) => void\n\n  /**\n   * [Experimental] Stop tracking a resource, stored in `@resource`\n   *\n   * @category Data Collection\n   * @param url - URL of the resource\n   * @param options - Options of the resource\n   */\n  stopResource: (url: string, options?: ResourceStopOptions) => void\n\n  /**\n   * Add a custom error, stored in `@error`.\n   *\n   * See [Send RUM Custom Actions](https://docs.datadoghq.com/real_user_monitoring/guide/send-rum-custom-actions) for further information.\n   *\n   * @category Data Collection\n   * @param error - Error. Favor sending a [Javascript Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) to have a stack trace attached to the error event.\n   * @param context - Context of the error\n   */\n  addError: (error: unknown, context?: object) => void\n\n  /**\n   * Add a custom timing relative to the start of the current view,\n   * stored in `@view.custom_timings.<timing_name>`\n   *\n   * Note: passing a relative time is discouraged since it is actually used as-is but displayed relative to the view start.\n   * We currently don't provide a way to retrieve the view start time, so it can be challenging to provide a timing relative to the view start.\n   * see https://github.com/DataDog/browser-sdk/issues/2552\n   *\n   * @category Data Collection\n   * @param name - Name of the custom timing\n   * @param [time] - Epoch timestamp of the custom timing (if not set, will use current time)\n   */\n  addTiming: (name: string, time?: number) => void\n\n  /**\n   * [Experimental] Manually set the current view's loading time.\n   *\n   * Call this method when the view has finished loading. The loading time is computed as the\n   * elapsed time since the view started. Each call replaces any previously set value (last-call-wins).\n   *\n   * @category Data Collection\n   */\n  setViewLoadingTime: () => void\n\n  /**\n   * Set the global context information to all events, stored in `@context`\n   * See [Global context](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#global-context) for further information.\n   *\n   * @category Context - Global Context\n   * @param context - Global context\n   */\n  setGlobalContext: (context: Context) => void\n\n  /**\n   * Get the global Context\n   *\n   * See [Global context](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#global-context) for further information.\n   *\n   * @category Context - Global Context\n   */\n  getGlobalContext: () => Context\n\n  /**\n   * Set or update a global context property, stored in `@context.<key>`\n   *\n   * See [Global context](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#global-context) for further information.\n   *\n   * @category Context - Global Context\n   * @param key - Key of the property\n   * @param value - Value of the property\n   */\n  setGlobalContextProperty: (key: any, value: any) => void\n\n  /**\n   * Remove a global context property\n   *\n   * See [Global context](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#global-context) for further information.\n   *\n   * @category Context - Global Context\n   */\n  removeGlobalContextProperty: (key: any) => void\n\n  /**\n   * Clear the global context\n   *\n   * See [Global context](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#global-context) for further information.\n   *\n   * @category Context - Global Context\n   */\n  clearGlobalContext(): void\n\n  /**\n   * Set user information to all events, stored in `@usr`\n   *\n   * See [User session](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#user-session) for further information.\n   *\n   * @category Context - User\n   * @param newUser - User information\n   */\n  setUser(newUser: User & { id: string }): void\n\n  /**\n   * Set user information to all events, stored in `@usr`\n   *\n   * @category Context - User\n   * @deprecated You must specify a user id, favor using {@link setUser} instead\n   * @param newUser - User information with optional id\n   */\n  setUser(newUser: User): void\n\n  /**\n   * Get user information\n   *\n   * See [User session](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#user-session) for further information.\n   *\n   * @category Context - User\n   * @returns User information\n   */\n  getUser: () => Context\n\n  /**\n   * Set or update the user property, stored in `@usr.<key>`\n   *\n   * See [User session](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#user-session) for further information.\n   *\n   * @category Context - User\n   * @param key - Key of the property\n   * @param property - Value of the property\n   */\n  setUserProperty: (key: any, property: any) => void\n\n  /**\n   * Remove a user property\n   *\n   * @category Context - User\n   * @param key - Key of the property to remove\n   * @see [User session](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#user-session) for further information.\n   */\n  removeUserProperty: (key: any) => void\n\n  /**\n   * Clear all user information\n   *\n   * See [User session](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#user-session) for further information.\n   *\n   * @category Context - User\n   */\n  clearUser: () => void\n\n  /**\n   * Set account information to all events, stored in `@account`\n   *\n   * @category Context - Account\n   * @param newAccount - Account information\n   */\n  setAccount: (newAccount: Account) => void\n\n  /**\n   * Get account information\n   *\n   * @category Context - Account\n   * @returns Account information\n   */\n  getAccount: () => Context\n\n  /**\n   * Set or update the account property, stored in `@account.<key>`\n   *\n   * @category Context - Account\n   * @param key - Key of the property\n   * @param property - Value of the property\n   */\n  setAccountProperty: (key: string, property: any) => void\n\n  /**\n   * Remove an account property\n   *\n   * @category Context - Account\n   * @param key - Key of the property to remove\n   */\n  removeAccountProperty: (key: string) => void\n\n  /**\n   * Clear all account information\n   *\n   * @category Context - Account\n   * @returns Clear all account information\n   */\n  clearAccount: () => void\n  /**\n   * Start a view manually.\n   * Enable to manual start a view, use `trackViewsManually: true` init parameter and call `startView()` to create RUM views and be aligned with how you’ve defined them in your SPA application routing.\n   *\n   * See [Override default RUM view names](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/#override-default-rum-view-names) for further information.\n   *\n   * Context - @category Data Collection\n   *\n   * @param nameOrOptions - The view name, or a {@link ViewOptions} object to configure the view\n   */\n  startView(nameOrOptions?: string | ViewOptions): void\n\n  /**\n   * Stop the session. A new session will start at the next user interaction with the page.\n   *\n   * @category Session\n   */\n  stopSession(): void\n\n  /**\n   * Add a feature flag evaluation,\n   * stored in `@feature_flags.<feature_flag_key>`\n   *\n   * We recommend enabling the intake request compression when using feature flags `compressIntakeRequests: true`.\n   *\n   * See [Feature Flag Tracking](https://docs.datadoghq.com/real_user_monitoring/feature_flag_tracking/) for further information.\n   *\n   * @category Data Collection\n   * @param key - The key of the feature flag.\n   * @param value - The value of the feature flag.\n   */\n  addFeatureFlagEvaluation: (key: string, value: any) => void\n\n  /**\n   * Get the Session Replay Link.\n   *\n   * See [Connect Session Replay To Your Third-Party Tools](https://docs.datadoghq.com/real_user_monitoring/guide/connect-session-replay-to-your-third-party-tools) for further information.\n   *\n   * @category Session Replay\n   */\n  getSessionReplayLink: () => string | undefined\n\n  /**\n   * Start Session Replay recording.\n   * Enable to conditionally start the recording, use the `startSessionReplayRecordingManually:true` init parameter and call `startSessionReplayRecording()`\n   *\n   * See [Browser Session Replay](https://docs.datadoghq.com/real_user_monitoring/session_replay/browser) for further information.\n   *\n   * @category Session Replay\n   */\n  startSessionReplayRecording: (options?: StartRecordingOptions) => void\n\n  /**\n   * Stop Session Replay recording.\n   *\n   * See [Browser Session Replay](https://docs.datadoghq.com/real_user_monitoring/session_replay/browser) for further information.\n   *\n   * @category Session Replay\n   */\n  stopSessionReplayRecording: () => void\n\n  /**\n   * Add a custom duration vital\n   *\n   * @category Vital - Duration\n   * @param name - Name of the custom vital\n   * @param options - Options for the custom vital (startTime, duration, context, description)\n   */\n  addDurationVital: (name: string, options: AddDurationVitalOptions) => void\n\n  /**\n   * Start a custom duration vital.\n   *\n   * If you plan to have multiple durations for the same vital, you should use the reference returned by this method.\n   *\n   * @category Vital - Duration\n   * @param name - Name of the custom vital\n   * @param options - Options for the custom vital (context, description)\n   * @returns reference to the custom vital\n   */\n  startDurationVital: (name: string, options?: DurationVitalOptions) => DurationVitalReference\n\n  /**\n   * Stop a custom duration vital\n   *\n   * @category Vital - Duration\n   * @param nameOrRef - Name or reference of the custom vital\n   * @param options - Options for the custom vital (operationKey, context, description)\n   */\n  stopDurationVital: (nameOrRef: string | DurationVitalReference, options?: DurationVitalOptions) => void\n\n  /**\n   * start a feature operation\n   *\n   * @category Vital - Feature Operation\n   * @param name - Name of the operation step\n   * @param options - Options for the operation step (operationKey, context, description)\n   * @hidden // TODO: replace by @since when GA\n   */\n  startFeatureOperation: (name: string, options?: FeatureOperationOptions) => void\n\n  /**\n   * succeed a feature operation\n   *\n   * @category Vital - Feature Operation\n   * @param name - Name of the operation step\n   * @param options - Options for the operation step (operationKey, context, description)\n   * @hidden // TODO: replace by @since when GA\n   */\n  succeedFeatureOperation: (name: string, options?: FeatureOperationOptions) => void\n\n  /**\n   * fail a feature operation\n   *\n   * @category Vital - Feature Operation\n   * @param name - Name of the operation step\n   * @param failureReason - Reason for the failure\n   * @param options - Options for the operation step (operationKey, context, description)\n   * @hidden // TODO: replace by @since when GA\n   */\n  failFeatureOperation: (name: string, failureReason: FailureReason, options?: FeatureOperationOptions) => void\n}\n\nexport interface RecorderApi {\n  start: (options?: StartRecordingOptions) => void\n  stop: () => void\n  onRumStart: (\n    lifeCycle: LifeCycle,\n    configuration: RumConfiguration,\n    sessionManager: RumSessionManager,\n    viewHistory: ViewHistory,\n    deflateWorker: DeflateWorker | undefined,\n    telemetry: Telemetry\n  ) => void\n  isRecording: () => boolean\n  getReplayStats: (viewId: string) => ReplayStats | undefined\n  getSessionReplayLink: () => string | undefined\n}\n\nexport interface ProfilerApi {\n  stop: () => void\n  onRumStart: (\n    lifeCycle: LifeCycle,\n    hooks: Hooks,\n    configuration: RumConfiguration,\n    sessionManager: RumSessionManager,\n    viewHistory: ViewHistory,\n    createEncoder: (streamId: DeflateEncoderStreamId) => Encoder\n  ) => void\n}\n\nexport interface RumPublicApiOptions {\n  ignoreInitIfSyntheticsWillInjectRum?: boolean\n  startDeflateWorker?: (\n    configuration: RumConfiguration,\n    source: string,\n    onInitializationFailure: () => void\n  ) => DeflateWorker | undefined\n  createDeflateEncoder?: (\n    configuration: RumConfiguration,\n    worker: DeflateWorker,\n    streamId: DeflateEncoderStreamId\n  ) => DeflateEncoder\n  sdkName?: SdkName\n}\n\nexport interface Strategy {\n  init: (initConfiguration: RumInitConfiguration, publicApi: RumPublicApi, errorStack?: string) => void\n  initConfiguration: RumInitConfiguration | undefined\n  getInternalContext: StartRumResult['getInternalContext']\n  stopSession: StartRumResult['stopSession']\n  addTiming: StartRumResult['addTiming']\n  setLoadingTime: StartRumResult['setLoadingTime']\n  startView: StartRumResult['startView']\n  setViewName: StartRumResult['setViewName']\n\n  setViewContext: StartRumResult['setViewContext']\n  setViewContextProperty: StartRumResult['setViewContextProperty']\n  getViewContext: StartRumResult['getViewContext']\n\n  globalContext: ContextManager\n  userContext: ContextManager\n  accountContext: ContextManager\n\n  addAction: StartRumResult['addAction']\n  startAction: StartRumResult['startAction']\n  stopAction: StartRumResult['stopAction']\n  startResource: StartRumResult['startResource']\n  stopResource: StartRumResult['stopResource']\n  addError: StartRumResult['addError']\n  addFeatureFlagEvaluation: StartRumResult['addFeatureFlagEvaluation']\n  startDurationVital: StartRumResult['startDurationVital']\n  stopDurationVital: StartRumResult['stopDurationVital']\n  addDurationVital: StartRumResult['addDurationVital']\n  addOperationStepVital: StartRumResult['addOperationStepVital']\n}\n\nexport function makeRumPublicApi(\n  recorderApi: RecorderApi,\n  profilerApi: ProfilerApi,\n  options: RumPublicApiOptions = {}\n): RumPublicApi {\n  const trackingConsentState = createTrackingConsentState()\n  const customVitalsState = createCustomVitalsState()\n  const bufferedDataObservable = startBufferingData().observable\n\n  let strategy = createPreStartStrategy(\n    options,\n    trackingConsentState,\n    customVitalsState,\n    (configuration, deflateWorker, initialViewOptions, telemetry, hooks) => {\n      const createEncoder =\n        deflateWorker && options.createDeflateEncoder\n          ? (streamId: DeflateEncoderStreamId) => options.createDeflateEncoder!(configuration, deflateWorker, streamId)\n          : createIdentityEncoder\n\n      const startRumResult = mockable(startRum)(\n        configuration,\n        recorderApi,\n        profilerApi,\n        initialViewOptions,\n        createEncoder,\n        trackingConsentState,\n        customVitalsState,\n        bufferedDataObservable,\n        telemetry,\n        hooks,\n        options.sdkName\n      )\n\n      recorderApi.onRumStart(\n        startRumResult.lifeCycle,\n        configuration,\n        startRumResult.session,\n        startRumResult.viewHistory,\n        deflateWorker,\n        startRumResult.telemetry\n      )\n\n      profilerApi.onRumStart(\n        startRumResult.lifeCycle,\n        startRumResult.hooks,\n        configuration,\n        startRumResult.session,\n        startRumResult.viewHistory,\n        createEncoder\n      )\n\n      strategy = createPostStartStrategy(strategy, startRumResult)\n\n      callPluginsMethod(configuration.plugins, 'onRumStart', {\n        strategy, // TODO: remove this in the next major release\n        addEvent: startRumResult.addEvent,\n        addError: startRumResult.addError,\n      })\n\n      return startRumResult\n    }\n  )\n  const getStrategy = () => strategy\n\n  const startView: {\n    (name?: string): void\n    (options: ViewOptions): void\n  } = (options?: string | ViewOptions) => {\n    const handlingStack = createHandlingStack('view')\n    callMonitored(() => {\n      const sanitizedOptions = typeof options === 'object' ? options : { name: options }\n      strategy.startView({ ...sanitizedOptions, handlingStack })\n      addTelemetryUsage({ feature: 'start-view' })\n    })\n  }\n\n  const rumPublicApi: RumPublicApi = makePublicApi<RumPublicApi>({\n    init: (initConfiguration) => {\n      const errorStack = new Error().stack\n      callMonitored(() => strategy.init(initConfiguration, rumPublicApi, errorStack))\n    },\n\n    setTrackingConsent: monitor((trackingConsent) => {\n      trackingConsentState.update(trackingConsent)\n      addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: trackingConsent })\n    }),\n\n    setViewName: monitor((name: string) => {\n      strategy.setViewName(name)\n      addTelemetryUsage({ feature: 'set-view-name' })\n    }),\n\n    setViewContext: monitor((context: Context) => {\n      strategy.setViewContext(context)\n      addTelemetryUsage({ feature: 'set-view-context' })\n    }),\n\n    setViewContextProperty: monitor((key: string, value: any) => {\n      strategy.setViewContextProperty(key, value)\n      addTelemetryUsage({ feature: 'set-view-context-property' })\n    }),\n\n    getViewContext: monitor(() => {\n      addTelemetryUsage({ feature: 'set-view-context-property' })\n      return strategy.getViewContext()\n    }),\n\n    getInternalContext: monitor((startTime) => strategy.getInternalContext(startTime)),\n\n    getInitConfiguration: monitor(() => deepClone(strategy.initConfiguration)),\n\n    addAction: (name, context) => {\n      const handlingStack = createHandlingStack('action')\n\n      callMonitored(() => {\n        strategy.addAction({\n          name: sanitize(name)!,\n          context: sanitize(context) as Context,\n          startClocks: clocksNow(),\n          type: ActionType.CUSTOM,\n          handlingStack,\n        })\n        addTelemetryUsage({ feature: 'add-action' })\n      })\n    },\n\n    startAction: monitor((name, options) => {\n      // Check feature flag only after init; pre-init calls should be buffered\n      if (strategy.initConfiguration && !isExperimentalFeatureEnabled(ExperimentalFeature.START_STOP_ACTION)) {\n        return\n      }\n      // addTelemetryUsage({ feature: 'start-action' })\n      strategy.startAction(sanitize(name)!, {\n        type: sanitize(options && options.type) as ActionType | undefined,\n        context: sanitize(options && options.context) as Context,\n        actionKey: options && options.actionKey,\n      })\n    }),\n\n    stopAction: monitor((name, options) => {\n      if (strategy.initConfiguration && !isExperimentalFeatureEnabled(ExperimentalFeature.START_STOP_ACTION)) {\n        return\n      }\n      // addTelemetryUsage({ feature: 'stop-action' })\n      strategy.stopAction(sanitize(name)!, {\n        type: sanitize(options && options.type) as ActionType | undefined,\n        context: sanitize(options && options.context) as Context,\n        actionKey: options && options.actionKey,\n      })\n    }),\n\n    startResource: monitor((url, options) => {\n      // Check feature flag only after init; pre-init calls should be buffered\n      if (strategy.initConfiguration && !isExperimentalFeatureEnabled(ExperimentalFeature.START_STOP_RESOURCE)) {\n        return\n      }\n      // addTelemetryUsage({ feature: 'start-resource' })\n      strategy.startResource(sanitize(url)!, {\n        type: sanitize(options && options.type) as ResourceType | undefined,\n        method: sanitize(options && options.method) as string | undefined,\n        context: sanitize(options && options.context) as Context,\n        resourceKey: options && options.resourceKey,\n      })\n    }),\n\n    stopResource: monitor((url, options) => {\n      if (strategy.initConfiguration && !isExperimentalFeatureEnabled(ExperimentalFeature.START_STOP_RESOURCE)) {\n        return\n      }\n      // addTelemetryUsage({ feature: 'stop-resource' })\n      strategy.stopResource(sanitize(url)!, {\n        type: sanitize(options && options.type) as ResourceType | undefined,\n        statusCode: options && options.statusCode,\n        size: options && options.size,\n        context: sanitize(options && options.context) as Context,\n        resourceKey: options && options.resourceKey,\n      })\n    }),\n\n    addError: (error, context) => {\n      const handlingStack = createHandlingStack('error')\n      callMonitored(() => {\n        strategy.addError({\n          error, // Do not sanitize error here, it is needed unserialized by computeRawError()\n          handlingStack,\n          context: sanitize(context) as Context,\n          startClocks: clocksNow(),\n        })\n        addTelemetryUsage({ feature: 'add-error' })\n      })\n    },\n\n    addTiming: monitor((name, time) => {\n      // TODO: next major decide to drop relative time support or update its behaviour\n      strategy.addTiming(sanitize(name)!, time as RelativeTime | TimeStamp | undefined)\n    }),\n\n    setViewLoadingTime: monitor(() => {\n      const callTimestamp = timeStampNow()\n      strategy.setLoadingTime(callTimestamp)\n      addTelemetryUsage({\n        feature: 'addViewLoadingTime',\n      })\n    }),\n\n    setGlobalContext: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.setContext,\n      'set-global-context'\n    ),\n    getGlobalContext: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.getContext,\n      'get-global-context'\n    ),\n    setGlobalContextProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.setContextProperty,\n      'set-global-context-property'\n    ),\n    removeGlobalContextProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.removeContextProperty,\n      'remove-global-context-property'\n    ),\n    clearGlobalContext: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.globalContext,\n      ContextManagerMethod.clearContext,\n      'clear-global-context'\n    ),\n\n    setUser: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.setContext,\n      'set-user'\n    ),\n    getUser: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.getContext,\n      'get-user'\n    ),\n    setUserProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.setContextProperty,\n      'set-user-property'\n    ),\n    removeUserProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.removeContextProperty,\n      'remove-user-property'\n    ),\n    clearUser: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.userContext,\n      ContextManagerMethod.clearContext,\n      'clear-user'\n    ),\n\n    setAccount: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.setContext,\n      'set-account'\n    ),\n    getAccount: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.getContext,\n      'get-account'\n    ),\n    setAccountProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.setContextProperty,\n      'set-account-property'\n    ),\n    removeAccountProperty: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.removeContextProperty,\n      'remove-account-property'\n    ),\n    clearAccount: defineContextMethod(\n      getStrategy,\n      CustomerContextKey.accountContext,\n      ContextManagerMethod.clearContext,\n      'clear-account'\n    ),\n\n    startView,\n\n    stopSession: monitor(() => {\n      strategy.stopSession()\n      addTelemetryUsage({ feature: 'stop-session' })\n    }),\n\n    addFeatureFlagEvaluation: monitor((key, value) => {\n      strategy.addFeatureFlagEvaluation(sanitize(key)!, sanitize(value))\n      addTelemetryUsage({ feature: 'add-feature-flag-evaluation' })\n    }),\n\n    getSessionReplayLink: monitor(() => recorderApi.getSessionReplayLink()),\n\n    startSessionReplayRecording: monitor((options?: StartRecordingOptions) => {\n      recorderApi.start(options)\n      addTelemetryUsage({ feature: 'start-session-replay-recording', force: options && options.force })\n    }),\n\n    stopSessionReplayRecording: monitor(() => recorderApi.stop()),\n\n    addDurationVital: (name, options) => {\n      const handlingStack = createHandlingStack('vital')\n      callMonitored(() => {\n        addTelemetryUsage({ feature: 'add-duration-vital' })\n        strategy.addDurationVital({\n          id: generateUUID(),\n          name: sanitize(name)!,\n          type: VitalType.DURATION,\n          startClocks: timeStampToClocks(options.startTime as TimeStamp),\n          duration: options.duration as Duration,\n          context: sanitize(options && options.context) as Context,\n          description: sanitize(options && options.description) as string | undefined,\n          handlingStack,\n        })\n      })\n    },\n\n    startDurationVital: (name, options) => {\n      const handlingStack = createHandlingStack('vital')\n      return callMonitored(() => {\n        addTelemetryUsage({ feature: 'start-duration-vital' })\n        return strategy.startDurationVital(sanitize(name)!, {\n          context: sanitize(options && options.context) as Context,\n          description: sanitize(options && options.description) as string | undefined,\n          handlingStack,\n        })\n      }) as DurationVitalReference\n    },\n\n    stopDurationVital: monitor((nameOrRef, options) => {\n      addTelemetryUsage({ feature: 'stop-duration-vital' })\n      strategy.stopDurationVital(typeof nameOrRef === 'string' ? sanitize(nameOrRef)! : nameOrRef, {\n        context: sanitize(options && options.context) as Context,\n        description: sanitize(options && options.description) as string | undefined,\n      })\n    }),\n\n    startFeatureOperation: (name, options) => {\n      const handlingStack = createHandlingStack('vital')\n      callMonitored(() => {\n        addTelemetryUsage({ feature: 'add-operation-step-vital', action_type: 'start' })\n        strategy.addOperationStepVital(name, 'start', { ...options, handlingStack })\n      })\n    },\n\n    succeedFeatureOperation: monitor((name, options) => {\n      addTelemetryUsage({ feature: 'add-operation-step-vital', action_type: 'succeed' })\n      strategy.addOperationStepVital(name, 'end', options)\n    }),\n\n    failFeatureOperation: monitor((name, failureReason, options) => {\n      addTelemetryUsage({ feature: 'add-operation-step-vital', action_type: 'fail' })\n      strategy.addOperationStepVital(name, 'end', options, failureReason)\n    }),\n  })\n\n  return rumPublicApi\n}\n\nfunction createPostStartStrategy(preStartStrategy: Strategy, startRumResult: StartRumResult): Strategy {\n  return {\n    init: (initConfiguration: RumInitConfiguration) => {\n      displayAlreadyInitializedError('DD_RUM', initConfiguration)\n    },\n    initConfiguration: preStartStrategy.initConfiguration,\n    ...startRumResult,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/boot/startRum.spec.ts",
    "content": "import type { RawError, Duration, BufferedData } from '@datadog/browser-core'\nimport {\n  Observable,\n  stopSessionManager,\n  toServerDuration,\n  ONE_SECOND,\n  findLast,\n  noop,\n  relativeNow,\n  createIdentityEncoder,\n  createTrackingConsentState,\n  TrackingConsent,\n  BufferedObservable,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport {\n  createNewEvent,\n  interceptRequests,\n  mockClock,\n  mockEventBridge,\n  registerCleanupTask,\n  createFakeTelemetryObject,\n} from '@datadog/browser-core/test'\nimport type { RumSessionManagerMock } from '../../test'\nimport { createRumSessionManagerMock, mockRumConfiguration, noopProfilerApi, noopRecorderApi } from '../../test'\nimport { LifeCycle, LifeCycleEventType } from '../domain/lifeCycle'\nimport { SESSION_KEEP_ALIVE_INTERVAL } from '../domain/view/trackViews'\nimport type { RumEvent, RumViewEvent } from '../rumEvent.types'\nimport type { RumConfiguration } from '../domain/configuration'\nimport { RumEventType } from '../rawRumEvent.types'\nimport { createCustomVitalsState } from '../domain/vital/vitalCollection'\nimport { createHooks } from '../domain/hooks'\nimport type { RumSessionManager } from '../domain/rumSessionManager'\nimport { startRum, startRumEventCollection } from './startRum'\n\nfunction collectServerEvents(lifeCycle: LifeCycle) {\n  const serverRumEvents: RumEvent[] = []\n  lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, (serverRumEvent) => {\n    serverRumEvents.push(serverRumEvent)\n  })\n  return serverRumEvents\n}\n\nfunction startRumStub(\n  lifeCycle: LifeCycle,\n  configuration: RumConfiguration,\n  sessionManager: RumSessionManager,\n  reportError: (error: RawError) => void\n) {\n  const hooks = createHooks()\n\n  const { stop: rumEventCollectionStop } = startRumEventCollection(\n    lifeCycle,\n    hooks,\n    configuration,\n    sessionManager,\n    noopRecorderApi,\n    undefined,\n    createCustomVitalsState(),\n    new Observable(),\n    undefined,\n    reportError\n  )\n\n  return {\n    stop: () => {\n      rumEventCollectionStop()\n    },\n  }\n}\n\ndescribe('rum session', () => {\n  let serverRumEvents: RumEvent[]\n  let lifeCycle: LifeCycle\n  let sessionManager: RumSessionManagerMock\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    sessionManager = createRumSessionManagerMock().setId('42')\n\n    serverRumEvents = collectServerEvents(lifeCycle)\n    const { stop } = startRumStub(lifeCycle, mockRumConfiguration(), sessionManager, noop)\n\n    registerCleanupTask(stop)\n  })\n\n  it('when the session is renewed, a new view event should be sent', () => {\n    expect(serverRumEvents.length).toEqual(1)\n    expect(serverRumEvents[0].type).toEqual('view')\n    expect(serverRumEvents[0].session.id).toEqual('42')\n\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n    expect(serverRumEvents.length).toEqual(2)\n\n    sessionManager.setId('43')\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n    expect(serverRumEvents.length).toEqual(3)\n\n    // New view event\n    expect(serverRumEvents[2].type).toEqual('view')\n    expect(serverRumEvents[2].session.id).toEqual('43')\n    expect(serverRumEvents[2].view.id).not.toEqual(serverRumEvents[0].view.id)\n  })\n})\n\ndescribe('rum session keep alive', () => {\n  let lifeCycle: LifeCycle\n  let clock: Clock\n  let sessionManager: RumSessionManagerMock\n  let serverRumEvents: RumEvent[]\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    clock = mockClock()\n    sessionManager = createRumSessionManagerMock().setId('1234')\n\n    serverRumEvents = collectServerEvents(lifeCycle)\n    const { stop } = startRumStub(lifeCycle, mockRumConfiguration(), sessionManager, noop)\n\n    registerCleanupTask(() => {\n      stop()\n    })\n  })\n\n  it('should send a view update regularly', () => {\n    // clear initial events\n    clock.tick(SESSION_KEEP_ALIVE_INTERVAL * 0.9)\n    serverRumEvents.length = 0\n\n    clock.tick(SESSION_KEEP_ALIVE_INTERVAL * 0.1)\n\n    // view update\n    expect(serverRumEvents.length).toEqual(1)\n    expect(serverRumEvents[0].type).toEqual('view')\n\n    clock.tick(SESSION_KEEP_ALIVE_INTERVAL)\n\n    // view update\n    expect(serverRumEvents.length).toEqual(2)\n    expect(serverRumEvents[1].type).toEqual('view')\n  })\n\n  it('should not send view update when sessionManager is expired', () => {\n    // clear initial events\n    clock.tick(SESSION_KEEP_ALIVE_INTERVAL * 0.9)\n    serverRumEvents.length = 0\n\n    // expire session\n    sessionManager.setNotTracked()\n\n    clock.tick(SESSION_KEEP_ALIVE_INTERVAL * 0.1)\n\n    expect(serverRumEvents.length).toEqual(0)\n  })\n})\n\ndescribe('view events', () => {\n  let clock: Clock\n  let interceptor: ReturnType<typeof interceptRequests>\n  let stop: () => void\n\n  function setupViewCollectionTest() {\n    const startResult = startRum(\n      mockRumConfiguration(),\n      noopRecorderApi,\n      noopProfilerApi,\n      undefined,\n      createIdentityEncoder,\n      createTrackingConsentState(TrackingConsent.GRANTED),\n      createCustomVitalsState(),\n      new BufferedObservable<BufferedData>(100),\n      createFakeTelemetryObject(),\n      createHooks(),\n      'rum'\n    )\n\n    stop = startResult.stop\n    interceptor = interceptRequests()\n  }\n\n  beforeEach(() => {\n    clock = mockClock()\n\n    registerCleanupTask(() => {\n      stop()\n      stopSessionManager()\n    })\n  })\n\n  it('sends a view update on page unload when bridge is absent', () => {\n    // Note: this test is intentionally very high level to make sure the view update is correctly\n    // made right before flushing the Batch.\n\n    // Arbitrary duration to simulate a non-zero view duration\n    const VIEW_DURATION = ONE_SECOND as Duration\n\n    setupViewCollectionTest()\n\n    clock.tick(VIEW_DURATION - relativeNow())\n    window.dispatchEvent(createNewEvent('beforeunload'))\n\n    const lastRumEvents = interceptor.requests[interceptor.requests.length - 1].body\n      .split('\\n')\n      .map((line) => JSON.parse(line) as RumEvent)\n    const lastRumViewEvent = findLast(\n      lastRumEvents,\n      (serverRumEvent): serverRumEvent is RumViewEvent => serverRumEvent.type === RumEventType.VIEW\n    )!\n\n    expect(lastRumViewEvent.view.time_spent).toBe(toServerDuration(VIEW_DURATION))\n  })\n\n  it('sends a view update on page unload when bridge is present', () => {\n    const eventBridge = mockEventBridge()\n    const sendSpy = spyOn(eventBridge, 'send')\n\n    const VIEW_DURATION = ONE_SECOND as Duration\n\n    setupViewCollectionTest()\n\n    clock.tick(VIEW_DURATION - relativeNow())\n    window.dispatchEvent(createNewEvent('beforeunload'))\n\n    const lastBridgeMessage = JSON.parse(sendSpy.calls.mostRecent().args[0]) as {\n      eventType: 'rum'\n      event: RumEvent\n    }\n    expect(lastBridgeMessage.event.type).toBe('view')\n    expect(lastBridgeMessage.event.view.time_spent).toBe(toServerDuration(VIEW_DURATION))\n  })\n\n  it('sends a view update with the correct sdk name', () => {\n    // Arbitrary duration to simulate a non-zero view duration\n    const VIEW_DURATION = ONE_SECOND as Duration\n\n    setupViewCollectionTest()\n\n    clock.tick(VIEW_DURATION - relativeNow())\n    window.dispatchEvent(createNewEvent('beforeunload'))\n\n    const lastRumEvents = interceptor.requests[interceptor.requests.length - 1].body\n      .split('\\n')\n      .map((line) => JSON.parse(line) as RumEvent)\n    const lastRumViewEvent = findLast(\n      lastRumEvents,\n      (serverRumEvent): serverRumEvent is RumViewEvent => serverRumEvent.type === RumEventType.VIEW\n    )!\n    expect(lastRumViewEvent._dd.sdk_name).toBe('rum')\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/boot/startRum.ts",
    "content": "import type {\n  Observable,\n  RawError,\n  DeflateEncoderStreamId,\n  Encoder,\n  TrackingConsentState,\n  BufferedData,\n  BufferedObservable,\n  Telemetry,\n} from '@datadog/browser-core'\nimport {\n  sendToExtension,\n  createPageMayExitObservable,\n  canUseEventBridge,\n  addTelemetryDebug,\n  startAccountContext,\n  startGlobalContext,\n  startUserContext,\n  startTabContext,\n} from '@datadog/browser-core'\nimport { createDOMMutationObservable } from '../browser/domMutationObservable'\nimport { createWindowOpenObservable } from '../browser/windowOpenObservable'\nimport { startInternalContext } from '../domain/contexts/internalContext'\nimport { LifeCycle, LifeCycleEventType } from '../domain/lifeCycle'\nimport { startViewHistory } from '../domain/contexts/viewHistory'\nimport { startRequestCollection } from '../domain/requestCollection'\nimport { startActionCollection } from '../domain/action/actionCollection'\nimport { startErrorCollection } from '../domain/error/errorCollection'\nimport { startResourceCollection } from '../domain/resource/resourceCollection'\nimport { startViewCollection } from '../domain/view/viewCollection'\nimport type { RumSessionManager } from '../domain/rumSessionManager'\nimport { startRumSessionManager, startRumSessionManagerStub } from '../domain/rumSessionManager'\nimport { startRumBatch } from '../transport/startRumBatch'\nimport { startRumEventBridge } from '../transport/startRumEventBridge'\nimport { startUrlContexts } from '../domain/contexts/urlContexts'\nimport { createLocationChangeObservable } from '../browser/locationChangeObservable'\nimport type { RumConfiguration } from '../domain/configuration'\nimport type { ViewOptions } from '../domain/view/trackViews'\nimport { startFeatureFlagContexts } from '../domain/contexts/featureFlagContext'\nimport { startCustomerDataTelemetry } from '../domain/startCustomerDataTelemetry'\nimport { startPageStateHistory } from '../domain/contexts/pageStateHistory'\nimport { startDisplayContext } from '../domain/contexts/displayContext'\nimport type { CustomVitalsState } from '../domain/vital/vitalCollection'\nimport { startVitalCollection } from '../domain/vital/vitalCollection'\nimport { startCiVisibilityContext } from '../domain/contexts/ciVisibilityContext'\nimport { startLongTaskCollection } from '../domain/longTask/longTaskCollection'\nimport { startSyntheticsContext } from '../domain/contexts/syntheticsContext'\nimport { startRumAssembly } from '../domain/assembly'\nimport { startSessionContext } from '../domain/contexts/sessionContext'\nimport { startConnectivityContext } from '../domain/contexts/connectivityContext'\nimport type { SdkName } from '../domain/contexts/defaultContext'\nimport { startDefaultContext } from '../domain/contexts/defaultContext'\nimport { startTrackingConsentContext } from '../domain/contexts/trackingConsentContext'\nimport type { Hooks } from '../domain/hooks'\nimport { startEventCollection } from '../domain/event/eventCollection'\nimport { startInitialViewMetricsTelemetry } from '../domain/view/viewMetrics/startInitialViewMetricsTelemetry'\nimport { startSourceCodeContext } from '../domain/contexts/sourceCodeContext'\nimport type { RecorderApi, ProfilerApi } from './rumPublicApi'\n\nexport type StartRum = typeof startRum\nexport type StartRumResult = ReturnType<StartRum>\n\nexport function startRum(\n  configuration: RumConfiguration,\n  recorderApi: RecorderApi,\n  profilerApi: ProfilerApi,\n  initialViewOptions: ViewOptions | undefined,\n  createEncoder: (streamId: DeflateEncoderStreamId) => Encoder,\n\n  // `startRum` and its subcomponents assume tracking consent is granted initially and starts\n  // collecting logs unconditionally. As such, `startRum` should be called with a\n  // `trackingConsentState` set to \"granted\".\n  trackingConsentState: TrackingConsentState,\n  customVitalsState: CustomVitalsState,\n  bufferedDataObservable: BufferedObservable<BufferedData>,\n  telemetry: Telemetry,\n  hooks: Hooks,\n  sdkName?: SdkName\n) {\n  const cleanupTasks: Array<() => void> = []\n  const lifeCycle = new LifeCycle()\n\n  lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, (event) => sendToExtension('rum', event))\n\n  const reportError = (error: RawError) => {\n    lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, { error })\n    // monitor-until: forever, to keep an eye on the errors reported to customers\n    addTelemetryDebug('Error reported to customer', { 'error.message': error.message })\n  }\n\n  const pageMayExitObservable = createPageMayExitObservable(configuration)\n\n  const session = !canUseEventBridge()\n    ? startRumSessionManager(configuration, lifeCycle, trackingConsentState)\n    : startRumSessionManagerStub()\n\n  if (!canUseEventBridge()) {\n    const batch = startRumBatch(\n      configuration,\n      lifeCycle,\n      reportError,\n      pageMayExitObservable,\n      session.expireObservable,\n      createEncoder\n    )\n    const preparePageExitSubscription = batch.flushController.preparePageExitFlushObservable.subscribe((reason) => {\n      lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason })\n    })\n    cleanupTasks.push(() => preparePageExitSubscription.unsubscribe())\n    cleanupTasks.push(() => batch.stop())\n    startCustomerDataTelemetry(telemetry, lifeCycle, batch.flushController.flushObservable)\n  } else {\n    startRumEventBridge(lifeCycle)\n    const pageMayExitSubscription = pageMayExitObservable.subscribe((event) => {\n      lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, event)\n    })\n    cleanupTasks.push(() => pageMayExitSubscription.unsubscribe())\n  }\n\n  startTrackingConsentContext(hooks, trackingConsentState)\n\n  const { stop: stopInitialViewMetricsTelemetry } = startInitialViewMetricsTelemetry(lifeCycle, telemetry)\n  cleanupTasks.push(stopInitialViewMetricsTelemetry)\n\n  const { stop: stopRumEventCollection, ...startRumEventCollectionResult } = startRumEventCollection(\n    lifeCycle,\n    hooks,\n    configuration,\n    session,\n    recorderApi,\n    initialViewOptions,\n    customVitalsState,\n    bufferedDataObservable,\n    sdkName,\n    reportError\n  )\n  cleanupTasks.push(stopRumEventCollection)\n  bufferedDataObservable.unbuffer()\n\n  // Add Clean-up tasks for Profiler API.\n  cleanupTasks.push(() => profilerApi.stop())\n\n  return {\n    ...startRumEventCollectionResult,\n    lifeCycle,\n    session,\n    stopSession: () => session.expire(),\n    telemetry,\n    stop: () => {\n      cleanupTasks.forEach((task) => task())\n    },\n    hooks,\n  }\n}\n\nexport function startRumEventCollection(\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  configuration: RumConfiguration,\n  session: RumSessionManager,\n  recorderApi: RecorderApi,\n  initialViewOptions: ViewOptions | undefined,\n  customVitalsState: CustomVitalsState,\n  bufferedDataObservable: Observable<BufferedData>,\n  sdkName: SdkName | undefined,\n  reportError: (error: RawError) => void\n) {\n  const cleanupTasks: Array<() => void> = []\n\n  const domMutationObservable = createDOMMutationObservable()\n  const locationChangeObservable = createLocationChangeObservable(configuration)\n  const { observable: windowOpenObservable, stop: stopWindowOpen } = createWindowOpenObservable()\n  cleanupTasks.push(stopWindowOpen)\n\n  startDefaultContext(hooks, configuration, sdkName)\n  const pageStateHistory = startPageStateHistory(hooks, configuration)\n  cleanupTasks.push(() => pageStateHistory.stop())\n  const viewHistory = startViewHistory(lifeCycle)\n  cleanupTasks.push(() => viewHistory.stop())\n  const urlContexts = startUrlContexts(lifeCycle, hooks, locationChangeObservable)\n  cleanupTasks.push(() => urlContexts.stop())\n  const featureFlagContexts = startFeatureFlagContexts(lifeCycle, hooks, configuration)\n  startSessionContext(hooks, session, recorderApi, viewHistory)\n  startConnectivityContext(hooks)\n  startTabContext(hooks)\n  const globalContext = startGlobalContext(hooks, configuration, 'rum', true)\n  const userContext = startUserContext(hooks, configuration, session, 'rum')\n  const accountContext = startAccountContext(hooks, configuration, 'rum')\n\n  const actionCollection = startActionCollection(\n    lifeCycle,\n    hooks,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration\n  )\n  cleanupTasks.push(actionCollection.stop)\n\n  const eventCollection = startEventCollection(lifeCycle)\n\n  const displayContext = startDisplayContext(hooks, configuration)\n  cleanupTasks.push(displayContext.stop)\n  const ciVisibilityContext = startCiVisibilityContext(configuration, hooks)\n  cleanupTasks.push(ciVisibilityContext.stop)\n  startSyntheticsContext(hooks)\n\n  startRumAssembly(configuration, lifeCycle, hooks, reportError)\n\n  const {\n    addTiming,\n    setLoadingTime,\n    startView,\n    setViewName,\n    setViewContext,\n    setViewContextProperty,\n    getViewContext,\n    stop: stopViewCollection,\n  } = startViewCollection(\n    lifeCycle,\n    hooks,\n    configuration,\n    domMutationObservable,\n    windowOpenObservable,\n    locationChangeObservable,\n    recorderApi,\n    viewHistory,\n    initialViewOptions\n  )\n\n  startSourceCodeContext(hooks)\n\n  cleanupTasks.push(stopViewCollection)\n\n  const resourceCollection = startResourceCollection(lifeCycle, configuration, pageStateHistory)\n  cleanupTasks.push(resourceCollection.stop)\n\n  const { stop: stopLongTaskCollection } = startLongTaskCollection(lifeCycle, configuration)\n  cleanupTasks.push(stopLongTaskCollection)\n\n  const { addError } = startErrorCollection(lifeCycle, configuration, bufferedDataObservable)\n\n  startRequestCollection(lifeCycle, configuration, session, userContext, accountContext)\n\n  const vitalCollection = startVitalCollection(lifeCycle, pageStateHistory, customVitalsState)\n\n  const internalContext = startInternalContext(\n    configuration.applicationId,\n    session,\n    viewHistory,\n    actionCollection.actionContexts,\n    urlContexts\n  )\n\n  return {\n    addAction: actionCollection.addAction,\n    startAction: actionCollection.startAction,\n    stopAction: actionCollection.stopAction,\n    startResource: resourceCollection.startResource,\n    stopResource: resourceCollection.stopResource,\n    addEvent: eventCollection.addEvent,\n    addError,\n    addTiming,\n    setLoadingTime,\n    addFeatureFlagEvaluation: featureFlagContexts.addFeatureFlagEvaluation,\n    startView,\n    setViewContext,\n    setViewContextProperty,\n    getViewContext,\n    setViewName,\n    viewHistory,\n    getInternalContext: internalContext.get,\n    startDurationVital: vitalCollection.startDurationVital,\n    stopDurationVital: vitalCollection.stopDurationVital,\n    addDurationVital: vitalCollection.addDurationVital,\n    addOperationStepVital: vitalCollection.addOperationStepVital,\n    globalContext,\n    userContext,\n    accountContext,\n    stop: () => cleanupTasks.forEach((task) => task()),\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/cookieObservable.spec.ts",
    "content": "import type { Subscription } from '@datadog/browser-core'\nimport { ONE_MINUTE, deleteCookie, setCookie } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../test'\nimport type { CookieStoreWindow } from './cookieObservable'\nimport { WATCH_COOKIE_INTERVAL_DELAY, createCookieObservable } from './cookieObservable'\n\nconst COOKIE_NAME = 'cookie_name'\nconst COOKIE_DURATION = ONE_MINUTE\n\ndescribe('cookieObservable', () => {\n  let subscription: Subscription\n  let originalSupportedEntryTypes: PropertyDescriptor | undefined\n  let clock: Clock\n  beforeEach(() => {\n    deleteCookie(COOKIE_NAME)\n    clock = mockClock()\n    originalSupportedEntryTypes = Object.getOwnPropertyDescriptor(window, 'cookieStore')\n  })\n\n  afterEach(() => {\n    subscription?.unsubscribe()\n    if (originalSupportedEntryTypes) {\n      Object.defineProperty(window, 'cookieStore', originalSupportedEntryTypes)\n    }\n  })\n\n  it('should notify observers on cookie change', async () => {\n    const observable = createCookieObservable(mockRumConfiguration(), COOKIE_NAME)\n\n    const cookieChangePromise = new Promise((resolve) => {\n      subscription = observable.subscribe(resolve)\n    })\n\n    // When writing a cookie just after subscribing to the cookieStore 'change' event, the 'change'\n    // event is sometimes not triggered, making this test case flaky.\n    // To work around this, we get some random cookie from the cookieStore. This adds enough delay\n    // to ensure that the 'change' event is triggered when we write our cookie.\n    // This was reported here: https://issues.chromium.org/issues/420405275\n    const cookieStore = (window as CookieStoreWindow).cookieStore\n    if (cookieStore) {\n      // Wait for the cookieStore to be ready\n      await cookieStore.get('some_cookie_name')\n    }\n\n    setCookie(COOKIE_NAME, 'foo', COOKIE_DURATION)\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY)\n\n    const cookieChange = await cookieChangePromise\n    expect(cookieChange).toEqual('foo')\n  })\n\n  it('should notify observers on cookie change when cookieStore is not supported', () => {\n    Object.defineProperty(window, 'cookieStore', { get: () => undefined, configurable: true })\n    const observable = createCookieObservable(mockRumConfiguration(), COOKIE_NAME)\n\n    let cookieChange: string | undefined\n    subscription = observable.subscribe((change) => (cookieChange = change))\n\n    setCookie(COOKIE_NAME, 'foo', COOKIE_DURATION)\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY)\n\n    expect(cookieChange).toEqual('foo')\n  })\n\n  it('should not notify observers on cookie change when the cookie value as not changed when cookieStore is not supported', () => {\n    Object.defineProperty(window, 'cookieStore', { get: () => undefined, configurable: true })\n    const observable = createCookieObservable(mockRumConfiguration(), COOKIE_NAME)\n\n    setCookie(COOKIE_NAME, 'foo', COOKIE_DURATION)\n\n    let cookieChange: string | undefined\n    subscription = observable.subscribe((change) => (cookieChange = change))\n\n    setCookie(COOKIE_NAME, 'foo', COOKIE_DURATION)\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY)\n\n    expect(cookieChange).toBeUndefined()\n  })\n\n  it('should not re-notify observers if the cookie has not changed since last notification when cookieStore is not supported', () => {\n    Object.defineProperty(window, 'cookieStore', { get: () => undefined, configurable: true })\n    const observable = createCookieObservable(mockRumConfiguration(), COOKIE_NAME)\n\n    const cookieChanges: Array<string | undefined> = []\n    subscription = observable.subscribe((change) => cookieChanges.push(change))\n\n    setCookie(COOKIE_NAME, 'foo', COOKIE_DURATION)\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY) // detects 'foo'\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY) // no change since last notification\n\n    expect(cookieChanges).toEqual(['foo'])\n  })\n\n  it('should notify observers on consecutive cookie changes when cookieStore is not supported', () => {\n    Object.defineProperty(window, 'cookieStore', { get: () => undefined, configurable: true })\n    const observable = createCookieObservable(mockRumConfiguration(), COOKIE_NAME)\n\n    const cookieChanges: Array<string | undefined> = []\n    subscription = observable.subscribe((change) => cookieChanges.push(change))\n\n    setCookie(COOKIE_NAME, 'foo', COOKIE_DURATION)\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY)\n\n    setCookie(COOKIE_NAME, 'bar', COOKIE_DURATION)\n    clock.tick(WATCH_COOKIE_INTERVAL_DELAY)\n\n    expect(cookieChanges).toEqual(['foo', 'bar'])\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/cookieObservable.ts",
    "content": "import type { Configuration, CookieStore } from '@datadog/browser-core'\nimport {\n  setInterval,\n  clearInterval,\n  Observable,\n  addEventListener,\n  ONE_SECOND,\n  findCommaSeparatedValue,\n  DOM_EVENT,\n} from '@datadog/browser-core'\n\nexport interface CookieStoreWindow {\n  cookieStore?: CookieStore\n}\n\nexport type CookieObservable = ReturnType<typeof createCookieObservable>\n\nexport function createCookieObservable(configuration: Configuration, cookieName: string) {\n  const detectCookieChangeStrategy = (window as CookieStoreWindow).cookieStore\n    ? listenToCookieStoreChange(configuration)\n    : watchCookieFallback\n\n  return new Observable<string | undefined>((observable) =>\n    detectCookieChangeStrategy(cookieName, (event) => observable.notify(event))\n  )\n}\n\nfunction listenToCookieStoreChange(configuration: Configuration) {\n  return (cookieName: string, callback: (event: string | undefined) => void) => {\n    const listener = addEventListener(\n      configuration,\n      (window as CookieStoreWindow).cookieStore!,\n      DOM_EVENT.CHANGE,\n      (event) => {\n        // Based on our experimentation, we're assuming that entries for the same cookie cannot be in both the 'changed' and 'deleted' arrays.\n        // However, due to ambiguity in the specification, we asked for clarification: https://github.com/WICG/cookie-store/issues/226\n        const changeEvent =\n          event.changed.find((event) => event.name === cookieName) ||\n          event.deleted.find((event) => event.name === cookieName)\n        if (changeEvent) {\n          callback(changeEvent.value)\n        }\n      }\n    )\n    return listener.stop\n  }\n}\n\nexport const WATCH_COOKIE_INTERVAL_DELAY = ONE_SECOND\n\nfunction watchCookieFallback(cookieName: string, callback: (event: string | undefined) => void) {\n  let previousCookieValue = findCommaSeparatedValue(document.cookie, cookieName)\n  const watchCookieIntervalId = setInterval(() => {\n    const cookieValue = findCommaSeparatedValue(document.cookie, cookieName)\n    if (cookieValue !== previousCookieValue) {\n      previousCookieValue = cookieValue\n      callback(cookieValue)\n    }\n  }, WATCH_COOKIE_INTERVAL_DELAY)\n\n  return () => {\n    clearInterval(watchCookieIntervalId)\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/domMutationObservable.spec.ts",
    "content": "import type { MockZoneJs } from '@datadog/browser-core/test'\nimport { registerCleanupTask, mockZoneJs } from '@datadog/browser-core/test'\nimport { createDOMMutationObservable, getMutationObserverConstructor } from './domMutationObservable'\n\n// The MutationObserver invokes its callback in an event loop microtask, making this asynchronous.\n// We want to wait for a few event loop executions to potentially collect multiple mutation events.\nconst DOM_MUTATION_OBSERVABLE_DURATION = 16\n\ndescribe('domMutationObservable', () => {\n  function domMutationSpec(mutate: (root: HTMLElement) => void, { expectedMutations }: { expectedMutations: number }) {\n    return (done: DoneFn) => {\n      const root = document.createElement('div')\n      root.setAttribute('data-test', 'foo')\n      root.appendChild(document.createElement('span'))\n      root.appendChild(document.createTextNode('foo'))\n      document.body.appendChild(root)\n\n      const domMutationObservable = createDOMMutationObservable()\n\n      let counter = 0\n      const domMutationSubscription = domMutationObservable.subscribe(() => (counter += 1))\n\n      mutate(root)\n\n      setTimeout(() => {\n        expect(counter).toBe(expectedMutations)\n        root.parentNode!.removeChild(root)\n        domMutationSubscription.unsubscribe()\n        done()\n      }, DOM_MUTATION_OBSERVABLE_DURATION)\n    }\n  }\n\n  it(\n    'collects DOM mutation when an element is added',\n    domMutationSpec(\n      (root) => {\n        root.appendChild(document.createElement('button'))\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  it(\n    'collects DOM mutation when a text node is added',\n    domMutationSpec(\n      (root) => {\n        root.appendChild(document.createTextNode('foo'))\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  it(\n    'collects DOM mutation on attribute creation',\n    domMutationSpec(\n      (root) => {\n        root.setAttribute('data-test2', 'bar')\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  it(\n    'collects DOM mutation on attribute change',\n    domMutationSpec(\n      (root) => {\n        root.setAttribute('data-test', 'bar')\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  it(\n    'collects DOM mutation when an element is removed',\n    domMutationSpec(\n      (root) => {\n        root.removeChild(root.childNodes[0])\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  it(\n    'collects DOM mutation when an element is moved',\n    domMutationSpec(\n      (root) => {\n        root.insertBefore(root.childNodes[0], null)\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  it(\n    'collects DOM mutation when text node content changes',\n    domMutationSpec(\n      (root) => {\n        ;(root.childNodes[1] as Text).data = 'bar'\n      },\n      { expectedMutations: 1 }\n    )\n  )\n\n  describe('Zone.js support', () => {\n    let zoneJs: MockZoneJs\n    const OriginalMutationObserverConstructor = window.MutationObserver\n\n    beforeEach(() => {\n      zoneJs = mockZoneJs()\n\n      registerCleanupTask(() => {\n        window.MutationObserver = OriginalMutationObserverConstructor\n      })\n    })\n\n    it('gets the original MutationObserver constructor from the \"window\" object (Zone.js >= 0.8.6)', () => {\n      zoneJs.replaceProperty(window, 'MutationObserver', function () {\n        // This won't be instantiated.\n      } as any)\n      expect(getMutationObserverConstructor()).toBe(OriginalMutationObserverConstructor)\n    })\n\n    it('gets the original MutationObserver constructor from a patched instance (Zone.js < 0.8.6)', () => {\n      window.MutationObserver = function (this: any, callback: () => void) {\n        this[zoneJs.getSymbol('originalInstance')] = new OriginalMutationObserverConstructor(callback)\n      } as any\n\n      expect(getMutationObserverConstructor()).toBe(OriginalMutationObserverConstructor)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/domMutationObservable.ts",
    "content": "import { monitor, noop, Observable, getZoneJsOriginalValue } from '@datadog/browser-core'\n\n// https://dom.spec.whatwg.org/#interface-mutationrecord\nexport interface RumCharacterDataMutationRecord {\n  type: 'characterData'\n  target: Node\n  oldValue: string | null\n}\n\nexport interface RumAttributesMutationRecord {\n  type: 'attributes'\n  target: Element\n  oldValue: string | null\n  attributeName: string\n}\n\nexport interface RumChildListMutationRecord {\n  type: 'childList'\n  target: Node\n  addedNodes: NodeList\n  removedNodes: NodeList\n}\n\nexport type RumMutationRecord =\n  | RumCharacterDataMutationRecord\n  | RumAttributesMutationRecord\n  | RumChildListMutationRecord\n\nexport function createDOMMutationObservable() {\n  const MutationObserver = getMutationObserverConstructor()\n\n  return new Observable<RumMutationRecord[]>((observable) => {\n    if (!MutationObserver) {\n      return\n    }\n\n    const observer = new MutationObserver(monitor((records) => observable.notify(records)))\n    observer.observe(document, {\n      attributes: true,\n      characterData: true,\n      childList: true,\n      subtree: true,\n    })\n    return () => observer.disconnect()\n  })\n}\n\ntype MutationObserverConstructor = new (callback: (records: RumMutationRecord[]) => void) => MutationObserver\n\nexport interface BrowserWindow extends Window {\n  MutationObserver?: MutationObserverConstructor\n  Zone?: unknown\n}\n\nexport function getMutationObserverConstructor(): MutationObserverConstructor | undefined {\n  let constructor: MutationObserverConstructor | undefined\n  const browserWindow = window as BrowserWindow\n\n  // Angular uses Zone.js to provide a context persisting across async tasks.  Zone.js replaces the\n  // global MutationObserver constructor with a patched version to support the context propagation.\n  // There is an ongoing issue[1][2] with this setup when using a MutationObserver within a Angular\n  // component: on some occasions, the callback is being called in an infinite loop, causing the\n  // page to freeze (even if the callback is completely empty).\n  //\n  // To work around this issue, we try to get the original MutationObserver constructor stored by\n  // Zone.js.\n  //\n  // [1] https://github.com/angular/angular/issues/26948\n  // [2] https://github.com/angular/angular/issues/31712\n  if (browserWindow.Zone) {\n    // Zone.js 0.8.6+ is storing original class constructors into the browser 'window' object[3].\n    //\n    // [3] https://github.com/angular/angular/blob/6375fa79875c0fe7b815efc45940a6e6f5c9c9eb/packages/zone.js/lib/common/utils.ts#L288\n    constructor = getZoneJsOriginalValue(browserWindow, 'MutationObserver')\n\n    if (browserWindow.MutationObserver && constructor === browserWindow.MutationObserver) {\n      // Anterior Zone.js versions (used in Angular 2) does not expose the original MutationObserver\n      // in the 'window' object. Luckily, the patched MutationObserver class is storing an original\n      // instance in its properties[4]. Let's get the original MutationObserver constructor from\n      // there.\n      //\n      // [4] https://github.com/angular/zone.js/blob/v0.8.5/lib/common/utils.ts#L412\n\n      const patchedInstance = new browserWindow.MutationObserver(noop) as {\n        originalInstance?: { constructor: MutationObserverConstructor }\n      }\n\n      const originalInstance = getZoneJsOriginalValue(patchedInstance, 'originalInstance')\n      constructor = originalInstance && originalInstance.constructor\n    }\n  }\n\n  if (!constructor) {\n    constructor = browserWindow.MutationObserver\n  }\n\n  return constructor\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/firstInputPolyfill.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { addEventListeners, dateNow, DOM_EVENT, relativeNow } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../domain/configuration'\n\n/**\n * first-input timing entry polyfill based on\n * https://github.com/GoogleChrome/web-vitals/blob/master/src/lib/polyfills/firstInputPolyfill.ts\n */\nexport function retrieveFirstInputTiming(\n  configuration: RumConfiguration,\n  callback: (timing: PerformanceEventTiming) => void\n) {\n  const startTimeStamp = dateNow()\n  let timingSent = false\n\n  const { stop: removeEventListeners } = addEventListeners(\n    configuration,\n    window,\n    [DOM_EVENT.CLICK, DOM_EVENT.MOUSE_DOWN, DOM_EVENT.KEY_DOWN, DOM_EVENT.TOUCH_START, DOM_EVENT.POINTER_DOWN],\n    (evt) => {\n      // Only count cancelable events, which should trigger behavior important to the user.\n      if (!evt.cancelable) {\n        return\n      }\n\n      // This timing will be used to compute the \"first Input delay\", which is the delta between\n      // when the system received the event (e.g. evt.timeStamp) and when it could run the callback\n      // (e.g. performance.now()).\n      const timing: PerformanceEventTiming = {\n        entryType: 'first-input',\n        processingStart: relativeNow(),\n        processingEnd: relativeNow(),\n        startTime: evt.timeStamp as RelativeTime,\n        duration: 0 as Duration, // arbitrary value to avoid nullable duration and simplify INP logic\n        name: '',\n        cancelable: false,\n        target: null,\n        interactionId: 0,\n        toJSON: () => ({}),\n      }\n\n      if (evt.type === DOM_EVENT.POINTER_DOWN) {\n        sendTimingIfPointerIsNotCancelled(configuration, timing)\n      } else {\n        sendTiming(timing)\n      }\n    },\n    { passive: true, capture: true }\n  )\n\n  return { stop: removeEventListeners }\n\n  /**\n   * Pointer events are a special case, because they can trigger main or compositor thread behavior.\n   * We differentiate these cases based on whether or not we see a pointercancel event, which are\n   * fired when we scroll. If we're scrolling we don't need to report input delay since FID excludes\n   * scrolling and pinch/zooming.\n   */\n  function sendTimingIfPointerIsNotCancelled(configuration: RumConfiguration, timing: PerformanceEventTiming) {\n    addEventListeners(\n      configuration,\n      window,\n      [DOM_EVENT.POINTER_UP, DOM_EVENT.POINTER_CANCEL],\n      (event) => {\n        if (event.type === DOM_EVENT.POINTER_UP) {\n          sendTiming(timing)\n        }\n      },\n      { once: true }\n    )\n  }\n\n  function sendTiming(timing: PerformanceEventTiming) {\n    if (!timingSent) {\n      timingSent = true\n      removeEventListeners()\n      // In some cases the recorded delay is clearly wrong, e.g. it's negative or it's larger than\n      // the time between now and when the page was loaded.\n      // - https://github.com/GoogleChromeLabs/first-input-delay/issues/4\n      // - https://github.com/GoogleChromeLabs/first-input-delay/issues/6\n      // - https://github.com/GoogleChromeLabs/first-input-delay/issues/7\n      const delay = timing.processingStart - timing.startTime\n      if (delay >= 0 && delay < dateNow() - startTimeStamp) {\n        callback(timing)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/htmlDomUtils.spec.ts",
    "content": "import { appendElement, appendText } from '../../test'\nimport {\n  isTextNode,\n  isCommentNode,\n  isElementNode,\n  isNodeShadowRoot,\n  getParentNode,\n  getParentElement,\n  isNodeShadowHost,\n  forEachChildNodes,\n  hasChildNodes,\n} from './htmlDomUtils'\n\ndescribe('isTextNode', () => {\n  const parameters: Array<[Node, boolean]> = [\n    [document.createTextNode('hello'), true],\n    [document.createElement('div'), false],\n    [document.body, false],\n    [document.createComment('hello'), false],\n    ['hello' as unknown as Node, false],\n  ]\n\n  parameters.forEach(([element, result]) => {\n    // eslint-disable-next-line @typescript-eslint/no-base-to-string\n    it(`should return ${String(result)} for \"${String(element)}\"`, () => {\n      expect(isTextNode(element)).toBe(result)\n    })\n  })\n})\n\ndescribe('isCommentNode', () => {\n  const parameters: Array<[Node, boolean]> = [\n    [document.createComment('hello'), true],\n    [document.createTextNode('hello'), false],\n    [document.createElement('div'), false],\n    [document.body, false],\n    ['hello' as unknown as Node, false],\n  ]\n\n  parameters.forEach(([element, result]) => {\n    // eslint-disable-next-line @typescript-eslint/no-base-to-string\n    it(`should return ${String(result)} for \"${String(element)}\"`, () => {\n      expect(isCommentNode(element)).toBe(result)\n    })\n  })\n})\n\ndescribe('isElementNode', () => {\n  const parameters: Array<[Node, boolean]> = [\n    [document.createElement('div'), true],\n    [document.body, true],\n    [document.createTextNode('hello'), false],\n    [document.createComment('hello'), false],\n    ['hello' as unknown as Node, false],\n  ]\n\n  parameters.forEach(([element, result]) => {\n    // eslint-disable-next-line @typescript-eslint/no-base-to-string\n    it(`should return ${String(result)} for \"${String(element)}\"`, () => {\n      expect(isElementNode(element)).toBe(result)\n    })\n  })\n})\n\ndescribe('isShadowRoot', () => {\n  const notShadowDomNodes: Node[] = [\n    document,\n    document.head,\n    document.body,\n    document.createElement('div'),\n    document.createTextNode('hello'),\n    document.createComment('hello'),\n  ]\n\n  notShadowDomNodes.forEach((element) => {\n    it(`should return false for \"${String(element.nodeName)}\"`, () => {\n      expect(isNodeShadowRoot(element)).toBe(false)\n    })\n  })\n\n  it('should return true for shadow root but not its host', () => {\n    const parent = document.createElement('div')\n    const shadowRoot = parent.attachShadow({ mode: 'open' })\n    expect(isNodeShadowRoot(parent)).toBe(false)\n    expect(isNodeShadowRoot(shadowRoot)).toBe(true)\n  })\n\n  it('should return false for a[href] despite it has a host property', () => {\n    const link = document.createElement('a')\n    link.setAttribute('href', 'http://localhost/some/path')\n    expect(link.host).toBeTruthy()\n    expect(isNodeShadowRoot(link)).toBe(false)\n  })\n\n  it('should return false for a form with an input[name=\"host\"] despite it has a host property', () => {\n    const form = document.createElement('form')\n    const input = document.createElement('input')\n    input.setAttribute('name', 'host')\n    form.appendChild(input)\n    expect(isNodeShadowRoot(form)).toBe(false)\n  })\n})\n\ndescribe('isShadowHost', () => {\n  const host = document.createElement('div')\n  host.attachShadow({ mode: 'open' })\n\n  // Edge 18 and before doesn't support shadow dom, so `Element#shadowRoot` is undefined.\n  const oldEdgeElement = document.createElement('div')\n  Object.defineProperty(oldEdgeElement, 'shadowRoot', { value: undefined })\n\n  const parameters: Array<[Node, boolean]> = [\n    [host, true],\n    [host.shadowRoot!, false],\n    [document.body, false],\n    [document.createTextNode('hello'), false],\n    [document.createComment('hello'), false],\n    [oldEdgeElement, false],\n  ]\n\n  parameters.forEach(([element, result]) => {\n    // eslint-disable-next-line @typescript-eslint/no-base-to-string\n    it(`should return ${String(result)} for \"${String(element)}\"`, () => {\n      expect(isNodeShadowHost(element)).toBe(result)\n    })\n  })\n})\n\ndescribe('hasChildNode', () => {\n  it('should return `true` if the element has a direct child node', () => {\n    expect(hasChildNodes(appendElement('<div>foo</div>'))).toBe(true)\n    expect(hasChildNodes(appendElement('<div><hr /></div>'))).toBe(true)\n    expect(hasChildNodes(appendElement('<div><!--  --></div>'))).toBe(true)\n  })\n\n  it('should return `true` if the element is a shadow host', () => {\n    const container = appendElement('<div></div>')\n    container.attachShadow({ mode: 'open' })\n    expect(hasChildNodes(container)).toBe(true)\n  })\n\n  it('should return `false` otherwise', () => {\n    expect(hasChildNodes(appendElement('<div></div>'))).toBe(false)\n    expect(hasChildNodes(appendText('foo'))).toBe(false)\n  })\n})\n\ndescribe('forEachChildNodes', () => {\n  it('should iterate over the direct children for a normal node', () => {\n    const container = appendElement(`\n      <div>toto<span></span><!-- --></div>\n    `)\n\n    const spy = jasmine.createSpy()\n    forEachChildNodes(container, spy)\n    expect(spy).toHaveBeenCalledTimes(3)\n  })\n\n  it('should iterate over the the shadow root for a node that is a host', () => {\n    const container = appendElement('<div></div>')\n    const shadowRoot = container.attachShadow({ mode: 'open' })\n\n    const spy = jasmine.createSpy()\n    forEachChildNodes(container, spy)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(spy.calls.argsFor(0)[0]).toBe(shadowRoot)\n  })\n\n  it('should iterate over the the shadow root and direct children for a node that is a host', () => {\n    const container = appendElement('<div><span></span></div>')\n    const shadowRoot = container.attachShadow({ mode: 'open' })\n\n    const spy = jasmine.createSpy()\n    forEachChildNodes(container, spy)\n    expect(spy).toHaveBeenCalledTimes(2)\n    expect(spy.calls.argsFor(0)[0]).toBe(container.childNodes[0])\n    expect(spy.calls.argsFor(1)[0]).toBe(shadowRoot)\n  })\n})\n\ndescribe('getParentNode', () => {\n  const orphanDiv = document.createElement('div')\n  const parentWithShadowRoot = document.createElement('div')\n  const shadowRoot = parentWithShadowRoot.attachShadow({ mode: 'open' })\n\n  const parentWithoutShadowRoot = document.createElement('div')\n  const child = document.createElement('span')\n  parentWithoutShadowRoot.appendChild(child)\n\n  const parameters: Array<[string, Node, Node | null]> = [\n    ['return null if without parent', orphanDiv, null],\n    ['return the host for a shadow root', shadowRoot, parentWithShadowRoot],\n    ['return the parent for normal child', child, parentWithoutShadowRoot],\n  ]\n  parameters.forEach(([label, element, result]) => {\n    it(`should ${label}`, () => {\n      expect(getParentNode(element)).toBe(result)\n    })\n  })\n})\n\ndescribe('getParentElement', () => {\n  it('should return parentElement for normal element', () => {\n    const parent = document.createElement('div')\n    const child = document.createElement('span')\n    parent.appendChild(child)\n\n    expect(getParentElement(child)).toBe(parent)\n  })\n\n  it('should return the shadow host for element inside shadow DOM', () => {\n    const host = document.createElement('div')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n    const button = document.createElement('button')\n    shadowRoot.appendChild(button)\n\n    expect(button.parentElement).toBe(null)\n    expect(getParentElement(button)).toBe(host)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/htmlDomUtils.ts",
    "content": "export function isTextNode(node: Node): node is Text {\n  return node.nodeType === Node.TEXT_NODE\n}\n\nexport function isCommentNode(node: Node): node is Comment {\n  return node.nodeType === Node.COMMENT_NODE\n}\n\nexport function isElementNode(node: Node): node is Element {\n  return node.nodeType === Node.ELEMENT_NODE\n}\n\nexport function isNodeShadowHost(node: Node): node is Element & { shadowRoot: ShadowRoot } {\n  return isElementNode(node) && Boolean(node.shadowRoot)\n}\n\nexport function isNodeShadowRoot(node: Node): node is ShadowRoot {\n  const shadowRoot = node as ShadowRoot\n  return !!shadowRoot.host && shadowRoot.nodeType === Node.DOCUMENT_FRAGMENT_NODE && isElementNode(shadowRoot.host)\n}\n\nexport function hasChildNodes(node: Node) {\n  return node.childNodes.length > 0 || isNodeShadowHost(node)\n}\n\nexport function forEachChildNodes(node: Node, callback: (child: Node) => void) {\n  let child = node.firstChild\n\n  while (child) {\n    callback(child)\n\n    child = child.nextSibling\n  }\n\n  if (isNodeShadowHost(node)) {\n    callback(node.shadowRoot)\n  }\n}\n\n/**\n * Return `host` in case if the current node is a shadow root otherwise will return the `parentNode`\n */\nexport function getParentNode(node: Node): Node | null {\n  return isNodeShadowRoot(node) ? node.host : node.parentNode\n}\n\n/**\n * Return the parent element, crossing shadow DOM boundaries.\n * If the element is a direct child of a shadow root, returns the shadow host.\n */\nexport function getParentElement(element: Element): Element | null {\n  if (element.parentElement) {\n    return element.parentElement\n  }\n  const parentNode = element.parentNode\n  if (parentNode && isNodeShadowRoot(parentNode)) {\n    return parentNode.host\n  }\n  return null\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/locationChangeObservable.spec.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { createLocationChangeObservable } from './locationChangeObservable'\n\ndescribe('locationChangeObservable', () => {\n  it('should notify observers on history change', () => {\n    const observer = setup()\n\n    history.pushState({}, '', '/foo?bar=qux')\n\n    const locationChanges = observer.calls.argsFor(0)[0]\n    expect(locationChanges.oldLocation.href).toMatch(/\\/foo$/)\n    expect(locationChanges.newLocation.href).toMatch(/\\/foo\\?bar=qux$/)\n  })\n\n  it('should notify observers on hashchange', (done) => {\n    const observer = setup()\n\n    function hashChangeCallback() {\n      const locationChanges = observer.calls.argsFor(0)[0]\n      expect(locationChanges.oldLocation.href).toMatch(/\\/foo$/)\n      expect(locationChanges.newLocation.href).toMatch(/\\/foo#bar$/)\n\n      window.removeEventListener('hashchange', hashChangeCallback)\n      done()\n    }\n    window.addEventListener('hashchange', hashChangeCallback)\n\n    window.location.hash = '#bar'\n  })\n\n  it('should not notify if the url has not changed', () => {\n    const observer = setup()\n\n    history.pushState({}, '', '/foo')\n\n    expect(observer).not.toHaveBeenCalled()\n  })\n\n  it('allow frameworks to patch history.pushState', () => {\n    const wrapperSpy = setupHistoryInstancePushStateWrapper()\n    const observer = setup()\n\n    history.pushState({}, '', '/foo?bar=qux')\n\n    const locationChanges = observer.calls.argsFor(0)[0]\n    expect(locationChanges.oldLocation.href).toMatch(/\\/foo$/)\n    expect(locationChanges.newLocation.href).toMatch(/\\/foo\\?bar=qux$/)\n    expect(wrapperSpy).toHaveBeenCalled()\n  })\n\n  it('allow frameworks to patch History.prototype.pushState', () => {\n    const wrapperSpy = setupHistoryPrototypePushStateWrapper()\n    const observer = setup()\n\n    history.pushState({}, '', '/foo?bar=qux')\n\n    const locationChanges = observer.calls.argsFor(0)[0]\n    expect(locationChanges.oldLocation.href).toMatch(/\\/foo$/)\n    expect(locationChanges.newLocation.href).toMatch(/\\/foo\\?bar=qux$/)\n    expect(wrapperSpy).toHaveBeenCalled()\n  })\n})\n\nfunction setup() {\n  const originalPathname = location.pathname\n\n  history.pushState({}, '', '/foo')\n\n  const observable = createLocationChangeObservable({} as RumConfiguration)\n  const observer = jasmine.createSpy('obs')\n  const subscription = observable.subscribe(observer)\n\n  registerCleanupTask(() => {\n    subscription.unsubscribe()\n    history.pushState({}, '', originalPathname)\n  })\n\n  return observer\n}\n\nfunction setupHistoryInstancePushStateWrapper() {\n  const wrapperSpy = jasmine.createSpy('wrapperSpy')\n  const originalPushState = history.pushState.bind(history)\n\n  history.pushState = (...args) => {\n    wrapperSpy(...args)\n    originalPushState(...args)\n  }\n\n  registerCleanupTask(() => {\n    // @ts-expect-error reseting history instance to its original state\n    delete history.pushState\n  })\n\n  return wrapperSpy\n}\n\nfunction setupHistoryPrototypePushStateWrapper() {\n  const wrapperSpy = jasmine.createSpy('wrapperSpy')\n  const originalPushState = History.prototype.pushState.bind(history)\n\n  History.prototype.pushState = (...args) => {\n    wrapperSpy(...args)\n    originalPushState(...args)\n  }\n\n  registerCleanupTask(() => {\n    History.prototype.pushState = originalPushState\n  })\n\n  return wrapperSpy\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/locationChangeObservable.ts",
    "content": "import { addEventListener, DOM_EVENT, instrumentMethod, Observable, shallowClone } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../domain/configuration'\n\nexport interface LocationChange {\n  oldLocation: Readonly<Location>\n  newLocation: Readonly<Location>\n}\n\nexport function createLocationChangeObservable(configuration: RumConfiguration) {\n  let currentLocation = shallowClone(location)\n\n  return new Observable<LocationChange>((observable) => {\n    const { stop: stopHistoryTracking } = trackHistory(configuration, onLocationChange)\n    const { stop: stopHashTracking } = trackHash(configuration, onLocationChange)\n\n    function onLocationChange() {\n      if (currentLocation.href === location.href) {\n        return\n      }\n      const newLocation = shallowClone(location)\n      observable.notify({\n        newLocation,\n        oldLocation: currentLocation,\n      })\n      currentLocation = newLocation\n    }\n\n    return () => {\n      stopHistoryTracking()\n      stopHashTracking()\n    }\n  })\n}\n\nfunction trackHistory(configuration: RumConfiguration, onHistoryChange: () => void) {\n  const { stop: stopInstrumentingPushState } = instrumentMethod(\n    getHistoryInstrumentationTarget('pushState'),\n    'pushState',\n    ({ onPostCall }) => {\n      onPostCall(onHistoryChange)\n    }\n  )\n  const { stop: stopInstrumentingReplaceState } = instrumentMethod(\n    getHistoryInstrumentationTarget('replaceState'),\n    'replaceState',\n    ({ onPostCall }) => {\n      onPostCall(onHistoryChange)\n    }\n  )\n  const { stop: removeListener } = addEventListener(configuration, window, DOM_EVENT.POP_STATE, onHistoryChange)\n\n  return {\n    stop: () => {\n      stopInstrumentingPushState()\n      stopInstrumentingReplaceState()\n      removeListener()\n    },\n  }\n}\n\nfunction trackHash(configuration: RumConfiguration, onHashChange: () => void) {\n  return addEventListener(configuration, window, DOM_EVENT.HASH_CHANGE, onHashChange)\n}\n\nfunction getHistoryInstrumentationTarget(methodName: 'pushState' | 'replaceState') {\n  // Ideally we should always instument the method on the prototype, however some frameworks (e.g [Next.js](https://github.com/vercel/next.js/blob/d3f5532065f3e3bb84fb54bd2dfd1a16d0f03a21/packages/next/src/client/components/app-router.tsx#L429))\n  // are wrapping the instance method. In that case we should also wrap the instance method.\n  return Object.prototype.hasOwnProperty.call(history, methodName) ? history : History.prototype\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/performanceObservable.spec.ts",
    "content": "import type { Duration, Subscription } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport { createPerformanceEntry, mockPerformanceObserver, mockRumConfiguration } from '../../test'\nimport { RumPerformanceEntryType, createPerformanceObservable } from './performanceObservable'\n\ndescribe('performanceObservable', () => {\n  let performanceSubscription: Subscription | undefined\n  const configuration = mockRumConfiguration()\n  const forbiddenUrl = 'https://forbidden.url/abce?ddsource=browser&dd-api-key=xxxx&dd-request-id=1234567890'\n  const allowedUrl = 'https://allowed.url'\n  let observableCallback: jasmine.Spy\n  let clock: Clock\n\n  beforeEach(() => {\n    if (!window.PerformanceObserver) {\n      pending('PerformanceObserver not supported')\n    }\n    observableCallback = jasmine.createSpy()\n    clock = mockClock()\n  })\n\n  afterEach(() => {\n    performanceSubscription?.unsubscribe()\n  })\n\n  describe('primary strategy when type supported', () => {\n    it('should notify performance resources', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver()\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: allowedUrl })])\n      expect(observableCallback).toHaveBeenCalledWith([jasmine.objectContaining({ name: allowedUrl })])\n    })\n\n    it('should not notify performance resources with intake url', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver()\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: forbiddenUrl })])\n      expect(observableCallback).not.toHaveBeenCalled()\n    })\n\n    it('should not notify performance resources with invalid duration', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver()\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { duration: -1 as Duration })])\n      expect(observableCallback).not.toHaveBeenCalled()\n    })\n\n    it('should notify buffered performance resources asynchronously', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver()\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: allowedUrl })])\n\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n        buffered: true,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n      expect(observableCallback).not.toHaveBeenCalled()\n      clock.tick(0)\n      expect(observableCallback).toHaveBeenCalledWith([jasmine.objectContaining({ name: allowedUrl })])\n    })\n  })\n\n  describe('fallback strategy when type not supported', () => {\n    it('should notify performance resources when type not supported', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver({ typeSupported: false })\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: allowedUrl })])\n      expect(observableCallback).toHaveBeenCalledWith([jasmine.objectContaining({ name: allowedUrl })])\n    })\n\n    it('should notify buffered performance resources when type not supported', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver({ typeSupported: false })\n      // add the performance entry to the buffer\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: allowedUrl })])\n\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n        buffered: true,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n      expect(observableCallback).not.toHaveBeenCalled()\n      clock.tick(0)\n      expect(observableCallback).toHaveBeenCalledWith([jasmine.objectContaining({ name: allowedUrl })])\n    })\n\n    it('should handle exceptions coming from performance observer .observe()', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver({\n        typeSupported: false,\n        emulateAllEntryTypesUnsupported: true,\n      })\n      const performanceResourceObservable = createPerformanceObservable(configuration, {\n        type: RumPerformanceEntryType.RESOURCE,\n        buffered: true,\n      })\n      performanceSubscription = performanceResourceObservable.subscribe(observableCallback)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE)])\n      expect(observableCallback).not.toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/performanceObservable.ts",
    "content": "import type { Duration, RelativeTime, TimeoutId } from '@datadog/browser-core'\nimport { addEventListener, Observable, setTimeout, clearTimeout, monitor } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../domain/configuration'\nimport { hasValidResourceEntryDuration, isAllowedRequestUrl } from '../domain/resource/resourceUtils'\nimport { retrieveFirstInputTiming } from './firstInputPolyfill'\n\ntype RumPerformanceObserverConstructor = new (callback: PerformanceObserverCallback) => RumPerformanceObserver\n\nexport interface BrowserWindow extends Window {\n  PerformanceObserver: RumPerformanceObserverConstructor\n  performance: Performance & { interactionCount?: number }\n}\n\nexport interface RumPerformanceObserver extends PerformanceObserver {\n  observe(options?: PerformanceObserverInit & { durationThreshold?: number }): void\n}\n\n// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary\n// string is an expected performance entry\n// eslint-disable-next-line no-restricted-syntax\nexport enum RumPerformanceEntryType {\n  EVENT = 'event',\n  FIRST_INPUT = 'first-input',\n  LARGEST_CONTENTFUL_PAINT = 'largest-contentful-paint',\n  LAYOUT_SHIFT = 'layout-shift',\n  LONG_TASK = 'longtask',\n  LONG_ANIMATION_FRAME = 'long-animation-frame',\n  NAVIGATION = 'navigation',\n  PAINT = 'paint',\n  RESOURCE = 'resource',\n  VISIBILITY_STATE = 'visibility-state',\n}\n\nexport interface RumPerformanceLongTaskTiming {\n  name: string\n  entryType: RumPerformanceEntryType.LONG_TASK\n  startTime: RelativeTime\n  duration: Duration\n  toJSON(): Omit<PerformanceEntry, 'toJSON'>\n}\n\nexport interface RumPerformanceResourceTiming {\n  entryType: RumPerformanceEntryType.RESOURCE\n  initiatorType: string\n  responseStatus?: number\n  name: string\n  startTime: RelativeTime\n  duration: Duration\n  fetchStart: RelativeTime\n  workerStart: RelativeTime\n  domainLookupStart: RelativeTime\n  domainLookupEnd: RelativeTime\n  connectStart: RelativeTime\n  secureConnectionStart: RelativeTime\n  connectEnd: RelativeTime\n  requestStart: RelativeTime\n  responseStart: RelativeTime\n  responseEnd: RelativeTime\n  redirectStart: RelativeTime\n  redirectEnd: RelativeTime\n  decodedBodySize?: number\n  encodedBodySize?: number\n  transferSize?: number\n  nextHopProtocol?: string\n  renderBlockingStatus?: string\n  traceId?: string\n  deliveryType?: 'cache' | 'navigational-prefetch' | ''\n  contentType?: string\n  toJSON(): Omit<PerformanceEntry, 'toJSON'>\n}\n\nexport interface RumPerformancePaintTiming {\n  entryType: RumPerformanceEntryType.PAINT\n  name: 'first-paint' | 'first-contentful-paint'\n  startTime: RelativeTime\n  toJSON(): Omit<RumPerformancePaintTiming, 'toJSON'>\n}\n\nexport interface RumPerformanceNavigationTiming extends Omit<RumPerformanceResourceTiming, 'entryType'> {\n  entryType: RumPerformanceEntryType.NAVIGATION\n  initiatorType: 'navigation'\n  name: string\n\n  domComplete: RelativeTime\n  domContentLoadedEventEnd: RelativeTime\n  domInteractive: RelativeTime\n  loadEventEnd: RelativeTime\n\n  toJSON(): Omit<RumPerformanceNavigationTiming, 'toJSON'>\n}\n\nexport interface RumLargestContentfulPaintTiming {\n  entryType: RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT\n  startTime: RelativeTime\n  size: number\n  element?: Element\n  url?: string\n  toJSON(): Omit<RumLargestContentfulPaintTiming, 'toJSON'>\n}\n\nexport interface RumFirstInputTiming {\n  entryType: RumPerformanceEntryType.FIRST_INPUT\n  startTime: RelativeTime\n  processingStart: RelativeTime\n  processingEnd: RelativeTime\n  duration: Duration\n  target?: Node\n  interactionId?: number\n  toJSON(): Omit<RumFirstInputTiming, 'toJSON'>\n}\n\nexport interface RumPerformanceEventTiming {\n  entryType: RumPerformanceEntryType.EVENT\n  startTime: RelativeTime\n  processingStart: RelativeTime\n  processingEnd: RelativeTime\n  duration: Duration\n  interactionId?: number\n  target?: Node\n  name: string\n  toJSON(): Omit<RumPerformanceEventTiming, 'toJSON'>\n}\n\nexport interface RumLayoutShiftAttribution {\n  node: Node | null\n  previousRect: DOMRectReadOnly\n  currentRect: DOMRectReadOnly\n}\n\nexport interface RumLayoutShiftTiming {\n  entryType: RumPerformanceEntryType.LAYOUT_SHIFT\n  startTime: RelativeTime\n  value: number\n  hadRecentInput: boolean\n  sources: RumLayoutShiftAttribution[]\n  toJSON(): Omit<RumLayoutShiftTiming, 'toJSON'>\n}\n\n// Documentation https://developer.chrome.com/docs/web-platform/long-animation-frames#better-attribution\nexport interface RumPerformanceScriptTiming {\n  duration: Duration\n  entryType: 'script'\n  executionStart: RelativeTime\n  forcedStyleAndLayoutDuration: Duration\n  invoker: string // e.g. \"https://static.datadoghq.com/static/c/93085/chunk-bc4db53278fd4c77a637.min.js\"\n  invokerType:\n    | 'user-callback'\n    | 'event-listener'\n    | 'resolve-promise'\n    | 'reject-promise'\n    | 'classic-script'\n    | 'module-script'\n  name: 'script'\n  pauseDuration: Duration\n  sourceCharPosition: number\n  sourceFunctionName: string\n  sourceURL: string\n  startTime: RelativeTime\n  window: Window\n  windowAttribution: string\n}\n\nexport interface RumPerformanceLongAnimationFrameTiming {\n  blockingDuration: Duration\n  duration: Duration\n  entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME\n  firstUIEventTimestamp: RelativeTime\n  name: 'long-animation-frame'\n  renderStart: RelativeTime\n  scripts: RumPerformanceScriptTiming[]\n  startTime: RelativeTime\n  styleAndLayoutStart: RelativeTime\n  toJSON(): Omit<RumPerformanceLongAnimationFrameTiming, 'toJSON'>\n}\n\nexport interface RumFirstHiddenTiming {\n  entryType: RumPerformanceEntryType.VISIBILITY_STATE\n  name: 'hidden' | 'visible'\n  startTime: RelativeTime\n  toJSON(): Omit<RumFirstHiddenTiming, 'toJSON'>\n}\n\nexport type RumPerformanceEntry =\n  | RumPerformanceResourceTiming\n  | RumPerformanceLongTaskTiming\n  | RumPerformanceLongAnimationFrameTiming\n  | RumPerformancePaintTiming\n  | RumPerformanceNavigationTiming\n  | RumLargestContentfulPaintTiming\n  | RumFirstInputTiming\n  | RumPerformanceEventTiming\n  | RumLayoutShiftTiming\n  | RumFirstHiddenTiming\n\nexport interface EntryTypeToReturnType {\n  [RumPerformanceEntryType.EVENT]: RumPerformanceEventTiming\n  [RumPerformanceEntryType.FIRST_INPUT]: RumFirstInputTiming\n  [RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT]: RumLargestContentfulPaintTiming\n  [RumPerformanceEntryType.LAYOUT_SHIFT]: RumLayoutShiftTiming\n  [RumPerformanceEntryType.PAINT]: RumPerformancePaintTiming\n  [RumPerformanceEntryType.LONG_TASK]: RumPerformanceLongTaskTiming\n  [RumPerformanceEntryType.LONG_ANIMATION_FRAME]: RumPerformanceLongAnimationFrameTiming\n  [RumPerformanceEntryType.NAVIGATION]: RumPerformanceNavigationTiming\n  [RumPerformanceEntryType.RESOURCE]: RumPerformanceResourceTiming\n  [RumPerformanceEntryType.VISIBILITY_STATE]: RumFirstHiddenTiming\n}\n\nexport function createPerformanceObservable<T extends RumPerformanceEntryType>(\n  configuration: RumConfiguration,\n  options: { type: T; buffered?: boolean; durationThreshold?: number }\n) {\n  return new Observable<Array<EntryTypeToReturnType[T]>>((observable) => {\n    if (!window.PerformanceObserver) {\n      return\n    }\n\n    const handlePerformanceEntries = (entries: PerformanceEntryList) => {\n      const rumPerformanceEntries = filterRumPerformanceEntries(entries as Array<EntryTypeToReturnType[T]>)\n      if (rumPerformanceEntries.length > 0) {\n        observable.notify(rumPerformanceEntries)\n      }\n    }\n\n    let timeoutId: TimeoutId | undefined\n    let isObserverInitializing = true\n    const observer = new PerformanceObserver(\n      monitor((entries) => {\n        // In Safari the performance observer callback is synchronous.\n        // Because the buffered performance entry list can be quite large we delay the computation to prevent the SDK from blocking the main thread on init\n        if (isObserverInitializing) {\n          timeoutId = setTimeout(() => handlePerformanceEntries(entries.getEntries()))\n        } else {\n          handlePerformanceEntries(entries.getEntries())\n        }\n      })\n    )\n    try {\n      observer.observe(options)\n    } catch {\n      // Some old browser versions (<= chrome 74 ) don't support the PerformanceObserver type and buffered options\n      // In these cases, fallback to getEntriesByType and PerformanceObserver with entryTypes\n      // TODO: remove this fallback in the next major version\n      const fallbackSupportedEntryTypes = [\n        RumPerformanceEntryType.RESOURCE,\n        RumPerformanceEntryType.NAVIGATION,\n        RumPerformanceEntryType.LONG_TASK,\n        RumPerformanceEntryType.PAINT,\n      ]\n      if (fallbackSupportedEntryTypes.includes(options.type)) {\n        if (options.buffered) {\n          timeoutId = setTimeout(() => handlePerformanceEntries(performance.getEntriesByType(options.type)))\n        }\n        try {\n          observer.observe({ entryTypes: [options.type] })\n        } catch {\n          // Old versions of Safari are throwing \"entryTypes contained only unsupported types\"\n          // errors when observing only unsupported entry types.\n          //\n          // We could use `supportPerformanceTimingEvent` to make sure we don't invoke\n          // `observer.observe` with an unsupported entry type, but Safari 11 and 12 don't support\n          // `Performance.supportedEntryTypes`, so doing so would lose support for these versions\n          // even if they do support the entry type.\n          return\n        }\n      }\n    }\n    isObserverInitializing = false\n\n    manageResourceTimingBufferFull(configuration)\n\n    let stopFirstInputTiming: (() => void) | undefined\n    if (\n      !supportPerformanceTimingEvent(RumPerformanceEntryType.FIRST_INPUT) &&\n      options.type === RumPerformanceEntryType.FIRST_INPUT\n    ) {\n      ;({ stop: stopFirstInputTiming } = retrieveFirstInputTiming(configuration, (timing) => {\n        handlePerformanceEntries([timing])\n      }))\n    }\n\n    return () => {\n      observer.disconnect()\n      if (stopFirstInputTiming) {\n        stopFirstInputTiming()\n      }\n      clearTimeout(timeoutId)\n    }\n  })\n}\n\nlet resourceTimingBufferFullListener: { stop: () => void } | undefined\nfunction manageResourceTimingBufferFull(configuration: RumConfiguration) {\n  if (!resourceTimingBufferFullListener && supportPerformanceObject() && 'addEventListener' in performance) {\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=1559377\n    resourceTimingBufferFullListener = addEventListener(configuration, performance, 'resourcetimingbufferfull', () => {\n      performance.clearResourceTimings()\n    })\n  }\n}\n\nexport function resetManageResourceTimingBufferFull() {\n  if (resourceTimingBufferFullListener) {\n    resourceTimingBufferFullListener.stop()\n    resourceTimingBufferFullListener = undefined\n  }\n}\n\nfunction supportPerformanceObject() {\n  return window.performance !== undefined && 'getEntries' in performance\n}\n\nexport function supportPerformanceTimingEvent(entryType: RumPerformanceEntryType) {\n  return (\n    window.PerformanceObserver &&\n    PerformanceObserver.supportedEntryTypes !== undefined &&\n    PerformanceObserver.supportedEntryTypes.includes(entryType)\n  )\n}\n\nfunction filterRumPerformanceEntries<T extends RumPerformanceEntryType>(entries: Array<EntryTypeToReturnType[T]>) {\n  return entries.filter((entry) => !isForbiddenResource(entry))\n}\n\nfunction isForbiddenResource(entry: RumPerformanceEntry) {\n  return (\n    entry.entryType === RumPerformanceEntryType.RESOURCE &&\n    (!isAllowedRequestUrl(entry.name) || !hasValidResourceEntryDuration(entry))\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/performanceUtils.spec.ts",
    "content": "import { type RelativeTime } from '@datadog/browser-core'\nimport { createPerformanceEntry, mockGlobalPerformanceBuffer } from '../../test'\nimport type { RumPerformanceNavigationTiming } from './performanceObservable'\nimport { RumPerformanceEntryType, supportPerformanceTimingEvent } from './performanceObservable'\nimport { findLcpResourceEntry, getNavigationEntry } from './performanceUtils'\n\ndescribe('getNavigationEntry', () => {\n  it('returns the navigation entry', () => {\n    // Declare the expected value here, so TypeScript can make sure all expected fields are covered,\n    // even though the actual value contains more fields.\n    const expectation: jasmine.Expected<RumPerformanceNavigationTiming> = {\n      entryType: RumPerformanceEntryType.NAVIGATION,\n      initiatorType: 'navigation',\n      name: jasmine.any(String),\n\n      domComplete: jasmine.any(Number),\n      domContentLoadedEventEnd: jasmine.any(Number),\n      domInteractive: jasmine.any(Number),\n      loadEventEnd: jasmine.any(Number),\n\n      startTime: 0 as RelativeTime,\n      duration: jasmine.any(Number),\n\n      fetchStart: jasmine.any(Number),\n      workerStart: jasmine.any(Number),\n      domainLookupStart: jasmine.any(Number),\n      domainLookupEnd: jasmine.any(Number),\n      connectStart: jasmine.any(Number),\n      secureConnectionStart: jasmine.any(Number),\n      connectEnd: jasmine.any(Number),\n      requestStart: jasmine.any(Number),\n      responseStart: jasmine.any(Number),\n      responseEnd: jasmine.any(Number),\n      redirectStart: jasmine.any(Number),\n      redirectEnd: jasmine.any(Number),\n\n      toJSON: jasmine.any(Function),\n    }\n\n    const navigationEntry = getNavigationEntry()\n\n    expect(navigationEntry).toEqual(jasmine.objectContaining(expectation))\n\n    if (navigationEntry.decodedBodySize) {\n      expect(navigationEntry.decodedBodySize).toEqual(jasmine.any(Number))\n    }\n    if (navigationEntry.encodedBodySize) {\n      expect(navigationEntry.encodedBodySize).toEqual(jasmine.any(Number))\n    }\n    if (navigationEntry.transferSize) {\n      expect(navigationEntry.transferSize).toEqual(jasmine.any(Number))\n    }\n  })\n})\n\ndescribe('findLcpResourceEntry', () => {\n  beforeEach(() => {\n    if (!supportPerformanceTimingEvent(RumPerformanceEntryType.RESOURCE)) {\n      pending('Resource Timing Event is not supported in this browser')\n    }\n  })\n\n  it('should return undefined when no resource entries exist', () => {\n    mockGlobalPerformanceBuffer([])\n\n    const result = findLcpResourceEntry('https://example.com/image.jpg', 1000 as RelativeTime)\n\n    expect(result).toBeUndefined()\n  })\n\n  it('should return undefined when no matching URL is found', () => {\n    mockGlobalPerformanceBuffer([\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/foo.jpg',\n        startTime: 100 as RelativeTime,\n      }),\n    ])\n\n    const result = findLcpResourceEntry('https://example.com/image.jpg', 1000 as RelativeTime)\n\n    expect(result).toBeUndefined()\n  })\n\n  it('should return the matching resource entry', () => {\n    mockGlobalPerformanceBuffer([\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/image.jpg',\n        startTime: 100 as RelativeTime,\n      }),\n    ])\n\n    const result = findLcpResourceEntry('https://example.com/image.jpg', 1000 as RelativeTime)\n\n    expect(result).toBeDefined()\n    expect(result!.name).toBe('https://example.com/image.jpg')\n  })\n\n  it('should return the most recent matching entry when multiple entries exist for the same URL', () => {\n    mockGlobalPerformanceBuffer([\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/image.jpg',\n        startTime: 100 as RelativeTime,\n        responseEnd: 200 as RelativeTime,\n      }),\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/image.jpg',\n        startTime: 500 as RelativeTime,\n        responseEnd: 600 as RelativeTime,\n      }),\n    ])\n\n    const result = findLcpResourceEntry('https://example.com/image.jpg', 1000 as RelativeTime)\n\n    expect(result).toBeDefined()\n    expect(result!.startTime).toBe(500 as RelativeTime)\n  })\n\n  it('should ignore resource entries that started after LCP time', () => {\n    mockGlobalPerformanceBuffer([\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/image.jpg',\n        startTime: 100 as RelativeTime,\n        responseEnd: 200 as RelativeTime,\n      }),\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/image.jpg',\n        startTime: 1500 as RelativeTime,\n        responseEnd: 1600 as RelativeTime,\n      }),\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n        name: 'https://example.com/image.jpg',\n        startTime: 1500 as RelativeTime,\n      }),\n    ])\n\n    const result = findLcpResourceEntry('https://example.com/image.jpg', 1000 as RelativeTime)\n\n    expect(result).toBeDefined()\n    expect(result!.startTime).toBe(100 as RelativeTime)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/performanceUtils.ts",
    "content": "import type { RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { findLast, getRelativeTime, isNumber, relativeNow } from '@datadog/browser-core'\nimport type { RelevantNavigationTiming } from '../domain/view/viewMetrics/trackNavigationTimings'\nimport type { RumPerformanceNavigationTiming } from './performanceObservable'\nimport { RumPerformanceEntryType, supportPerformanceTimingEvent } from './performanceObservable'\n\nexport function getNavigationEntry(): RumPerformanceNavigationTiming {\n  if (supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION)) {\n    const navigationEntry = performance.getEntriesByType(\n      RumPerformanceEntryType.NAVIGATION\n    )[0] as unknown as RumPerformanceNavigationTiming\n    if (navigationEntry) {\n      return navigationEntry\n    }\n  }\n\n  const timings = computeTimingsFromDeprecatedPerformanceTiming()\n  const entry: RumPerformanceNavigationTiming = {\n    entryType: RumPerformanceEntryType.NAVIGATION as const,\n    initiatorType: 'navigation' as const,\n    name: window.location.href,\n    startTime: 0 as RelativeTime,\n    duration: timings.loadEventEnd,\n    decodedBodySize: 0,\n    encodedBodySize: 0,\n    transferSize: 0,\n    workerStart: 0 as RelativeTime,\n    toJSON: () => ({ ...entry, toJSON: undefined }),\n    ...timings,\n  }\n\n  return entry\n}\n\nexport type TimingsFromDeprecatedPerformanceTiming = {\n  -readonly [key in keyof Omit<PerformanceTiming, 'toJSON'>]: RelativeTime\n}\n\nexport function computeTimingsFromDeprecatedPerformanceTiming() {\n  const result: Partial<TimingsFromDeprecatedPerformanceTiming> = {}\n  const timing = performance.timing\n\n  for (const key in timing) {\n    if (isNumber(timing[key as keyof PerformanceTiming])) {\n      const numberKey = key as keyof TimingsFromDeprecatedPerformanceTiming\n      const timingElement = timing[numberKey] as TimeStamp\n      result[numberKey] = timingElement === 0 ? (0 as RelativeTime) : getRelativeTime(timingElement)\n    }\n  }\n  return result as TimingsFromDeprecatedPerformanceTiming\n}\n\nexport function sanitizeFirstByte(entry: RelevantNavigationTiming) {\n  // In some cases the value reported is negative or is larger\n  // than the current page time. Ignore these cases:\n  // https://github.com/GoogleChrome/web-vitals/issues/137\n  // https://github.com/GoogleChrome/web-vitals/issues/162\n  return entry.responseStart >= 0 && entry.responseStart <= relativeNow() ? entry.responseStart : undefined\n}\n\nexport function getResourceEntries() {\n  if (supportPerformanceTimingEvent(RumPerformanceEntryType.RESOURCE)) {\n    return performance.getEntriesByType(RumPerformanceEntryType.RESOURCE)\n  }\n\n  return undefined\n}\n\n/**\n * Find the most relevant resource entry for an LCP element.\n *\n * Resource entries persist for the entire page lifetime and can include multiple requests\n * for the same URL (preloads, cache-busting reloads, SPA route changes, etc.).\n * This function returns the most recent matching entry that started before the LCP time,\n * which is most likely the one that triggered the LCP paint.\n */\nexport function findLcpResourceEntry(\n  resourceUrl: string,\n  lcpStartTime: RelativeTime\n): PerformanceResourceTiming | undefined {\n  const entries = getResourceEntries()\n  if (!entries) {\n    return undefined\n  }\n\n  return findLast(\n    entries,\n    (entry): entry is PerformanceResourceTiming => entry.name === resourceUrl && entry.startTime <= lcpStartTime\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/scroll.spec.ts",
    "content": "import { waitAfterNextPaint } from '../../../core/test'\nimport { getScrollX, getScrollY } from './scroll'\n\ndescribe('scroll', () => {\n  beforeEach(() => {\n    document.body.style.setProperty('margin-bottom', '5000px')\n  })\n\n  afterEach(async () => {\n    document.body.style.removeProperty('margin-bottom')\n    window.scrollTo(0, 0)\n\n    // Those tests are triggering asynchronous events (notably: window scroll and visualViewport\n    // resize) that might impact tests run after them. To avoid that, we wait for the events before\n    // continuing to the next test.\n    await waitAfterNextPaint()\n  })\n\n  describe('getScrollX/Y', () => {\n    it('normalized scroll matches initial behavior', () => {\n      expect(getScrollX()).toBe(0)\n      expect(getScrollY()).toBe(0)\n      expect(getScrollX()).toBe(window.scrollX || window.pageXOffset)\n      expect(getScrollY()).toBe(window.scrollY || window.pageYOffset)\n    })\n\n    it('normalized scroll updates when scrolled', () => {\n      const SCROLL_DOWN_PX = 100\n\n      window.scrollTo(0, SCROLL_DOWN_PX)\n\n      expect(getScrollX()).toBe(0)\n      expect(getScrollY()).toBe(100)\n      expect(getScrollX()).toBe(window.scrollX || window.pageXOffset)\n      expect(getScrollY()).toBe(window.scrollY || window.pageYOffset)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/scroll.ts",
    "content": "export function getScrollX() {\n  let scrollX\n  const visual = window.visualViewport\n  if (visual) {\n    scrollX = visual.pageLeft - visual.offsetLeft\n  } else if (window.scrollX !== undefined) {\n    scrollX = window.scrollX\n  } else {\n    scrollX = window.pageXOffset || 0\n  }\n  return Math.round(scrollX)\n}\n\nexport function getScrollY() {\n  let scrollY\n  const visual = window.visualViewport\n  if (visual) {\n    scrollY = visual.pageTop - visual.offsetTop\n  } else if (window.scrollY !== undefined) {\n    scrollY = window.scrollY\n  } else {\n    scrollY = window.pageYOffset || 0\n  }\n  return Math.round(scrollY)\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/viewportObservable.spec.ts",
    "content": "import type { Subscription } from '@datadog/browser-core/src/tools/observable'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, createNewEvent, registerCleanupTask, waitAfterNextPaint } from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../test'\nimport type { ViewportDimension } from './viewportObservable'\nimport { getViewportDimension, initViewportObservable } from './viewportObservable'\n\ndescribe('viewportObservable', () => {\n  let viewportSubscription: Subscription\n  let viewportDimension: ViewportDimension\n  let clock: Clock\n  const configuration = mockRumConfiguration()\n\n  beforeEach(() => {\n    viewportSubscription = initViewportObservable(configuration).subscribe((dimension) => {\n      viewportDimension = dimension\n    })\n    clock = mockClock()\n  })\n\n  afterEach(() => {\n    viewportSubscription.unsubscribe()\n  })\n\n  it('should track viewport resize', () => {\n    window.dispatchEvent(createNewEvent('resize'))\n    clock.tick(200)\n\n    expect(viewportDimension).toEqual({ width: jasmine.any(Number), height: jasmine.any(Number) })\n  })\n\n  describe('get layout width and height has similar native behaviour', () => {\n    // innerWidth includes the thickness of the sidebar while `visualViewport.width` and clientWidth exclude it\n    it('without scrollbars', () => {\n      expect(getViewportDimension()).toEqual({ width: window.innerWidth, height: window.innerHeight })\n    })\n\n    it('with scrollbars', () => {\n      // Add scrollbars\n      document.body.style.setProperty('margin-bottom', '5000px')\n      document.body.style.setProperty('margin-right', '5000px')\n      registerCleanupTask(async () => {\n        document.body.style.removeProperty('margin-bottom')\n        document.body.style.removeProperty('margin-right')\n        await waitAfterNextPaint()\n      })\n\n      expect([\n        // Some devices don't follow specification of including scrollbars\n        { width: window.innerWidth, height: window.innerHeight },\n        { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight },\n      ]).toContain(getViewportDimension())\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/viewportObservable.ts",
    "content": "import { Observable, throttle, addEventListener, DOM_EVENT } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../domain/configuration'\n\nexport interface ViewportDimension {\n  height: number\n  width: number\n  [k: string]: unknown\n}\n\nlet viewportObservable: Observable<ViewportDimension> | undefined\n\nexport function initViewportObservable(configuration: RumConfiguration) {\n  if (!viewportObservable) {\n    viewportObservable = createViewportObservable(configuration)\n  }\n  return viewportObservable\n}\n\nexport function createViewportObservable(configuration: RumConfiguration) {\n  return new Observable<ViewportDimension>((observable) => {\n    const { throttled: updateDimension } = throttle(() => {\n      observable.notify(getViewportDimension())\n    }, 200)\n\n    return addEventListener(configuration, window, DOM_EVENT.RESIZE, updateDimension, { capture: true, passive: true })\n      .stop\n  })\n}\n\n// excludes the width and height of any rendered classic scrollbar that is fixed to the visual viewport\nexport function getViewportDimension(): ViewportDimension {\n  const visual = window.visualViewport\n  if (visual) {\n    return {\n      width: Number(visual.width * visual.scale),\n      height: Number(visual.height * visual.scale),\n    }\n  }\n\n  return {\n    width: Number(window.innerWidth || 0),\n    height: Number(window.innerHeight || 0),\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/browser/windowOpenObservable.spec.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\nimport { createWindowOpenObservable } from './windowOpenObservable'\n\ndescribe('windowOpenObservable', () => {\n  it('should notify observer on `window.open` call', () => {\n    const original = window.open\n    window.open = jasmine.createSpy()\n    const spy = jasmine.createSpy()\n\n    const { observable, stop } = createWindowOpenObservable()\n    const { unsubscribe } = observable.subscribe(spy)\n\n    registerCleanupTask(() => {\n      unsubscribe()\n      stop()\n      window.open = original\n    })\n\n    window.open()\n\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/browser/windowOpenObservable.ts",
    "content": "import { instrumentMethod, Observable } from '@datadog/browser-core'\n\nexport function createWindowOpenObservable() {\n  const observable = new Observable<void>()\n  const { stop } = instrumentMethod(window, 'open', () => observable.notify())\n  return { observable, stop }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/actionCollection.spec.ts",
    "content": "import type { Duration, RelativeTime, ServerDuration, TimeStamp } from '@datadog/browser-core'\nimport { addDuration, HookNames, Observable } from '@datadog/browser-core'\nimport { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { collectAndValidateRawRumEvents, mockRumConfiguration } from '../../../test'\nimport type { RawRumActionEvent, RawRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType, ActionType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { AssembleHookParams, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { LONG_TASK_START_TIME_CORRECTION, startActionCollection } from './actionCollection'\nimport { ActionNameSource } from './actionNameConstants'\nimport type { ActionContexts } from './actionCollection'\n\ndescribe('actionCollection', () => {\n  const lifeCycle = new LifeCycle()\n  let hooks: Hooks\n  let addAction: ReturnType<typeof startActionCollection>['addAction']\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>>\n  let actionContexts: ActionContexts\n\n  beforeEach(() => {\n    const domMutationObservable = new Observable<RumMutationRecord[]>()\n    const windowOpenObservable = new Observable<void>()\n    hooks = createHooks()\n\n    const actionCollection = startActionCollection(\n      lifeCycle,\n      hooks,\n      domMutationObservable,\n      windowOpenObservable,\n      mockRumConfiguration()\n    )\n    registerCleanupTask(actionCollection.stop)\n    addAction = actionCollection.addAction\n    actionContexts = actionCollection.actionContexts\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n  })\n\n  it('should create action from auto action with name source', () => {\n    const event = createNewEvent('pointerup', { target: document.createElement('button') })\n    lifeCycle.notify(LifeCycleEventType.AUTO_ACTION_COMPLETED, {\n      counts: {\n        errorCount: 10,\n        longTaskCount: 10,\n        resourceCount: 10,\n      },\n      frustrationTypes: [],\n      duration: 100 as Duration,\n      id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',\n      name: 'foo',\n      nameSource: ActionNameSource.TEXT_CONTENT,\n      startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      type: ActionType.CLICK,\n      event,\n      target: {\n        selector: '#foo',\n        width: 1,\n        height: 2,\n      },\n      position: { x: 1, y: 2 },\n      events: [event],\n    })\n\n    expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)\n    expect(rawRumEvents[0].rawRumEvent).toEqual({\n      action: {\n        error: {\n          count: 10,\n        },\n        id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',\n        loading_time: (100 * 1e6) as ServerDuration,\n        frustration: {\n          type: [],\n        },\n        long_task: {\n          count: 10,\n        },\n        resource: {\n          count: 10,\n        },\n        target: {\n          name: 'foo',\n        },\n        type: ActionType.CLICK,\n      },\n      date: jasmine.any(Number),\n      type: RumEventType.ACTION,\n      _dd: {\n        action: {\n          target: {\n            selector: '#foo',\n            width: 1,\n            height: 2,\n            composed_path_selector: undefined,\n          },\n          name_source: 'text_content',\n          position: {\n            x: 1,\n            y: 2,\n          },\n        },\n      },\n    })\n    expect(rawRumEvents[0].domainContext).toEqual({\n      events: [event],\n    })\n  })\n\n  it('should create action from custom action', () => {\n    addAction({\n      name: 'foo',\n      startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      type: ActionType.CUSTOM,\n      context: { foo: 'bar' },\n    })\n\n    expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)\n    expect(rawRumEvents[0].rawRumEvent).toEqual({\n      action: {\n        id: jasmine.any(String),\n        target: {\n          name: 'foo',\n        },\n        type: ActionType.CUSTOM,\n        frustration: {\n          type: [],\n        },\n      },\n      date: jasmine.any(Number),\n      type: RumEventType.ACTION,\n      context: { foo: 'bar' },\n    })\n\n    expect(rawRumEvents[0].domainContext).toEqual({ handlingStack: undefined })\n  })\n  it('should not set the loading time field of the action', () => {\n    const event = createNewEvent('pointerup', { target: document.createElement('button') })\n    lifeCycle.notify(LifeCycleEventType.AUTO_ACTION_COMPLETED, {\n      counts: {\n        errorCount: 0,\n        longTaskCount: 0,\n        resourceCount: 0,\n      },\n      duration: -10 as Duration,\n      event,\n      events: [event],\n      frustrationTypes: [],\n      id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',\n      name: 'foo',\n      nameSource: ActionNameSource.TEXT_CONTENT,\n      startClocks: { relative: 0 as RelativeTime, timeStamp: 0 as TimeStamp },\n      type: ActionType.CLICK,\n    })\n    expect((rawRumEvents[0].rawRumEvent as RawRumActionEvent).action.loading_time).toBeUndefined()\n  })\n\n  it('should create action with handling stack', () => {\n    addAction({\n      name: 'foo',\n      startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      type: ActionType.CUSTOM,\n      handlingStack: 'Error\\n    at foo\\n    at bar',\n    })\n\n    expect(rawRumEvents[0].domainContext).toEqual({\n      handlingStack: 'Error\\n    at foo\\n    at bar',\n    })\n  })\n\n  describe('assembly hook', () => {\n    ;[RumEventType.RESOURCE, RumEventType.LONG_TASK, RumEventType.ERROR].forEach((eventType) => {\n      it(`should add action properties on ${eventType} from the context`, () => {\n        const actionId = ['1']\n        spyOn(actionContexts, 'findActionId').and.returnValue(actionId)\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType,\n          startTime: 0 as RelativeTime,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({ type: eventType, action: { id: actionId } })\n      })\n    })\n    ;[RumEventType.VIEW, RumEventType.VITAL].forEach((eventType) => {\n      it(`should not add action properties on ${eventType} from the context`, () => {\n        const actionId = ['1']\n        spyOn(actionContexts, 'findActionId').and.returnValue(actionId)\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType,\n          startTime: 0 as RelativeTime,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual(undefined)\n      })\n    })\n\n    it('should add action properties on long task from the context when the start time is slightly before the action start time', () => {\n      const longTaskStartTime = 100 as RelativeTime\n      const findActionIdSpy = spyOn(actionContexts, 'findActionId').and.returnValue([])\n\n      hooks.triggerHook(HookNames.Assemble, {\n        eventType: RumEventType.LONG_TASK,\n        startTime: longTaskStartTime,\n        duration: 50 as Duration,\n      } as AssembleHookParams)\n\n      const [correctedStartTime] = findActionIdSpy.calls.mostRecent().args\n      expect(correctedStartTime).toEqual(addDuration(longTaskStartTime, LONG_TASK_START_TIME_CORRECTION))\n    })\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should add action id', () => {\n      const actionId = ['1']\n      spyOn(actionContexts, 'findActionId').and.returnValue(actionId)\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      }) as DefaultTelemetryEventAttributes\n      // todo: fix telemetry event type\n      expect(telemetryEventAttributes.action?.id).toEqual(actionId as unknown as string)\n    })\n\n    it('should not add action id if the action is not found', () => {\n      spyOn(actionContexts, 'findActionId').and.returnValue([])\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      }) as DefaultTelemetryEventAttributes\n\n      expect(telemetryEventAttributes.action?.id).toEqual([] as unknown as string)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/actionCollection.ts",
    "content": "import type { Duration, Observable, RelativeTime } from '@datadog/browser-core'\nimport { noop, toServerDuration, SKIPPED, HookNames, addDuration } from '@datadog/browser-core'\nimport { discardNegativeDuration } from '../discardNegativeDuration'\nimport type { RawRumActionEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { LifeCycle, RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { RumConfiguration } from '../configuration'\nimport type { DefaultRumEventAttributes, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { trackClickActions } from './trackClickActions'\nimport type { ClickAction } from './trackClickActions'\nimport { trackManualActions } from './trackManualActions'\nimport type { ManualAction } from './trackManualActions'\n\nexport type AutoAction = ClickAction\n\nexport interface ActionContexts {\n  findActionId: (startTime?: RelativeTime) => string[]\n}\n\nexport const LONG_TASK_START_TIME_CORRECTION = 1 as Duration\n\nexport function startActionCollection(\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration\n) {\n  const { unsubscribe: unsubscribeAutoAction } = lifeCycle.subscribe(\n    LifeCycleEventType.AUTO_ACTION_COMPLETED,\n    (action) => {\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processAction(action))\n    }\n  )\n\n  const stopClickActions: () => void = noop\n  let clickActions: ReturnType<typeof trackClickActions> | undefined\n\n  if (configuration.trackUserInteractions) {\n    clickActions = trackClickActions(lifeCycle, domMutationObservable, windowOpenObservable, configuration)\n  }\n\n  const manualActions = trackManualActions(lifeCycle, (action) => {\n    lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processAction(action))\n  })\n\n  const actionContexts: ActionContexts = {\n    findActionId: (startTime?: RelativeTime) => {\n      const manualActionId = manualActions.findActionId(startTime)\n      const clickActionId = clickActions?.findActionId(startTime) ?? []\n      return manualActionId.concat(clickActionId)\n    },\n  }\n\n  hooks.register(HookNames.Assemble, ({ startTime, eventType }): DefaultRumEventAttributes | SKIPPED => {\n    if (\n      eventType !== RumEventType.ERROR &&\n      eventType !== RumEventType.RESOURCE &&\n      eventType !== RumEventType.LONG_TASK\n    ) {\n      return SKIPPED\n    }\n\n    // Long tasks triggered by interaction handlers (pointerup, click, etc.)\n    // can have a start time slightly before the interaction timestamp (long_task.start_time < action.start_time).\n    // This likely happens because the interaction timestamp is recorded during the event dispatch,\n    // not at the beginning of the rendering frame. I observed a difference of < 1 ms in my tests.\n    // Fixes flakiness in test: \"associates long tasks to interaction actions\"\n    const correctedStartTime =\n      eventType === RumEventType.LONG_TASK ? addDuration(startTime, LONG_TASK_START_TIME_CORRECTION) : startTime\n\n    const actionId = actionContexts.findActionId(correctedStartTime)\n\n    if (!actionId.length) {\n      return SKIPPED\n    }\n\n    return {\n      type: eventType,\n      action: { id: actionId },\n    }\n  })\n\n  hooks.register(\n    HookNames.AssembleTelemetry,\n    ({ startTime }): DefaultTelemetryEventAttributes => ({\n      // todo: fix telemetry event type\n      action: { id: actionContexts.findActionId(startTime) as unknown as string },\n    })\n  )\n\n  return {\n    addAction: manualActions.addAction,\n    startAction: manualActions.startAction,\n    stopAction: manualActions.stopAction,\n    actionContexts,\n    stop: () => {\n      unsubscribeAutoAction()\n      stopClickActions()\n      manualActions.stop()\n      clickActions?.stop()\n    },\n  }\n}\n\nfunction processAction(action: AutoAction | ManualAction): RawRumEventCollectedData<RawRumActionEvent> {\n  const isAuto = isAutoAction(action)\n  const loadingTime = discardNegativeDuration(toServerDuration(action.duration))\n\n  return {\n    rawRumEvent: {\n      type: RumEventType.ACTION,\n      date: action.startClocks.timeStamp,\n      action: {\n        id: action.id,\n        target: { name: action.name },\n        type: action.type,\n        ...(loadingTime !== undefined && { loading_time: loadingTime }),\n        ...(action.counts && {\n          error: { count: action.counts.errorCount },\n          long_task: { count: action.counts.longTaskCount },\n          resource: { count: action.counts.resourceCount },\n        }),\n        frustration: { type: action.frustrationTypes },\n      },\n      ...(isAuto\n        ? {\n            _dd: {\n              action: {\n                target: {\n                  selector: action.target?.selector || undefined,\n                  width: action.target?.width || undefined,\n                  height: action.target?.height || undefined,\n                  composed_path_selector: action.target?.composedPathSelector,\n                },\n                position: action.position,\n                name_source: action.nameSource,\n              },\n            },\n          }\n        : { context: action.context }),\n    },\n    duration: action.duration,\n    startClocks: action.startClocks,\n    domainContext: isAuto ? { events: action.events } : { handlingStack: action.handlingStack },\n  }\n}\n\nfunction isAutoAction(action: AutoAction | ManualAction): action is AutoAction {\n  return 'events' in action\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/actionNameConstants.ts",
    "content": "/**\n * Get the action name from the attribute 'data-dd-action-name' on the element or any of its parent.\n * It can also be retrieved from a user defined attribute.\n */\nexport const DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE = 'data-dd-action-name'\nexport const ACTION_NAME_PLACEHOLDER = 'Masked Element'\nexport const ACTION_NAME_MASK = 'xxx'\n\nexport const enum ActionNameSource {\n  CUSTOM_ATTRIBUTE = 'custom_attribute',\n  MASK_PLACEHOLDER = 'mask_placeholder',\n  TEXT_CONTENT = 'text_content',\n  STANDARD_ATTRIBUTE = 'standard_attribute',\n  BLANK = 'blank',\n}\n\nexport interface ActionName {\n  name: string\n  nameSource: ActionNameSource\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/clickChain.spec.ts",
    "content": "import type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport { createFakeClick } from '../../../test'\nimport type { ClickChain } from './clickChain'\nimport { MAX_DISTANCE_BETWEEN_CLICKS, MAX_DURATION_BETWEEN_CLICKS, createClickChain } from './clickChain'\n\ndescribe('createClickChain', () => {\n  let clickChain: ClickChain | undefined\n  let clock: Clock\n  let onFinalizeSpy: jasmine.Spy\n\n  beforeEach(() => {\n    clock = mockClock()\n    onFinalizeSpy = jasmine.createSpy('onFinalize')\n  })\n\n  afterEach(() => {\n    clickChain?.stop()\n  })\n\n  it('creates a click chain', () => {\n    clickChain = createClickChain(createFakeClick(), onFinalizeSpy)\n    expect(clickChain).toEqual({\n      tryAppend: jasmine.any(Function),\n      stop: jasmine.any(Function),\n    })\n  })\n\n  it('appends a click', () => {\n    clickChain = createClickChain(createFakeClick(), onFinalizeSpy)\n    expect(clickChain.tryAppend(createFakeClick())).toBe(true)\n  })\n\n  describe('finalize', () => {\n    it('finalizes if we try to append a non-similar click', () => {\n      const firstClick = createFakeClick({ event: { target: document.documentElement } })\n      clickChain = createClickChain(firstClick, onFinalizeSpy)\n      firstClick.stop()\n      clickChain.tryAppend(createFakeClick({ event: { target: document.body } }))\n      expect(onFinalizeSpy).toHaveBeenCalled()\n    })\n\n    it('does not finalize until it waited long enough to ensure no other click can be appended', () => {\n      const firstClick = createFakeClick()\n      clickChain = createClickChain(firstClick, onFinalizeSpy)\n      firstClick.stop()\n      clock.tick(MAX_DURATION_BETWEEN_CLICKS - 1)\n      expect(onFinalizeSpy).not.toHaveBeenCalled()\n      clock.tick(1)\n      expect(onFinalizeSpy).toHaveBeenCalled()\n    })\n\n    it('does not finalize until all clicks are stopped', () => {\n      const firstClick = createFakeClick()\n      clickChain = createClickChain(firstClick, onFinalizeSpy)\n      clock.tick(MAX_DURATION_BETWEEN_CLICKS)\n      expect(onFinalizeSpy).not.toHaveBeenCalled()\n      firstClick.stop()\n      expect(onFinalizeSpy).toHaveBeenCalled()\n    })\n\n    it('finalizes when stopping the click chain', () => {\n      const firstClick = createFakeClick()\n      clickChain = createClickChain(firstClick, onFinalizeSpy)\n      firstClick.stop()\n      clickChain.stop()\n      expect(onFinalizeSpy).toHaveBeenCalled()\n    })\n  })\n\n  describe('clicks similarity', () => {\n    it('does not accept a click if its timestamp is long after the previous one', () => {\n      clickChain = createClickChain(createFakeClick(), onFinalizeSpy)\n      clock.tick(MAX_DURATION_BETWEEN_CLICKS)\n      expect(clickChain.tryAppend(createFakeClick())).toBe(false)\n    })\n\n    it('does not accept a click if its target is different', () => {\n      clickChain = createClickChain(createFakeClick({ event: { target: document.documentElement } }), onFinalizeSpy)\n      expect(clickChain.tryAppend(createFakeClick({ event: { target: document.body } }))).toBe(false)\n    })\n\n    it('does not accept a click if its location is far from the previous one', () => {\n      clickChain = createClickChain(createFakeClick({ event: { clientX: 100, clientY: 100 } }), onFinalizeSpy)\n      expect(\n        clickChain.tryAppend(\n          createFakeClick({ event: { clientX: 100, clientY: 100 + MAX_DISTANCE_BETWEEN_CLICKS + 1 } })\n        )\n      ).toBe(false)\n    })\n\n    it('considers clicks relative to the previous one', () => {\n      clickChain = createClickChain(createFakeClick(), onFinalizeSpy)\n      clock.tick(MAX_DURATION_BETWEEN_CLICKS - 1)\n      clickChain.tryAppend(createFakeClick())\n      clock.tick(MAX_DURATION_BETWEEN_CLICKS - 1)\n      expect(clickChain.tryAppend(createFakeClick())).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/clickChain.ts",
    "content": "import type { TimeoutId } from '@datadog/browser-core'\nimport { ONE_SECOND, clearTimeout, setTimeout } from '@datadog/browser-core'\nimport type { Click } from './trackClickActions'\n\nexport interface ClickChain {\n  tryAppend: (click: Click) => boolean\n  stop: () => void\n}\n\nexport const MAX_DURATION_BETWEEN_CLICKS = ONE_SECOND\nexport const MAX_DISTANCE_BETWEEN_CLICKS = 100\n\nconst enum ClickChainStatus {\n  WaitingForMoreClicks,\n  WaitingForClicksToStop,\n  Finalized,\n}\n\nexport function createClickChain(firstClick: Click, onFinalize: (clicks: Click[]) => void): ClickChain {\n  const bufferedClicks: Click[] = []\n  let status = ClickChainStatus.WaitingForMoreClicks\n  let maxDurationBetweenClicksTimeoutId: TimeoutId | undefined\n  appendClick(firstClick)\n\n  function appendClick(click: Click) {\n    click.stopObservable.subscribe(tryFinalize)\n    bufferedClicks.push(click)\n    clearTimeout(maxDurationBetweenClicksTimeoutId)\n    maxDurationBetweenClicksTimeoutId = setTimeout(dontAcceptMoreClick, MAX_DURATION_BETWEEN_CLICKS)\n  }\n\n  function tryFinalize() {\n    if (status === ClickChainStatus.WaitingForClicksToStop && bufferedClicks.every((click) => click.isStopped())) {\n      status = ClickChainStatus.Finalized\n      onFinalize(bufferedClicks)\n    }\n  }\n\n  function dontAcceptMoreClick() {\n    clearTimeout(maxDurationBetweenClicksTimeoutId)\n    if (status === ClickChainStatus.WaitingForMoreClicks) {\n      status = ClickChainStatus.WaitingForClicksToStop\n      tryFinalize()\n    }\n  }\n\n  return {\n    tryAppend: (click) => {\n      if (status !== ClickChainStatus.WaitingForMoreClicks) {\n        return false\n      }\n\n      if (\n        bufferedClicks.length > 0 &&\n        !areEventsSimilar(bufferedClicks[bufferedClicks.length - 1].event, click.event)\n      ) {\n        dontAcceptMoreClick()\n        return false\n      }\n\n      appendClick(click)\n      return true\n    },\n    stop: () => {\n      dontAcceptMoreClick()\n    },\n  }\n}\n\n/**\n * Checks whether two events are similar by comparing their target, position and timestamp\n */\nfunction areEventsSimilar(first: MouseEvent, second: MouseEvent) {\n  return (\n    first.target === second.target &&\n    mouseEventDistance(first, second) <= MAX_DISTANCE_BETWEEN_CLICKS &&\n    first.timeStamp - second.timeStamp <= MAX_DURATION_BETWEEN_CLICKS\n  )\n}\n\nfunction mouseEventDistance(origin: MouseEvent, other: MouseEvent) {\n  return Math.sqrt(Math.pow(origin.clientX - other.clientX, 2) + Math.pow(origin.clientY - other.clientY, 2))\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/computeFrustration.spec.ts",
    "content": "import { ONE_SECOND } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport { FrustrationType } from '../../rawRumEvent.types'\nimport type { FakeClick } from '../../../test'\nimport { appendElement, createFakeClick } from '../../../test'\nimport { computeFrustration, isRage, isDead } from './computeFrustration'\n\ndescribe('computeFrustration', () => {\n  let clicks: FakeClick[]\n  let clicksConsideredAsRage: FakeClick[]\n  let rageClick: FakeClick\n\n  beforeEach(() => {\n    clicks = [createFakeClick(), createFakeClick()]\n    clicksConsideredAsRage = [createFakeClick(), createFakeClick(), createFakeClick()]\n    rageClick = createFakeClick()\n  })\n\n  it('returns whether the clicks are considered as rage', () => {\n    expect(computeFrustration(clicksConsideredAsRage, rageClick).isRage).toBeTrue()\n    expect(computeFrustration(clicks, rageClick).isRage).toBeFalse()\n  })\n\n  describe('if clicks are considered as rage', () => {\n    it('adds a rage frustration to the rage click', () => {\n      computeFrustration(clicksConsideredAsRage, rageClick)\n      expect(getFrustrations(rageClick)).toEqual([FrustrationType.RAGE_CLICK])\n    })\n\n    it('adds a dead frustration to the rage click if any click does not have page activity', () => {\n      clicksConsideredAsRage[1] = createFakeClick({ hasPageActivity: false })\n      computeFrustration(clicksConsideredAsRage, rageClick)\n      expect(getFrustrations(rageClick)).toEqual([FrustrationType.RAGE_CLICK, FrustrationType.DEAD_CLICK])\n    })\n\n    it('do not add a dead frustration to the rage click if clicks are associated with an \"input\" event', () => {\n      clicksConsideredAsRage[1] = createFakeClick({ hasPageActivity: false, userActivity: { input: true } })\n      computeFrustration(clicksConsideredAsRage, rageClick)\n      expect(getFrustrations(rageClick)).toEqual([FrustrationType.RAGE_CLICK])\n    })\n\n    it('adds an error frustration to the rage click if an error occurs during the rage click lifetime', () => {\n      rageClick = createFakeClick({ hasError: true })\n      computeFrustration(clicksConsideredAsRage, rageClick)\n      expect(getFrustrations(rageClick)).toEqual([FrustrationType.RAGE_CLICK, FrustrationType.ERROR_CLICK])\n    })\n  })\n\n  describe('if clicks are not considered as rage', () => {\n    it('does not add any frustration by default', () => {\n      computeFrustration(clicks, rageClick)\n      for (const click of clicks) {\n        expect(getFrustrations(click)).toEqual([])\n      }\n    })\n\n    it('adds a dead frustration to clicks that do not have activity', () => {\n      clicks[1] = createFakeClick({ hasPageActivity: false })\n      computeFrustration(clicks, rageClick)\n      expect(getFrustrations(clicks[1])).toEqual([FrustrationType.DEAD_CLICK])\n    })\n\n    it('does not add a dead frustration when double clicking to select a word', () => {\n      clicks[0] = createFakeClick({ userActivity: { selection: true } })\n      clicks[1] = createFakeClick({ hasPageActivity: false })\n      computeFrustration(clicks, rageClick)\n      expect(getFrustrations(clicks[1])).toEqual([])\n    })\n\n    it('adds an error frustration to clicks that have an error', () => {\n      clicks[1] = createFakeClick({ hasError: true })\n      computeFrustration(clicks, rageClick)\n      expect(getFrustrations(clicks[1])).toEqual([FrustrationType.ERROR_CLICK])\n    })\n  })\n\n  function getFrustrations(click: FakeClick) {\n    return click.addFrustration.calls.allArgs().map((args) => args[0])\n  }\n})\n\ndescribe('isRage', () => {\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  it('considers as rage three clicks happening at the same time', () => {\n    expect(isRage([createFakeClick(), createFakeClick(), createFakeClick()])).toBe(true)\n  })\n\n  it('does not consider as rage when triple clicking to select a paragraph', () => {\n    expect(isRage([createFakeClick(), createFakeClick({ userActivity: { selection: true } }), createFakeClick()])).toBe(\n      false\n    )\n  })\n\n  it('does not consider rage when at least one click is related to a \"scroll\" event', () => {\n    expect(isRage([createFakeClick(), createFakeClick({ userActivity: { scroll: true } }), createFakeClick()])).toBe(\n      false\n    )\n  })\n\n  it('does not consider as rage two clicks happening at the same time', () => {\n    expect(isRage([createFakeClick(), createFakeClick()])).toBe(false)\n  })\n\n  it('does not consider as rage a first click long before two fast clicks', () => {\n    const clicks = [createFakeClick()]\n    clock.tick(ONE_SECOND * 2)\n    clicks.push(createFakeClick(), createFakeClick())\n\n    expect(isRage(clicks)).toBe(false)\n  })\n\n  it('considers as rage a first click long before three fast clicks', () => {\n    const clicks = [createFakeClick()]\n    clock.tick(ONE_SECOND * 2)\n    clicks.push(createFakeClick(), createFakeClick(), createFakeClick())\n\n    expect(isRage(clicks)).toBe(true)\n  })\n\n  it('considers as rage three fast clicks long before a last click', () => {\n    const clicks = [createFakeClick(), createFakeClick(), createFakeClick()]\n    clock.tick(ONE_SECOND * 2)\n    clicks.push(createFakeClick())\n\n    expect(isRage(clicks)).toBe(true)\n  })\n})\n\ndescribe('isDead', () => {\n  it('considers as dead when the click has no page activity', () => {\n    expect(isDead(createFakeClick({ hasPageActivity: false }))).toBe(true)\n  })\n\n  it('does not consider as dead when the click has page activity', () => {\n    expect(isDead(createFakeClick({ hasPageActivity: true }))).toBe(false)\n  })\n\n  it('does not consider as dead when the click is related to an \"input\" event', () => {\n    expect(isDead(createFakeClick({ hasPageActivity: false, userActivity: { input: true } }))).toBe(false)\n  })\n\n  it('does not consider as dead when the click is related to a \"scroll\" event', () => {\n    expect(isDead(createFakeClick({ hasPageActivity: false, userActivity: { scroll: true } }))).toBe(false)\n  })\n\n  for (const { element, expected } of [\n    { element: '<input />', expected: false },\n    { element: '<textarea />', expected: false },\n    { element: '<input type=\"checkbox\" />', expected: true },\n    { element: '<input type=\"password\" />', expected: false },\n    { element: '<canvas  />', expected: false },\n    { element: '<a id=\"foo\">Foo</a>', expected: true },\n    { element: '<a href=\"foo\">Foo</a>', expected: false },\n    { element: '<a href=\"foo\">Foo<span target>bar</span></a>', expected: false },\n    { element: '<div contenteditable>Foo bar</div>', expected: false },\n    { element: '<div contenteditable>Foo<span target>bar</span></div>', expected: false },\n  ]) {\n    it(`does not consider as dead when the click target is ${element}`, () => {\n      expect(\n        isDead(\n          createFakeClick({\n            hasPageActivity: false,\n            event: { target: appendElement(element) },\n          })\n        )\n      ).toBe(expected)\n    })\n  }\n\n  describe('label elements', () => {\n    it('does not consider as dead when the click target is a label referring to a text input', () => {\n      appendElement('<input type=\"text\" id=\"test-input\" />')\n      const label = appendElement('<label for=\"test-input\">Click me</label>')\n\n      expect(\n        isDead(\n          createFakeClick({\n            hasPageActivity: false,\n            event: { target: label },\n          })\n        )\n      ).toBe(false)\n    })\n\n    it('considers as dead when the click target is a label referring to a checkbox', () => {\n      appendElement('<input type=\"checkbox\" id=\"test-checkbox\" />')\n      const label = appendElement('<label for=\"test-checkbox\">Check me</label>')\n\n      expect(\n        isDead(\n          createFakeClick({\n            hasPageActivity: false,\n            event: { target: label },\n          })\n        )\n      ).toBe(true)\n    })\n\n    it('considers as dead when the click target is a label referring to a non-existent element', () => {\n      const label = appendElement('<label for=\"non-existent-id\">Click me</label>')\n\n      expect(\n        isDead(\n          createFakeClick({\n            hasPageActivity: false,\n            event: { target: label },\n          })\n        )\n      ).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/computeFrustration.ts",
    "content": "import { ONE_SECOND } from '@datadog/browser-core'\nimport { FrustrationType } from '../../rawRumEvent.types'\nimport type { Click } from './trackClickActions'\n\nconst MIN_CLICKS_PER_SECOND_TO_CONSIDER_RAGE = 3\n\nexport function computeFrustration(clicks: Click[], rageClick: Click) {\n  if (isRage(clicks)) {\n    rageClick.addFrustration(FrustrationType.RAGE_CLICK)\n    if (clicks.some(isDead)) {\n      rageClick.addFrustration(FrustrationType.DEAD_CLICK)\n    }\n    if (rageClick.hasError) {\n      rageClick.addFrustration(FrustrationType.ERROR_CLICK)\n    }\n    return { isRage: true }\n  }\n\n  const hasSelectionChanged = clicks.some((click) => click.getUserActivity().selection)\n  clicks.forEach((click) => {\n    if (click.hasError) {\n      click.addFrustration(FrustrationType.ERROR_CLICK)\n    }\n    if (\n      isDead(click) &&\n      // Avoid considering clicks part of a double-click or triple-click selections as dead clicks\n      !hasSelectionChanged\n    ) {\n      click.addFrustration(FrustrationType.DEAD_CLICK)\n    }\n  })\n  return { isRage: false }\n}\n\nexport function isRage(clicks: Click[]) {\n  if (clicks.some((click) => click.getUserActivity().selection || click.getUserActivity().scroll)) {\n    return false\n  }\n  for (let i = 0; i < clicks.length - (MIN_CLICKS_PER_SECOND_TO_CONSIDER_RAGE - 1); i += 1) {\n    if (\n      clicks[i + MIN_CLICKS_PER_SECOND_TO_CONSIDER_RAGE - 1].event.timeStamp - clicks[i].event.timeStamp <=\n      ONE_SECOND\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\nconst DEAD_CLICK_EXCLUDE_SELECTOR =\n  // inputs that don't trigger a meaningful event like \"input\" when clicked, including textual\n  // inputs (using a negative selector is shorter here)\n  'input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"button\"]):not([type=\"submit\"]):not([type=\"reset\"]):not([type=\"range\"]),' +\n  'textarea,' +\n  'select,' +\n  // contenteditable and their descendants don't always trigger meaningful changes when manipulated\n  '[contenteditable],' +\n  '[contenteditable] *,' +\n  // canvas, as there is no good way to detect activity occurring on them\n  'canvas,' +\n  // links that are interactive (have an href attribute) or any of their descendants, as they can\n  // open a new tab or navigate to a hash without triggering a meaningful event\n  'a[href],' +\n  'a[href] *'\n\nexport function isDead(click: Click) {\n  if (click.hasPageActivity || click.getUserActivity().input || click.getUserActivity().scroll) {\n    return false\n  }\n\n  let target: Element | null = click.event.target\n\n  if (target.tagName === 'LABEL' && target.hasAttribute('for')) {\n    target = document.getElementById(target.getAttribute('for')!)\n  }\n\n  return !target || !target.matches(DEAD_CLICK_EXCLUDE_SELECTOR)\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/getActionNameFromElement.spec.ts",
    "content": "import { addExperimentalFeatures, ExperimentalFeature } from '@datadog/browser-core'\nimport { appendElement, mockRumConfiguration } from '../../../test'\nimport { NodePrivacyLevel } from '../privacyConstants'\nimport { getNodeSelfPrivacyLevel } from '../privacy'\nimport { getActionNameFromElement } from './getActionNameFromElement'\nimport { ActionNameSource } from './actionNameConstants'\n\nconst defaultConfiguration = mockRumConfiguration()\n\ndescribe('getActionNameFromElement', () => {\n  it('extracts the textual content of an element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<div>Foo <div>bar</div></div>'),\n      defaultConfiguration\n    )\n    expect(name).toBe('Foo bar')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts the text of an input button', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<input type=\"button\" value=\"Click\" />'),\n      defaultConfiguration\n    )\n    expect(name).toBe('Click')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts the alt text of an image', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<img title=\"foo\" alt=\"bar\" />'),\n      defaultConfiguration\n    )\n    expect(name).toBe('bar')\n    expect(nameSource).toBe('standard_attribute')\n  })\n\n  it('extracts the title text of an image', () => {\n    const { name, nameSource } = getActionNameFromElement(appendElement('<img title=\"foo\" />'), defaultConfiguration)\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('standard_attribute')\n  })\n\n  it('extracts the text of an aria-label attribute', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<span aria-label=\"Foo\" />'),\n      defaultConfiguration\n    )\n    expect(name).toBe('Foo')\n    expect(nameSource).toBe('standard_attribute')\n  })\n\n  it('gets the parent element textual content if everything else fails', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<div>Foo <img target /></div>'),\n      defaultConfiguration\n    )\n    expect(name).toBe('Foo')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it(\"doesn't get the value of a text input\", () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<input type=\"text\" value=\"foo\" />'),\n      defaultConfiguration\n    )\n    expect(name).toBe('')\n    expect(nameSource).toBe('blank')\n  })\n\n  it(\"doesn't get the value of a password input\", () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<input type=\"password\" value=\"foo\" />'),\n      defaultConfiguration\n    )\n    expect(name).toBe('')\n    expect(nameSource).toBe('blank')\n  })\n\n  it('limits the { name, nameSource } length to a reasonable size', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(\n        '<div>Foooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz</div>'\n      ),\n      defaultConfiguration\n    )\n    expect(name).toBe(\n      'Foooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [...]'\n    )\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('normalize white spaces', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<div>foo\\tbar\\n\\n  baz</div>'),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo bar baz')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('should correctly compute whitespace for <br> and <p> elements', () => {\n    const testCases = [\n      { element: appendElement('<div>hello<br/>world</div>'), expected: 'hello world' },\n      { element: appendElement('<div>hello<p>world</p></div>'), expected: 'hello world' },\n      { element: appendElement('<div>hello<p>world<br/>!</p></div>'), expected: 'hello world !' },\n      { element: appendElement('<div>hello world<br/>!<p>!</p></div>'), expected: 'hello world ! !' },\n    ]\n    testCases.forEach(({ element, expected }) => {\n      const { name, nameSource } = getActionNameFromElement(element, defaultConfiguration)\n      expect(name).toBe(expected)\n      expect(nameSource).toBe('text_content')\n    })\n  })\n\n  it('should introduce whitespace for block-level display values', () => {\n    addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n    const testCases = [\n      { display: 'block', expected: 'space' },\n      { display: 'inline-block', expected: 'no-space' },\n      { display: 'flex', expected: 'space' },\n      { display: 'inline-flex', expected: 'no-space' },\n      { display: 'grid', expected: 'space' },\n      { display: 'inline-grid', expected: 'no-space' },\n      { display: 'list-item', expected: 'space' },\n      { display: 'table', expected: 'space' },\n      { display: 'table-caption', expected: 'space' },\n      { display: 'inline', expected: 'no-space' },\n      { display: 'none', expected: 'nothing' },\n    ]\n    testCases.forEach(({ display, expected }) => {\n      const element = appendElement(\n        `<div><div style=\"display: ${display}\">foo</div><div style=\"display: ${display}\">bar</div></div>`\n      )\n      const { name, nameSource } = getActionNameFromElement(element, defaultConfiguration)\n      switch (expected) {\n        case 'space':\n          expect(name).toBe('foo bar')\n          expect(nameSource).toBe('text_content')\n          break\n        case 'no-space':\n          expect(name).toBe('foobar')\n          expect(nameSource).toBe('text_content')\n          break\n        case 'nothing':\n          expect(name).toBe('')\n          expect(nameSource).toBe('blank')\n          break\n      }\n    })\n  })\n\n  it('ignores the inline script textual content', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(\"<div><script>console.log('toto')</script>b</div>\"),\n      defaultConfiguration\n    )\n    expect(name).toBe('b')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from SVG elements', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement('<svg><text>foo  bar</text></svg>'),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo bar')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from an associated label', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <label for=\"toto\">label text</label>\n        <div>ignored</div>\n        <input id=\"toto\" target />\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('label text')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from a parent label', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <label>\n        foo\n        <div>\n          bar\n          <input target />\n        </div>\n      </label>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo bar')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from the first OPTION element when clicking on a SELECT', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <select>\n        <option>foo</option>\n        <option>bar</option>\n      </select>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from a aria-labelledby associated element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <label id=\"toto\">label text</label>\n        <div>ignored</div>\n        <input aria-labelledby=\"toto\" target />\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('label text')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from multiple aria-labelledby associated elements', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <label id=\"toto1\">label</label>\n        <div>ignored</div>\n        <input aria-labelledby=\"toto1 toto2\" target />\n        <div>ignored</div>\n        <label id=\"toto2\">text</label>\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('label text')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from a BUTTON element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <div>ignored</div>\n        <button target>foo</button>\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('extracts text from a role=button element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <div>ignored</div>\n        <div role=\"button\" target>foo</div>\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('limits the recursion to the 10th parent', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <div>ignored</div>\n        <i><i><i><i><i><i><i><i><i><i>\n          <i target></i>\n        </i></i></i></i></i></i></i></i></i></i>\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('')\n    expect(nameSource).toBe('blank')\n  })\n\n  it('limits the recursion to the BODY element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>ignored</div>\n      <i target></i>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('')\n    expect(nameSource).toBe('blank')\n  })\n\n  it('limits the recursion to a FORM element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <div>ignored</div>\n        <form>\n          <i target></i>\n        </form>\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('')\n    expect(nameSource).toBe('blank')\n  })\n\n  it('extracts the { name, nameSource } from a parent FORM element', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div>\n        <div>ignored</div>\n        <form title=\"foo\">\n          <i target></i>\n        </form>\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('standard_attribute')\n  })\n\n  it('extracts the whole textual content of a button', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <button>\n        foo\n        <i target>bar</i>\n      </button>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo bar')\n    expect(nameSource).toBe('text_content')\n  })\n\n  it('ignores the textual content of contenteditable elements', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div contenteditable>\n        <i target>ignored</i>\n        ignored\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('')\n    expect(nameSource).toBe('blank')\n  })\n\n  it('extracts the { name, nameSource } from attributes of contenteditable elements', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n      <div contenteditable>\n        <i aria-label=\"foo\" target>ignored</i>\n        ignored\n      </div>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('standard_attribute')\n  })\n\n  it('computes an action name on SVG elements', () => {\n    const { name, nameSource } = getActionNameFromElement(\n      appendElement(`\n       <button>\n        foo <svg target></svg>\n       <button>\n    `),\n      defaultConfiguration\n    )\n    expect(name).toBe('foo')\n    expect(nameSource).toBe('text_content')\n  })\n\n  describe('programmatically declared action name', () => {\n    it('extracts the name from the data-dd-action-name attribute', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <div data-dd-action-name=\"foo\">ignored</div>\n      `),\n        defaultConfiguration\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('considers any parent', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <form data-dd-action-name=\"foo\">\n          <i><i><i><i><i><i><i><i><i><i><i><i>\n            <span target>ignored</span>\n          </i></i></i></i></i></i></i></i></i></i></i></i>\n        </form>\n      `),\n        defaultConfiguration\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('normalizes the value', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <div data-dd-action-name=\"   foo  \\t bar  \">ignored</div>\n      `),\n        defaultConfiguration\n      )\n      expect(name).toBe('foo bar')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('fallback on an automatic strategy if the attribute is empty', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <div data-dd-action-name=\"ignored\">\n          <div data-dd-action-name=\"\">\n            <span target>foo</span>\n          </div>\n        </div>\n    `),\n        defaultConfiguration\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('extracts the name from a user-configured attribute', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <div data-test-id=\"foo\">ignored</div>\n      `),\n        {\n          ...defaultConfiguration,\n          actionNameAttribute: 'data-test-id',\n        },\n        undefined\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('favors data-dd-action-name over user-configured attribute', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <div data-test-id=\"foo\" data-dd-action-name=\"bar\">ignored</div>\n      `),\n        {\n          ...defaultConfiguration,\n          actionNameAttribute: 'data-test-id',\n        },\n        undefined\n      )\n      expect(name).toBe('bar')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('removes children with programmatic action name in textual content', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement('<div>Foo <div data-dd-action-name=\"custom action\">bar<div></div>'),\n        defaultConfiguration\n      )\n\n      expect(name).toBe('Foo')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('removes only the child with programmatic action name in textual content', () => {\n      addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement('<div>Foobar Baz<div data-dd-action-name=\"custom action\">bar<div></div>'),\n        defaultConfiguration\n      )\n      expect(name).toBe('Foobar Baz')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('remove children with programmatic action name in textual content based on the user-configured attribute', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement('<div>Foo <div data-test-id=\"custom action\">bar<div></div>'),\n        {\n          ...defaultConfiguration,\n          actionNameAttribute: 'data-test-id',\n        },\n        undefined\n      )\n      expect(name).toBe('Foo')\n      expect(nameSource).toBe('text_content')\n    })\n  })\n  describe('with allowlist and enablePrivacyForActionName is true', () => {\n    interface BrowserWindow extends Window {\n      $DD_ALLOW?: Set<string>\n    }\n\n    it('preserves privacy level of the element when defaultPrivacyLevel is mask-unless-allowlisted', () => {\n      addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n        <div data-dd-privacy=\"mask\">\n          <span target>bar</span>\n        </div>\n      `),\n        {\n          ...defaultConfiguration,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          enablePrivacyForActionName: true,\n        },\n        NodePrivacyLevel.MASK\n      )\n      expect(name).toBe('Masked Element')\n      expect(nameSource).toBe('mask_placeholder')\n    })\n\n    it('preserves privacy level of the element when node privacy level is mask-unless-allowlisted', () => {\n      const testCases = [\n        {\n          html: `\n           <div data-dd-privacy=\"mask-unless-allowlisted\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"mask\">\n              <span>bar</span>\n              <div data-dd-privacy=\"allow\">\n                <span>baz</span>\n              </div>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          expectedName: '',\n          expectedNameSource: 'blank',\n        },\n        {\n          html: `\n           <div data-dd-privacy=\"mask-unless-allowlisted\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"mask\">\n              <span>bar</span>\n              <div data-dd-privacy=\"allow\">\n                <span>baz</span>\n              </div>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          allowlist: ['foo'],\n          expectedName: 'foo',\n          expectedNameSource: 'text_content',\n        },\n        {\n          html: `\n           <div data-dd-privacy=\"mask-unless-allowlisted\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"allow\">\n              <span>baz</span>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          expectedName: 'baz',\n          expectedNameSource: 'text_content',\n        },\n        {\n          html: `\n          <div data-dd-privacy=\"mask\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"mask-unless-allowlisted\">\n              <span>bar</span>\n              <div data-dd-privacy=\"allow\">\n                <span>baz</span>\n              </div>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          expectedName: 'Masked Element',\n          expectedNameSource: 'mask_placeholder',\n        },\n        {\n          html: `\n          <div data-dd-privacy=\"allow\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"mask-unless-allowlisted\">\n              <span>bar</span>\n              <div data-dd-privacy=\"allow\">\n                <span>baz</span>\n              </div>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          expectedName: 'foo baz',\n          expectedNameSource: 'text_content',\n        },\n        {\n          html: `\n          <div data-dd-privacy=\"allow\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"mask-unless-allowlisted\">\n              <span>bar</span>\n              <div data-dd-privacy=\"mask\">\n                <span>baz</span>\n              </div>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          expectedName: 'foo',\n          expectedNameSource: 'text_content',\n        },\n        {\n          html: `\n          <div data-dd-privacy=\"allow\" target>\n            <span>foo</span>\n            <div data-dd-privacy=\"mask-unless-allowlisted\">\n              <span>bar</span>\n              <div data-dd-privacy=\"allow\">\n                <span>baz</span>\n              </div>\n            </div>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          allowlist: ['bar'],\n          expectedName: 'foo bar baz',\n          expectedNameSource: 'text_content',\n        },\n        {\n          html: `\n          <div data-dd-privacy=\"mask-unless-allowlisted\" alt=\"bar\" target>\n            <span>bar</span>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          expectedName: 'Masked Element',\n          expectedNameSource: 'standard_attribute',\n        },\n        {\n          html: `\n          <div data-dd-privacy=\"mask-unless-allowlisted\" alt=\"foo\" target>\n            <span>bar</span>\n          </div>\n          `,\n          defaultPrivacyLevel: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n          allowlist: ['foo'],\n          expectedName: 'foo',\n          expectedNameSource: 'standard_attribute',\n        },\n      ]\n      testCases.forEach(({ html, defaultPrivacyLevel, allowlist, expectedName, expectedNameSource }) => {\n        addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n        ;(window as BrowserWindow).$DD_ALLOW = new Set(allowlist)\n        const target = appendElement(html)\n        const { name, nameSource } = getActionNameFromElement(\n          target,\n          {\n            ...defaultConfiguration,\n            defaultPrivacyLevel,\n            enablePrivacyForActionName: true,\n          },\n          getNodeSelfPrivacyLevel(target)\n        )\n        expect(name).toBe(expectedName)\n        expect(nameSource).toBe(expectedNameSource)\n      })\n    })\n  })\n\n  describe('with privacyEnabledForActionName', () => {\n    it('extracts attribute text when privacyEnabledActionName is false', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n          <div data-dd-action-name=\"foo\">\n            <span target>ignored</span>\n          </div>\n    `),\n        defaultConfiguration,\n        NodePrivacyLevel.MASK\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('extracts user defined attribute text when privacyEnabledActionName is false', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n          <div data-test-id=\"foo\">\n            <span target>ignored</span>\n          </div>\n    `),\n        {\n          ...defaultConfiguration,\n          actionNameAttribute: 'data-test-id',\n        },\n        NodePrivacyLevel.MASK\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('extracts inner text when privacyEnabledActionName is false and custom action name set to empty', () => {\n      const { name, nameSource } = getActionNameFromElement(\n        appendElement(`\n          <div data-test-id=\"\">\n            <span target>foo</span>\n          </div>\n    `),\n        {\n          ...defaultConfiguration,\n          actionNameAttribute: 'data-test-id',\n        },\n        NodePrivacyLevel.ALLOW\n      )\n      expect(name).toBe('foo')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('returns placeholder when privacyEnabledActionName is true and custom action name set to empty', () => {\n      expect(\n        getActionNameFromElement(\n          appendElement(`\n            <div data-test-id=\"\">\n              <span target>foo</span>\n            </div>\n      `),\n          {\n            ...defaultConfiguration,\n            actionNameAttribute: 'data-test-id',\n            enablePrivacyForActionName: true,\n          },\n          NodePrivacyLevel.MASK\n        )\n      ).toEqual({ name: 'Masked Element', nameSource: ActionNameSource.MASK_PLACEHOLDER })\n    })\n\n    it('extracts default attribute text when privacyEnabledActionName is true', () => {\n      expect(\n        getActionNameFromElement(\n          appendElement(`\n            <div data-dd-action-name=\"foo\">\n              <span target>ignored</span>\n            </div>\n      `),\n          defaultConfiguration,\n          NodePrivacyLevel.ALLOW\n        )\n      ).toEqual({ name: 'foo', nameSource: ActionNameSource.CUSTOM_ATTRIBUTE })\n    })\n\n    it('extracts user defined attribute text when privacyEnabledActionName is true', () => {\n      expect(\n        getActionNameFromElement(\n          appendElement(`\n            <div data-test-id=\"foo\">\n              <span target>ignored</span>\n            </div>\n      `),\n          {\n            ...defaultConfiguration,\n            actionNameAttribute: 'data-test-id',\n          },\n          NodePrivacyLevel.ALLOW\n        )\n      ).toEqual({ name: 'foo', nameSource: ActionNameSource.CUSTOM_ATTRIBUTE })\n    })\n\n    describe('with html tag privacy override when privacyEnabledActionName is true', () => {\n      it('extracts inner text when privacy level is allow', () => {\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div data-dd-privacy=\"allow\">\n                <span target>foo</span>\n              </div>\n        `),\n            defaultConfiguration,\n            NodePrivacyLevel.ALLOW\n          )\n        ).toEqual({ name: 'foo', nameSource: ActionNameSource.TEXT_CONTENT })\n      })\n\n      it('returns placeholder when privacy level is mask', () => {\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div data-dd-privacy=\"mask\">\n                <span target>foo</span>\n              </div>\n        `),\n            {\n              ...defaultConfiguration,\n              enablePrivacyForActionName: true,\n            },\n            NodePrivacyLevel.MASK\n          )\n        ).toEqual({ name: 'Masked Element', nameSource: ActionNameSource.MASK_PLACEHOLDER })\n      })\n\n      it('inherit privacy level and does not fallback to masked child text', () => {\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div data-dd-privacy=\"allow\">\n                bar\n                <div target>\n                  foo\n                  <div data-dd-privacy=\"mask\">\n                    <span>secret</span>\n                  </div>\n                </div>\n              </div>\n        `),\n            {\n              ...defaultConfiguration,\n              enablePrivacyForActionName: true,\n            },\n            NodePrivacyLevel.ALLOW\n          )\n        ).toEqual({ name: 'foo', nameSource: ActionNameSource.TEXT_CONTENT })\n      })\n      it('fallback to children but not the masked one with mixed class name and attribute', () => {\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div data-dd-privacy=\"allow\" target>\n                bar\n                <div>\n                  foo\n                  <div data-dd-privacy=\"hidden\">\n                    <span>secret</span>\n                  </div>\n                </div>\n              </div>\n        `),\n            {\n              ...defaultConfiguration,\n              enablePrivacyForActionName: true,\n            },\n            NodePrivacyLevel.ALLOW\n          )\n        ).toEqual({ name: 'bar foo', nameSource: ActionNameSource.TEXT_CONTENT })\n      })\n\n      it('inherit privacy level and does not fallback to masked child text with mixed classname and attribute', () => {\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div class=\"dd-privacy-allow\">\n                bar\n                <div target>\n                  foo\n                  <div data-dd-privacy=\"hidden\">\n                    <span>secret</span>\n                  </div>\n                </div>\n              </div>\n        `),\n            {\n              ...defaultConfiguration,\n              enablePrivacyForActionName: true,\n            },\n            NodePrivacyLevel.ALLOW\n          )\n        ).toEqual({ name: 'foo', nameSource: ActionNameSource.TEXT_CONTENT })\n      })\n\n      it('inherit privacy level and remove only the masked child', () => {\n        addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div class=\"dd-privacy-allow\" target>\n                bar secret\n                <div>\n                  foo \n                  <div class=\"dd-privacy-mask\">\n                    <span>secret</span>\n                  </div>\n                </div>\n              </div>\n        `),\n            {\n              ...defaultConfiguration,\n              enablePrivacyForActionName: true,\n            },\n            NodePrivacyLevel.ALLOW\n          )\n        ).toEqual({ name: 'bar secret foo', nameSource: ActionNameSource.TEXT_CONTENT })\n      })\n\n      it('fallback to children but not the masked one with class names', () => {\n        expect(\n          getActionNameFromElement(\n            appendElement(`\n              <div class=\"dd-privacy-allow\" target>\n                bar\n                <div>\n                  foo\n                  <div class=\"dd-privacy-mask\">\n                    <span>secret</span>\n                  </div>\n                </div>\n              </div>\n        `),\n            {\n              ...defaultConfiguration,\n              enablePrivacyForActionName: true,\n            },\n            NodePrivacyLevel.ALLOW\n          )\n        ).toEqual({ name: 'bar foo', nameSource: ActionNameSource.TEXT_CONTENT })\n      })\n    })\n  })\n\n  describe('shadow DOM support', () => {\n    it('extracts text content from element inside shadow DOM', () => {\n      const host = appendElement('<div></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n      const button = document.createElement('button')\n      button.textContent = 'Shadow Button'\n      shadowRoot.appendChild(button)\n\n      const { name, nameSource } = getActionNameFromElement(button, defaultConfiguration)\n      expect(name).toBe('Shadow Button')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('finds data-dd-action-name on shadow host when element is inside shadow DOM', () => {\n      const host = appendElement('<div data-dd-action-name=\"Custom Action\"></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n      const target = document.createElement('button')\n      shadowRoot.appendChild(target)\n\n      const { name, nameSource } = getActionNameFromElement(target, defaultConfiguration)\n      expect(name).toBe('Custom Action')\n      expect(nameSource).toBe('custom_attribute')\n    })\n\n    it('traverses parent elements across shadow boundary to find action name', () => {\n      const host = appendElement('<div></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n      const wrapper = document.createElement('div')\n      wrapper.setAttribute('title', 'Parent Title')\n      const target = document.createElement('span')\n      wrapper.appendChild(target)\n      shadowRoot.appendChild(wrapper)\n\n      const { name, nameSource } = getActionNameFromElement(target, defaultConfiguration)\n      expect(name).toBe('Parent Title')\n      expect(nameSource).toBe('standard_attribute')\n    })\n\n    it('finds aria-labelledby element inside the same shadow DOM', () => {\n      const host = appendElement('<div></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n\n      const label = document.createElement('span')\n      label.id = 'shadow-label'\n      label.textContent = 'Save Data'\n      shadowRoot.appendChild(label)\n\n      const button = document.createElement('button')\n      button.setAttribute('aria-labelledby', 'shadow-label')\n      shadowRoot.appendChild(button)\n\n      const { name, nameSource } = getActionNameFromElement(button, defaultConfiguration)\n      expect(name).toBe('Save Data')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('falls back to document when aria-labelledby references an element outside shadow DOM', () => {\n      appendElement('<span id=\"light-dom-label\">External Label</span>')\n\n      const host = appendElement('<div></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n\n      const button = document.createElement('button')\n      button.setAttribute('aria-labelledby', 'light-dom-label')\n      shadowRoot.appendChild(button)\n\n      const { name, nameSource } = getActionNameFromElement(button, defaultConfiguration)\n      expect(name).toBe('External Label')\n      expect(nameSource).toBe('text_content')\n    })\n\n    it('respects privacy settings for elements inside shadow DOM', () => {\n      const host = appendElement('<div></div>')\n      const shadowRoot = host.attachShadow({ mode: 'open' })\n      const button = document.createElement('button')\n      button.textContent = 'Secret Button'\n      shadowRoot.appendChild(button)\n\n      const { name } = getActionNameFromElement(button, defaultConfiguration, NodePrivacyLevel.MASK)\n      expect(name).toBe('Masked Element')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/getActionNameFromElement.ts",
    "content": "import { ExperimentalFeature, isExperimentalFeatureEnabled, safeTruncate } from '@datadog/browser-core'\nimport { getPrivacySelector, NodePrivacyLevel } from '../privacyConstants'\nimport { getNodePrivacyLevel, maskDisallowedTextContent, shouldMaskNode, shouldMaskAttribute } from '../privacy'\nimport type { NodePrivacyLevelCache } from '../privacy'\nimport type { RumConfiguration } from '../configuration'\nimport { isElementNode, getParentElement } from '../../browser/htmlDomUtils'\nimport {\n  ActionNameSource,\n  DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE,\n  ACTION_NAME_PLACEHOLDER,\n} from './actionNameConstants'\nimport type { ActionName } from './actionNameConstants'\n\nexport function getActionNameFromElement(\n  element: Element,\n  rumConfiguration: RumConfiguration,\n  nodePrivacyLevel: NodePrivacyLevel = NodePrivacyLevel.ALLOW\n): ActionName {\n  const nodePrivacyLevelCache: NodePrivacyLevelCache = new Map()\n\n  const { actionNameAttribute: userProgrammaticAttribute } = rumConfiguration\n\n  // Proceed to get the action name in two steps:\n  // * first, get the name programmatically, explicitly defined by the user.\n  // * then, if privacy is set to mask, return a placeholder for the undefined.\n  // * if privacy is not set to mask, use strategies that are known to return good results.\n  //   Those strategies will be used on the element and a few parents, but it's likely that they won't succeed at all.\n  // * if no name is found this way, use strategies returning less accurate names as a fallback.\n  //   Those are much likely to succeed.\n  const defaultActionName =\n    getActionNameFromElementProgrammatically(element, DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE) ||\n    (userProgrammaticAttribute && getActionNameFromElementProgrammatically(element, userProgrammaticAttribute))\n\n  if (defaultActionName) {\n    return { name: defaultActionName, nameSource: ActionNameSource.CUSTOM_ATTRIBUTE }\n  } else if (nodePrivacyLevel === NodePrivacyLevel.MASK) {\n    return { name: ACTION_NAME_PLACEHOLDER, nameSource: ActionNameSource.MASK_PLACEHOLDER }\n  }\n\n  return (\n    getActionNameFromElementForStrategies(element, priorityStrategies, rumConfiguration, nodePrivacyLevelCache) ||\n    getActionNameFromElementForStrategies(element, fallbackStrategies, rumConfiguration, nodePrivacyLevelCache) || {\n      name: '',\n      nameSource: ActionNameSource.BLANK,\n    }\n  )\n}\n\nfunction getActionNameFromElementProgrammatically(targetElement: Element, programmaticAttribute: string) {\n  // We don't use getActionNameFromElementForStrategies here, because we want to consider all parents,\n  // without limit. It is up to the user to declare a relevant naming strategy.\n  const elementWithAttribute = closestShadowAware(targetElement, `[${programmaticAttribute}]`)\n\n  if (!elementWithAttribute) {\n    return\n  }\n  const name = elementWithAttribute.getAttribute(programmaticAttribute)!\n  return truncate(normalizeWhitespace(name.trim()))\n}\n\nfunction closestShadowAware(element: Element, selector: string): Element | null {\n  let current: Element | null = element\n  while (current) {\n    if (current.matches(selector)) {\n      return current\n    }\n    current = getParentElement(current)\n  }\n  return null\n}\n\ntype NameStrategy = (\n  element: Element | HTMLElement | HTMLInputElement | HTMLSelectElement,\n  rumConfiguration: RumConfiguration,\n  nodePrivacyLevelCache: NodePrivacyLevelCache\n) => ActionName | undefined | null\n\nconst priorityStrategies: NameStrategy[] = [\n  // associated LABEL text\n  (element, rumConfiguration, nodePrivacyLevelCache) => {\n    if ('labels' in element && element.labels && element.labels.length > 0) {\n      return getActionNameFromTextualContent(element.labels[0], rumConfiguration, nodePrivacyLevelCache)\n    }\n  },\n  // INPUT button (and associated) value\n  (element) => {\n    if (element.nodeName === 'INPUT') {\n      const input = element as HTMLInputElement\n      const type = input.getAttribute('type')\n      if (type === 'button' || type === 'submit' || type === 'reset') {\n        return { name: input.value, nameSource: ActionNameSource.TEXT_CONTENT }\n      }\n    }\n  },\n  // BUTTON, LABEL or button-like element text\n  (element, rumConfiguration, nodePrivacyLevelCache) => {\n    if (element.nodeName === 'BUTTON' || element.nodeName === 'LABEL' || element.getAttribute('role') === 'button') {\n      return getActionNameFromTextualContent(element, rumConfiguration, nodePrivacyLevelCache)\n    }\n  },\n  (element, rumConfiguration, nodePrivacyLevelCache) =>\n    getActionNameFromStandardAttribute(element, 'aria-label', rumConfiguration, nodePrivacyLevelCache),\n  // associated element text designated by the aria-labelledby attribute\n  (element, rumConfiguration, nodePrivacyLevelCache) => {\n    const labelledByAttribute = element.getAttribute('aria-labelledby')\n    if (labelledByAttribute) {\n      return {\n        name: labelledByAttribute\n          .split(/\\s+/)\n          .map((id) => getElementById(element, id))\n          .filter((label): label is HTMLElement => Boolean(label))\n          .map((element) => getTextualContent(element, rumConfiguration, nodePrivacyLevelCache))\n          .join(' '),\n        nameSource: ActionNameSource.TEXT_CONTENT,\n      }\n    }\n  },\n  (element, rumConfiguration, nodePrivacyLevelCache) =>\n    getActionNameFromStandardAttribute(element, 'alt', rumConfiguration, nodePrivacyLevelCache),\n  (element, rumConfiguration, nodePrivacyLevelCache) =>\n    getActionNameFromStandardAttribute(element, 'name', rumConfiguration, nodePrivacyLevelCache),\n  (element, rumConfiguration, nodePrivacyLevelCache) =>\n    getActionNameFromStandardAttribute(element, 'title', rumConfiguration, nodePrivacyLevelCache),\n  (element, rumConfiguration, nodePrivacyLevelCache) =>\n    getActionNameFromStandardAttribute(element, 'placeholder', rumConfiguration, nodePrivacyLevelCache),\n  // SELECT first OPTION text\n  (element, rumConfiguration, nodePrivacyLevelCache) => {\n    if ('options' in element && element.options.length > 0) {\n      return getActionNameFromTextualContent(element.options[0], rumConfiguration, nodePrivacyLevelCache)\n    }\n  },\n]\n\nconst fallbackStrategies: NameStrategy[] = [\n  (element, rumConfiguration, nodePrivacyLevelCache) =>\n    getActionNameFromTextualContent(element, rumConfiguration, nodePrivacyLevelCache),\n]\n\n/**\n * Iterates over the target element and its parent, using the strategies list to get an action name.\n * Each strategies are applied on each element, stopping as soon as a non-empty value is returned.\n */\nconst MAX_PARENTS_TO_CONSIDER = 10\nfunction getActionNameFromElementForStrategies(\n  targetElement: Element,\n  strategies: NameStrategy[],\n  rumConfiguration: RumConfiguration,\n  nodePrivacyLevelCache: NodePrivacyLevelCache\n) {\n  let element: Element | null = targetElement\n  let recursionCounter = 0\n  while (\n    recursionCounter <= MAX_PARENTS_TO_CONSIDER &&\n    element &&\n    element.nodeName !== 'BODY' &&\n    element.nodeName !== 'HTML' &&\n    element.nodeName !== 'HEAD'\n  ) {\n    for (const strategy of strategies) {\n      const actionName = strategy(element, rumConfiguration, nodePrivacyLevelCache)\n      if (actionName) {\n        const { name, nameSource } = actionName\n        const trimmedName = name && name.trim()\n        if (trimmedName) {\n          return { name: truncate(normalizeWhitespace(trimmedName)), nameSource }\n        }\n      }\n    }\n    // Consider a FORM as a contextual limit to get the action name.  This is experimental and may\n    // be reconsidered in the future.\n    if (element.nodeName === 'FORM') {\n      break\n    }\n    element = getParentElement(element)\n    recursionCounter += 1\n  }\n}\n\nfunction normalizeWhitespace(s: string) {\n  return s.replace(/\\s+/g, ' ')\n}\n\nfunction truncate(s: string) {\n  return s.length > 100 ? `${safeTruncate(s, 100)} [...]` : s\n}\n\nfunction getElementById(refElement: Element, id: string): HTMLElement | null {\n  const rootNode = refElement.getRootNode()\n  if (rootNode instanceof ShadowRoot) {\n    const shadowElement = rootNode.getElementById(id)\n    if (shadowElement) {\n      return shadowElement\n    }\n  }\n\n  // Use the element ownerDocument here, because tests are executed in an iframe, so\n  // document.getElementById won't work.\n  return refElement.ownerDocument ? refElement.ownerDocument.getElementById(id) : null\n}\n\nfunction getActionNameFromStandardAttribute(\n  element: Element | HTMLElement,\n  attribute: string,\n  rumConfiguration: RumConfiguration,\n  nodePrivacyLevelCache: NodePrivacyLevelCache\n): ActionName {\n  const { enablePrivacyForActionName, defaultPrivacyLevel } = rumConfiguration\n  let attributeValue = element.getAttribute(attribute)\n  if (attributeValue && enablePrivacyForActionName) {\n    const nodePrivacyLevel = getNodePrivacyLevel(element, defaultPrivacyLevel, nodePrivacyLevelCache)\n    if (shouldMaskAttribute(element.tagName, attribute, attributeValue, nodePrivacyLevel, rumConfiguration)) {\n      attributeValue = maskDisallowedTextContent(attributeValue, ACTION_NAME_PLACEHOLDER)\n    }\n  } else if (!attributeValue) {\n    attributeValue = ''\n  }\n\n  return {\n    name: attributeValue,\n    nameSource: ActionNameSource.STANDARD_ATTRIBUTE,\n  }\n}\n\nfunction getActionNameFromTextualContent(\n  element: Element | HTMLElement,\n  rumConfiguration: RumConfiguration,\n  nodePrivacyLevelCache: NodePrivacyLevelCache\n): ActionName {\n  return {\n    name: getTextualContent(element, rumConfiguration, nodePrivacyLevelCache) || '',\n    nameSource: ActionNameSource.TEXT_CONTENT,\n  }\n}\n\nfunction getTextualContent(\n  element: Element,\n  rumConfiguration: RumConfiguration,\n  nodePrivacyLevelCache: NodePrivacyLevelCache\n) {\n  if ((element as HTMLElement).isContentEditable) {\n    return\n  }\n\n  const {\n    enablePrivacyForActionName,\n    actionNameAttribute: userProgrammaticAttribute,\n    defaultPrivacyLevel,\n  } = rumConfiguration\n\n  if (isExperimentalFeatureEnabled(ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME)) {\n    return getTextualContentWithTreeWalker(\n      element,\n      userProgrammaticAttribute,\n      enablePrivacyForActionName,\n      defaultPrivacyLevel,\n      nodePrivacyLevelCache\n    )\n  }\n\n  if ('innerText' in element) {\n    let text = (element as HTMLElement).innerText\n\n    const removeTextFromElements = (query: string) => {\n      const list = element.querySelectorAll<Element | HTMLElement>(query)\n      for (let index = 0; index < list.length; index += 1) {\n        const element = list[index]\n        if ('innerText' in element) {\n          const textToReplace = element.innerText\n          if (textToReplace && textToReplace.trim().length > 0) {\n            text = text.replace(textToReplace, '')\n          }\n        }\n      }\n    }\n\n    // remove the text of elements with programmatic attribute value\n    removeTextFromElements(`[${DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE}]`)\n\n    if (userProgrammaticAttribute) {\n      removeTextFromElements(`[${userProgrammaticAttribute}]`)\n    }\n\n    if (enablePrivacyForActionName) {\n      // remove the text of elements with privacy override\n      removeTextFromElements(\n        `${getPrivacySelector(NodePrivacyLevel.HIDDEN)}, ${getPrivacySelector(NodePrivacyLevel.MASK)}`\n      )\n    }\n\n    return text\n  }\n\n  return element.textContent\n}\n\nfunction getTextualContentWithTreeWalker(\n  element: Element,\n  userProgrammaticAttribute: string | undefined,\n  privacyEnabledActionName: boolean,\n  defaultPrivacyLevel: NodePrivacyLevel,\n  nodePrivacyLevelCache: NodePrivacyLevelCache\n) {\n  const walker = document.createTreeWalker(\n    element,\n    // eslint-disable-next-line no-bitwise\n    NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,\n    rejectInvisibleOrMaskedElementsFilter\n  )\n\n  let text = ''\n\n  while (walker.nextNode()) {\n    const node = walker.currentNode\n    if (isElementNode(node)) {\n      if (\n        // Following InnerText rendering spec https://html.spec.whatwg.org/multipage/dom.html#rendered-text-collection-steps\n        node.nodeName === 'BR' ||\n        node.nodeName === 'P' ||\n        ['block', 'flex', 'grid', 'list-item', 'table', 'table-caption'].includes(getComputedStyle(node).display)\n      ) {\n        text += ' '\n      }\n      continue // skip element nodes\n    }\n\n    text += node.textContent || ''\n  }\n\n  return text.replace(/\\s+/g, ' ').trim()\n\n  function rejectInvisibleOrMaskedElementsFilter(node: Node) {\n    const nodeSelfPrivacyLevel = getNodePrivacyLevel(node, defaultPrivacyLevel, nodePrivacyLevelCache)\n    if (privacyEnabledActionName && nodeSelfPrivacyLevel && shouldMaskNode(node, nodeSelfPrivacyLevel)) {\n      return NodeFilter.FILTER_REJECT\n    }\n    if (isElementNode(node)) {\n      if (\n        node.hasAttribute(DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE) ||\n        (userProgrammaticAttribute && node.hasAttribute(userProgrammaticAttribute))\n      ) {\n        return NodeFilter.FILTER_REJECT\n      }\n      const style = getComputedStyle(node)\n      if (\n        style.visibility !== 'visible' ||\n        style.display === 'none' ||\n        (style.contentVisibility && style.contentVisibility !== 'visible')\n        // contentVisibility is not supported in all browsers, so we need to check it\n      ) {\n        return NodeFilter.FILTER_REJECT\n      }\n    }\n\n    return NodeFilter.FILTER_ACCEPT\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/interactionSelectorCache.spec.ts",
    "content": "import { relativeNow } from '@datadog/browser-core'\nimport { mockClock } from '@datadog/browser-core/test'\nimport type { Clock } from '@datadog/browser-core/test'\nimport {\n  updateInteractionSelector,\n  getInteractionSelector,\n  interactionSelectorCache,\n  CLICK_ACTION_MAX_DURATION,\n} from './interactionSelectorCache'\n\ndescribe('interactionSelectorCache', () => {\n  let clock: Clock\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  it('should delete the selector after getting it', () => {\n    const timestamp = relativeNow()\n    updateInteractionSelector(timestamp, 'selector')\n    expect(getInteractionSelector(timestamp)).toBe('selector')\n    expect(interactionSelectorCache.get(timestamp)).toBeUndefined()\n  })\n\n  it('should delete outdated selectors', () => {\n    const timestamp = relativeNow()\n    updateInteractionSelector(timestamp, 'selector')\n    expect(getInteractionSelector(timestamp)).toBe('selector')\n    clock.tick(CLICK_ACTION_MAX_DURATION)\n    expect(interactionSelectorCache.get(timestamp)).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/interactionSelectorCache.ts",
    "content": "import { elapsed, ONE_SECOND, relativeNow } from '@datadog/browser-core'\nimport type { RelativeTime } from '@datadog/browser-core'\n\n// Maximum duration for click actions\nexport const CLICK_ACTION_MAX_DURATION = 10 * ONE_SECOND\nexport const interactionSelectorCache = new Map<RelativeTime, string>()\n\nexport function getInteractionSelector(relativeTimestamp: RelativeTime) {\n  const selector = interactionSelectorCache.get(relativeTimestamp)\n  interactionSelectorCache.delete(relativeTimestamp)\n  return selector\n}\n\nexport function updateInteractionSelector(relativeTimestamp: RelativeTime, selector: string) {\n  interactionSelectorCache.set(relativeTimestamp, selector)\n  interactionSelectorCache.forEach((_, relativeTimestamp) => {\n    if (elapsed(relativeTimestamp, relativeNow()) > CLICK_ACTION_MAX_DURATION) {\n      interactionSelectorCache.delete(relativeTimestamp)\n    }\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/isActionChildEvent.ts",
    "content": "import type { RumActionEvent, RumErrorEvent, RumLongTaskEvent, RumResourceEvent } from '../../rumEvent.types'\n\nexport function isActionChildEvent(id: string) {\n  return (event: RumActionEvent | RumErrorEvent | RumLongTaskEvent | RumResourceEvent) =>\n    event.action !== undefined && event.action.id !== undefined && event.action.id.includes(id)\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/listenActionEvents.spec.ts",
    "content": "import { createNewEvent } from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../../test'\nimport type { ActionEventsHooks } from './listenActionEvents'\nimport { listenActionEvents } from './listenActionEvents'\n\ndescribe('listenActionEvents', () => {\n  let actionEventsHooks: {\n    onPointerUp: jasmine.Spy<ActionEventsHooks<object>['onPointerUp']>\n    onPointerDown: jasmine.Spy<ActionEventsHooks<object>['onPointerDown']>\n  }\n  let stopListenEvents: () => void\n\n  beforeEach(() => {\n    actionEventsHooks = {\n      onPointerUp: jasmine.createSpy(),\n      onPointerDown: jasmine.createSpy().and.returnValue({}),\n    }\n    ;({ stop: stopListenEvents } = listenActionEvents(mockRumConfiguration(), actionEventsHooks))\n  })\n\n  afterEach(() => {\n    stopListenEvents()\n  })\n\n  it('listen to pointerdown events', () => {\n    emulateClick()\n    expect(actionEventsHooks.onPointerDown).toHaveBeenCalledOnceWith(jasmine.objectContaining({ type: 'pointerdown' }))\n  })\n\n  it('ignore non-primary pointerdown events', () => {\n    emulateClick({\n      beforeMouseUp() {\n        window.dispatchEvent(createNewEvent('pointerdown', { target: document.body, isPrimary: false }))\n      },\n    })\n    expect(actionEventsHooks.onPointerDown).toHaveBeenCalledTimes(1)\n  })\n\n  it('listen to pointerup events', () => {\n    emulateClick()\n    expect(actionEventsHooks.onPointerUp).toHaveBeenCalledOnceWith(\n      {},\n      jasmine.objectContaining({ type: 'pointerup' }),\n      jasmine.any(Function)\n    )\n  })\n\n  it('aborts click lifecycle if the pointerdown event occurs on a non-element', () => {\n    emulateClick({ target: document.createTextNode('foo') })\n    expect(actionEventsHooks.onPointerDown).not.toHaveBeenCalled()\n  })\n\n  it('can abort click lifecycle by returning undefined from the onPointerDown callback', () => {\n    actionEventsHooks.onPointerDown.and.returnValue(undefined)\n    emulateClick()\n    expect(actionEventsHooks.onPointerUp).not.toHaveBeenCalled()\n  })\n\n  it('passes the context created in onPointerDown to onPointerUp', () => {\n    const context = {}\n    actionEventsHooks.onPointerDown.and.returnValue(context)\n    emulateClick()\n    expect(actionEventsHooks.onPointerUp.calls.mostRecent().args[0]).toBe(context)\n  })\n\n  it('ignore \"click\" events if no \"pointerdown\" event happened since the previous \"click\" event', () => {\n    emulateClick()\n    actionEventsHooks.onPointerUp.calls.reset()\n\n    window.dispatchEvent(createNewEvent('click', { target: document.body }))\n\n    expect(actionEventsHooks.onPointerUp).not.toHaveBeenCalled()\n  })\n\n  describe('selection change', () => {\n    let text: Text\n\n    beforeEach(() => {\n      text = document.createTextNode('foo bar')\n      document.body.appendChild(text)\n    })\n\n    afterEach(() => {\n      document.body.removeChild(text)\n      document.getSelection()!.removeAllRanges()\n    })\n\n    it('click without selection impact should not report a selection change', () => {\n      emulateClick()\n      expect(hasSelectionChanged()).toBe(false)\n    })\n\n    it('click and drag to select text should reports a selection change', () => {\n      emulateClick({\n        beforeMouseUp() {\n          emulateNodeSelection(0, 3)\n        },\n      })\n      expect(hasSelectionChanged()).toBe(true)\n    })\n\n    it('click and drag that adds a selection range should reports a selection change', () => {\n      // Example: Command-Click selection on Firefox\n      emulateNodeSelection(0, 3)\n      emulateClick({\n        beforeMouseUp() {\n          emulateNodeSelection(3, 6, { clearSelection: false })\n        },\n      })\n      expect(hasSelectionChanged()).toBe(true)\n    })\n\n    it('click to deselect previously selected text should report a selection change', () => {\n      emulateNodeSelection(0, 3)\n      emulateClick({\n        beforeMouseUp() {\n          emulateNodeSelection(0, 0)\n        },\n      })\n      expect(hasSelectionChanged()).toBe(true)\n    })\n\n    it('click to change the selection position (ex: last click of a triple-click selection) should report a selection change', () => {\n      emulateNodeSelection(3, 4)\n      emulateClick({\n        beforeMouseUp() {\n          emulateNodeSelection(0, 7)\n        },\n      })\n      expect(hasSelectionChanged()).toBe(true)\n    })\n\n    it('click that change the caret (collapsed selection) position should not report selection change', () => {\n      emulateNodeSelection(0, 0)\n      emulateClick({\n        beforeMouseUp() {\n          emulateNodeSelection(1, 1)\n        },\n      })\n      expect(hasSelectionChanged()).toBe(false)\n    })\n\n    function hasSelectionChanged() {\n      return actionEventsHooks.onPointerUp.calls.mostRecent().args[2]().selection\n    }\n\n    function emulateNodeSelection(\n      start: number,\n      end: number,\n      { clearSelection = true }: { clearSelection?: boolean } = {}\n    ) {\n      const selection = document.getSelection()!\n      const range = document.createRange()\n      range.setStart(text, start)\n      range.setEnd(text, end)\n      if (clearSelection) {\n        selection.removeAllRanges()\n      }\n      selection.addRange(range)\n      window.dispatchEvent(createNewEvent('selectionchange', { target: document }))\n    }\n  })\n\n  describe('input user activity', () => {\n    it('click that do not trigger an input input event should not report input user activity', () => {\n      emulateClick()\n      expect(hasInputUserActivity()).toBe(false)\n    })\n\n    it('click that triggers an input event during the click should report an input user activity', () => {\n      emulateClick({\n        beforeMouseUp() {\n          emulateInputEvent()\n        },\n      })\n      expect(hasInputUserActivity()).toBe(true)\n    })\n\n    it('click that triggers an input event slightly after the click should report an input user activity', () => {\n      emulateClick()\n      emulateInputEvent()\n      expect(hasInputUserActivity()).toBe(true)\n    })\n\n    it('input events that precede clicks should not be taken into account', () => {\n      emulateInputEvent()\n      emulateClick()\n      expect(hasInputUserActivity()).toBe(false)\n    })\n\n    it('click and type should report an input user activity', () => {\n      emulateClick({\n        beforeMouseUp() {\n          emulateInputEvent()\n        },\n      })\n      expect(hasInputUserActivity()).toBe(true)\n    })\n\n    function emulateInputEvent() {\n      window.dispatchEvent(createNewEvent('input'))\n    }\n    function hasInputUserActivity() {\n      return actionEventsHooks.onPointerUp.calls.mostRecent().args[2]().input\n    }\n  })\n\n  describe('scroll', () => {\n    it('click that do not trigger a scroll event should not report scroll user activity', () => {\n      emulateClick()\n      expect(hasScrollUserActivity()).toBe(false)\n    })\n\n    it('click that triggers a scroll event during the click should report a scroll user activity', () => {\n      emulateClick({\n        beforeMouseUp() {\n          emulateScrollEvent()\n        },\n      })\n      expect(hasScrollUserActivity()).toBe(true)\n    })\n\n    it('click that triggers a scroll event slightly after the click should report a scroll user activity', () => {\n      emulateClick()\n      emulateScrollEvent()\n      expect(hasScrollUserActivity()).toBe(true)\n    })\n\n    it('scroll events that precede clicks should not be taken into account', () => {\n      emulateScrollEvent()\n      emulateClick()\n      expect(hasScrollUserActivity()).toBe(false)\n    })\n\n    function emulateScrollEvent() {\n      window.dispatchEvent(createNewEvent('scroll'))\n    }\n    function hasScrollUserActivity() {\n      return actionEventsHooks.onPointerUp.calls.mostRecent().args[2]().scroll\n    }\n  })\n\n  function emulateClick({\n    beforeMouseUp,\n    target = document.body,\n    clickEventIsPrimary = undefined,\n  }: { beforeMouseUp?(this: void): void; target?: Node; clickEventIsPrimary?: boolean } = {}) {\n    window.dispatchEvent(createNewEvent('pointerdown', { target, isPrimary: true }))\n    window.dispatchEvent(createNewEvent('mousedown', { target }))\n    beforeMouseUp?.()\n    window.dispatchEvent(createNewEvent('pointerup', { target, isPrimary: true }))\n    window.dispatchEvent(createNewEvent('mouseup', { target }))\n    window.dispatchEvent(createNewEvent('click', { target, isPrimary: clickEventIsPrimary }))\n  }\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/listenActionEvents.ts",
    "content": "import { addEventListener, DOM_EVENT } from '@datadog/browser-core'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\n\nexport interface ExtraPointerEventFields {\n  target: Element\n  timeStamp: RelativeTime\n}\nexport type MouseEventOnElement = PointerEvent & ExtraPointerEventFields\n\nexport interface UserActivity {\n  selection: boolean\n  input: boolean\n  scroll: boolean\n}\nexport interface ActionEventsHooks<ClickContext> {\n  onPointerDown: (event: MouseEventOnElement) => ClickContext | undefined\n  onPointerUp: (context: ClickContext, event: MouseEventOnElement, getUserActivity: () => UserActivity) => void\n}\n\nexport function listenActionEvents<ClickContext>(\n  configuration: RumConfiguration,\n  { onPointerDown, onPointerUp }: ActionEventsHooks<ClickContext>\n) {\n  let selectionEmptyAtPointerDown: boolean\n  let userActivity: UserActivity = {\n    selection: false,\n    input: false,\n    scroll: false,\n  }\n  let clickContext: ClickContext | undefined\n\n  const listeners = [\n    addEventListener(\n      configuration,\n      window,\n      DOM_EVENT.POINTER_DOWN,\n      (event: PointerEvent) => {\n        if (isValidPointerEvent(event)) {\n          selectionEmptyAtPointerDown = isSelectionEmpty()\n          userActivity = {\n            selection: false,\n            input: false,\n            scroll: false,\n          }\n          clickContext = onPointerDown(event)\n        }\n      },\n      { capture: true }\n    ),\n\n    addEventListener(\n      configuration,\n      window,\n      DOM_EVENT.SELECTION_CHANGE,\n      () => {\n        if (!selectionEmptyAtPointerDown || !isSelectionEmpty()) {\n          userActivity.selection = true\n        }\n      },\n      { capture: true }\n    ),\n\n    addEventListener(\n      configuration,\n      window,\n      DOM_EVENT.SCROLL,\n      () => {\n        userActivity.scroll = true\n      },\n      { capture: true, passive: true }\n    ),\n\n    addEventListener(\n      configuration,\n      window,\n      DOM_EVENT.POINTER_UP,\n      (event: PointerEvent) => {\n        if (isValidPointerEvent(event) && clickContext) {\n          // Use a scoped variable to make sure the value is not changed by other clicks\n          const localUserActivity = userActivity\n          onPointerUp(clickContext, event, () => localUserActivity)\n          clickContext = undefined\n        }\n      },\n      { capture: true }\n    ),\n\n    addEventListener(\n      configuration,\n      window,\n      DOM_EVENT.INPUT,\n      () => {\n        userActivity.input = true\n      },\n      { capture: true }\n    ),\n  ]\n\n  return {\n    stop: () => {\n      listeners.forEach((listener) => listener.stop())\n    },\n  }\n}\n\nfunction isSelectionEmpty(): boolean {\n  const selection = window.getSelection()\n  return !selection || selection.isCollapsed\n}\n\nfunction isValidPointerEvent(event: PointerEvent): event is MouseEventOnElement {\n  return (\n    event.target instanceof Element &&\n    // Only consider 'primary' pointer events for now. Multi-touch support could be implemented in\n    // the future.\n    event.isPrimary !== false\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/trackClickActions.spec.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport {\n  addDuration,\n  clocksNow,\n  timeStampNow,\n  relativeNow,\n  DefaultPrivacyLevel,\n  Observable,\n  ExperimentalFeature,\n  PageExitReason,\n  addExperimentalFeatures,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { createNewEvent, mockClock } from '@datadog/browser-core/test'\nimport { createFakeClick, createMutationRecord, mockRumConfiguration } from '../../../test'\nimport type { AssembledRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType, ActionType, FrustrationType } from '../../rawRumEvent.types'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { PAGE_ACTIVITY_VALIDATION_DELAY } from '../waitPageActivityEnd'\nimport type { RumConfiguration } from '../configuration'\nimport type { BrowserWindow } from '../privacy'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { SHADOW_DOM_MARKER } from '../getSelectorFromElement'\nimport type { ClickAction } from './trackClickActions'\nimport { finalizeClicks, trackClickActions } from './trackClickActions'\nimport { MAX_DURATION_BETWEEN_CLICKS } from './clickChain'\nimport { getInteractionSelector, CLICK_ACTION_MAX_DURATION } from './interactionSelectorCache'\nimport { ActionNameSource } from './actionNameConstants'\n\n// Used to wait some time after the creation of an action\nconst BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY = PAGE_ACTIVITY_VALIDATION_DELAY * 0.8\n// A long delay used to wait after any action is finished.\nconst EXPIRE_DELAY = CLICK_ACTION_MAX_DURATION * 10\n// Arbitrary duration between pointerdown and pointerup for emulated clicks\nconst EMULATED_CLICK_DURATION = 80 as Duration\n\nfunction eventsCollector<T>() {\n  const events: T[] = []\n  beforeEach(() => {\n    events.length = 0\n  })\n  return {\n    events,\n    pushEvent: (event: T) => {\n      events.push(event)\n    },\n  }\n}\n\ndescribe('trackClickActions', () => {\n  let lifeCycle: LifeCycle\n  let domMutationObservable: Observable<RumMutationRecord[]>\n  let windowOpenObservable: Observable<void>\n  let clock: Clock\n\n  const { events, pushEvent } = eventsCollector<ClickAction>()\n  let button: HTMLButtonElement\n  let emptyElement: HTMLHRElement\n  let input: HTMLInputElement\n  let findActionId: (startTime?: RelativeTime) => string[]\n  let stopClickActionsTracking: () => void\n\n  function startClickActionsTracking(partialConfig: Partial<RumConfiguration> = {}) {\n    const subscription = lifeCycle.subscribe(LifeCycleEventType.AUTO_ACTION_COMPLETED, pushEvent)\n\n    const trackClickActionsResult = trackClickActions(\n      lifeCycle,\n      domMutationObservable,\n      windowOpenObservable,\n      mockRumConfiguration(partialConfig)\n    )\n\n    findActionId = trackClickActionsResult.findActionId\n    stopClickActionsTracking = () => {\n      trackClickActionsResult.stop()\n      subscription.unsubscribe()\n    }\n  }\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    clock = mockClock()\n    domMutationObservable = new Observable<RumMutationRecord[]>()\n    windowOpenObservable = new Observable<void>()\n\n    button = document.createElement('button')\n    button.type = 'button'\n    button.id = 'button'\n    button.style.width = '100px'\n    button.style.height = '100px'\n    button.appendChild(document.createTextNode('Click me'))\n    document.body.appendChild(button)\n\n    emptyElement = document.createElement('hr')\n    document.body.appendChild(emptyElement)\n\n    input = document.createElement('input')\n    input.value = 'foo bar'\n    document.body.appendChild(input)\n  })\n\n  afterEach(() => {\n    stopClickActionsTracking()\n    button.parentNode!.removeChild(button)\n    emptyElement.parentNode!.removeChild(emptyElement)\n    input.parentNode!.removeChild(input)\n  })\n\n  it('starts a click action when clicking on an element', () => {\n    startClickActionsTracking()\n    const pointerDownClocks = clocksNow()\n    emulateClick({ activity: {} })\n    expect(findActionId()).not.toBeUndefined()\n    clock.tick(EXPIRE_DELAY)\n    const domEvent = createNewEvent('pointerup', { target: document.createElement('button') })\n    expect(events).toEqual([\n      jasmine.objectContaining({\n        counts: jasmine.objectContaining({\n          errorCount: 0,\n          longTaskCount: 0,\n          resourceCount: 0,\n        }),\n        duration: BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY as Duration,\n        id: jasmine.any(String),\n        name: 'Click me',\n        nameSource: ActionNameSource.TEXT_CONTENT,\n        startClocks: {\n          relative: addDuration(pointerDownClocks.relative, EMULATED_CLICK_DURATION),\n          timeStamp: addDuration(pointerDownClocks.timeStamp, EMULATED_CLICK_DURATION),\n        },\n        type: ActionType.CLICK,\n        event: domEvent,\n        frustrationTypes: [],\n        target: {\n          selector: '#button',\n          width: 100,\n          height: 100,\n          composedPathSelector: jasmine.any(String),\n        },\n        position: { x: 50, y: 50 },\n        events: [domEvent],\n      }),\n    ])\n  })\n\n  it('should keep track of previously validated click actions', () => {\n    startClickActionsTracking()\n    const pointerDownStart = relativeNow()\n    emulateClick({ activity: {} })\n    clock.tick(EXPIRE_DELAY)\n\n    expect(findActionId(addDuration(pointerDownStart, EMULATED_CLICK_DURATION))).not.toBeUndefined()\n  })\n\n  it('counts errors occurring during the click action', () => {\n    startClickActionsTracking()\n\n    emulateClick({ activity: {} })\n\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeErrorEvent())\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n    domMutationObservable.notify([createMutationRecord()])\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeErrorEvent())\n    clock.tick(EXPIRE_DELAY)\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeErrorEvent())\n\n    expect(events.length).toBe(1)\n    const clickAction = events[0]\n    expect(clickAction.counts).toEqual(\n      jasmine.objectContaining({\n        errorCount: 2,\n        longTaskCount: 0,\n        resourceCount: 0,\n      })\n    )\n  })\n\n  it('does not count child events unrelated to the click action', () => {\n    startClickActionsTracking()\n\n    emulateClick({ activity: {} })\n\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n      type: RumEventType.RESOURCE,\n      action: { id: 'unrelated-action-id' },\n    } as AssembledRumEvent)\n\n    clock.tick(EXPIRE_DELAY)\n\n    expect(events.length).toBe(1)\n    const clickAction = events[0]\n    expect(clickAction.counts.resourceCount).toBe(0)\n  })\n\n  it('should take the name from user-configured attribute', () => {\n    startClickActionsTracking({ actionNameAttribute: 'data-my-custom-attribute' })\n\n    button.setAttribute('data-my-custom-attribute', 'test-1')\n    emulateClick({ activity: {} })\n\n    clock.tick(EXPIRE_DELAY)\n    expect(events.length).toBe(1)\n    expect(events[0].name).toBe('test-1')\n  })\n\n  it('discards any click action with a negative duration', () => {\n    startClickActionsTracking()\n    emulateClick({ activity: { delay: -1 } })\n    expect(findActionId().length).toEqual(2)\n    clock.tick(EXPIRE_DELAY)\n\n    expect(events).toEqual([])\n    expect(findActionId()).toEqual([])\n  })\n\n  it('ongoing click action is stopped on view end', () => {\n    startClickActionsTracking()\n    emulateClick({ activity: { delay: BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY } })\n\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n\n    lifeCycle.notify(LifeCycleEventType.VIEW_ENDED, {\n      endClocks: clocksNow(),\n    })\n\n    expect(events.length).toBe(1)\n    expect(events[0].duration).toBe((2 * BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY) as Duration)\n  })\n\n  it('ongoing click action is stopped on page exit', () => {\n    startClickActionsTracking()\n    emulateClick()\n\n    clock.tick(12)\n\n    lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, {\n      reason: PageExitReason.HIDDEN,\n    })\n\n    expect(events.length).toBe(1)\n    expect(events[0].duration).toBe(12 as Duration)\n    expect(events[0].frustrationTypes).toEqual([])\n  })\n\n  it('collect click actions even if another one is ongoing', () => {\n    startClickActionsTracking()\n\n    const firstPointerDownTimeStamp = timeStampNow()\n    emulateClick({ activity: {} })\n    const secondPointerDownTimeStamp = timeStampNow()\n    emulateClick({ activity: {} })\n\n    clock.tick(EXPIRE_DELAY)\n    expect(events.length).toBe(2)\n    expect(events[0].startClocks.timeStamp).toBe(addDuration(firstPointerDownTimeStamp, EMULATED_CLICK_DURATION))\n    expect(events[1].startClocks.timeStamp).toBe(addDuration(secondPointerDownTimeStamp, EMULATED_CLICK_DURATION))\n  })\n\n  it('collect click actions even if nothing happens after a click (dead click)', () => {\n    startClickActionsTracking()\n    emulateClick()\n\n    clock.tick(EXPIRE_DELAY)\n    expect(events.length).toBe(1)\n    expect(events[0].frustrationTypes).toEqual([FrustrationType.DEAD_CLICK])\n    expect(findActionId()).toEqual([])\n  })\n\n  it('does not set a duration for dead clicks', () => {\n    startClickActionsTracking()\n    emulateClick()\n\n    clock.tick(EXPIRE_DELAY)\n    expect(events.length).toBe(1)\n    expect(events[0].duration).toBeUndefined()\n  })\n\n  it('collect click actions even if it fails to find a name', () => {\n    startClickActionsTracking()\n    emulateClick({ activity: {}, target: emptyElement })\n    expect(findActionId().length).toBeGreaterThan(0)\n    clock.tick(EXPIRE_DELAY)\n\n    expect(events.length).toBe(1)\n  })\n\n  describe('with enablePrivacyForActionName false', () => {\n    it('extracts action name when default privacy level is mask', () => {\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK,\n        enablePrivacyForActionName: false,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Click me')\n    })\n  })\n\n  describe('with enablePrivacyForActionName true', () => {\n    it('does not track click actions when html override set hidden', () => {\n      button.setAttribute('data-dd-privacy', 'hidden')\n      startClickActionsTracking({\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(0)\n    })\n    it('get placeholder when defaultPrivacyLevel is mask without programmatically declared action name', () => {\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Masked Element')\n    })\n  })\n\n  describe('rage clicks', () => {\n    it('considers a chain of three clicks or more as a single action with \"rage\" frustration type', () => {\n      startClickActionsTracking()\n      const firstPointerDownTimeStamp = timeStampNow()\n      const activityDelay = 5\n      emulateClick({ activity: { delay: activityDelay } })\n      emulateClick({ activity: { delay: activityDelay } })\n      emulateClick({ activity: { delay: activityDelay } })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].startClocks.timeStamp).toBe(addDuration(firstPointerDownTimeStamp, EMULATED_CLICK_DURATION))\n      expect(events[0].frustrationTypes).toEqual([FrustrationType.RAGE_CLICK])\n      expect(events[0].duration).toBe(\n        (MAX_DURATION_BETWEEN_CLICKS + 2 * activityDelay + 2 * EMULATED_CLICK_DURATION) as Duration\n      )\n    })\n\n    it('should contain original events from of rage sequence', () => {\n      startClickActionsTracking()\n      const activityDelay = 5\n      emulateClick({ activity: { delay: activityDelay } })\n      emulateClick({ activity: { delay: activityDelay } })\n      emulateClick({ activity: { delay: activityDelay } })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual([FrustrationType.RAGE_CLICK])\n      expect(events[0].events?.length).toBe(3)\n    })\n\n    it('aggregates frustration Types from all clicks', () => {\n      startClickActionsTracking()\n\n      // Dead\n      emulateClick()\n      clock.tick(PAGE_ACTIVITY_VALIDATION_DELAY)\n\n      // Error\n      emulateClick({ activity: {} })\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeErrorEvent())\n      clock.tick(PAGE_ACTIVITY_VALIDATION_DELAY)\n\n      // Third click to make a rage click\n      emulateClick({ activity: {} })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual(\n        jasmine.arrayWithExactContents([\n          FrustrationType.DEAD_CLICK,\n          FrustrationType.ERROR_CLICK,\n          FrustrationType.RAGE_CLICK,\n        ])\n      )\n    })\n  })\n\n  describe('error clicks', () => {\n    it('considers a \"click with activity\" followed by an error as a click action with \"error\" frustration type', () => {\n      startClickActionsTracking()\n\n      emulateClick({ activity: {} })\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeErrorEvent())\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual([FrustrationType.ERROR_CLICK])\n    })\n\n    it('considers a \"click without activity\" followed by an error as a click action with \"error\" (and \"dead\") frustration type', () => {\n      startClickActionsTracking()\n\n      emulateClick()\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeErrorEvent())\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual(\n        jasmine.arrayWithExactContents([FrustrationType.ERROR_CLICK, FrustrationType.DEAD_CLICK])\n      )\n    })\n  })\n\n  describe('dead clicks', () => {\n    it('considers a \"click without activity\" as a dead click', () => {\n      startClickActionsTracking()\n\n      emulateClick()\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual([FrustrationType.DEAD_CLICK])\n    })\n\n    it('does not consider a click with activity happening on pointerdown as a dead click', () => {\n      startClickActionsTracking()\n\n      emulateClick({ activity: { on: 'pointerdown' } })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual([])\n    })\n\n    it('activity happening on pointerdown is not taken into account for the action duration', () => {\n      startClickActionsTracking()\n\n      emulateClick({ activity: { on: 'pointerdown' } })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].duration).toBe(0 as Duration)\n    })\n\n    it('does not consider a click with activity happening on pointerup as a dead click', () => {\n      startClickActionsTracking()\n\n      emulateClick({ activity: { on: 'pointerup' } })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events.length).toBe(1)\n      expect(events[0].frustrationTypes).toEqual([])\n    })\n  })\n\n  describe('interactionSelectorCache', () => {\n    it('should add pointer down to the map', () => {\n      startClickActionsTracking()\n      const timeStamp = relativeNow()\n\n      emulateClick({ eventProperty: { timeStamp } })\n      expect(getInteractionSelector(timeStamp)).toBe('#button')\n    })\n\n    it('should add pointerup to the map', () => {\n      startClickActionsTracking()\n      const timeStamp = relativeNow()\n\n      emulateClick({ eventProperty: { timeStamp } })\n      expect(getInteractionSelector(timeStamp)).toBe('#button')\n    })\n  })\n\n  describe('NodePrivacyLevel masking when enablePrivacyForActionName is true', () => {\n    beforeAll(() => {\n      ;(window as BrowserWindow).$DD_ALLOW = new Set(['foo-bar'])\n    })\n\n    afterAll(() => {\n      ;(window as BrowserWindow).$DD_ALLOW = undefined\n    })\n\n    it('should mask action name when defaultPrivacyLevel is mask_unless_allowlisted and not in allowlist', () => {\n      addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('')\n      expect(events[0].nameSource).toBe(ActionNameSource.BLANK)\n    })\n\n    it('should not mask action name when defaultPrivacyLevel is allow', () => {\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Click me')\n    })\n\n    it('should not use allowlist masking when enablePrivacyForActionName is true and defaultPrivacyLevel is mask', () => {\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Masked Element')\n      expect(events[0].nameSource).toBe(ActionNameSource.MASK_PLACEHOLDER)\n    })\n\n    it('should use allowlist masking when defaultPrivacyLevel is allow and node privacy level is mask-unless-allowlisted', () => {\n      addExperimentalFeatures([ExperimentalFeature.USE_TREE_WALKER_FOR_ACTION_NAME])\n      button.setAttribute('data-dd-privacy', 'mask-unless-allowlisted')\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('')\n      expect(events[0].nameSource).toBe(ActionNameSource.BLANK)\n    })\n\n    it('should preserve mask levels when defaultPrivacyLevel is mask-unless-allowlisted', () => {\n      button.setAttribute('data-dd-privacy', 'mask')\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Masked Element')\n      expect(events[0].nameSource).toBe(ActionNameSource.MASK_PLACEHOLDER)\n    })\n\n    it('should not use allowlist masking when defaultPrivacyLevel is mask-unless-allowlisted but dd-privacy is allow', () => {\n      button.setAttribute('data-dd-privacy', 'allow')\n      startClickActionsTracking({\n        defaultPrivacyLevel: DefaultPrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n        enablePrivacyForActionName: true,\n      })\n\n      emulateClick({ activity: {} })\n      expect(findActionId()).not.toBeUndefined()\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Click me')\n    })\n  })\n\n  function emulateClick({\n    target = button,\n    activity,\n    eventProperty,\n  }: {\n    target?: HTMLElement\n    activity?: {\n      delay?: number\n      on?: 'pointerup' | 'click' | 'pointerdown'\n    }\n    eventProperty?: { [key: string]: any }\n  } = {}) {\n    const targetPosition = target.getBoundingClientRect()\n    const offsetX = targetPosition.width / 2\n    const offsetY = targetPosition.height / 2\n    const baseEventProperties = {\n      target,\n      clientX: targetPosition.left + offsetX,\n      clientY: targetPosition.top + offsetY,\n      offsetX,\n      offsetY,\n      isPrimary: true,\n      ...eventProperty,\n    }\n    target.dispatchEvent(createNewEvent('pointerdown', { ...baseEventProperties, timeStamp: relativeNow() }))\n    emulateActivityIfNeeded('pointerdown')\n    clock!.tick(EMULATED_CLICK_DURATION)\n    target.dispatchEvent(createNewEvent('pointerup', { ...baseEventProperties, timeStamp: relativeNow() }))\n    emulateActivityIfNeeded('pointerup')\n    target.dispatchEvent(createNewEvent('click', { ...baseEventProperties, timeStamp: relativeNow() }))\n    emulateActivityIfNeeded('click')\n\n    function emulateActivityIfNeeded(event: 'pointerdown' | 'pointerup' | 'click') {\n      if (activity && (activity.on ?? 'click') === event) {\n        const delay = activity.delay ?? BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY\n        if (delay < 0) {\n          // Do not use `.tick()` here because negative clock tick does not work since jasmine 4: https://github.com/jasmine/jasmine/pull/1948\n          clock!.setDate(new Date(Date.now() + delay))\n        } else {\n          clock!.tick(delay)\n        }\n        // Since we don't collect dom mutations for this test, manually dispatch one\n        domMutationObservable.notify([createMutationRecord()])\n      }\n    }\n  }\n\n  function createFakeErrorEvent() {\n    return { type: RumEventType.ERROR, action: { id: findActionId() } } as AssembledRumEvent\n  }\n\n  describe('shadow DOM support', () => {\n    let shadowHost: HTMLElement\n    let shadowButton: HTMLButtonElement\n\n    beforeEach(() => {\n      shadowHost = document.createElement('div')\n      shadowHost.id = 'shadow-host'\n      shadowHost.style.width = '100px'\n      shadowHost.style.height = '100px'\n      document.body.appendChild(shadowHost)\n\n      const shadowRoot = shadowHost.attachShadow({ mode: 'open' })\n      shadowButton = document.createElement('button')\n      shadowButton.textContent = 'Shadow Button'\n      shadowRoot.appendChild(shadowButton)\n    })\n\n    afterEach(() => {\n      shadowHost.remove()\n    })\n\n    it('with betaTrackActionsInShadowDom, gets action name from composedPath', () => {\n      startClickActionsTracking({ betaTrackActionsInShadowDom: true })\n\n      emulateClick({\n        target: shadowHost,\n        activity: {},\n        eventProperty: {\n          composed: true,\n          composedPath: () => [shadowButton, shadowHost.shadowRoot, shadowHost, document.body, document],\n        },\n      })\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].name).toBe('Shadow Button')\n    })\n\n    it('with betaTrackActionsInShadowDom, gets selector with shadow marker from composedPath', () => {\n      startClickActionsTracking({ betaTrackActionsInShadowDom: true })\n\n      emulateClick({\n        target: shadowHost,\n        activity: {},\n        eventProperty: {\n          composed: true,\n          composedPath: () => [shadowButton, shadowHost.shadowRoot, shadowHost, document.body, document],\n        },\n      })\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].target?.selector).toContain(SHADOW_DOM_MARKER)\n      expect(events[0].target?.selector).toContain('BUTTON')\n    })\n\n    it('without betaTrackActionsInShadowDom, selector uses shadow host', () => {\n      startClickActionsTracking({ betaTrackActionsInShadowDom: false })\n\n      emulateClick({\n        target: shadowHost,\n        activity: {},\n        eventProperty: {\n          composed: true,\n          composedPath: () => [shadowButton, shadowHost.shadowRoot, shadowHost, document.body, document],\n        },\n      })\n      clock.tick(EXPIRE_DELAY)\n\n      expect(events.length).toBe(1)\n      expect(events[0].target?.selector).toBe('#shadow-host')\n      expect(events[0].target?.selector).not.toContain(SHADOW_DOM_MARKER)\n    })\n  })\n\n  describe('when composed path selector is enabled', () => {\n    it('should return a composed_path_selector', () => {\n      startClickActionsTracking()\n      emulateClick({\n        target: button,\n        activity: {},\n        eventProperty: {\n          composed: true,\n          composedPath: () => [button, document.body, document],\n        },\n      })\n\n      clock.tick(EXPIRE_DELAY)\n      expect(events[0].target?.composedPathSelector).toBeDefined()\n    })\n  })\n})\n\ndescribe('finalizeClicks', () => {\n  describe('when no rage is detected', () => {\n    it('discards the rage click', () => {\n      const clicks = [createFakeClick(), createFakeClick()]\n      const rageClick = createFakeClick()\n      finalizeClicks(clicks, rageClick)\n      expect(rageClick.discard).toHaveBeenCalled()\n    })\n\n    it('validates individual clicks', () => {\n      const clicks = [createFakeClick(), createFakeClick()]\n      const rageClick = createFakeClick()\n      finalizeClicks(clicks, rageClick)\n      clicks.forEach((click) => expect(click.validate).toHaveBeenCalled())\n    })\n  })\n\n  describe('when rage is detected', () => {\n    it('discards individual clicks', () => {\n      const clicks = [createFakeClick(), createFakeClick(), createFakeClick()]\n      const rageClick = createFakeClick()\n      finalizeClicks(clicks, rageClick)\n      clicks.forEach((click) => expect(click.discard).toHaveBeenCalled())\n    })\n\n    it('validates the rage click', () => {\n      const clicks = [createFakeClick(), createFakeClick(), createFakeClick()]\n      const rageClick = createFakeClick()\n      finalizeClicks(clicks, rageClick)\n      expect(rageClick.validate).toHaveBeenCalled()\n    })\n\n    it('the rage click should have a \"rage\" frustration', () => {\n      const clicks = [createFakeClick(), createFakeClick(), createFakeClick()]\n      const rageClick = createFakeClick()\n      finalizeClicks(clicks, rageClick)\n      expect(rageClick.addFrustration).toHaveBeenCalledWith(FrustrationType.RAGE_CLICK)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/trackClickActions.ts",
    "content": "import type { Duration, ClocksState, TimeStamp } from '@datadog/browser-core'\nimport { timeStampNow, Observable, timeStampToClocks, relativeToClocks, generateUUID } from '@datadog/browser-core'\nimport { isNodeShadowHost } from '../../browser/htmlDomUtils'\nimport type { FrustrationType } from '../../rawRumEvent.types'\nimport { ActionType } from '../../rawRumEvent.types'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { PAGE_ACTIVITY_VALIDATION_DELAY, waitPageActivityEnd } from '../waitPageActivityEnd'\nimport { getSelectorFromElement } from '../getSelectorFromElement'\nimport { getNodePrivacyLevel } from '../privacy'\nimport { NodePrivacyLevel } from '../privacyConstants'\nimport type { RumConfiguration } from '../configuration'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { startEventTracker } from '../eventTracker'\nimport type { StoppedEvent, DiscardedEvent, EventTracker } from '../eventTracker'\nimport { getComposedPathSelector } from '../getComposedPathSelector'\nimport type { ClickChain } from './clickChain'\nimport { createClickChain } from './clickChain'\nimport { getActionNameFromElement } from './getActionNameFromElement'\nimport type { ActionNameSource } from './actionNameConstants'\nimport type { MouseEventOnElement, UserActivity } from './listenActionEvents'\nimport { listenActionEvents } from './listenActionEvents'\nimport { computeFrustration } from './computeFrustration'\nimport { CLICK_ACTION_MAX_DURATION, updateInteractionSelector } from './interactionSelectorCache'\nimport { isActionChildEvent } from './isActionChildEvent'\n\ninterface ActionCounts {\n  errorCount: number\n  longTaskCount: number\n  resourceCount: number\n}\n\nexport interface ClickAction {\n  type: typeof ActionType.CLICK\n  id: string\n  name: string\n  nameSource: ActionNameSource\n  target?: {\n    selector: string | undefined\n    composedPathSelector?: string\n    width: number\n    height: number\n  }\n  position?: { x: number; y: number }\n  startClocks: ClocksState\n  duration?: Duration\n  counts: ActionCounts\n  event: MouseEventOnElement\n  frustrationTypes: FrustrationType[]\n  events: Event[]\n}\n\nexport function trackClickActions(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration\n) {\n  const actionTracker = startEventTracker<ClickActionBase>(lifeCycle)\n  const stopObservable = new Observable<void>()\n  let currentClickChain: ClickChain | undefined\n\n  lifeCycle.subscribe(LifeCycleEventType.VIEW_ENDED, stopClickChain)\n  lifeCycle.subscribe(LifeCycleEventType.PAGE_MAY_EXIT, stopClickChain)\n\n  const { stop: stopActionEventsListener } = listenActionEvents<{\n    clickActionBase: ClickActionBase\n    hadActivityOnPointerDown: () => boolean\n  }>(configuration, {\n    onPointerDown: (pointerDownEvent) =>\n      processPointerDown(configuration, lifeCycle, domMutationObservable, pointerDownEvent, windowOpenObservable),\n    onPointerUp: ({ clickActionBase, hadActivityOnPointerDown }, startEvent, getUserActivity) => {\n      startClickAction(\n        configuration,\n        lifeCycle,\n        domMutationObservable,\n        windowOpenObservable,\n        actionTracker,\n        stopObservable,\n        appendClickToClickChain,\n        clickActionBase,\n        startEvent,\n        getUserActivity,\n        hadActivityOnPointerDown\n      )\n    },\n  })\n\n  return {\n    stop: () => {\n      stopClickChain()\n      stopObservable.notify()\n      stopActionEventsListener()\n      actionTracker.stopAll()\n    },\n    findActionId: actionTracker.findId,\n  }\n\n  function appendClickToClickChain(click: Click) {\n    if (!currentClickChain || !currentClickChain.tryAppend(click)) {\n      const rageClick = click.clone()\n      currentClickChain = createClickChain(click, (clicks) => {\n        finalizeClicks(clicks, rageClick)\n        // Clear the reference to allow garbage collection. Without this, the finalize callback\n        // retains a closure reference to the old click chain, preventing it from being cleaned up\n        // and causing a memory leak as click chains accumulate over time.\n        currentClickChain = undefined\n      })\n    }\n  }\n\n  function stopClickChain() {\n    if (currentClickChain) {\n      currentClickChain.stop()\n    }\n  }\n}\n\nfunction processPointerDown(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  pointerDownEvent: MouseEventOnElement,\n  windowOpenObservable: Observable<void>\n) {\n  const targetForPrivacy = configuration.betaTrackActionsInShadowDom\n    ? getEventTarget(pointerDownEvent)\n    : pointerDownEvent.target\n\n  let nodePrivacyLevel: NodePrivacyLevel\n\n  if (configuration.enablePrivacyForActionName) {\n    nodePrivacyLevel = getNodePrivacyLevel(targetForPrivacy, configuration.defaultPrivacyLevel)\n  } else {\n    nodePrivacyLevel = NodePrivacyLevel.ALLOW\n  }\n\n  if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n    return undefined\n  }\n\n  const clickActionBase = computeClickActionBase(pointerDownEvent, nodePrivacyLevel, configuration)\n\n  let hadActivityOnPointerDown = false\n\n  waitPageActivityEnd(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration,\n    (pageActivityEndEvent) => {\n      hadActivityOnPointerDown = pageActivityEndEvent.hadActivity\n    },\n    // We don't care about the activity duration, we just want to know whether an activity did happen\n    // within the \"validation delay\" or not. Limit the duration so the callback is called sooner.\n    PAGE_ACTIVITY_VALIDATION_DELAY\n  )\n\n  return { clickActionBase, hadActivityOnPointerDown: () => hadActivityOnPointerDown }\n}\n\nfunction startClickAction(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  actionTracker: EventTracker<ClickActionBase>,\n  stopObservable: Observable<void>,\n  appendClickToClickChain: (click: Click) => void,\n  clickActionBase: ClickActionBase,\n  startEvent: MouseEventOnElement,\n  getUserActivity: () => UserActivity,\n  hadActivityOnPointerDown: () => boolean\n) {\n  const click = newClick(lifeCycle, actionTracker, getUserActivity, clickActionBase, startEvent)\n  appendClickToClickChain(click)\n\n  const selector = clickActionBase?.target?.selector\n  if (selector) {\n    updateInteractionSelector(startEvent.timeStamp, selector)\n  }\n\n  const { stop: stopWaitPageActivityEnd } = waitPageActivityEnd(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration,\n    (pageActivityEndEvent) => {\n      if (pageActivityEndEvent.hadActivity && pageActivityEndEvent.end < click.startClocks.timeStamp) {\n        // If the clock is looking weird, just discard the click\n        click.discard()\n      } else {\n        if (pageActivityEndEvent.hadActivity) {\n          click.stop(pageActivityEndEvent.end)\n        } else if (hadActivityOnPointerDown()) {\n          click.stop(\n            // using the click start as activity end, so the click will have some activity but its\n            // duration will be 0 (as the activity started before the click start)\n            click.startClocks.timeStamp\n          )\n        } else {\n          click.stop()\n        }\n      }\n    },\n    CLICK_ACTION_MAX_DURATION\n  )\n\n  const viewEndedSubscription = lifeCycle.subscribe(LifeCycleEventType.VIEW_ENDED, ({ endClocks }) => {\n    click.stop(endClocks.timeStamp)\n  })\n\n  const pageMayExitSubscription = lifeCycle.subscribe(LifeCycleEventType.PAGE_MAY_EXIT, () => {\n    click.stop(timeStampNow())\n  })\n\n  const stopSubscription = stopObservable.subscribe(() => {\n    click.stop()\n  })\n\n  click.stopObservable.subscribe(() => {\n    pageMayExitSubscription.unsubscribe()\n    viewEndedSubscription.unsubscribe()\n    stopWaitPageActivityEnd()\n    stopSubscription.unsubscribe()\n  })\n}\n\nexport type ClickActionBase = Pick<ClickAction, 'type' | 'name' | 'nameSource' | 'target' | 'position'>\n\nfunction computeClickActionBase(\n  event: MouseEventOnElement,\n  nodePrivacyLevel: NodePrivacyLevel,\n  configuration: RumConfiguration\n): ClickActionBase {\n  const target = configuration.betaTrackActionsInShadowDom ? getEventTarget(event) : event.target\n\n  const rect = target.getBoundingClientRect()\n  const selector = getSelectorFromElement(target, configuration.actionNameAttribute)\n\n  const composedPathSelector = getComposedPathSelector(event.composedPath(), configuration.actionNameAttribute)\n\n  if (selector) {\n    updateInteractionSelector(event.timeStamp, selector)\n  }\n\n  const { name, nameSource } = getActionNameFromElement(target, configuration, nodePrivacyLevel)\n\n  return {\n    type: ActionType.CLICK,\n    target: {\n      width: Math.round(rect.width),\n      height: Math.round(rect.height),\n      selector,\n      composedPathSelector: composedPathSelector || undefined,\n    },\n    position: {\n      // Use clientX and Y because for SVG element offsetX and Y are relatives to the <svg> element\n      x: Math.round(event.clientX - rect.left),\n      y: Math.round(event.clientY - rect.top),\n    },\n    name,\n    nameSource,\n  }\n}\n\nfunction getEventTarget(event: MouseEventOnElement): Element {\n  if (event.composed && isNodeShadowHost(event.target) && typeof event.composedPath === 'function') {\n    const composedPath = event.composedPath()\n    if (composedPath.length > 0 && composedPath[0] instanceof Element) {\n      return composedPath[0]\n    }\n  }\n  return event.target\n}\n\nconst enum ClickStatus {\n  // Initial state, the click is still ongoing.\n  ONGOING,\n  // The click is no more ongoing but still needs to be validated or discarded.\n  STOPPED,\n  // Final state, the click has been stopped and validated or discarded.\n  FINALIZED,\n}\n\nexport type Click = ReturnType<typeof newClick>\n\nfunction newClick(\n  lifeCycle: LifeCycle,\n  actionTracker: EventTracker<ClickActionBase>,\n  getUserActivity: () => UserActivity,\n  clickActionBase: ClickActionBase,\n  startEvent: MouseEventOnElement\n) {\n  const clickKey = generateUUID()\n  const startClocks = relativeToClocks(startEvent.timeStamp)\n\n  const startedClickAction = actionTracker.start(clickKey, startClocks, clickActionBase, {\n    isChildEvent: isActionChildEvent,\n  })\n\n  lifeCycle.notify(LifeCycleEventType.ACTION_STARTED, startedClickAction)\n\n  let status = ClickStatus.ONGOING\n  let actionTrackerFinishedEvent: StoppedEvent<ClickActionBase> | DiscardedEvent<ClickActionBase> | undefined\n  const frustrationTypes: FrustrationType[] = []\n  const stopObservable = new Observable<void>()\n\n  function stop(activityEndTime?: TimeStamp) {\n    if (status !== ClickStatus.ONGOING) {\n      return\n    }\n\n    status = ClickStatus.STOPPED\n\n    actionTrackerFinishedEvent = activityEndTime\n      ? actionTracker.stop(clickKey, timeStampToClocks(activityEndTime))\n      : actionTracker.discard(clickKey)\n\n    stopObservable.notify()\n  }\n\n  return {\n    event: startEvent,\n    stop,\n    stopObservable,\n\n    get hasError() {\n      const currentCounts = actionTrackerFinishedEvent?.counts ?? actionTracker.getCounts(clickKey)\n      return currentCounts ? currentCounts.errorCount > 0 : false\n    },\n    get hasPageActivity() {\n      return actionTrackerFinishedEvent && 'duration' in actionTrackerFinishedEvent\n    },\n    getUserActivity,\n    addFrustration: (frustrationType: FrustrationType) => {\n      frustrationTypes.push(frustrationType)\n    },\n    get startClocks() {\n      return startClocks\n    },\n\n    isStopped: () => status === ClickStatus.STOPPED || status === ClickStatus.FINALIZED,\n\n    clone: () => newClick(lifeCycle, actionTracker, getUserActivity, clickActionBase, startEvent),\n\n    validate: (domEvents?: Event[]) => {\n      stop()\n      if (status !== ClickStatus.STOPPED) {\n        return\n      }\n\n      if (!actionTrackerFinishedEvent) {\n        return\n      }\n\n      const clickAction: ClickAction = {\n        frustrationTypes,\n        events: domEvents ?? [startEvent],\n        event: startEvent,\n        ...actionTrackerFinishedEvent,\n        counts: actionTrackerFinishedEvent.counts!, // This is needed to satisfy the type checker\n      }\n\n      lifeCycle.notify(LifeCycleEventType.AUTO_ACTION_COMPLETED, clickAction)\n      status = ClickStatus.FINALIZED\n    },\n\n    discard: () => {\n      stop()\n      status = ClickStatus.FINALIZED\n    },\n  }\n}\n\nexport function finalizeClicks(clicks: Click[], rageClick: Click) {\n  const { isRage } = computeFrustration(clicks, rageClick)\n  if (isRage) {\n    clicks.forEach((click) => click.discard())\n    rageClick.stop(timeStampNow())\n    rageClick.validate(clicks.map((click) => click.event))\n  } else {\n    rageClick.discard()\n    clicks.forEach((click) => click.validate())\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/trackManualActions.spec.ts",
    "content": "import type { Duration, ServerDuration } from '@datadog/browser-core'\nimport { addExperimentalFeatures, ExperimentalFeature, Observable } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport { collectAndValidateRawRumEvents, mockRumConfiguration } from '../../../test'\nimport type { RawRumActionEvent, RawRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType, ActionType, FrustrationType } from '../../rawRumEvent.types'\nimport { type RawRumEventCollectedData, LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { createHooks } from '../hooks'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { startActionCollection } from './actionCollection'\nimport type { ActionContexts } from './actionCollection'\n\ndescribe('trackManualActions', () => {\n  const lifeCycle = new LifeCycle()\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>>\n  let actionContexts: ActionContexts\n  let startAction: ReturnType<typeof startActionCollection>['startAction']\n  let stopAction: ReturnType<typeof startActionCollection>['stopAction']\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    addExperimentalFeatures([ExperimentalFeature.START_STOP_ACTION])\n\n    const domMutationObservable = new Observable<RumMutationRecord[]>()\n    const windowOpenObservable = new Observable<void>()\n    const hooks = createHooks()\n\n    const actionCollection = startActionCollection(\n      lifeCycle,\n      hooks,\n      domMutationObservable,\n      windowOpenObservable,\n      mockRumConfiguration()\n    )\n    registerCleanupTask(actionCollection.stop)\n    startAction = actionCollection.startAction\n    stopAction = actionCollection.stopAction\n    actionContexts = actionCollection.actionContexts\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n  })\n\n  describe('basic functionality', () => {\n    it('should create action with duration from name-based tracking', () => {\n      startAction('user_login')\n      clock.tick(500)\n      stopAction('user_login')\n\n      expect(rawRumEvents).toHaveSize(1)\n      expect(rawRumEvents[0].duration).toBe(500 as Duration)\n      expect(rawRumEvents[0].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          type: RumEventType.ACTION,\n          action: jasmine.objectContaining({\n            target: { name: 'user_login' },\n            type: ActionType.CUSTOM,\n          }),\n        })\n      )\n    })\n\n    it('should use consistent action ID from start to collected event', () => {\n      startAction('checkout')\n\n      const actionId = actionContexts.findActionId()\n      expect(actionId).toBeDefined()\n\n      stopAction('checkout')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const actionEvent = rawRumEvents[0].rawRumEvent as RawRumActionEvent\n      expect(actionEvent.action.id).toEqual(actionId[0])\n    })\n\n    it('should include loading_time for timed manual actions', () => {\n      startAction('checkout')\n      clock.tick(500)\n      stopAction('checkout')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const actionEvent = rawRumEvents[0].rawRumEvent as RawRumActionEvent\n      expect(actionEvent.action.loading_time).toBe((500 * 1e6) as ServerDuration)\n    })\n  })\n\n  describe('action types', () => {\n    ;[ActionType.SWIPE, ActionType.TAP, ActionType.SCROLL].forEach((actionType) => {\n      it(`should support ${actionType} action type`, () => {\n        startAction('test_action', { type: actionType })\n        stopAction('test_action')\n\n        expect(rawRumEvents).toHaveSize(1)\n        expect(rawRumEvents[0].rawRumEvent).toEqual(\n          jasmine.objectContaining({\n            type: RumEventType.ACTION,\n            action: jasmine.objectContaining({\n              type: actionType,\n            }),\n          })\n        )\n      })\n    })\n\n    it('should handle type precedence (stop overrides start)', () => {\n      startAction('action1', { type: ActionType.TAP })\n      stopAction('action1', { type: ActionType.SCROLL })\n\n      startAction('action2', { type: ActionType.SWIPE })\n      stopAction('action2')\n\n      startAction('action3')\n      stopAction('action3')\n\n      expect(rawRumEvents).toHaveSize(3)\n      expect(rawRumEvents[0].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          action: jasmine.objectContaining({ type: ActionType.SCROLL }),\n        })\n      )\n      expect(rawRumEvents[1].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          action: jasmine.objectContaining({ type: ActionType.SWIPE }),\n        })\n      )\n      expect(rawRumEvents[2].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          action: jasmine.objectContaining({ type: ActionType.CUSTOM }),\n        })\n      )\n    })\n  })\n\n  describe('actionKey', () => {\n    it('should support actionKey for tracking same name multiple times', () => {\n      startAction('click', { actionKey: 'button1' })\n      startAction('click', { actionKey: 'button2' })\n\n      clock.tick(100)\n      stopAction('click', { actionKey: 'button2' })\n\n      clock.tick(100)\n      stopAction('click', { actionKey: 'button1' })\n\n      expect(rawRumEvents).toHaveSize(2)\n      expect(rawRumEvents[0].duration).toBe(100 as Duration)\n      expect(rawRumEvents[1].duration).toBe(200 as Duration)\n    })\n\n    it('getActionLookupKey should not collide', () => {\n      startAction('foo bar')\n      startAction('foo', { actionKey: 'bar' })\n\n      const actionIds = actionContexts.findActionId()\n      expect(Array.isArray(actionIds)).toBeTrue()\n      expect(actionIds.length).toBe(2)\n\n      stopAction('foo bar')\n      stopAction('foo', { actionKey: 'bar' })\n\n      expect(rawRumEvents).toHaveSize(2)\n      expect(rawRumEvents[0].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          action: jasmine.objectContaining({ target: { name: 'foo bar' } }),\n        })\n      )\n      expect(rawRumEvents[1].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          action: jasmine.objectContaining({ target: { name: 'foo' } }),\n        })\n      )\n    })\n  })\n\n  describe('event counting', () => {\n    it('should include counts in the action event', () => {\n      startAction('complex-action')\n\n      const actionId = actionContexts.findActionId()\n\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.ERROR,\n        action: { id: actionId },\n      } as any)\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.ERROR,\n        action: { id: actionId },\n      } as any)\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.RESOURCE,\n        action: { id: actionId },\n      } as any)\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.LONG_TASK,\n        action: { id: actionId },\n      } as any)\n\n      stopAction('complex-action')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const actionEvent = rawRumEvents[0].rawRumEvent as RawRumActionEvent\n      expect(actionEvent.action.error?.count).toBe(2)\n      expect(actionEvent.action.resource?.count).toBe(1)\n      expect(actionEvent.action.long_task?.count).toBe(1)\n    })\n  })\n\n  describe('frustration detection', () => {\n    it('should include ERROR_CLICK frustration when action has errors', () => {\n      startAction('error-action')\n\n      const actionId = actionContexts.findActionId()\n\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.ERROR,\n        action: { id: actionId },\n      } as any)\n\n      stopAction('error-action')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const actionEvent = rawRumEvents[0].rawRumEvent as RawRumActionEvent\n      expect(actionEvent.action.frustration?.type).toEqual([FrustrationType.ERROR_CLICK])\n    })\n\n    it('should have empty frustration array when action has no errors', () => {\n      startAction('success-action')\n      stopAction('success-action')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const actionEvent = rawRumEvents[0].rawRumEvent as RawRumActionEvent\n      expect(actionEvent.action.frustration?.type).toEqual([])\n    })\n\n    it('should include ERROR_CLICK frustration when action has multiple errors', () => {\n      startAction('multi-error-action')\n\n      const actionId = actionContexts.findActionId()\n\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.ERROR,\n        action: { id: actionId },\n      } as any)\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.ERROR,\n        action: { id: actionId },\n      } as any)\n\n      stopAction('multi-error-action')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const actionEvent = rawRumEvents[0].rawRumEvent as RawRumActionEvent\n      expect(actionEvent.action.frustration?.type).toEqual([FrustrationType.ERROR_CLICK])\n      expect(actionEvent.action.error?.count).toBe(2)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/action/trackManualActions.ts",
    "content": "import type { ClocksState, Context, Duration } from '@datadog/browser-core'\nimport { clocksNow, generateUUID } from '@datadog/browser-core'\nimport type { ActionType, FrustrationType } from '../../rawRumEvent.types'\nimport { ActionType as ActionTypeEnum, FrustrationType as FrustrationTypeEnum } from '../../rawRumEvent.types'\nimport type { EventCounts } from '../trackEventCounts'\nimport { startEventTracker } from '../eventTracker'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { isActionChildEvent } from './isActionChildEvent'\n\nexport type ActionCounts = EventCounts\n\nexport interface ActionOptions {\n  /**\n   * Action Type\n   *\n   * @default 'custom'\n   */\n  type?: ActionType\n\n  /**\n   * Action context\n   */\n  context?: any\n\n  /**\n   * Action key\n   */\n  actionKey?: string\n}\n\nexport interface ManualAction {\n  id: string\n  type: ActionType\n  name: string\n  startClocks: ClocksState\n  duration?: Duration\n  context?: Context\n  handlingStack?: string\n  counts?: ActionCounts\n  frustrationTypes: FrustrationType[]\n}\n\nexport interface ActionEventData {\n  name: string\n  type?: ActionType\n  context?: Context\n}\n\nexport function trackManualActions(lifeCycle: LifeCycle, onManualActionCompleted: (action: ManualAction) => void) {\n  const actionTracker = startEventTracker<ActionEventData>(lifeCycle)\n  function startManualAction(name: string, options: ActionOptions = {}, startClocks = clocksNow()) {\n    const lookupKey = options.actionKey ?? name\n\n    const startedManualAction = actionTracker.start(\n      lookupKey,\n      startClocks,\n      {\n        name,\n        ...options,\n      },\n      { isChildEvent: isActionChildEvent }\n    )\n\n    lifeCycle.notify(LifeCycleEventType.ACTION_STARTED, startedManualAction)\n  }\n\n  function stopManualAction(name: string, options: ActionOptions = {}, stopClocks = clocksNow()) {\n    const lookupKey = options.actionKey ?? name\n\n    const stopped = actionTracker.stop(lookupKey, stopClocks, options)\n\n    if (!stopped) {\n      return\n    }\n\n    const frustrationTypes: FrustrationType[] = []\n    if (stopped.counts && stopped.counts.errorCount > 0) {\n      frustrationTypes.push(FrustrationTypeEnum.ERROR_CLICK)\n    }\n\n    const manualAction: ManualAction = {\n      ...stopped,\n      type: stopped.type || ActionTypeEnum.CUSTOM,\n      frustrationTypes,\n    }\n\n    onManualActionCompleted(manualAction)\n  }\n\n  function addInstantAction(action: Omit<ManualAction, 'id' | 'duration' | 'counts' | 'frustrationTypes'>) {\n    onManualActionCompleted({ id: generateUUID(), frustrationTypes: [], ...action })\n  }\n\n  return {\n    addAction: addInstantAction,\n    startAction: startManualAction,\n    stopAction: stopManualAction,\n    findActionId: actionTracker.findId,\n    stop: actionTracker.stopAll,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/assembly.spec.ts",
    "content": "import type { ClocksState, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport {\n  ErrorSource,\n  HookNames,\n  ONE_MINUTE,\n  display,\n  relativeToClocks,\n  startGlobalContext,\n  startTabContext,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { registerCleanupTask, mockClock } from '@datadog/browser-core/test'\nimport {\n  createRumSessionManagerMock,\n  createRawRumEvent,\n  mockRumConfiguration,\n  mockViewHistory,\n  noopRecorderApi,\n} from '../../test'\nimport type { RumEventDomainContext } from '../domainContext.types'\nimport type { RawRumEvent } from '../rawRumEvent.types'\nimport { RumEventType } from '../rawRumEvent.types'\nimport type { RumErrorEvent, RumEvent, RumResourceEvent } from '../rumEvent.types'\nimport { startRumAssembly } from './assembly'\nimport type { RawRumEventCollectedData } from './lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport type { RumConfiguration } from './configuration'\nimport type { ViewHistory } from './contexts/viewHistory'\nimport type { RumSessionManager } from './rumSessionManager'\nimport { startSessionContext } from './contexts/sessionContext'\nimport { createHooks } from './hooks'\n\ndescribe('rum assembly', () => {\n  describe('beforeSend', () => {\n    describe('fields modification', () => {\n      describe('modifiable fields', () => {\n        it('should allow modification', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => (event.view.url = 'modified'),\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { view: { url: '/path?foo=bar' } }),\n          })\n\n          expect(serverRumEvents[0].view.url).toBe('modified')\n        })\n\n        it('should allow addition', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => (event.view.name = 'added'),\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { view: { url: '/path?foo=bar' } }),\n          })\n\n          expect(serverRumEvents[0].view.name).toBe('added')\n        })\n\n        it('should allow modification of view.performance.lcp.resource_url', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => (event.view.performance.lcp.resource_url = 'modified_url'),\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.VIEW, {\n              view: { performance: { lcp: { resource_url: 'original_url' } } },\n            }),\n          })\n\n          expect((serverRumEvents[0].view as any).performance.lcp.resource_url).toBe('modified_url')\n        })\n\n        it('should allow modification of error.handling_stack', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => (event.error.handling_stack = 'modified_handling_stack'),\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.ERROR, {\n              error: { handling_stack: 'original_handling_stack' },\n            }),\n          })\n\n          expect((serverRumEvents[0].error as any).handling_stack).toBe('modified_handling_stack')\n        })\n      })\n\n      describe('context field', () => {\n        it('should allow modification on context field for events other than views', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.context.foo = 'bar'\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK),\n          })\n\n          expect(serverRumEvents[0].context!.foo).toBe('bar')\n        })\n\n        it('should allow replacing the context field for events other than views', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.context.foo = 'bar'\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK),\n          })\n\n          expect(serverRumEvents[0].context!.foo).toBe('bar')\n        })\n\n        it('should empty the context field if set to null', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.context = null\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { context: { foo: 'bar' } }),\n          })\n\n          expect(serverRumEvents[0].context).toBeUndefined()\n        })\n\n        it('should empty the context field if set to undefined', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.context = undefined\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { context: { foo: 'bar' } }),\n          })\n\n          expect(serverRumEvents[0].context).toBeUndefined()\n        })\n\n        it('should empty the context field if deleted', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                delete event.context\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { context: { foo: 'bar' } }),\n          })\n\n          expect(serverRumEvents[0].context).toBeUndefined()\n        })\n\n        it('should define the context field even if the global context is empty', () => {\n          const { lifeCycle } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                expect(event.context).toEqual({})\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK),\n          })\n        })\n\n        it('should accept modification on context field for view events', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.context.foo = 'bar'\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.VIEW),\n          })\n\n          expect(serverRumEvents[0].context).toEqual({ foo: 'bar' })\n        })\n\n        it('should reject replacing the context field to non-object', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.context = 1\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { context: { foo: 'bar' } }),\n          })\n\n          expect(serverRumEvents[0].context!.foo).toBe('bar')\n        })\n      })\n\n      describe('allowed customer provided field', () => {\n        it('should allow modification of the error fingerprint', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => (event.error.fingerprint = 'my_fingerprint'),\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.ERROR),\n          })\n\n          expect((serverRumEvents[0] as RumErrorEvent).error.fingerprint).toBe('my_fingerprint')\n        })\n      })\n\n      describe('field resource.graphql on Resource events', () => {\n        it('should allow modification of resource.graphql.variables property', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                if (event.resource!.graphql) {\n                  event.resource!.graphql.variables = '{\"modified\":\"value\"}'\n                }\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, {\n              resource: {\n                graphql: {\n                  operationType: 'query',\n                  variables: '{\"original\":\"value\"}',\n                },\n              },\n            }),\n          })\n\n          expect((serverRumEvents[0] as RumResourceEvent).resource.graphql!.variables).toBe('{\"modified\":\"value\"}')\n        })\n      })\n\n      describe('resource headers on Resource events', () => {\n        it('should allow modification of resource request and response headers', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                event.resource!.request!.headers!['x-request-id'] = 'REDACTED'\n                event.resource!.response!.headers!['x-powered-by'] = 'REDACTED'\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, {\n              resource: {\n                request: { headers: { 'x-request-id': 'abc-123', 'content-type': 'application/json' } },\n                response: { headers: { 'x-powered-by': 'Express', 'content-type': 'text/html' } },\n              },\n            }),\n          })\n\n          const resource = (serverRumEvents[0] as RumResourceEvent).resource\n          expect(resource.request!.headers!['x-request-id']).toBe('REDACTED')\n          expect(resource.request!.headers!['content-type']).toBe('application/json')\n          expect(resource.response!.headers!['x-powered-by']).toBe('REDACTED')\n          expect(resource.response!.headers!['content-type']).toBe('text/html')\n        })\n\n        it('should allow deletion of resource request and response headers', () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            partialConfiguration: {\n              beforeSend: (event) => {\n                delete event.resource!.request!.headers!['x-request-id']\n                delete event.resource!.response!.headers!['x-powered-by']\n              },\n            },\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, {\n              resource: {\n                request: { headers: { 'x-request-id': 'abc-123', 'content-type': 'application/json' } },\n                response: { headers: { 'x-powered-by': 'Express', 'content-type': 'text/html' } },\n              },\n            }),\n          })\n\n          const resource = (serverRumEvents[0] as RumResourceEvent).resource\n          expect(resource.request!.headers!['x-request-id']).toBeUndefined()\n          expect(resource.request!.headers!['content-type']).toBe('application/json')\n          expect(resource.response!.headers!['x-powered-by']).toBeUndefined()\n          expect(resource.response!.headers!['content-type']).toBe('text/html')\n        })\n      })\n\n      it('should reject modification of field not sensitive, context or customer provided', () => {\n        const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n          partialConfiguration: {\n            beforeSend: (event: RumEvent) => ((event.view as any).id = 'modified'),\n          },\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n            view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n          }),\n        })\n\n        expect(serverRumEvents[0].view.id).toBe('aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee')\n      })\n\n      it('should not allow to add a sensitive field on the wrong event type', () => {\n        const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n          partialConfiguration: {\n            beforeSend: (event) => {\n              event.error = { message: 'added' }\n            },\n          },\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.VIEW),\n        })\n\n        expect((serverRumEvents[0] as any).error?.message).toBeUndefined()\n      })\n    })\n\n    describe('events dismission', () => {\n      it('should allow dismissing events other than views', () => {\n        const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n          partialConfiguration: {\n            beforeSend: () => false,\n          },\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n            view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n          }),\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.ERROR, {\n            view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n          }),\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, {\n            view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n          }),\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, {\n            view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n          }),\n        })\n\n        expect(serverRumEvents.length).toBe(0)\n      })\n\n      it('should not allow dismissing view events', () => {\n        const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n          partialConfiguration: {\n            beforeSend: () => false,\n          },\n        })\n\n        const displaySpy = spyOn(display, 'warn')\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(RumEventType.VIEW, {\n            view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n          }),\n        })\n\n        expect(serverRumEvents[0].view.id).toBe('aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee')\n        expect(displaySpy).toHaveBeenCalledWith(\"Can't dismiss view events using beforeSend!\")\n      })\n    })\n\n    it('should not dismiss when true is returned', () => {\n      const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n        partialConfiguration: {\n          beforeSend: () => true,\n        },\n      })\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n        }),\n      })\n\n      expect(serverRumEvents.length).toBe(1)\n    })\n\n    it('should not dismiss when undefined is returned', () => {\n      const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n        partialConfiguration: {\n          beforeSend: () => undefined,\n        },\n      })\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, {\n          view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' },\n        }),\n      })\n\n      expect(serverRumEvents.length).toBe(1)\n    })\n  })\n\n  describe('service and version', () => {\n    const extraConfigurationOptions = { service: 'default-service', version: 'default-version' }\n\n    Object.values(RumEventType).forEach((eventType) => {\n      it(`should be modifiable for ${eventType}`, () => {\n        const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n          partialConfiguration: {\n            ...extraConfigurationOptions,\n            beforeSend: (event) => {\n              event.service = 'bar'\n              event.version = '0.2.0'\n\n              return true\n            },\n          },\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType),\n        })\n        expect((serverRumEvents[0] as RumResourceEvent).service).toBe('bar')\n        expect((serverRumEvents[0] as RumResourceEvent).version).toBe('0.2.0')\n      })\n    })\n\n    it('should be added to the event as ddtags', () => {\n      const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n        partialConfiguration: extraConfigurationOptions,\n      })\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW),\n      })\n\n      expect(serverRumEvents[0].ddtags).toEqual('sdk_version:test,service:default-service,version:default-version')\n    })\n  })\n\n  describe('assemble hook', () => {\n    it('should add and override common properties', () => {\n      const { lifeCycle, hooks, serverRumEvents } = setupAssemblyTestWithDefaults({\n        partialConfiguration: { service: 'default-service', version: 'default-version' },\n      })\n\n      hooks.register(HookNames.Assemble, ({ eventType }) => ({\n        type: eventType,\n        service: 'new service',\n        version: 'new version',\n        view: { id: 'new view id', url: '' },\n      }))\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION),\n      })\n      expect(serverRumEvents[0].service).toEqual('new service')\n      expect(serverRumEvents[0].version).toEqual('new version')\n      expect(serverRumEvents[0].view.id).toEqual('new view id')\n    })\n\n    it('should not override customer context', () => {\n      const { lifeCycle, hooks, serverRumEvents } = setupAssemblyTestWithDefaults()\n\n      hooks.register(HookNames.Assemble, ({ eventType }) => ({\n        type: eventType,\n        context: { foo: 'bar' },\n      }))\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION, { context: { foo: 'customer context' } }),\n      })\n      expect(serverRumEvents[0].context).toEqual({ foo: 'customer context' })\n    })\n\n    it('should include tab.id from tabContext', () => {\n      const { lifeCycle, hooks, serverRumEvents } = setupAssemblyTestWithDefaults()\n\n      startTabContext(hooks)\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW),\n      })\n\n      expect((serverRumEvents[0] as any).tab.id).toEqual(jasmine.any(String))\n    })\n  })\n\n  describe('event generation condition', () => {\n    it('when tracked, it should generate event', () => {\n      const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults()\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW),\n      })\n      expect(serverRumEvents.length).toBe(1)\n    })\n\n    it('when not tracked, it should not generate event', () => {\n      const sessionManager = createRumSessionManagerMock().setNotTracked()\n      const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({ sessionManager })\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.VIEW),\n      })\n      expect(serverRumEvents.length).toBe(0)\n    })\n\n    it('should get session state from event start', () => {\n      const sessionManager = createRumSessionManagerMock()\n      spyOn(sessionManager, 'findTrackedSession').and.callThrough()\n      const { lifeCycle } = setupAssemblyTestWithDefaults({ sessionManager })\n\n      notifyRawRumEvent(lifeCycle, {\n        rawRumEvent: createRawRumEvent(RumEventType.ACTION),\n        startClocks: relativeToClocks(123 as RelativeTime),\n      })\n\n      expect(sessionManager.findTrackedSession).toHaveBeenCalledWith(123 as RelativeTime)\n    })\n  })\n  ;[\n    {\n      eventType: RumEventType.ERROR,\n      message: 'Reached max number of errors by minute: 1',\n    },\n    {\n      eventType: RumEventType.ACTION,\n      message: 'Reached max number of actions by minute: 1',\n    },\n    {\n      eventType: RumEventType.VITAL,\n      message: 'Reached max number of vitals by minute: 1',\n    },\n  ].forEach(({ eventType, message }) => {\n    describe(`${eventType} events limitation`, () => {\n      it(`stops sending ${eventType} events when reaching the limit`, () => {\n        const { lifeCycle, serverRumEvents, reportErrorSpy } = setupAssemblyTestWithDefaults({\n          eventRateLimit: 1,\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType, { date: 100 as TimeStamp }),\n        })\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType, { date: 200 as TimeStamp }),\n        })\n\n        expect(serverRumEvents.length).toBe(1)\n        expect(serverRumEvents[0].date).toBe(100)\n        expect(reportErrorSpy).toHaveBeenCalledTimes(1)\n        expect(reportErrorSpy.calls.argsFor(0)[0]).toEqual(\n          jasmine.objectContaining({\n            message,\n            source: ErrorSource.AGENT,\n          })\n        )\n      })\n\n      it(`does not take discarded ${eventType} events into account`, () => {\n        const { lifeCycle, serverRumEvents, reportErrorSpy } = setupAssemblyTestWithDefaults({\n          partialConfiguration: {\n            beforeSend: (event) => {\n              if (event.type === eventType && event.date === 100) {\n                return false\n              }\n            },\n          },\n          eventRateLimit: 1,\n        })\n\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType, { date: 100 as TimeStamp }),\n        })\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType, { date: 100 as TimeStamp }),\n        })\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType, { date: 100 as TimeStamp }),\n        })\n        notifyRawRumEvent(lifeCycle, {\n          rawRumEvent: createRawRumEvent(eventType, { date: 200 as TimeStamp }),\n        })\n        expect(serverRumEvents.length).toBe(1)\n        expect(serverRumEvents[0].date).toBe(200)\n        expect(reportErrorSpy).not.toHaveBeenCalled()\n      })\n\n      describe('when clock ticks with one minute', () => {\n        let clock: Clock\n        beforeEach(() => {\n          clock = mockClock()\n        })\n\n        it(`allows to send new ${eventType} events after a minute`, () => {\n          const { lifeCycle, serverRumEvents } = setupAssemblyTestWithDefaults({\n            eventRateLimit: 1,\n          })\n\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(eventType, { date: 100 as TimeStamp }),\n          })\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(eventType, { date: 200 as TimeStamp }),\n          })\n          clock.tick(ONE_MINUTE)\n          notifyRawRumEvent(lifeCycle, {\n            rawRumEvent: createRawRumEvent(eventType, { date: 300 as TimeStamp }),\n          })\n\n          expect(serverRumEvents.length).toBe(2)\n          expect(serverRumEvents[0].date).toBe(100)\n          expect(serverRumEvents[1].date).toBe(300)\n        })\n      })\n    })\n  })\n})\n\nfunction notifyRawRumEvent<E extends RawRumEvent>(\n  lifeCycle: LifeCycle,\n  partialData: Omit<RawRumEventCollectedData<E>, 'startClocks' | 'domainContext'> &\n    Partial<Pick<RawRumEventCollectedData<E>, 'startClocks' | 'domainContext'>>\n) {\n  const fullData = {\n    startClocks: relativeToClocks(0 as RelativeTime),\n    domainContext: {} as RumEventDomainContext,\n    ...partialData,\n  }\n  lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, fullData)\n}\n\ninterface AssemblyTestParams {\n  partialConfiguration?: Partial<RumConfiguration>\n  sessionManager?: RumSessionManager\n  ciVisibilityContext?: Record<string, string>\n  findView?: ViewHistory['findView']\n  eventRateLimit?: number\n}\n\nfunction setupAssemblyTestWithDefaults({\n  partialConfiguration,\n  sessionManager,\n  findView = () => ({ id: '7890', name: 'view name', startClocks: {} as ClocksState, sessionIsActive: false }),\n  eventRateLimit,\n}: AssemblyTestParams = {}) {\n  const lifeCycle = new LifeCycle()\n  const hooks = createHooks()\n  const reportErrorSpy = jasmine.createSpy('reportError')\n  const rumSessionManager = sessionManager ?? createRumSessionManagerMock().setId('1234')\n  const serverRumEvents: RumEvent[] = []\n  const subscription = lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, (serverRumEvent) => {\n    serverRumEvents.push(serverRumEvent)\n  })\n  const recorderApi = noopRecorderApi\n  const viewHistory = { ...mockViewHistory(), findView: () => findView() }\n  startGlobalContext(hooks, mockRumConfiguration(), 'rum', true)\n  startSessionContext(hooks, rumSessionManager, recorderApi, viewHistory)\n  startRumAssembly(mockRumConfiguration(partialConfiguration), lifeCycle, hooks, reportErrorSpy, eventRateLimit)\n\n  registerCleanupTask(() => {\n    subscription.unsubscribe()\n  })\n\n  return { lifeCycle, hooks, reportErrorSpy, serverRumEvents, recorderApi }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/assembly.ts",
    "content": "import type { RawError, EventRateLimiter } from '@datadog/browser-core'\nimport {\n  combine,\n  isEmptyObject,\n  display,\n  createEventRateLimiter,\n  HookNames,\n  DISCARDED,\n  buildTags,\n} from '@datadog/browser-core'\nimport type { RumEventDomainContext } from '../domainContext.types'\nimport type { AssembledRumEvent } from '../rawRumEvent.types'\nimport { RumEventType } from '../rawRumEvent.types'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\nimport type { RumConfiguration } from './configuration'\nimport type { ModifiableFieldPaths } from './limitModification'\nimport { limitModification } from './limitModification'\nimport type { Hooks, AssembleHookParams } from './hooks'\n\nconst VIEW_MODIFIABLE_FIELD_PATHS: ModifiableFieldPaths = {\n  'view.name': 'string',\n  'view.url': 'string',\n  'view.referrer': 'string',\n}\n\nconst USER_CUSTOMIZABLE_FIELD_PATHS: ModifiableFieldPaths = {\n  context: 'object',\n}\n\nconst ROOT_MODIFIABLE_FIELD_PATHS: ModifiableFieldPaths = {\n  service: 'string',\n  version: 'string',\n}\n\nlet modifiableFieldPathsByEvent: { [key in RumEventType]: ModifiableFieldPaths }\n\nexport function startRumAssembly(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  reportError: (error: RawError) => void,\n  eventRateLimit?: number\n) {\n  modifiableFieldPathsByEvent = {\n    [RumEventType.VIEW]: {\n      'view.performance.lcp.resource_url': 'string',\n      ...USER_CUSTOMIZABLE_FIELD_PATHS,\n      ...VIEW_MODIFIABLE_FIELD_PATHS,\n      ...ROOT_MODIFIABLE_FIELD_PATHS,\n    },\n    [RumEventType.ERROR]: {\n      'error.message': 'string',\n      'error.stack': 'string',\n      'error.handling_stack': 'string',\n      'error.resource.url': 'string',\n      'error.fingerprint': 'string',\n      ...USER_CUSTOMIZABLE_FIELD_PATHS,\n      ...VIEW_MODIFIABLE_FIELD_PATHS,\n      ...ROOT_MODIFIABLE_FIELD_PATHS,\n    },\n    [RumEventType.RESOURCE]: {\n      'resource.url': 'string',\n      'resource.graphql.variables': 'string',\n      'resource.request.headers': 'object',\n      'resource.response.headers': 'object',\n      ...USER_CUSTOMIZABLE_FIELD_PATHS,\n      ...VIEW_MODIFIABLE_FIELD_PATHS,\n      ...ROOT_MODIFIABLE_FIELD_PATHS,\n    },\n    [RumEventType.ACTION]: {\n      'action.target.name': 'string',\n      ...USER_CUSTOMIZABLE_FIELD_PATHS,\n      ...VIEW_MODIFIABLE_FIELD_PATHS,\n      ...ROOT_MODIFIABLE_FIELD_PATHS,\n    },\n    [RumEventType.LONG_TASK]: {\n      'long_task.scripts[].source_url': 'string',\n      'long_task.scripts[].invoker': 'string',\n      ...USER_CUSTOMIZABLE_FIELD_PATHS,\n      ...VIEW_MODIFIABLE_FIELD_PATHS,\n      ...ROOT_MODIFIABLE_FIELD_PATHS,\n    },\n    [RumEventType.VITAL]: {\n      ...USER_CUSTOMIZABLE_FIELD_PATHS,\n      ...VIEW_MODIFIABLE_FIELD_PATHS,\n      ...ROOT_MODIFIABLE_FIELD_PATHS,\n    },\n  }\n  const eventRateLimiters = {\n    [RumEventType.ERROR]: createEventRateLimiter(RumEventType.ERROR, reportError, eventRateLimit),\n    [RumEventType.ACTION]: createEventRateLimiter(RumEventType.ACTION, reportError, eventRateLimit),\n    [RumEventType.VITAL]: createEventRateLimiter(RumEventType.VITAL, reportError, eventRateLimit),\n  }\n\n  lifeCycle.subscribe(\n    LifeCycleEventType.RAW_RUM_EVENT_COLLECTED,\n    ({ startClocks, duration, rawRumEvent, domainContext }) => {\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: rawRumEvent.type,\n        rawRumEvent,\n        domainContext,\n        startTime: startClocks.relative,\n        duration,\n      } as AssembleHookParams)!\n\n      if (defaultRumEventAttributes === DISCARDED) {\n        return\n      }\n\n      const serverRumEvent = combine(defaultRumEventAttributes, rawRumEvent, {\n        ddtags: buildTags(configuration).join(','),\n      }) as AssembledRumEvent\n\n      if (shouldSend(serverRumEvent, configuration.beforeSend, domainContext, eventRateLimiters)) {\n        if (isEmptyObject(serverRumEvent.context!)) {\n          delete serverRumEvent.context\n        }\n        lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent)\n      }\n    }\n  )\n}\n\nfunction shouldSend(\n  event: AssembledRumEvent,\n  beforeSend: RumConfiguration['beforeSend'],\n  domainContext: RumEventDomainContext,\n  eventRateLimiters: { [key in RumEventType]?: EventRateLimiter }\n) {\n  if (beforeSend) {\n    const result = limitModification(event, modifiableFieldPathsByEvent[event.type], (event) =>\n      beforeSend(event, domainContext)\n    )\n    if (result === false && event.type !== RumEventType.VIEW) {\n      return false\n    }\n    if (result === false) {\n      display.warn(\"Can't dismiss view events using beforeSend!\")\n    }\n  }\n\n  const rateLimitReached = eventRateLimiters[event.type]?.isLimitReached()\n\n  return !rateLimitReached\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/configuration.spec.ts",
    "content": "import type { InitConfiguration } from '@datadog/browser-core'\nimport { DefaultPrivacyLevel, display, TraceContextInjection } from '@datadog/browser-core'\nimport type {\n  ExtractTelemetryConfiguration,\n  CamelToSnakeCase,\n  MapInitConfigurationKey,\n} from '@datadog/browser-core/test'\nimport { EXHAUSTIVE_INIT_CONFIGURATION, SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION } from '@datadog/browser-core/test'\nimport type { RumInitConfiguration } from './configuration'\nimport {\n  DEFAULT_PROPAGATOR_TYPES,\n  DEFAULT_TRACKED_RESOURCE_HEADERS,\n  serializeRumConfiguration,\n  validateAndBuildRumConfiguration,\n} from './configuration'\n\nconst DEFAULT_INIT_CONFIGURATION = { clientToken: 'xxx', applicationId: 'xxx' }\n\ndescribe('validateAndBuildRumConfiguration', () => {\n  let displayErrorSpy: jasmine.Spy<typeof display.error>\n  let displayWarnSpy: jasmine.Spy<typeof display.warn>\n\n  beforeEach(() => {\n    displayErrorSpy = spyOn(display, 'error')\n    displayWarnSpy = spyOn(display, 'warn')\n  })\n\n  describe('applicationId', () => {\n    it('does not validate the configuration if it is missing', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, applicationId: undefined as any })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith(\n        'Application ID is not configured, no RUM data will be collected.'\n      )\n    })\n  })\n\n  describe('sessionReplaySampleRate', () => {\n    it('defaults to 0 if the option is not provided', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.sessionReplaySampleRate).toBe(0)\n    })\n\n    it('is set to `sessionReplaySampleRate` provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, sessionReplaySampleRate: 50 })!\n          .sessionReplaySampleRate\n      ).toBe(50)\n    })\n\n    it('does not validate the configuration if an incorrect value is provided', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, sessionReplaySampleRate: 'foo' as any })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith(\n        'Session Replay Sample Rate should be a number between 0 and 100'\n      )\n\n      displayErrorSpy.calls.reset()\n\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, sessionReplaySampleRate: 200 })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith(\n        'Session Replay Sample Rate should be a number between 0 and 100'\n      )\n    })\n  })\n\n  describe('traceSampleRate', () => {\n    it('defaults to 100 if the option is not provided', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.traceSampleRate).toBe(100)\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, traceSampleRate: 50 })!.traceSampleRate\n      ).toBe(50)\n    })\n\n    it('does not validate the configuration if an incorrect value is provided', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, traceSampleRate: 'foo' as any })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith('Trace Sample Rate should be a number between 0 and 100')\n\n      displayErrorSpy.calls.reset()\n      expect(validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, traceSampleRate: 200 })).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith('Trace Sample Rate should be a number between 0 and 100')\n    })\n  })\n\n  describe('rulePsr', () => {\n    it('is set to one hundredth of the traceSampleRate if defined', () => {\n      expect(validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, traceSampleRate: 50 })!.rulePsr).toBe(\n        0.5\n      )\n    })\n\n    it('is undefined is no traceSampleRate is defined', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.rulePsr).toBeUndefined()\n    })\n  })\n\n  describe('traceContextInjection', () => {\n    it('defaults to sampled if no options provided', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.traceContextInjection).toBe(\n        TraceContextInjection.SAMPLED\n      )\n    })\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, traceContextInjection: 'all' })!\n          .traceContextInjection\n      ).toBe(TraceContextInjection.ALL)\n    })\n    it('ignores incorrect value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, traceContextInjection: 'foo' as any })!\n          .traceContextInjection\n      ).toBe(TraceContextInjection.SAMPLED)\n    })\n  })\n\n  describe('allowedTracingUrls', () => {\n    it('defaults to an empty array', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.allowedTracingUrls).toEqual([])\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: ['foo'],\n          service: 'bar',\n        })!.allowedTracingUrls\n      ).toEqual([{ match: 'foo', propagatorTypes: DEFAULT_PROPAGATOR_TYPES }])\n    })\n\n    it('accepts functions', () => {\n      const customOriginFunction = (url: string): boolean => url === 'https://my.origin.com'\n\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [customOriginFunction],\n          service: 'bar',\n        })!.allowedTracingUrls\n      ).toEqual([{ match: customOriginFunction, propagatorTypes: DEFAULT_PROPAGATOR_TYPES }])\n    })\n\n    it('accepts RegExp', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [/az/i],\n          service: 'bar',\n        })!.allowedTracingUrls\n      ).toEqual([{ match: /az/i, propagatorTypes: DEFAULT_PROPAGATOR_TYPES }])\n    })\n\n    it('keeps headers', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [{ match: 'simple', propagatorTypes: ['b3multi', 'tracecontext'] }],\n          service: 'bar',\n        })!.allowedTracingUrls\n      ).toEqual([{ match: 'simple', propagatorTypes: ['b3multi', 'tracecontext'] }])\n    })\n\n    it('fallbacks to default propagators', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [{ match: 'simple' }],\n          service: 'bar',\n        })!.allowedTracingUrls\n      ).toEqual([{ match: 'simple', propagatorTypes: DEFAULT_PROPAGATOR_TYPES }])\n\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [{ match: 'simple', propagatorTypes: null }],\n          service: 'bar',\n        })!.allowedTracingUrls\n      ).toEqual([{ match: 'simple', propagatorTypes: DEFAULT_PROPAGATOR_TYPES }])\n    })\n\n    it('should filter out unexpected parameter types', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          service: 'bar',\n          allowedTracingUrls: [\n            42 as any,\n            undefined,\n            { match: 42, propagatorTypes: ['datadog'] },\n            { match: 'toto', propagatorTypes: 42 },\n          ],\n        })!.allowedTracingUrls\n      ).toEqual([])\n\n      expect(displayWarnSpy).toHaveBeenCalledTimes(4)\n    })\n\n    it('does not validate the configuration if a value is provided and service is undefined', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, allowedTracingUrls: ['foo'] })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith('Service needs to be configured when tracing is enabled')\n    })\n\n    it('does not validate the configuration if an incorrect value is provided', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, allowedTracingUrls: 'foo' as any })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith('Allowed Tracing URLs should be an array')\n    })\n  })\n\n  describe('excludedActivityUrls', () => {\n    it('defaults to an empty array', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.excludedActivityUrls).toEqual([])\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          excludedActivityUrls: ['foo'],\n          service: 'bar',\n        })!.excludedActivityUrls\n      ).toEqual(['foo'])\n    })\n\n    it('accepts functions', () => {\n      const customUrlFunction = (url: string): boolean => url === 'foo'\n\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          excludedActivityUrls: [customUrlFunction],\n          service: 'bar',\n        })!.excludedActivityUrls\n      ).toEqual([customUrlFunction])\n    })\n\n    it('does not validate the configuration if an incorrect value is provided', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, excludedActivityUrls: 'foo' as any })\n      ).toBeUndefined()\n      expect(displayErrorSpy).toHaveBeenCalledOnceWith('Excluded Activity Urls should be an array')\n    })\n  })\n\n  describe('trackUserInteractions', () => {\n    it('defaults to true', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.trackUserInteractions).toBeTrue()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackUserInteractions: true })!\n          .trackUserInteractions\n      ).toBeTrue()\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackUserInteractions: false })!\n          .trackUserInteractions\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackUserInteractions: 'foo' as any })!\n          .trackUserInteractions\n      ).toBeTrue()\n    })\n  })\n\n  describe('trackViewsManually', () => {\n    it('defaults to false', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.trackViewsManually).toBeFalse()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackViewsManually: true })!\n          .trackViewsManually\n      ).toBeTrue()\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackViewsManually: false })!\n          .trackViewsManually\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackViewsManually: 'foo' as any })!\n          .trackViewsManually\n      ).toBeTrue()\n    })\n  })\n\n  describe('startSessionReplayRecordingManually', () => {\n    it('defaults to true if sessionReplaySampleRate is 0', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, sessionReplaySampleRate: 0 })!\n          .startSessionReplayRecordingManually\n      ).toBeTrue()\n    })\n\n    it('defaults to false if sessionReplaySampleRate is not 0', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, sessionReplaySampleRate: 50 })!\n          .startSessionReplayRecordingManually\n      ).toBeFalse()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, startSessionReplayRecordingManually: true })!\n          .startSessionReplayRecordingManually\n      ).toBeTrue()\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, startSessionReplayRecordingManually: false })!\n          .startSessionReplayRecordingManually\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          startSessionReplayRecordingManually: 'foo' as any,\n        })!.startSessionReplayRecordingManually\n      ).toBeTrue()\n    })\n  })\n\n  describe('actionNameAttribute', () => {\n    it('defaults to undefined', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.actionNameAttribute).toBeUndefined()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, actionNameAttribute: 'foo' })!\n          .actionNameAttribute\n      ).toBe('foo')\n    })\n  })\n\n  describe('defaultPrivacyLevel', () => {\n    it('defaults to MASK', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.defaultPrivacyLevel).toBe(\n        DefaultPrivacyLevel.MASK\n      )\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          defaultPrivacyLevel: DefaultPrivacyLevel.MASK,\n        })!.defaultPrivacyLevel\n      ).toBe(DefaultPrivacyLevel.MASK)\n    })\n\n    it('ignores incorrect values', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, defaultPrivacyLevel: 'foo' as any })!\n          .defaultPrivacyLevel\n      ).toBe(DefaultPrivacyLevel.MASK)\n    })\n  })\n\n  describe('enablePrivacyForActionName', () => {\n    it('defaults to false', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.enablePrivacyForActionName).toBeFalse()\n    })\n\n    it('is true when the option is true', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.enablePrivacyForActionName).toBeFalse()\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, enablePrivacyForActionName: true })!\n          .enablePrivacyForActionName\n      ).toBeTrue()\n    })\n  })\n\n  describe('trackResources', () => {\n    it('defaults to true', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.trackResources).toBeTrue()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackResources: true })!.trackResources\n      ).toBeTrue()\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackResources: false })!.trackResources\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackResources: 'foo' as any })!\n          .trackResources\n      ).toBeTrue()\n    })\n  })\n\n  describe('trackResourceHeaders', () => {\n    describe('disabled', () => {\n      it('defaults to empty array', () => {\n        expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.trackResourceHeaders).toEqual([])\n      })\n\n      it('returns empty array when set to false', () => {\n        expect(\n          validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackResourceHeaders: false })!\n            .trackResourceHeaders\n        ).toEqual([])\n      })\n    })\n\n    describe('enabled with regular usage', () => {\n      it('returns default headers as MatchHeader[] when set to true', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: true,\n        })!.trackResourceHeaders\n\n        expect(result).toEqual(DEFAULT_TRACKED_RESOURCE_HEADERS.map((name) => ({ name })))\n      })\n\n      it('accepts a MatchHeader with only name', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'x-custom' }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([{ name: 'x-custom' }])\n      })\n\n      it('lowercases string name', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'X-Custom-Header' }],\n        })!.trackResourceHeaders\n\n        expect(result[0].name).toBe('x-custom-header')\n      })\n\n      it('accepts RegExp and function name matchers', () => {\n        const regexpMatcher = /x-custom-.*/i\n        const fnMatcher = (header: string) => header.startsWith('x-')\n\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: regexpMatcher }, { name: fnMatcher }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([{ name: regexpMatcher }, { name: fnMatcher }])\n      })\n\n      it('preserves url', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ url: /api/, name: 'x-id' }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([{ url: /api/, name: 'x-id' }])\n      })\n\n      it('preserves location', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'x-id', location: 'response' }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([{ name: 'x-id', location: 'response' }])\n      })\n\n      it('preserves extractor', () => {\n        const extractor = /max-age=(\\d+)/\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'cache-control', extractor }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([{ name: 'cache-control', extractor }])\n      })\n    })\n\n    describe('enabled with incorrect usage', () => {\n      it('warns and returns empty array for invalid value', () => {\n        expect(\n          validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackResourceHeaders: 42 as any })!\n            .trackResourceHeaders\n        ).toEqual([])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n          'trackResourceHeaders should be true or an array of MatchHeader'\n        )\n      })\n\n      it('warns and returns empty array when set to an empty array', () => {\n        expect(\n          validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackResourceHeaders: [] })!\n            .trackResourceHeaders\n        ).toEqual([])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n          'trackResourceHeaders is an empty array, no headers will be captured'\n        )\n      })\n\n      it('keeps valid items and skips invalid ones', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'x-valid' }, 42 as any, { name: 'x-also-valid' }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([{ name: 'x-valid' }, { name: 'x-also-valid' }])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n          \"trackResourceHeaders[1] should be a MatchHeader object with a 'name' property\"\n        )\n      })\n\n      it('warns and skips item without name', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ url: 'https://example.com' } as any],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n          \"trackResourceHeaders[0] should be a MatchHeader object with a 'name' property\"\n        )\n      })\n\n      it('warns and skips item with invalid url', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'x-foo', url: 42 as any }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith('trackResourceHeaders[0].url should be a MatchOption')\n      })\n\n      it('warns and skips item with invalid location', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'x-foo', location: 'invalid' as any }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n          \"trackResourceHeaders[0].location should be 'request', 'response', or 'any'\"\n        )\n      })\n\n      it('warns and skips item with invalid extractor', () => {\n        const result = validateAndBuildRumConfiguration({\n          ...DEFAULT_INIT_CONFIGURATION,\n          trackResourceHeaders: [{ name: 'x-foo', extractor: 'bad' as any }],\n        })!.trackResourceHeaders\n\n        expect(result).toEqual([])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith('trackResourceHeaders[0].extractor should be a RegExp')\n      })\n    })\n  })\n\n  describe('trackLongTasks', () => {\n    it('defaults to false', () => {\n      expect(validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!.trackLongTasks).toBeTrue()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackLongTasks: true })!.trackLongTasks\n      ).toBeTrue()\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackLongTasks: false })!.trackLongTasks\n      ).toBeFalse()\n    })\n\n    it('the provided value is cast to boolean', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, trackLongTasks: 'foo' as any })!\n          .trackLongTasks\n      ).toBeTrue()\n    })\n  })\n\n  describe('serializeRumConfiguration', () => {\n    describe('selected tracing propagators serialization', () => {\n      it('should not return any propagator type', () => {\n        expect(serializeRumConfiguration(DEFAULT_INIT_CONFIGURATION).selected_tracing_propagators).toEqual([])\n      })\n\n      it('should return the default propagator types', () => {\n        const simpleTracingConfig: RumInitConfiguration = {\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: ['foo'],\n        }\n        expect(serializeRumConfiguration(simpleTracingConfig).selected_tracing_propagators).toEqual(\n          DEFAULT_PROPAGATOR_TYPES\n        )\n      })\n\n      it('should return all propagator types', () => {\n        const complexTracingConfig: RumInitConfiguration = {\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [\n            'foo',\n            { match: 'first', propagatorTypes: ['datadog'] },\n            { match: 'test', propagatorTypes: ['tracecontext'] },\n            { match: 'other', propagatorTypes: ['b3'] },\n            { match: 'final', propagatorTypes: ['b3multi'] },\n          ],\n        }\n        expect(serializeRumConfiguration(complexTracingConfig).selected_tracing_propagators).toEqual(\n          jasmine.arrayWithExactContents(['datadog', 'b3', 'b3multi', 'tracecontext'])\n        )\n      })\n\n      it('should survive a configuration with wrong parameters', () => {\n        const wrongTracingConfig: RumInitConfiguration = {\n          ...DEFAULT_INIT_CONFIGURATION,\n          allowedTracingUrls: [42 as any, { match: 'test', propagatorTypes: 42 }, undefined, null, {}],\n        }\n        expect(serializeRumConfiguration(wrongTracingConfig).selected_tracing_propagators).toEqual([])\n      })\n    })\n  })\n\n  describe('workerUrl', () => {\n    it('defaults to undefined', () => {\n      const configuration = validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!\n      expect(configuration.workerUrl).toBeUndefined()\n    })\n\n    it('is set to provided value', () => {\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, workerUrl: '/worker.js' })!.workerUrl\n      ).toBe('/worker.js')\n      expect(\n        validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, workerUrl: 'https://example.org/worker.js' })!\n          .workerUrl\n      ).toBe('https://example.org/worker.js')\n    })\n  })\n\n  describe('version parameter validation', () => {\n    it('should not reject null', () => {\n      const configuration = validateAndBuildRumConfiguration({ ...DEFAULT_INIT_CONFIGURATION, version: null })\n      expect(displayErrorSpy).not.toHaveBeenCalled()\n      expect(configuration!.version).toBeUndefined()\n    })\n  })\n\n  describe('plugins', () => {\n    it('should be set in the configuration', () => {\n      const plugin = {\n        name: 'foo',\n      }\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        plugins: [plugin],\n      })\n      expect(configuration!.plugins).toEqual([plugin])\n    })\n  })\n  describe('trackFeatureFlagsForEvents', () => {\n    it('defaults to an empty set', () => {\n      const configuration = validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!\n      expect(configuration.trackFeatureFlagsForEvents).toEqual([])\n    })\n\n    it('should accept valid input', () => {\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        trackFeatureFlagsForEvents: ['resource', 'long_task', 'vital'],\n      })!\n      expect(configuration.trackFeatureFlagsForEvents).toEqual(['resource', 'long_task', 'vital'])\n      expect(displayWarnSpy).not.toHaveBeenCalled()\n    })\n    it('does not validate the configuration if an incorrect value is provided', () => {\n      validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        trackFeatureFlagsForEvents: 123 as any,\n      })!\n      expect(displayWarnSpy).toHaveBeenCalledOnceWith('trackFeatureFlagsForEvents should be an array')\n    })\n  })\n\n  describe('allowedGraphQlUrls', () => {\n    it('defaults to an empty array', () => {\n      const configuration = validateAndBuildRumConfiguration(DEFAULT_INIT_CONFIGURATION)!\n      expect(configuration.allowedGraphQlUrls).toEqual([])\n    })\n\n    it('should accept string URLs', () => {\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        allowedGraphQlUrls: ['https://api.example.com/graphql', '/graphql'],\n      })!\n      expect(configuration.allowedGraphQlUrls).toEqual([\n        { match: 'https://api.example.com/graphql', trackPayload: false, trackResponseErrors: false },\n        { match: '/graphql', trackPayload: false, trackResponseErrors: false },\n      ])\n    })\n\n    it('should accept MatchOption objects', () => {\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        allowedGraphQlUrls: [{ match: /\\/graphql$/i }, { match: 'https://api.example.com/graphql' }],\n      })!\n      expect(configuration.allowedGraphQlUrls).toEqual([\n        { match: /\\/graphql$/i, trackPayload: false, trackResponseErrors: false },\n        { match: 'https://api.example.com/graphql', trackPayload: false, trackResponseErrors: false },\n      ])\n    })\n\n    it('should accept function matchers', () => {\n      const customMatcher = (url: string) => url.includes('graphql')\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        allowedGraphQlUrls: [{ match: customMatcher }],\n      })!\n      expect(configuration.allowedGraphQlUrls).toEqual([\n        { match: customMatcher, trackPayload: false, trackResponseErrors: false },\n      ])\n    })\n\n    it('should accept GraphQL options with trackPayload', () => {\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        allowedGraphQlUrls: [{ match: '/graphql', trackPayload: true }],\n      })!\n      expect(configuration.allowedGraphQlUrls).toEqual([\n        { match: '/graphql', trackPayload: true, trackResponseErrors: false },\n      ])\n    })\n\n    it('should accept GraphQL options with trackResponseErrors', () => {\n      const configuration = validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        allowedGraphQlUrls: [{ match: '/graphql', trackResponseErrors: true }],\n      })!\n      expect(configuration.allowedGraphQlUrls).toEqual([\n        { match: '/graphql', trackPayload: false, trackResponseErrors: true },\n      ])\n    })\n\n    it('should reject invalid values', () => {\n      validateAndBuildRumConfiguration({\n        ...DEFAULT_INIT_CONFIGURATION,\n        allowedGraphQlUrls: 'not-an-array' as any,\n      })\n      expect(displayWarnSpy).toHaveBeenCalledOnceWith('allowedGraphQlUrls should be an array')\n    })\n  })\n})\n\ndescribe('serializeRumConfiguration', () => {\n  it('should serialize the configuration', () => {\n    const exhaustiveRumInitConfiguration: Required<RumInitConfiguration> = {\n      ...EXHAUSTIVE_INIT_CONFIGURATION,\n      applicationId: 'applicationId',\n      beforeSend: () => true,\n      excludedActivityUrls: ['toto.com'],\n      workerUrl: './worker.js',\n      compressIntakeRequests: true,\n      allowedTracingUrls: ['foo'],\n      allowedGraphQlUrls: ['bar'],\n      traceSampleRate: 50,\n      traceContextInjection: TraceContextInjection.ALL,\n      defaultPrivacyLevel: 'allow',\n      enablePrivacyForActionName: false,\n      subdomain: 'foo',\n      sessionReplaySampleRate: 60,\n      startSessionReplayRecordingManually: true,\n      trackUserInteractions: true,\n      actionNameAttribute: 'test-id',\n      trackViewsManually: true,\n      trackResources: true,\n      trackLongTasks: true,\n      trackBfcacheViews: true,\n      trackEarlyRequests: true,\n      remoteConfigurationId: '123',\n      remoteConfigurationProxy: 'config',\n      plugins: [{ name: 'foo', getConfigurationTelemetry: () => ({ bar: true }) }],\n      trackFeatureFlagsForEvents: ['vital'],\n      profilingSampleRate: 42,\n      propagateTraceBaggage: true,\n      betaTrackActionsInShadowDom: true,\n      trackResourceHeaders: true,\n    }\n\n    type MapRumInitConfigurationKey<Key extends string> = Key extends keyof InitConfiguration\n      ? MapInitConfigurationKey<Key>\n      : Key extends\n            | 'workerUrl'\n            | 'allowedTracingUrls'\n            | 'excludedActivityUrls'\n            | 'remoteConfigurationProxy'\n            | 'allowedGraphQlUrls'\n        ? `use_${CamelToSnakeCase<Key>}`\n        : Key extends 'trackLongTasks'\n          ? 'track_long_task' // We forgot the s, keeping this for backward compatibility\n          : // The following options are not reported as telemetry. Please avoid adding more of them.\n            // TODO: Add betaTrackActionsInShadowDom and trackResourceHeaders to rum-events-format telemetry schema and remove from this exclusion\n            Key extends 'applicationId' | 'subdomain' | 'betaTrackActionsInShadowDom' | 'trackResourceHeaders'\n            ? never\n            : CamelToSnakeCase<Key>\n    // By specifying the type here, we can ensure that serializeConfiguration is returning an\n    // object containing all expected properties.\n    const serializedConfiguration: ExtractTelemetryConfiguration<\n      | MapRumInitConfigurationKey<keyof RumInitConfiguration>\n      | 'selected_tracing_propagators'\n      | 'use_track_graph_ql_payload'\n      | 'use_track_graph_ql_response_errors'\n    > = serializeRumConfiguration(exhaustiveRumInitConfiguration)\n\n    expect(serializedConfiguration).toEqual({\n      ...SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION,\n      session_replay_sample_rate: 60,\n      trace_sample_rate: 50,\n      trace_context_injection: TraceContextInjection.ALL,\n      propagate_trace_baggage: true,\n      use_allowed_tracing_urls: true,\n      use_allowed_graph_ql_urls: true,\n      use_track_graph_ql_payload: false,\n      use_track_graph_ql_response_errors: false,\n      selected_tracing_propagators: ['tracecontext', 'datadog'],\n      use_excluded_activity_urls: true,\n      track_user_interactions: true,\n      track_views_manually: true,\n      start_session_replay_recording_manually: true,\n      action_name_attribute: 'test-id',\n      default_privacy_level: 'allow',\n      enable_privacy_for_action_name: false,\n      track_resources: true,\n      track_long_task: true,\n      track_bfcache_views: true,\n      track_early_requests: true,\n      use_worker_url: true,\n      compress_intake_requests: true,\n      plugins: [{ name: 'foo', bar: true }],\n      track_feature_flags_for_events: ['vital'],\n      remote_configuration_id: '123',\n      use_remote_configuration_proxy: true,\n      profiling_sample_rate: 42,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/configuration.ts",
    "content": "import type { Configuration, InitConfiguration, MatchOption, RawTelemetryConfiguration } from '@datadog/browser-core'\nimport {\n  isMatchOption,\n  serializeConfiguration,\n  DefaultPrivacyLevel,\n  TraceContextInjection,\n  display,\n  objectHasValue,\n  validateAndBuildConfiguration,\n  isSampleRate,\n  isNumber,\n  isNonEmptyArray,\n  isIndexableObject,\n} from '@datadog/browser-core'\nimport type { RumEventDomainContext } from '../../domainContext.types'\nimport type { RumEvent } from '../../rumEvent.types'\nimport type { RumPlugin } from '../plugins'\nimport type { PropagatorType, TracingOption } from '../tracing/tracer.types'\n\nexport const DEFAULT_PROPAGATOR_TYPES: PropagatorType[] = ['tracecontext', 'datadog']\n\nexport const DEFAULT_TRACKED_RESOURCE_HEADERS = [\n  'cache-control',\n  'etag',\n  'age',\n  'expires',\n  'content-type',\n  'content-encoding',\n  'vary',\n  'content-length',\n  'server-timing',\n  'x-cache',\n] as const\n\n/**\n * Init Configuration for the RUM browser SDK.\n *\n * @category Main\n * @example NPM\n * ```ts\n * import { datadogRum } from '@datadog/browser-rum'\n *\n * datadogRum.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   site: '<DATADOG_SITE>',\n *   // ...\n * })\n * ```\n * @example CDN\n * ```ts\n * DD_RUM.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   site: '<DATADOG_SITE>',\n *   ...\n * })\n * ```\n */\nexport interface RumInitConfiguration extends InitConfiguration {\n  // global options\n  /**\n   * The RUM application ID.\n   *\n   * @category Authentication\n   */\n  applicationId: string\n\n  /**\n   * Whether to propagate user and account IDs in the baggage header of trace requests.\n   *\n   * @category Tracing\n   * @defaultValue false\n   */\n  propagateTraceBaggage?: boolean | undefined\n\n  /**\n   * Access to every event collected by the RUM SDK before they are sent to Datadog.\n   * It allows:\n   * - Enrich your RUM events with additional context attributes\n   * - Modify your RUM events to modify their content, or redact sensitive sequences (see the list of editable properties)\n   * - Discard selected RUM events\n   *\n   * See [Enrich And Control Browser RUM Data With beforeSend](https://docs.datadoghq.com/real_user_monitoring/guide/enrich-and-control-rum-data) for further information.\n   *\n   * @category Data Collection\n   */\n  beforeSend?: RumBeforeSend | undefined\n\n  /**\n   * A list of request origins ignored when computing the page activity.\n   * See [How page activity is calculated](https://docs.datadoghq.com/real_user_monitoring/browser/monitoring_page_performance/#how-page-activity-is-calculated) for further information.\n   */\n  excludedActivityUrls?: MatchOption[] | undefined\n\n  /**\n   * URL pointing to the Datadog Browser SDK Worker JavaScript file. The URL can be relative or absolute, but is required to have the same origin as the web application.\n   * See [Content Security Policy guidelines](https://docs.datadoghq.com/integrations/content_security_policy_logs/?tab=firefox#use-csp-with-real-user-monitoring-and-session-replay) for further information.\n   *\n   * @category Transport\n   */\n  workerUrl?: string\n\n  /**\n   * Compress requests sent to the Datadog intake to reduce bandwidth usage when sending large amounts of data. The compression is done in a Worker thread.\n   * See [Content Security Policy guidelines](https://docs.datadoghq.com/integrations/content_security_policy_logs/?tab=firefox#use-csp-with-real-user-monitoring-and-session-replay) for further information.\n   *\n   * @category Transport\n   */\n  compressIntakeRequests?: boolean | undefined\n\n  /**\n   * [Internal option] Id of the remote configuration\n   *\n   * @internal\n   */\n  remoteConfigurationId?: string | undefined\n\n  /**\n   * [Internal option] set a proxy URL for the remote configuration\n   *\n   * @internal\n   */\n  remoteConfigurationProxy?: string | undefined\n\n  // tracing options\n  /**\n   * A list of request URLs used to inject tracing headers.\n   * See [Connect RUM and Traces](https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum) for further information.\n   *\n   * @category Tracing\n   */\n  allowedTracingUrls?:\n    | Array<MatchOption | { match: MatchOption; propagatorTypes?: PropagatorType[] | null | undefined }>\n    | undefined\n\n  /**\n   * The percentage of requests to trace: 100 for all, 0 for none.\n   * See [Connect RUM and Traces](https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum) for further information.\n   *\n   * @category Tracing\n   * @defaultValue 100\n   */\n  traceSampleRate?: number | undefined\n  /**\n   * If you set a `traceSampleRate`, to ensure backend services' sampling decisions are still applied, configure the `traceContextInjection` initialization parameter to sampled.\n   *\n   * See [Connect RUM and Traces](https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum) for further information.\n   *\n   * @category Tracing\n   * @defaultValue sampled\n   */\n  traceContextInjection?: TraceContextInjection | undefined\n\n  // replay options\n  /**\n   * Allow to protect end user privacy and prevent sensitive organizational information from being collected.\n   *\n   * See [Replay Privacy Options](https://docs.datadoghq.com/real_user_monitoring/session_replay/browser/privacy_options) for further information.\n   *\n   * @category Privacy\n   * @defaultValue mask\n   */\n  defaultPrivacyLevel?: DefaultPrivacyLevel | undefined\n\n  /**\n   * If you are accessing Datadog through a custom subdomain, you can set `subdomain` to include your custom domain in the `getSessionReplayLink()` returned URL .\n   *\n   * See [Connect Session Replay To Your Third-Party Tools](https://docs.datadoghq.com/real_user_monitoring/guide/connect-session-replay-to-your-third-party-tools) for further information.\n   *\n   */\n  subdomain?: string\n\n  /**\n   * The percentage of tracked sessions with [Browser RUM & Session Replay pricing](https://www.datadoghq.com/pricing/?product=real-user-monitoring--session-replay#real-user-monitoring--session-replay) features: 100 for all, 0 for none.\n   *\n   * See [Configure Your Setup For Browser RUM and Browser RUM & Session Replay Sampling](https://docs.datadoghq.com/real_user_monitoring/guide/sampling-browser-plans) for further information.\n   *\n   * @category Session Replay\n   * @defaultValue 0\n   */\n  sessionReplaySampleRate?: number | undefined\n\n  /**\n   * If the session is sampled for Session Replay, only start the recording when `startSessionReplayRecording()` is called, instead of at the beginning of the session. Default: if startSessionReplayRecording is 0, true; otherwise, false.\n   *\n   * See [Session Replay Usage](https://docs.datadoghq.com/real_user_monitoring/session_replay/browser/#usage) for further information.\n   *\n   * @category Session Replay\n   */\n  startSessionReplayRecordingManually?: boolean | undefined\n\n  /**\n   * Enables privacy control for action names.\n   *\n   * @category Privacy\n   */\n  enablePrivacyForActionName?: boolean | undefined // TODO next major: remove this option and make privacy for action name the default behavior\n\n  /**\n   * Enables automatic collection of users actions.\n   *\n   * See [Tracking User Actions](https://docs.datadoghq.com/real_user_monitoring/browser/tracking_user_actions) for further information.\n   *\n   * @category Data Collection\n   * @defaultValue true\n   */\n  trackUserInteractions?: boolean | undefined\n\n  /**\n   * Specify your own attribute to use to name actions.\n   *\n   * See [Declare a name for click actions](https://docs.datadoghq.com/real_user_monitoring/browser/tracking_user_actions/#declare-a-name-for-click-actions) for further information.\n   *\n   * @category Data Collection\n   */\n  actionNameAttribute?: string | undefined\n\n  /**\n   * Enables accurate action names for clicks inside Shadow DOM elements.\n   * ⚠️ This is a beta feature and will be updated in the future with selector tracking.\n   *\n   * @category Beta\n   * @defaultValue false\n   */\n  betaTrackActionsInShadowDom?: boolean | undefined\n\n  // view options\n  /**\n   * Allows you to control RUM views creation. See [Override default RUM view names](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/?tab=npm#override-default-rum-view-names) for further information.\n   *\n   * @category Data Collection\n   */\n  trackViewsManually?: boolean | undefined\n\n  /**\n   * Enable the creation of dedicated views for pages restored from the Back-Forward cache.\n   *\n   * @category Data Collection\n   * @defaultValue false\n   */\n  trackBfcacheViews?: boolean | undefined\n\n  /**\n   * Enables collection of resource events.\n   *\n   * @category Data Collection\n   * @defaultValue true\n   */\n  trackResources?: boolean | undefined\n\n  /**\n   * Enables collection of request and response headers on resource events.\n   *\n   * - `true`: collect {@link DEFAULT_TRACKED_RESOURCE_HEADERS} for all URLs, both directions\n   * - `MatchHeader[]`: each {@link MatchHeader} targets a header name, with optional URL scope\n   * (`url`), value extraction (`extractor`), and `location`. By default, both request and\n   * response headers are captured; set `location` to `'request'` or `'response'` to restrict\n   * to one.\n   *\n   * Headers whose names match a built-in sensitive-data pattern are always dropped, regardless\n   * of the configured matchers. The pattern blocks headers whose names contain: `token`, `cookie`,\n   * `secret`, `authorization`, `api-key`, `secret-key`, `access-key`, `app-key`, `client-ip`,\n   * `connecting-ip`, `real-ip`, or `forwarded`.\n   *\n   * @category Data Collection\n   * @defaultValue false (disabled)\n   * @example\n   * // Collect default headers plus custom ones for all URLs\n   * trackResourceHeaders: [\n   *   { name: (h) => DEFAULT_TRACKED_RESOURCE_HEADERS.includes(h) },\n   *   { name: 'x-request-id' },\n   * ]\n   * @example\n   * // URL-scoped rule: capture specific response headers only for calls to /api\n   * trackResourceHeaders: [{ url: /\\/api\\//, name: 'cache-control', location: 'response' }]\n   * @example\n   * // Extract a partial value from a header\n   * trackResourceHeaders: [{ url: /\\/api\\//, name: 'server-timing', extractor: /dur=(\\d+)/, location: 'response' }]\n   * @hidden\n   */\n  trackResourceHeaders?: boolean | MatchHeader[] | undefined\n\n  /**\n   * Enables collection of long task events.\n   *\n   * @category Data Collection\n   * @defaultValue true\n   */\n  trackLongTasks?: boolean | undefined\n\n  /**\n   * Enables early request collection before resource timing entries are available.\n   *\n   * @category Data Collection\n   * @defaultValue false\n   */\n  trackEarlyRequests?: boolean | undefined\n\n  /**\n   * List of plugins to enable. The plugins API is unstable and experimental, and may change without\n   * notice. Please use only plugins provided by Datadog matching the version of the SDK you are\n   * using.\n   */\n  plugins?: RumPlugin[] | undefined\n\n  /**\n   * Enables collection of features flags in additional events (e.g. long task, resource, action, vital).\n   *\n   * @category Data Collection\n   */\n  trackFeatureFlagsForEvents?: FeatureFlagsForEvents[]\n\n  /**\n   * The percentage of users profiled. A value between 0 and 100.\n   *\n   * @category Profiling\n   * @defaultValue 0\n   */\n  profilingSampleRate?: number | undefined\n\n  /**\n   * A list of GraphQL endpoint URLs to track and enrich with GraphQL-specific metadata.\n   *\n   * @category Data Collection\n   */\n  allowedGraphQlUrls?: Array<MatchOption | GraphQlUrlOption> | undefined\n}\n\nexport type HybridInitConfiguration = Omit<RumInitConfiguration, 'applicationId' | 'clientToken'>\n\nexport type FeatureFlagsForEvents = 'vital' | 'action' | 'long_task' | 'resource'\n\n/**\n * Function called before a RUM event is sent to Datadog. See {@link RumInitConfiguration.beforeSend}\n *\n * @param event - The RUM event\n * @param context - The RUM event domain context providing access to native browser data based on the event type (e.g. error, performance entry).\n * @returns true if the event should be sent to Datadog, false otherwise\n */\nexport type RumBeforeSend = (event: RumEvent, context: RumEventDomainContext) => boolean\n\nexport interface GraphQlUrlOption {\n  match: MatchOption\n  trackPayload?: boolean\n  trackResponseErrors?: boolean\n}\n\nexport interface MatchHeader {\n  url?: MatchOption\n  name: MatchOption\n  extractor?: RegExp\n  location?: 'request' | 'response' | 'any'\n}\n\nexport interface RumConfiguration extends Configuration {\n  // Built from init configuration\n  actionNameAttribute: string | undefined\n  betaTrackActionsInShadowDom: boolean\n  traceSampleRate: number\n  rulePsr: number | undefined\n  allowedTracingUrls: TracingOption[]\n  excludedActivityUrls: MatchOption[]\n  workerUrl: string | undefined\n  compressIntakeRequests: boolean\n  applicationId: string\n  defaultPrivacyLevel: DefaultPrivacyLevel\n  enablePrivacyForActionName: boolean\n  sessionReplaySampleRate: number\n  startSessionReplayRecordingManually: boolean\n  trackUserInteractions: boolean\n  trackViewsManually: boolean\n  trackResources: boolean\n  trackResourceHeaders: MatchHeader[]\n  trackLongTasks: boolean\n  trackBfcacheViews: boolean\n  trackEarlyRequests: boolean\n  subdomain?: string\n  traceContextInjection: TraceContextInjection\n  plugins: RumPlugin[]\n  trackFeatureFlagsForEvents: FeatureFlagsForEvents[]\n  profilingSampleRate: number\n  propagateTraceBaggage: boolean\n  allowedGraphQlUrls: GraphQlUrlOption[]\n}\n\nexport function validateAndBuildRumConfiguration(\n  initConfiguration: RumInitConfiguration,\n  errorStack?: string\n): RumConfiguration | undefined {\n  if (\n    initConfiguration.trackFeatureFlagsForEvents !== undefined &&\n    !Array.isArray(initConfiguration.trackFeatureFlagsForEvents)\n  ) {\n    display.warn('trackFeatureFlagsForEvents should be an array')\n  }\n\n  if (!initConfiguration.applicationId) {\n    display.error('Application ID is not configured, no RUM data will be collected.')\n    return\n  }\n\n  if (\n    !isSampleRate(initConfiguration.sessionReplaySampleRate, 'Session Replay') ||\n    !isSampleRate(initConfiguration.traceSampleRate, 'Trace')\n  ) {\n    return\n  }\n\n  if (initConfiguration.excludedActivityUrls !== undefined && !Array.isArray(initConfiguration.excludedActivityUrls)) {\n    display.error('Excluded Activity Urls should be an array')\n    return\n  }\n\n  const allowedTracingUrls = validateAndBuildTracingOptions(initConfiguration)\n  if (!allowedTracingUrls) {\n    return\n  }\n\n  const baseConfiguration = validateAndBuildConfiguration(initConfiguration, errorStack)\n\n  const allowedGraphQlUrls = validateAndBuildGraphQlOptions(initConfiguration)\n\n  if (!baseConfiguration) {\n    return\n  }\n\n  const sessionReplaySampleRate = initConfiguration.sessionReplaySampleRate ?? 0\n\n  return {\n    applicationId: initConfiguration.applicationId,\n    actionNameAttribute: initConfiguration.actionNameAttribute,\n    betaTrackActionsInShadowDom: !!initConfiguration.betaTrackActionsInShadowDom,\n    sessionReplaySampleRate,\n    startSessionReplayRecordingManually:\n      initConfiguration.startSessionReplayRecordingManually !== undefined\n        ? !!initConfiguration.startSessionReplayRecordingManually\n        : sessionReplaySampleRate === 0,\n    traceSampleRate: initConfiguration.traceSampleRate ?? 100,\n    rulePsr: isNumber(initConfiguration.traceSampleRate) ? initConfiguration.traceSampleRate / 100 : undefined,\n    allowedTracingUrls,\n    excludedActivityUrls: initConfiguration.excludedActivityUrls ?? [],\n    workerUrl: initConfiguration.workerUrl,\n    compressIntakeRequests: !!initConfiguration.compressIntakeRequests,\n    trackUserInteractions: !!(initConfiguration.trackUserInteractions ?? true),\n    trackViewsManually: !!initConfiguration.trackViewsManually,\n    trackResources: !!(initConfiguration.trackResources ?? true),\n    trackResourceHeaders: validateAndBuildTrackResourceHeaders(initConfiguration),\n    trackLongTasks: !!(initConfiguration.trackLongTasks ?? true),\n    trackBfcacheViews: !!initConfiguration.trackBfcacheViews,\n    trackEarlyRequests: !!initConfiguration.trackEarlyRequests,\n    subdomain: initConfiguration.subdomain,\n    defaultPrivacyLevel: objectHasValue(DefaultPrivacyLevel, initConfiguration.defaultPrivacyLevel)\n      ? initConfiguration.defaultPrivacyLevel\n      : DefaultPrivacyLevel.MASK,\n    enablePrivacyForActionName: !!initConfiguration.enablePrivacyForActionName,\n    traceContextInjection: objectHasValue(TraceContextInjection, initConfiguration.traceContextInjection)\n      ? initConfiguration.traceContextInjection\n      : TraceContextInjection.SAMPLED,\n    plugins: initConfiguration.plugins || [],\n    trackFeatureFlagsForEvents: initConfiguration.trackFeatureFlagsForEvents || [],\n    profilingSampleRate: initConfiguration.profilingSampleRate ?? 0,\n    propagateTraceBaggage: !!initConfiguration.propagateTraceBaggage,\n    allowedGraphQlUrls,\n    ...baseConfiguration,\n  }\n}\n\n/**\n * Validates allowedTracingUrls and converts match options to tracing options\n */\nfunction validateAndBuildTracingOptions(initConfiguration: RumInitConfiguration): TracingOption[] | undefined {\n  if (initConfiguration.allowedTracingUrls === undefined) {\n    return []\n  }\n  if (!Array.isArray(initConfiguration.allowedTracingUrls)) {\n    display.error('Allowed Tracing URLs should be an array')\n    return\n  }\n  if (initConfiguration.allowedTracingUrls.length !== 0 && initConfiguration.service === undefined) {\n    display.error('Service needs to be configured when tracing is enabled')\n    return\n  }\n  // Convert from (MatchOption | TracingOption) to TracingOption, remove unknown properties\n  const tracingOptions: TracingOption[] = []\n  initConfiguration.allowedTracingUrls.forEach((option) => {\n    const normalizedOption = normalizeTracingOption(option)\n    if (normalizedOption) {\n      tracingOptions.push(normalizedOption)\n    } else {\n      display.warn(\n        'Allowed Tracing Urls parameters should be a string, RegExp, function, or an object. Ignoring parameter',\n        option\n      )\n    }\n  })\n\n  return tracingOptions\n}\n\n/**\n * Combines the selected tracing propagators from the different options in allowedTracingUrls\n */\nfunction getSelectedTracingPropagators(configuration: RumInitConfiguration): PropagatorType[] {\n  const usedTracingPropagators = new Set<PropagatorType>()\n\n  if (isNonEmptyArray(configuration.allowedTracingUrls)) {\n    configuration.allowedTracingUrls.forEach((option) => {\n      normalizeTracingOption(option)?.propagatorTypes.forEach((propagatorType) =>\n        usedTracingPropagators.add(propagatorType)\n      )\n    })\n  }\n\n  return Array.from(usedTracingPropagators)\n}\n\nfunction normalizeTracingOption(option: unknown): TracingOption | undefined {\n  if (isMatchOption(option)) {\n    return { match: option, propagatorTypes: DEFAULT_PROPAGATOR_TYPES }\n  }\n\n  if (\n    isIndexableObject(option) &&\n    isMatchOption(option.match) &&\n    (option.propagatorTypes === null || option.propagatorTypes === undefined || Array.isArray(option.propagatorTypes))\n  ) {\n    return {\n      match: option.match,\n      propagatorTypes: option.propagatorTypes || DEFAULT_PROPAGATOR_TYPES,\n    }\n  }\n}\n\n/**\n * Build GraphQL options from configuration\n */\nfunction validateAndBuildGraphQlOptions(initConfiguration: RumInitConfiguration): GraphQlUrlOption[] {\n  if (!initConfiguration.allowedGraphQlUrls) {\n    return []\n  }\n\n  if (!Array.isArray(initConfiguration.allowedGraphQlUrls)) {\n    display.warn('allowedGraphQlUrls should be an array')\n    return []\n  }\n\n  const graphQlOptions: GraphQlUrlOption[] = []\n\n  initConfiguration.allowedGraphQlUrls.forEach((option) => {\n    if (isMatchOption(option)) {\n      graphQlOptions.push({ match: option, trackPayload: false, trackResponseErrors: false })\n    } else if (isIndexableObject(option) && isMatchOption(option.match)) {\n      graphQlOptions.push({\n        match: option.match,\n        trackPayload: !!option.trackPayload,\n        trackResponseErrors: !!option.trackResponseErrors,\n      })\n    }\n  })\n\n  return graphQlOptions\n}\n\nconst VALID_HEADER_LOCATIONS = ['request', 'response', 'any']\n\nfunction validateAndBuildTrackResourceHeaders(initConfiguration: RumInitConfiguration): MatchHeader[] {\n  const option = initConfiguration.trackResourceHeaders\n\n  if (option === undefined || option === false) {\n    return []\n  }\n\n  if (option === true) {\n    return DEFAULT_TRACKED_RESOURCE_HEADERS.map((name) => ({ name }))\n  }\n\n  if (!Array.isArray(option)) {\n    display.warn('trackResourceHeaders should be true or an array of MatchHeader')\n    return []\n  }\n\n  if (option.length === 0) {\n    display.warn('trackResourceHeaders is an empty array, no headers will be captured')\n    return []\n  }\n\n  const result: MatchHeader[] = []\n\n  option.forEach((item, index) => {\n    if (!isIndexableObject(item) || !isMatchOption(item.name)) {\n      display.warn(`trackResourceHeaders[${index}] should be a MatchHeader object with a 'name' property`)\n      return\n    }\n    if (item.url !== undefined && !isMatchOption(item.url)) {\n      display.warn(`trackResourceHeaders[${index}].url should be a MatchOption`)\n      return\n    }\n    if (item.extractor !== undefined && !(item.extractor instanceof RegExp)) {\n      display.warn(`trackResourceHeaders[${index}].extractor should be a RegExp`)\n      return\n    }\n    if (item.location !== undefined && !VALID_HEADER_LOCATIONS.includes(item.location as string)) {\n      display.warn(`trackResourceHeaders[${index}].location should be 'request', 'response', or 'any'`)\n      return\n    }\n\n    result.push({\n      ...item,\n      name: typeof item.name === 'string' ? item.name.toLowerCase() : (item.name as MatchOption),\n    })\n  })\n\n  return result\n}\n\nfunction hasGraphQlPayloadTracking(allowedGraphQlUrls: RumInitConfiguration['allowedGraphQlUrls']): boolean {\n  return (\n    isNonEmptyArray(allowedGraphQlUrls) &&\n    allowedGraphQlUrls.some((option) => isIndexableObject(option) && option.trackPayload)\n  )\n}\n\nfunction hasGraphQlResponseErrorsTracking(allowedGraphQlUrls: RumInitConfiguration['allowedGraphQlUrls']): boolean {\n  return (\n    isNonEmptyArray(allowedGraphQlUrls) &&\n    allowedGraphQlUrls.some((option) => isIndexableObject(option) && option.trackResponseErrors)\n  )\n}\n\nexport function serializeRumConfiguration(configuration: RumInitConfiguration) {\n  const baseSerializedConfiguration = serializeConfiguration(configuration)\n\n  return {\n    session_replay_sample_rate: configuration.sessionReplaySampleRate,\n    start_session_replay_recording_manually: configuration.startSessionReplayRecordingManually,\n    trace_sample_rate: configuration.traceSampleRate,\n    trace_context_injection: configuration.traceContextInjection,\n    propagate_trace_baggage: configuration.propagateTraceBaggage,\n    action_name_attribute: configuration.actionNameAttribute,\n    use_allowed_tracing_urls: isNonEmptyArray(configuration.allowedTracingUrls),\n    use_allowed_graph_ql_urls: isNonEmptyArray(configuration.allowedGraphQlUrls),\n    use_track_graph_ql_payload: hasGraphQlPayloadTracking(configuration.allowedGraphQlUrls),\n    use_track_graph_ql_response_errors: hasGraphQlResponseErrorsTracking(configuration.allowedGraphQlUrls),\n    selected_tracing_propagators: getSelectedTracingPropagators(configuration),\n    default_privacy_level: configuration.defaultPrivacyLevel,\n    enable_privacy_for_action_name: configuration.enablePrivacyForActionName,\n    use_excluded_activity_urls: isNonEmptyArray(configuration.excludedActivityUrls),\n    use_worker_url: !!configuration.workerUrl,\n    compress_intake_requests: configuration.compressIntakeRequests,\n    track_views_manually: configuration.trackViewsManually,\n    track_user_interactions: configuration.trackUserInteractions,\n    track_resources: configuration.trackResources,\n    track_long_task: configuration.trackLongTasks,\n    track_bfcache_views: configuration.trackBfcacheViews,\n    track_early_requests: configuration.trackEarlyRequests,\n    plugins: configuration.plugins?.map((plugin) => ({\n      name: plugin.name,\n      ...plugin.getConfigurationTelemetry?.(),\n    })),\n    track_feature_flags_for_events: configuration.trackFeatureFlagsForEvents,\n    remote_configuration_id: configuration.remoteConfigurationId,\n    profiling_sample_rate: configuration.profilingSampleRate,\n    use_remote_configuration_proxy: !!configuration.remoteConfigurationProxy,\n    ...baseSerializedConfiguration,\n  } satisfies RawTelemetryConfiguration\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/index.ts",
    "content": "export * from './configuration'\nexport * from './remoteConfiguration'\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/jsonPathParser.spec.ts",
    "content": "import { parseJsonPath } from './jsonPathParser'\n\ndescribe('parseJsonPath', () => {\n  it('should extract selectors from dot notation', () => {\n    expect(parseJsonPath('a')).toEqual(['a'])\n    expect(parseJsonPath('foo.bar')).toEqual(['foo', 'bar'])\n    expect(parseJsonPath('foo.bar.qux')).toEqual(['foo', 'bar', 'qux'])\n  })\n\n  it('should parse extract selectors from bracket notation', () => {\n    expect(parseJsonPath(String.raw`['a']`)).toEqual(['a'])\n    expect(parseJsonPath(String.raw`[\"a\"]`)).toEqual(['a'])\n    expect(parseJsonPath(String.raw`['foo'][\"bar\"]`)).toEqual(['foo', 'bar'])\n    expect(parseJsonPath(String.raw`['foo'][\"bar\"]['qux']`)).toEqual(['foo', 'bar', 'qux'])\n  })\n\n  it('should extract selectors from mixed notations', () => {\n    expect(parseJsonPath(String.raw`['foo'].bar['qux']`)).toEqual(['foo', 'bar', 'qux'])\n  })\n\n  it('should extract name and index selectors', () => {\n    expect(parseJsonPath('[0]')).toEqual(['0'])\n    expect(parseJsonPath('foo[12]')).toEqual(['foo', '12'])\n    expect(parseJsonPath(String.raw`['foo'][12]`)).toEqual(['foo', '12'])\n  })\n\n  it('should extract name selectors replacing escaped sequence by equivalent character', () => {\n    expect(parseJsonPath(String.raw`['foo\\n']`)).toEqual(['foo\\n'])\n    expect(parseJsonPath(String.raw`['foo\\b']`)).toEqual(['foo\\b'])\n    expect(parseJsonPath(String.raw`['foo\\t']`)).toEqual(['foo\\t'])\n    expect(parseJsonPath(String.raw`['foo\\f']`)).toEqual(['foo\\f'])\n    expect(parseJsonPath(String.raw`['foo\\r']`)).toEqual(['foo\\r'])\n    expect(parseJsonPath(String.raw`[\"foo\\u03A9\"]`)).toEqual(['fooΩ'])\n    expect(parseJsonPath(String.raw`[\"\\u03A9A\"]`)).toEqual(['ΩA'])\n    expect(parseJsonPath(String.raw`[\"\\t\\u03A9\\n\"]`)).toEqual(['\\tΩ\\n'])\n    expect(parseJsonPath(String.raw`['foo\\'']`)).toEqual([String.raw`foo'`])\n    expect(parseJsonPath(String.raw`[\"foo\\\"\"]`)).toEqual([String.raw`foo\"`])\n    expect(parseJsonPath(String.raw`[\"foo\\/\"]`)).toEqual([String.raw`foo/`])\n  })\n\n  it('should extract name selectors containing characters not supported in name shorthands', () => {\n    expect(parseJsonPath(String.raw`['foo[]']`)).toEqual([String.raw`foo[]`])\n    expect(parseJsonPath(String.raw`['foo.']`)).toEqual([String.raw`foo.`])\n  })\n\n  it('should return an empty array for an invalid path', () => {\n    expect(parseJsonPath('.foo')).toEqual([])\n    expect(parseJsonPath('.')).toEqual([])\n    expect(parseJsonPath('foo.')).toEqual([])\n    expect(parseJsonPath('foo..bar')).toEqual([])\n    expect(parseJsonPath('[1')).toEqual([])\n    expect(parseJsonPath('foo]')).toEqual([])\n    expect(parseJsonPath(String.raw`[['foo']`)).toEqual([])\n    expect(parseJsonPath(String.raw`['foo'`)).toEqual([])\n    expect(parseJsonPath(String.raw`['foo]`)).toEqual([])\n    expect(parseJsonPath(String.raw`[foo']`)).toEqual([])\n    expect(parseJsonPath(String.raw`['foo''bar']`)).toEqual([])\n    expect(parseJsonPath(String.raw`['foo\\o']`)).toEqual([])\n    expect(parseJsonPath(String.raw`[\"\\u03Z9\"]`)).toEqual([])\n    expect(parseJsonPath(String.raw`['foo\\u12']`)).toEqual([])\n    expect(parseJsonPath(String.raw`['foo']a`)).toEqual([])\n    expect(parseJsonPath(String.raw`[\"foo']`)).toEqual([])\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/jsonPathParser.ts",
    "content": "/**\n * Terminology inspired from https://www.rfc-editor.org/rfc/rfc9535.html\n *\n * jsonpath-query      = segment*\n * segment             = .name-shorthand / bracketed-selection\n * bracketed-selection = ['name-selector'] / [\"name-selector\"] / [index-selector]\n *\n * Useful references:\n * - https://goessner.net/articles/JsonPath/\n * - https://jsonpath.com/\n * - https://github.com/jsonpath-standard\n */\n\ninterface ParsingContext {\n  quote: string | undefined\n  escapeSequence: string | undefined\n}\n\n/**\n * Extract selectors from a simple JSON path expression, return [] for an invalid path\n *\n * Supports:\n * - Dot notation: `foo.bar.baz`\n * - Bracket notation: `['foo'][\"bar\"]`\n * - Array indices: `items[0]`, `data['users'][1]`\n *\n * Examples:\n * parseJsonPath(\"['foo'].bar[12]\")\n * => ['foo', 'bar', '12']\n *\n * parseJsonPath(\"['foo\")\n * => []\n */\nexport function parseJsonPath(path: string): string[] {\n  const selectors: string[] = []\n  let previousToken = Token.START\n  let currentToken: Token | undefined\n  const parsingContext: ParsingContext = { quote: undefined, escapeSequence: undefined }\n  let currentSelector = ''\n  for (const char of path) {\n    // find which kind of token is this char\n    currentToken = ALLOWED_NEXT_TOKENS[previousToken].find((token) => TOKEN_PREDICATE[token](char, parsingContext))\n    if (!currentToken) {\n      return []\n    }\n    if (parsingContext.escapeSequence !== undefined && currentToken !== Token.ESCAPE_SEQUENCE_CHAR) {\n      if (!isValidEscapeSequence(parsingContext.escapeSequence)) {\n        return []\n      }\n      currentSelector += resolveEscapeSequence(parsingContext.escapeSequence)\n      parsingContext.escapeSequence = undefined\n    }\n    if (ALLOWED_SELECTOR_TOKENS.includes(currentToken)) {\n      // buffer the char if it belongs to the selector\n      // ex: foo['bar']\n      //      ^    ^\n      currentSelector += char\n    } else if (ALLOWED_SELECTOR_DELIMITER_TOKENS.includes(currentToken) && currentSelector !== '') {\n      // close the current path part if we have reach a path part delimiter\n      // ex: foo.bar['qux']\n      //        ^   ^     ^\n      selectors.push(currentSelector)\n      currentSelector = ''\n    } else if (currentToken === Token.ESCAPE_SEQUENCE_CHAR) {\n      parsingContext.escapeSequence = parsingContext.escapeSequence ? `${parsingContext.escapeSequence}${char}` : char\n    } else if (currentToken === Token.QUOTE_START) {\n      parsingContext.quote = char\n    } else if (currentToken === Token.QUOTE_END) {\n      parsingContext.quote = undefined\n    }\n    previousToken = currentToken\n  }\n  if (!ALLOWED_NEXT_TOKENS[previousToken].includes(Token.END)) {\n    return []\n  }\n  if (currentSelector !== '') {\n    selectors.push(currentSelector)\n  }\n  return selectors\n}\n\n/**\n * List of all tokens in the path\n *\n * @example                        foo.bar['qu\\'x'][0]\n *                                |   |   |        |  |\n * Token sequence:                |   |   |        |  |\n * 1. START (before first char) <-+   |   |        |  |\n * 2. NAME_SHORTHAND_FIRST_CHAR: f    |   |        |  |\n * 3. NAME_SHORTHAND_CHAR: oo         |   |        |  |\n * 4. DOT: . <------------------------+   |        |  |\n * 5. NAME_SHORTHAND_FIRST_CHAR: b        |        |  |\n * 6. NAME_SHORTHAND_CHAR: ar             |        |  |\n * 7. BRACKET_START: [ <------------------+        |  |\n * 8. QUOTE_START: '                               |  |\n * 9. NAME_SELECTOR_CHAR: qu                       |  |\n * 10. ESCAPE: \\                                   |  |\n * 11. ESCAPABLE_CHAR: '                           |  |\n * 12. NAME_SELECTOR_CHAR: x                       |  |\n * 13. QUOTE_END: '                                |  |\n * 14. BRACKET_END: ]                              |  |\n * 15. BRACKET_START: [ <--------------------------+  |\n * 16. DIGIT: 0                                       |\n * 17. BRACKET_END: ]                                 |\n * 18. END (after last char) <------------------------+\n */\nconst enum Token {\n  START,\n  END,\n\n  NAME_SHORTHAND_FIRST_CHAR,\n  NAME_SHORTHAND_CHAR,\n  DOT,\n\n  BRACKET_START,\n  BRACKET_END,\n  DIGIT,\n\n  QUOTE_START,\n  QUOTE_END,\n  NAME_SELECTOR_CHAR,\n  ESCAPE,\n  ESCAPE_SEQUENCE_CHAR,\n}\n\nconst NAME_SHORTHAND_FIRST_CHAR_REGEX = /[a-zA-Z_$]/\nconst NAME_SHORTHAND_CHAR_REGEX = /[a-zA-Z0-9_$]/\nconst DIGIT_REGEX = /[0-9]/\nconst UNICODE_CHAR_REGEX = /[a-fA-F0-9]/\nconst QUOTE_CHARS = '\\'\"'\n\nconst TOKEN_PREDICATE: { [token in Token]: (char: string, parsingContext: ParsingContext) => boolean } = {\n  // no char should match to START or END\n  [Token.START]: () => false,\n  [Token.END]: () => false,\n\n  [Token.NAME_SHORTHAND_FIRST_CHAR]: (char) => NAME_SHORTHAND_FIRST_CHAR_REGEX.test(char),\n  [Token.NAME_SHORTHAND_CHAR]: (char) => NAME_SHORTHAND_CHAR_REGEX.test(char),\n  [Token.DOT]: (char) => char === '.',\n\n  [Token.BRACKET_START]: (char) => char === '[',\n  [Token.BRACKET_END]: (char) => char === ']',\n  [Token.DIGIT]: (char) => DIGIT_REGEX.test(char),\n\n  [Token.QUOTE_START]: (char) => QUOTE_CHARS.includes(char),\n  [Token.QUOTE_END]: (char, parsingContext) => char === parsingContext.quote,\n  [Token.NAME_SELECTOR_CHAR]: () => true, // any char can be used in name selector\n  [Token.ESCAPE]: (char) => char === '\\\\',\n  [Token.ESCAPE_SEQUENCE_CHAR]: (char, parsingContext) => {\n    if (parsingContext.escapeSequence === undefined) {\n      // see https://www.rfc-editor.org/rfc/rfc9535.html#name-semantics-3\n      return `${parsingContext.quote}/\\\\bfnrtu`.includes(char)\n    } else if (parsingContext.escapeSequence.startsWith('u') && parsingContext.escapeSequence.length < 5) {\n      return UNICODE_CHAR_REGEX.test(char)\n    }\n    return false\n  },\n}\n\nconst ALLOWED_NEXT_TOKENS: { [token in Token]: Token[] } = {\n  [Token.START]: [Token.NAME_SHORTHAND_FIRST_CHAR, Token.BRACKET_START],\n  [Token.END]: [],\n\n  [Token.NAME_SHORTHAND_FIRST_CHAR]: [Token.NAME_SHORTHAND_CHAR, Token.DOT, Token.BRACKET_START, Token.END],\n  [Token.NAME_SHORTHAND_CHAR]: [Token.NAME_SHORTHAND_CHAR, Token.DOT, Token.BRACKET_START, Token.END],\n  [Token.DOT]: [Token.NAME_SHORTHAND_FIRST_CHAR],\n\n  [Token.BRACKET_START]: [Token.QUOTE_START, Token.DIGIT],\n  [Token.BRACKET_END]: [Token.DOT, Token.BRACKET_START, Token.END],\n  [Token.DIGIT]: [Token.DIGIT, Token.BRACKET_END],\n\n  [Token.QUOTE_START]: [Token.ESCAPE, Token.QUOTE_END, Token.NAME_SELECTOR_CHAR],\n  [Token.QUOTE_END]: [Token.BRACKET_END],\n  [Token.NAME_SELECTOR_CHAR]: [Token.ESCAPE, Token.QUOTE_END, Token.NAME_SELECTOR_CHAR],\n  [Token.ESCAPE]: [Token.ESCAPE_SEQUENCE_CHAR],\n  [Token.ESCAPE_SEQUENCE_CHAR]: [Token.ESCAPE_SEQUENCE_CHAR, Token.ESCAPE, Token.QUOTE_END, Token.NAME_SELECTOR_CHAR],\n}\n\n// foo['bar\\n'][12]\n// ^^    ^ ^^   ^\nconst ALLOWED_SELECTOR_TOKENS = [\n  Token.NAME_SHORTHAND_FIRST_CHAR,\n  Token.NAME_SHORTHAND_CHAR,\n  Token.DIGIT,\n  Token.NAME_SELECTOR_CHAR,\n]\n\n// foo.bar['qux']\n//    ^   ^     ^\nconst ALLOWED_SELECTOR_DELIMITER_TOKENS = [Token.DOT, Token.BRACKET_START, Token.BRACKET_END]\n\nfunction isValidEscapeSequence(escapeSequence: string): boolean {\n  return '\"\\'/\\\\bfnrt'.includes(escapeSequence) || (escapeSequence.startsWith('u') && escapeSequence.length === 5)\n}\n\nconst ESCAPED_CHARS: { [key: string]: string } = {\n  '\"': '\"',\n  \"'\": \"'\",\n  '/': '/',\n  '\\\\': '\\\\',\n  b: '\\b',\n  f: '\\f',\n  n: '\\n',\n  r: '\\r',\n  t: '\\t',\n}\n\nfunction resolveEscapeSequence(escapeSequence: string): string {\n  if (escapeSequence.startsWith('u')) {\n    // build Unicode char from code\n    return String.fromCharCode(parseInt(escapeSequence.slice(1), 16))\n  }\n  return ESCAPED_CHARS[escapeSequence]\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/remoteConfiguration.spec.ts",
    "content": "import {\n  DefaultPrivacyLevel,\n  INTAKE_SITE_US1,\n  display,\n  setCookie,\n  deleteCookie,\n  ONE_MINUTE,\n  createContextManager,\n} from '@datadog/browser-core'\nimport { interceptRequests, registerCleanupTask } from '@datadog/browser-core/test'\nimport { appendElement } from '../../../test'\nimport type { RumInitConfiguration } from './configuration'\nimport {\n  type RumRemoteConfiguration,\n  initMetrics,\n  applyRemoteConfiguration,\n  buildEndpoint,\n  fetchRemoteConfiguration,\n} from './remoteConfiguration'\n\nconst DEFAULT_INIT_CONFIGURATION: RumInitConfiguration = {\n  clientToken: 'xxx',\n  applicationId: 'xxx',\n  service: 'xxx',\n  sessionReplaySampleRate: 100,\n  defaultPrivacyLevel: DefaultPrivacyLevel.MASK,\n}\n\ntype ResolveRemoteConfigurationValue<T> = T extends any[]\n  ? Array<ResolveRemoteConfigurationValue<T[number]>>\n  : T extends { rcSerializedType: infer SerializedType }\n    ? SerializedType extends 'string' | 'dynamic'\n      ? string\n      : SerializedType extends 'regex'\n        ? RegExp\n        : never\n    : T extends Record<string, any>\n      ? { [K in keyof T]: ResolveRemoteConfigurationProperty<K, T[K]> }\n      : T\n\ntype ResolveRemoteConfigurationProperty<Key, Value> =\n  // 'defaultPrivacyLevel' is defined as 'string' in remote configuration but as\n  // 'DefaultPrivacyLevel' in init configuration, so in theory there is no guarantee that remote\n  // configuration sets a supported value for this. This could be improved later.\n  Key extends 'defaultPrivacyLevel' ? DefaultPrivacyLevel : ResolveRemoteConfigurationValue<Value>\n\ntype ResolvedRumRemoteConfiguration = ResolveRemoteConfigurationValue<RumRemoteConfiguration>\n\n// Make sure the RumRemoteConfiguration type is assignable to RumInitConfiguration.\ntype Assert<T extends true> = T\nexport type _ = Assert<\n  ResolvedRumRemoteConfiguration & {\n    // clientToken is not part of the remote configuration but required in init configuration\n    clientToken: string\n  } extends RumInitConfiguration\n    ? true\n    : false\n>\n\ndescribe('remoteConfiguration', () => {\n  describe('fetchRemoteConfiguration', () => {\n    const configuration = { remoteConfigurationId: 'xxx' } as RumInitConfiguration\n    let interceptor: ReturnType<typeof interceptRequests>\n\n    beforeEach(() => {\n      interceptor = interceptRequests()\n    })\n\n    it('should fetch the remote configuration', async () => {\n      interceptor.withFetch(() =>\n        Promise.resolve({\n          ok: true,\n          json: () =>\n            Promise.resolve({\n              rum: {\n                applicationId: 'xxx',\n                sessionSampleRate: 50,\n                sessionReplaySampleRate: 50,\n                defaultPrivacyLevel: 'allow',\n              },\n            }),\n        })\n      )\n\n      const fetchResult = await fetchRemoteConfiguration(configuration)\n      expect(fetchResult).toEqual({\n        ok: true,\n        value: {\n          applicationId: 'xxx',\n          sessionSampleRate: 50,\n          sessionReplaySampleRate: 50,\n          defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n        },\n      })\n    })\n\n    it('should return an error if the fetching fails with a server error', async () => {\n      interceptor.withFetch(() => Promise.reject(new Error('Server error')))\n\n      const fetchResult = await fetchRemoteConfiguration(configuration)\n      expect(fetchResult).toEqual({\n        ok: false,\n        error: new Error('Error fetching the remote configuration.'),\n      })\n    })\n\n    it('should throw an error if the fetching fails with a client error', async () => {\n      interceptor.withFetch(() =>\n        Promise.resolve({\n          ok: false,\n        })\n      )\n\n      const fetchResult = await fetchRemoteConfiguration(configuration)\n      expect(fetchResult).toEqual({\n        ok: false,\n        error: new Error('Error fetching the remote configuration.'),\n      })\n    })\n\n    it('should throw an error if the remote config does not contain rum config', async () => {\n      interceptor.withFetch(() =>\n        Promise.resolve({\n          ok: true,\n          json: () => Promise.resolve({}),\n        })\n      )\n\n      const fetchResult = await fetchRemoteConfiguration(configuration)\n      expect(fetchResult).toEqual({\n        ok: false,\n        error: new Error('No remote configuration for RUM.'),\n      })\n    })\n  })\n\n  describe('applyRemoteConfiguration', () => {\n    const COOKIE_NAME = 'unit_rc'\n    const root = window as any\n\n    let displaySpy: jasmine.Spy\n    let supportedContextManagers: {\n      user: ReturnType<typeof createContextManager>\n      context: ReturnType<typeof createContextManager>\n    }\n    let metrics: ReturnType<typeof initMetrics>\n\n    function expectAppliedRemoteConfigurationToBe(\n      actual: Partial<RumRemoteConfiguration>,\n      expected: Partial<RumInitConfiguration>\n    ) {\n      const rumRemoteConfiguration: RumRemoteConfiguration = {\n        applicationId: 'yyy',\n        ...actual,\n      }\n      expect(\n        applyRemoteConfiguration(DEFAULT_INIT_CONFIGURATION, rumRemoteConfiguration, supportedContextManagers, metrics)\n      ).toEqual({\n        ...DEFAULT_INIT_CONFIGURATION,\n        applicationId: 'yyy',\n        ...expected,\n      })\n    }\n\n    beforeEach(() => {\n      displaySpy = spyOn(display, 'error')\n      supportedContextManagers = { user: createContextManager(), context: createContextManager() }\n      metrics = initMetrics()\n    })\n\n    it('should override the initConfiguration options with the ones from the remote configuration', () => {\n      const rumRemoteConfiguration: RumRemoteConfiguration = {\n        applicationId: 'yyy',\n        sessionSampleRate: 1,\n        sessionReplaySampleRate: 1,\n        traceSampleRate: 1,\n        trackSessionAcrossSubdomains: true,\n        allowedTrackingOrigins: [\n          { rcSerializedType: 'string', value: 'https://example.com' },\n          { rcSerializedType: 'regex', value: '^https:\\\\/\\\\/app-\\\\w+\\\\.datadoghq\\\\.com' },\n        ],\n        allowedTracingUrls: [\n          {\n            match: { rcSerializedType: 'string', value: 'https://example.com' },\n            propagatorTypes: ['b3', 'tracecontext'],\n          },\n          {\n            match: { rcSerializedType: 'regex', value: '^https:\\\\/\\\\/app-\\\\w+\\\\.datadoghq\\\\.com' },\n            propagatorTypes: ['datadog', 'b3multi'],\n          },\n        ],\n        defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n      }\n      expect(\n        applyRemoteConfiguration(DEFAULT_INIT_CONFIGURATION, rumRemoteConfiguration, supportedContextManagers, metrics)\n      ).toEqual({\n        applicationId: 'yyy',\n        clientToken: 'xxx',\n        service: 'xxx',\n        sessionSampleRate: 1,\n        sessionReplaySampleRate: 1,\n        traceSampleRate: 1,\n        trackSessionAcrossSubdomains: true,\n        allowedTrackingOrigins: ['https://example.com', /^https:\\/\\/app-\\w+\\.datadoghq\\.com/],\n        allowedTracingUrls: [\n          { match: 'https://example.com', propagatorTypes: ['b3', 'tracecontext'] },\n          { match: /^https:\\/\\/app-\\w+\\.datadoghq\\.com/, propagatorTypes: ['datadog', 'b3multi'] },\n        ],\n        defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n      })\n    })\n\n    it('should display an error if the remote config contains invalid regex', () => {\n      expectAppliedRemoteConfigurationToBe(\n        { allowedTrackingOrigins: [{ rcSerializedType: 'regex', value: 'Hello(?|!)' }] },\n        { allowedTrackingOrigins: [undefined as any] }\n      )\n      expect(displaySpy).toHaveBeenCalledWith(\"Invalid regex in the remote configuration: 'Hello(?|!)'\")\n    })\n\n    it('should display an error if an unsupported `rcSerializedType` is provided', () => {\n      expectAppliedRemoteConfigurationToBe(\n        { allowedTrackingOrigins: [{ rcSerializedType: 'foo' as any, value: 'bar' }] },\n        { allowedTrackingOrigins: [undefined as any] }\n      )\n      expect(displaySpy).toHaveBeenCalledWith('Unsupported remote configuration: \"rcSerializedType\": \"foo\"')\n    })\n\n    it('should display an error if an unsupported `strategy` is provided', () => {\n      expectAppliedRemoteConfigurationToBe(\n        { version: { rcSerializedType: 'dynamic', strategy: 'foo' as any } as any },\n        { version: undefined }\n      )\n      expect(displaySpy).toHaveBeenCalledWith('Unsupported remote configuration: \"strategy\": \"foo\"')\n    })\n\n    describe('cookie strategy', () => {\n      it('should resolve a configuration value from a cookie', () => {\n        setCookie(COOKIE_NAME, 'my-version', ONE_MINUTE)\n        registerCleanupTask(() => deleteCookie(COOKIE_NAME))\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'cookie', name: COOKIE_NAME } },\n          { version: 'my-version' }\n        )\n        expect(metrics.get().cookie).toEqual({ success: 1 })\n      })\n\n      it('should resolve to undefined if the cookie is missing', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'cookie', name: COOKIE_NAME } },\n          { version: undefined }\n        )\n        expect(metrics.get().cookie).toEqual({ missing: 1 })\n      })\n    })\n\n    describe('dom strategy', () => {\n      beforeEach(() => {\n        appendElement(`<div>\n            <span id=\"version1\" class=\"version\">version-123</span>\n            <span id=\"version2\" class=\"version\" data-version=\"version-456\"></span>\n          </div>`)\n      })\n\n      it('should resolve a configuration value from an element text content', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#version1' } },\n          { version: 'version-123' }\n        )\n        expect(metrics.get().dom).toEqual({ success: 1 })\n      })\n\n      it('should resolve a configuration value from an element text content and an extractor', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'dom',\n              selector: '#version1',\n              extractor: { rcSerializedType: 'regex', value: '\\\\d+' },\n            },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should resolve a configuration value from the first element matching the selector', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '.version' } },\n          { version: 'version-123' }\n        )\n      })\n\n      it('should resolve to undefined and display an error if the selector is invalid', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '' } },\n          { version: undefined }\n        )\n        expect(displaySpy).toHaveBeenCalledWith(\"Invalid selector in the remote configuration: ''\")\n        expect(metrics.get().dom).toEqual({ failure: 1 })\n      })\n\n      it('should resolve to undefined if the element is missing', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#missing' } },\n          { version: undefined }\n        )\n        expect(metrics.get().dom).toEqual({ missing: 1 })\n      })\n\n      it('should resolve a configuration value from an element attribute', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#version2', attribute: 'data-version' },\n          },\n          { version: 'version-456' }\n        )\n      })\n\n      it('should resolve to undefined if the element attribute is missing', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#version2', attribute: 'missing' } },\n          { version: undefined }\n        )\n        expect(metrics.get().dom).toEqual({ missing: 1 })\n      })\n\n      it('should resolve to undefined if trying to access a password input value attribute', () => {\n        appendElement('<input id=\"pwd\" type=\"password\" value=\"foo\" />')\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#pwd', attribute: 'value' } },\n          { version: undefined }\n        )\n        expect(displaySpy).toHaveBeenCalledWith(\"Forbidden element selected by the remote configuration: '#pwd'\")\n      })\n    })\n\n    describe('js strategy', () => {\n      it('should resolve a value from a variable content', () => {\n        root.foo = 'bar'\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo' },\n          },\n          { version: 'bar' }\n        )\n        expect(metrics.get().js).toEqual({ success: 1 })\n      })\n\n      it('should resolve a value from an object property', () => {\n        root.foo = { bar: { qux: '123' } }\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo.bar.qux' },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should resolve a string value with an extractor', () => {\n        root.foo = 'version-123'\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'js',\n              path: 'foo',\n              extractor: { rcSerializedType: 'regex', value: '\\\\d+' },\n            },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should resolve to a non string value', () => {\n        root.foo = 23\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo' },\n          },\n          { version: 23 as any }\n        )\n      })\n\n      it('should resolve a value from an object property containing an escapable character', () => {\n        root.foo = { 'bar\\nqux': '123' }\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: \"foo['bar\\\\nqux']\" },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should not apply the extractor to a non string value', () => {\n        root.foo = 23\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'js',\n              path: 'foo',\n              extractor: { rcSerializedType: 'regex', value: '\\\\d+' },\n            },\n          },\n          { version: 23 as any }\n        )\n      })\n\n      it('should resolve a value from an array item', () => {\n        root.foo = { bar: [{ qux: '123' }] }\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo.bar[0].qux' },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should resolve to undefined and display an error if the JSON path is invalid', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: '.' },\n          },\n          { version: undefined }\n        )\n        expect(displaySpy).toHaveBeenCalledWith(\"Invalid JSON path in the remote configuration: '.'\")\n        expect(metrics.get().js).toEqual({ failure: 1 })\n      })\n\n      it('should resolve to undefined and display an error if the variable access throws', () => {\n        root.foo = {\n          get bar() {\n            throw new Error('foo')\n          },\n        }\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo.bar' },\n          },\n          { version: undefined }\n        )\n        expect(displaySpy).toHaveBeenCalledWith(\"Error accessing: 'foo.bar'\", new Error('foo'))\n        expect(metrics.get().js).toEqual({ failure: 1 })\n      })\n\n      it('should resolve to undefined if the variable does not exist', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'missing' },\n          },\n          { version: undefined }\n        )\n        expect(metrics.get().js).toEqual({ missing: 1 })\n      })\n\n      it('should resolve to undefined if the property does not exist', () => {\n        root.foo = {}\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo.missing' },\n          },\n          { version: undefined }\n        )\n        expect(metrics.get().js).toEqual({ missing: 1 })\n      })\n\n      it('should resolve to undefined if the array index does not exist', () => {\n        root.foo = []\n        registerCleanupTask(() => {\n          delete root.foo\n        })\n\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'foo[0]' },\n          },\n          { version: undefined }\n        )\n        expect(metrics.get().js).toEqual({ missing: 1 })\n      })\n    })\n\n    describe('localStorage strategy', () => {\n      const LOCAL_STORAGE_KEY = 'dd_test_version'\n\n      beforeEach(() => {\n        localStorage.setItem(LOCAL_STORAGE_KEY, 'my-version')\n        registerCleanupTask(() => localStorage.removeItem(LOCAL_STORAGE_KEY))\n      })\n\n      it('should resolve a configuration value from localStorage', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'localStorage', key: LOCAL_STORAGE_KEY } },\n          { version: 'my-version' }\n        )\n        expect(metrics.get().localStorage).toEqual({ success: 1 })\n      })\n\n      it('should resolve a configuration value from localStorage with an extractor', () => {\n        localStorage.setItem(LOCAL_STORAGE_KEY, 'version-123')\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'localStorage',\n              key: LOCAL_STORAGE_KEY,\n              extractor: { rcSerializedType: 'regex', value: '\\\\d+' },\n            },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should resolve to undefined if the localStorage key is missing', () => {\n        expectAppliedRemoteConfigurationToBe(\n          { version: { rcSerializedType: 'dynamic', strategy: 'localStorage', key: 'non_existent_key' } },\n          { version: undefined }\n        )\n        expect(metrics.get().localStorage).toEqual({ missing: 1 })\n      })\n    })\n\n    describe('with extractor', () => {\n      beforeEach(() => {\n        setCookie(COOKIE_NAME, 'my-version-123', ONE_MINUTE)\n      })\n\n      afterEach(() => {\n        deleteCookie(COOKIE_NAME)\n      })\n\n      it('should resolve to the match on the value', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'cookie',\n              name: COOKIE_NAME,\n              extractor: { rcSerializedType: 'regex', value: '\\\\d+' },\n            },\n          },\n          { version: '123' }\n        )\n      })\n\n      it('should resolve to the capture group on the value', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'cookie',\n              name: COOKIE_NAME,\n              extractor: { rcSerializedType: 'regex', value: 'my-version-(\\\\d+)' },\n            },\n          },\n          { version: '123' }\n        )\n      })\n\n      it(\"should resolve to undefined if the value don't match\", () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'cookie',\n              name: COOKIE_NAME,\n              extractor: { rcSerializedType: 'regex', value: 'foo' },\n            },\n          },\n          { version: undefined }\n        )\n      })\n\n      it('should display an error if the extractor is not a valid regex', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            version: {\n              rcSerializedType: 'dynamic',\n              strategy: 'cookie',\n              name: COOKIE_NAME,\n              extractor: { rcSerializedType: 'regex', value: 'Hello(?|!)' },\n            },\n          },\n          { version: undefined }\n        )\n        expect(displaySpy).toHaveBeenCalledWith(\"Invalid regex in the remote configuration: 'Hello(?|!)'\")\n      })\n    })\n\n    describe('supported contexts', () => {\n      beforeEach(() => {\n        setCookie(COOKIE_NAME, 'first.second', ONE_MINUTE)\n      })\n\n      afterEach(() => {\n        deleteCookie(COOKIE_NAME)\n      })\n\n      it('should be resolved from the provided configuration', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            user: [\n              {\n                key: 'id',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'cookie',\n                  name: COOKIE_NAME,\n                  extractor: { rcSerializedType: 'regex', value: '(\\\\w+)\\\\.\\\\w+' },\n                },\n              },\n              {\n                key: 'bar',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'cookie',\n                  name: COOKIE_NAME,\n                  extractor: { rcSerializedType: 'regex', value: '\\\\w+\\\\.(\\\\w+)' },\n                },\n              },\n            ],\n          },\n          {}\n        )\n        expect(supportedContextManagers.user.getContext()).toEqual({\n          id: 'first',\n          bar: 'second',\n        })\n      })\n\n      it('unresolved property should be set to undefined', () => {\n        expectAppliedRemoteConfigurationToBe(\n          {\n            context: [\n              {\n                key: 'foo',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'cookie',\n                  name: 'missing-cookie',\n                },\n              },\n            ],\n          },\n          {}\n        )\n        expect(supportedContextManagers.context.getContext()).toEqual({\n          foo: undefined,\n        })\n      })\n    })\n\n    describe('metrics', () => {\n      it('should report resolution stats', () => {\n        setCookie(COOKIE_NAME, 'my-version', ONE_MINUTE)\n        root.foo = '123'\n        registerCleanupTask(() => {\n          deleteCookie(COOKIE_NAME)\n          delete root.foo\n        })\n\n        expectAppliedRemoteConfigurationToBe(\n          {\n            context: [\n              {\n                key: 'missing-cookie',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'cookie',\n                  name: 'missing-cookie',\n                },\n              },\n              {\n                key: 'existing-cookie',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'cookie',\n                  name: COOKIE_NAME,\n                },\n              },\n              {\n                key: 'existing-cookie2',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'cookie',\n                  name: COOKIE_NAME,\n                },\n              },\n              {\n                key: 'existing-js',\n                value: {\n                  rcSerializedType: 'dynamic',\n                  strategy: 'js',\n                  path: 'foo',\n                },\n              },\n            ],\n          },\n          {}\n        )\n        expect(metrics.get()).toEqual(\n          jasmine.objectContaining({\n            cookie: { success: 2, missing: 1 },\n            js: { success: 1 },\n          })\n        )\n      })\n    })\n  })\n\n  describe('buildEndpoint', () => {\n    it('should return the remote configuration endpoint', () => {\n      const remoteConfigurationId = '0e008b1b-8600-4709-9d1d-f4edcfdf5587'\n      expect(buildEndpoint({ site: INTAKE_SITE_US1, remoteConfigurationId } as RumInitConfiguration)).toEqual(\n        `https://sdk-configuration.browser-intake-datadoghq.com/v1/${remoteConfigurationId}.json`\n      )\n    })\n\n    it('should return the remote configuration proxy', () => {\n      expect(buildEndpoint({ remoteConfigurationProxy: '/config' } as RumInitConfiguration)).toEqual('/config')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/remoteConfiguration.ts",
    "content": "import type { createContextManager, Context } from '@datadog/browser-core'\nimport {\n  display,\n  buildEndpointHost,\n  mapValues,\n  getCookie,\n  addTelemetryMetrics,\n  TelemetryMetrics,\n  isIndexableObject,\n  fetch,\n} from '@datadog/browser-core'\nimport { extractRegexMatch } from '../extractRegexMatch'\nimport type { RumInitConfiguration } from './configuration'\nimport type { RumSdkConfig, DynamicOption, ContextItem } from './remoteConfiguration.types'\nimport { parseJsonPath } from './jsonPathParser'\n\nexport type RemoteConfiguration = RumSdkConfig\nexport type RumRemoteConfiguration = Exclude<RemoteConfiguration['rum'], undefined>\nconst REMOTE_CONFIGURATION_VERSION = 'v1'\nconst SUPPORTED_FIELDS: Array<keyof RumInitConfiguration> = [\n  'applicationId',\n  'service',\n  'env',\n  'version',\n  'sessionSampleRate',\n  'sessionReplaySampleRate',\n  'defaultPrivacyLevel',\n  'enablePrivacyForActionName',\n  'traceSampleRate',\n  'trackSessionAcrossSubdomains',\n  'allowedTracingUrls',\n  'allowedTrackingOrigins',\n]\n\n// type needed for switch on union\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ntype SerializedRegex = { rcSerializedType: 'regex'; value: string }\ntype SerializedOption = { rcSerializedType: 'string'; value: string } | SerializedRegex | DynamicOption\n\ninterface SupportedContextManagers {\n  user: ReturnType<typeof createContextManager>\n  context: ReturnType<typeof createContextManager>\n}\n\nexport interface RemoteConfigurationMetrics extends Context {\n  fetch: RemoteConfigurationMetricCounters\n  cookie?: RemoteConfigurationMetricCounters\n  dom?: RemoteConfigurationMetricCounters\n  js?: RemoteConfigurationMetricCounters\n  localStorage?: RemoteConfigurationMetricCounters\n}\n\ninterface RemoteConfigurationMetricCounters {\n  success?: number\n  missing?: number\n  failure?: number\n  [key: string]: number | undefined\n}\n\nexport async function fetchAndApplyRemoteConfiguration(\n  initConfiguration: RumInitConfiguration,\n  supportedContextManagers: SupportedContextManagers\n) {\n  let rumInitConfiguration: RumInitConfiguration | undefined\n  const metrics = initMetrics()\n  const fetchResult = await fetchRemoteConfiguration(initConfiguration)\n  if (!fetchResult.ok) {\n    metrics.increment('fetch', 'failure')\n    display.error(fetchResult.error)\n  } else {\n    metrics.increment('fetch', 'success')\n    rumInitConfiguration = applyRemoteConfiguration(\n      initConfiguration,\n      fetchResult.value,\n      supportedContextManagers,\n      metrics\n    )\n  }\n  // monitor-until: forever\n  addTelemetryMetrics(TelemetryMetrics.REMOTE_CONFIGURATION_METRIC_NAME, { metrics: metrics.get() })\n  return rumInitConfiguration\n}\n\nexport function applyRemoteConfiguration(\n  initConfiguration: RumInitConfiguration,\n  rumRemoteConfiguration: RumRemoteConfiguration & { [key: string]: unknown },\n  supportedContextManagers: SupportedContextManagers,\n  metrics: ReturnType<typeof initMetrics>\n): RumInitConfiguration {\n  // intents:\n  // - explicitly set each supported field to limit risk in case an attacker can create configurations\n  // - check the existence in the remote config to avoid clearing a provided init field\n  const appliedConfiguration = { ...initConfiguration } as RumInitConfiguration & { [key: string]: unknown }\n  SUPPORTED_FIELDS.forEach((option: string) => {\n    if (option in rumRemoteConfiguration) {\n      appliedConfiguration[option] = resolveConfigurationProperty(rumRemoteConfiguration[option])\n    }\n  })\n  ;(Object.keys(supportedContextManagers) as Array<keyof SupportedContextManagers>).forEach((context) => {\n    if (rumRemoteConfiguration[context] !== undefined) {\n      resolveContextProperty(supportedContextManagers[context], rumRemoteConfiguration[context])\n    }\n  })\n  return appliedConfiguration\n\n  // share context to access metrics\n\n  function resolveConfigurationProperty(property: unknown): unknown {\n    if (Array.isArray(property)) {\n      return property.map(resolveConfigurationProperty)\n    }\n    if (isIndexableObject(property)) {\n      if (isSerializedOption(property)) {\n        const type = property.rcSerializedType\n        switch (type) {\n          case 'string':\n            return property.value\n          case 'regex':\n            return resolveRegex(property.value)\n          case 'dynamic':\n            return resolveDynamicOption(property)\n          default:\n            display.error(`Unsupported remote configuration: \"rcSerializedType\": \"${type as string}\"`)\n            return\n        }\n      }\n      return mapValues(property, resolveConfigurationProperty)\n    }\n    return property\n  }\n\n  function resolveContextProperty(\n    contextManager: ReturnType<typeof createContextManager>,\n    contextItems: ContextItem[]\n  ) {\n    contextItems.forEach(({ key, value }) => {\n      contextManager.setContextProperty(key, resolveConfigurationProperty(value))\n    })\n  }\n\n  function resolveDynamicOption(property: DynamicOption) {\n    const strategy = property.strategy\n    let resolvedValue: unknown\n    switch (strategy) {\n      case 'cookie':\n        resolvedValue = resolveCookieValue(property)\n        break\n      case 'dom':\n        resolvedValue = resolveDomValue(property)\n        break\n      case 'js':\n        resolvedValue = resolveJsValue(property)\n        break\n      case 'localStorage':\n        resolvedValue = resolveLocalStorageValue(property)\n        break\n      default:\n        display.error(`Unsupported remote configuration: \"strategy\": \"${strategy as string}\"`)\n        return\n    }\n    const extractor = property.extractor\n    if (extractor !== undefined && typeof resolvedValue === 'string') {\n      return extractValue(extractor, resolvedValue)\n    }\n    return resolvedValue\n  }\n\n  function resolveCookieValue({ name }: { name: string }) {\n    const value = getCookie(name)\n    metrics.increment('cookie', value !== undefined ? 'success' : 'missing')\n    return value\n  }\n\n  function resolveLocalStorageValue({ key }: { key: string }) {\n    let value: string | null\n    try {\n      value = localStorage.getItem(key)\n    } catch {\n      metrics.increment('localStorage', 'failure')\n      return\n    }\n    metrics.increment('localStorage', value !== null ? 'success' : 'missing')\n    return value ?? undefined\n  }\n\n  function resolveDomValue({ selector, attribute }: { selector: string; attribute?: string }) {\n    let element: Element | null\n    try {\n      element = document.querySelector(selector)\n    } catch {\n      display.error(`Invalid selector in the remote configuration: '${selector}'`)\n      metrics.increment('dom', 'failure')\n      return\n    }\n    if (!element) {\n      metrics.increment('dom', 'missing')\n      return\n    }\n    if (isForbidden(element, attribute)) {\n      display.error(`Forbidden element selected by the remote configuration: '${selector}'`)\n      metrics.increment('dom', 'failure')\n      return\n    }\n    const domValue = attribute !== undefined ? element.getAttribute(attribute) : element.textContent\n    if (domValue === null) {\n      metrics.increment('dom', 'missing')\n      return\n    }\n    metrics.increment('dom', 'success')\n    return domValue\n  }\n\n  function isForbidden(element: Element, attribute: string | undefined) {\n    return element.getAttribute('type') === 'password' && attribute === 'value'\n  }\n\n  function resolveJsValue({ path }: { path: string }): unknown {\n    let current = window as unknown as { [key: string]: unknown }\n    const pathParts = parseJsonPath(path)\n    if (pathParts.length === 0) {\n      display.error(`Invalid JSON path in the remote configuration: '${path}'`)\n      metrics.increment('js', 'failure')\n      return\n    }\n    for (const pathPart of pathParts) {\n      if (!(pathPart in current)) {\n        metrics.increment('js', 'missing')\n        return\n      }\n      try {\n        current = current[pathPart] as { [key: string]: unknown }\n      } catch (e) {\n        display.error(`Error accessing: '${path}'`, e)\n        metrics.increment('js', 'failure')\n        return\n      }\n    }\n    metrics.increment('js', 'success')\n    return current\n  }\n}\n\nexport function initMetrics() {\n  const metrics: RemoteConfigurationMetrics = { fetch: {} }\n  return {\n    get: () => metrics,\n    increment: (metricName: 'fetch' | DynamicOption['strategy'], type: keyof RemoteConfigurationMetricCounters) => {\n      if (!metrics[metricName]) {\n        metrics[metricName] = {}\n      }\n      if (!metrics[metricName][type]) {\n        metrics[metricName][type] = 0\n      }\n      metrics[metricName][type] = metrics[metricName][type] + 1\n    },\n  }\n}\n\nfunction isSerializedOption(value: object): value is SerializedOption {\n  return 'rcSerializedType' in value\n}\n\nfunction resolveRegex(pattern: string): RegExp | undefined {\n  try {\n    return new RegExp(pattern)\n  } catch {\n    display.error(`Invalid regex in the remote configuration: '${pattern}'`)\n  }\n}\n\nfunction extractValue(extractor: SerializedRegex, candidate: string) {\n  const resolvedExtractor = resolveRegex(extractor.value)\n  if (resolvedExtractor === undefined) {\n    return\n  }\n  return extractRegexMatch(candidate, resolvedExtractor)\n}\n\ntype FetchRemoteConfigurationResult = { ok: true; value: RumRemoteConfiguration } | { ok: false; error: Error }\n\nexport async function fetchRemoteConfiguration(\n  configuration: RumInitConfiguration\n): Promise<FetchRemoteConfigurationResult> {\n  let response: Response | undefined\n  try {\n    response = await fetch(buildEndpoint(configuration))\n  } catch {\n    response = undefined\n  }\n  if (!response || !response.ok) {\n    return {\n      ok: false,\n      error: new Error('Error fetching the remote configuration.'),\n    }\n  }\n  const remoteConfiguration: RemoteConfiguration = await response.json()\n  if (remoteConfiguration.rum) {\n    return {\n      ok: true,\n      value: remoteConfiguration.rum,\n    }\n  }\n  return {\n    ok: false,\n    error: new Error('No remote configuration for RUM.'),\n  }\n}\n\nexport function buildEndpoint(configuration: RumInitConfiguration) {\n  if (configuration.remoteConfigurationProxy) {\n    return configuration.remoteConfigurationProxy\n  }\n  return `https://sdk-configuration.${buildEndpointHost('rum', configuration)}/${REMOTE_CONFIGURATION_VERSION}/${encodeURIComponent(configuration.remoteConfigurationId!)}.json`\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/configuration/remoteConfiguration.types.ts",
    "content": "/**\n * DO NOT MODIFY IT BY HAND. Run `yarn json-schemas:sync` instead.\n */\n\nexport type DynamicOption =\n  | {\n      rcSerializedType: 'dynamic'\n      strategy: 'js'\n      path: string\n      extractor?: SerializedRegex\n      [k: string]: unknown\n    }\n  | {\n      rcSerializedType: 'dynamic'\n      strategy: 'cookie'\n      name: string\n      extractor?: SerializedRegex\n      [k: string]: unknown\n    }\n  | {\n      rcSerializedType: 'dynamic'\n      strategy: 'dom'\n      selector: string\n      attribute?: string\n      extractor?: SerializedRegex\n      [k: string]: unknown\n    }\n  | {\n      rcSerializedType: 'dynamic'\n      strategy: 'localStorage'\n      key: string\n      extractor?: SerializedRegex\n      [k: string]: unknown\n    }\n\n/**\n * RUM Browser & Mobile SDKs Remote Configuration properties\n */\nexport interface RumSdkConfig {\n  /**\n   * RUM feature Remote Configuration properties\n   */\n  rum?: {\n    /**\n     * UUID of the application\n     */\n    applicationId: string\n    /**\n     * The service name for this application\n     */\n    service?: string\n    /**\n     * The environment for this application\n     */\n    env?: string\n    /**\n     * The version for this application\n     */\n    version?:\n      | {\n          rcSerializedType: 'dynamic'\n          strategy: 'js'\n          path: string\n          extractor?: SerializedRegex\n          [k: string]: unknown\n        }\n      | {\n          rcSerializedType: 'dynamic'\n          strategy: 'cookie'\n          name: string\n          extractor?: SerializedRegex\n          [k: string]: unknown\n        }\n      | {\n          rcSerializedType: 'dynamic'\n          strategy: 'dom'\n          selector: string\n          attribute?: string\n          extractor?: SerializedRegex\n          [k: string]: unknown\n        }\n      | {\n          rcSerializedType: 'dynamic'\n          strategy: 'localStorage'\n          key: string\n          extractor?: SerializedRegex\n          [k: string]: unknown\n        }\n    /**\n     * The percentage of sessions tracked\n     */\n    sessionSampleRate?: number\n    /**\n     * The percentage of sessions with RUM & Session Replay pricing tracked\n     */\n    sessionReplaySampleRate?: number\n    /**\n     * Session replay default privacy level\n     */\n    defaultPrivacyLevel?: string\n    /**\n     * Privacy control for action name\n     */\n    enablePrivacyForActionName?: boolean\n    /**\n     * URLs where tracing is allowed\n     */\n    allowedTracingUrls?: {\n      match: MatchOption\n      /**\n       * List of propagator types\n       */\n      propagatorTypes?: ('datadog' | 'b3' | 'b3multi' | 'tracecontext')[] | null\n    }[]\n    /**\n     * Origins where tracking is allowed\n     */\n    allowedTrackingOrigins?: MatchOption[]\n    /**\n     * The percentage of traces sampled\n     */\n    traceSampleRate?: number\n    /**\n     * Whether to track sessions across subdomains\n     */\n    trackSessionAcrossSubdomains?: boolean\n    /**\n     * Function to define user information\n     */\n    user?: ContextItem[]\n    /**\n     * Function to define global context\n     */\n    context?: ContextItem[]\n  }\n}\nexport interface SerializedRegex {\n  /**\n   * Remote config serialized type for regex extraction\n   */\n  rcSerializedType: 'regex'\n  /**\n   * Regex pattern for value extraction\n   */\n  value: string\n}\nexport interface MatchOption {\n  /**\n   * Remote config serialized type of match\n   */\n  rcSerializedType: 'string' | 'regex'\n  /**\n   * Match value\n   */\n  value: string\n}\nexport interface ContextItem {\n  key: string\n  value: DynamicOption\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/ciVisibilityContext.spec.ts",
    "content": "import type { Configuration, RelativeTime } from '@datadog/browser-core'\nimport { HookNames, Observable } from '@datadog/browser-core'\nimport { mockCiVisibilityValues } from '../../../test'\nimport type { CookieObservable } from '../../browser/cookieObservable'\nimport { SessionType } from '../rumSessionManager'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startCiVisibilityContext } from './ciVisibilityContext'\n\ndescribe('startCiVisibilityContext', () => {\n  let cookieObservable: CookieObservable\n  let stopCiVisibility: () => void\n  let hooks: Hooks\n\n  beforeEach(() => {\n    cookieObservable = new Observable()\n    hooks = createHooks()\n  })\n\n  afterEach(() => {\n    stopCiVisibility?.()\n  })\n\n  describe('assemble hook', () => {\n    it('should set ci visibility context defined by Cypress global variables', () => {\n      mockCiVisibilityValues('trace_id_value')\n      ;({ stop: stopCiVisibility } = startCiVisibilityContext({} as Configuration, hooks, cookieObservable))\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.CI_TEST,\n        },\n        ci_test: {\n          test_execution_id: 'trace_id_value',\n        },\n      })\n    })\n\n    it('should add the ci visibility context defined by global cookie', () => {\n      mockCiVisibilityValues('trace_id_value', 'cookies')\n      ;({ stop: stopCiVisibility } = startCiVisibilityContext({} as Configuration, hooks, cookieObservable))\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.CI_TEST,\n        },\n        ci_test: {\n          test_execution_id: 'trace_id_value',\n        },\n      })\n    })\n\n    it('should update the ci visibility context when global cookie is updated', () => {\n      mockCiVisibilityValues('trace_id_value', 'cookies')\n      ;({ stop: stopCiVisibility } = startCiVisibilityContext({} as Configuration, hooks, cookieObservable))\n      cookieObservable.notify('trace_id_value_updated')\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.CI_TEST,\n        },\n        ci_test: {\n          test_execution_id: 'trace_id_value_updated',\n        },\n      })\n    })\n\n    it('should not set ci visibility context if the Cypress global variable is undefined', () => {\n      mockCiVisibilityValues(undefined)\n      ;({ stop: stopCiVisibility } = startCiVisibilityContext({} as Configuration, hooks, cookieObservable))\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n\n    it('should not set ci visibility context if it is not a string', () => {\n      mockCiVisibilityValues({ key: 'value' })\n      ;({ stop: stopCiVisibility } = startCiVisibilityContext({} as Configuration, hooks, cookieObservable))\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/ciVisibilityContext.ts",
    "content": "import { getInitCookie, HookNames, SKIPPED } from '@datadog/browser-core'\nimport type { Configuration } from '@datadog/browser-core'\nimport { createCookieObservable } from '../../browser/cookieObservable'\nimport { SessionType } from '../rumSessionManager'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\nexport const CI_VISIBILITY_TEST_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id'\n\nexport interface CiTestWindow extends Window {\n  Cypress?: {\n    env: (key: string) => string | undefined\n  }\n}\n\nexport type CiVisibilityContext = ReturnType<typeof startCiVisibilityContext>\n\nexport function startCiVisibilityContext(\n  configuration: Configuration,\n  hooks: Hooks,\n  cookieObservable = createCookieObservable(configuration, CI_VISIBILITY_TEST_ID_COOKIE_NAME)\n) {\n  let testExecutionId =\n    getInitCookie(CI_VISIBILITY_TEST_ID_COOKIE_NAME) || (window as CiTestWindow).Cypress?.env('traceId')\n\n  const cookieObservableSubscription = cookieObservable.subscribe((value) => {\n    testExecutionId = value\n  })\n\n  hooks.register(HookNames.Assemble, ({ eventType }): DefaultRumEventAttributes | SKIPPED => {\n    if (typeof testExecutionId !== 'string') {\n      return SKIPPED\n    }\n\n    return {\n      type: eventType,\n      session: {\n        type: SessionType.CI_TEST,\n      },\n      ci_test: {\n        test_execution_id: testExecutionId,\n      },\n    }\n  })\n\n  return {\n    stop: () => {\n      cookieObservableSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/connectivityContext.spec.ts",
    "content": "import { setNavigatorOnLine, setNavigatorConnection } from '@datadog/browser-core/test'\nimport { HookNames } from '@datadog/browser-core'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startConnectivityContext } from './connectivityContext'\n\ndescribe('startConnectivityContext', () => {\n  describe('assemble hook', () => {\n    let hooks: Hooks\n\n    beforeEach(() => {\n      hooks = createHooks()\n    })\n\n    it('should set ci visibility context defined by Cypress global variables', () => {\n      startConnectivityContext(hooks)\n      setNavigatorOnLine(true)\n      setNavigatorConnection({ effectiveType: '2g' })\n      const event = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(event).toEqual({\n        type: 'view',\n        connectivity: {\n          status: 'connected',\n          effective_type: '2g',\n          interfaces: undefined,\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/connectivityContext.ts",
    "content": "import { getConnectivity, HookNames } from '@datadog/browser-core'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\nexport function startConnectivityContext(hooks: Hooks) {\n  hooks.register(\n    HookNames.Assemble,\n    ({ eventType }): DefaultRumEventAttributes => ({\n      type: eventType,\n      connectivity: getConnectivity(),\n    })\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/defaultContext.spec.ts",
    "content": "import { mockClock, mockEventBridge } from '@datadog/browser-core/test'\nimport { HookNames, timeStampNow } from '@datadog/browser-core'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport { mockRumConfiguration } from '../../../test'\nimport type { AssembleHookParams, DefaultRumEventAttributes, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startDefaultContext } from './defaultContext'\n\ndescribe('startDefaultContext', () => {\n  let hooks: Hooks\n\n  beforeEach(() => {\n    mockClock()\n    hooks = createHooks()\n  })\n\n  describe('assemble hook', () => {\n    it('should set the rum default context', () => {\n      startDefaultContext(hooks, mockRumConfiguration({ applicationId: '1' }), 'rum')\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        application: {\n          id: '1',\n        },\n        date: timeStampNow(),\n        source: 'browser',\n        _dd: jasmine.objectContaining({\n          format_version: 2,\n          drift: jasmine.any(Number),\n        }),\n      })\n    })\n\n    it('should set the browser sdk version if event bridge detected', () => {\n      startDefaultContext(hooks, mockRumConfiguration(), 'rum')\n      const eventWithoutEventBridge = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams) as DefaultRumEventAttributes\n\n      mockEventBridge()\n\n      const eventWithEventBridge = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams) as DefaultRumEventAttributes\n\n      expect(eventWithEventBridge._dd!.browser_sdk_version).toBeDefined()\n      expect(eventWithoutEventBridge._dd!.browser_sdk_version).toBeUndefined()\n    })\n\n    it('should set the configured sample rates', () => {\n      startDefaultContext(\n        hooks,\n        mockRumConfiguration({ sessionSampleRate: 10, sessionReplaySampleRate: 20, traceSampleRate: 30 }),\n        'rum'\n      )\n\n      const event = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams) as DefaultRumEventAttributes\n\n      expect(event._dd!.configuration!.session_sample_rate).toBe(10)\n      expect(event._dd!.configuration!.session_replay_sample_rate).toBe(20)\n      expect(event._dd!.configuration!.trace_sample_rate).toBe(30)\n      expect(event._dd!.configuration!.profiling_sample_rate).toBe(0)\n      expect(event._dd!.sdk_name).toBe('rum')\n    })\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should set the application id', () => {\n      startDefaultContext(hooks, mockRumConfiguration(), 'rum')\n\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      }) as DefaultTelemetryEventAttributes\n\n      expect(telemetryEventAttributes.application?.id).toEqual('appId')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/defaultContext.ts",
    "content": "import { canUseEventBridge, currentDrift, HookNames, round, timeStampNow } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\nimport type { DefaultRumEventAttributes, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\n\n// replaced at build time\ndeclare const __BUILD_ENV__SDK_VERSION__: string\n\nexport type SdkName = 'rum' | 'rum-slim' | 'rum-synthetics'\n\nexport function startDefaultContext(hooks: Hooks, configuration: RumConfiguration, sdkName: SdkName | undefined) {\n  hooks.register(HookNames.Assemble, ({ eventType }): DefaultRumEventAttributes => {\n    const source = configuration.source\n\n    return {\n      type: eventType,\n      _dd: {\n        format_version: 2,\n        drift: currentDrift(),\n        configuration: {\n          session_sample_rate: round(configuration.sessionSampleRate, 3),\n          session_replay_sample_rate: round(configuration.sessionReplaySampleRate, 3),\n          profiling_sample_rate: round(configuration.profilingSampleRate, 3),\n          trace_sample_rate: round(configuration.traceSampleRate, 3),\n          beta_encode_cookie_options: configuration.betaEncodeCookieOptions,\n        },\n        browser_sdk_version: canUseEventBridge() ? __BUILD_ENV__SDK_VERSION__ : undefined,\n        sdk_name: sdkName,\n      },\n      application: {\n        id: configuration.applicationId,\n      },\n      date: timeStampNow(),\n      source,\n    }\n  })\n\n  hooks.register(\n    HookNames.AssembleTelemetry,\n    (): DefaultTelemetryEventAttributes => ({\n      application: { id: configuration.applicationId },\n    })\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/displayContext.spec.ts",
    "content": "import { HookNames } from '@datadog/browser-core'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport { mockRumConfiguration } from '../../../test'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport type { DisplayContext } from './displayContext'\nimport { startDisplayContext } from './displayContext'\n\ndescribe('displayContext', () => {\n  let displayContext: DisplayContext\n  let requestAnimationFrameSpy: jasmine.Spy\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n    requestAnimationFrameSpy = spyOn(window, 'requestAnimationFrame').and.callFake((callback) => {\n      callback(1)\n      return 1\n    })\n  })\n\n  afterEach(() => {\n    displayContext.stop()\n  })\n\n  describe('assemble hook', () => {\n    it('should set the display context', () => {\n      displayContext = startDisplayContext(hooks, mockRumConfiguration())\n\n      const event = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n      expect(requestAnimationFrameSpy).toHaveBeenCalledTimes(1)\n\n      expect(event).toEqual({\n        type: 'view',\n        display: {\n          viewport: {\n            width: jasmine.any(Number),\n            height: jasmine.any(Number),\n          },\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/displayContext.ts",
    "content": "import { HookNames, monitor } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\nimport type { ViewportDimension } from '../../browser/viewportObservable'\nimport { getViewportDimension, initViewportObservable } from '../../browser/viewportObservable'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\nexport type DisplayContext = ReturnType<typeof startDisplayContext>\n\nexport function startDisplayContext(hooks: Hooks, configuration: RumConfiguration) {\n  let viewport: ViewportDimension | undefined\n  // Use requestAnimationFrame to delay the calculation of viewport dimensions until after SDK initialization, preventing long tasks.\n  const animationFrameId = requestAnimationFrame(\n    monitor(() => {\n      viewport = getViewportDimension()\n    })\n  )\n\n  const unsubscribeViewport = initViewportObservable(configuration).subscribe((viewportDimension) => {\n    viewport = viewportDimension\n  }).unsubscribe\n\n  hooks.register(\n    HookNames.Assemble,\n    ({ eventType }): DefaultRumEventAttributes => ({\n      type: eventType,\n      display: viewport ? { viewport } : undefined,\n    })\n  )\n\n  return {\n    stop: () => {\n      unsubscribeViewport()\n      if (animationFrameId) {\n        cancelAnimationFrame(animationFrameId)\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/featureFlagContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { HookNames, relativeToClocks } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { ViewCreatedEvent, ViewEndedEvent } from '../view/trackViews'\nimport type { RumConfiguration } from '../configuration'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport type { FeatureFlagContexts } from './featureFlagContext'\nimport { startFeatureFlagContexts } from './featureFlagContext'\n\ndescribe('featureFlagContexts', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let featureFlagContexts: FeatureFlagContexts\n  let hooks: Hooks\n  let trackFeatureFlagsForEvents: any[]\n\n  beforeEach(() => {\n    clock = mockClock()\n    hooks = createHooks()\n    trackFeatureFlagsForEvents = []\n    featureFlagContexts = startFeatureFlagContexts(lifeCycle, hooks, {\n      trackFeatureFlagsForEvents,\n    } as unknown as RumConfiguration)\n  })\n\n  describe('assemble hook', () => {\n    it('should add feature flag evaluations on VIEW and ERROR by default ', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(0 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      featureFlagContexts.addFeatureFlagEvaluation('feature', 'foo')\n\n      const defaultViewAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n      const defaultErrorAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'error',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultViewAttributes).toEqual({\n        type: 'view',\n        feature_flags: {\n          feature: 'foo',\n        },\n      })\n\n      expect(defaultErrorAttributes).toEqual({\n        type: 'error',\n        feature_flags: {\n          feature: 'foo',\n        },\n      })\n    })\n    ;[RumEventType.VITAL, RumEventType.ACTION, RumEventType.LONG_TASK, RumEventType.RESOURCE].forEach((eventType) => {\n      it(`should add feature flag evaluations on ${eventType} when specified in trackFeatureFlagsForEvents`, () => {\n        trackFeatureFlagsForEvents.push(eventType)\n        lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n          startClocks: relativeToClocks(0 as RelativeTime),\n        } as ViewCreatedEvent)\n\n        featureFlagContexts.addFeatureFlagEvaluation('feature', 'foo')\n\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType,\n          startTime: 0 as RelativeTime,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({\n          type: eventType,\n          feature_flags: {\n            feature: 'foo',\n          },\n        })\n      })\n    })\n\n    it('should add feature flag evaluations of any type', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(0 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      featureFlagContexts.addFeatureFlagEvaluation('feature', 'foo')\n      featureFlagContexts.addFeatureFlagEvaluation('feature2', 2)\n      featureFlagContexts.addFeatureFlagEvaluation('feature3', true)\n      featureFlagContexts.addFeatureFlagEvaluation('feature4', { foo: 'bar' })\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        feature_flags: {\n          feature: 'foo',\n          feature2: 2,\n          feature3: true,\n          feature4: { foo: 'bar' },\n        },\n      })\n    })\n\n    it('should add feature flag evaluations corresponding to the view start time', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(0 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      clock.tick(10)\n      featureFlagContexts.addFeatureFlagEvaluation('feature', 'one')\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, {\n        endClocks: relativeToClocks(10 as RelativeTime),\n      } as ViewEndedEvent)\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(10 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      clock.tick(10)\n      featureFlagContexts.addFeatureFlagEvaluation('feature', 'two')\n\n      const defaultEventOneAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 5 as RelativeTime,\n      } as AssembleHookParams)\n      const defaultEventTwoAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 15 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultEventOneAttributes).toEqual({ type: 'view', feature_flags: { feature: 'one' } })\n      expect(defaultEventTwoAttributes).toEqual({ type: 'view', feature_flags: { feature: 'two' } })\n    })\n\n    /**\n     * It could happen if there is an event happening just between view end and view creation\n     * (which seems unlikely) and this event would anyway be rejected by lack of view id\n     */\n    it('should not add feature flag evaluations when no current view', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(0 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n\n    it('should replace existing feature flag evaluations for the current view', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(0 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      featureFlagContexts.addFeatureFlagEvaluation('feature', 'foo')\n      featureFlagContexts.addFeatureFlagEvaluation('feature2', 'baz')\n      featureFlagContexts.addFeatureFlagEvaluation('feature', 'bar')\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({ type: 'view', feature_flags: { feature: 'bar', feature2: 'baz' } })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/featureFlagContext.ts",
    "content": "import type { ContextValue, Context } from '@datadog/browser-core'\nimport { HookNames, SESSION_TIME_OUT_DELAY, SKIPPED, createValueHistory, isEmptyObject } from '@datadog/browser-core'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { RumConfiguration } from '../configuration'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\nexport const FEATURE_FLAG_CONTEXT_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY\nexport const BYTES_COMPUTATION_THROTTLING_DELAY = 200\n\nexport type FeatureFlagContext = Context\n\nexport interface FeatureFlagContexts {\n  addFeatureFlagEvaluation: (key: string, value: ContextValue) => void\n}\n\n/**\n * Start feature flag contexts\n *\n * Feature flag contexts follow the life of views.\n * A new context is added when a view is created and ended when the view is ended\n *\n * Note: we choose not to add a new context at each evaluation to save memory\n */\nexport function startFeatureFlagContexts(\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  configuration: RumConfiguration\n): FeatureFlagContexts {\n  const featureFlagContexts = createValueHistory<FeatureFlagContext>({\n    expireDelay: FEATURE_FLAG_CONTEXT_TIME_OUT_DELAY,\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.BEFORE_VIEW_CREATED, ({ startClocks }) => {\n    featureFlagContexts.add({}, startClocks.relative)\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.AFTER_VIEW_ENDED, ({ endClocks }) => {\n    featureFlagContexts.closeActive(endClocks.relative)\n  })\n\n  hooks.register(HookNames.Assemble, ({ startTime, eventType }): DefaultRumEventAttributes | SKIPPED => {\n    const trackFeatureFlagsForEvents = (configuration.trackFeatureFlagsForEvents as RumEventType[]).concat([\n      RumEventType.VIEW,\n      RumEventType.ERROR,\n    ])\n    if (!trackFeatureFlagsForEvents.includes(eventType as RumEventType)) {\n      return SKIPPED\n    }\n\n    const featureFlagContext = featureFlagContexts.find(startTime)\n    if (!featureFlagContext || isEmptyObject(featureFlagContext)) {\n      return SKIPPED\n    }\n\n    return {\n      type: eventType,\n      feature_flags: featureFlagContext,\n    }\n  })\n\n  return {\n    addFeatureFlagEvaluation: (key: string, value: ContextValue) => {\n      const currentContext = featureFlagContexts.find()\n      if (currentContext) {\n        currentContext[key] = value\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/internalContext.spec.ts",
    "content": "import { noop, type RelativeTime } from '@datadog/browser-core'\nimport { buildLocation } from '@datadog/browser-core/test'\nimport { createRumSessionManagerMock } from '../../../test'\nimport type { RumSessionManager } from '../rumSessionManager'\nimport type { ActionContexts } from '../action/actionCollection'\nimport { startInternalContext } from './internalContext'\nimport type { ViewHistory } from './viewHistory'\nimport type { UrlContexts } from './urlContexts'\n\ndescribe('internal context', () => {\n  let findUrlSpy: jasmine.Spy<UrlContexts['findUrl']>\n  let findSessionSpy: jasmine.Spy<RumSessionManager['findTrackedSession']>\n  let fakeLocation: Location\n  let viewHistory: ViewHistory\n  let actionContexts: ActionContexts\n\n  function setupInternalContext(sessionManager: RumSessionManager) {\n    viewHistory = {\n      findView: jasmine.createSpy('findView').and.returnValue({\n        id: 'abcde',\n        name: 'foo',\n      }),\n      stop: noop,\n    }\n\n    actionContexts = {\n      findActionId: jasmine.createSpy('findActionId').and.returnValue('7890'),\n    }\n\n    fakeLocation = buildLocation('/foo')\n\n    const urlContexts: UrlContexts = {\n      findUrl: () => ({\n        url: fakeLocation.href,\n        referrer: document.referrer,\n      }),\n      stop: noop,\n    }\n    findSessionSpy = spyOn(sessionManager, 'findTrackedSession').and.callThrough()\n    findUrlSpy = spyOn(urlContexts, 'findUrl').and.callThrough()\n\n    return startInternalContext('appId', sessionManager, viewHistory, actionContexts, urlContexts)\n  }\n\n  it('should return current internal context', () => {\n    const sessionManager = createRumSessionManagerMock().setId('456')\n    const internalContext = setupInternalContext(sessionManager)\n\n    expect(internalContext.get()).toEqual({\n      application_id: 'appId',\n      session_id: '456',\n      user_action: {\n        id: '7890',\n      },\n      view: {\n        id: 'abcde',\n        name: 'foo',\n        referrer: document.referrer,\n        url: fakeLocation.href,\n      },\n    })\n  })\n\n  it(\"should return undefined if the session isn't tracked\", () => {\n    const sessionManager = createRumSessionManagerMock().setNotTracked()\n    const internalContext = setupInternalContext(sessionManager)\n    expect(internalContext.get()).toEqual(undefined)\n  })\n\n  it(\"should return internal context corresponding to 'startTime'\", () => {\n    const sessionManager = createRumSessionManagerMock().setId('456')\n    const internalContext = setupInternalContext(sessionManager)\n\n    internalContext.get(123)\n\n    expect(viewHistory.findView).toHaveBeenCalledWith(123 as RelativeTime)\n    expect(actionContexts.findActionId).toHaveBeenCalledWith(123 as RelativeTime)\n    expect(findUrlSpy).toHaveBeenCalledWith(123 as RelativeTime)\n    expect(findSessionSpy).toHaveBeenCalledWith(123 as RelativeTime)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/internalContext.ts",
    "content": "import type { RelativeTime, RumInternalContext } from '@datadog/browser-core'\nimport type { RumSessionManager } from '../rumSessionManager'\nimport type { ActionContexts } from '../action/actionCollection'\nimport type { ViewHistory } from './viewHistory'\nimport type { UrlContexts } from './urlContexts'\n\n/**\n * Internal context keep returning v1 format\n * to not break compatibility with logs data format\n */\nexport function startInternalContext(\n  applicationId: string,\n  sessionManager: RumSessionManager,\n  viewHistory: ViewHistory,\n  actionContexts: ActionContexts,\n  urlContexts: UrlContexts\n) {\n  return {\n    get: (startTime?: number): RumInternalContext | undefined => {\n      const viewContext = viewHistory.findView(startTime as RelativeTime)\n      const urlContext = urlContexts.findUrl(startTime as RelativeTime)\n      const session = sessionManager.findTrackedSession(startTime as RelativeTime)\n      if (session && viewContext && urlContext) {\n        const actionId = actionContexts.findActionId(startTime as RelativeTime)\n        return {\n          application_id: applicationId,\n          session_id: session.id,\n          user_action: actionId ? { id: actionId } : undefined,\n          view: { id: viewContext.id, name: viewContext.name, referrer: urlContext.referrer, url: urlContext.url },\n        }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/pageStateHistory.spec.ts",
    "content": "import type { ServerDuration, Duration, RelativeTime } from '@datadog/browser-core'\nimport { HookNames } from '@datadog/browser-core'\nimport type { Clock } from '../../../../core/test'\nimport { mockClock, registerCleanupTask } from '../../../../core/test'\nimport { createPerformanceEntry, mockPerformanceObserver, mockRumConfiguration } from '../../../test'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport * as performanceObservable from '../../browser/performanceObservable'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport type { PageStateHistory } from './pageStateHistory'\nimport { PageState, startPageStateHistory } from './pageStateHistory'\n\ndescribe('pageStateHistory', () => {\n  let clock: Clock\n  let hooks: Hooks\n  const configuration = mockRumConfiguration()\n\n  beforeEach(() => {\n    clock = mockClock()\n    hooks = createHooks()\n  })\n\n  describe('wasInPageStateDuringPeriod', () => {\n    let pageStateHistory: PageStateHistory\n\n    beforeEach(() => {\n      mockPerformanceObserver()\n      pageStateHistory = startPageStateHistory(hooks, configuration)\n      registerCleanupTask(pageStateHistory.stop)\n    })\n\n    it('should return true if the page was in the given state during the given period', () => {\n      pageStateHistory.addPageState(PageState.ACTIVE)\n      clock.tick(10)\n      pageStateHistory.addPageState(PageState.PASSIVE)\n      clock.tick(10)\n      pageStateHistory.addPageState(PageState.HIDDEN)\n      clock.tick(10)\n\n      expect(pageStateHistory.wasInPageStateDuringPeriod(PageState.PASSIVE, clock.relative(0), 30 as Duration)).toEqual(\n        true\n      )\n    })\n\n    it('should return false if the page was not in the given state during the given period', () => {\n      pageStateHistory.addPageState(PageState.ACTIVE)\n      clock.tick(10)\n      pageStateHistory.addPageState(PageState.PASSIVE)\n      clock.tick(10)\n      pageStateHistory.addPageState(PageState.HIDDEN)\n      clock.tick(10)\n\n      expect(pageStateHistory.wasInPageStateDuringPeriod(PageState.FROZEN, clock.relative(0), 30 as Duration)).toEqual(\n        false\n      )\n    })\n\n    it('should return false if there was no page state during the given period', () => {\n      // pageStateHistory is initialized with the current page state\n      // look for a period before the initialization to make sure there is no page state\n      expect(\n        pageStateHistory.wasInPageStateDuringPeriod(PageState.ACTIVE, clock.relative(-40), 30 as Duration)\n      ).toEqual(false)\n    })\n  })\n\n  describe('assemble hook', () => {\n    describe('for view events', () => {\n      let pageStateHistory: PageStateHistory\n\n      beforeEach(() => {\n        mockPerformanceObserver()\n        pageStateHistory = startPageStateHistory(hooks, configuration)\n        registerCleanupTask(pageStateHistory.stop)\n      })\n\n      it('should add the correct page states for the given time period', () => {\n        pageStateHistory.addPageState(PageState.ACTIVE)\n\n        clock.tick(10)\n        pageStateHistory.addPageState(PageState.PASSIVE)\n\n        clock.tick(10)\n        pageStateHistory.addPageState(PageState.HIDDEN)\n\n        clock.tick(10)\n        pageStateHistory.addPageState(PageState.FROZEN)\n\n        clock.tick(10)\n        pageStateHistory.addPageState(PageState.TERMINATED)\n\n        /*\n      page state time    0     10    20    30    40\n      event time                  15<-------->35\n      */\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType: 'view',\n          startTime: clock.relative(15),\n          duration: 20 as Duration,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({\n          type: 'view',\n          _dd: {\n            page_states: [\n              {\n                state: PageState.PASSIVE,\n                start: -5000000 as ServerDuration,\n              },\n              {\n                state: PageState.HIDDEN,\n                start: 5000000 as ServerDuration,\n              },\n              {\n                state: PageState.FROZEN,\n                start: 15000000 as ServerDuration,\n              },\n            ],\n          },\n        })\n      })\n\n      it('should add the current state when starting', () => {\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType: 'view',\n          startTime: clock.relative(0),\n          duration: 10 as Duration,\n        } as AssembleHookParams)\n        expect(defaultRumEventAttributes).toEqual({\n          type: 'view',\n          _dd: { page_states: jasmine.any(Array) },\n        })\n      })\n\n      it('should not add the page state if the time period is out of history bounds', () => {\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType: 'view',\n          startTime: clock.relative(-10),\n          duration: 0 as Duration,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({\n          type: 'view',\n          _dd: { page_states: undefined },\n        })\n      })\n\n      it('should limit the number of page states added', () => {\n        pageStateHistory.stop()\n        const maxPageStateEntriesSelectable = 1\n        pageStateHistory = startPageStateHistory(hooks, configuration, maxPageStateEntriesSelectable)\n        registerCleanupTask(pageStateHistory.stop)\n\n        pageStateHistory.addPageState(PageState.ACTIVE)\n        clock.tick(10)\n        pageStateHistory.addPageState(PageState.PASSIVE)\n\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType: 'view',\n          startTime: clock.relative(0),\n          duration: Infinity as Duration,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({\n          type: 'view',\n          _dd: {\n            page_states: [\n              {\n                state: PageState.PASSIVE,\n                start: 0 as ServerDuration,\n              },\n            ],\n          },\n        })\n      })\n    })\n  })\n  ;[RumEventType.ACTION, RumEventType.ERROR].forEach((eventType) => {\n    describe(`for ${eventType} events`, () => {\n      let pageStateHistory: PageStateHistory\n\n      beforeEach(() => {\n        mockPerformanceObserver()\n        pageStateHistory = startPageStateHistory(hooks, configuration)\n        registerCleanupTask(pageStateHistory.stop)\n      })\n\n      it('should add in_foreground: true when the page is active', () => {\n        pageStateHistory.addPageState(PageState.ACTIVE)\n\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType,\n          startTime: clock.relative(0),\n          duration: 0 as Duration,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({\n          type: eventType,\n          view: { in_foreground: true },\n        })\n      })\n\n      it('should add in_foreground: false when the page is not active', () => {\n        pageStateHistory.addPageState(PageState.HIDDEN)\n\n        const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n          eventType,\n          startTime: clock.relative(0),\n          duration: 0 as Duration,\n        } as AssembleHookParams)\n\n        expect(defaultRumEventAttributes).toEqual({\n          type: eventType,\n          view: { in_foreground: false },\n        })\n      })\n    })\n  })\n\n  describe('initialization with visibility-state backfill', () => {\n    let pageStateHistory: PageStateHistory\n\n    afterEach(() => {\n      if (pageStateHistory) {\n        pageStateHistory.stop()\n      }\n    })\n\n    it('should backfill history if visibility-state is supported and entries exist', () => {\n      const { notifyPerformanceEntries } = mockPerformanceObserver({\n        supportedEntryTypes: [performanceObservable.RumPerformanceEntryType.VISIBILITY_STATE],\n      })\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(performanceObservable.RumPerformanceEntryType.VISIBILITY_STATE, {\n          name: 'visible',\n          startTime: 5 as RelativeTime,\n        }),\n        createPerformanceEntry(performanceObservable.RumPerformanceEntryType.VISIBILITY_STATE, {\n          name: 'hidden',\n          startTime: 15 as RelativeTime,\n        }),\n      ])\n\n      pageStateHistory = startPageStateHistory(hooks, configuration)\n      registerCleanupTask(pageStateHistory.stop)\n\n      expect(pageStateHistory.wasInPageStateDuringPeriod(PageState.ACTIVE, 5 as RelativeTime, 5 as Duration)).toBeTrue()\n      expect(\n        pageStateHistory.wasInPageStateDuringPeriod(PageState.HIDDEN, 15 as RelativeTime, 5 as Duration)\n      ).toBeTrue()\n    })\n\n    it('should not backfill if visibility-state is not supported', () => {\n      mockPerformanceObserver({\n        supportedEntryTypes: [],\n      })\n\n      pageStateHistory = startPageStateHistory(hooks, configuration)\n      registerCleanupTask(pageStateHistory.stop)\n\n      expect(\n        pageStateHistory.wasInPageStateDuringPeriod(PageState.ACTIVE, 5 as RelativeTime, 5 as Duration)\n      ).toBeFalse()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/pageStateHistory.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport {\n  SKIPPED,\n  elapsed,\n  createValueHistory,\n  SESSION_TIME_OUT_DELAY,\n  toServerDuration,\n  addEventListeners,\n  relativeNow,\n  DOM_EVENT,\n  HookNames,\n} from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\nimport { supportPerformanceTimingEvent, RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport type { PageStateServerEntry } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\n// Arbitrary value to cap number of element for memory consumption in the browser\nexport const MAX_PAGE_STATE_ENTRIES = 4000\n// Arbitrary value to cap number of element for backend & to save bandwidth\nexport const MAX_PAGE_STATE_ENTRIES_SELECTABLE = 500\n\nexport const PAGE_STATE_CONTEXT_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY\n\nexport const enum PageState {\n  ACTIVE = 'active',\n  PASSIVE = 'passive',\n  HIDDEN = 'hidden',\n  FROZEN = 'frozen',\n  TERMINATED = 'terminated',\n}\n\nexport interface PageStateEntry {\n  state: PageState\n  startTime: RelativeTime\n}\n\nexport interface PageStateHistory {\n  wasInPageStateDuringPeriod: (state: PageState, startTime: RelativeTime, duration: Duration) => boolean\n  addPageState(nextPageState: PageState, startTime?: RelativeTime): void\n  stop: () => void\n}\n\nexport function startPageStateHistory(\n  hooks: Hooks,\n  configuration: RumConfiguration,\n  maxPageStateEntriesSelectable = MAX_PAGE_STATE_ENTRIES_SELECTABLE\n): PageStateHistory {\n  const pageStateEntryHistory = createValueHistory<PageStateEntry>({\n    expireDelay: PAGE_STATE_CONTEXT_TIME_OUT_DELAY,\n    maxEntries: MAX_PAGE_STATE_ENTRIES,\n  })\n\n  let currentPageState: PageState\n\n  if (supportPerformanceTimingEvent(RumPerformanceEntryType.VISIBILITY_STATE)) {\n    const visibilityEntries = performance.getEntriesByType(\n      RumPerformanceEntryType.VISIBILITY_STATE\n    ) as PerformanceEntry[]\n\n    visibilityEntries.forEach((entry) => {\n      const state = entry.name === 'hidden' ? PageState.HIDDEN : PageState.ACTIVE\n      addPageState(state, entry.startTime as RelativeTime)\n    })\n  }\n\n  addPageState(getPageState(), relativeNow())\n\n  const { stop: stopEventListeners } = addEventListeners(\n    configuration,\n    window,\n    [\n      DOM_EVENT.PAGE_SHOW,\n      DOM_EVENT.FOCUS,\n      DOM_EVENT.BLUR,\n      DOM_EVENT.VISIBILITY_CHANGE,\n      DOM_EVENT.RESUME,\n      DOM_EVENT.FREEZE,\n      DOM_EVENT.PAGE_HIDE,\n    ],\n    (event) => {\n      addPageState(computePageState(event), event.timeStamp as RelativeTime)\n    },\n    { capture: true }\n  )\n\n  function addPageState(nextPageState: PageState, startTime = relativeNow()) {\n    if (nextPageState === currentPageState) {\n      return\n    }\n\n    currentPageState = nextPageState\n    pageStateEntryHistory.closeActive(startTime)\n    pageStateEntryHistory.add({ state: currentPageState, startTime }, startTime)\n  }\n\n  function wasInPageStateDuringPeriod(state: PageState, startTime: RelativeTime, duration: Duration) {\n    return pageStateEntryHistory.findAll(startTime, duration).some((pageState) => pageState.state === state)\n  }\n\n  hooks.register(\n    HookNames.Assemble,\n    ({ startTime, duration = 0 as Duration, eventType }): DefaultRumEventAttributes | SKIPPED => {\n      if (eventType === RumEventType.VIEW) {\n        const pageStates = pageStateEntryHistory.findAll(startTime, duration)\n        return {\n          type: eventType,\n          _dd: { page_states: processPageStates(pageStates, startTime, maxPageStateEntriesSelectable) },\n        }\n      }\n\n      if (eventType === RumEventType.ACTION || eventType === RumEventType.ERROR) {\n        return {\n          type: eventType,\n          view: { in_foreground: wasInPageStateDuringPeriod(PageState.ACTIVE, startTime, 0 as Duration) },\n        }\n      }\n\n      return SKIPPED\n    }\n  )\n\n  return {\n    wasInPageStateDuringPeriod,\n    addPageState,\n    stop: () => {\n      stopEventListeners()\n      pageStateEntryHistory.stop()\n    },\n  }\n}\n\nfunction processPageStates(\n  pageStateEntries: PageStateEntry[],\n  eventStartTime: RelativeTime,\n  maxPageStateEntriesSelectable: number\n): PageStateServerEntry[] | undefined {\n  if (pageStateEntries.length === 0) {\n    return\n  }\n\n  return pageStateEntries\n    .slice(-maxPageStateEntriesSelectable)\n    .reverse()\n    .map(({ state, startTime }) => ({\n      state,\n      start: toServerDuration(elapsed(eventStartTime, startTime)),\n    }))\n}\n\nfunction computePageState(event: Event & { type: DOM_EVENT }) {\n  if (event.type === DOM_EVENT.FREEZE) {\n    return PageState.FROZEN\n  } else if (event.type === DOM_EVENT.PAGE_HIDE) {\n    return (event as PageTransitionEvent).persisted ? PageState.FROZEN : PageState.TERMINATED\n  }\n  return getPageState()\n}\n\nfunction getPageState() {\n  if (document.visibilityState === 'hidden') {\n    return PageState.HIDDEN\n  }\n\n  if (document.hasFocus()) {\n    return PageState.ACTIVE\n  }\n\n  return PageState.PASSIVE\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/sessionContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { clocksNow, DISCARDED, HookNames } from '@datadog/browser-core'\nimport type { RumSessionManagerMock } from '../../../test'\nimport { createRumSessionManagerMock, noopRecorderApi } from '../../../test'\nimport { SessionType } from '../rumSessionManager'\nimport type { AssembleHookParams, DefaultRumEventAttributes, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startSessionContext } from './sessionContext'\nimport type { ViewHistory } from './viewHistory'\n\ndescribe('session context', () => {\n  let hooks: Hooks\n  let viewHistory: ViewHistory\n  let sessionManager: RumSessionManagerMock\n  const fakeView = {\n    id: '1',\n    startClocks: clocksNow(),\n    sessionIsActive: false,\n  }\n  let isRecordingSpy: jasmine.Spy\n  let getReplayStatsSpy: jasmine.Spy\n  let findViewSpy: jasmine.Spy\n  const fakeStats = {\n    segments_count: 4,\n    records_count: 10,\n    segments_total_raw_size: 1000,\n  }\n\n  beforeEach(() => {\n    viewHistory = { findView: () => undefined } as ViewHistory\n    hooks = createHooks()\n    sessionManager = createRumSessionManagerMock()\n    sessionManager.setId('123')\n    const recorderApi = noopRecorderApi\n\n    isRecordingSpy = spyOn(recorderApi, 'isRecording')\n    getReplayStatsSpy = spyOn(recorderApi, 'getReplayStats')\n    findViewSpy = spyOn(viewHistory, 'findView').and.returnValue(fakeView)\n\n    startSessionContext(hooks, sessionManager, recorderApi, viewHistory)\n  })\n\n  it('should set id and type', () => {\n    isRecordingSpy.and.returnValue(true)\n\n    const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'action',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams)\n\n    expect(defaultRumEventAttributes).toEqual({\n      type: 'action',\n      session: jasmine.objectContaining({\n        id: jasmine.any(String),\n        type: SessionType.USER,\n      }),\n    })\n  })\n\n  it('should set hasReplay when recording has started (isRecording) on events', () => {\n    isRecordingSpy.and.returnValue(true)\n    const eventWithHasReplay = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'action',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    isRecordingSpy.and.returnValue(false)\n    const eventWithoutHasReplay = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'action',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    expect(getReplayStatsSpy).not.toHaveBeenCalled()\n    expect(isRecordingSpy).toHaveBeenCalled()\n    expect(eventWithHasReplay.session!.has_replay).toEqual(true)\n    expect(eventWithoutHasReplay.session!.has_replay).toBeUndefined()\n  })\n\n  it('should set hasReplay when there are Replay stats on view events', () => {\n    getReplayStatsSpy.and.returnValue(fakeStats)\n    const eventWithHasReplay = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    getReplayStatsSpy.and.returnValue(undefined)\n    const eventWithoutHasReplay = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    expect(getReplayStatsSpy).toHaveBeenCalled()\n    expect(isRecordingSpy).not.toHaveBeenCalled()\n    expect(eventWithHasReplay.session!.has_replay).toEqual(true)\n    expect(eventWithoutHasReplay.session!.has_replay).toBeUndefined()\n  })\n\n  it('should set session.is_active when the session is active', () => {\n    findViewSpy.and.returnValue({ ...fakeView, sessionIsActive: true })\n    const eventWithActiveSession = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n    findViewSpy.and.returnValue({ ...fakeView, sessionIsActive: false })\n    const eventWithoutActiveSession = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    expect(eventWithActiveSession.session!.is_active).toBe(undefined)\n    expect(eventWithoutActiveSession.session!.is_active).toBe(false)\n  })\n\n  it('should set sampled_for_replay', () => {\n    sessionManager.setTrackedWithSessionReplay()\n    const eventSampleForReplay = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    sessionManager.setTrackedWithoutSessionReplay()\n    const eventSampledOutForReplay = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams) as DefaultRumEventAttributes\n\n    expect(eventSampleForReplay.session!.sampled_for_replay).toBe(true)\n    expect(eventSampledOutForReplay.session!.sampled_for_replay).toBe(false)\n  })\n\n  it('should discard the event if no session', () => {\n    sessionManager.setNotTracked()\n    const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams)\n\n    expect(defaultRumEventAttributes).toBe(DISCARDED)\n  })\n\n  it('should discard the event if no view', () => {\n    findViewSpy.and.returnValue(undefined)\n    const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'view',\n      startTime: 0 as RelativeTime,\n    } as AssembleHookParams)\n\n    expect(defaultRumEventAttributes).toBe(DISCARDED)\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should add session.id', () => {\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      }) as DefaultTelemetryEventAttributes\n\n      expect(telemetryEventAttributes.session?.id).toEqual('123')\n    })\n\n    it('should not add session.id if no session', () => {\n      sessionManager.setNotTracked()\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(telemetryEventAttributes).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/sessionContext.ts",
    "content": "import { DISCARDED, HookNames, SKIPPED } from '@datadog/browser-core'\nimport { SessionReplayState, SessionType } from '../rumSessionManager'\nimport type { RumSessionManager } from '../rumSessionManager'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { RecorderApi } from '../../boot/rumPublicApi'\nimport type { DefaultRumEventAttributes, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport type { ViewHistory } from './viewHistory'\n\nexport function startSessionContext(\n  hooks: Hooks,\n  sessionManager: RumSessionManager,\n  recorderApi: RecorderApi,\n  viewHistory: ViewHistory\n) {\n  hooks.register(HookNames.Assemble, ({ eventType, startTime }): DefaultRumEventAttributes | DISCARDED => {\n    const session = sessionManager.findTrackedSession(startTime)\n    const view = viewHistory.findView(startTime)\n\n    if (!session || !view) {\n      return DISCARDED\n    }\n\n    let hasReplay\n    let sampledForReplay\n    let isActive\n    if (eventType === RumEventType.VIEW) {\n      hasReplay = recorderApi.getReplayStats(view.id) ? true : undefined\n      sampledForReplay = session.sessionReplay === SessionReplayState.SAMPLED\n      isActive = view.sessionIsActive ? undefined : false\n    } else {\n      hasReplay = recorderApi.isRecording() ? true : undefined\n    }\n\n    return {\n      type: eventType,\n      session: {\n        id: session.id,\n        type: SessionType.USER,\n        has_replay: hasReplay,\n        sampled_for_replay: sampledForReplay,\n        is_active: isActive,\n      },\n    }\n  })\n\n  hooks.register(HookNames.AssembleTelemetry, ({ startTime }): DefaultTelemetryEventAttributes | SKIPPED => {\n    const session = sessionManager.findTrackedSession(startTime)\n\n    if (!session) {\n      return SKIPPED\n    }\n\n    return {\n      session: {\n        id: session.id,\n      },\n    }\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/sourceCodeContext.spec.ts",
    "content": "import { HookNames } from '@datadog/browser-core'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { registerCleanupTask } from '../../../../core/test'\nimport type { RawRumLongAnimationFrameEvent } from '../../rawRumEvent.types'\nimport type { BrowserWindow } from './sourceCodeContext'\nimport { startSourceCodeContext } from './sourceCodeContext'\n\ndescribe('sourceCodeContext', () => {\n  let hooks: Hooks\n  let browserWindow: BrowserWindow\n  const TEST_STACK = `Error: Test error\n    at testFunction (http://localhost:8080/file.js:41:27)\n    at HTMLButtonElement.onclick (http://localhost:8080/file-2.js:107:146)`\n\n  const MATCHING_TEST_STACK = `Error: Another error\n    at anotherFunction (http://localhost:8080/file.js:41:27)\n    at HTMLButtonElement.onPointerUp (http://localhost:8080/another-file.js:107:146)`\n\n  beforeEach(() => {\n    hooks = createHooks()\n    browserWindow = window as BrowserWindow\n  })\n\n  function setupBrowserWindowWithContext() {\n    browserWindow.DD_SOURCE_CODE_CONTEXT = {\n      [TEST_STACK]: {\n        service: 'my-service',\n        version: '1.0.0',\n      },\n    }\n\n    registerCleanupTask(() => {\n      delete browserWindow.DD_SOURCE_CODE_CONTEXT\n    })\n  }\n\n  it('should add source code context matching the error stack first frame URL', () => {\n    setupBrowserWindowWithContext()\n    startSourceCodeContext(hooks)\n\n    const result = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'error',\n      startTime: 0 as RelativeTime,\n      domainContext: {},\n      rawRumEvent: {\n        type: 'error',\n        error: {\n          stack: MATCHING_TEST_STACK,\n        },\n      },\n    } as AssembleHookParams)\n\n    expect(result).toEqual({\n      type: 'error',\n      service: 'my-service',\n      version: '1.0.0',\n    })\n  })\n\n  it('should add source code context matching the handling_stack first frame URL', () => {\n    setupBrowserWindowWithContext()\n    startSourceCodeContext(hooks)\n\n    const result = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'action',\n      startTime: 0 as RelativeTime,\n      rawRumEvent: {\n        type: 'action',\n      },\n      domainContext: {\n        handlingStack: MATCHING_TEST_STACK,\n      },\n    } as AssembleHookParams)\n\n    expect(result).toEqual({\n      type: 'action',\n      service: 'my-service',\n      version: '1.0.0',\n    })\n  })\n\n  it('should add source code context matching the LoAF first script source URL', () => {\n    setupBrowserWindowWithContext()\n    startSourceCodeContext(hooks)\n\n    const result = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'long_task',\n      startTime: 0 as RelativeTime,\n      domainContext: {},\n      rawRumEvent: {\n        type: 'long_task',\n        long_task: {\n          entry_type: 'long-animation-frame',\n          scripts: [\n            {\n              source_url: 'http://localhost:8080/file.js',\n            },\n          ],\n        },\n      } as RawRumLongAnimationFrameEvent,\n    } as AssembleHookParams)\n\n    expect(result).toEqual({\n      type: 'long_task',\n      service: 'my-service',\n      version: '1.0.0',\n    })\n  })\n\n  it('should not add source code context matching no stack', () => {\n    setupBrowserWindowWithContext()\n    startSourceCodeContext(hooks)\n\n    const result = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'error',\n      startTime: 0 as RelativeTime,\n      domainContext: {},\n      rawRumEvent: {\n        type: 'error',\n        error: {\n          stack: `Error: Another error\n                at anotherFunction (http://localhost:8080/another-file.js:41:27)`,\n        },\n      },\n    } as AssembleHookParams)\n\n    expect(result).toBeUndefined()\n  })\n\n  it('should support late updates to DD_SOURCE_CODE_CONTEXT', () => {\n    startSourceCodeContext(hooks)\n\n    // Add context AFTER initialization\n    setupBrowserWindowWithContext()\n\n    const result = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'error',\n      startTime: 0 as RelativeTime,\n      domainContext: {},\n      rawRumEvent: {\n        type: 'error',\n        error: {\n          stack: TEST_STACK,\n        },\n      },\n    } as AssembleHookParams)\n\n    expect(result).toEqual({\n      type: 'error',\n      service: 'my-service',\n      version: '1.0.0',\n    })\n  })\n\n  it('should ignore updates to existing source code context after initialization', () => {\n    setupBrowserWindowWithContext()\n    startSourceCodeContext(hooks)\n\n    // Update existing entry\n    browserWindow.DD_SOURCE_CODE_CONTEXT![TEST_STACK] = {\n      service: 'updated-service',\n      version: '1.1.0',\n    }\n\n    const result = hooks.triggerHook(HookNames.Assemble, {\n      eventType: 'error',\n      startTime: 0 as RelativeTime,\n      domainContext: {},\n      rawRumEvent: {\n        type: 'error',\n        error: {\n          stack: TEST_STACK,\n        },\n      },\n    } as AssembleHookParams)\n\n    expect(result).toEqual({\n      type: 'error',\n      service: 'my-service',\n      version: '1.0.0',\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/sourceCodeContext.ts",
    "content": "import { SKIPPED, computeStackTrace, objectEntries, addTelemetryError, HookNames } from '@datadog/browser-core'\nimport type { Hooks, DefaultRumEventAttributes, AssembleHookParams } from '../hooks'\n\ninterface SourceCodeContext {\n  service: string\n  version?: string\n}\n\nexport interface BrowserWindow {\n  DD_SOURCE_CODE_CONTEXT?: { [stack: string]: SourceCodeContext }\n}\ntype StackFrameUrl = string\n\nexport function startSourceCodeContext(hooks: Hooks) {\n  const browserWindow = window as BrowserWindow\n  const contextByFile = new Map<StackFrameUrl, SourceCodeContext>()\n\n  function buildContextByFile() {\n    if (!browserWindow.DD_SOURCE_CODE_CONTEXT) {\n      return\n    }\n\n    objectEntries(browserWindow.DD_SOURCE_CODE_CONTEXT).forEach(([stack, context]) => {\n      const stackTrace = computeStackTrace({ stack })\n      const firstFrame = stackTrace.stack[0]\n\n      if (!firstFrame.url) {\n        addTelemetryError('Source code context: missing frame url', { stack })\n        return\n      }\n      // don't overwrite existing context\n      if (!contextByFile.has(firstFrame.url)) {\n        contextByFile.set(firstFrame.url, context)\n      }\n    })\n\n    browserWindow.DD_SOURCE_CODE_CONTEXT = {}\n  }\n\n  buildContextByFile()\n\n  hooks.register(HookNames.Assemble, ({ domainContext, rawRumEvent }): DefaultRumEventAttributes | SKIPPED => {\n    buildContextByFile()\n\n    if (contextByFile.size === 0) {\n      return SKIPPED\n    }\n\n    const url = getSourceUrl(domainContext, rawRumEvent)\n    const context = url && contextByFile.get(url)\n\n    if (!context) {\n      return SKIPPED\n    }\n\n    return {\n      type: rawRumEvent.type,\n      service: context.service,\n      version: context.version,\n    }\n  })\n}\n\nfunction getSourceUrl(\n  domainContext: AssembleHookParams['domainContext'],\n  rawRumEvent: AssembleHookParams['rawRumEvent']\n) {\n  if (rawRumEvent.type === 'long_task' && rawRumEvent.long_task.entry_type === 'long-animation-frame') {\n    return rawRumEvent.long_task.scripts[0]?.source_url\n  }\n\n  let stack\n  if ('handlingStack' in domainContext) {\n    stack = domainContext.handlingStack\n  }\n\n  if (rawRumEvent.type === 'error' && rawRumEvent.error.stack) {\n    stack = rawRumEvent.error.stack\n  }\n  const stackTrace = computeStackTrace({ stack })\n\n  return stackTrace.stack[0]?.url\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/syntheticsContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { HookNames } from '@datadog/browser-core'\nimport { mockSyntheticsWorkerValues } from '../../../../core/test'\nimport { SessionType } from '../rumSessionManager'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startSyntheticsContext } from './syntheticsContext'\n\ndescribe('getSyntheticsContext', () => {\n  let hooks: Hooks\n  beforeEach(() => {\n    hooks = createHooks()\n  })\n\n  describe('assemble hook', () => {\n    it('should set the synthetics context defined by global variables', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo', result_id: 'bar' } }, 'globals')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.SYNTHETICS,\n        },\n        synthetics: {\n          test_id: 'foo',\n          result_id: 'bar',\n          injected: false,\n        },\n      })\n    })\n\n    it('should set the synthetics context defined by cookie', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo', result_id: 'bar' } }, 'cookies')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.SYNTHETICS,\n        },\n        synthetics: {\n          test_id: 'foo',\n          result_id: 'bar',\n          injected: false,\n        },\n      })\n    })\n\n    it('should pass all extra fields from the context to the synthetics property', () => {\n      mockSyntheticsWorkerValues(\n        {\n          context: {\n            test_id: 'foo',\n            result_id: 'bar',\n            run_type: 'scheduled',\n            suite_ids: ['abc'] as any,\n          },\n        },\n        'globals'\n      )\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.SYNTHETICS,\n        },\n        synthetics: {\n          test_id: 'foo',\n          result_id: 'bar',\n          run_type: 'scheduled',\n          suite_ids: ['abc'],\n          injected: false,\n        },\n      })\n    })\n\n    it('should set the `injected` field to true if the Synthetics test is configured to automatically inject RUM', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo', result_id: 'bar' }, injectsRum: true }, 'globals')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.SYNTHETICS,\n        },\n        synthetics: {\n          test_id: 'foo',\n          result_id: 'bar',\n          injected: true,\n        },\n      })\n    })\n\n    it('should not set synthetics context if the global variable is missing required fields', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo' } as any }, 'globals')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n\n    it('should not set synthetics context if the global variable fields are not strings', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 1, result_id: 2 } as any }, 'globals')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n\n    it('should set the synthetics context from legacy globals when the new context is absent', () => {\n      mockSyntheticsWorkerValues({ publicId: 'foo', resultId: 'bar' }, 'globals')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual({\n        type: 'view',\n        session: {\n          type: SessionType.SYNTHETICS,\n        },\n        synthetics: {\n          test_id: 'foo',\n          result_id: 'bar',\n          injected: false,\n        },\n      })\n    })\n\n    it('should not set synthetics context if the cookie is missing required fields', () => {\n      mockSyntheticsWorkerValues({ context: { test_id: 'foo' } as any }, 'cookies')\n      startSyntheticsContext(hooks)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/syntheticsContext.ts",
    "content": "import {\n  SKIPPED,\n  getSyntheticsContext,\n  HookNames,\n  willSyntheticsInjectRum,\n  isSyntheticsTest,\n} from '@datadog/browser-core'\nimport { SessionType } from '../rumSessionManager'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\nexport function startSyntheticsContext(hooks: Hooks) {\n  hooks.register(HookNames.Assemble, ({ eventType }): DefaultRumEventAttributes | SKIPPED => {\n    if (!isSyntheticsTest()) {\n      return SKIPPED\n    }\n\n    return {\n      type: eventType,\n      session: {\n        type: SessionType.SYNTHETICS,\n      },\n      synthetics: {\n        ...getSyntheticsContext(),\n        injected: willSyntheticsInjectRum(),\n      },\n    }\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/trackingConsentContext.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { DISCARDED, HookNames, createTrackingConsentState, TrackingConsent } from '@datadog/browser-core'\nimport type { Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startTrackingConsentContext } from './trackingConsentContext'\n\ndescribe('tracking consent context', () => {\n  let hooks: Hooks\n\n  beforeEach(() => {\n    hooks = createHooks()\n  })\n\n  describe('for telemetry (AssembleTelemetry hook)', () => {\n    it('should discard telemetry if consent is not granted', () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.NOT_GRANTED)\n      startTrackingConsentContext(hooks, trackingConsentState)\n\n      const defaultLogAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      })\n\n      expect(defaultLogAttributes).toBe(DISCARDED)\n    })\n\n    it('should not discard telemetry if consent is granted', () => {\n      const trackingConsentState = createTrackingConsentState(TrackingConsent.GRANTED)\n      startTrackingConsentContext(hooks, trackingConsentState)\n\n      const defaultLogAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 100 as RelativeTime,\n      })\n\n      expect(defaultLogAttributes).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/trackingConsentContext.ts",
    "content": "import { DISCARDED, HookNames, SKIPPED } from '@datadog/browser-core'\nimport type { TrackingConsentState } from '@datadog/browser-core'\nimport type { Hooks } from '../hooks'\n\nexport function startTrackingConsentContext(hooks: Hooks, trackingConsentState: TrackingConsentState) {\n  hooks.register(HookNames.AssembleTelemetry, () => {\n    const wasConsented = trackingConsentState.isGranted()\n\n    if (!wasConsented) {\n      return DISCARDED\n    }\n\n    return SKIPPED\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/urlContexts.spec.ts",
    "content": "import { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport type { Clock } from '@datadog/browser-core/test'\nimport type { RelativeTime } from '@datadog/browser-core'\nimport { clocksNow, DISCARDED, HookNames, relativeToClocks } from '@datadog/browser-core'\nimport { setupLocationObserver } from '../../../test'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { ViewCreatedEvent, ViewEndedEvent } from '../view/trackViews'\nimport type { AssembleHookParams, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport { startUrlContexts, type UrlContexts } from './urlContexts'\n\ndescribe('urlContexts', () => {\n  const lifeCycle = new LifeCycle()\n  let changeLocation: (to: string) => void\n  let urlContexts: UrlContexts\n  let clock: Clock\n  let hooks: Hooks\n\n  beforeEach(() => {\n    clock = mockClock()\n    hooks = createHooks()\n    const setupResult = setupLocationObserver('http://fake-url.com')\n\n    changeLocation = setupResult.changeLocation\n    urlContexts = startUrlContexts(lifeCycle, hooks, setupResult.locationChangeObservable)\n\n    registerCleanupTask(() => {\n      urlContexts.stop()\n    })\n  })\n\n  it('should return undefined before the initial view', () => {\n    expect(urlContexts.findUrl()).toBeUndefined()\n  })\n\n  it('should not create url context on location change before the initial view', () => {\n    changeLocation('/foo')\n\n    expect(urlContexts.findUrl()).toBeUndefined()\n  })\n\n  it('should return current url and document referrer for initial view', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n    } as ViewCreatedEvent)\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toBe('http://fake-url.com/')\n    expect(urlContext.referrer).toBe(document.referrer)\n  })\n\n  it('should use the provided url override instead of location', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n      url: 'https://example.com/overridden-path',\n    } as ViewCreatedEvent)\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toBe('https://example.com/overridden-path')\n    expect(urlContext.referrer).toBe(document.referrer)\n  })\n\n  it('should resolve a relative url override against the current location', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n      url: '/dashboard',\n    } as ViewCreatedEvent)\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toBe('http://fake-url.com/dashboard')\n  })\n\n  it('should fall back to location.href when no url override is provided', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n    } as ViewCreatedEvent)\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toBe('http://fake-url.com/')\n  })\n\n  it('should fall back to location.href when url override is explicitly undefined', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n      url: undefined,\n    } as ViewCreatedEvent)\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toBe('http://fake-url.com/')\n  })\n\n  it('should use the provided url override for events starting before a location change', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: clocksNow(),\n      url: 'https://example.com/manual-url',\n    } as ViewCreatedEvent)\n\n    clock.tick(10)\n    const resourceStartTime = clock.relative(10)\n\n    clock.tick(10)\n    changeLocation('/new-path')\n\n    expect(urlContexts.findUrl(resourceStartTime)).toEqual({\n      url: 'https://example.com/manual-url',\n      referrer: document.referrer,\n    })\n  })\n\n  it('should update url context on location change', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n    } as ViewCreatedEvent)\n    changeLocation('/foo')\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toContain('http://fake-url.com/foo')\n    expect(urlContext.referrer).toBe(document.referrer)\n  })\n\n  it('should update url context on new view', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n    } as ViewCreatedEvent)\n    changeLocation('/foo')\n    lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, {\n      endClocks: relativeToClocks(10 as RelativeTime),\n    } as ViewEndedEvent)\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(10 as RelativeTime),\n    } as ViewCreatedEvent)\n\n    const urlContext = urlContexts.findUrl()!\n    expect(urlContext.url).toBe('http://fake-url.com/foo')\n    expect(urlContext.referrer).toBe('http://fake-url.com/')\n  })\n\n  it('should return the url context corresponding to the start time', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: clocksNow(),\n    } as ViewCreatedEvent)\n\n    clock.tick(10)\n    changeLocation('/foo')\n    lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, {\n      endClocks: clocksNow(),\n    } as ViewEndedEvent)\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: clocksNow(),\n    } as ViewCreatedEvent)\n\n    clock.tick(10)\n    changeLocation('/foo#bar')\n\n    clock.tick(10)\n    changeLocation('/qux')\n    lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, {\n      endClocks: clocksNow(),\n    } as ViewEndedEvent)\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: clocksNow(),\n    } as ViewCreatedEvent)\n\n    expect(urlContexts.findUrl(clock.relative(5))).toEqual({\n      url: 'http://fake-url.com/',\n      referrer: document.referrer,\n    })\n    expect(urlContexts.findUrl(clock.relative(15))).toEqual({\n      url: 'http://fake-url.com/foo',\n      referrer: 'http://fake-url.com/',\n    })\n    expect(urlContexts.findUrl(clock.relative(25))).toEqual({\n      url: 'http://fake-url.com/foo#bar',\n      referrer: 'http://fake-url.com/',\n    })\n    expect(urlContexts.findUrl(clock.relative(35))).toEqual({\n      url: 'http://fake-url.com/qux',\n      referrer: 'http://fake-url.com/foo',\n    })\n  })\n\n  /**\n   * It could happen if there is an event happening just between view end and view creation\n   * (which seems unlikely) and this event would anyway be rejected by lack of view id\n   */\n  it('should return undefined when no current view', () => {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n      startClocks: relativeToClocks(0 as RelativeTime),\n    } as ViewCreatedEvent)\n    lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, {\n      endClocks: relativeToClocks(10 as RelativeTime),\n    } as ViewEndedEvent)\n\n    expect(urlContexts.findUrl()).toBeUndefined()\n  })\n\n  describe('assemble hook', () => {\n    it('should add url properties from the history', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, {\n        startClocks: relativeToClocks(0 as RelativeTime),\n      } as ViewCreatedEvent)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual(\n        jasmine.objectContaining({\n          view: {\n            url: jasmine.any(String),\n            referrer: jasmine.any(String),\n          },\n        })\n      )\n    })\n\n    it('should discard the event if no URL', () => {\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBe(DISCARDED)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/urlContexts.ts",
    "content": "import type { RelativeTime, Observable } from '@datadog/browser-core'\nimport {\n  SESSION_TIME_OUT_DELAY,\n  relativeNow,\n  createValueHistory,\n  HookNames,\n  DISCARDED,\n  mockable,\n  buildUrl,\n} from '@datadog/browser-core'\nimport type { LocationChange } from '../../browser/locationChangeObservable'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { DefaultRumEventAttributes, Hooks } from '../hooks'\n\n/**\n * We want to attach to an event:\n * - the url corresponding to its start\n * - the referrer corresponding to the previous view url (or document referrer for initial view)\n */\n\nexport const URL_CONTEXT_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY\n\nexport interface UrlContext {\n  url: string\n  referrer: string\n}\n\nexport interface UrlContexts {\n  findUrl: (startTime?: RelativeTime) => UrlContext | undefined\n  stop: () => void\n}\n\nexport function startUrlContexts(\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  locationChangeObservable: Observable<LocationChange>\n) {\n  const urlContextHistory = createValueHistory<UrlContext>({ expireDelay: URL_CONTEXT_TIME_OUT_DELAY })\n\n  let previousViewUrl: string | undefined\n\n  lifeCycle.subscribe(LifeCycleEventType.BEFORE_VIEW_CREATED, ({ startClocks, url }) => {\n    const locationHref = mockable(location).href\n    const viewUrl = url !== undefined ? buildUrl(url, locationHref).href : locationHref\n    urlContextHistory.add(\n      buildUrlContext({\n        url: viewUrl,\n        referrer: !previousViewUrl ? document.referrer : previousViewUrl,\n      }),\n      startClocks.relative\n    )\n    previousViewUrl = viewUrl\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.AFTER_VIEW_ENDED, ({ endClocks }) => {\n    urlContextHistory.closeActive(endClocks.relative)\n  })\n\n  const locationChangeSubscription = locationChangeObservable.subscribe(({ newLocation }) => {\n    const current = urlContextHistory.find()\n    if (current) {\n      const changeTime = relativeNow()\n      urlContextHistory.closeActive(changeTime)\n      urlContextHistory.add(\n        buildUrlContext({\n          url: newLocation.href,\n          referrer: current.referrer,\n        }),\n        changeTime\n      )\n    }\n  })\n\n  function buildUrlContext({ url, referrer }: { url: string; referrer: string }) {\n    return {\n      url,\n      referrer,\n    }\n  }\n\n  hooks.register(HookNames.Assemble, ({ startTime, eventType }): DefaultRumEventAttributes | DISCARDED => {\n    const urlContext = urlContextHistory.find(startTime)\n\n    if (!urlContext) {\n      return DISCARDED\n    }\n\n    return {\n      type: eventType,\n      view: {\n        url: urlContext.url,\n        referrer: urlContext.referrer,\n      },\n    }\n  })\n\n  return {\n    findUrl: (startTime?: RelativeTime) => urlContextHistory.find(startTime),\n    stop: () => {\n      locationChangeSubscription.unsubscribe()\n      urlContextHistory.stop()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/viewHistory.spec.ts",
    "content": "import type { Context, RelativeTime } from '@datadog/browser-core'\nimport { relativeToClocks, CLEAR_OLD_VALUES_INTERVAL } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { BeforeViewUpdateEvent, ViewCreatedEvent } from '../view/trackViews'\nimport type { ViewHistory } from './viewHistory'\nimport { startViewHistory, VIEW_CONTEXT_TIME_OUT_DELAY } from './viewHistory'\n\ndescribe('ViewHistory', () => {\n  const FAKE_ID = 'fake'\n  const startClocks = relativeToClocks(10 as RelativeTime)\n\n  function buildViewCreatedEvent(partialViewCreatedEvent: Partial<ViewCreatedEvent> = {}): ViewCreatedEvent {\n    return {\n      startClocks,\n      id: FAKE_ID,\n      ...partialViewCreatedEvent,\n    }\n  }\n\n  let clock: Clock\n  let lifeCycle: LifeCycle\n  let viewHistory: ViewHistory\n\n  beforeEach(() => {\n    clock = mockClock()\n    lifeCycle = new LifeCycle()\n    viewHistory = startViewHistory(lifeCycle)\n\n    registerCleanupTask(() => {\n      viewHistory.stop()\n    })\n  })\n\n  describe('findView', () => {\n    it('should return undefined when there is no current view and no startTime', () => {\n      expect(viewHistory.findView()).toBeUndefined()\n    })\n\n    it('should return the current view context when there is no start time', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, buildViewCreatedEvent())\n\n      expect(viewHistory.findView()).toBeDefined()\n      expect(viewHistory.findView()!.id).toEqual(FAKE_ID)\n    })\n\n    it('should return the view context corresponding to startTime', () => {\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({ startClocks: relativeToClocks(10 as RelativeTime), id: 'view 1' })\n      )\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, { endClocks: relativeToClocks(20 as RelativeTime) })\n\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({ startClocks: relativeToClocks(20 as RelativeTime), id: 'view 2' })\n      )\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, { endClocks: relativeToClocks(30 as RelativeTime) })\n\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({ startClocks: relativeToClocks(30 as RelativeTime), id: 'view 3' })\n      )\n\n      expect(viewHistory.findView(15 as RelativeTime)!.id).toEqual('view 1')\n      expect(viewHistory.findView(20 as RelativeTime)!.id).toEqual('view 2')\n      expect(viewHistory.findView(40 as RelativeTime)!.id).toEqual('view 3')\n    })\n\n    it('should return undefined when no view context corresponding to startTime', () => {\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({ startClocks: relativeToClocks(10 as RelativeTime), id: 'view 1' })\n      )\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, { endClocks: relativeToClocks(20 as RelativeTime) })\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({ startClocks: relativeToClocks(20 as RelativeTime), id: 'view 2' })\n      )\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, { endClocks: relativeToClocks(20 as RelativeTime) })\n\n      expect(viewHistory.findView(5 as RelativeTime)).not.toBeDefined()\n    })\n\n    it('should set the current view context on BEFORE_VIEW_CREATED', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, buildViewCreatedEvent())\n      const newViewId = 'fake 2'\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, buildViewCreatedEvent({ id: newViewId }))\n\n      expect(viewHistory.findView()!.id).toEqual(newViewId)\n    })\n\n    it('should return the view name with the view', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, buildViewCreatedEvent({ name: 'Fake name' }))\n      expect(viewHistory.findView()!.name).toBe('Fake name')\n    })\n\n    it('should update the view name for the current context', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, buildViewCreatedEvent({ name: 'foo' }))\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_UPDATED, {\n        startClocks,\n        name: 'Fake Name',\n      } as BeforeViewUpdateEvent)\n      expect(viewHistory.findView()!.name).toBe('Fake Name')\n    })\n\n    it('should update the view context for the current context', () => {\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, buildViewCreatedEvent({ context: { foo: 'bar' } }))\n      lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_UPDATED, {\n        startClocks,\n        context: { bar: 'foo' } as Context,\n      } as BeforeViewUpdateEvent)\n      expect(viewHistory.findView()!.context).toEqual({ bar: 'foo' })\n    })\n  })\n\n  describe('history contexts', () => {\n    it('should be cleared on SESSION_RENEWED', () => {\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({\n          id: 'view 1',\n          startClocks: relativeToClocks(10 as RelativeTime),\n        })\n      )\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, { endClocks: relativeToClocks(20 as RelativeTime) })\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({\n          id: 'view 2',\n          startClocks: relativeToClocks(20 as RelativeTime),\n        })\n      )\n\n      expect(viewHistory.findView(15 as RelativeTime)).toBeDefined()\n      expect(viewHistory.findView(25 as RelativeTime)).toBeDefined()\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n      expect(viewHistory.findView(15 as RelativeTime)).toBeUndefined()\n      expect(viewHistory.findView(25 as RelativeTime)).toBeUndefined()\n    })\n\n    it('should be cleared when too old', () => {\n      const originalTime = performance.now()\n      const originalClocks = relativeToClocks(originalTime as RelativeTime)\n      const targetTime = (originalTime + 5) as RelativeTime\n\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({\n          id: 'view 1',\n          startClocks: originalClocks,\n        })\n      )\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, {\n        endClocks: relativeToClocks((originalTime + 10) as RelativeTime),\n      })\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({ startClocks: relativeToClocks((originalTime + 10) as RelativeTime), id: 'view 2' })\n      )\n\n      clock.tick(10)\n      expect(viewHistory.findView(targetTime)).toBeDefined()\n\n      clock.tick(VIEW_CONTEXT_TIME_OUT_DELAY + CLEAR_OLD_VALUES_INTERVAL)\n      expect(viewHistory.findView(targetTime)).toBeUndefined()\n    })\n  })\n\n  describe('custom context', () => {\n    it('should be set on view creation', () => {\n      lifeCycle.notify(\n        LifeCycleEventType.BEFORE_VIEW_CREATED,\n        buildViewCreatedEvent({\n          id: 'view 1',\n          context: {\n            foo: 'bar',\n          },\n        })\n      )\n      expect(viewHistory.findView()).toBeDefined()\n      expect(viewHistory.findView()!.context).toEqual({\n        foo: 'bar',\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/contexts/viewHistory.ts",
    "content": "import type { RelativeTime, ClocksState, Context } from '@datadog/browser-core'\nimport { SESSION_TIME_OUT_DELAY, createValueHistory } from '@datadog/browser-core'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { BeforeViewUpdateEvent, ViewCreatedEvent } from '../view/trackViews'\n\nexport const VIEW_CONTEXT_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY\n\nexport interface ViewHistoryEntry {\n  service?: string\n  version?: string\n  context?: Context | undefined\n  id: string\n  name?: string\n  startClocks: ClocksState\n  sessionIsActive?: boolean\n}\n\nexport interface ViewHistory {\n  findView: (startTime?: RelativeTime) => ViewHistoryEntry | undefined\n  stop: () => void\n}\n\nexport function startViewHistory(lifeCycle: LifeCycle): ViewHistory {\n  const viewValueHistory = createValueHistory<ViewHistoryEntry>({ expireDelay: VIEW_CONTEXT_TIME_OUT_DELAY })\n\n  lifeCycle.subscribe(LifeCycleEventType.BEFORE_VIEW_CREATED, (view) => {\n    viewValueHistory.add(buildViewHistoryEntry(view), view.startClocks.relative)\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.AFTER_VIEW_ENDED, ({ endClocks }) => {\n    viewValueHistory.closeActive(endClocks.relative)\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.BEFORE_VIEW_UPDATED, (viewUpdate: BeforeViewUpdateEvent) => {\n    const currentView = viewValueHistory.find(viewUpdate.startClocks.relative)\n    if (!currentView) {\n      return\n    }\n    if (viewUpdate.name) {\n      currentView.name = viewUpdate.name\n    }\n    if (viewUpdate.context) {\n      currentView.context = viewUpdate.context\n    }\n    currentView.sessionIsActive = viewUpdate.sessionIsActive\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {\n    viewValueHistory.reset()\n  })\n\n  function buildViewHistoryEntry(view: ViewCreatedEvent) {\n    return {\n      service: view.service,\n      version: view.version,\n      context: view.context,\n      id: view.id,\n      name: view.name,\n      startClocks: view.startClocks,\n    }\n  }\n\n  return {\n    findView: (startTime) => viewValueHistory.find(startTime),\n    stop: () => {\n      viewValueHistory.stop()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/discardNegativeDuration.ts",
    "content": "import type { ServerDuration } from '@datadog/browser-core'\nimport { isNumber } from '@datadog/browser-core'\n\nexport function discardNegativeDuration(duration: ServerDuration | undefined): ServerDuration | undefined {\n  return isNumber(duration) && duration < 0 ? undefined : duration\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/error/errorCollection.spec.ts",
    "content": "import type { RelativeTime, TimeStamp, ErrorWithCause } from '@datadog/browser-core'\nimport { ErrorHandling, ErrorSource, NO_ERROR_STACK_PRESENT_MESSAGE } from '@datadog/browser-core'\nimport { FAKE_CSP_VIOLATION_EVENT } from '@datadog/browser-core/test'\nimport { collectAndValidateRawRumEvents } from '../../../test'\nimport type { RawRumErrorEvent, RawRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { doStartErrorCollection } from './errorCollection'\n\ndescribe('error collection', () => {\n  let lifeCycle: LifeCycle\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>> = []\n  let addError: ReturnType<typeof doStartErrorCollection>['addError']\n\n  function setupErrorCollection() {\n    lifeCycle = new LifeCycle()\n    ;({ addError } = doStartErrorCollection(lifeCycle))\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n  }\n\n  // when calling toString on SubErrorViaPrototype, the results will be '[object Object]'\n  // but the value of 'error instanceof Error' will still be true.\n  function SubErrorViaPrototype(this: Error, _message: string) {\n    Error.call(this, _message)\n    this.name = 'Error'\n    this.message = _message\n    this.stack = `Error: ${_message}\\n    at <anonymous>`\n  }\n  SubErrorViaPrototype.prototype = Object.create(Error.prototype)\n  SubErrorViaPrototype.prototype.constructor = SubErrorViaPrototype\n\n  describe('addError', () => {\n    ;[\n      {\n        testCase: 'an error instance',\n        error: new Error('foo'),\n        message: 'foo',\n        type: 'Error',\n        stack: jasmine.stringMatching('Error: foo'),\n      },\n      {\n        testCase: 'an error subclass via prototype',\n        error: new (SubErrorViaPrototype as unknown as { new (message: string): Error })('bar'),\n        message: 'bar',\n        type: 'Error',\n        stack: jasmine.stringMatching('Error: bar'),\n      },\n      {\n        testCase: 'a string',\n        error: 'foo',\n        message: 'Provided \"foo\"',\n        type: undefined,\n        stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n      },\n      {\n        testCase: 'an object',\n        error: { a: 'foo' },\n        message: 'Provided {\"a\":\"foo\"}',\n        type: undefined,\n        stack: NO_ERROR_STACK_PRESENT_MESSAGE,\n      },\n    ].forEach(({ testCase, error, message, type, stack }) => {\n      it(`notifies a raw rum error event from ${testCase}`, () => {\n        setupErrorCollection()\n\n        const startClocks = { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp }\n        addError({\n          error,\n          handlingStack: 'Error: handling foo',\n          startClocks,\n        })\n\n        expect(rawRumEvents.length).toBe(1)\n        expect(rawRumEvents[0]).toEqual({\n          rawRumEvent: {\n            date: jasmine.any(Number),\n            error: {\n              id: jasmine.any(String),\n              message,\n              source: ErrorSource.CUSTOM,\n              stack,\n              handling_stack: 'Error: handling foo',\n              component_stack: undefined,\n              type,\n              handling: ErrorHandling.HANDLED,\n              source_type: 'browser',\n              causes: undefined,\n              fingerprint: undefined,\n              csp: undefined,\n            },\n            type: RumEventType.ERROR,\n            context: undefined,\n          },\n          startClocks,\n          domainContext: {\n            error,\n            handlingStack: 'Error: handling foo',\n          },\n        })\n      })\n    })\n\n    it('should extract causes from error', () => {\n      setupErrorCollection()\n      const error1 = new Error('foo') as ErrorWithCause\n      const error2 = new Error('bar') as ErrorWithCause\n      const error3 = new Error('biz') as ErrorWithCause\n\n      error1.cause = error2\n      error2.cause = error3\n\n      addError({\n        error: error1,\n        handlingStack: 'Error: handling foo',\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      })\n      const { error } = rawRumEvents[0].rawRumEvent as RawRumErrorEvent\n      expect(error.message).toEqual('foo')\n      expect(error.source).toEqual(ErrorSource.CUSTOM)\n\n      expect(error?.causes?.length).toEqual(2)\n      expect(error?.causes?.[0].message).toEqual('bar')\n      expect(error?.causes?.[0].source).toEqual(ErrorSource.CUSTOM)\n      expect(error?.causes?.[1].message).toEqual('biz')\n      expect(error?.causes?.[1].source).toEqual(ErrorSource.CUSTOM)\n    })\n\n    it('should extract non-Error causes with consistent structure', () => {\n      setupErrorCollection()\n      const error = new Error('RSA key generation failed') as ErrorWithCause\n      error.cause = { code: 'NonInteger', values: [3.14, 2.71] }\n\n      addError({\n        error,\n        handlingStack: 'Error: handling',\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      })\n\n      const { error: rumError } = rawRumEvents[0].rawRumEvent as RawRumErrorEvent\n      expect(rumError.causes?.length).toBe(1)\n      expect(rumError.causes?.[0]).toEqual({\n        message: '{\"code\":\"NonInteger\",\"values\":[3.14,2.71]}',\n        source: ErrorSource.CUSTOM,\n        type: undefined,\n        stack: undefined,\n      })\n    })\n\n    it('should extract fingerprint from error', () => {\n      setupErrorCollection()\n\n      interface DatadogError extends Error {\n        dd_fingerprint?: string\n      }\n      const error = new Error('foo')\n      ;(error as DatadogError).dd_fingerprint = 'my-fingerprint'\n\n      addError({\n        error,\n        handlingStack: 'Error: handling foo',\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      })\n\n      expect((rawRumEvents[0].rawRumEvent as RawRumErrorEvent).error.fingerprint).toEqual('my-fingerprint')\n    })\n\n    it('should sanitize error fingerprint', () => {\n      setupErrorCollection()\n\n      const error = new Error('foo')\n      ;(error as any).dd_fingerprint = 2\n\n      addError({\n        error,\n        handlingStack: 'Error: handling foo',\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      })\n\n      expect((rawRumEvents[0].rawRumEvent as RawRumErrorEvent).error.fingerprint).toEqual('2')\n    })\n\n    it('should save the specified customer context', () => {\n      setupErrorCollection()\n      addError({\n        context: { foo: 'bar' },\n        error: new Error('foo'),\n        handlingStack: 'Error: handling foo',\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      })\n      expect((rawRumEvents[0].rawRumEvent as RawRumErrorEvent).context).toEqual({\n        foo: 'bar',\n      })\n    })\n\n    it('should include non-Error values in domain context', () => {\n      setupErrorCollection()\n      addError({\n        error: { foo: 'bar' },\n        handlingStack: 'Error: handling foo',\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      })\n      expect(rawRumEvents[0].domainContext).toEqual({\n        error: { foo: 'bar' },\n        handlingStack: 'Error: handling foo',\n      })\n    })\n\n    it('should include handling stack', () => {\n      setupErrorCollection()\n\n      addError({\n        error: new Error('foo'),\n        startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n        handlingStack: 'Error\\n    at foo\\n    at bar',\n      })\n      expect(rawRumEvents[0].domainContext).toEqual({\n        error: new Error('foo'),\n        handlingStack: 'Error\\n    at foo\\n    at bar',\n      })\n    })\n  })\n\n  describe('RAW_ERROR_COLLECTED LifeCycle event', () => {\n    it('should create error event from collected error', () => {\n      setupErrorCollection()\n      const error = new Error('hello')\n      lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, {\n        error: {\n          message: 'hello',\n          source: ErrorSource.CUSTOM,\n          stack: 'bar',\n          startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n          type: 'foo',\n          originalError: error,\n          handlingStack: 'Error: handling foo',\n          componentStack: 'at div',\n          context: { foo: 'bar' },\n        },\n      })\n\n      expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)\n      expect(rawRumEvents[0].rawRumEvent).toEqual({\n        date: jasmine.any(Number),\n        error: {\n          id: jasmine.any(String),\n          message: 'hello',\n          source: ErrorSource.CUSTOM,\n          stack: 'bar',\n          handling_stack: 'Error: handling foo',\n          component_stack: 'at div',\n          type: 'foo',\n          handling: undefined,\n          source_type: 'browser',\n          causes: undefined,\n          fingerprint: undefined,\n          csp: undefined,\n        },\n        type: RumEventType.ERROR,\n        context: { foo: 'bar' },\n      })\n      expect(rawRumEvents[0].domainContext).toEqual({\n        error,\n        handlingStack: 'Error: handling foo',\n      })\n    })\n\n    it('should extract disposition from Security Policy Violation Events', () => {\n      setupErrorCollection()\n\n      lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, {\n        error: {\n          message: 'hello',\n          source: ErrorSource.CUSTOM,\n          stack: 'bar',\n          startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n          type: 'foo',\n          originalError: FAKE_CSP_VIOLATION_EVENT,\n          handling: ErrorHandling.HANDLED,\n          csp: {\n            disposition: FAKE_CSP_VIOLATION_EVENT.disposition,\n          },\n        },\n      })\n\n      expect((rawRumEvents[0].rawRumEvent as RawRumErrorEvent).error.csp?.disposition).toEqual('enforce')\n    })\n\n    it('should merge dd_context from the original error with addError context', () => {\n      setupErrorCollection()\n      const error = new Error('foo')\n      ;(error as any).dd_context = { component: 'Menu', param: 123 }\n\n      addError({\n        error,\n        context: { user: 'john' },\n        handlingStack: 'Error: handling dd_context',\n        startClocks: { relative: 500 as RelativeTime, timeStamp: 500000 as TimeStamp },\n      })\n\n      expect((rawRumEvents[0].rawRumEvent as RawRumErrorEvent).context).toEqual({\n        component: 'Menu',\n        param: 123,\n        user: 'john',\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/error/errorCollection.ts",
    "content": "import type { Context, RawError, ClocksState, BufferedData } from '@datadog/browser-core'\nimport {\n  BufferedDataType,\n  Observable,\n  ErrorSource,\n  generateUUID,\n  computeRawError,\n  ErrorHandling,\n  NonErrorPrefix,\n  combine,\n} from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\nimport type { RawRumErrorEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { LifeCycle, RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { RumErrorEventDomainContext } from '../../domainContext.types'\nimport { trackConsoleError } from './trackConsoleError'\nimport { trackReportError } from './trackReportError'\n\nexport interface ProvidedError {\n  startClocks: ClocksState\n  error: unknown\n  context?: Context\n  handlingStack: string\n  componentStack?: string\n}\n\nexport function startErrorCollection(\n  lifeCycle: LifeCycle,\n  configuration: RumConfiguration,\n  bufferedDataObservable: Observable<BufferedData>\n) {\n  const errorObservable = new Observable<RawError>()\n\n  bufferedDataObservable.subscribe((bufferedData) => {\n    if (bufferedData.type === BufferedDataType.RUNTIME_ERROR) {\n      errorObservable.notify(bufferedData.error)\n    }\n  })\n\n  trackConsoleError(errorObservable)\n  trackReportError(configuration, errorObservable)\n\n  errorObservable.subscribe((error) => lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, { error }))\n\n  return doStartErrorCollection(lifeCycle)\n}\n\nexport function doStartErrorCollection(lifeCycle: LifeCycle) {\n  lifeCycle.subscribe(LifeCycleEventType.RAW_ERROR_COLLECTED, ({ error }) => {\n    lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processError(error))\n  })\n\n  return {\n    addError: ({ error, handlingStack, componentStack, startClocks, context }: ProvidedError) => {\n      const rawError = computeRawError({\n        originalError: error,\n        handlingStack,\n        componentStack,\n        startClocks,\n        nonErrorPrefix: NonErrorPrefix.PROVIDED,\n        source: ErrorSource.CUSTOM,\n        handling: ErrorHandling.HANDLED,\n      })\n      rawError.context = combine(rawError.context, context)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, { error: rawError })\n    },\n  }\n}\n\nfunction processError(error: RawError): RawRumEventCollectedData<RawRumErrorEvent> {\n  const rawRumEvent: RawRumErrorEvent = {\n    date: error.startClocks.timeStamp,\n    error: {\n      id: generateUUID(),\n      message: error.message,\n      source: error.source,\n      stack: error.stack,\n      handling_stack: error.handlingStack,\n      component_stack: error.componentStack,\n      type: error.type,\n      handling: error.handling,\n      causes: error.causes,\n      source_type: 'browser',\n      fingerprint: error.fingerprint,\n      csp: error.csp,\n    },\n    type: RumEventType.ERROR,\n    context: error.context,\n  }\n\n  const domainContext: RumErrorEventDomainContext = {\n    error: error.originalError,\n    handlingStack: error.handlingStack,\n  }\n\n  return {\n    rawRumEvent,\n    startClocks: error.startClocks,\n    domainContext,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/error/trackConsoleError.spec.ts",
    "content": "import type { RawError, Subscription } from '@datadog/browser-core'\nimport { ErrorHandling, ErrorSource, Observable, clocksNow } from '@datadog/browser-core'\nimport { ignoreConsoleLogs, mockClock } from '@datadog/browser-core/test'\nimport { trackConsoleError } from './trackConsoleError'\n\ndescribe('trackConsoleError', () => {\n  let errorObservable: Observable<RawError>\n  let subscription: Subscription\n  let notifyLog: jasmine.Spy\n\n  beforeEach(() => {\n    ignoreConsoleLogs('error', 'Error: foo')\n    errorObservable = new Observable()\n    notifyLog = jasmine.createSpy('notifyLog')\n    trackConsoleError(errorObservable)\n    subscription = errorObservable.subscribe(notifyLog)\n    mockClock()\n  })\n\n  afterEach(() => {\n    subscription.unsubscribe()\n  })\n\n  it('should track console error', () => {\n    const error = new TypeError('foo')\n\n    // eslint-disable-next-line no-console\n    console.error(error)\n\n    expect(notifyLog).toHaveBeenCalledWith({\n      startClocks: clocksNow(),\n      message: jasmine.any(String),\n      stack: jasmine.any(String),\n      source: ErrorSource.CONSOLE,\n      handling: ErrorHandling.HANDLED,\n      handlingStack: jasmine.any(String),\n      fingerprint: undefined,\n      causes: undefined,\n      context: undefined,\n      originalError: error,\n      type: 'TypeError',\n      componentStack: undefined,\n    })\n  })\n\n  it('should retrieve fingerprint from console error', () => {\n    interface DatadogError extends Error {\n      dd_fingerprint?: string\n    }\n    const error = new Error('foo')\n    ;(error as DatadogError).dd_fingerprint = 'my-fingerprint'\n\n    // eslint-disable-next-line no-console\n    console.error(error)\n\n    expect(notifyLog).toHaveBeenCalledWith({\n      startClocks: clocksNow(),\n      message: jasmine.any(String),\n      stack: jasmine.any(String),\n      source: ErrorSource.CONSOLE,\n      handling: ErrorHandling.HANDLED,\n      handlingStack: jasmine.any(String),\n      fingerprint: 'my-fingerprint',\n      causes: undefined,\n      context: undefined,\n      originalError: error,\n      type: 'Error',\n      componentStack: undefined,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/error/trackConsoleError.ts",
    "content": "import type { Observable, RawError } from '@datadog/browser-core'\nimport { initConsoleObservable, ConsoleApiName } from '@datadog/browser-core'\n\nexport function trackConsoleError(errorObservable: Observable<RawError>) {\n  const subscription = initConsoleObservable([ConsoleApiName.error]).subscribe((consoleLog) =>\n    errorObservable.notify(consoleLog.error)\n  )\n\n  return {\n    stop: () => {\n      subscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/error/trackReportError.spec.ts",
    "content": "import type { RawError, Subscription } from '@datadog/browser-core'\nimport { ErrorHandling, ErrorSource, Observable, clocksNow } from '@datadog/browser-core'\nimport type { MockCspEventListener, MockReportingObserver } from '@datadog/browser-core/test'\nimport {\n  FAKE_CSP_VIOLATION_EVENT,\n  FAKE_REPORT,\n  mockClock,\n  mockCspEventListener,\n  mockReportingObserver,\n  registerCleanupTask,\n} from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../../test'\nimport type { RumConfiguration } from '../configuration'\nimport { trackReportError } from './trackReportError'\n\ndescribe('trackReportError', () => {\n  let errorObservable: Observable<RawError>\n  let subscription: Subscription\n  let notifyLog: jasmine.Spy\n  let reportingObserver: MockReportingObserver\n  let cspEventListener: MockCspEventListener\n  let configuration: RumConfiguration\n\n  beforeEach(() => {\n    if (!window.ReportingObserver) {\n      pending('ReportingObserver not supported')\n    }\n    configuration = mockRumConfiguration()\n    errorObservable = new Observable()\n    notifyLog = jasmine.createSpy('notifyLog')\n    reportingObserver = mockReportingObserver()\n    subscription = errorObservable.subscribe(notifyLog)\n    mockClock()\n    registerCleanupTask(() => {\n      subscription.unsubscribe()\n    })\n    cspEventListener = mockCspEventListener()\n  })\n\n  it('should track reports', () => {\n    trackReportError(configuration, errorObservable)\n    reportingObserver.raiseReport('intervention')\n\n    expect(notifyLog).toHaveBeenCalledWith({\n      startClocks: clocksNow(),\n      message: jasmine.any(String),\n      stack: jasmine.any(String),\n      source: ErrorSource.REPORT,\n      handling: ErrorHandling.UNHANDLED,\n      type: 'NavigatorVibrate',\n      originalError: FAKE_REPORT,\n    })\n  })\n\n  it('should track securitypolicyviolation', () => {\n    trackReportError(configuration, errorObservable)\n    cspEventListener.dispatchEvent()\n\n    expect(notifyLog).toHaveBeenCalledWith({\n      startClocks: clocksNow(),\n      message: jasmine.any(String),\n      stack: jasmine.any(String),\n      source: ErrorSource.REPORT,\n      handling: ErrorHandling.UNHANDLED,\n      type: FAKE_CSP_VIOLATION_EVENT.effectiveDirective,\n      originalError: FAKE_CSP_VIOLATION_EVENT,\n      csp: {\n        disposition: FAKE_CSP_VIOLATION_EVENT.disposition,\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/error/trackReportError.ts",
    "content": "import type { Observable, RawError } from '@datadog/browser-core'\nimport { initReportObservable, RawReportType } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\n\nexport function trackReportError(configuration: RumConfiguration, errorObservable: Observable<RawError>) {\n  const subscription = initReportObservable(configuration, [\n    RawReportType.cspViolation,\n    RawReportType.intervention,\n  ]).subscribe((rawError) => errorObservable.notify(rawError))\n\n  return {\n    stop: () => {\n      subscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/event/eventCollection.spec.ts",
    "content": "import type { Duration, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport type { RumEventDomainContext } from '../../domainContext.types'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { RumEventType, VitalType } from '../../rawRumEvent.types'\nimport { startEventCollection } from './eventCollection'\n\ndescribe('eventCollection', () => {\n  let lifeCycle: LifeCycle\n  let notifySpy: jasmine.Spy\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n    notifySpy = spyOn(lifeCycle, 'notify')\n  })\n\n  it('should notify lifecycle with raw rum event when adding an event', () => {\n    const eventCollection = startEventCollection(lifeCycle)\n    const startTime = 123 as RelativeTime\n    const duration = 456 as Duration\n    const event = {\n      type: RumEventType.VITAL,\n      date: Date.now() as TimeStamp,\n      context: { foo: 'bar' },\n      vital: {\n        id: '123',\n        name: 'test-vital',\n        type: VitalType.DURATION,\n        duration: 100,\n      },\n    }\n    const domainContext: RumEventDomainContext = {}\n\n    eventCollection.addEvent(startTime, event, domainContext, duration)\n\n    expect(notifySpy).toHaveBeenCalledWith(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n      startClocks: { relative: startTime, timeStamp: jasmine.any(Number) },\n      rawRumEvent: event,\n      domainContext,\n      duration,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/event/eventCollection.ts",
    "content": "import { relativeToClocks } from '@datadog/browser-core'\nimport type { Context, Duration, RelativeTime } from '@datadog/browser-core'\nimport type { RumEventDomainContext } from '../../domainContext.types'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\n\nimport type {\n  RawRumActionEvent,\n  RawRumErrorEvent,\n  RawRumLongAnimationFrameEvent,\n  RawRumLongTaskEvent,\n  RawRumResourceEvent,\n  RawRumVitalEvent,\n} from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\n\nconst allowedEventTypes = [\n  RumEventType.ACTION,\n  RumEventType.ERROR,\n  RumEventType.LONG_TASK,\n  RumEventType.RESOURCE,\n  RumEventType.VITAL,\n] as const\n\nexport type AllowedRawRumEvent = (\n  | RawRumErrorEvent\n  | RawRumResourceEvent\n  | RawRumLongTaskEvent\n  | RawRumLongAnimationFrameEvent\n  | RawRumActionEvent\n  | RawRumVitalEvent\n) & { context?: Context }\n\nexport function startEventCollection(lifeCycle: LifeCycle) {\n  return {\n    addEvent: (\n      startTime: RelativeTime,\n      event: AllowedRawRumEvent,\n      domainContext: RumEventDomainContext,\n      duration?: Duration\n    ) => {\n      if (!allowedEventTypes.includes(event.type)) {\n        return\n      }\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        startClocks: relativeToClocks(startTime),\n        rawRumEvent: event,\n        domainContext,\n        duration,\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/eventTracker.spec.ts",
    "content": "import type { Duration, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { clocksNow } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport type { EventTracker } from './eventTracker'\nimport { startEventTracker } from './eventTracker'\n\ndescribe('eventTracker', () => {\n  let lifeCycle: LifeCycle\n  let tracker: EventTracker<{ value?: string; extra?: string }>\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    lifeCycle = new LifeCycle()\n    tracker = startEventTracker(lifeCycle)\n    registerCleanupTask(() => tracker.stopAll())\n  })\n\n  describe('start', () => {\n    it('should generate a unique ID for each event', () => {\n      const startClocks = clocksNow()\n      tracker.start('key1', startClocks, { value: 'data1' })\n      tracker.start('key2', startClocks, { value: 'data2' })\n\n      const stopped1 = tracker.stop('key1', startClocks)\n      const stopped2 = tracker.stop('key2', startClocks)\n\n      expect(stopped1?.id).toBeDefined()\n      expect(stopped2?.id).toBeDefined()\n      expect(stopped1?.id).not.toBe(stopped2?.id)\n    })\n\n    it('should disable event counting by default', () => {\n      const startClocks = clocksNow()\n      tracker.start('key1', startClocks, { value: 'data' })\n\n      const stopped = tracker.stop('key1', clocksNow())\n\n      expect(stopped?.counts).toBeUndefined()\n    })\n\n    it('should enable event counting when isChildEvent is provided', () => {\n      const startClocks = clocksNow()\n      tracker.start('key1', startClocks, { value: 'data' }, { isChildEvent: () => () => true })\n\n      const stopped = tracker.stop('key1', clocksNow())\n\n      expect(stopped?.counts).toBeDefined()\n      expect(stopped?.counts?.errorCount).toBe(0)\n    })\n  })\n\n  describe('stop', () => {\n    it('should return undefined for non-existent key', () => {\n      expect(tracker.stop('non-existent', clocksNow())).toBeUndefined()\n    })\n\n    it('should return stopped event with correct structure', () => {\n      const startClocks = clocksNow()\n      tracker.start('key1', startClocks, { value: 'data1' })\n      clock.tick(500)\n\n      const stopped = tracker.stop('key1', clocksNow())\n\n      expect(stopped).toEqual({\n        id: jasmine.any(String),\n        startClocks,\n        duration: 500 as Duration,\n        counts: undefined,\n        value: 'data1',\n      })\n    })\n\n    it('should merge extraData with start data', () => {\n      tracker.start('key1', clocksNow(), { value: 'original' })\n\n      const stopped = tracker.stop('key1', clocksNow(), { extra: 'additional' })\n\n      expect(stopped).toEqual(\n        jasmine.objectContaining({\n          value: 'original',\n          extra: 'additional',\n        })\n      )\n    })\n\n    it('should compute duration from timestamps, not relative times', () => {\n      const startClocks = { relative: 100 as RelativeTime, timeStamp: 1000 as TimeStamp }\n      tracker.start('key1', startClocks, { value: 'data1' })\n\n      const endClocks = { relative: 300 as RelativeTime, timeStamp: 1050 as TimeStamp }\n\n      const stopped = tracker.stop('key1', endClocks)\n\n      expect(stopped?.duration).toBe(50 as Duration)\n    })\n  })\n\n  describe('findId', () => {\n    it('should return empty array when no events are tracked', () => {\n      expect(tracker.findId()).toEqual([])\n    })\n\n    it('should return array of IDs for active events', () => {\n      const startClocks = { relative: 100 as RelativeTime, timeStamp: 1000 as TimeStamp }\n      tracker.start('key1', startClocks, { value: 'data1' })\n      tracker.start('key2', startClocks, { value: 'data2' })\n\n      const result = tracker.findId()\n\n      expect(Array.isArray(result)).toBeTrue()\n      expect(result).toHaveSize(2)\n    })\n\n    it('should find events within their time range', () => {\n      const startClocks = { relative: 100 as RelativeTime, timeStamp: 1000 as TimeStamp }\n      tracker.start('key1', startClocks, { value: 'data' })\n      const stopped = tracker.stop('key1', { relative: 200 as RelativeTime, timeStamp: 2000 as TimeStamp })\n\n      expect(tracker.findId(150 as RelativeTime)).toEqual([stopped!.id])\n      expect(tracker.findId(250 as RelativeTime)).toEqual([])\n    })\n\n    it('should not include discarded events', () => {\n      tracker.start('key1', clocksNow(), { value: 'data' })\n      tracker.discard('key1')\n\n      expect(tracker.findId()).toEqual([])\n    })\n  })\n\n  describe('stopAll', () => {\n    it('should clear all events', () => {\n      const startClocks = clocksNow()\n\n      tracker.start('key1', startClocks, { value: 'data1' })\n      tracker.start('key2', startClocks, { value: 'data2' })\n\n      tracker.stopAll()\n\n      expect(tracker.stop('key1', clocksNow())).toBeUndefined()\n      expect(tracker.stop('key2', clocksNow())).toBeUndefined()\n    })\n\n    it('should unsubscribe from session renewal events', () => {\n      tracker.start('key1', clocksNow(), { value: 'data1' })\n\n      tracker.stopAll()\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n      expect(tracker.findId()).toEqual([])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/eventTracker.ts",
    "content": "import type { ClocksState, Duration, RelativeTime, ValueHistoryEntry } from '@datadog/browser-core'\nimport { ONE_MINUTE, generateUUID, createValueHistory, elapsed, combine } from '@datadog/browser-core'\nimport type { RumActionEvent, RumErrorEvent, RumLongTaskEvent, RumResourceEvent } from '../rumEvent.types'\nimport { LifeCycleEventType } from './lifeCycle'\nimport type { LifeCycle } from './lifeCycle'\nimport type { EventCounts } from './trackEventCounts'\nimport { trackEventCounts } from './trackEventCounts'\n\nexport const EVENT_CONTEXT_TIME_OUT_DELAY = 5 * ONE_MINUTE // arbitrary\n\ntype BaseTrackedEvent<TData = object> = TData & {\n  id: string\n  startClocks: ClocksState\n  counts?: EventCounts\n}\n\nexport type StoppedEvent<TData> = BaseTrackedEvent<TData> & {\n  duration: Duration\n}\n\nexport type DiscardedEvent<TData> = BaseTrackedEvent<TData>\n\nexport interface StartOptions {\n  isChildEvent?: (\n    id: string\n  ) => (event: RumActionEvent | RumErrorEvent | RumLongTaskEvent | RumResourceEvent) => boolean\n}\n\nexport interface EventTracker<TData> {\n  start: (key: string, startClocks: ClocksState, data: TData, options?: StartOptions) => TrackedEventData<TData>\n  stop: (key: string, stopClocks: ClocksState, data?: Partial<TData>) => StoppedEvent<TData> | undefined\n  discard: (key: string) => DiscardedEvent<TData> | undefined\n  getCounts: (key: string) => EventCounts | undefined\n  findId: (startTime?: RelativeTime) => string[]\n  stopAll: () => void\n}\n\nexport interface TrackedEventData<TData> {\n  id: string\n  key: string\n  startClocks: ClocksState\n  data: TData\n  historyEntry: ValueHistoryEntry<string>\n  eventCounts?: ReturnType<typeof trackEventCounts>\n}\n\nexport function startEventTracker<TData>(lifeCycle: LifeCycle): EventTracker<TData> {\n  // Used by actions to associate events with actions.\n  const history = createValueHistory<string>({ expireDelay: EVENT_CONTEXT_TIME_OUT_DELAY })\n  // Used by manual actions and resources that use named keys to match the start and stop calls.\n  const keyedEvents = new Map<string, TrackedEventData<TData>>()\n\n  function cleanUpEvent(event: TrackedEventData<TData>) {\n    keyedEvents.delete(event.key)\n\n    event.eventCounts?.stop()\n  }\n\n  function discardAll() {\n    keyedEvents.forEach((event) => {\n      cleanUpEvent(event)\n    })\n\n    history.reset()\n  }\n\n  const sessionRenewalSubscription = lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, discardAll)\n\n  function start(key: string, startClocks: ClocksState, data: TData, options?: StartOptions): TrackedEventData<TData> {\n    const id = generateUUID()\n\n    const historyEntry = history.add(id, startClocks.relative)\n\n    const existing = keyedEvents.get(key)\n    if (existing) {\n      cleanUpEvent(existing)\n    }\n\n    const eventCounts = options?.isChildEvent\n      ? trackEventCounts({\n          lifeCycle,\n          isChildEvent: options.isChildEvent(id),\n        })\n      : undefined\n\n    const trackedEventData: TrackedEventData<TData> = {\n      id,\n      key,\n      startClocks,\n      data,\n      historyEntry,\n      eventCounts,\n    }\n\n    keyedEvents.set(key, trackedEventData)\n    return trackedEventData\n  }\n\n  function stop(key: string, stopClocks: ClocksState, extraData?: Partial<TData>): StoppedEvent<TData> | undefined {\n    const event = keyedEvents.get(key)\n    if (!event) {\n      return undefined\n    }\n\n    const finalData = extraData ? (combine(event.data, extraData) as TData) : event.data\n\n    event.historyEntry.close(stopClocks.relative)\n\n    const duration = elapsed(event.startClocks.timeStamp, stopClocks.timeStamp)\n\n    const counts = event.eventCounts?.eventCounts\n\n    cleanUpEvent(event)\n\n    return {\n      ...finalData,\n      id: event.id,\n      startClocks: event.startClocks,\n      duration,\n      counts,\n    }\n  }\n\n  function discard(key: string): DiscardedEvent<TData> | undefined {\n    const event = keyedEvents.get(key)\n    if (!event) {\n      return undefined\n    }\n\n    const counts = event.eventCounts?.eventCounts\n\n    cleanUpEvent(event)\n\n    event.historyEntry.remove()\n\n    return {\n      ...event.data,\n      id: event.id,\n      startClocks: event.startClocks,\n      counts,\n    }\n  }\n\n  function findId(startTime?: RelativeTime): string[] {\n    return history.findAll(startTime)\n  }\n\n  function getCounts(key: string): EventCounts | undefined {\n    return keyedEvents.get(key)?.eventCounts?.eventCounts\n  }\n\n  function stopTracker() {\n    sessionRenewalSubscription.unsubscribe()\n    discardAll()\n    history.stop()\n  }\n\n  return {\n    start,\n    stop,\n    discard,\n    getCounts,\n    findId,\n    stopAll: stopTracker,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/extractRegexMatch.ts",
    "content": "/**\n * Executes a RegExp against a string and returns the first capture group, or the full match if\n * there is no capture group. Returns undefined when the pattern does not match.\n */\nexport function extractRegexMatch(candidate: string, extractor: RegExp): string | undefined {\n  // Prevent stateful matching when the RegExp has the global or sticky flag\n  extractor.lastIndex = 0\n\n  const regexResult = extractor.exec(candidate)\n  if (!regexResult) {\n    return undefined\n  }\n  const [match, capture] = regexResult\n  return capture ? capture : match\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/getComposedPathSelector.spec.ts",
    "content": "import { appendElement } from '../../test'\nimport { getComposedPathSelector, CHARACTER_LIMIT } from './getComposedPathSelector'\n\n/** Appends content inside a wrapper so the element is the only child (no nth-child from body). */\nfunction appendElementInIsolation(html: string): HTMLElement {\n  const wrapper = appendElement('<div></div>')\n  return appendElement(html, wrapper)\n}\n\ndescribe('getSelectorFromComposedPath', () => {\n  describe('getComposedPathSelector', () => {\n    it('returns an empty string for an empty composedPath', () => {\n      const result = getComposedPathSelector([], undefined)\n      expect(result).toEqual('')\n    })\n\n    it('filters out non-Element items from composedPath', () => {\n      const element = appendElementInIsolation('<div id=\"test\"></div>')\n      const composedPath: EventTarget[] = [element, document.body, document, window]\n\n      const result = getComposedPathSelector(composedPath, undefined)\n\n      expect(result).toBe('DIV#test;')\n    })\n\n    it('ignores BODY and HTML elements from the composedPath', () => {\n      const composedPath: EventTarget[] = [document.body, document.documentElement]\n\n      const result = getComposedPathSelector(composedPath, undefined)\n\n      expect(result).toBe('')\n    })\n\n    describe('element data extraction', () => {\n      it('extracts tag name from element', () => {\n        const element = appendElementInIsolation('<button></button>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('BUTTON;')\n      })\n\n      it('extracts id from element when present', () => {\n        const element = appendElementInIsolation('<div id=\"my-id\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV#my-id;')\n      })\n\n      it('does not include id when not present', () => {\n        const element = appendElementInIsolation('<div></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV;')\n      })\n\n      it('extracts sorted classes from element', () => {\n        const element = appendElementInIsolation('<div class=\"foo bar baz\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV.bar.baz.foo;')\n      })\n\n      it('excludes generated class names containing digits', () => {\n        const element = appendElementInIsolation('<div class=\"foo1 bar\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV.bar;')\n      })\n    })\n\n    describe('safe attribute filtering', () => {\n      it('collects multiple safe attributes', () => {\n        const element = appendElementInIsolation('<div data-testid=\"foo\" data-qa=\"bar\" data-cy=\"baz\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV[data-cy=\"baz\"][data-qa=\"bar\"][data-testid=\"foo\"];')\n      })\n\n      it('does not collect non-allowlisted attributes', () => {\n        const element = appendElementInIsolation('<div data-user-email=\"john@example.com\" title=\"secret info\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV;')\n      })\n\n      it('collects data-dd-action-name attribute', () => {\n        const element = appendElementInIsolation('<div data-dd-action-name=\"Submit Form\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe(`DIV[data-dd-action-name=\"${CSS.escape('Submit Form')}\"];`)\n      })\n\n      it('collects role attribute', () => {\n        const element = appendElementInIsolation('<div role=\"button\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV[role=\"button\"];')\n      })\n\n      it('collects type attribute', () => {\n        const element = appendElementInIsolation('<input type=\"submit\" />')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('INPUT[type=\"submit\"];')\n      })\n\n      it('collects attribute containing separator characters ;', () => {\n        const element = appendElementInIsolation('<div data-testid=\"foo;bar\" />')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV[data-testid=\"foo\\\\;bar\"];')\n      })\n    })\n\n    describe('nthChild and nthOfType', () => {\n      it('does not include nthChild when element is the only child', () => {\n        const element = appendElement(`<div>\n          <span target></span>\n        </div>`)\n\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('SPAN;')\n      })\n\n      it('includes nthChild when element has siblings', () => {\n        const element = appendElement(`<div>\n          <span></span>\n          <div></div>\n          <span target></span>\n        </div>`)\n\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('SPAN:nth-child(3):nth-of-type(2);')\n      })\n\n      it('calculates nthChild correctly for first child', () => {\n        const element = appendElement(`<div>\n          <span target></span>\n          <div></div>\n        </div>`)\n\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('SPAN:nth-child(1);')\n      })\n\n      it('does not include nthOfType when element is unique of its type', () => {\n        const parent = appendElement('<div></div>')\n        const span = appendElement('<span></span>', parent)\n        appendElement('<div></div>', parent)\n\n        const result = getComposedPathSelector([span], undefined)\n\n        // span is unique of type, but not unique child (has sibling)\n        expect(result).toBe('SPAN:nth-child(1);')\n      })\n\n      it('includes nthOfType when the first element has same-type siblings', () => {\n        const span1 = appendElement(`\n          <div>\n            <span target></span>\n            <div></div>\n            <span></span>\n          </div>\n        `)\n\n        const result = getComposedPathSelector([span1], undefined)\n\n        expect(result).toBe('SPAN:nth-child(1):nth-of-type(1);')\n      })\n\n      it('calculates nthOfType correctly among mixed siblings', () => {\n        const button = appendElement(`\n          <div>\n            <button></button>\n            <div></div>\n            <button target></button>\n          </div>\n        `)\n\n        const result = getComposedPathSelector([button], undefined)\n\n        expect(result).toBe('BUTTON:nth-child(3):nth-of-type(2);')\n      })\n\n      it('handles elements in composedPath with their position data', () => {\n        const grandparent = appendElementInIsolation('<div></div>')\n        const parent = appendElement('<section target></section><article></article>', grandparent)\n        const target = appendElement('<button></button>', parent)\n\n        const composedPath = [target, parent, grandparent]\n        const result = getComposedPathSelector(composedPath, undefined)\n\n        expect(result).toBe('BUTTON;SECTION:nth-child(1);DIV;')\n      })\n\n      it('does not include nthChild or nthOfType for elements without parent', () => {\n        // Detached element with no parent\n        const element = appendElementInIsolation('<div></div>')\n\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV;')\n      })\n    })\n\n    describe('truncation', () => {\n      it('truncates the selector if it exceeds the character limit', () => {\n        // generate an array of 1000 elements to test a long composedPath\n        const composedPath = Array.from({ length: 1000 }, () =>\n          appendElement('<div data-testid=\"test-btn\" class=\"secret\"></div>')\n        )\n        const result = getComposedPathSelector(composedPath, undefined)\n\n        expect(result.length).toBeLessThanOrEqual(CHARACTER_LIMIT)\n      })\n    })\n\n    describe('edge cases', () => {\n      it('handles elements with empty class attribute', () => {\n        const element = appendElementInIsolation('<div class=\"\"></div>')\n        const result = getComposedPathSelector([element], undefined)\n\n        expect(result).toBe('DIV;')\n      })\n\n      it('handles elements with whitespace-only class', () => {\n        const element = appendElement('<div><div target class=\"   \"></div></div>')\n\n        const result = getComposedPathSelector([element], undefined)\n        expect(result).toBe('DIV;')\n      })\n\n      it('handles SVG elements', () => {\n        const element = appendElement('<div><svg target data-testid=\"my-svg\" g=\"1\"></svg></div>')\n\n        const result = getComposedPathSelector([element], undefined)\n\n        // tagName for SVG in HTML document is lowercase\n        expect(result).toBe('svg[data-testid=\"my-svg\"];')\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/getComposedPathSelector.ts",
    "content": "import { safeTruncate, ONE_KIBI_BYTE } from '@datadog/browser-core'\nimport type { MatchOption } from '@datadog/browser-core'\nimport {\n  STABLE_ATTRIBUTES,\n  isGeneratedValue,\n  getIDSelector,\n  getTagNameSelector,\n  getNthOfTypeSelector,\n  getAttributeValueSelector,\n} from './getSelectorFromElement'\n\nconst FILTERED_TAGNAMES = ['HTML', 'BODY']\n\n/**\n * arbitrary value, we want to truncate the selector if it exceeds the limit\n */\nexport const CHARACTER_LIMIT = 2 * ONE_KIBI_BYTE\n\n/**\n * Safe attributes that can be collected without PII concerns.\n * These are commonly used for testing, accessibility, and UI identification.\n */\nexport const SAFE_ATTRIBUTES = STABLE_ATTRIBUTES.concat([\n  'role',\n  'type',\n  'disabled',\n  'readonly',\n  'tabindex',\n  'draggable',\n  'target',\n  'rel',\n  'download',\n  'method',\n  'action',\n  'enctype',\n  'autocomplete',\n])\n\n/**\n * Extracts a selector string from a MouseEvent composedPath.\n *\n * This function:\n * 1. Filters out non-Element items (Document, Window, ShadowRoot)\n * 2. Extracts a selector string from each element\n * 3. Truncates the selector string if it exceeds the character limit\n * 4. Returns the selector string\n *\n * @param composedPath - The composedPath from a MouseEvent\n * @returns A selector string\n */\nexport function getComposedPathSelector(composedPath: EventTarget[], actionNameAttribute: string | undefined): string {\n  // Filter to only include Element nodes\n  const elements = composedPath.filter(\n    (el): el is Element => el instanceof Element && !FILTERED_TAGNAMES.includes(el.tagName)\n  )\n\n  if (elements.length === 0) {\n    return ''\n  }\n\n  const allowedAttributes = actionNameAttribute ? [actionNameAttribute].concat(SAFE_ATTRIBUTES) : SAFE_ATTRIBUTES\n\n  let result = ''\n  for (const element of elements) {\n    const part = getSelectorStringFromElement(element, allowedAttributes)\n    result += part\n    if (result.length >= CHARACTER_LIMIT) {\n      return safeTruncate(result, CHARACTER_LIMIT)\n    }\n  }\n  return result\n}\n\n/**\n * Extracts a selector string from an element.\n */\nfunction getSelectorStringFromElement(element: Element, allowedAttributes: MatchOption[]): string {\n  const tagName = getTagNameSelector(element)\n  const id = getIDSelector(element)\n  const classes = getElementClassesString(element)\n  const attributes = extractSafeAttributesString(element, allowedAttributes)\n  const positionData = computePositionDataString(element)\n\n  return `${tagName}${id || ''}${attributes}${classes}${positionData};`\n}\n\nfunction getElementClassesString(element: Element): string {\n  return Array.from(element.classList)\n    .filter((c) => !isGeneratedValue(c))\n    .sort()\n    .map((c) => `.${CSS.escape(c)}`)\n    .join('')\n}\n\n/**\n * Computes the nthChild and nthOfType positions for an element.\n *\n * @param element - The element to compute the position data for\n * @returns A string of the form \":nth-child(1):nth-of-type(1)\"\n */\nfunction computePositionDataString(element: Element): string {\n  const siblings = Array.from(element.parentNode!.children)\n\n  if (siblings.length <= 1) {\n    return ''\n  }\n\n  const sameTypeSiblings = siblings.filter((sibling) => sibling.tagName === element.tagName)\n\n  const nthChild = siblings.indexOf(element)\n\n  const nthOfType = getNthOfTypeSelector(element)\n\n  return `:nth-child(${nthChild + 1})${sameTypeSiblings.length > 1 ? `:nth-of-type(${nthOfType})` : ''}`\n}\n\n/**\n * Extracts only the safe (allowlisted) attributes from an element.\n * The attributes are sorted alphabetically by name.\n */\nfunction extractSafeAttributesString(element: Element, allowedAttributes: MatchOption[]): string {\n  const result: string[] = []\n  const attributes = Array.from(element.attributes)\n  for (const attribute of attributes) {\n    if (allowedAttributes.includes(attribute.name)) {\n      result.push(getAttributeValueSelector(attribute.name, attribute.value))\n    }\n  }\n  return result.sort().join('')\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/getSelectorFromElement.spec.ts",
    "content": "import { appendElement } from '../../test'\nimport { getSelectorFromElement, isSelectorUniqueAmongSiblings, SHADOW_DOM_MARKER } from './getSelectorFromElement'\n\ndescribe('getSelectorFromElement', () => {\n  afterEach(() => {\n    document.body.classList.remove('foo')\n  })\n\n  it('returns undefined for detached elements', () => {\n    const element = document.createElement('div')\n    expect(getSelector(element)).toBeUndefined()\n  })\n\n  describe('ID selector', () => {\n    it('should use the ID selector when the element as an ID', () => {\n      expect(getSelector('<div id=\"foo\"></div>')).toBe('#foo')\n    })\n\n    it('should not use the ID selector when the ID is not unique', () => {\n      expect(getSelector('<div id=\"foo\"></div><div id=\"foo\"></div>')).not.toContain('#foo')\n    })\n\n    it('should not use generated IDs', () => {\n      expect(getSelector('<div id=\"foo4\"></div>')).toBe('BODY>DIV')\n    })\n  })\n\n  describe('class selector', () => {\n    it('should use the class selector when the element as classes', () => {\n      expect(getSelector('<div target class=\"foo\"></div>')).toBe('BODY>DIV.foo')\n    })\n\n    it('should use the class selector when siblings have the same classes but different tags', () => {\n      expect(getSelector('<div target class=\"foo\"></div><span class=\"foo\"></span>')).toBe('BODY>DIV.foo')\n    })\n\n    it('should not use the class selector when siblings have the tag + classes', () => {\n      expect(getSelector('<div target class=\"foo\"></div><div class=\"foo\"></div>')).not.toContain('DIV.foo')\n      expect(getSelector('<div target class=\"foo bar\"></div><div class=\"bar foo baz\"></div>')).not.toContain('DIV.foo')\n    })\n\n    it('should not use the class selector for body elements', () => {\n      const element = appendElement('<div></div>')\n      document.body.classList.add('foo')\n      expect(getSelector(element)).toBe('BODY>DIV')\n    })\n\n    it('should not use generated classes', () => {\n      expect(getSelector('<div class=\"foo4\"></div>')).toBe('BODY>DIV')\n    })\n\n    it('uses only the first class', () => {\n      expect(getSelector('<div class=\"foo bar baz baa\"></div>')).toBe('BODY>DIV.foo')\n    })\n  })\n\n  describe('position selector', () => {\n    it('should use nth-of-type when the selector matches multiple descendants', () => {\n      expect(\n        getSelector(`\n            <span></span>\n            <div><button></button></div>\n            <span></span>\n            <div><button target></button></div>\n          `)\n      ).toBe('BODY>DIV:nth-of-type(2)>BUTTON')\n    })\n\n    it('should not use nth-of-type when the selector is matching a single descendant', () => {\n      expect(\n        getSelector(`\n          <div></div>\n          <div><button target></button></div>\n        `)\n      ).toBe('BODY>DIV>BUTTON')\n    })\n\n    it('should only consider direct descendants (>) of the parent element when checking for unicity', () => {\n      expect(\n        getSelector(`\n          <main>\n            <div><div><button></button></div></div>\n            <div><button target></button></div>\n          </main>\n        `)\n      ).toBe('BODY>MAIN>DIV>BUTTON')\n    })\n  })\n\n  describe('strategies priority', () => {\n    it('ID selector should take precedence over class selector', () => {\n      expect(getSelector('<div id=\"foo\" class=\"bar\"></div>')).toBe('#foo')\n    })\n\n    it('class selector should take precedence over position selector', () => {\n      expect(getSelector('<div class=\"bar\"></div><div></div>')).toBe('BODY>DIV.bar')\n    })\n  })\n\n  describe('should escape CSS selectors', () => {\n    it('on ID value', () => {\n      expect(getSelector('<div id=\"#bar\"></div>')).toBe('#\\\\#bar')\n    })\n\n    it('on attribute value', () => {\n      expect(getSelector('<div data-testid=\"&quot;foo bar&quot;\"></div>')).toBe('DIV[data-testid=\"\\\\\"foo\\\\ bar\\\\\"\"]')\n    })\n\n    it('on class name', () => {\n      expect(getSelector('<div class=\"#bar\"</div>')).toBe('BODY>DIV.\\\\#bar')\n    })\n\n    it('on tag name', () => {\n      expect(getSelector('<div&nbsp;span>></div&nbsp;span>')).toBe('BODY>DIV\\\\&NBSP\\\\;SPAN')\n    })\n  })\n\n  describe('attribute selector', () => {\n    it('uses a stable attribute if the element has one', () => {\n      expect(getSelector('<div data-testid=\"foo\"></div>')).toBe('DIV[data-testid=\"foo\"]')\n    })\n\n    it('attribute selector with the custom action name attribute takes precedence over other stable attribute selectors', () => {\n      expect(getSelector('<div action-name=\"foo\" data-testid=\"bar\"></div>', 'action-name')).toBe(\n        'DIV[action-name=\"foo\"]'\n      )\n    })\n\n    it('stable attribute selector should take precedence over class selector', () => {\n      expect(getSelector('<div class=\"foo\" data-testid=\"foo\"></div>')).toBe('DIV[data-testid=\"foo\"]')\n    })\n\n    it('stable attribute selector should take precedence over ID selector', () => {\n      expect(getSelector('<div id=\"foo\" data-testid=\"foo\"></div>')).toBe('DIV[data-testid=\"foo\"]')\n    })\n\n    it(\"uses a stable attribute selector and continue recursing if it's not unique globally\", () => {\n      expect(\n        getSelector(`\n            <button target data-testid=\"foo\"></button>\n\n            <div>\n              <button data-testid=\"foo\"></button>\n            </div>\n          `)\n      ).toBe('BODY>BUTTON[data-testid=\"foo\"]')\n    })\n  })\n\n  it('should compute a CSS selector on SVG elements', () => {\n    const element = appendElement('<svg class=\"foo\"></svg>')\n    expect(getSelector(element)).toBe('BODY>svg.foo')\n  })\n\n  function getSelector(htmlOrElement: string | Element, actionNameAttribute?: string): string | undefined {\n    return getSelectorFromElement(\n      typeof htmlOrElement === 'string' ? appendElement(htmlOrElement) : htmlOrElement,\n      actionNameAttribute\n    )\n  }\n})\n\ndescribe('isSelectorUniqueAmongSiblings', () => {\n  it('returns true when the element is alone', () => {\n    const element = appendElement('<div></div>')\n    expect(isSelectorUniqueAmongSiblings(element, document, 'DIV', undefined)).toBeTrue()\n  })\n\n  it('returns false when a sibling element matches the element selector', () => {\n    const element = appendElement(`\n      <div target></div>\n      <div></div>\n    `)\n    expect(isSelectorUniqueAmongSiblings(element, document, 'DIV', undefined)).toBeFalse()\n  })\n\n  it('returns true when the element selector does not match any sibling', () => {\n    const element = appendElement(`\n      <div target></div>\n      <span></span>\n    `)\n    expect(isSelectorUniqueAmongSiblings(element, document, 'DIV', undefined)).toBeTrue()\n  })\n\n  it('returns false when the child selector matches an element in a sibling', () => {\n    const element = appendElement(`\n      <div target>\n        <hr>\n      </div>\n      <div>\n        <hr>\n      </div>\n    `)\n    expect(isSelectorUniqueAmongSiblings(element, document, 'DIV', 'HR')).toBeFalse()\n  })\n\n  it('returns true when the current element selector does not match the sibling', () => {\n    const element = appendElement(`\n      <div target>\n        <hr>\n      </div>\n      <h1>\n        <hr>\n      </h1>\n    `)\n    expect(isSelectorUniqueAmongSiblings(element, document, 'DIV', 'HR')).toBeTrue()\n  })\n\n  it('the selector should not consider elements deep in the tree', () => {\n    const element = appendElement(`\n      <div target>\n        <hr>\n      </div>\n      <h1>\n        <div>\n          <hr>\n        </div>\n      </h1>\n    `)\n    expect(isSelectorUniqueAmongSiblings(element, document, 'DIV', 'HR')).toBeTrue()\n  })\n})\n\ndescribe('getSelectorFromElement with shadow DOM', () => {\n  it('should generate selector with shadow marker for element inside shadow DOM', () => {\n    const host = appendElement('<div id=\"shadow-host\"></div>')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n    const button = document.createElement('button')\n    button.classList.add('shadow-button')\n    shadowRoot.appendChild(button)\n\n    const selector = getSelectorFromElement(button, undefined)\n    expect(selector).toBe(`#shadow-host${SHADOW_DOM_MARKER}BUTTON.shadow-button`)\n  })\n\n  it('should use stable attribute for element inside shadow DOM with shadow marker', () => {\n    const host = appendElement('<div></div>')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n    const button = document.createElement('button')\n    button.setAttribute('data-testid', 'shadow-test')\n    shadowRoot.appendChild(button)\n\n    const selector = getSelectorFromElement(button, undefined)\n    expect(selector).toBe(`BODY>DIV${SHADOW_DOM_MARKER}BUTTON[data-testid=\"shadow-test\"]`)\n  })\n\n  it('should insert shadow marker when traversing shadow boundary', () => {\n    const host = appendElement('<div id=\"my-host\"></div>')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n    const button = document.createElement('button')\n    shadowRoot.appendChild(button)\n\n    const selector = getSelectorFromElement(button, undefined)\n    expect(selector).toBe(`#my-host${SHADOW_DOM_MARKER}BUTTON`)\n  })\n\n  it('should handle nested shadow DOMs with multiple markers', () => {\n    const outerHost = appendElement('<div data-testid=\"outer-host\"></div>')\n    const outerShadowRoot = outerHost.attachShadow({ mode: 'open' })\n\n    const innerHost = document.createElement('div')\n    innerHost.setAttribute('data-testid', 'inner-host')\n    outerShadowRoot.appendChild(innerHost)\n    const innerShadowRoot = innerHost.attachShadow({ mode: 'open' })\n\n    const button = document.createElement('button')\n    button.setAttribute('data-testid', 'deep-button')\n    innerShadowRoot.appendChild(button)\n\n    const selector = getSelectorFromElement(button, undefined)\n    expect(selector).toBe(\n      `DIV[data-testid=\"outer-host\"]${SHADOW_DOM_MARKER}DIV[data-testid=\"inner-host\"]${SHADOW_DOM_MARKER}BUTTON[data-testid=\"deep-button\"]`\n    )\n  })\n\n  it('should use position selector inside shadow DOM with shadow marker', () => {\n    const host = appendElement('<div></div>')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n\n    const div1 = document.createElement('div')\n    const span1 = document.createElement('span')\n    div1.appendChild(span1)\n\n    const div2 = document.createElement('div')\n    const target = document.createElement('span')\n    div2.appendChild(target)\n\n    shadowRoot.appendChild(div1)\n    shadowRoot.appendChild(div2)\n\n    const selector = getSelectorFromElement(target, undefined)\n    // Both divs have a span, so DIV>SPAN is not unique, need nth-of-type\n    expect(selector).toBe(`BODY>DIV${SHADOW_DOM_MARKER}DIV:nth-of-type(2)>SPAN`)\n  })\n\n  it('should generate unique selector when siblings exist inside shadow DOM', () => {\n    const host = appendElement('<div id=\"host\"></div>')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n\n    const button1 = document.createElement('button')\n    button1.classList.add('first')\n    const button2 = document.createElement('button')\n    button2.classList.add('second')\n\n    shadowRoot.appendChild(button1)\n    shadowRoot.appendChild(button2)\n\n    const selector1 = getSelectorFromElement(button1, undefined)\n    const selector2 = getSelectorFromElement(button2, undefined)\n\n    expect(selector1).toBe(`#host${SHADOW_DOM_MARKER}BUTTON.first`)\n    expect(selector2).toBe(`#host${SHADOW_DOM_MARKER}BUTTON.second`)\n  })\n\n  it('should NOT add shadow marker for elements in light DOM', () => {\n    const element = appendElement('<div><button class=\"light-btn\"></button></div>')\n    const button = element.querySelector('button')!\n\n    const selector = getSelectorFromElement(button, undefined)\n    expect(selector).toBe('BODY>DIV>BUTTON.light-btn')\n  })\n\n  it('should generate DIFFERENT selectors for buttons in two identical shadow hosts', () => {\n    const container = appendElement('<div id=\"test-container\"></div>')\n\n    const host1 = document.createElement('my-button')\n    const host2 = document.createElement('my-button')\n    container.appendChild(host1)\n    container.appendChild(host2)\n\n    const shadow1 = host1.attachShadow({ mode: 'open' })\n    const shadow2 = host2.attachShadow({ mode: 'open' })\n\n    const button1 = document.createElement('button')\n    button1.textContent = 'Button 1'\n    shadow1.appendChild(button1)\n\n    const button2 = document.createElement('button')\n    button2.textContent = 'Button 2'\n    shadow2.appendChild(button2)\n\n    const selector1 = getSelectorFromElement(button1, undefined)\n    const selector2 = getSelectorFromElement(button2, undefined)\n\n    expect(selector1).toBe(`#test-container>MY-BUTTON:nth-of-type(1)${SHADOW_DOM_MARKER}BUTTON`)\n    expect(selector2).toBe(`#test-container>MY-BUTTON:nth-of-type(2)${SHADOW_DOM_MARKER}BUTTON`)\n  })\n\n  it('should handle duplicated IDs between light DOM and shadow DOM', () => {\n    const host = appendElement('<div id=\"foo\"></div>')\n    const shadowRoot = host.attachShadow({ mode: 'open' })\n    const button = document.createElement('button')\n    button.id = 'foo'\n    shadowRoot.appendChild(button)\n\n    const selector = getSelectorFromElement(button, undefined)\n    expect(selector).toBe(`#foo${SHADOW_DOM_MARKER}#foo`)\n  })\n\n  it('returns false when element is in DocumentFragment with matching siblings', () => {\n    const fragment = document.createDocumentFragment()\n    const div1 = document.createElement('div')\n    const div2 = document.createElement('div')\n    fragment.appendChild(div1)\n    fragment.appendChild(div2)\n\n    // The function should return false because div2 matches 'DIV' selector\n    expect(isSelectorUniqueAmongSiblings(div1, document, 'DIV', undefined)).toBeFalse()\n  })\n\n  it('returns true when element is in DocumentFragment with no matching siblings', () => {\n    const fragment = document.createDocumentFragment()\n    const div = document.createElement('div')\n    fragment.appendChild(div)\n\n    expect(isSelectorUniqueAmongSiblings(div, document, 'DIV', undefined)).toBeTrue()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/getSelectorFromElement.ts",
    "content": "import { isNodeShadowRoot } from '../browser/htmlDomUtils'\nimport { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './action/actionNameConstants'\n\n/**\n * Marker used to indicate shadow DOM boundaries in selectors.\n * Named after the deprecated Shadow DOM v0 '::shadow' pseudo-element which served the same\n * purpose of marking entry into a shadow root.\n * Note: This is NOT a valid CSS selector, it's an internal marker that requires custom\n * parsing logic.\n */\nexport const SHADOW_DOM_MARKER = '::shadow '\n\n/**\n * Stable attributes are attributes that are commonly used to identify parts of a UI (ex:\n * component). Those attribute values should not be generated randomly (hardcoded most of the time)\n * and stay the same across deploys. They are not necessarily unique across the document.\n */\nexport const STABLE_ATTRIBUTES = [\n  DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE,\n  // Common test attributes (list provided by google recorder)\n  'data-testid',\n  'data-test',\n  'data-qa',\n  'data-cy',\n  'data-test-id',\n  'data-qa-id',\n  'data-testing',\n  // FullStory decorator attributes:\n  'data-component',\n  'data-element',\n  'data-source-file',\n]\n\ntype SelectorGetter = (element: Element, actionNameAttribute: string | undefined) => string | undefined\n\n// Selectors to use if they target a single element on the whole document. Those selectors are\n// considered as \"stable\" and uniquely identify an element regardless of the page state. If we find\n// one, we should consider the selector \"complete\" and stop iterating over ancestors.\nconst GLOBALLY_UNIQUE_SELECTOR_GETTERS: SelectorGetter[] = [getStableAttributeSelector, getIDSelector]\n\n// Selectors to use if they target a single element among an element descendants. Those selectors\n// are more brittle than \"globally unique\" selectors and should be combined with ancestor selectors\n// to improve specificity.\nconst UNIQUE_AMONG_CHILDREN_SELECTOR_GETTERS: SelectorGetter[] = [\n  getStableAttributeSelector,\n  getClassSelector,\n  getTagNameSelector,\n]\n\ninterface SubtreeTarget {\n  rootNode: Document | ShadowRoot\n  target: Element\n}\n\nexport function getSelectorFromElement(\n  targetElement: Element,\n  actionNameAttribute: string | undefined\n): string | undefined {\n  if (!targetElement.isConnected) {\n    // We cannot compute a selector for a detached element, as we don't have access to all of its\n    // parents, and we cannot determine if it's unique in the document.\n    return\n  }\n\n  const subtrees = getAllSubtreeTargets(targetElement)\n  const selectorParts: string[] = []\n\n  for (const { rootNode, target } of subtrees) {\n    const selector = getSelectorFromElementWithinSubtree(target, rootNode, actionNameAttribute)\n    if (!selector) {\n      return undefined\n    }\n    selectorParts.push(selector)\n  }\n\n  return selectorParts.join(SHADOW_DOM_MARKER)\n}\n\n/**\n * Returns all (rootNode, target) pairs from the document down to the element.\n */\nfunction getAllSubtreeTargets(element: Element): SubtreeTarget[] {\n  const result: SubtreeTarget[] = []\n  let currentTarget: Element | undefined = element\n\n  while (currentTarget) {\n    const rootNode = currentTarget.getRootNode() as Document | ShadowRoot\n    result.push({ rootNode, target: currentTarget })\n\n    if (isNodeShadowRoot(rootNode)) {\n      currentTarget = rootNode.host\n    } else {\n      break\n    }\n  }\n\n  return result.reverse()\n}\n\n/**\n * Computes a CSS selector for an element within a specific subtree (document or shadow root).\n */\nfunction getSelectorFromElementWithinSubtree(\n  targetElement: Element,\n  rootNode: Document | ShadowRoot,\n  actionNameAttribute: string | undefined\n): string | undefined {\n  let currentSelector: string | undefined\n  let currentElement: Element | null = targetElement\n\n  while (currentElement && currentElement.nodeName !== 'HTML') {\n    const globallyUniqueSelector = findSelector(\n      currentElement,\n      rootNode,\n      GLOBALLY_UNIQUE_SELECTOR_GETTERS,\n      isSelectorUniqueWithinRoot,\n      actionNameAttribute,\n      currentSelector\n    )\n    if (globallyUniqueSelector) {\n      return combineSelector(globallyUniqueSelector, currentSelector)\n    }\n\n    const uniqueSelectorAmongChildren = findSelector(\n      currentElement,\n      rootNode,\n      UNIQUE_AMONG_CHILDREN_SELECTOR_GETTERS,\n      isSelectorUniqueAmongSiblings,\n      actionNameAttribute,\n      currentSelector\n    )\n\n    const elementSelector = uniqueSelectorAmongChildren || getPositionSelector(currentElement)\n    currentSelector = combineSelector(elementSelector, currentSelector)\n\n    currentElement = currentElement.parentElement\n  }\n\n  return currentSelector\n}\n\nexport function isGeneratedValue(value: string) {\n  // To compute the \"URL path group\", the backend replaces every URL path parts as a question mark\n  // if it thinks the part is an identifier. The condition it uses is to checks whether a digit is\n  // present.\n  //\n  // Here, we use the same strategy: if the value contains a digit, we consider it generated. This\n  // strategy might be a bit naive and fail in some cases, but there are many fallbacks to generate\n  // CSS selectors so it should be fine most of the time.\n  return /[0-9]/.test(value)\n}\n\nexport function getIDSelector(element: Element): string | undefined {\n  if (element.id && !isGeneratedValue(element.id)) {\n    return `#${CSS.escape(element.id)}`\n  }\n}\n\nfunction getClassSelector(element: Element): string | undefined {\n  if (element.tagName === 'BODY') {\n    return\n  }\n  const classList = element.classList\n  for (let i = 0; i < classList.length; i += 1) {\n    const className = classList[i]\n    if (isGeneratedValue(className)) {\n      continue\n    }\n\n    return `${CSS.escape(element.tagName)}.${CSS.escape(className)}`\n  }\n}\n\nexport function getTagNameSelector(element: Element): string {\n  return CSS.escape(element.tagName)\n}\n\nfunction getStableAttributeSelector(element: Element, actionNameAttribute: string | undefined): string | undefined {\n  if (actionNameAttribute) {\n    const selector = getAttributeSelector(actionNameAttribute)\n    if (selector) {\n      return selector\n    }\n  }\n\n  for (const attributeName of STABLE_ATTRIBUTES) {\n    const selector = getAttributeSelector(attributeName)\n    if (selector) {\n      return selector\n    }\n  }\n\n  function getAttributeSelector(attributeName: string) {\n    if (element.hasAttribute(attributeName)) {\n      return `${CSS.escape(element.tagName)}${getAttributeValueSelector(attributeName, element.getAttribute(attributeName)!)}`\n    }\n  }\n}\n\nexport function getAttributeValueSelector(attributeName: string, attributeValue: string) {\n  return `[${attributeName}=\"${CSS.escape(attributeValue)}\"]`\n}\n\nfunction getPositionSelector(element: Element): string {\n  const nthOfType = getNthOfTypeSelector(element)\n\n  return `${CSS.escape(element.tagName)}:nth-of-type(${nthOfType})`\n}\n\nexport function getNthOfTypeSelector(element: Element): number {\n  const parent = element.parentNode!\n\n  let sibling = parent.firstElementChild\n\n  let nthOfType = 1\n\n  while (sibling && sibling !== element) {\n    if (sibling.tagName === element.tagName) {\n      nthOfType += 1\n    }\n    sibling = sibling.nextElementSibling\n  }\n\n  return nthOfType\n}\n\nfunction findSelector(\n  element: Element,\n  rootNode: Document | ShadowRoot,\n  selectorGetters: SelectorGetter[],\n  predicate: (\n    element: Element,\n    rootNode: Document | ShadowRoot,\n    elementSelector: string,\n    childSelector: string | undefined\n  ) => boolean,\n  actionNameAttribute: string | undefined,\n  childSelector: string | undefined\n) {\n  for (const selectorGetter of selectorGetters) {\n    const elementSelector = selectorGetter(element, actionNameAttribute)\n    if (!elementSelector) {\n      continue\n    }\n    if (predicate(element, rootNode, elementSelector, childSelector)) {\n      return elementSelector\n    }\n  }\n}\n\n/**\n * Check whether the selector is unique within the root node (document or shadow root).\n */\nfunction isSelectorUniqueWithinRoot(\n  _element: Element,\n  rootNode: Document | ShadowRoot,\n  elementSelector: string,\n  childSelector: string | undefined\n): boolean {\n  return rootNode.querySelectorAll(combineSelector(elementSelector, childSelector)).length === 1\n}\n\n/**\n * Check whether the selector is unique among the element siblings. In other words, it returns true\n * if \"ELEMENT_PARENT > CHILD_SELECTOR\" returns a single element.\n *\n * @param currentElement - the element being considered while iterating over the target\n * element ancestors.\n * @param _rootNode - the root node (document or shadow root) - unused but required for predicate signature.\n * @param currentElementSelector - a selector that matches the current element. That\n * selector is not a composed selector (i.e. it might be a single tag name, class name...).\n * @param childSelector - child selector is a selector that targets a descendant\n * of the current element. When undefined, the current element is the target element.\n *\n * # Scope selector usage\n *\n * When composed together, the final selector will be joined with `>` operators to make sure we\n * target direct descendants at each level. In this function, we'll use `querySelector` to check if\n * a selector matches descendants of the current element. But by default, the query selector match\n * elements at any level. Example:\n *\n * ```html\n * <main>\n *   <div>\n *     <span></span>\n *   </div>\n *   <marquee>\n *     <div>\n *       <span></span>\n *     </div>\n *   </marquee>\n * </main>\n * ```\n *\n * `sibling.querySelector('DIV > SPAN')` will match both span elements, so we would consider the\n * selector to be not unique, even if it is unique when we'll compose it with the parent with a `>`\n * operator (`MAIN > DIV > SPAN`).\n *\n * To avoid this, we can use the `:scope` selector to make sure the selector starts from the current\n * sibling (i.e. `sibling.querySelector('DIV:scope > SPAN')` will only match the first span).\n *\n * [1]: https://developer.mozilla.org/fr/docs/Web/CSS/:scope\n *\n * # Performance considerations\n *\n * We compute selectors in performance-critical operations (ex: during a click), so we need to make\n * sure the function is as fast as possible. We observed that naively using `querySelectorAll` to\n * check if the selector matches more than 1 element is quite expensive, so we want to avoid it.\n *\n * Because we are iterating the DOM upward and we use that function at every level, we know the\n * child selector is already unique among the current element children, so we don't need to check\n * for the current element subtree.\n *\n * Instead, we can focus on the current element siblings. If we find a single element matching the\n * selector within a sibling, we know that it's not unique. This allows us to use `querySelector`\n * (or `matches`, when the current element is the target element) instead of `querySelectorAll`.\n */\nexport function isSelectorUniqueAmongSiblings(\n  currentElement: Element,\n  _rootNode: Document | ShadowRoot,\n  currentElementSelector: string,\n  childSelector: string | undefined\n): boolean {\n  let isSiblingMatching: (sibling: Element) => boolean\n\n  if (childSelector === undefined) {\n    // If the child selector is undefined (meaning `currentElement` is the target element, not one\n    // of its ancestor), we need to use `matches` to check if the sibling is matching the selector,\n    // as `querySelector` only returns a descendant of the element.\n    isSiblingMatching = (sibling) => sibling.matches(currentElementSelector)\n  } else {\n    const scopedSelector = combineSelector(`${currentElementSelector}:scope`, childSelector)\n    isSiblingMatching = (sibling) => sibling.querySelector(scopedSelector) !== null\n  }\n\n  // Check siblings by iterating directly through previousElementSibling and nextElementSibling.\n  // This works even when parentElement is null (e.g., when parent is a DocumentFragment).\n\n  // Check previous siblings\n  let sibling = currentElement.previousElementSibling\n  while (sibling) {\n    if (isSiblingMatching(sibling)) {\n      return false\n    }\n    sibling = sibling.previousElementSibling\n  }\n\n  // Check next siblings\n  sibling = currentElement.nextElementSibling\n  while (sibling) {\n    if (isSiblingMatching(sibling)) {\n      return false\n    }\n    sibling = sibling.nextElementSibling\n  }\n\n  return true\n}\n\nfunction combineSelector(parent: string, child: string | undefined): string {\n  return child ? `${parent}>${child}` : parent\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/getSessionReplayUrl.spec.ts",
    "content": "import type { ClocksState } from '@datadog/browser-core'\nimport type { RumConfiguration, RumSession } from '@datadog/browser-rum-core'\n\nimport { getSessionReplayUrl, getDatadogSiteUrl } from './getSessionReplayUrl'\n\ndescribe('getDatadogSiteUrl', () => {\n  const parameters: Array<[string, string | undefined, string]> = [\n    ['datadoghq.com', undefined, 'app.datadoghq.com'],\n    ['datadoghq.com', 'toto', 'toto.datadoghq.com'],\n    ['datad0g.com', undefined, 'dd.datad0g.com'],\n    ['datad0g.com', 'toto', 'toto.datad0g.com'],\n    ['us3.datadoghq.com', undefined, 'us3.datadoghq.com'],\n    ['us3.datadoghq.com', 'toto', 'toto.us3.datadoghq.com'],\n    ['us5.datadoghq.com', undefined, 'us5.datadoghq.com'],\n    ['us5.datadoghq.com', 'toto', 'toto.us5.datadoghq.com'],\n  ]\n\n  parameters.forEach(([site, subdomain, host]) => {\n    it(`should return ${host} for subdomain \"${\n      subdomain ?? 'undefined'\n    }\" on \"${site}\" with query params if view is found`, () => {\n      const link = getDatadogSiteUrl({ site, subdomain } as RumConfiguration)\n\n      expect(link).toBe(`https://${host}`)\n    })\n  })\n})\n\ndescribe('getSessionReplayUrl', () => {\n  const parameters = [\n    [\n      {\n        testCase: 'session, no view, no error',\n        session: { id: 'session-id-1' } as RumSession,\n        viewContext: undefined,\n        errorType: undefined,\n        expected: 'https://app.datadoghq.com/rum/replay/sessions/session-id-1?',\n      },\n    ],\n    [\n      {\n        testCase: 'no session, no view, error',\n        session: undefined,\n        viewContext: undefined,\n        errorType: 'toto',\n        expected: 'https://app.datadoghq.com/rum/replay/sessions/no-session-id?error-type=toto',\n      },\n    ],\n    [\n      {\n        testCase: 'session, view, no error',\n        session: { id: 'session-id-2' } as RumSession,\n        viewContext: { id: 'view-id-1', startClocks: { relative: 0, timeStamp: 1234 } as ClocksState },\n        errorType: undefined,\n        expected: 'https://app.datadoghq.com/rum/replay/sessions/session-id-2?seed=view-id-1&from=1234',\n      },\n    ],\n    [\n      {\n        testCase: 'session, view, error',\n        session: { id: 'session-id-3' } as RumSession,\n        viewContext: { id: 'view-id-2', startClocks: { relative: 0, timeStamp: 1234 } as ClocksState },\n        errorType: 'titi',\n        expected: 'https://app.datadoghq.com/rum/replay/sessions/session-id-3?error-type=titi&seed=view-id-2&from=1234',\n      },\n    ],\n  ]\n\n  parameters.forEach(([{ testCase, session, viewContext, errorType, expected }]) => {\n    it(`should build url when ${testCase}`, () => {\n      const link = getSessionReplayUrl({ site: 'datadoghq.com' } as RumConfiguration, {\n        viewContext,\n        session,\n        errorType,\n      })\n      expect(link).toBe(expected)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/getSessionReplayUrl.ts",
    "content": "import { INTAKE_SITE_STAGING, INTAKE_SITE_US1, INTAKE_SITE_EU1 } from '@datadog/browser-core'\nimport type { RumConfiguration } from './configuration'\nimport type { ViewHistoryEntry } from './contexts/viewHistory'\nimport type { RumSession } from './rumSessionManager'\n\nexport function getSessionReplayUrl(\n  configuration: RumConfiguration,\n  {\n    session,\n    viewContext,\n    errorType,\n  }: {\n    session?: RumSession\n    viewContext?: ViewHistoryEntry\n    errorType?: string\n  }\n): string {\n  const sessionId = session ? session.id : 'no-session-id'\n  const parameters: string[] = []\n  if (errorType !== undefined) {\n    parameters.push(`error-type=${errorType}`)\n  }\n  if (viewContext) {\n    parameters.push(`seed=${viewContext.id}`)\n    parameters.push(`from=${viewContext.startClocks.timeStamp}`)\n  }\n\n  const origin = getDatadogSiteUrl(configuration)\n  const path = `/rum/replay/sessions/${sessionId}`\n  return `${origin}${path}?${parameters.join('&')}`\n}\n\nexport function getDatadogSiteUrl(rumConfiguration: RumConfiguration) {\n  const site = rumConfiguration.site\n  const subdomain = rumConfiguration.subdomain || getSiteDefaultSubdomain(rumConfiguration)\n  return `https://${subdomain ? `${subdomain}.` : ''}${site}`\n}\n\nfunction getSiteDefaultSubdomain(configuration: RumConfiguration): string | undefined {\n  switch (configuration.site) {\n    case INTAKE_SITE_US1:\n    case INTAKE_SITE_EU1:\n      return 'app'\n    case INTAKE_SITE_STAGING:\n      return 'dd'\n    default:\n      return undefined\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/hooks.ts",
    "content": "import type {\n  DISCARDED,\n  Duration,\n  HookNamesAsConst,\n  RecursivePartial,\n  RelativeTime,\n  SKIPPED,\n  TelemetryEvent,\n} from '@datadog/browser-core'\nimport { abstractHooks } from '@datadog/browser-core'\nimport type { RumEvent } from '../rumEvent.types'\nimport type { RawRumEvent } from '../rawRumEvent.types'\nimport type { RumEventDomainContext } from '../domainContext.types'\n\n// Define a partial RUM event type.\n// Ensuring the `type` field is always present improves type checking, especially in conditional logic in hooks (e.g., `if (eventType === 'view')`).\nexport type DefaultRumEventAttributes = RecursivePartial<RumEvent> & { type: RumEvent['type'] }\nexport type DefaultTelemetryEventAttributes = RecursivePartial<TelemetryEvent>\n\ntype DeepReadonly<T> = {\n  readonly [K in keyof T]: DeepReadonly<T[K]>\n}\n\n// Use readonly and DeepReadonly to prevents assemble hook callbacks from mutating the inputs.\n// DeepReadonly is only applied to objects rather than the entire AssembleHookParams to avoid casts for primitives.\nexport interface AssembleHookParams {\n  readonly eventType: RumEvent['type']\n  rawRumEvent: DeepReadonly<RawRumEvent>\n  domainContext: DeepReadonly<RumEventDomainContext<RawRumEvent['type']>>\n  readonly startTime: RelativeTime\n  readonly duration?: Duration | undefined\n}\n\nexport interface HookCallbackMap {\n  [HookNamesAsConst.ASSEMBLE]: (param: AssembleHookParams) => DefaultRumEventAttributes | SKIPPED | DISCARDED\n  [HookNamesAsConst.ASSEMBLE_TELEMETRY]: (param: {\n    startTime: RelativeTime\n  }) => DefaultTelemetryEventAttributes | SKIPPED | DISCARDED\n}\n\nexport type Hooks = ReturnType<typeof createHooks>\n\nexport const createHooks = abstractHooks<HookCallbackMap>\n"
  },
  {
    "path": "packages/rum-core/src/domain/lifeCycle.ts",
    "content": "import type { ClocksState, Context, Duration, PageMayExitEvent, RawError } from '@datadog/browser-core'\nimport { AbstractLifeCycle } from '@datadog/browser-core'\nimport type { RumEventDomainContext } from '../domainContext.types'\nimport type { RawRumEvent, AssembledRumEvent } from '../rawRumEvent.types'\nimport type { RequestCompleteEvent, RequestStartEvent } from './requestCollection'\nimport type { AutoAction } from './action/actionCollection'\nimport type { ViewEvent, ViewCreatedEvent, ViewEndedEvent, BeforeViewUpdateEvent } from './view/trackViews'\nimport type { DurationVitalStart } from './vital/vitalCollection'\nimport type { TrackedEventData } from './eventTracker'\nimport type { ActionEventData } from './action/trackManualActions'\n\nexport const enum LifeCycleEventType {\n  // Contexts (like viewHistory) should be opened using prefixed BEFORE_XXX events and closed using prefixed AFTER_XXX events\n  // It ensures the context is available during the non prefixed event callbacks\n  AUTO_ACTION_COMPLETED,\n  BEFORE_VIEW_CREATED,\n  VIEW_CREATED,\n  BEFORE_VIEW_UPDATED,\n  VIEW_UPDATED,\n  VIEW_ENDED,\n  AFTER_VIEW_ENDED,\n  REQUEST_STARTED,\n  REQUEST_COMPLETED,\n\n  // The SESSION_EXPIRED lifecycle event has been introduced to represent when a session has expired\n  // and trigger cleanup tasks related to this, prior to renewing the session. Its implementation is\n  // slightly naive: it is not triggered as soon as the session is expired, but rather just before\n  // notifying that the session is renewed. Thus, the session id is already set to the newly renewed\n  // session.\n  //\n  // This implementation is \"good enough\" for our use-cases. Improving this is not trivial,\n  // primarily because multiple instances of the SDK may be managing the same session cookie at\n  // the same time, for example when using Logs and RUM on the same page, or opening multiple tabs\n  // on the same domain.\n  SESSION_EXPIRED,\n  SESSION_RENEWED,\n  PAGE_MAY_EXIT,\n  RAW_RUM_EVENT_COLLECTED,\n  RUM_EVENT_COLLECTED,\n  RAW_ERROR_COLLECTED,\n  ACTION_STARTED,\n  VITAL_STARTED,\n}\n\n// This is a workaround for an issue occurring when the Browser SDK is included in a TypeScript\n// project configured with `isolatedModules: true`. Even if the const enum is declared in this\n// module, we cannot use it directly to define the EventMap interface keys (TS error: \"Cannot access\n// ambient const enums when the '--isolatedModules' flag is provided.\").\n//\n// Using a plain enum would fix the issue, but would also add 2KB to the minified bundle. By using\n// this workaround, we can keep using a const enum without impacting the bundle size (since it is a\n// \"declare\" statement, it will only be used during typecheck and completely ignored when building\n// JavaScript).\n//\n// See issues:\n// * https://github.com/DataDog/browser-sdk/issues/2208\n// * https://github.com/microsoft/TypeScript/issues/54152\ndeclare const LifeCycleEventTypeAsConst: {\n  ACTION_STARTED: LifeCycleEventType.ACTION_STARTED\n  AUTO_ACTION_COMPLETED: LifeCycleEventType.AUTO_ACTION_COMPLETED\n  BEFORE_VIEW_CREATED: LifeCycleEventType.BEFORE_VIEW_CREATED\n  VIEW_CREATED: LifeCycleEventType.VIEW_CREATED\n  BEFORE_VIEW_UPDATED: LifeCycleEventType.BEFORE_VIEW_UPDATED\n  VIEW_UPDATED: LifeCycleEventType.VIEW_UPDATED\n  VIEW_ENDED: LifeCycleEventType.VIEW_ENDED\n  AFTER_VIEW_ENDED: LifeCycleEventType.AFTER_VIEW_ENDED\n  REQUEST_STARTED: LifeCycleEventType.REQUEST_STARTED\n  REQUEST_COMPLETED: LifeCycleEventType.REQUEST_COMPLETED\n  SESSION_EXPIRED: LifeCycleEventType.SESSION_EXPIRED\n  SESSION_RENEWED: LifeCycleEventType.SESSION_RENEWED\n  PAGE_MAY_EXIT: LifeCycleEventType.PAGE_MAY_EXIT\n  RAW_RUM_EVENT_COLLECTED: LifeCycleEventType.RAW_RUM_EVENT_COLLECTED\n  RUM_EVENT_COLLECTED: LifeCycleEventType.RUM_EVENT_COLLECTED\n  RAW_ERROR_COLLECTED: LifeCycleEventType.RAW_ERROR_COLLECTED\n  VITAL_STARTED: LifeCycleEventType.VITAL_STARTED\n}\n\n// Note: this interface needs to be exported even if it is not used outside of this module, else TS\n// fails to build the rum-core package with error TS4058\nexport interface LifeCycleEventMap {\n  [LifeCycleEventTypeAsConst.ACTION_STARTED]: TrackedEventData<ActionEventData>\n  [LifeCycleEventTypeAsConst.AUTO_ACTION_COMPLETED]: AutoAction\n  [LifeCycleEventTypeAsConst.BEFORE_VIEW_CREATED]: ViewCreatedEvent\n  [LifeCycleEventTypeAsConst.VIEW_CREATED]: ViewCreatedEvent\n  [LifeCycleEventTypeAsConst.BEFORE_VIEW_UPDATED]: BeforeViewUpdateEvent\n  [LifeCycleEventTypeAsConst.VIEW_UPDATED]: ViewEvent\n  [LifeCycleEventTypeAsConst.VIEW_ENDED]: ViewEndedEvent\n  [LifeCycleEventTypeAsConst.AFTER_VIEW_ENDED]: ViewEndedEvent\n  [LifeCycleEventTypeAsConst.REQUEST_STARTED]: RequestStartEvent\n  [LifeCycleEventTypeAsConst.REQUEST_COMPLETED]: RequestCompleteEvent\n  [LifeCycleEventTypeAsConst.SESSION_EXPIRED]: void\n  [LifeCycleEventTypeAsConst.SESSION_RENEWED]: void\n  [LifeCycleEventTypeAsConst.PAGE_MAY_EXIT]: PageMayExitEvent\n  [LifeCycleEventTypeAsConst.RAW_RUM_EVENT_COLLECTED]: RawRumEventCollectedData\n  [LifeCycleEventTypeAsConst.RUM_EVENT_COLLECTED]: AssembledRumEvent\n  [LifeCycleEventTypeAsConst.RAW_ERROR_COLLECTED]: {\n    error: RawError\n    customerContext?: Context\n  }\n  [LifeCycleEventTypeAsConst.VITAL_STARTED]: DurationVitalStart\n}\n\nexport interface RawRumEventCollectedData<E extends RawRumEvent = RawRumEvent> {\n  startClocks: ClocksState\n  duration?: Duration\n  rawRumEvent: E\n  domainContext: RumEventDomainContext<E['type']>\n}\n\nexport const LifeCycle = AbstractLifeCycle<LifeCycleEventMap>\nexport type LifeCycle = AbstractLifeCycle<LifeCycleEventMap>\n"
  },
  {
    "path": "packages/rum-core/src/domain/limitModification.spec.ts",
    "content": "import type { Context } from '@datadog/browser-core'\nimport { display, noop, objectEntries, SANITIZE_DEFAULT_MAX_CHARACTER_COUNT } from '@datadog/browser-core'\nimport type { ModifiableFieldPaths } from './limitModification'\nimport { limitModification } from './limitModification'\n\ndescribe('limitModification', () => {\n  let object: unknown\n\n  beforeEach(() => {\n    object = {\n      foo: { bar: 'bar' },\n      arr: [{ foo: 'foo' }],\n      qux: 'qux',\n    }\n  })\n\n  it('should allow modifications on modifiable field', () => {\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = 'modified1'\n      candidate.qux = 'modified2'\n      candidate.arr[0].foo = 'modified3'\n    }\n\n    limitModification(\n      object,\n      {\n        'foo.bar': 'string',\n        qux: 'string',\n        'arr[].foo': 'string',\n      },\n      modifier\n    )\n\n    expect(object).toEqual({\n      foo: { bar: 'modified1' },\n      qux: 'modified2',\n      arr: [{ foo: 'modified3' }],\n    })\n  })\n\n  it('should not allow modifications on non modifiable field', () => {\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = 'modified1'\n      candidate.qux = 'modified2'\n      candidate.arr[0].foo = 'modified3'\n    }\n\n    limitModification(object, { 'foo.bar': 'string' }, modifier)\n\n    expect(object).toEqual({\n      foo: { bar: 'modified1' },\n      arr: [{ foo: 'foo' }],\n      qux: 'qux',\n    })\n  })\n\n  it('should allow to add a modifiable fields not present on the original object', () => {\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = 'modified1'\n      candidate.qux = 'modified2'\n      candidate.qix = 'modified3'\n    }\n\n    limitModification(object, { 'foo.bar': 'string', qux: 'string', qix: 'string' }, modifier)\n\n    expect(object as any).toEqual({\n      foo: { bar: 'modified1' },\n      arr: [{ foo: 'foo' }],\n      qux: 'modified2',\n      qix: 'modified3',\n    })\n  })\n\n  it('should not allow to add a non modifiable fields not present on the original object', () => {\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = 'modified1'\n      candidate.qux = 'modified2'\n      candidate.qix = 'modified3'\n    }\n\n    limitModification(object, { 'foo.bar': 'string', qux: 'string' }, modifier)\n\n    expect(object).toEqual({\n      foo: { bar: 'modified1' },\n      arr: [{ foo: 'foo' }],\n      qux: 'modified2',\n    })\n  })\n\n  it('should not allow changing the type of the value on modifiable field', () => {\n    const object = {\n      string_to_undefined: 'bar',\n      string_to_number: 'qux',\n\n      object_to_null: {},\n      object_to_undefined: {},\n      object_to_array: {},\n    }\n    const modifier = (candidate: any) => {\n      candidate.string_to_undefined = undefined\n      candidate.string_to_number = 1234\n\n      candidate.object_to_null = null\n      candidate.object_to_undefined = undefined\n      candidate.object_to_array = []\n    }\n\n    limitModification(object, generateModifiableFieldPathsFrom(object), modifier)\n\n    expect(object).toEqual({\n      string_to_undefined: 'bar',\n      string_to_number: 'qux',\n\n      object_to_null: {},\n      object_to_undefined: {},\n      object_to_array: {},\n    })\n  })\n\n  it('should allow emptying an object by setting it to null, undefined or deleting it', () => {\n    const object: any = {\n      a: { foo: 'a' },\n      b: { foo: 'b' },\n      c: { foo: 'c' },\n    }\n    const modifier = (candidate: any) => {\n      candidate.a = null\n      candidate.b = undefined\n      delete candidate.c\n    }\n\n    limitModification(object, generateModifiableFieldPathsFrom(object), modifier)\n\n    expect(object).toEqual({\n      a: {},\n      b: {},\n      c: {},\n    })\n  })\n\n  it('should not allow structural change of the object', () => {\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = { qux: 'qux' }\n      candidate.bar = 'bar'\n      delete candidate.qux\n      ;(candidate.arr as Array<Record<string, string>>).push({ bar: 'baz' })\n    }\n\n    limitModification(object, { 'foo.bar': 'string', qux: 'string' }, modifier)\n\n    expect(object).toEqual({\n      foo: { bar: 'bar' },\n      qux: 'qux',\n      arr: [{ foo: 'foo' }],\n    })\n  })\n\n  it('should allow modification on sub-fields for object fields', () => {\n    const object: Context = { foo: { bar: 'bar', baz: 'baz' } }\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = { qux: 'qux' }\n      delete candidate.foo.baz\n    }\n\n    limitModification(object, { foo: 'object' }, modifier)\n\n    expect(object).toEqual({\n      foo: { bar: { qux: 'qux' } },\n    })\n  })\n\n  it('should return the result of the modifier', () => {\n    const object = { foo: { bar: 'bar' } }\n    const modifier = (candidate: any) => {\n      candidate.foo.bar = 'qux'\n      return false\n    }\n\n    const result = limitModification(object, { 'foo.bar': 'string', qux: 'string' }, modifier)\n\n    expect(result).toBe(false)\n    expect(object).toEqual({\n      foo: { bar: 'qux' },\n    })\n  })\n\n  it('should call sanitize on newly provided values', () => {\n    const object: Context = { bar: { baz: 42 } }\n\n    const modifier = (candidate: any) => {\n      candidate.bar.self = candidate.bar\n    }\n\n    limitModification(object, { bar: 'object' }, modifier)\n    expect(() => JSON.stringify(object)).not.toThrowError()\n  })\n\n  it(\"should not reset unsafe literal fields that the user didn't alter\", () => {\n    spyOn(display, 'warn')\n    const wayTooLongUrl = `/${'a'.repeat(SANITIZE_DEFAULT_MAX_CHARACTER_COUNT + 1)}`\n    const object: Context = { resource: { url: wayTooLongUrl } }\n    const modifier = noop\n    limitModification(object, { 'resource.url': 'string' }, modifier)\n    expect(object).toEqual({ resource: { url: wayTooLongUrl } })\n  })\n\n  it('should sanitize object fields (fieldType \"object\") even with a noop modifier', () => {\n    spyOn(display, 'warn')\n    const wayTooLongUrl = `/${'a'.repeat(SANITIZE_DEFAULT_MAX_CHARACTER_COUNT + 1)}`\n    const object: Context = {\n      context: {\n        response: {\n          status: 200,\n          url: wayTooLongUrl,\n        },\n      },\n    }\n    const modifier = noop\n    limitModification(object, { context: 'object' }, modifier)\n    expect(object).toEqual({\n      context: {\n        response: {\n          status: 200,\n        },\n      },\n    })\n    expect(display.warn).toHaveBeenCalled()\n  })\n})\n\nfunction generateModifiableFieldPathsFrom(object: Record<string, string | object>) {\n  const modifiableFieldPaths: ModifiableFieldPaths = {}\n  objectEntries(object).forEach(([key, value]) => {\n    modifiableFieldPaths[key] = typeof value as 'object' | 'string'\n  })\n  return modifiableFieldPaths\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/limitModification.ts",
    "content": "import { sanitize, deepClone, getType, objectEntries } from '@datadog/browser-core'\nimport type { Context } from '@datadog/browser-core'\n\nexport type ModifiableFieldPaths = Record<string, 'string' | 'object'>\n\n/**\n * Allows declaring and enforcing modifications to specific fields of an object.\n * Only supports modifying properties of an object (even if nested in an array).\n * Does not support array manipulation (adding/removing items).\n *\n * Modifications of the object are sanitized only if the field was actually changed by the modifier function (i.e., value is different).\n * This ensures consistent SDK behavior regardless of whether limitModification is called.\n * Only string fields are handled this way, object fields are sanitized regardless of whether the modifier function was called or not.\n */\nexport function limitModification<T extends Context, Result>(\n  object: T,\n  modifiableFieldPaths: ModifiableFieldPaths,\n  modifier: (object: T) => Result\n): Result | undefined {\n  const clone = deepClone(object)\n  const result = modifier(clone)\n\n  objectEntries(modifiableFieldPaths).forEach(([fieldPath, fieldType]) =>\n    // Traverse both object and clone simultaneously up to the path and apply the modification from the clone to the original object when the type is valid\n    setValueAtPath(object, clone, fieldPath.split(/\\.|(?=\\[\\])/), fieldType)\n  )\n\n  return result\n}\n\nfunction setValueAtPath(object: unknown, clone: unknown, pathSegments: string[], fieldType: 'string' | 'object') {\n  const [field, ...restPathSegments] = pathSegments\n\n  if (field === '[]') {\n    if (Array.isArray(object) && Array.isArray(clone)) {\n      object.forEach((item, i) => setValueAtPath(item, clone[i], restPathSegments, fieldType))\n    }\n\n    return\n  }\n\n  if (!isValidObject(object) || !isValidObject(clone)) {\n    return\n  }\n\n  if (restPathSegments.length > 0) {\n    return setValueAtPath(object[field], clone[field], restPathSegments, fieldType)\n  }\n\n  setNestedValue(object, field, clone[field], fieldType)\n}\n\nfunction setNestedValue(\n  object: Record<string, unknown>,\n  field: string,\n  value: unknown,\n  fieldType: 'string' | 'object'\n) {\n  if (object[field] === value) {\n    return\n  }\n\n  const newType = getType(value)\n\n  if (newType === fieldType) {\n    object[field] = sanitize(value)\n  } else if (fieldType === 'object' && (newType === 'undefined' || newType === 'null')) {\n    object[field] = {}\n  }\n}\n\nfunction isValidObject(object: unknown): object is Record<string, unknown> {\n  return getType(object) === 'object'\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/longTask/longTaskCollection.spec.ts",
    "content": "import type { RelativeTime, ServerDuration } from '@datadog/browser-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport {\n  collectAndValidateRawRumEvents,\n  createPerformanceEntry,\n  mockPerformanceObserver,\n  mockRumConfiguration,\n} from '../../../test'\nimport type { RumPerformanceEntry } from '../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport type { RawRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType, RumLongTaskEntryType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycle } from '../lifeCycle'\nimport { startLongTaskCollection } from './longTaskCollection'\n\ndescribe('longTaskCollection', () => {\n  let lifeCycle: LifeCycle\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>>\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  function setupLongTaskCollection({\n    supportedEntryType,\n    trackLongTasks = true,\n  }: {\n    supportedEntryType?: RumPerformanceEntryType\n    trackLongTasks?: boolean\n  } = {}) {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver({\n      supportedEntryTypes: supportedEntryType ? [supportedEntryType] : undefined,\n    }))\n\n    lifeCycle = new LifeCycle()\n    const longTaskCollection = startLongTaskCollection(lifeCycle, mockRumConfiguration({ trackLongTasks }))\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n\n    registerCleanupTask(() => {\n      longTaskCollection.stop()\n    })\n\n    return longTaskCollection\n  }\n\n  describe('when browser supports long-animation-frame', () => {\n    it('should create a long task event from long animation frame performance entry', () => {\n      setupLongTaskCollection()\n      const performanceLongAnimationFrameTiming = createPerformanceEntry(RumPerformanceEntryType.LONG_ANIMATION_FRAME)\n\n      notifyPerformanceEntries([performanceLongAnimationFrameTiming])\n\n      expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)\n      expect(rawRumEvents[0].rawRumEvent).toEqual({\n        date: jasmine.any(Number),\n        long_task: {\n          id: jasmine.any(String),\n          entry_type: RumLongTaskEntryType.LONG_ANIMATION_FRAME,\n          duration: (82 * 1e6) as ServerDuration,\n          blocking_duration: 0 as ServerDuration,\n          first_ui_event_timestamp: 0 as ServerDuration,\n          render_start: 1_421_500_000 as ServerDuration,\n          style_and_layout_start: 1_428_000_000 as ServerDuration,\n          start_time: 1_234_000_000 as ServerDuration,\n          scripts: [\n            {\n              duration: (6 * 1e6) as ServerDuration,\n              pause_duration: 0 as ServerDuration,\n              forced_style_and_layout_duration: 0 as ServerDuration,\n              start_time: 1_348_000_000 as ServerDuration,\n              execution_start: 1_348_700_000 as ServerDuration,\n              source_url: 'http://example.com/script.js',\n              source_function_name: '',\n              source_char_position: 9876,\n              invoker: 'http://example.com/script.js',\n              invoker_type: 'classic-script',\n              window_attribution: 'self',\n            },\n          ],\n        },\n        type: RumEventType.LONG_TASK,\n        _dd: {\n          discarded: false,\n        },\n      })\n      expect(rawRumEvents[0].domainContext).toEqual({\n        performanceEntry: performanceLongAnimationFrameTiming,\n      })\n    })\n\n    it('should only listen to long animation frame performance entry', () => {\n      setupLongTaskCollection()\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LONG_ANIMATION_FRAME),\n        createPerformanceEntry(RumPerformanceEntryType.LONG_TASK),\n      ])\n\n      expect(rawRumEvents.length).toBe(1)\n    })\n\n    it('should not collect when trackLongTasks=false', () => {\n      setupLongTaskCollection({ trackLongTasks: false })\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LONG_ANIMATION_FRAME)])\n\n      expect(rawRumEvents.length).toBe(0)\n    })\n  })\n\n  describe('when browser only supports legacy longtask', () => {\n    it('should create a long task event from long task performance entry', () => {\n      setupLongTaskCollection({ supportedEntryType: RumPerformanceEntryType.LONG_TASK })\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LONG_TASK)])\n\n      expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)\n      expect(rawRumEvents[0].rawRumEvent).toEqual({\n        date: jasmine.any(Number),\n        long_task: {\n          id: jasmine.any(String),\n          entry_type: RumLongTaskEntryType.LONG_TASK,\n          duration: (100 * 1e6) as ServerDuration,\n        },\n        type: RumEventType.LONG_TASK,\n        _dd: {\n          discarded: false,\n        },\n      })\n      expect(rawRumEvents[0].domainContext).toEqual({\n        performanceEntry: {\n          name: 'self',\n          duration: 100,\n          entryType: 'longtask',\n          startTime: 1234,\n          toJSON: jasmine.any(Function),\n        },\n      })\n    })\n\n    it('should collect when trackLongTasks=true', () => {\n      setupLongTaskCollection({ supportedEntryType: RumPerformanceEntryType.LONG_TASK })\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LONG_TASK)])\n      expect(rawRumEvents.length).toBe(1)\n    })\n\n    it('should not collect when trackLongTasks=false', () => {\n      setupLongTaskCollection({ supportedEntryType: RumPerformanceEntryType.LONG_TASK, trackLongTasks: false })\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LONG_TASK)])\n\n      expect(rawRumEvents.length).toBe(0)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/longTask/longTaskCollection.ts",
    "content": "import type { ClocksState } from '@datadog/browser-core'\nimport { toServerDuration, relativeToClocks, generateUUID } from '@datadog/browser-core'\nimport type { RawRumLongTaskEvent, RawRumLongAnimationFrameEvent } from '../../rawRumEvent.types'\nimport { RumEventType, RumLongTaskEntryType } from '../../rawRumEvent.types'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport {\n  createPerformanceObservable,\n  RumPerformanceEntryType,\n  supportPerformanceTimingEvent,\n} from '../../browser/performanceObservable'\nimport type {\n  RumPerformanceLongAnimationFrameTiming,\n  RumPerformanceLongTaskTiming,\n  RumPerformanceScriptTiming,\n} from '../../browser/performanceObservable'\nimport type { RumConfiguration } from '../configuration'\n\nexport function startLongTaskCollection(lifeCycle: LifeCycle, configuration: RumConfiguration) {\n  const entryType = supportPerformanceTimingEvent(RumPerformanceEntryType.LONG_ANIMATION_FRAME)\n    ? RumPerformanceEntryType.LONG_ANIMATION_FRAME\n    : RumPerformanceEntryType.LONG_TASK\n\n  const subscription = createPerformanceObservable(configuration, {\n    type: entryType,\n    buffered: true,\n  }).subscribe((entries) => {\n    for (const entry of entries) {\n      if (!configuration.trackLongTasks) {\n        break\n      }\n\n      const startClocks = relativeToClocks(entry.startTime)\n      const rawRumEvent = processEntry(entry, startClocks)\n\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n        rawRumEvent,\n        startClocks,\n        duration: entry.duration,\n        domainContext: { performanceEntry: entry },\n      })\n    }\n  })\n\n  return {\n    stop: () => subscription.unsubscribe(),\n  }\n}\n\nfunction processEntry(\n  entry: RumPerformanceLongTaskTiming | RumPerformanceLongAnimationFrameTiming,\n  startClocks: ClocksState\n): RawRumLongTaskEvent | RawRumLongAnimationFrameEvent {\n  const id = generateUUID()\n  const duration = toServerDuration(entry.duration)\n\n  const baseEvent = {\n    date: startClocks.timeStamp,\n    type: RumEventType.LONG_TASK,\n    _dd: { discarded: false },\n  }\n\n  if (entry.entryType === RumPerformanceEntryType.LONG_TASK) {\n    return {\n      ...baseEvent,\n      long_task: {\n        id,\n        entry_type: RumLongTaskEntryType.LONG_TASK,\n        duration,\n      },\n    }\n  }\n\n  return {\n    ...baseEvent,\n    long_task: {\n      id,\n      entry_type: RumLongTaskEntryType.LONG_ANIMATION_FRAME,\n      duration,\n      blocking_duration: toServerDuration(entry.blockingDuration),\n      first_ui_event_timestamp: toServerDuration(entry.firstUIEventTimestamp),\n      render_start: toServerDuration(entry.renderStart),\n      style_and_layout_start: toServerDuration(entry.styleAndLayoutStart),\n      start_time: toServerDuration(entry.startTime),\n      scripts: entry.scripts.map((script: RumPerformanceScriptTiming) => ({\n        duration: toServerDuration(script.duration),\n        pause_duration: toServerDuration(script.pauseDuration),\n        forced_style_and_layout_duration: toServerDuration(script.forcedStyleAndLayoutDuration),\n        start_time: toServerDuration(script.startTime),\n        execution_start: toServerDuration(script.executionStart),\n        source_url: script.sourceURL,\n        source_function_name: script.sourceFunctionName,\n        source_char_position: script.sourceCharPosition,\n        invoker: script.invoker,\n        invoker_type: script.invokerType,\n        window_attribution: script.windowAttribution,\n      })),\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/plugins.spec.ts",
    "content": "import type { RumPublicApi } from '../boot/rumPublicApi'\nimport type { RumInitConfiguration } from './configuration'\nimport type { RumPlugin } from './plugins'\nimport { callPluginsMethod } from './plugins'\n\ndescribe('callPluginsMethod', () => {\n  it('calls the method on each plugin', () => {\n    const plugin1 = { name: 'a', onInit: jasmine.createSpy() } satisfies RumPlugin\n    const plugin2 = { name: 'b', onInit: jasmine.createSpy() } satisfies RumPlugin\n    const parameter = { initConfiguration: {} as RumInitConfiguration, publicApi: {} as RumPublicApi }\n    callPluginsMethod([plugin1, plugin2], 'onInit', parameter)\n    expect(plugin1.onInit).toHaveBeenCalledWith(parameter)\n    expect(plugin2.onInit).toHaveBeenCalledWith(parameter)\n  })\n\n  it('does not call the method if the plugin does not have it', () => {\n    const plugin1 = { name: 'a', onInit: jasmine.createSpy() } satisfies RumPlugin\n    const plugin2 = { name: 'b' } satisfies RumPlugin\n    const parameter = { initConfiguration: {} as RumInitConfiguration, publicApi: {} as RumPublicApi }\n    callPluginsMethod([plugin1, plugin2], 'onInit', parameter)\n    expect(plugin1.onInit).toHaveBeenCalledWith(parameter)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/plugins.ts",
    "content": "import type { RumPublicApi, Strategy } from '../boot/rumPublicApi'\nimport type { StartRumResult } from '../boot/startRum'\nimport type { RumInitConfiguration } from './configuration'\n\n/**\n * onRumStart plugin API options.\n *\n * @experimental\n */\nexport interface OnRumStartOptions {\n  /**\n   * @deprecated Use `addEvent` instead.\n   */\n  strategy?: Strategy\n  /**\n   * Add an event to the RUM browser SDK.\n   */\n  addEvent?: StartRumResult['addEvent']\n  /**\n   * Add a custom error to the RUM browser SDK.\n   */\n  addError?: StartRumResult['addError']\n}\n\n/**\n * Plugin interface of the RUM browser SDK.\n *\n * The plugins API is unstable and experimental, and may change without\n * notice. Please use only plugins provided by Datadog matching the version of the SDK you are\n * using.\n *\n * @experimental\n */\nexport interface RumPlugin {\n  name: string\n  getConfigurationTelemetry?(): Record<string, unknown>\n  onInit?(options: { initConfiguration: RumInitConfiguration; publicApi: RumPublicApi }): void\n  onRumStart?(options: OnRumStartOptions): void\n}\n\ntype MethodNames = 'onInit' | 'onRumStart'\ntype MethodParameter<MethodName extends MethodNames> = Parameters<NonNullable<RumPlugin[MethodName]>>[0]\n\nexport function callPluginsMethod<MethodName extends MethodNames>(\n  plugins: RumPlugin[] | undefined,\n  methodName: MethodName,\n  parameter: MethodParameter<MethodName>\n): void\nexport function callPluginsMethod<MethodName extends MethodNames>(\n  plugins: RumPlugin[] | undefined,\n  methodName: MethodName,\n  parameter: any\n) {\n  if (!plugins) {\n    return\n  }\n  for (const plugin of plugins) {\n    const method = plugin[methodName]\n    if (method) {\n      method(parameter)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/privacy.spec.ts",
    "content": "import { appendElement } from '../../test'\nimport {\n  NodePrivacyLevel,\n  PRIVACY_ATTR_NAME,\n  PRIVACY_ATTR_VALUE_HIDDEN,\n  PRIVACY_ATTR_VALUE_MASK,\n  PRIVACY_ATTR_VALUE_MASK_USER_INPUT,\n  CENSORED_STRING_MARK,\n} from './privacyConstants'\nimport {\n  censorText,\n  getNodeSelfPrivacyLevel,\n  reducePrivacyLevel,\n  getNodePrivacyLevel,\n  shouldMaskNode,\n  getTextContent,\n  maskDisallowedTextContent,\n} from './privacy'\nimport { ACTION_NAME_MASK } from './action/actionNameConstants'\n\ndescribe('getNodePrivacyLevel', () => {\n  it('returns the element privacy mode if it has one', () => {\n    const node = document.createElement('div')\n    node.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.MASK)\n  })\n\n  it('fallbacks to the default privacy mode if the element has none', () => {\n    const node = document.createElement('div')\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.ALLOW)\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.IGNORE)).toBe(NodePrivacyLevel.IGNORE)\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.MASK)).toBe(NodePrivacyLevel.MASK)\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.MASK_USER_INPUT)).toBe(NodePrivacyLevel.MASK_USER_INPUT)\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.HIDDEN)).toBe(NodePrivacyLevel.HIDDEN)\n    expect(getNodePrivacyLevel(node, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBe(\n      NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED\n    )\n  })\n\n  describe('inheritance', () => {\n    it('returns an ancestor privacy mode if the element has none', () => {\n      const ancestor = document.createElement('div')\n      const node = document.createElement('div')\n      ancestor.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n      ancestor.appendChild(node)\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.MASK)\n    })\n\n    it('fallbacks to the default privacy mode if no ancestor has one', () => {\n      const ancestor = document.createElement('div')\n      const node = document.createElement('div')\n      ancestor.appendChild(node)\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.ALLOW)\n    })\n\n    it('overrides the ancestor privacy mode', () => {\n      const ancestor = document.createElement('div')\n      ancestor.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n      const node = document.createElement('div')\n      node.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n      ancestor.appendChild(node)\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.MASK_USER_INPUT)\n    })\n\n    it('does not override the ancestor privacy mode if it is HIDDEN', () => {\n      const ancestor = document.createElement('div')\n      ancestor.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_HIDDEN)\n      const node = document.createElement('div')\n      node.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK_USER_INPUT)\n      ancestor.appendChild(node)\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.HIDDEN)\n    })\n\n    it('overrides the ancestor privacy mode if the element should be IGNORE', () => {\n      const ancestor = document.createElement('div')\n      ancestor.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n      const node = document.createElement('script')\n      ancestor.appendChild(node)\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.IGNORE)\n    })\n\n    it('returns an ancestor privacy mode if the element has none and cross shadow DOM', () => {\n      const ancestor = document.createElement('div')\n      ancestor.attachShadow({ mode: 'open' })\n      const node = document.createElement('div')\n      ancestor.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n      ancestor.shadowRoot!.appendChild(node)\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW)).toBe(NodePrivacyLevel.MASK)\n    })\n  })\n\n  describe('cache', () => {\n    it('fills the cache', () => {\n      const ancestor = document.createElement('div')\n      const node = document.createElement('div')\n      ancestor.setAttribute(PRIVACY_ATTR_NAME, PRIVACY_ATTR_VALUE_MASK)\n      ancestor.appendChild(node)\n\n      const cache = new Map()\n      getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW, cache)\n\n      expect(cache.get(node)).toBe(NodePrivacyLevel.MASK)\n    })\n\n    it('uses the cache', () => {\n      const ancestor = document.createElement('div')\n      const node = document.createElement('div')\n      ancestor.appendChild(node)\n\n      const cache = new Map()\n      cache.set(node, NodePrivacyLevel.MASK_USER_INPUT)\n\n      expect(getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW, cache)).toBe(NodePrivacyLevel.MASK_USER_INPUT)\n    })\n\n    it('does not recurse on ancestors if the node is already in the cache', () => {\n      const ancestor = document.createElement('div')\n      const node = document.createElement('div')\n      ancestor.appendChild(node)\n\n      const parentNodeGetterSpy = spyOnProperty(node, 'parentNode').and.returnValue(ancestor)\n\n      const cache = new Map()\n      cache.set(node, NodePrivacyLevel.MASK_USER_INPUT)\n\n      getNodePrivacyLevel(node, NodePrivacyLevel.ALLOW, cache)\n\n      expect(parentNodeGetterSpy).not.toHaveBeenCalled()\n    })\n  })\n})\n\ndescribe('getNodeSelfPrivacyLevel', () => {\n  ;[\n    {\n      msg: 'is not an element',\n      html: 'foo',\n      expected: undefined,\n    },\n\n    // Overrules\n    {\n      msg: 'has no privacy attribute or class',\n      html: '<span>',\n      expected: undefined,\n    },\n    {\n      msg: 'is a \"base\" element (forced override)',\n      html: '<base class=\"dd-privacy-mask\">',\n      expected: NodePrivacyLevel.ALLOW,\n    },\n    {\n      msg: 'is an \"input\" element of type \"password\" (forced override)',\n      html: '<input type=\"password\" class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'is an \"input\" element of type \"tel\" (forced override)',\n      html: '<input type=\"tel\" class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'is an \"input\" element of type \"email\" (forced override)',\n      html: '<input type=\"email\" class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'is an \"input\" element of type \"hidden\" (forced override)',\n      html: '<input type=\"hidden\" class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'is an \"input\" element and has an autocomplete attribute starting with \"cc-\" (forced override)',\n      html: '<input type=\"text\" class=\"dd-privacy-allow\" autocomplete=\"cc-foo\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'is an \"input\" element and has an autocomplete attribute ending with \"-password\" (forced override)',\n      html: '<input type=\"text\" class=\"dd-privacy-allow\" autocomplete=\"foo-password\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'is an \"input\" element and has an autocomplete attribute not starting with \"cc-\"',\n      html: '<input type=\"text\" autocomplete=\"email\">',\n      expected: undefined,\n    },\n\n    // Class\n    {\n      msg: 'has a dd-privacy-allow class',\n      html: '<span class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.ALLOW,\n    },\n    {\n      msg: 'has a dd-privacy-hidden class',\n      html: '<span class=\"dd-privacy-hidden\">',\n      expected: NodePrivacyLevel.HIDDEN,\n    },\n    {\n      msg: 'has a dd-privacy-mask class',\n      html: '<span class=\"dd-privacy-mask\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'has a dd-privacy-mask-user-input class',\n      html: '<span class=\"dd-privacy-mask-user-input\">',\n      expected: NodePrivacyLevel.MASK_USER_INPUT,\n    },\n    {\n      msg: 'has an unknown class starting with dd-privacy-',\n      html: '<span class=\"dd-privacy-foo\">',\n      expected: undefined,\n    },\n\n    // Attributes\n    {\n      msg: 'has a data-dd-privacy=\"allow\" attribute',\n      html: '<span data-dd-privacy=\"allow\">',\n      expected: NodePrivacyLevel.ALLOW,\n    },\n    {\n      msg: 'has a data-dd-privacy=\"hidden\" attribute',\n      html: '<span data-dd-privacy=\"hidden\">',\n      expected: NodePrivacyLevel.HIDDEN,\n    },\n    {\n      msg: 'has a data-dd-privacy=\"mask\" attribute',\n      html: '<span data-dd-privacy=\"mask\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'has a data-dd-privacy=\"mask-user-input\" attribute',\n      html: '<span data-dd-privacy=\"mask-user-input\">',\n      expected: NodePrivacyLevel.MASK_USER_INPUT,\n    },\n    {\n      msg: 'has an unknown data-dd-privacy attribute value',\n      html: '<span data-dd-privacy=\"foo\">',\n      expected: undefined,\n    },\n\n    // Ignored elements\n    {\n      msg: 'should be ignored',\n      html: '<script>',\n      expected: NodePrivacyLevel.IGNORE,\n    },\n    {\n      msg: 'should be ignored but has an ALLOW privacy class',\n      html: '<script class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.ALLOW,\n    },\n    {\n      msg: 'is a link with rel=preload and as=script',\n      html: '<link rel=\"preload\" crossorigins as=\"script\">',\n      expected: NodePrivacyLevel.IGNORE,\n    },\n    {\n      msg: 'is a link with rel=modulepreload and as=script',\n      html: '<link rel=\"modulepreload\" as=\"script\">',\n      expected: NodePrivacyLevel.IGNORE,\n    },\n    {\n      msg: 'is a link with rel=prefetch and as=script',\n      html: '<link rel=\"prefetch\" as=\"script\">',\n      expected: NodePrivacyLevel.IGNORE,\n    },\n    {\n      msg: 'is a link with rel=stylesheet and a not expected as=script',\n      html: '<link rel=\"stylesheet\" as=\"script\">',\n      expected: undefined,\n    },\n\n    // Precedence\n    {\n      msg: 'has an ALLOW privacy class and a MASK privacy attribute (MASK takes precedence)',\n      html: '<span data-dd-privacy=\"mask\" class=\"dd-privacy-allow\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'has ALLOW and MASK_USER_INPUT privacy classes (MASK_USER_INPUT takes precedence)',\n      html: '<span class=\"dd-privacy-allow dd-privacy-mask-user-input\">',\n      expected: NodePrivacyLevel.MASK_USER_INPUT,\n    },\n    {\n      msg: 'has MASK_USER_INPUT and MASK privacy classes (MASK takes precedence)',\n      html: '<span class=\"dd-privacy-mask-user-input dd-privacy-mask\">',\n      expected: NodePrivacyLevel.MASK,\n    },\n    {\n      msg: 'has MASK and HIDDEN privacy classes (HIDDEN takes precedence)',\n      html: '<span class=\"dd-privacy-mask dd-privacy-hidden\">',\n      expected: NodePrivacyLevel.HIDDEN,\n    },\n  ].forEach(({ msg, html, expected }) => {\n    it(`returns ${String(expected)} when the node ${msg}`, () => {\n      const el = document.createElement('div')\n      el.innerHTML = html\n      expect(getNodeSelfPrivacyLevel(el.childNodes[0])).toBe(expected)\n    })\n  })\n})\n\ndescribe('derivePrivacyLevelGivenParent', () => {\n  const tests = [\n    {\n      parent: 'CORRUPTED',\n      child: NodePrivacyLevel.ALLOW,\n      expected: NodePrivacyLevel.ALLOW,\n      msg: 'Robust against parent invalid',\n    },\n    {\n      parent: NodePrivacyLevel.ALLOW,\n      child: 'CORRUPTED',\n      expected: NodePrivacyLevel.ALLOW,\n      msg: 'Robust against child invalid',\n    },\n    {\n      parent: 'CORRUPTED_PARENT',\n      child: 'CORRUPTED_CHILD',\n      expected: 'CORRUPTED_PARENT',\n      msg: 'Fallback to parent if child is invalid',\n    },\n    {\n      parent: NodePrivacyLevel.MASK,\n      child: NodePrivacyLevel.ALLOW,\n      expected: NodePrivacyLevel.ALLOW,\n      msg: 'Override mask',\n    },\n    {\n      parent: NodePrivacyLevel.ALLOW,\n      child: NodePrivacyLevel.MASK,\n      expected: NodePrivacyLevel.MASK,\n      msg: 'Override allow',\n    },\n    {\n      parent: NodePrivacyLevel.ALLOW,\n      child: NodePrivacyLevel.HIDDEN,\n      expected: NodePrivacyLevel.HIDDEN,\n      msg: 'Override allow (for hidden)',\n    },\n    {\n      parent: NodePrivacyLevel.MASK_USER_INPUT,\n      child: NodePrivacyLevel.ALLOW,\n      expected: NodePrivacyLevel.ALLOW,\n      msg: 'Override mask-user-input',\n    },\n\n    {\n      parent: NodePrivacyLevel.HIDDEN,\n      child: NodePrivacyLevel.MASK,\n      expected: NodePrivacyLevel.HIDDEN,\n      msg: 'Hidden is final',\n    },\n    {\n      parent: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      child: NodePrivacyLevel.ALLOW,\n      expected: NodePrivacyLevel.ALLOW,\n      msg: 'Override mask-unless-allowlisted (for allow)',\n    },\n    {\n      parent: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      child: NodePrivacyLevel.MASK,\n      expected: NodePrivacyLevel.MASK,\n      msg: 'Override mask-unless-allowlisted (for mask)',\n    },\n    {\n      parent: NodePrivacyLevel.ALLOW,\n      child: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      expected: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      msg: 'Override allow (for mask-unless-allowlisted)',\n    },\n    {\n      parent: NodePrivacyLevel.MASK,\n      child: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      expected: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      msg: 'Override mask (for mask-unless-allowlisted)',\n    },\n    {\n      parent: NodePrivacyLevel.HIDDEN,\n      child: NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n      expected: NodePrivacyLevel.HIDDEN,\n      msg: 'Hidden is final (for mask-unless-allowlisted)',\n    },\n  ]\n\n  tests.forEach(({ parent, child, expected, msg }) => {\n    it(`${msg}: parent(${parent}) to child(${child}) should be (${expected})`, () => {\n      expect(reducePrivacyLevel(child as NodePrivacyLevel, parent as NodePrivacyLevel)).toBe(expected)\n    })\n  })\n})\n\ndescribe('shouldMaskNode', () => {\n  describe('for form elements', () => {\n    it('returns false if the privacy level is ALLOW', () => {\n      const element = document.createElement('input')\n      expect(shouldMaskNode(element, NodePrivacyLevel.ALLOW)).toBeFalse()\n    })\n\n    it('returns true if the privacy level is not ALLOW', () => {\n      const element = document.createElement('input')\n      expect(shouldMaskNode(element, NodePrivacyLevel.MASK)).toBeTrue()\n      expect(shouldMaskNode(element, NodePrivacyLevel.MASK_USER_INPUT)).toBeTrue()\n      expect(shouldMaskNode(element, NodePrivacyLevel.IGNORE)).toBeTrue()\n      expect(shouldMaskNode(element, NodePrivacyLevel.HIDDEN)).toBeTrue()\n      expect(shouldMaskNode(element, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeTrue()\n    })\n  })\n\n  describe('for text nodes contained in form elements', () => {\n    it('returns true if the privacy level is MASK or MASK_USER_INPUT or MASK_UNLESS_ALLOWLISTED', () => {\n      const element = document.createElement('input')\n      const text = document.createTextNode('foo')\n      element.appendChild(text)\n      expect(shouldMaskNode(text, NodePrivacyLevel.MASK)).toBeTrue()\n      expect(shouldMaskNode(text, NodePrivacyLevel.MASK_USER_INPUT)).toBeTrue()\n      expect(shouldMaskNode(text, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeTrue()\n    })\n  })\n\n  describe('for other elements', () => {\n    it('returns false if the privacy level is ALLOW or MASK_USER_INPUT', () => {\n      const element = document.createElement('div')\n      expect(shouldMaskNode(element, NodePrivacyLevel.ALLOW)).toBeFalse()\n      expect(shouldMaskNode(element, NodePrivacyLevel.MASK_USER_INPUT)).toBeFalse()\n    })\n\n    it('returns true if the privacy level is not ALLOW nor MASK_USER_INPUT nor MASK_UNLESS_ALLOWLISTED', () => {\n      const element = document.createElement('div')\n      expect(shouldMaskNode(element, NodePrivacyLevel.MASK)).toBeTrue()\n      expect(shouldMaskNode(element, NodePrivacyLevel.IGNORE)).toBeTrue()\n      expect(shouldMaskNode(element, NodePrivacyLevel.HIDDEN)).toBeTrue()\n    })\n\n    describe('when privacy level is MASK_UNLESS_ALLOWLISTED', () => {\n      beforeEach(() => {\n        // Reset allowlist before each test\n        delete (window as any).$DD_ALLOW\n      })\n\n      describe('for text nodes', () => {\n        let textNode: Text\n\n        beforeEach(() => {\n          textNode = document.createTextNode('')\n        })\n\n        it('returns false for allowlisted text content', () => {\n          const allowedText = 'allowed text'\n          textNode.textContent = allowedText\n          ;(window as any).$DD_ALLOW = new Set([allowedText.toLocaleLowerCase()])\n          expect(shouldMaskNode(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeFalse()\n        })\n\n        it('returns false for whitespace-only text content', () => {\n          textNode.textContent = '   \\n\\t  '\n          expect(shouldMaskNode(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeFalse()\n        })\n\n        it('returns true for non-allowlisted, non-whitespace text content', () => {\n          textNode.textContent = 'some text'\n          expect(shouldMaskNode(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeTrue()\n        })\n\n        it('returns true if text node is child of a form element regardless of allowlist', () => {\n          const input = document.createElement('input')\n          textNode.textContent = 'some text'\n          input.appendChild(textNode)\n          ;(window as any).$DD_ALLOW = new Set(['some text'])\n          expect(shouldMaskNode(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeTrue()\n        })\n      })\n\n      describe('for non-text nodes', () => {\n        it('returns true for form elements', () => {\n          const input = document.createElement('input')\n          expect(shouldMaskNode(input, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeTrue()\n\n          const textarea = document.createElement('textarea')\n          expect(shouldMaskNode(textarea, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeTrue()\n        })\n\n        it('returns false for non-form elements', () => {\n          const div = document.createElement('div')\n          expect(shouldMaskNode(div, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeFalse()\n\n          const span = document.createElement('span')\n          expect(shouldMaskNode(span, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBeFalse()\n        })\n      })\n    })\n  })\n})\n\ndescribe('getTextContent', () => {\n  interface BrowserWindow extends Window {\n    $DD_ALLOW?: Set<string>\n  }\n\n  describe('for text nodes inside form elements', () => {\n    let textNode: Text\n\n    beforeEach(() => {\n      const textarea = appendElement('<textarea>some text</textarea>')\n      textNode = textarea.firstChild as Text\n    })\n\n    afterEach(() => {\n      delete (window as BrowserWindow).$DD_ALLOW\n    })\n\n    it('returns original text if privacy level is ALLOW', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.ALLOW)).toBe('some text')\n    })\n\n    it('censors text if privacy level is MASK', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.MASK)).toBe(censorText('some text'))\n    })\n\n    it('censors text if privacy level is MASK_USER_INPUT', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.MASK_USER_INPUT)).toBe(censorText('some text'))\n    })\n\n    it('censors text if privacy level is MASK_UNLESS_ALLOWLISTED, even if the text is allowlisted', () => {\n      ;(window as BrowserWindow).$DD_ALLOW = new Set(['some text'])\n      expect(getTextContent(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBe(censorText('some text'))\n    })\n\n    it('returns CENSORED_STRING_MARK if privacy level is HIDDEN', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.HIDDEN)).toBe(CENSORED_STRING_MARK)\n    })\n  })\n\n  describe('for text nodes not inside form elements', () => {\n    let textNode: Text\n\n    beforeEach(() => {\n      const div = appendElement('<div>some text</div>')\n      textNode = div.firstChild as Text\n    })\n\n    afterEach(() => {\n      delete (window as BrowserWindow).$DD_ALLOW\n    })\n\n    it('returns original text if privacy level is ALLOW', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.ALLOW)).toBe('some text')\n    })\n\n    it('censors text if privacy level is MASK', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.MASK)).toBe(censorText('some text'))\n    })\n\n    it('returns original text if privacy level is MASK_USER_INPUT', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.MASK_USER_INPUT)).toBe('some text')\n    })\n\n    it('returns CENSORED_STRING_MARK if privacy level is HIDDEN', () => {\n      expect(getTextContent(textNode, NodePrivacyLevel.HIDDEN)).toBe(CENSORED_STRING_MARK)\n    })\n\n    describe('when privacy level is MASK_UNLESS_ALLOWLISTED', () => {\n      it('returns original text if the text is allowlisted', () => {\n        ;(window as BrowserWindow).$DD_ALLOW = new Set(['some text'])\n        expect(getTextContent(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBe('some text')\n      })\n\n      it('censors text if the text is not allowlisted', () => {\n        expect(getTextContent(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBe(censorText('some text'))\n      })\n\n      it('returns original text for whitespace-only content (treated as allowlisted)', () => {\n        textNode.textContent = '   '\n        expect(getTextContent(textNode, NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED)).toBe('   ')\n      })\n    })\n  })\n})\n\nconst TEST_STRINGS = {\n  COMPLEX_MIXED: 'test-team-name:💥$$$',\n  PARAGRAPH_MIXED: '✅ This is an action name in allowlist',\n}\n\ndescribe('maskWithAllowlist', () => {\n  interface BrowserWindow extends Window {\n    $DD_ALLOW?: Set<string>\n  }\n\n  beforeEach(() => {\n    ;(window as BrowserWindow).$DD_ALLOW = new Set([TEST_STRINGS.PARAGRAPH_MIXED])\n  })\n\n  afterEach(() => {\n    ;(window as BrowserWindow).$DD_ALLOW = undefined\n  })\n\n  it('should fail closed if $DD_ALLOW is not defined', () => {\n    ;(window as BrowserWindow).$DD_ALLOW = undefined\n    const testString = maskDisallowedTextContent('mask-feature-on', ACTION_NAME_MASK)\n    expect(testString).toBe(ACTION_NAME_MASK)\n  })\n\n  it('masks text content not in allowlist (with dictionary from $DD_ALLOW)', () => {\n    const testString = maskDisallowedTextContent('any unallowed string', ACTION_NAME_MASK)\n    expect(testString).toBe(ACTION_NAME_MASK)\n  })\n\n  it('does not mask text content if it is in allowlist', () => {\n    const testString = maskDisallowedTextContent(TEST_STRINGS.COMPLEX_MIXED, ACTION_NAME_MASK)\n    expect(testString).toBe('xxx')\n  })\n\n  it('handles empty string', () => {\n    const result = maskDisallowedTextContent('', ACTION_NAME_MASK)\n    expect(result).toBe('')\n  })\n\n  it('handles whitespace-only string', () => {\n    const result = maskDisallowedTextContent('   \\n\\t  ', ACTION_NAME_MASK)\n    expect(result).toBe('   \\n\\t  ')\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/privacy.ts",
    "content": "import { isElementNode, getParentNode, isTextNode } from '../browser/htmlDomUtils'\nimport {\n  NodePrivacyLevel,\n  FORM_PRIVATE_TAG_NAMES,\n  CENSORED_STRING_MARK,\n  getPrivacySelector,\n  TEXT_MASKING_CHAR,\n  PRIVACY_ATTR_NAME,\n} from './privacyConstants'\nimport { STABLE_ATTRIBUTES } from './getSelectorFromElement'\nimport type { RumConfiguration } from './configuration'\n\nexport type NodePrivacyLevelCache = Map<Node, NodePrivacyLevel>\n\n/**\n * Get node privacy level by iterating over its ancestors. When the direct parent privacy level is\n * know, it is best to use something like:\n *\n * derivePrivacyLevelGivenParent(getNodeSelfPrivacyLevel(node), parentNodePrivacyLevel)\n */\nexport function getNodePrivacyLevel(\n  node: Node,\n  defaultPrivacyLevel: NodePrivacyLevel,\n  cache?: NodePrivacyLevelCache\n): NodePrivacyLevel {\n  if (cache && cache.has(node)) {\n    return cache.get(node)!\n  }\n  const parentNode = getParentNode(node)\n  const parentNodePrivacyLevel = parentNode\n    ? getNodePrivacyLevel(parentNode, defaultPrivacyLevel, cache)\n    : defaultPrivacyLevel\n  const selfNodePrivacyLevel = getNodeSelfPrivacyLevel(node)\n  const nodePrivacyLevel = reducePrivacyLevel(selfNodePrivacyLevel, parentNodePrivacyLevel)\n  if (cache) {\n    cache.set(node, nodePrivacyLevel)\n  }\n  return nodePrivacyLevel\n}\n\n/**\n * Reduces the next privacy level based on self + parent privacy levels\n */\nexport function reducePrivacyLevel(\n  childPrivacyLevel: NodePrivacyLevel | undefined,\n  parentNodePrivacyLevel: NodePrivacyLevel\n): NodePrivacyLevel {\n  switch (parentNodePrivacyLevel) {\n    // These values cannot be overridden\n    case NodePrivacyLevel.HIDDEN:\n    case NodePrivacyLevel.IGNORE:\n      return parentNodePrivacyLevel\n  }\n  switch (childPrivacyLevel) {\n    case NodePrivacyLevel.ALLOW:\n    case NodePrivacyLevel.MASK:\n    case NodePrivacyLevel.MASK_USER_INPUT:\n    case NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED:\n    case NodePrivacyLevel.HIDDEN:\n    case NodePrivacyLevel.IGNORE:\n      return childPrivacyLevel\n    default:\n      return parentNodePrivacyLevel\n  }\n}\n\n/**\n * Determines the node's own privacy level without checking for ancestors.\n */\nexport function getNodeSelfPrivacyLevel(node: Node): NodePrivacyLevel | undefined {\n  // Only Element types can have a privacy level set\n  if (!isElementNode(node)) {\n    return\n  }\n\n  // Overrules for replay purpose\n  if (node.tagName === 'BASE') {\n    return NodePrivacyLevel.ALLOW\n  }\n\n  // Overrules to enforce end-user protection\n  if (node.tagName === 'INPUT') {\n    const inputElement = node as HTMLInputElement\n    if (inputElement.type === 'password' || inputElement.type === 'email' || inputElement.type === 'tel') {\n      return NodePrivacyLevel.MASK\n    }\n    if (inputElement.type === 'hidden') {\n      return NodePrivacyLevel.MASK\n    }\n    const autocomplete = inputElement.getAttribute('autocomplete')\n    // Handle input[autocomplete=cc-number/cc-csc/cc-exp/cc-exp-month/cc-exp-year/new-password/current-password]\n    if (autocomplete && (autocomplete.startsWith('cc-') || autocomplete.endsWith('-password'))) {\n      return NodePrivacyLevel.MASK\n    }\n  }\n\n  // Check HTML privacy attributes and classes\n  if (node.matches(getPrivacySelector(NodePrivacyLevel.HIDDEN))) {\n    return NodePrivacyLevel.HIDDEN\n  }\n\n  if (node.matches(getPrivacySelector(NodePrivacyLevel.MASK))) {\n    return NodePrivacyLevel.MASK\n  }\n\n  if (node.matches(getPrivacySelector(NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED))) {\n    return NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED\n  }\n\n  if (node.matches(getPrivacySelector(NodePrivacyLevel.MASK_USER_INPUT))) {\n    return NodePrivacyLevel.MASK_USER_INPUT\n  }\n\n  if (node.matches(getPrivacySelector(NodePrivacyLevel.ALLOW))) {\n    return NodePrivacyLevel.ALLOW\n  }\n\n  if (shouldIgnoreElement(node)) {\n    return NodePrivacyLevel.IGNORE\n  }\n}\n\n/**\n * Helper aiming to unify `mask` and `mask-user-input` privacy levels:\n *\n * In the `mask` case, it is trivial: we should mask the element.\n *\n * In the `mask-user-input` case, we should mask the element only if it is a \"form\" element or the\n * direct parent is a form element for text nodes).\n *\n * Other `shouldMaskNode` cases are edge cases that should not matter too much (ex: should we mask a\n * node if it is ignored or hidden? it doesn't matter since it won't be serialized).\n */\nexport function shouldMaskNode(node: Node, privacyLevel: NodePrivacyLevel) {\n  switch (privacyLevel) {\n    case NodePrivacyLevel.MASK:\n    case NodePrivacyLevel.HIDDEN:\n    case NodePrivacyLevel.IGNORE:\n      return true\n    case NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED:\n      if (isTextNode(node)) {\n        // Always return true if our parent is a form element, like MASK_USER_INPUT.\n        // Otherwise, decide whether to mask based on the allowlist.\n        return isFormElement(node.parentNode) ? true : !isAllowlisted(node.textContent || '')\n      }\n      // Always return true if we're a form element, like MASK_USER_INPUT.\n      // Otherwise, return false; MASK_UNLESS_ALLOWLISTED only directly masks text nodes.\n      return isFormElement(node)\n    case NodePrivacyLevel.MASK_USER_INPUT:\n      return isTextNode(node) ? isFormElement(node.parentNode) : isFormElement(node)\n    default:\n      return false\n  }\n}\n\nexport function shouldMaskAttribute(\n  tagName: string,\n  attributeName: string,\n  attributeValue: string | null,\n  nodePrivacyLevel: NodePrivacyLevel,\n  configuration: RumConfiguration\n) {\n  if (nodePrivacyLevel !== NodePrivacyLevel.MASK && nodePrivacyLevel !== NodePrivacyLevel.MASK_UNLESS_ALLOWLISTED) {\n    return false\n  }\n  if (\n    attributeName === PRIVACY_ATTR_NAME ||\n    STABLE_ATTRIBUTES.includes(attributeName) ||\n    attributeName === configuration.actionNameAttribute\n  ) {\n    return false\n  }\n\n  switch (attributeName) {\n    case 'title':\n    case 'alt':\n    case 'placeholder':\n    case 'aria-label':\n    case 'name':\n      return true\n  }\n  if (tagName === 'A' && attributeName === 'href') {\n    return true\n  }\n  if (tagName === 'IFRAME' && attributeName === 'srcdoc') {\n    return true\n  }\n  if (attributeValue && attributeName.startsWith('data-')) {\n    return true\n  }\n  if ((tagName === 'IMG' || tagName === 'SOURCE') && (attributeName === 'src' || attributeName === 'srcset')) {\n    return true\n  }\n\n  return false\n}\n\nfunction isFormElement(node: Node | null): boolean {\n  if (!node || node.nodeType !== node.ELEMENT_NODE) {\n    return false\n  }\n  const element = node as HTMLInputElement\n  if (element.tagName === 'INPUT') {\n    switch (element.type) {\n      case 'button':\n      case 'color':\n      case 'reset':\n      case 'submit':\n        return false\n    }\n  }\n  return !!FORM_PRIVATE_TAG_NAMES[element.tagName]\n}\n\n/**\n * Text censoring non-destructively maintains whitespace characters in order to preserve text shape\n * during replay.\n */\nexport function censorText(text: string): string {\n  return text.replace(/\\S/g, TEXT_MASKING_CHAR)\n}\n\nexport function getTextContent(textNode: Node, parentNodePrivacyLevel: NodePrivacyLevel): string | undefined {\n  // The parent node may not be a html element which has a tagName attribute.\n  // So just let it be undefined which is ok in this use case.\n  const parentTagName = textNode.parentElement?.tagName\n  let textContent = textNode.textContent || ''\n\n  const shouldIgnoreWhiteSpace = parentTagName === 'HEAD'\n  if (shouldIgnoreWhiteSpace && !textContent.trim()) {\n    return\n  }\n\n  const nodePrivacyLevel = parentNodePrivacyLevel\n\n  const isScript = parentTagName === 'SCRIPT'\n\n  if (isScript) {\n    // For perf reasons, we don't record script (heuristic)\n    textContent = CENSORED_STRING_MARK\n  } else if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {\n    // Should never occur, but just in case, we set to CENSORED_MARK.\n    textContent = CENSORED_STRING_MARK\n  } else if (shouldMaskNode(textNode, nodePrivacyLevel)) {\n    if (\n      // Scrambling the child list breaks text nodes for DATALIST/SELECT/OPTGROUP\n      parentTagName === 'DATALIST' ||\n      parentTagName === 'SELECT' ||\n      parentTagName === 'OPTGROUP'\n    ) {\n      if (!textContent.trim()) {\n        return\n      }\n    } else if (parentTagName === 'OPTION') {\n      // <Option> has low entropy in charset + text length, so use `CENSORED_STRING_MARK` when masked\n      textContent = CENSORED_STRING_MARK\n    } else {\n      textContent = censorText(textContent)\n    }\n  }\n  return textContent\n}\n\n/**\n * TODO: Preserve CSS element order, and record the presence of the tag, just don't render\n * We don't need this logic on the recorder side.\n * For security related meta's, customer can mask themmanually given they\n * are easy to identify in the HEAD tag.\n */\nexport function shouldIgnoreElement(element: Element): boolean {\n  if (element.nodeName === 'SCRIPT') {\n    return true\n  }\n\n  if (element.nodeName === 'LINK') {\n    const relAttribute = getLowerCaseAttribute('rel')\n    return (\n      // Link as script - Ignore only when rel=preload, modulepreload or prefetch\n      (/preload|prefetch/i.test(relAttribute) && getLowerCaseAttribute('as') === 'script') ||\n      // Favicons\n      relAttribute === 'shortcut icon' ||\n      relAttribute === 'icon'\n    )\n  }\n\n  if (element.nodeName === 'META') {\n    const nameAttribute = getLowerCaseAttribute('name')\n    const relAttribute = getLowerCaseAttribute('rel')\n    const propertyAttribute = getLowerCaseAttribute('property')\n    return (\n      // Favicons\n      /^msapplication-tile(image|color)$/.test(nameAttribute) ||\n      nameAttribute === 'application-name' ||\n      relAttribute === 'icon' ||\n      relAttribute === 'apple-touch-icon' ||\n      relAttribute === 'shortcut icon' ||\n      // Description\n      nameAttribute === 'keywords' ||\n      nameAttribute === 'description' ||\n      // Social\n      /^(og|twitter|fb):/.test(propertyAttribute) ||\n      /^(og|twitter):/.test(nameAttribute) ||\n      nameAttribute === 'pinterest' ||\n      // Robots\n      nameAttribute === 'robots' ||\n      nameAttribute === 'googlebot' ||\n      nameAttribute === 'bingbot' ||\n      // Http headers. Ex: X-UA-Compatible, Content-Type, Content-Language, cache-control,\n      // X-Translated-By\n      element.hasAttribute('http-equiv') ||\n      // Authorship\n      nameAttribute === 'author' ||\n      nameAttribute === 'generator' ||\n      nameAttribute === 'framework' ||\n      nameAttribute === 'publisher' ||\n      nameAttribute === 'progid' ||\n      /^article:/.test(propertyAttribute) ||\n      /^product:/.test(propertyAttribute) ||\n      // Verification\n      nameAttribute === 'google-site-verification' ||\n      nameAttribute === 'yandex-verification' ||\n      nameAttribute === 'csrf-token' ||\n      nameAttribute === 'p:domain_verify' ||\n      nameAttribute === 'verify-v1' ||\n      nameAttribute === 'verification' ||\n      nameAttribute === 'shopify-checkout-api-token'\n    )\n  }\n\n  function getLowerCaseAttribute(name: string) {\n    return (element.getAttribute(name) || '').toLowerCase()\n  }\n\n  return false\n}\n\nexport interface BrowserWindow extends Window {\n  $DD_ALLOW?: Set<string>\n}\n\nexport function isAllowlisted(text: string): boolean {\n  if (!text || !text.trim()) {\n    return true\n  }\n  // We are using toLocaleLowerCase when adding to the allowlist to avoid case sensitivity\n  // so we need to do the same here\n  return (window as BrowserWindow).$DD_ALLOW?.has(text.toLocaleLowerCase()) || false\n}\n\nexport function maskDisallowedTextContent(text: string, fixedMask?: string): string {\n  if (isAllowlisted(text)) {\n    return text\n  }\n  return fixedMask || censorText(text)\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/privacyConstants.ts",
    "content": "import { DefaultPrivacyLevel } from '@datadog/browser-core'\n\nexport const NodePrivacyLevel = {\n  IGNORE: 'ignore',\n  HIDDEN: 'hidden',\n  ALLOW: DefaultPrivacyLevel.ALLOW,\n  MASK: DefaultPrivacyLevel.MASK,\n  MASK_USER_INPUT: DefaultPrivacyLevel.MASK_USER_INPUT,\n  MASK_UNLESS_ALLOWLISTED: DefaultPrivacyLevel.MASK_UNLESS_ALLOWLISTED,\n} as const\nexport type NodePrivacyLevel = (typeof NodePrivacyLevel)[keyof typeof NodePrivacyLevel]\n\nexport const PRIVACY_ATTR_NAME = 'data-dd-privacy'\n\n// Privacy Attrs\nexport const PRIVACY_ATTR_VALUE_ALLOW = 'allow'\nexport const PRIVACY_ATTR_VALUE_MASK = 'mask'\nexport const PRIVACY_ATTR_VALUE_MASK_USER_INPUT = 'mask-user-input'\nexport const PRIVACY_ATTR_VALUE_MASK_UNLESS_ALLOWLISTED = 'mask-unless-allowlisted'\nexport const PRIVACY_ATTR_VALUE_HIDDEN = 'hidden'\n\n// Privacy Classes - not all customers can set plain HTML attributes, so support classes too\nexport const PRIVACY_CLASS_PREFIX = 'dd-privacy-'\n\n// Private Replacement Templates\nexport const CENSORED_STRING_MARK = '***'\nexport const CENSORED_IMG_MARK = 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='\n\nexport const FORM_PRIVATE_TAG_NAMES: { [tagName: string]: true } = {\n  INPUT: true,\n  OUTPUT: true,\n  TEXTAREA: true,\n  SELECT: true,\n  OPTION: true,\n  DATALIST: true,\n  OPTGROUP: true,\n}\n\nexport const TEXT_MASKING_CHAR = 'x'\n\nexport function getPrivacySelector(privacyLevel: string) {\n  return `[${PRIVACY_ATTR_NAME}=\"${privacyLevel}\"], .${PRIVACY_CLASS_PREFIX}${privacyLevel}`\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/requestCollection.spec.ts",
    "content": "import type { Payload } from '@datadog/browser-core'\nimport { RequestType } from '@datadog/browser-core'\nimport type { MockFetch, MockFetchManager } from '@datadog/browser-core/test'\nimport { registerCleanupTask, SPEC_ENDPOINTS, mockFetch, mockXhr, withXhr } from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../test'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport type { RequestCompleteEvent, RequestStartEvent } from './requestCollection'\nimport { trackFetch, trackXhr } from './requestCollection'\nimport type { Tracer } from './tracing/tracer'\nimport { clearTracingIfNeeded } from './tracing/tracer'\nimport { createSpanIdentifier, createTraceIdentifier } from './tracing/identifier'\n\nconst DEFAULT_PAYLOAD = {} as Payload\n\ndescribe('collect fetch', () => {\n  const FAKE_URL = 'http://fake-url/'\n  let fetch: MockFetch\n  let mockFetchManager: MockFetchManager\n  let startSpy: jasmine.Spy<(requestStartEvent: RequestStartEvent) => void>\n  let completeSpy: jasmine.Spy<(requestCompleteEvent: RequestCompleteEvent) => void>\n  let stopFetchTracking: () => void\n\n  beforeEach(() => {\n    mockFetchManager = mockFetch()\n\n    startSpy = jasmine.createSpy('requestStart')\n    completeSpy = jasmine.createSpy('requestComplete')\n    const lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.REQUEST_STARTED, startSpy)\n    lifeCycle.subscribe(LifeCycleEventType.REQUEST_COMPLETED, completeSpy)\n    const tracerStub: Partial<Tracer> = {\n      clearTracingIfNeeded,\n      traceFetch: (context) => {\n        context.traceId = createTraceIdentifier()\n        context.spanId = createSpanIdentifier()\n      },\n    }\n    ;({ stop: stopFetchTracking } = trackFetch(lifeCycle, mockRumConfiguration(), tracerStub as Tracer))\n\n    fetch = window.fetch as MockFetch\n\n    registerCleanupTask(() => {\n      stopFetchTracking()\n    })\n  })\n\n  it('should notify on request start', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 500, responseText: 'fetch error' })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(startSpy).toHaveBeenCalledWith({ requestIndex: jasmine.any(Number) as unknown as number, url: FAKE_URL })\n      done()\n    })\n  })\n\n  it('should notify on request without body', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 200 })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = completeSpy.calls.argsFor(0)[0]\n\n      expect(request.type).toEqual(RequestType.FETCH)\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(200)\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should notify on request with body used by another instrumentation', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 200, bodyUsed: true })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = completeSpy.calls.argsFor(0)[0]\n\n      expect(request.type).toEqual(RequestType.FETCH)\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(200)\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should notify on request with body disturbed', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 200, bodyDisturbed: true })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = completeSpy.calls.argsFor(0)[0]\n\n      expect(request.type).toEqual(RequestType.FETCH)\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(200)\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should notify on request complete', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 500, responseText: 'fetch error' })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = completeSpy.calls.argsFor(0)[0]\n\n      expect(request.type).toEqual(RequestType.FETCH)\n      expect(request.method).toEqual('GET')\n      expect(request.url).toEqual(FAKE_URL)\n      expect(request.status).toEqual(500)\n      expect(request.handlingStack).toBeDefined()\n      done()\n    })\n  })\n\n  it('should assign a request id', (done) => {\n    fetch(FAKE_URL).resolveWith({ status: 500, responseText: 'fetch error' })\n\n    mockFetchManager.whenAllComplete(() => {\n      const startRequestIndex = startSpy.calls.argsFor(0)[0].requestIndex\n      const completeRequestIndex = completeSpy.calls.argsFor(0)[0].requestIndex\n\n      expect(completeRequestIndex).toBe(startRequestIndex)\n      done()\n    })\n  })\n\n  it('should ignore intake requests', (done) => {\n    fetch(SPEC_ENDPOINTS.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD)).resolveWith({\n      status: 200,\n      responseText: 'foo',\n    })\n\n    mockFetchManager.whenAllComplete(() => {\n      expect(startSpy).not.toHaveBeenCalled()\n      expect(completeSpy).not.toHaveBeenCalled()\n      done()\n    })\n  })\n\n  describe('tracing', () => {\n    it('should trace requests by default', (done) => {\n      fetch(FAKE_URL).resolveWith({ status: 200, responseText: 'ok' })\n\n      mockFetchManager.whenAllComplete(() => {\n        const request = completeSpy.calls.argsFor(0)[0]\n\n        expect(request.traceId).toBeDefined()\n        done()\n      })\n    })\n\n    it('should trace aborted requests', (done) => {\n      fetch(FAKE_URL).abort()\n\n      mockFetchManager.whenAllComplete(() => {\n        const request = completeSpy.calls.argsFor(0)[0]\n\n        expect(request.traceId).toBeDefined()\n        done()\n      })\n    })\n\n    it('should not trace requests ending with status 0', (done) => {\n      fetch(FAKE_URL).resolveWith({ status: 0, responseText: 'fetch cancelled' })\n\n      mockFetchManager.whenAllComplete(() => {\n        const request = completeSpy.calls.argsFor(0)[0]\n\n        expect(request.status).toEqual(0)\n        expect(request.traceId).toBeUndefined()\n        done()\n      })\n    })\n  })\n})\n\ndescribe('collect xhr', () => {\n  let startSpy: jasmine.Spy<(requestStartEvent: RequestStartEvent) => void>\n  let completeSpy: jasmine.Spy<(requestCompleteEvent: RequestCompleteEvent) => void>\n  let stopXhrTracking: () => void\n\n  beforeEach(() => {\n    const configuration = mockRumConfiguration()\n    mockXhr()\n    startSpy = jasmine.createSpy('requestStart')\n    completeSpy = jasmine.createSpy('requestComplete')\n    const lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.REQUEST_STARTED, startSpy)\n    lifeCycle.subscribe(LifeCycleEventType.REQUEST_COMPLETED, completeSpy)\n    const tracerStub: Partial<Tracer> = {\n      clearTracingIfNeeded,\n      traceXhr: (context) => {\n        context.traceId = createTraceIdentifier()\n        context.spanId = createSpanIdentifier()\n      },\n    }\n    ;({ stop: stopXhrTracking } = trackXhr(lifeCycle, configuration, tracerStub as Tracer))\n\n    registerCleanupTask(() => {\n      stopXhrTracking()\n    })\n  })\n\n  it('should notify on request start', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200)\n      },\n      onComplete() {\n        expect(startSpy).toHaveBeenCalledWith({\n          requestIndex: jasmine.any(Number) as unknown as number,\n          url: jasmine.stringMatching(/\\/ok$/) as unknown as string,\n        })\n        done()\n      },\n    })\n  })\n\n  it('should notify on request complete', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200, 'ok')\n      },\n      onComplete() {\n        const request = completeSpy.calls.argsFor(0)[0]\n\n        expect(request.type).toEqual(RequestType.XHR)\n        expect(request.method).toEqual('GET')\n        expect(request.url).toContain('/ok')\n        expect(request.status).toEqual(200)\n        expect(request.handlingStack).toBeDefined()\n        done()\n      },\n    })\n  })\n\n  it('should assign a request id', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(200)\n      },\n      onComplete() {\n        const startRequestIndex = startSpy.calls.argsFor(0)[0].requestIndex\n        const completeRequestIndex = completeSpy.calls.argsFor(0)[0].requestIndex\n\n        expect(completeRequestIndex).toBe(startRequestIndex)\n        done()\n      },\n    })\n  })\n\n  it('should ignore intake requests', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', SPEC_ENDPOINTS.rumEndpointBuilder.build('fetch', DEFAULT_PAYLOAD))\n        xhr.send()\n        xhr.complete(200)\n      },\n      onComplete() {\n        expect(startSpy).not.toHaveBeenCalled()\n        expect(completeSpy).not.toHaveBeenCalled()\n        done()\n      },\n    })\n  })\n\n  it('should not trace cancelled requests', (done) => {\n    withXhr({\n      setup(xhr) {\n        xhr.open('GET', '/ok')\n        xhr.send()\n        xhr.complete(0)\n      },\n      onComplete() {\n        const request = completeSpy.calls.argsFor(0)[0]\n        expect(request.status).toEqual(0)\n        expect(request.traceId).toEqual(undefined)\n        done()\n      },\n    })\n  })\n\n  describe('tracing', () => {\n    it('should trace requests by default', (done) => {\n      withXhr({\n        setup(xhr) {\n          xhr.open('GET', '/ok')\n          xhr.send()\n          xhr.complete(200)\n        },\n        onComplete() {\n          const request = completeSpy.calls.argsFor(0)[0]\n          expect(request.traceId).toBeDefined()\n          done()\n        },\n      })\n    })\n\n    it('should trace aborted requests', (done) => {\n      withXhr({\n        setup(xhr) {\n          xhr.open('GET', '/ok')\n          xhr.send()\n          xhr.abort()\n        },\n        onComplete() {\n          const request = completeSpy.calls.argsFor(0)[0]\n          expect(request.traceId).toBeDefined()\n          done()\n        },\n      })\n    })\n\n    it('should not trace requests ending with status 0', (done) => {\n      withXhr({\n        setup(xhr) {\n          xhr.open('GET', '/ok')\n          xhr.send()\n          xhr.complete(0)\n        },\n        onComplete() {\n          const request = completeSpy.calls.argsFor(0)[0]\n          expect(request.status).toEqual(0)\n          expect(request.traceId).toBeUndefined()\n          done()\n        },\n      })\n    })\n  })\n})\n\ndescribe('GraphQL response text collection', () => {\n  const FAKE_GRAPHQL_URL = 'http://fake-url/graphql'\n\n  function setupGraphQlFetchTest(trackResponseErrors: boolean) {\n    const mockFetchManager = mockFetch()\n    const completeSpy = jasmine.createSpy('requestComplete')\n    const lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.REQUEST_COMPLETED, completeSpy)\n\n    const configuration = mockRumConfiguration({\n      allowedGraphQlUrls: [{ match: /\\/graphql$/, trackResponseErrors }],\n    })\n    const tracerStub: Partial<Tracer> = { clearTracingIfNeeded, traceFetch: jasmine.createSpy() }\n    const { stop } = trackFetch(lifeCycle, configuration, tracerStub as Tracer)\n    registerCleanupTask(() => {\n      stop()\n    })\n\n    return { mockFetchManager, completeSpy, fetch: window.fetch as MockFetch }\n  }\n\n  it('should collect responseBody when trackResponseErrors is enabled', (done) => {\n    const { mockFetchManager, completeSpy, fetch } = setupGraphQlFetchTest(true)\n\n    const responseBody = JSON.stringify({\n      data: null,\n      errors: [{ message: 'Not found' }, { message: 'Unauthorized' }],\n    })\n\n    fetch(FAKE_GRAPHQL_URL, {\n      method: 'POST',\n      body: JSON.stringify({ query: 'query Test { test }' }),\n    }).resolveWith({\n      status: 200,\n      responseText: responseBody,\n    })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = completeSpy.calls.argsFor(0)[0]\n      expect(request.responseBody).toBe(responseBody)\n      done()\n    })\n  })\n\n  it('should not collect responseBody when trackResponseErrors is disabled', (done) => {\n    const { mockFetchManager, completeSpy, fetch } = setupGraphQlFetchTest(false)\n\n    const responseBody = JSON.stringify({\n      data: null,\n      errors: [{ message: 'Not found' }],\n    })\n\n    fetch(FAKE_GRAPHQL_URL, {\n      method: 'POST',\n      body: JSON.stringify({ query: 'query Test { test }' }),\n    }).resolveWith({\n      status: 200,\n      responseText: responseBody,\n    })\n\n    mockFetchManager.whenAllComplete(() => {\n      const request = completeSpy.calls.argsFor(0)[0]\n      expect(request.responseBody).toBeUndefined()\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/requestCollection.ts",
    "content": "import type {\n  Duration,\n  XhrCompleteContext,\n  XhrStartContext,\n  ClocksState,\n  FetchStartContext,\n  FetchResolveContext,\n  ContextManager,\n} from '@datadog/browser-core'\nimport {\n  RequestType,\n  ResponseBodyAction,\n  elapsed,\n  initFetchObservable,\n  initXhrObservable,\n  timeStampNow,\n} from '@datadog/browser-core'\nimport type { RumSessionManager } from '..'\nimport type { RumConfiguration } from './configuration'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\nimport { isAllowedRequestUrl } from './resource/resourceUtils'\nimport type { Tracer } from './tracing/tracer'\nimport { startTracer } from './tracing/tracer'\nimport type { SpanIdentifier, TraceIdentifier } from './tracing/identifier'\nimport { findGraphQlConfiguration } from './resource/graphql'\n\nexport interface CustomContext {\n  requestIndex: number\n  spanId?: SpanIdentifier\n  traceId?: TraceIdentifier\n  traceSampled?: boolean\n}\nexport interface RumFetchStartContext extends FetchStartContext, CustomContext {}\nexport interface RumFetchResolveContext extends FetchResolveContext, CustomContext {}\nexport interface RumXhrStartContext extends XhrStartContext, CustomContext {}\nexport interface RumXhrCompleteContext extends XhrCompleteContext, CustomContext {}\n\nexport interface RequestStartEvent {\n  requestIndex: number\n  url: string\n}\nexport interface RequestCompleteEvent {\n  requestIndex: number\n  type: RequestType\n  method: string\n  url: string\n  status: number\n  responseType?: string\n  startClocks: ClocksState\n  duration: Duration\n  spanId?: SpanIdentifier\n  traceId?: TraceIdentifier\n  traceSampled?: boolean\n  xhr?: XMLHttpRequest\n  response?: Response\n  input?: unknown\n  init?: RequestInit\n  error?: Error\n  isAborted: boolean\n  isAbortedOnStart: boolean\n  handlingStack?: string\n  requestBody?: unknown\n  responseBody?: string\n}\n\nlet nextRequestIndex = 1\n\nexport function startRequestCollection(\n  lifeCycle: LifeCycle,\n  configuration: RumConfiguration,\n  sessionManager: RumSessionManager,\n  userContext: ContextManager,\n  accountContext: ContextManager\n) {\n  const tracer = startTracer(configuration, sessionManager, userContext, accountContext)\n  trackXhr(lifeCycle, configuration, tracer)\n  trackFetch(lifeCycle, configuration, tracer)\n}\n\nexport function trackXhr(lifeCycle: LifeCycle, configuration: RumConfiguration, tracer: Tracer) {\n  const subscription = initXhrObservable(configuration).subscribe((rawContext) => {\n    const context = rawContext as RumXhrStartContext | RumXhrCompleteContext\n    if (!isAllowedRequestUrl(context.url)) {\n      return\n    }\n\n    switch (context.state) {\n      case 'start':\n        tracer.traceXhr(context, context.xhr)\n        context.requestIndex = getNextRequestIndex()\n\n        lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, {\n          requestIndex: context.requestIndex,\n          url: context.url,\n        })\n        break\n      case 'complete':\n        tracer.clearTracingIfNeeded(context)\n        lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, {\n          ...context,\n          type: RequestType.XHR,\n          isAbortedOnStart: false,\n        })\n        break\n    }\n  })\n\n  return { stop: () => subscription.unsubscribe() }\n}\n\nexport function trackFetch(lifeCycle: LifeCycle, configuration: RumConfiguration, tracer: Tracer) {\n  const subscription = initFetchObservable({\n    responseBodyAction: (context) => {\n      if (findGraphQlConfiguration(context.url, configuration)?.trackResponseErrors) {\n        return ResponseBodyAction.COLLECT\n      }\n      return ResponseBodyAction.WAIT\n    },\n  }).subscribe((rawContext) => {\n    const context = rawContext as RumFetchResolveContext | RumFetchStartContext\n    if (!isAllowedRequestUrl(context.url)) {\n      return\n    }\n\n    switch (context.state) {\n      case 'start':\n        tracer.traceFetch(context)\n        context.requestIndex = getNextRequestIndex()\n\n        lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, {\n          requestIndex: context.requestIndex,\n          url: context.url,\n        })\n        break\n      case 'resolve':\n        tracer.clearTracingIfNeeded(context)\n        lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, {\n          ...context,\n          duration: elapsed(context.startClocks.timeStamp, timeStampNow()),\n          type: RequestType.FETCH,\n          requestBody: context.init?.body,\n        })\n        break\n    }\n  })\n  return { stop: () => subscription.unsubscribe() }\n}\n\nfunction getNextRequestIndex() {\n  const result = nextRequestIndex\n  nextRequestIndex += 1\n  return result\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/graphql.spec.ts",
    "content": "import { mockRumConfiguration } from '../../../test'\nimport type { RequestCompleteEvent } from '../requestCollection'\nimport {\n  extractGraphQlMetadata,\n  extractGraphQlRequestMetadata,\n  findGraphQlConfiguration,\n  parseGraphQlResponse,\n} from './graphql'\n\ndescribe('GraphQL detection and metadata extraction', () => {\n  describe('findGraphQlConfiguration', () => {\n    it('should detect GraphQL requests matching string URLs', () => {\n      const configuration = mockRumConfiguration({\n        allowedGraphQlUrls: [\n          { match: 'http://localhost/graphql', trackPayload: false },\n          { match: 'https://api.example.com/graphql', trackPayload: false },\n        ],\n      })\n\n      expect(findGraphQlConfiguration('https://api.example.com/graphql', configuration)).toBeTruthy()\n      expect(findGraphQlConfiguration('http://localhost/api', configuration)).toBeUndefined()\n    })\n\n    it('should detect GraphQL requests matching regex patterns', () => {\n      const configuration = mockRumConfiguration({\n        allowedGraphQlUrls: [{ match: /\\/graphql$/i, trackPayload: false }],\n      })\n\n      expect(findGraphQlConfiguration('/api/graphql', configuration)).toBeTruthy()\n      expect(findGraphQlConfiguration('/graphql/admin', configuration)).toBeUndefined()\n    })\n\n    it('should detect GraphQL requests matching function matchers', () => {\n      const configuration = mockRumConfiguration({\n        allowedGraphQlUrls: [{ match: (url: string) => url.includes('gql'), trackPayload: false }],\n      })\n\n      expect(findGraphQlConfiguration('/api/gql', configuration)).toBeTruthy()\n      expect(findGraphQlConfiguration('/gql-endpoint', configuration)).toBeTruthy()\n      expect(findGraphQlConfiguration('/api/rest', configuration)).toBeUndefined()\n    })\n  })\n\n  describe('extractGraphQlRequestMetadata', () => {\n    it('should extract query operation type and name from POST request body', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id name } }',\n        operationName: 'GetUser',\n        variables: { id: '123' },\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: 'query GetUser { user { id name } }',\n      })\n    })\n\n    it('should handle empty variables object', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id name } }',\n        operationName: 'GetUser',\n        variables: {},\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: '{}',\n        payload: 'query GetUser { user { id name } }',\n      })\n    })\n\n    it('should handle null variables', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id name } }',\n        operationName: 'GetUser',\n        variables: null,\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: undefined,\n        payload: 'query GetUser { user { id name } }',\n      })\n    })\n\n    it('should return undefined for invalid JSON in POST body', () => {\n      const result = extractGraphQlRequestMetadata(\n        { method: 'POST', url: '/graphql', requestBody: 'not valid json' },\n        true\n      )\n      expect(result).toBeUndefined()\n    })\n\n    it('should return metadata with undefined fields for non-GraphQL POST request body', () => {\n      const requestBody = JSON.stringify({ data: 'some data' })\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: undefined,\n        variables: undefined,\n        payload: undefined,\n      })\n    })\n\n    it('should handle GraphQL queries with leading and trailing whitespace', () => {\n      const requestBody = JSON.stringify({\n        query: '  \\n  query GetUser { user { id name } }  \\n  ',\n        operationName: 'GetUser',\n        variables: { id: '123' },\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: 'query GetUser { user { id name } }',\n      })\n    })\n\n    it('should return undefined for queries with missing operation type', () => {\n      const requestBody = JSON.stringify({\n        query: '{ user { id name } }',\n        operationName: 'GetUser',\n        variables: { id: '123' },\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: '{ user { id name } }',\n      })\n    })\n\n    it('should return undefined for queries with invalid operation type', () => {\n      const requestBody = JSON.stringify({\n        query: 'invalid GetUser { user { id name } }',\n        operationName: 'GetUser',\n        variables: { id: '123' },\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: 'invalid GetUser { user { id name } }',\n      })\n    })\n\n    it('should extract operation name and variables when query is absent in POST body', () => {\n      const requestBody = JSON.stringify({\n        operationName: 'GetUser',\n        variables: { id: '123' },\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: undefined,\n      })\n    })\n\n    it('should extract metadata from URL query params for GET requests with persisted queries', () => {\n      const url =\n        'http://example.com/graphql?operationName=GetUser&variables=%7B%22id%22%3A%22123%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%22abc123%22%7D%7D'\n\n      const result = extractGraphQlRequestMetadata({ method: 'GET', url, requestBody: undefined }, false)\n\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: undefined,\n      })\n    })\n\n    it('should use body for POST and URL params for GET', () => {\n      const requestBody = JSON.stringify({\n        query: 'query FromBody { user { id } }',\n        operationName: 'FromBody',\n      })\n      const url = 'http://example.com/graphql?operationName=FromUrl'\n\n      const postResult = extractGraphQlRequestMetadata({ method: 'POST', url, requestBody }, true)\n      expect(postResult?.operationName).toBe('FromBody')\n\n      const getResult = extractGraphQlRequestMetadata({ method: 'GET', url, requestBody }, true)\n      expect(getResult?.operationName).toBe('FromUrl')\n    })\n\n    it('should return metadata with undefined fields for GET request with URL that has no GraphQL params', () => {\n      const result = extractGraphQlRequestMetadata(\n        { method: 'GET', url: 'http://example.com/graphql', requestBody: undefined },\n        false\n      )\n\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: undefined,\n        variables: undefined,\n        payload: undefined,\n      })\n    })\n\n    it('should return metadata with undefined fields for GET request with URL with unrelated query params', () => {\n      const result = extractGraphQlRequestMetadata(\n        { method: 'GET', url: 'http://example.com/graphql?foo=bar&baz=qux', requestBody: undefined },\n        false\n      )\n\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: undefined,\n        variables: undefined,\n        payload: undefined,\n      })\n    })\n\n    it('should extract query from URL params and detect operation type for GET requests', () => {\n      const url = 'http://example.com/graphql?query=query%20GetUser%20%7B%20user%20%7D&operationName=GetUser'\n\n      const result = extractGraphQlRequestMetadata({ method: 'GET', url, requestBody: undefined }, true)\n\n      expect(result).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: undefined,\n        payload: 'query GetUser { user }',\n      })\n    })\n\n    it('should omit variables for GET request when URL variables param is invalid JSON', () => {\n      const url = 'http://example.com/graphql?operationName=GetUser&variables=not-valid-json'\n\n      const result = extractGraphQlRequestMetadata({ method: 'GET', url, requestBody: undefined }, false)\n\n      expect(result).toEqual({\n        operationType: undefined,\n        operationName: 'GetUser',\n        variables: undefined,\n        payload: undefined,\n      })\n    })\n\n    it('should return undefined for unsupported HTTP methods', () => {\n      const requestBody = JSON.stringify({ query: 'query GetUser { user { id } }' })\n      const result = extractGraphQlRequestMetadata(\n        { method: 'PUT', url: 'http://example.com/graphql', requestBody },\n        true\n      )\n      expect(result).toBeUndefined()\n    })\n  })\n\n  describe('request payload truncation', () => {\n    it('should not truncate payload under 32KB', () => {\n      const shortQuery = 'query GetUser { user { id } }'\n      const requestBody = JSON.stringify({\n        query: shortQuery,\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result?.payload).toBe(shortQuery)\n    })\n\n    it('should truncate payload over 32KB', () => {\n      const longQuery = `query LongQuery { ${'a'.repeat(33000)} }`\n      const requestBody = JSON.stringify({\n        query: longQuery,\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, true)\n\n      expect(result?.payload?.length).toBe(32768 + 3)\n      expect(result?.payload?.endsWith('...')).toBe(true)\n      expect(result?.payload?.startsWith('query LongQuery {')).toBe(true)\n    })\n\n    it('should not include payload when trackPayload is false', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id name } }',\n        operationName: 'GetUser',\n        variables: { id: '123' },\n      })\n\n      const result = extractGraphQlRequestMetadata({ method: 'POST', url: '/graphql', requestBody }, false)\n\n      expect(result).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: undefined,\n      })\n    })\n  })\n\n  describe('parseGraphQlResponse', () => {\n    it('should extract detailed errors from GraphQL response', () => {\n      const responseText = JSON.stringify({\n        data: null,\n        errors: [{ message: 'Field not found' }, { message: 'Unauthorized' }],\n      })\n\n      const result = parseGraphQlResponse(responseText)\n\n      expect(result).toEqual([\n        { message: 'Field not found', path: undefined, locations: undefined, code: undefined },\n        { message: 'Unauthorized', path: undefined, locations: undefined, code: undefined },\n      ])\n    })\n\n    it('should extract detailed errors with extensions, locations and path', () => {\n      const responseText = JSON.stringify({\n        data: null,\n        errors: [\n          {\n            message: 'Field not found',\n            extensions: { code: 'FIELD_NOT_FOUND' },\n            locations: [{ line: 2, column: 5 }],\n            path: ['user', 'profile'],\n          },\n        ],\n      })\n\n      const result = parseGraphQlResponse(responseText)\n\n      expect(result).toEqual([\n        {\n          message: 'Field not found',\n          code: 'FIELD_NOT_FOUND',\n          locations: [{ line: 2, column: 5 }],\n          path: ['user', 'profile'],\n        },\n      ])\n    })\n\n    it('should handle response without errors', () => {\n      const responseText = JSON.stringify({\n        data: { user: { name: 'John' } },\n      })\n\n      const result = parseGraphQlResponse(responseText)\n\n      expect(result).toBeUndefined()\n    })\n\n    it('should handle invalid JSON', () => {\n      const result = parseGraphQlResponse('not valid json')\n\n      expect(result).toBeUndefined()\n    })\n\n    it('should handle errors with missing extensions', () => {\n      const responseText = JSON.stringify({\n        errors: [{ message: 'Simple error' }],\n      })\n\n      const result = parseGraphQlResponse(responseText)\n\n      expect(result).toEqual([{ message: 'Simple error', path: undefined, locations: undefined, code: undefined }])\n    })\n  })\n\n  describe('extractGraphQlMetadata', () => {\n    it('should extract request metadata and response errors from RequestCompleteEvent', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id } }',\n      })\n\n      const request: RequestCompleteEvent = {\n        method: 'POST',\n        url: '/graphql',\n        requestBody,\n        responseBody: JSON.stringify({\n          errors: [{ message: 'Not found' }],\n        }),\n      } as RequestCompleteEvent\n\n      const result = extractGraphQlMetadata(request, {\n        match: '/graphql',\n        trackPayload: false,\n        trackResponseErrors: true,\n      })\n\n      expect(result?.operationType).toBe('query')\n      expect(result?.error_count).toBe(1)\n      expect(result?.errors).toEqual([{ message: 'Not found', path: undefined, locations: undefined, code: undefined }])\n    })\n\n    it('should extract request metadata without response errors when not provided', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id } }',\n      })\n\n      const request: RequestCompleteEvent = {\n        method: 'POST',\n        url: '/graphql',\n        requestBody,\n      } as RequestCompleteEvent\n\n      const result = extractGraphQlMetadata(request, {\n        match: '/graphql',\n        trackPayload: false,\n        trackResponseErrors: true,\n      })\n\n      expect(result?.operationType).toBe('query')\n      expect(result?.error_count).toBeUndefined()\n      expect(result?.errors).toBeUndefined()\n    })\n\n    it('should handle multiple errors from RequestCompleteEvent', () => {\n      const requestBody = JSON.stringify({\n        query: 'query GetUser { user { id } }',\n      })\n\n      const request: RequestCompleteEvent = {\n        method: 'POST',\n        url: '/graphql',\n        requestBody,\n        responseBody: JSON.stringify({\n          errors: [{ message: 'Error 1' }, { message: 'Error 2' }],\n        }),\n      } as RequestCompleteEvent\n\n      const result = extractGraphQlMetadata(request, {\n        match: '/graphql',\n        trackPayload: false,\n        trackResponseErrors: true,\n      })\n\n      expect(result?.operationType).toBe('query')\n      expect(result?.error_count).toBe(2)\n      expect(result?.errors).toEqual([\n        { message: 'Error 1', path: undefined, locations: undefined, code: undefined },\n        { message: 'Error 2', path: undefined, locations: undefined, code: undefined },\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/graphql.ts",
    "content": "import { buildUrl, isNonEmptyArray, matchList, ONE_KIBI_BYTE, safeTruncate, tryJsonParse } from '@datadog/browser-core'\nimport type { RumConfiguration, GraphQlUrlOption } from '../configuration'\nimport type { RequestCompleteEvent } from '../requestCollection'\n\n/**\n * arbitrary value, byte precision not needed\n */\nconst GRAPHQL_PAYLOAD_LIMIT = 32 * ONE_KIBI_BYTE\n\ninterface RawGraphQlMetadata {\n  query?: string\n  operationName?: string\n  variables?: string\n}\n\nexport interface GraphQlError {\n  message: string\n  code?: string\n  locations?: Array<{ line: number; column: number }>\n  path?: Array<string | number>\n}\n\nexport interface GraphQlMetadata {\n  operationType?: 'query' | 'mutation' | 'subscription'\n  operationName?: string\n  variables?: string\n  payload?: string\n  error_count?: number\n  errors?: GraphQlError[]\n}\n\nexport function extractGraphQlMetadata(\n  request: RequestCompleteEvent,\n  graphQlConfig: GraphQlUrlOption\n): GraphQlMetadata | undefined {\n  const metadata = extractGraphQlRequestMetadata(request, graphQlConfig.trackPayload)\n  if (!metadata) {\n    return\n  }\n\n  if (graphQlConfig.trackResponseErrors && request.responseBody) {\n    const responseErrors = parseGraphQlResponse(request.responseBody)\n    if (responseErrors) {\n      metadata.error_count = responseErrors.length\n      metadata.errors = responseErrors\n    }\n  }\n\n  return metadata\n}\n\nexport function parseGraphQlResponse(responseText: string): GraphQlError[] | undefined {\n  const response = tryJsonParse(responseText)\n\n  if (!response || typeof response !== 'object') {\n    return\n  }\n\n  const responseObj = response as Record<string, unknown>\n\n  if (!isNonEmptyArray(responseObj.errors)) {\n    return\n  }\n\n  const errors = (responseObj.errors as Array<Record<string, unknown>>).map((error) => {\n    const graphqlError: GraphQlError = {\n      message: error.message as string,\n      path: error.path as Array<string | number>,\n      locations: error.locations as Array<{ line: number; column: number }>,\n      code: (error.extensions as Record<string, unknown> | undefined)?.code as string,\n    }\n\n    return graphqlError\n  })\n\n  return errors\n}\n\nexport function findGraphQlConfiguration(url: string, configuration: RumConfiguration): GraphQlUrlOption | undefined {\n  return configuration.allowedGraphQlUrls.find((graphQlOption) => matchList([graphQlOption.match], url))\n}\n\nexport function extractGraphQlRequestMetadata(\n  request: Pick<RequestCompleteEvent, 'method' | 'url' | 'requestBody'>,\n  trackPayload: boolean = false\n): GraphQlMetadata | undefined {\n  let rawMetadata: RawGraphQlMetadata | undefined\n\n  if (request.method === 'POST') {\n    rawMetadata = extractFromBody(request.requestBody)\n  } else if (request.method === 'GET') {\n    rawMetadata = extractFromUrlQueryParams(request.url)\n  }\n\n  if (!rawMetadata) {\n    return\n  }\n\n  return sanitizeGraphQlMetadata(rawMetadata, trackPayload)\n}\n\nfunction extractFromBody(requestBody: unknown): RawGraphQlMetadata | undefined {\n  if (!requestBody || typeof requestBody !== 'string') {\n    return\n  }\n\n  const graphqlBody = tryJsonParse<{\n    query?: string\n    operationName?: string\n    variables?: unknown\n  }>(requestBody)\n\n  if (!graphqlBody) {\n    return\n  }\n\n  return {\n    query: graphqlBody.query,\n    operationName: graphqlBody.operationName,\n    variables: graphqlBody.variables ? JSON.stringify(graphqlBody.variables) : undefined,\n  }\n}\n\nfunction extractFromUrlQueryParams(url: string): RawGraphQlMetadata {\n  const searchParams = buildUrl(url).searchParams\n  const variablesParam = searchParams.get('variables')\n  const variables = variablesParam && tryJsonParse(variablesParam) !== undefined ? variablesParam : undefined\n\n  return {\n    query: searchParams.get('query') || undefined,\n    operationName: searchParams.get('operationName') || undefined,\n    variables,\n  }\n}\n\nfunction sanitizeGraphQlMetadata(rawMetadata: RawGraphQlMetadata, trackPayload: boolean): GraphQlMetadata {\n  let operationType: 'query' | 'mutation' | 'subscription' | undefined\n  let payload: string | undefined\n  let variables: string | undefined\n\n  if (rawMetadata.query) {\n    const trimmedQuery = rawMetadata.query.trim()\n    operationType = getOperationType(trimmedQuery)\n    if (trackPayload) {\n      payload = safeTruncate(trimmedQuery, GRAPHQL_PAYLOAD_LIMIT, '...')\n    }\n  }\n\n  if (rawMetadata.variables) {\n    variables = rawMetadata.variables\n  }\n\n  return {\n    operationType,\n    operationName: rawMetadata.operationName,\n    variables,\n    payload,\n  }\n}\n\nfunction getOperationType(query: string) {\n  return query.match(/^\\s*(query|mutation|subscription)\\b/i)?.[1] as 'query' | 'mutation' | 'subscription' | undefined\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/matchRequestResourceEntry.spec.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { relativeToClocks } from '@datadog/browser-core'\nimport type { GlobalPerformanceBufferMock } from '../../../test'\nimport { createPerformanceEntry, mockGlobalPerformanceBuffer } from '../../../test'\nimport type { RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport type { RequestCompleteEvent } from '../requestCollection'\n\nimport { matchRequestResourceEntry } from './matchRequestResourceEntry'\n\ndescribe('matchRequestResourceEntry', () => {\n  const FAKE_URL = 'https://example.com'\n  const FAKE_REQUEST: Partial<RequestCompleteEvent> = {\n    url: FAKE_URL,\n    startClocks: relativeToClocks(100 as RelativeTime),\n    duration: 500 as Duration,\n  }\n  let globalPerformanceObjectMock: GlobalPerformanceBufferMock\n\n  beforeEach(() => {\n    globalPerformanceObjectMock = mockGlobalPerformanceBuffer()\n  })\n\n  it('should match single entry nested in the request ', () => {\n    const entry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 200 as RelativeTime,\n      duration: 300 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(entry.toJSON() as RumPerformanceResourceTiming)\n  })\n\n  it('should match single entry nested in the request with error margin', () => {\n    const entry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 99 as RelativeTime,\n      duration: 502 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(entry.toJSON() as RumPerformanceResourceTiming)\n  })\n\n  it('should not match single entry outside the request ', () => {\n    const entry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 0 as RelativeTime,\n      duration: 300 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(undefined)\n  })\n\n  it('should discard already matched entries when multiple identical requests are done conurently', () => {\n    const entry1 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 200 as RelativeTime,\n      duration: 300 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry1)\n\n    const matchingEntry1 = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry1).toEqual(entry1.toJSON() as RumPerformanceResourceTiming)\n\n    const entry2 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 99 as RelativeTime,\n      duration: 502 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry2)\n\n    const matchingEntry2 = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry2).toEqual(entry2.toJSON() as RumPerformanceResourceTiming)\n  })\n\n  it('should not match two not following entries nested in the request ', () => {\n    const entry1 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 150 as RelativeTime,\n      duration: 100 as Duration,\n    })\n    const entry2 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 200 as RelativeTime,\n      duration: 100 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry1)\n    globalPerformanceObjectMock.addPerformanceEntry(entry2)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(undefined)\n  })\n\n  it('should not match multiple entries nested in the request', () => {\n    const entry1 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 100 as RelativeTime,\n      duration: 50 as Duration,\n    })\n    const entry2 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 150 as RelativeTime,\n      duration: 50 as Duration,\n    })\n    const entry3 = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      startTime: 200 as RelativeTime,\n      duration: 50 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry1)\n    globalPerformanceObjectMock.addPerformanceEntry(entry2)\n    globalPerformanceObjectMock.addPerformanceEntry(entry3)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(undefined)\n  })\n\n  it('should not match entry with invalid duration', () => {\n    const entry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      duration: -1 as Duration,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(undefined)\n  })\n\n  it('should not match invalid entry nested in the request ', () => {\n    const entry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      name: FAKE_URL,\n      // fetchStart < startTime is invalid\n      fetchStart: 0 as RelativeTime,\n      workerStart: 0 as RelativeTime,\n      startTime: 200 as RelativeTime,\n    })\n    globalPerformanceObjectMock.addPerformanceEntry(entry)\n\n    const matchingEntry = matchRequestResourceEntry(FAKE_REQUEST as RequestCompleteEvent)\n\n    expect(matchingEntry).toEqual(undefined)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/matchRequestResourceEntry.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { addDuration } from '@datadog/browser-core'\nimport type { RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport type { RequestCompleteEvent } from '../requestCollection'\nimport { hasValidResourceEntryDuration, hasValidResourceEntryTimings } from './resourceUtils'\n\ninterface Timing {\n  startTime: RelativeTime\n  duration: Duration\n}\n\nconst alreadyMatchedEntries = new WeakSet<PerformanceEntry>()\n\n/**\n * Look for corresponding timing in resource timing buffer\n *\n * Observations:\n * - Timing (start, end) are nested inside the request (start, end)\n * - Some timing can be not exactly nested, being off by < 1 ms\n *\n * Strategy:\n * - from valid nested entries (with 1 ms error margin)\n * - filter out timing that were already matched to a request\n * - then, if a single timing match, return the timing\n * - otherwise we can't decide, return undefined\n */\nexport function matchRequestResourceEntry(request: RequestCompleteEvent) {\n  if (!performance || !('getEntriesByName' in performance)) {\n    return\n  }\n  const sameNameEntries = performance.getEntriesByName(request.url, 'resource') as RumPerformanceResourceTiming[]\n\n  if (!sameNameEntries.length || !('toJSON' in sameNameEntries[0])) {\n    return\n  }\n\n  const candidates = sameNameEntries\n    .filter((entry) => !alreadyMatchedEntries.has(entry))\n    .filter((entry) => hasValidResourceEntryDuration(entry) && hasValidResourceEntryTimings(entry))\n    .filter((entry) =>\n      isBetween(\n        entry,\n        request.startClocks.relative,\n        endTime({ startTime: request.startClocks.relative, duration: request.duration })\n      )\n    )\n\n  if (candidates.length === 1) {\n    alreadyMatchedEntries.add(candidates[0])\n\n    return candidates[0].toJSON() as RumPerformanceResourceTiming\n  }\n\n  return\n}\n\nfunction endTime(timing: Timing) {\n  return addDuration(timing.startTime, timing.duration)\n}\n\nfunction isBetween(timing: Timing, start: RelativeTime, end: RelativeTime) {\n  const errorMargin = 1 as Duration\n  return timing.startTime >= start - errorMargin && endTime(timing) <= addDuration(end, errorMargin)\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/requestRegistry.spec.ts",
    "content": "import type { Duration, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { addExperimentalFeatures, ExperimentalFeature, RequestType } from '@datadog/browser-core'\nimport type { Clock, MockTelemetry } from '@datadog/browser-core/test'\nimport { mockClock, startMockTelemetry } from '@datadog/browser-core/test'\nimport { createPerformanceEntry } from '../../../test'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { RequestCompleteEvent } from '../requestCollection'\nimport { createRequestRegistry, MAX_REQUESTS } from './requestRegistry'\n\ndescribe('RequestRegistry', () => {\n  const URL = 'https://example.com/resource'\n  it('returns the closest preceding request', () => {\n    const lifeCycle = new LifeCycle()\n\n    const requestRegistry = createRequestRegistry(lifeCycle)\n    const request1 = createRequestCompleteEvent({ startTime: 1 })\n    const request2 = createRequestCompleteEvent({ startTime: 2 })\n    const request3 = createRequestCompleteEvent({ startTime: 3 })\n    const request4 = createRequestCompleteEvent({ startTime: 100 })\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request1)\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request2)\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request3)\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request4)\n\n    expect(requestRegistry.getMatchingRequest(createResourceEntry({ startTime: 99 }))).toBe(request3)\n  })\n\n  it('ignores requests that have a different URL', () => {\n    const lifeCycle = new LifeCycle()\n\n    const requestRegistry = createRequestRegistry(lifeCycle)\n\n    const request1 = createRequestCompleteEvent({ startTime: 1, url: URL })\n    const request2 = createRequestCompleteEvent({ startTime: 2, url: 'https://another-url.com/resource' })\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request1)\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request2)\n\n    expect(requestRegistry.getMatchingRequest(createResourceEntry({ startTime: 3 }))).toBe(request1)\n  })\n\n  it('does not return the same request twice', () => {\n    const lifeCycle = new LifeCycle()\n\n    const requestRegistry = createRequestRegistry(lifeCycle)\n\n    const request1 = createRequestCompleteEvent({ startTime: 1 })\n    const request2 = createRequestCompleteEvent({ startTime: 2 })\n\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request1)\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, request2)\n\n    expect(requestRegistry.getMatchingRequest(createResourceEntry({ startTime: 2 }))).toBe(request2)\n    expect(requestRegistry.getMatchingRequest(createResourceEntry({ startTime: 2 }))).toBe(request1)\n    expect(requestRegistry.getMatchingRequest(createResourceEntry({ startTime: 2 }))).toBeUndefined()\n  })\n\n  it('is limited to a maximum number of requests', () => {\n    const lifeCycle = new LifeCycle()\n    const requestRegistry = createRequestRegistry(lifeCycle)\n    for (let i = 0; i < MAX_REQUESTS + 1; i++) {\n      lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, createRequestCompleteEvent({ startTime: i }))\n    }\n    expect(requestRegistry.getMatchingRequest(createResourceEntry({ startTime: 0 }))).toBeUndefined()\n  })\n\n  describe('when the registry overflows', () => {\n    let telemetry: MockTelemetry\n    let lifeCycle: LifeCycle\n\n    beforeEach(() => {\n      telemetry = startMockTelemetry()\n      lifeCycle = new LifeCycle()\n      createRequestRegistry(lifeCycle)\n    })\n\n    it('fires \"Too many requests\" telemetry only once', async () => {\n      for (let i = 0; i < MAX_REQUESTS + 3; i++) {\n        lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, createRequestCompleteEvent({ startTime: i }))\n      }\n      expect(await telemetry.getEvents()).toEqual([jasmine.objectContaining({ message: 'Too many requests' })])\n    })\n\n    it('includes debug context when TOO_MANY_REQUESTS_INVESTIGATION is enabled', async () => {\n      const clock: Clock = mockClock()\n      addExperimentalFeatures([ExperimentalFeature.TOO_MANY_REQUESTS_INVESTIGATION])\n      let fetchCount = 0\n      let xhrCount = 0\n      let abortedCount = 0\n      let abortedOnStartCount = 0\n\n      // oldest request: created at t=0, FETCH, takes 50ms\n      lifeCycle.notify(\n        LifeCycleEventType.REQUEST_COMPLETED,\n        createRequestCompleteEvent({ startTime: 0, timeStamp: clock.timeStamp(0), duration: 50 as Duration })\n      )\n      fetchCount++\n\n      clock.tick(1000)\n\n      // 1 XHR request\n      lifeCycle.notify(\n        LifeCycleEventType.REQUEST_COMPLETED,\n        createRequestCompleteEvent({ startTime: MAX_REQUESTS - 1, type: RequestType.XHR })\n      )\n      xhrCount++\n\n      // aborted\n      lifeCycle.notify(\n        LifeCycleEventType.REQUEST_COMPLETED,\n        createRequestCompleteEvent({ startTime: MAX_REQUESTS, isAborted: true })\n      )\n      fetchCount++\n      abortedCount++\n\n      // aborted on start\n      lifeCycle.notify(\n        LifeCycleEventType.REQUEST_COMPLETED,\n        createRequestCompleteEvent({ startTime: MAX_REQUESTS, isAborted: true, isAbortedOnStart: true })\n      )\n      fetchCount++\n      abortedCount++\n      abortedOnStartCount++\n\n      // trigger requests until we reach the limit\n      while (fetchCount + xhrCount <= MAX_REQUESTS) {\n        lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, createRequestCompleteEvent({ startTime: 10 }))\n        fetchCount++\n      }\n\n      expect(await telemetry.getEvents()).toEqual([\n        jasmine.objectContaining({\n          message: 'Too many requests',\n          abortedCount,\n          abortedOnStartCount,\n          xhrCount,\n          fetchCount,\n          oldestRequestAge: 1000,\n          oldestRequestEndAge: 950,\n          withoutMatchingEntryCount: MAX_REQUESTS + 1,\n        }),\n      ])\n    })\n  })\n\n  function createRequestCompleteEvent({\n    startTime,\n    url = URL,\n    timeStamp,\n    duration = 0 as Duration,\n    type = RequestType.FETCH,\n    isAborted = false,\n    isAbortedOnStart = false,\n  }: {\n    startTime: number\n    url?: string\n    timeStamp?: TimeStamp\n    duration?: Duration\n    type?: RequestType\n    isAborted?: boolean\n    isAbortedOnStart?: boolean\n  }): RequestCompleteEvent {\n    return {\n      startClocks: { relative: startTime as RelativeTime, timeStamp },\n      url,\n      duration,\n      type,\n      isAborted,\n      isAbortedOnStart,\n    } as RequestCompleteEvent\n  }\n\n  function createResourceEntry({ startTime }: { startTime: number }) {\n    return createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      startTime: startTime as RelativeTime,\n      name: URL,\n    })\n  }\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/requestRegistry.ts",
    "content": "import type { Context } from '@datadog/browser-core'\nimport {\n  addTelemetryDebug,\n  ExperimentalFeature,\n  isExperimentalFeatureEnabled,\n  RequestType,\n  timeStampNow,\n} from '@datadog/browser-core'\nimport type { RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { RequestCompleteEvent } from '../requestCollection'\n\nexport interface RequestRegistry {\n  getMatchingRequest(entry: RumPerformanceResourceTiming): RequestCompleteEvent | undefined\n  stop(): void\n}\n\n// Maximum number of requests to keep in the registry. Requests should be removed quite quickly in\n// general, this is just a safety limit to avoid memory leaks in case of a bug.\nexport const MAX_REQUESTS = 1000\n\nexport function createRequestRegistry(lifeCycle: LifeCycle): RequestRegistry {\n  const requests = new Set<RequestCompleteEvent>()\n  let tooManyRequestsReported = false\n\n  const subscription = lifeCycle.subscribe(LifeCycleEventType.REQUEST_COMPLETED, (request) => {\n    requests.add(request)\n\n    if (requests.size > MAX_REQUESTS) {\n      const oldestRequest = requests.values().next().value!\n\n      if (!tooManyRequestsReported) {\n        tooManyRequestsReported = true\n\n        let debugContext: Context | undefined\n\n        if (isExperimentalFeatureEnabled(ExperimentalFeature.TOO_MANY_REQUESTS_INVESTIGATION)) {\n          let abortedCount = 0\n          let abortedOnStartCount = 0\n          let xhrCount = 0\n          let withoutMatchingEntryCount = 0\n          for (const r of requests) {\n            if (r.isAborted) {\n              abortedCount++\n            }\n            if (r.isAbortedOnStart) {\n              abortedOnStartCount++\n            }\n            if (r.type === RequestType.XHR) {\n              xhrCount++\n            }\n            const entries = performance.getEntriesByName(r.url, 'resource') as PerformanceResourceTiming[]\n            const hasMatchingEntry = entries.some((e) => e.startTime >= r.startClocks.relative)\n            if (!hasMatchingEntry) {\n              withoutMatchingEntryCount++\n            }\n          }\n          const oldestRequestAge = timeStampNow() - oldestRequest.startClocks.timeStamp\n          debugContext = {\n            abortedCount,\n            abortedOnStartCount,\n            xhrCount,\n            fetchCount: requests.size - xhrCount,\n            oldestRequestAge,\n            oldestRequestEndAge: oldestRequestAge - oldestRequest.duration,\n            withoutMatchingEntryCount,\n          }\n        }\n\n        // monitor-until: 2026-06-01, after early request collection is the default in v7\n        addTelemetryDebug('Too many requests', debugContext)\n      }\n\n      requests.delete(oldestRequest)\n    }\n  })\n\n  return {\n    getMatchingRequest(entry) {\n      // Returns the closest request object that happened before the entry\n      let minTimeDifference = Infinity\n      let closestRequest: RequestCompleteEvent | undefined\n      for (const request of requests) {\n        const timeDifference = entry.startTime - request.startClocks.relative\n        if (0 <= timeDifference && timeDifference < minTimeDifference && request.url === entry.name) {\n          minTimeDifference = Math.abs(timeDifference)\n          closestRequest = request\n        }\n      }\n\n      if (closestRequest) {\n        requests.delete(closestRequest)\n      }\n\n      return closestRequest\n    },\n\n    stop() {\n      subscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/resourceCollection.spec.ts",
    "content": "import type { Duration, RelativeTime, ServerDuration, TaskQueue, TimeStamp, MatchOption } from '@datadog/browser-core'\nimport {\n  createTaskQueue,\n  noop,\n  RequestType,\n  ResourceType,\n  addExperimentalFeatures,\n  ExperimentalFeature,\n  display,\n} from '@datadog/browser-core'\nimport type { MockTelemetry } from '@datadog/browser-core/test'\nimport { replaceMockable, registerCleanupTask, startMockTelemetry } from '@datadog/browser-core/test'\nimport { resetExperimentalFeatures } from '@datadog/browser-core/src/tools/experimentalFeatures'\nimport type { RumFetchResourceEventDomainContext, RumXhrResourceEventDomainContext } from '../../domainContext.types'\nimport {\n  collectAndValidateRawRumEvents,\n  createPerformanceEntry,\n  mockPageStateHistory,\n  mockPerformanceObserver,\n  mockRumConfiguration,\n} from '../../../test'\nimport type { RawRumEvent, RawRumResourceEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { RequestCompleteEvent } from '../requestCollection'\nimport type { RumConfiguration, MatchHeader } from '../configuration'\nimport { validateAndBuildRumConfiguration } from '../configuration'\nimport type { RumPerformanceEntry, RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport { createSpanIdentifier, createTraceIdentifier } from '../tracing/identifier'\nimport { startResourceCollection } from './resourceCollection'\nimport { retrieveInitialDocumentResourceTiming } from './retrieveInitialDocumentResourceTiming'\n\nfunction buildMatchHeadersForAllUrls(headerNames: MatchOption[]): MatchHeader[] {\n  return headerNames.map((name) => ({ name }))\n}\n\nconst HANDLING_STACK_REGEX = /^Error: \\n\\s+at <anonymous> @/\nconst baseConfiguration = mockRumConfiguration()\nconst pageStateHistory = mockPageStateHistory()\n\ndescribe('resourceCollection', () => {\n  let lifeCycle: LifeCycle\n  let wasInPageStateDuringPeriodSpy: jasmine.Spy<jasmine.Func>\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>> = []\n  let taskQueuePushSpy: jasmine.Spy<TaskQueue['push']>\n\n  function setupResourceCollection(partialConfig: Partial<RumConfiguration> = { trackResources: true }) {\n    replaceMockable(retrieveInitialDocumentResourceTiming, noop)\n    lifeCycle = new LifeCycle()\n    const taskQueue = createTaskQueue()\n    replaceMockable(createTaskQueue, () => taskQueue)\n    taskQueuePushSpy = spyOn(taskQueue, 'push')\n    const startResult = startResourceCollection(lifeCycle, { ...baseConfiguration, ...partialConfig }, pageStateHistory)\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n\n    registerCleanupTask(() => {\n      startResult.stop()\n    })\n  }\n\n  beforeEach(() => {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n    wasInPageStateDuringPeriodSpy = spyOn(pageStateHistory, 'wasInPageStateDuringPeriod')\n  })\n\n  it('should create resource from performance entry', () => {\n    setupResourceCollection()\n\n    const performanceEntry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n      encodedBodySize: 42,\n      decodedBodySize: 51,\n      transferSize: 63,\n      renderBlockingStatus: 'blocking',\n      deliveryType: 'cache',\n      responseStart: 250 as RelativeTime,\n    })\n    notifyPerformanceEntries([performanceEntry])\n    runTasks()\n\n    expect(rawRumEvents[0].startClocks.relative).toBe(200 as RelativeTime)\n    expect(rawRumEvents[0].rawRumEvent).toEqual({\n      date: jasmine.any(Number) as unknown as TimeStamp,\n      resource: {\n        id: jasmine.any(String),\n        duration: (100 * 1e6) as ServerDuration,\n        size: 51,\n        encoded_body_size: 42,\n        decoded_body_size: 51,\n        transfer_size: 63,\n        type: ResourceType.IMAGE,\n        url: 'https://resource.com/valid',\n        download: jasmine.any(Object),\n        first_byte: jasmine.any(Object),\n        status_code: 200,\n        protocol: 'HTTP/1.0',\n        delivery_type: 'cache',\n        render_blocking_status: 'blocking',\n        method: undefined,\n        graphql: undefined,\n      },\n      type: RumEventType.RESOURCE,\n      _dd: {\n        discarded: false,\n      },\n    })\n    expect(rawRumEvents[0].domainContext).toEqual({\n      performanceEntry,\n    })\n  })\n\n  it('should create resource from completed XHR request', () => {\n    setupResourceCollection()\n    const xhr = new XMLHttpRequest()\n    notifyRequest({\n      request: {\n        duration: 100 as Duration,\n        method: 'GET',\n        startClocks: { relative: 200 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n        status: 200,\n        type: RequestType.XHR,\n        url: 'https://resource.com/valid',\n        xhr,\n        isAborted: false,\n      },\n    })\n\n    expect(rawRumEvents[0].startClocks.relative).toBe(200 as RelativeTime)\n    expect(rawRumEvents[0].rawRumEvent).toEqual({\n      date: jasmine.any(Number),\n      resource: {\n        id: jasmine.any(String),\n        duration: (100 * 1e6) as ServerDuration,\n        method: 'GET',\n        status_code: 200,\n        delivery_type: 'cache',\n        protocol: 'HTTP/1.0',\n        type: ResourceType.XHR,\n        url: 'https://resource.com/valid',\n        render_blocking_status: 'non-blocking',\n        size: undefined,\n        encoded_body_size: undefined,\n        decoded_body_size: undefined,\n        transfer_size: undefined,\n        download: { duration: 100000000 as ServerDuration, start: 0 as ServerDuration },\n        first_byte: { duration: 0 as ServerDuration, start: 0 as ServerDuration },\n        graphql: undefined,\n      },\n      type: RumEventType.RESOURCE,\n      _dd: {\n        discarded: false,\n      },\n    })\n    expect(rawRumEvents[0].domainContext).toEqual({\n      xhr,\n      performanceEntry: jasmine.any(Object),\n      isAborted: false,\n      handlingStack: jasmine.stringMatching(HANDLING_STACK_REGEX),\n    })\n  })\n\n  describe('GraphQL metadata enrichment', () => {\n    interface TestCase {\n      requestType: RequestType\n      name: string\n    }\n\n    const testCases: TestCase[] = [\n      { requestType: RequestType.FETCH, name: 'FETCH' },\n      { requestType: RequestType.XHR, name: 'XHR' },\n    ]\n\n    testCases.forEach(({ requestType, name }) => {\n      describe(`for ${name} requests`, () => {\n        function createRequest(requestType: RequestType, url: string, requestBody: string) {\n          const baseRequest = {\n            type: requestType,\n            url,\n            method: 'POST' as const,\n          }\n\n          if (requestType === RequestType.FETCH) {\n            return {\n              ...baseRequest,\n              init: {\n                method: 'POST' as const,\n                body: requestBody,\n              },\n              input: url,\n              requestBody,\n            }\n          }\n          {\n            // XHR\n            return {\n              ...baseRequest,\n              requestBody,\n              status: 200,\n              duration: 100 as Duration,\n              startClocks: { relative: 200 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n              isAborted: false,\n            }\n          }\n        }\n\n        it('should enrich resource with GraphQL metadata when the URL matches allowedGraphQlUrls', () => {\n          setupResourceCollection({\n            trackResources: true,\n            allowedGraphQlUrls: [{ match: 'https://api.example.com/graphql', trackPayload: true }],\n          })\n\n          const requestBody = JSON.stringify({\n            query: 'query GetUser($id: ID!) { user(id: $id) { name email } }',\n            operationName: 'GetUser',\n            variables: { id: '123' },\n          })\n\n          notifyRequest({\n            request: createRequest(requestType, 'https://api.example.com/graphql', requestBody),\n          })\n\n          expect(rawRumEvents[0].rawRumEvent).toEqual(\n            jasmine.objectContaining({\n              resource: jasmine.objectContaining({\n                graphql: {\n                  operationType: 'query',\n                  operationName: 'GetUser',\n                  variables: '{\"id\":\"123\"}',\n                  payload: 'query GetUser($id: ID!) { user(id: $id) { name email } }',\n                },\n              }),\n            })\n          )\n        })\n\n        it('should not enrich resource with GraphQL metadata when URL does not match', () => {\n          setupResourceCollection({\n            trackResources: true,\n            allowedGraphQlUrls: [{ match: '/graphql', trackPayload: false }],\n          })\n\n          const requestBody = JSON.stringify({\n            query: 'query GetUser { user { name } }',\n          })\n\n          notifyRequest({\n            request: createRequest(requestType, 'https://api.example.com/api/rest', requestBody),\n          })\n\n          const resourceEvent = rawRumEvents[0].rawRumEvent as any\n          expect(resourceEvent.resource.graphql).toBeUndefined()\n        })\n\n        it('should not include payload when trackPayload is false', () => {\n          setupResourceCollection({\n            trackResources: true,\n            allowedGraphQlUrls: [{ match: 'https://api.example.com/graphql', trackPayload: false }],\n          })\n\n          const requestBody = JSON.stringify({\n            query: 'mutation CreateUser { createUser { id } }',\n            operationName: 'CreateUser',\n            variables: { name: 'John' },\n          })\n\n          notifyRequest({\n            request: createRequest(requestType, 'https://api.example.com/graphql', requestBody),\n          })\n\n          expect(rawRumEvents[0].rawRumEvent).toEqual(\n            jasmine.objectContaining({\n              resource: jasmine.objectContaining({\n                graphql: {\n                  operationType: 'mutation',\n                  operationName: 'CreateUser',\n                  variables: '{\"name\":\"John\"}',\n                  payload: undefined,\n                },\n              }),\n            })\n          )\n        })\n      })\n    })\n  })\n\n  describe('HTTP response metadata enrichment', () => {\n    it('should extract content-type from performance entry when available', () => {\n      setupResourceCollection()\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n          contentType: 'image/png',\n        }),\n      ])\n      runTasks()\n\n      expect(rawRumEvents[0].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          resource: jasmine.objectContaining({\n            response: {\n              headers: {\n                'content-type': 'image/png',\n              },\n            },\n          }),\n        })\n      )\n    })\n\n    it('should not include response when no content-type is available', () => {\n      setupResourceCollection()\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {})])\n      runTasks()\n\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.response).toBeUndefined()\n    })\n  })\n\n  describe('with trackEarlyRequests enabled', () => {\n    it('creates a resource from a performance entry without a matching request', () => {\n      setupResourceCollection({ trackResources: true, trackEarlyRequests: true })\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n          initiatorType: RequestType.FETCH,\n        }),\n      ])\n      runTasks()\n\n      expect(rawRumEvents.length).toBe(1)\n      expect(rawRumEvents[0].startClocks.relative).toBe(200 as RelativeTime)\n      expect(rawRumEvents[0].rawRumEvent).toEqual({\n        date: jasmine.any(Number),\n        resource: {\n          id: jasmine.any(String),\n          duration: (100 * 1e6) as ServerDuration,\n          method: undefined,\n          status_code: 200,\n          delivery_type: 'cache',\n          protocol: 'HTTP/1.0',\n          type: ResourceType.FETCH,\n          url: 'https://resource.com/valid',\n          render_blocking_status: 'non-blocking',\n          size: undefined,\n          encoded_body_size: undefined,\n          decoded_body_size: undefined,\n          transfer_size: undefined,\n          download: { duration: 100000000 as ServerDuration, start: 0 as ServerDuration },\n          first_byte: { duration: 0 as ServerDuration, start: 0 as ServerDuration },\n          graphql: undefined,\n        },\n        type: RumEventType.RESOURCE,\n        _dd: {\n          discarded: false,\n        },\n      })\n      expect(rawRumEvents[0].domainContext).toEqual({\n        performanceEntry: jasmine.any(Object),\n      })\n    })\n  })\n\n  describe('when trackResource is false', () => {\n    describe('and resource is not traced', () => {\n      it('should not collect a resource from a performance entry', () => {\n        setupResourceCollection({ trackResources: false })\n\n        notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE)])\n        runTasks()\n\n        expect(rawRumEvents.length).toBe(0)\n      })\n\n      it('should not collect a resource from a completed XHR request', () => {\n        setupResourceCollection({ trackResources: false })\n        notifyRequest({\n          request: {\n            type: RequestType.XHR,\n          },\n        })\n\n        expect(rawRumEvents.length).toBe(0)\n      })\n    })\n\n    describe('and resource is traced', () => {\n      it('should collect a resource from a performance entry', () => {\n        setupResourceCollection({ trackResources: false })\n\n        notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { traceId: '1234' })])\n        runTasks()\n\n        expect(rawRumEvents.length).toBe(1)\n        expect((rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd.discarded).toBeTrue()\n      })\n\n      it('should collect a resource from a completed XHR request', () => {\n        setupResourceCollection({ trackResources: false })\n        notifyRequest({\n          request: {\n            type: RequestType.XHR,\n            traceId: createTraceIdentifier(),\n            spanId: createSpanIdentifier(),\n            traceSampled: true,\n          },\n        })\n\n        expect(rawRumEvents.length).toBe(1)\n        expect((rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd.discarded).toBeTrue()\n      })\n    })\n  })\n\n  it('should not have a duration if a frozen state happens during the request and no performance entry matches', () => {\n    setupResourceCollection()\n    wasInPageStateDuringPeriodSpy.and.returnValue(true)\n\n    notifyRequest({\n      // For now, this behavior only happens when there is no performance entry matching the request\n      notifyPerformanceEntry: false,\n    })\n\n    const rawRumResourceEventFetch = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n    expect(rawRumResourceEventFetch.resource.duration).toBeUndefined()\n  })\n\n  it('should create resource from completed fetch request', () => {\n    setupResourceCollection()\n    const response = new Response()\n    notifyRequest({\n      request: {\n        duration: 100 as Duration,\n        method: 'GET',\n        startClocks: { relative: 200 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n        status: 200,\n        type: RequestType.FETCH,\n        url: 'https://resource.com/valid',\n        response,\n        input: 'https://resource.com/valid',\n        init: { headers: { foo: 'bar' } },\n        isAborted: false,\n      },\n    })\n\n    expect(rawRumEvents[0].startClocks.relative).toBe(200 as RelativeTime)\n    expect(rawRumEvents[0].rawRumEvent).toEqual({\n      date: jasmine.any(Number),\n      resource: {\n        id: jasmine.any(String),\n        duration: (100 * 1e6) as ServerDuration,\n        method: 'GET',\n        status_code: 200,\n        delivery_type: 'cache',\n        protocol: 'HTTP/1.0',\n        type: ResourceType.FETCH,\n\n        render_blocking_status: 'non-blocking',\n        size: undefined,\n        encoded_body_size: undefined,\n        decoded_body_size: undefined,\n        transfer_size: undefined,\n        download: { duration: 100000000 as ServerDuration, start: 0 as ServerDuration },\n        first_byte: { duration: 0 as ServerDuration, start: 0 as ServerDuration },\n        url: 'https://resource.com/valid',\n        graphql: undefined,\n      },\n      type: RumEventType.RESOURCE,\n      _dd: {\n        discarded: false,\n      },\n    })\n    expect(rawRumEvents[0].domainContext).toEqual({\n      performanceEntry: jasmine.any(Object),\n      response,\n      requestInput: 'https://resource.com/valid',\n      requestInit: { headers: { foo: 'bar' } },\n      error: undefined,\n      isAborted: false,\n      handlingStack: jasmine.stringMatching(HANDLING_STACK_REGEX),\n    })\n  })\n  ;[null, undefined, 42, {}].forEach((input: any) => {\n    it(`should support ${\n      typeof input === 'object' ? JSON.stringify(input) : String(input)\n    } as fetch input parameter`, () => {\n      setupResourceCollection()\n      notifyRequest({\n        request: { type: RequestType.FETCH, input },\n      })\n\n      expect(rawRumEvents.length).toBe(1)\n      expect((rawRumEvents[0].domainContext as RumFetchResourceEventDomainContext).requestInput).toBe(input)\n    })\n  })\n\n  it('should include the error in failed fetch requests', () => {\n    setupResourceCollection()\n    const error = new Error()\n    notifyRequest({\n      request: { type: RequestType.FETCH, error },\n    })\n\n    expect(rawRumEvents[0].domainContext).toEqual(\n      jasmine.objectContaining({\n        error,\n      })\n    )\n  })\n\n  it('should discard 0 status code', () => {\n    setupResourceCollection()\n    const performanceEntry = createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { responseStatus: 0 })\n    notifyPerformanceEntries([performanceEntry])\n    runTasks()\n    expect((rawRumEvents[0].rawRumEvent as RawRumResourceEvent).resource.status_code).toBeUndefined()\n  })\n\n  describe('network headers', () => {\n    beforeEach(() => {\n      addExperimentalFeatures([ExperimentalFeature.TRACK_RESOURCE_HEADERS])\n    })\n\n    describe('Fetch', () => {\n      it('should extract matching response headers from Fetch', () => {\n        setupResourceCollection({\n          trackResourceHeaders: buildMatchHeadersForAllUrls(['content-type', 'cache-control']),\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', {\n              headers: { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'X-Other': 'ignored' },\n            }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response).toEqual({\n          headers: {\n            'content-type': 'text/html',\n            'cache-control': 'no-cache',\n          },\n        })\n      })\n\n      it('should extract matching request headers from Fetch', () => {\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['x-custom']) })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            init: { headers: { 'X-Custom': 'my-value', 'X-Other': 'ignored' } },\n            response: new Response(''),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.request).toEqual({\n          headers: { 'x-custom': 'my-value' },\n        })\n      })\n\n      it('should extract request headers from Fetch Request input', () => {\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['x-custom']) })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            input: new Request('https://example.com', { headers: { 'X-Custom': 'from-request' } }),\n            response: new Response(''),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.request).toEqual({\n          headers: { 'x-custom': 'from-request' },\n        })\n      })\n    })\n\n    describe('XHR', () => {\n      it('should extract matching response headers from XHR', () => {\n        setupResourceCollection({\n          trackResourceHeaders: buildMatchHeadersForAllUrls(['content-type', 'cache-control']),\n        })\n\n        const xhr = new XMLHttpRequest()\n        spyOn(xhr, 'getAllResponseHeaders').and.returnValue(\n          'Content-Type: application/json\\r\\nCache-Control: max-age=300\\r\\nX-Other: ignored\\r\\n'\n        )\n\n        notifyRequest({\n          request: { type: RequestType.XHR, xhr },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response).toEqual({\n          headers: {\n            'content-type': 'application/json',\n            'cache-control': 'max-age=300',\n          },\n        })\n      })\n\n      // TODO: Remove this test when we support request headers for XHR\n      it('should not extract request headers from XHR', () => {\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['content-type']) })\n\n        const xhr = new XMLHttpRequest()\n        spyOn(xhr, 'getAllResponseHeaders').and.returnValue('Content-Type: text/html\\r\\n')\n\n        notifyRequest({\n          request: { type: RequestType.XHR, xhr },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.request).toBeUndefined()\n      })\n    })\n\n    it('should not collect headers when trackResourceHeaders is empty', () => {\n      setupResourceCollection({ trackResourceHeaders: [] })\n\n      notifyRequest({\n        request: {\n          type: RequestType.FETCH,\n          response: new Response('', { headers: { 'content-type': 'text/html', 'cache-control': 'no-cache' } }),\n          input: new Request('https://example.com/resource', { headers: { 'x-some-header': 'some-value' } }),\n        },\n      })\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.request).toBeUndefined()\n      expect(event.resource.response).toBeUndefined()\n    })\n\n    it('should override perf entry content-type with network content-type', () => {\n      setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['content-type']) })\n\n      notifyRequest({\n        request: {\n          type: RequestType.FETCH,\n          response: new Response('', { headers: { 'Content-Type': 'application/json' } }),\n        },\n        performanceEntryOverrides: { contentType: 'text/html' },\n      })\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.response!.headers!['content-type']).toBe('application/json')\n    })\n\n    it('should preserve perf entry content-type when no request object', () => {\n      setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['content-type']) })\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { contentType: 'image/png' })])\n      runTasks()\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.response!.headers!['content-type']).toBe('image/png')\n    })\n\n    it('should lowercase header names', () => {\n      setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['x-custom-header']) })\n\n      notifyRequest({\n        request: {\n          type: RequestType.FETCH,\n          response: new Response('', { headers: { 'X-Custom-Header': 'value' } }),\n        },\n      })\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.response!.headers!['x-custom-header']).toBe('value')\n    })\n\n    it('should support RegExp matchers', () => {\n      setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls([/^x-custom/]) })\n\n      notifyRequest({\n        request: {\n          type: RequestType.FETCH,\n          response: new Response('', { headers: { 'X-Custom-One': 'a', 'X-Custom-Two': 'b', 'Cache-Control': 'no' } }),\n        },\n      })\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.response!.headers!['x-custom-one']).toBe('a')\n      expect(event.resource.response!.headers!['x-custom-two']).toBe('b')\n      expect(event.resource.response!.headers!['cache-control']).toBeUndefined()\n    })\n\n    it('should support function matchers', () => {\n      setupResourceCollection({\n        trackResourceHeaders: buildMatchHeadersForAllUrls([(name: string) => name.startsWith('x-')]),\n      })\n\n      notifyRequest({\n        request: {\n          type: RequestType.FETCH,\n          response: new Response('', { headers: { 'X-Foo': 'bar', 'Content-Type': 'text/html' } }),\n        },\n      })\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.response!.headers!['x-foo']).toBe('bar')\n      expect(event.resource.response!.headers!['content-type']).toBeUndefined()\n    })\n\n    it('should not collect headers when experimental feature is disabled', () => {\n      resetExperimentalFeatures()\n      setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['content-type']) })\n\n      notifyRequest({\n        request: {\n          type: RequestType.FETCH,\n          response: new Response('', { headers: { 'Content-Type': 'text/html' } }),\n        },\n      })\n\n      const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(event.resource.response).toBeUndefined()\n    })\n\n    describe('forbidden headers', () => {\n      const forbiddenHeaders = [\n        'authorization',\n        'x-api-key',\n        'x-access-token',\n        'x-auth-token',\n        'x-session-token',\n        'x-forwarded-for',\n        'x-real-ip',\n        'cf-connecting-ip',\n        'true-client-ip',\n        'x-csrf-token',\n        'x-xsrf-token',\n        'x-security-token',\n      ]\n\n      forbiddenHeaders.forEach((header) => {\n        it(`should not capture forbidden response header: ${header}`, () => {\n          setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(forbiddenHeaders) })\n\n          notifyRequest({\n            request: {\n              type: RequestType.FETCH,\n              response: new Response('', { headers: { [header]: 'secret-value' } }),\n            },\n          })\n\n          const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n          expect(event.resource.response?.headers?.[header]).toBeUndefined()\n        })\n\n        it(`should not capture forbidden request header: ${header}`, () => {\n          setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(forbiddenHeaders) })\n\n          notifyRequest({\n            request: {\n              type: RequestType.FETCH,\n              init: { headers: { [header]: 'secret-value' } },\n              response: new Response(''),\n            },\n          })\n\n          const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n          expect(event.resource.request?.headers?.[header]).toBeUndefined()\n        })\n      })\n    })\n\n    describe('limit headers size', () => {\n      it('should truncate header values exceeding the max length', () => {\n        const displaySpy = spyOn(display, 'warn')\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['x-long']) })\n        const longValue = 'a'.repeat(200)\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'X-Long': longValue } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response!.headers!['x-long']).toBe('a'.repeat(128))\n        expect(displaySpy).toHaveBeenCalledOnceWith('Header \"x-long\" value was truncated from 200 to 128 characters.')\n      })\n\n      it('should limit the number of collected headers', () => {\n        spyOn(display, 'warn')\n        const headerNames = Array.from({ length: 101 }, (_, i) => `x-header-${i}`)\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(headerNames) })\n\n        const headerEntries: Record<string, string> = {}\n        for (const name of headerNames) {\n          headerEntries[name] = 'value'\n        }\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: headerEntries }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(Object.keys(event.resource.response!.headers!).length).toBe(100)\n      })\n\n      it('should only count headers that pass filtering toward the limit', () => {\n        spyOn(display, 'warn')\n        const allowedHeaders = Array.from({ length: 100 }, (_, i) => `x-header-${i}`)\n        // Include a forbidden header name in the matchers - it won't be counted\n        const allMatchers = [...allowedHeaders, 'authorization', 'x-extra']\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(allMatchers) })\n\n        const headerEntries: Record<string, string> = {}\n        // The forbidden header comes first but should not count toward the limit\n        headerEntries['Authorization'] = 'secret'\n        for (const name of allowedHeaders) {\n          headerEntries[name] = 'value'\n        }\n        headerEntries['X-Extra'] = 'extra-value'\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: headerEntries }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        const collectedHeaders = event.resource.response!.headers!\n        expect(Object.keys(collectedHeaders).length).toBe(100)\n        expect(collectedHeaders['authorization']).toBeUndefined()\n      })\n\n      it('should not emit telemetry when the max number of headers has not been reached', async () => {\n        spyOn(display, 'warn')\n        const telemetry: MockTelemetry = startMockTelemetry()\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(['x-header-0', 'x-header-1']) })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'x-header-0': 'a', 'x-header-1': 'b' } }),\n          },\n        })\n\n        expect(await telemetry.getEvents()).not.toContain(\n          jasmine.objectContaining({ message: 'Maximum number of resource headers reached' })\n        )\n      })\n\n      it('should warn and emit telemetry when the max number of headers is reached', async () => {\n        const displaySpy = spyOn(display, 'warn')\n        const telemetry: MockTelemetry = startMockTelemetry()\n        const headerNames = Array.from({ length: 110 }, (_, i) => `x-header-${i}`)\n        setupResourceCollection({ trackResourceHeaders: buildMatchHeadersForAllUrls(headerNames) })\n\n        const headerEntries: Record<string, string> = {}\n        for (const name of headerNames) {\n          headerEntries[name] = 'value'\n        }\n        const response = new Response('', { headers: headerEntries })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response,\n          },\n        })\n\n        expect(displaySpy).toHaveBeenCalledOnceWith(\n          'Maximum number of headers (100) has been reached. Further headers are dropped.'\n        )\n        expect(await telemetry.getEvents()).toContain(\n          jasmine.objectContaining({\n            message: 'Maximum number of resource headers reached',\n            collectedHeaderCount: 100,\n            // Account for automatically added content-type header\n            totalHeaderCount: Array.from(response.headers as unknown as ArrayLike<string>).length,\n          })\n        )\n      })\n    })\n\n    describe('URL-scoped filtering', () => {\n      it('should only capture matching headers for a given URL', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ url: 'https://resource.com', name: 'x-api-version' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', {\n              headers: { 'X-Api-Version': '2', 'Content-Type': 'text/html' },\n            }),\n          },\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            url: 'https://other.com/endpoint',\n            response: new Response('', {\n              headers: { 'X-Api-Version': '3' },\n            }),\n          },\n        })\n\n        const matchingEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(matchingEvent.resource.response!.headers!['x-api-version']).toBe('2')\n        expect(matchingEvent.resource.response!.headers!['content-type']).toBeUndefined()\n\n        const nonMatchingEvent = rawRumEvents[1].rawRumEvent as RawRumResourceEvent\n        expect(nonMatchingEvent.resource.response?.headers).toBeUndefined()\n      })\n\n      it('should not capture headers when no URL rule matches', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ url: 'https://other.example.com', name: 'content-type' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Content-Type': 'text/html' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response).toBeUndefined()\n      })\n\n      it('should merge matchers from multiple matching rules', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [\n            { url: 'https://resource.com', name: 'x-first', location: 'response' },\n            { url: /resource\\.com/, name: 'x-second', location: 'response' },\n          ],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'X-First': 'a', 'X-Second': 'b' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response!.headers!['x-first']).toBe('a')\n        expect(event.resource.response!.headers!['x-second']).toBe('b')\n      })\n\n      it('should use startsWith for string URL matchers', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ url: 'https://resource.com', name: 'x-test', location: 'response' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'X-Test': 'value' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response!.headers!['x-test']).toBe('value')\n      })\n    })\n\n    describe('per-direction filtering', () => {\n      it('should capture only response headers when location is response', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ name: 'content-type', location: 'response' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            init: { headers: { 'X-Custom': 'value' } },\n            response: new Response('', { headers: { 'Content-Type': 'text/html' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response).toEqual({ headers: { 'content-type': 'text/html' } })\n        expect(event.resource.request).toBeUndefined()\n      })\n\n      it('should capture only request headers when location is request', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ name: 'x-custom', location: 'request' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            init: { headers: { 'X-Custom': 'value' } },\n            response: new Response('', { headers: { 'Content-Type': 'text/html' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.request).toEqual({ headers: { 'x-custom': 'value' } })\n        expect(event.resource.response).toBeUndefined()\n      })\n\n      it('should apply different matchers per direction', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [\n            { name: 'x-request-id', location: 'request' },\n            { name: 'content-type', location: 'response' },\n          ],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            init: { headers: { 'X-Request-Id': 'abc', 'Content-Type': 'application/json' } },\n            response: new Response('', { headers: { 'Content-Type': 'text/html', 'X-Request-Id': '123' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.request!.headers!['x-request-id']).toBe('abc')\n        expect(event.resource.request!.headers!['content-type']).toBeUndefined()\n        expect(event.resource.response!.headers!['content-type']).toBe('text/html')\n        expect(event.resource.response!.headers!['x-request-id']).toBeUndefined()\n      })\n    })\n\n    describe('extractor', () => {\n      it('should extract value with RegExp capture group', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ name: 'cache-control', extractor: /max-age=(\\d+)/, location: 'response' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Cache-Control': 'public, max-age=3600' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response!.headers!['cache-control']).toBe('3600')\n      })\n\n      it('should use full match when no capture group', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ name: 'cache-control', extractor: /max-age=\\d+/, location: 'response' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Cache-Control': 'public, max-age=3600' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response!.headers!['cache-control']).toBe('max-age=3600')\n      })\n\n      it('should skip header when extractor does not match', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [{ name: 'cache-control', extractor: /max-age=(\\d+)/, location: 'response' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Cache-Control': 'no-cache' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response?.headers?.['cache-control']).toBeUndefined()\n      })\n\n      it('should extract consistently when extractor has global flag', () => {\n        const globalExtractor = /max-age=(\\d+)/g\n        setupResourceCollection({\n          trackResourceHeaders: [{ name: 'cache-control', extractor: globalExtractor, location: 'response' }],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Cache-Control': 'public, max-age=3600' } }),\n          },\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Cache-Control': 'public, max-age=7200' } }),\n          },\n        })\n\n        const firstEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        const secondEvent = rawRumEvents[1].rawRumEvent as RawRumResourceEvent\n        expect(firstEvent.resource.response!.headers!['cache-control']).toBe('3600')\n        expect(secondEvent.resource.response!.headers!['cache-control']).toBe('7200')\n      })\n\n      it('first matching matcher wins', () => {\n        setupResourceCollection({\n          trackResourceHeaders: [\n            { name: 'cache-control', extractor: /max-age=(\\d+)/, location: 'response' },\n            { name: 'cache-control', location: 'response' },\n          ],\n        })\n\n        notifyRequest({\n          request: {\n            type: RequestType.FETCH,\n            response: new Response('', { headers: { 'Cache-Control': 'public, max-age=3600' } }),\n          },\n        })\n\n        const event = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n        expect(event.resource.response!.headers!['cache-control']).toBe('3600')\n      })\n    })\n  })\n\n  describe('tracing info', () => {\n    it('should be processed from traced initial document', () => {\n      setupResourceCollection()\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { traceId: '1234' })])\n      runTasks()\n      const privateFields = (rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd\n      expect(privateFields).toBeDefined()\n      expect(privateFields.trace_id).toBe('1234')\n      expect(privateFields.span_id).toEqual(jasmine.any(String))\n    })\n\n    it('should be processed from sampled completed request', () => {\n      setupResourceCollection()\n      notifyRequest({\n        request: {\n          traceSampled: true,\n          spanId: createSpanIdentifier(),\n          traceId: createTraceIdentifier(),\n        },\n      })\n      const privateFields = (rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd\n      expect(privateFields.trace_id).toBeDefined()\n      expect(privateFields.span_id).toBeDefined()\n    })\n\n    it('should not be processed from not sampled completed request', () => {\n      setupResourceCollection()\n      notifyRequest({\n        request: {\n          traceSampled: false,\n          spanId: createSpanIdentifier(),\n          traceId: createTraceIdentifier(),\n        },\n      })\n      const privateFields = (rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd\n      expect(privateFields.trace_id).not.toBeDefined()\n      expect(privateFields.span_id).not.toBeDefined()\n    })\n\n    it('should pull traceSampleRate from config if present', () => {\n      const config = validateAndBuildRumConfiguration({\n        clientToken: 'xxx',\n        applicationId: 'xxx',\n        traceSampleRate: 60,\n      })!\n      setupResourceCollection(config)\n\n      notifyRequest({\n        request: {\n          traceSampled: true,\n          spanId: createSpanIdentifier(),\n          traceId: createTraceIdentifier(),\n        },\n      })\n      const privateFields = (rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd\n      expect(privateFields.rule_psr).toEqual(0.6)\n    })\n\n    it('should not define rule_psr if traceSampleRate is undefined', () => {\n      const config = validateAndBuildRumConfiguration({\n        clientToken: 'xxx',\n        applicationId: 'xxx',\n      })!\n      setupResourceCollection(config)\n\n      notifyRequest({\n        request: {\n          traceSampled: true,\n          spanId: createSpanIdentifier(),\n          traceId: createTraceIdentifier(),\n        },\n      })\n      const privateFields = (rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd\n      expect(privateFields.rule_psr).toBeUndefined()\n    })\n\n    it('should define rule_psr to 0 if traceSampleRate is set to 0', () => {\n      const config = validateAndBuildRumConfiguration({\n        clientToken: 'xxx',\n        applicationId: 'xxx',\n        traceSampleRate: 0,\n      })!\n      setupResourceCollection(config)\n\n      notifyRequest({\n        request: {\n          traceSampled: true,\n          spanId: createSpanIdentifier(),\n          traceId: createTraceIdentifier(),\n        },\n      })\n      const privateFields = (rawRumEvents[0].rawRumEvent as RawRumResourceEvent)._dd\n      expect(privateFields.rule_psr).toEqual(0)\n    })\n  })\n\n  it('should collect handlingStack from completed fetch request', () => {\n    setupResourceCollection()\n    const response = new Response()\n    notifyRequest({ request: { type: RequestType.FETCH, response } })\n    const domainContext = rawRumEvents[0].domainContext as RumFetchResourceEventDomainContext\n\n    expect(domainContext.handlingStack).toMatch(HANDLING_STACK_REGEX)\n  })\n\n  it('should collect handlingStack from completed XHR request', () => {\n    setupResourceCollection()\n    const xhr = new XMLHttpRequest()\n    notifyRequest({ request: { type: RequestType.XHR, xhr } })\n\n    const domainContext = rawRumEvents[0].domainContext as RumXhrResourceEventDomainContext\n\n    expect(domainContext.handlingStack).toMatch(HANDLING_STACK_REGEX)\n  })\n\n  it('collects handle resources in different tasks', () => {\n    setupResourceCollection()\n\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE),\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE),\n      createPerformanceEntry(RumPerformanceEntryType.RESOURCE),\n    ])\n\n    expect(taskQueuePushSpy).toHaveBeenCalledTimes(3)\n\n    expect(rawRumEvents.length).toBe(0)\n\n    taskQueuePushSpy.calls.allArgs().forEach(([task], index) => {\n      task()\n      expect(rawRumEvents.length).toBe(index + 1)\n    })\n  })\n\n  function runTasks() {\n    taskQueuePushSpy.calls.allArgs().forEach(([task]) => {\n      task()\n    })\n    taskQueuePushSpy.calls.reset()\n  }\n\n  function notifyRequest({\n    request,\n    notifyPerformanceEntry = true,\n    performanceEntryOverrides,\n  }: {\n    request?: Partial<RequestCompleteEvent>\n    notifyPerformanceEntry?: boolean\n    performanceEntryOverrides?: Partial<RumPerformanceResourceTiming>\n  } = {}) {\n    const requestCompleteEvent = {\n      duration: 100 as Duration,\n      method: 'GET',\n      startClocks: { relative: 200 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n      status: 200,\n      type: RequestType.XHR,\n      url: 'https://resource.com/valid',\n      handlingStack:\n        'Error: \\n  at <anonymous> @ http://localhost/foo.js:1:2\\n    at <anonymous> @ http://localhost/vendor.js:1:2',\n      ...request,\n    } satisfies Partial<RequestCompleteEvent> as RequestCompleteEvent\n\n    lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, requestCompleteEvent)\n\n    if (notifyPerformanceEntry) {\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n          initiatorType: requestCompleteEvent.type === RequestType.FETCH ? 'fetch' : 'xmlhttprequest',\n          ...performanceEntryOverrides,\n        }),\n      ])\n    }\n\n    runTasks()\n  }\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/resourceCollection.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport {\n  combine,\n  generateUUID,\n  RequestType,\n  ResourceType,\n  toServerDuration,\n  relativeToClocks,\n  createTaskQueue,\n  mockable,\n  isExperimentalFeatureEnabled,\n  ExperimentalFeature,\n  matchList,\n  safeTruncate,\n  display,\n  addTelemetryDebug,\n} from '@datadog/browser-core'\nimport type { MatchHeader, RumConfiguration } from '../configuration'\nimport type { RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport { RumPerformanceEntryType, createPerformanceObservable } from '../../browser/performanceObservable'\nimport type {\n  RumXhrResourceEventDomainContext,\n  RumFetchResourceEventDomainContext,\n  RumOtherResourceEventDomainContext,\n} from '../../domainContext.types'\nimport type { NetworkHeaders, RawRumResourceEvent, ResourceRequest, ResourceResponse } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData, LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { RequestCompleteEvent } from '../requestCollection'\nimport type { PageStateHistory } from '../contexts/pageStateHistory'\nimport { PageState } from '../contexts/pageStateHistory'\nimport { createSpanIdentifier } from '../tracing/identifier'\nimport { startEventTracker } from '../eventTracker'\nimport { extractRegexMatch } from '../extractRegexMatch'\nimport { matchRequestResourceEntry } from './matchRequestResourceEntry'\nimport {\n  computeResourceEntryDetails,\n  computeResourceEntryDuration,\n  computeResourceEntryType,\n  computeResourceEntrySize,\n  computeResourceEntryProtocol,\n  computeResourceEntryDeliveryType,\n  isResourceEntryRequestType,\n  sanitizeIfLongDataUrl,\n} from './resourceUtils'\nimport { retrieveInitialDocumentResourceTiming } from './retrieveInitialDocumentResourceTiming'\nimport type { RequestRegistry } from './requestRegistry'\nimport { createRequestRegistry } from './requestRegistry'\nimport type { GraphQlMetadata } from './graphql'\nimport { extractGraphQlMetadata, findGraphQlConfiguration } from './graphql'\nimport type { ManualResourceData } from './trackManualResources'\nimport { trackManualResources } from './trackManualResources'\n\nexport function startResourceCollection(\n  lifeCycle: LifeCycle,\n  configuration: RumConfiguration,\n  pageStateHistory: PageStateHistory\n) {\n  const taskQueue = mockable(createTaskQueue)()\n  let requestRegistry: RequestRegistry | undefined\n  const isEarlyRequestCollectionEnabled = configuration.trackEarlyRequests\n\n  if (isEarlyRequestCollectionEnabled) {\n    requestRegistry = createRequestRegistry(lifeCycle)\n  } else {\n    lifeCycle.subscribe(LifeCycleEventType.REQUEST_COMPLETED, (request: RequestCompleteEvent) => {\n      handleResource(() => processRequest(request, configuration, pageStateHistory))\n    })\n  }\n\n  const performanceResourceSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.RESOURCE,\n    buffered: true,\n  }).subscribe((entries) => {\n    for (const entry of entries) {\n      if (isEarlyRequestCollectionEnabled || !isResourceEntryRequestType(entry)) {\n        handleResource(() => processResourceEntry(entry, configuration, pageStateHistory, requestRegistry))\n      }\n    }\n  })\n\n  mockable(retrieveInitialDocumentResourceTiming)(configuration, (timing) => {\n    handleResource(() => processResourceEntry(timing, configuration, pageStateHistory, requestRegistry))\n  })\n\n  function handleResource(computeRawEvent: () => RawRumEventCollectedData<RawRumResourceEvent> | undefined) {\n    taskQueue.push(() => {\n      const rawEvent = computeRawEvent()\n      if (rawEvent) {\n        lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, rawEvent)\n      }\n    })\n  }\n\n  const resourceTracker = startEventTracker<ManualResourceData>(lifeCycle)\n  const manualResources = trackManualResources(lifeCycle, resourceTracker)\n\n  return {\n    startResource: manualResources.startResource,\n    stopResource: manualResources.stopResource,\n    stop: () => {\n      taskQueue.stop()\n      performanceResourceSubscription.unsubscribe()\n      resourceTracker.stopAll()\n    },\n  }\n}\n\nfunction processRequest(\n  request: RequestCompleteEvent,\n  configuration: RumConfiguration,\n  pageStateHistory: PageStateHistory\n): RawRumEventCollectedData<RawRumResourceEvent> | undefined {\n  const matchingTiming = matchRequestResourceEntry(request)\n  return assembleResource(matchingTiming, request, pageStateHistory, configuration)\n}\n\nfunction processResourceEntry(\n  entry: RumPerformanceResourceTiming,\n  configuration: RumConfiguration,\n  pageStateHistory: PageStateHistory,\n  requestRegistry: RequestRegistry | undefined\n): RawRumEventCollectedData<RawRumResourceEvent> | undefined {\n  const matchingRequest =\n    isResourceEntryRequestType(entry) && requestRegistry ? requestRegistry.getMatchingRequest(entry) : undefined\n  return assembleResource(entry, matchingRequest, pageStateHistory, configuration)\n}\n\n// TODO: In the future, the `entry` parameter should be required, making things simpler.\nfunction assembleResource(\n  entry: RumPerformanceResourceTiming | undefined,\n  request: RequestCompleteEvent | undefined,\n  pageStateHistory: PageStateHistory,\n  configuration: RumConfiguration\n): RawRumEventCollectedData<RawRumResourceEvent> | undefined {\n  if (!entry && !request) {\n    return\n  }\n\n  const tracingInfo = request\n    ? computeRequestTracingInfo(request, configuration)\n    : computeResourceEntryTracingInfo(entry!, configuration)\n  if (!configuration.trackResources && !tracingInfo) {\n    return\n  }\n\n  const startClocks = entry ? relativeToClocks(entry.startTime) : request!.startClocks\n  const duration = entry\n    ? computeResourceEntryDuration(entry)\n    : computeRequestDuration(pageStateHistory, startClocks, request!.duration)\n\n  const networkHeaders = isExperimentalFeatureEnabled(ExperimentalFeature.TRACK_RESOURCE_HEADERS)\n    ? computeNetworkHeaders(request, configuration)\n    : undefined\n\n  const graphql = request && computeGraphQlMetaData(request, configuration)\n  const contentTypeFromPerformanceEntry = entry && computeContentTypeFromPerformanceEntry(entry)\n\n  const resourceEvent = combine(\n    {\n      date: startClocks.timeStamp,\n      resource: {\n        id: generateUUID(),\n        duration: toServerDuration(duration),\n        // TODO: in the future when `entry` is required, we can probably only rely on `computeResourceEntryType`\n        type: request\n          ? request.type === RequestType.XHR\n            ? ResourceType.XHR\n            : ResourceType.FETCH\n          : computeResourceEntryType(entry!),\n        method: request ? request.method : undefined,\n        status_code: request ? request.status : discardZeroStatus(entry!.responseStatus),\n        url: request ? sanitizeIfLongDataUrl(request.url) : entry!.name,\n        protocol: entry && computeResourceEntryProtocol(entry),\n        delivery_type: entry && computeResourceEntryDeliveryType(entry),\n        graphql,\n      },\n      type: RumEventType.RESOURCE,\n      _dd: {\n        discarded: !configuration.trackResources,\n      },\n    },\n    tracingInfo,\n    entry && computeResourceEntryMetrics(entry),\n    contentTypeFromPerformanceEntry,\n    networkHeaders\n  )\n\n  return {\n    startClocks,\n    duration,\n    rawRumEvent: resourceEvent,\n    domainContext: getResourceDomainContext(entry, request),\n  }\n}\n\nfunction computeGraphQlMetaData(\n  request: RequestCompleteEvent,\n  configuration: RumConfiguration\n): GraphQlMetadata | undefined {\n  const graphQlConfig = findGraphQlConfiguration(request.url, configuration)\n  if (!graphQlConfig) {\n    return\n  }\n\n  return extractGraphQlMetadata(request, graphQlConfig)\n}\n\nfunction computeContentTypeFromPerformanceEntry(\n  entry: RumPerformanceResourceTiming\n): { resource: Pick<RawRumResourceEvent['resource'], 'response'> } | undefined {\n  const contentType = entry.contentType\n\n  if (contentType) {\n    return {\n      resource: {\n        response: {\n          headers: {\n            'content-type': contentType,\n          },\n        },\n      },\n    }\n  }\n\n  return undefined\n}\n\nfunction getResourceDomainContext(\n  entry: RumPerformanceResourceTiming | undefined,\n  request: RequestCompleteEvent | undefined\n): RumFetchResourceEventDomainContext | RumXhrResourceEventDomainContext | RumOtherResourceEventDomainContext {\n  if (request) {\n    const baseDomainContext = {\n      performanceEntry: entry,\n      isAborted: request.isAborted,\n      handlingStack: request.handlingStack,\n    }\n\n    if (request.type === RequestType.XHR) {\n      return {\n        xhr: request.xhr!,\n        ...baseDomainContext,\n      }\n    }\n    return {\n      requestInput: request.input as RequestInfo,\n      requestInit: request.init,\n      response: request.response,\n      error: request.error,\n      ...baseDomainContext,\n    }\n  }\n  return {\n    // Currently, at least one of `entry` or `request` must be defined when calling this function.\n    // So `entry` is guaranteed to be defined here. In the future, when `entry` is required, we can\n    // remove the `!` assertion.\n    performanceEntry: entry!,\n  }\n}\n\nfunction computeResourceEntryMetrics(entry: RumPerformanceResourceTiming) {\n  const { renderBlockingStatus } = entry\n  return {\n    resource: {\n      render_blocking_status: renderBlockingStatus,\n      ...computeResourceEntrySize(entry),\n      ...computeResourceEntryDetails(entry),\n    },\n  }\n}\n\nfunction computeRequestTracingInfo(request: RequestCompleteEvent, configuration: RumConfiguration) {\n  const hasBeenTraced = request.traceSampled && request.traceId && request.spanId\n  if (!hasBeenTraced) {\n    return undefined\n  }\n  return {\n    _dd: {\n      span_id: request.spanId!.toString(),\n      trace_id: request.traceId!.toString(),\n      rule_psr: configuration.rulePsr,\n    },\n  }\n}\n\nfunction computeResourceEntryTracingInfo(entry: RumPerformanceResourceTiming, configuration: RumConfiguration) {\n  const hasBeenTraced = entry.traceId\n  if (!hasBeenTraced) {\n    return undefined\n  }\n  return {\n    _dd: {\n      trace_id: entry.traceId,\n      span_id: createSpanIdentifier().toString(),\n      rule_psr: configuration.rulePsr,\n    },\n  }\n}\n\nfunction computeRequestDuration(pageStateHistory: PageStateHistory, startClocks: ClocksState, duration: Duration) {\n  return !pageStateHistory.wasInPageStateDuringPeriod(PageState.FROZEN, startClocks.relative, duration)\n    ? duration\n    : undefined\n}\n\n/**\n * The status is 0 for cross-origin resources without CORS headers, so the status is meaningless, and we shouldn't report it\n * https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus#cross-origin_response_status_codes\n */\nfunction discardZeroStatus(statusCode: number | undefined): number | undefined {\n  return statusCode === 0 ? undefined : statusCode\n}\n\nfunction computeNetworkHeaders(\n  request: RequestCompleteEvent | undefined,\n  configuration: RumConfiguration\n): { resource: { request?: ResourceRequest; response?: ResourceResponse } } | undefined {\n  const matchers = configuration.trackResourceHeaders\n  if (matchers.length === 0 || !request) {\n    return undefined\n  }\n\n  const urlMatchers = matchers.filter((m) => (m.url !== undefined ? matchList([m.url], request.url, true) : true))\n  if (urlMatchers.length === 0) {\n    return undefined\n  }\n\n  const responseMatchers = urlMatchers.filter(\n    (m) => m.location === undefined || m.location === 'any' || m.location === 'response'\n  )\n  const requestMatchers = urlMatchers.filter(\n    (m) => m.location === undefined || m.location === 'any' || m.location === 'request'\n  )\n\n  const responseHeaders = responseMatchers.length > 0 ? getResponseHeaders(request, responseMatchers) : undefined\n  const requestHeaders = requestMatchers.length > 0 ? getRequestHeaders(request, requestMatchers) : undefined\n\n  if (!responseHeaders && !requestHeaders) {\n    return undefined\n  }\n\n  return {\n    resource: {\n      request: requestHeaders ? { headers: requestHeaders } : undefined,\n      response: responseHeaders ? { headers: responseHeaders } : undefined,\n    },\n  }\n}\n\nfunction getResponseHeaders(request: RequestCompleteEvent, matchers: MatchHeader[]): NetworkHeaders | undefined {\n  if (request.type === RequestType.FETCH && request.response) {\n    return filterHeaders(request.response.headers, matchers)\n  }\n\n  if (request.type === RequestType.XHR && request.xhr) {\n    const rawXhrHeaders = request.xhr.getAllResponseHeaders()\n    if (rawXhrHeaders) {\n      try {\n        return filterHeaders(new Headers(parseRawXhrHeaders(rawXhrHeaders)), matchers)\n      } catch {\n        // Ignore parsing errors\n      }\n    }\n  }\n\n  return undefined\n}\n\nfunction getRequestHeaders(request: RequestCompleteEvent, matchers: MatchHeader[]): NetworkHeaders | undefined {\n  if (request.type !== RequestType.FETCH) {\n    return undefined\n  }\n\n  let headers: Headers | undefined\n\n  if (request.init?.headers) {\n    headers = new Headers(request.init.headers)\n  } else if (request.input instanceof Request) {\n    headers = request.input.headers\n  }\n\n  return headers ? filterHeaders(headers, matchers) : undefined\n}\n\nconst FORBIDDEN_HEADER_PATTERN =\n  /(token|cookie|secret|authorization|(api|secret|access|app).?key|(client|connecting|real).?ip|forwarded)/\nconst MAX_HEADER_COUNT = 100\nconst MAX_HEADER_VALUE_LENGTH = 128\n\nfunction filterHeaders(headers: Headers, matchers: MatchHeader[]): NetworkHeaders | undefined {\n  const result: NetworkHeaders = {} as NetworkHeaders\n  let collectedHeaderCount = 0\n  let totalHeaderCount = 0\n  let hasReachedMaxHeaderCount = false\n\n  headers.forEach((value, name) => {\n    totalHeaderCount++\n\n    if (collectedHeaderCount >= MAX_HEADER_COUNT) {\n      if (!hasReachedMaxHeaderCount) {\n        display.warn(`Maximum number of headers (${MAX_HEADER_COUNT}) has been reached. Further headers are dropped.`)\n        hasReachedMaxHeaderCount = true\n      }\n\n      return\n    }\n\n    const lowerName = name.toLowerCase()\n\n    if (FORBIDDEN_HEADER_PATTERN.test(lowerName)) {\n      return\n    }\n\n    const matchHeader = matchers.find((m) => matchList([m.name], lowerName))\n    if (!matchHeader) {\n      return\n    }\n\n    const { extractor } = matchHeader\n    const capturedValue = extractor ? extractRegexMatch(value, extractor) : value\n    if (capturedValue === undefined) {\n      return\n    }\n\n    if (capturedValue.length > MAX_HEADER_VALUE_LENGTH) {\n      display.warn(\n        `Header \"${lowerName}\" value was truncated from ${capturedValue.length} to ${MAX_HEADER_VALUE_LENGTH} characters.`\n      )\n      // monitor-until: 2026-05-23\n      addTelemetryDebug('Resource header value was truncated', {\n        header_name: lowerName,\n        original_length: capturedValue.length,\n        limit: MAX_HEADER_VALUE_LENGTH,\n      })\n    }\n\n    result[lowerName] = safeTruncate(capturedValue, MAX_HEADER_VALUE_LENGTH)\n    collectedHeaderCount++\n  })\n\n  if (hasReachedMaxHeaderCount) {\n    // monitor-until: 2026-05-23\n    addTelemetryDebug('Maximum number of resource headers reached', {\n      collectedHeaderCount,\n      totalHeaderCount,\n    })\n  }\n\n  return collectedHeaderCount > 0 ? result : undefined\n}\n\n// Input:  \"content-type: application/json\\r\\ncache-control: no-cache\"\n// Output: [[\"content-type\", \"application/json\"], [\"cache-control\", \"no-cache\"]]\nfunction parseRawXhrHeaders(rawXhrheaders: string): Array<[string, string]> {\n  const pairs: Array<[string, string]> = []\n  const lines = rawXhrheaders.trim().split(/\\r\\n/)\n  for (const line of lines) {\n    const colonIndex = line.indexOf(':')\n    if (colonIndex > 0) {\n      pairs.push([line.substring(0, colonIndex).trim(), line.substring(colonIndex + 1).trim()])\n    }\n  }\n  return pairs\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/resourceUtils.spec.ts",
    "content": "import { addExperimentalFeatures, type Duration, type RelativeTime, type ServerDuration } from '@datadog/browser-core'\nimport { ExperimentalFeature } from '@datadog/browser-core'\nimport { RumPerformanceEntryType, type RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport {\n  MAX_RESOURCE_VALUE_CHAR_LENGTH,\n  computeResourceEntryDetails,\n  computeResourceEntryDuration,\n  computeResourceEntryType,\n  isAllowedRequestUrl,\n  sanitizeIfLongDataUrl,\n} from './resourceUtils'\n\nfunction generateResourceWith(overrides: Partial<RumPerformanceResourceTiming>) {\n  const completeTiming: RumPerformanceResourceTiming = {\n    connectEnd: 17 as RelativeTime,\n    connectStart: 15 as RelativeTime,\n    domainLookupEnd: 14 as RelativeTime,\n    domainLookupStart: 13 as RelativeTime,\n    duration: 50 as Duration,\n    entryType: RumPerformanceEntryType.RESOURCE,\n    fetchStart: 12 as RelativeTime,\n    name: 'entry',\n    redirectEnd: 11 as RelativeTime,\n    redirectStart: 10 as RelativeTime,\n    requestStart: 20 as RelativeTime,\n    responseEnd: 60 as RelativeTime,\n    responseStart: 50 as RelativeTime,\n    secureConnectionStart: 16 as RelativeTime,\n    startTime: 10 as RelativeTime,\n    workerStart: 0 as RelativeTime,\n\n    initiatorType: 'script',\n    decodedBodySize: 0,\n    encodedBodySize: 0,\n    transferSize: 0,\n    toJSON: () => ({ ...completeTiming, toJSON: undefined }),\n\n    ...overrides,\n  }\n  return completeTiming\n}\n\ndescribe('computeResourceEntryType', () => {\n  ;[\n    {\n      description: 'file extension with query params',\n      expected: 'js',\n      name: 'http://localhost/test.js?from=foo.css',\n    },\n    {\n      description: 'css extension',\n      expected: 'css',\n      name: 'http://localhost/test.css',\n    },\n    {\n      description: 'image initiator',\n      expected: 'image',\n      initiatorType: 'img',\n      name: 'http://localhost/test',\n    },\n    {\n      description: 'image extension',\n      expected: 'image',\n      name: 'http://localhost/test.jpg',\n    },\n  ].forEach(\n    ({\n      description,\n      name,\n      initiatorType,\n      expected,\n    }: {\n      description: string\n      name: string\n      initiatorType?: string\n      expected: string\n    }) => {\n      it(`should compute resource kind: ${description}`, () => {\n        const entry = generateResourceWith({ initiatorType, name })\n        expect(computeResourceEntryType(entry)).toEqual(expected)\n      })\n    }\n  )\n})\n\ndescribe('computeResourceEntryDetails', () => {\n  it('should not compute entry without detailed timings', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          connectEnd: 0 as RelativeTime,\n          connectStart: 0 as RelativeTime,\n          domainLookupEnd: 0 as RelativeTime,\n          domainLookupStart: 0 as RelativeTime,\n          redirectEnd: 0 as RelativeTime,\n          redirectStart: 0 as RelativeTime,\n          requestStart: 0 as RelativeTime,\n          responseStart: 0 as RelativeTime,\n          secureConnectionStart: 0 as RelativeTime,\n        })\n      )\n    ).toBeUndefined()\n  })\n\n  it('should compute details from entry', () => {\n    expect(computeResourceEntryDetails(generateResourceWith({}))).toEqual({\n      connect: { start: 5e6 as ServerDuration, duration: 2e6 as ServerDuration },\n      dns: { start: 3e6 as ServerDuration, duration: 1e6 as ServerDuration },\n      download: { start: 40e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 10e6 as ServerDuration, duration: 30e6 as ServerDuration },\n      redirect: { start: 0 as ServerDuration, duration: 1e6 as ServerDuration },\n      ssl: { start: 6e6 as ServerDuration, duration: 1e6 as ServerDuration },\n    })\n  })\n\n  it('should compute worker timing when workerStart < fetchStart', () => {\n    const resourceTiming = generateResourceWith({\n      workerStart: 11 as RelativeTime,\n      fetchStart: 12 as RelativeTime,\n    })\n    const details = computeResourceEntryDetails(resourceTiming)\n    expect(details!.worker).toEqual({ start: 1e6 as ServerDuration, duration: 1e6 as ServerDuration })\n  })\n\n  it('should not compute redirect timing when no redirect', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          fetchStart: 10 as RelativeTime,\n          redirectEnd: 0 as RelativeTime,\n          redirectStart: 0 as RelativeTime,\n        })\n      )\n    ).toEqual({\n      connect: { start: 5e6 as ServerDuration, duration: 2e6 as ServerDuration },\n      dns: { start: 3e6 as ServerDuration, duration: 1e6 as ServerDuration },\n      download: { start: 40e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 10e6 as ServerDuration, duration: 30e6 as ServerDuration },\n      ssl: { start: 6e6 as ServerDuration, duration: 1e6 as ServerDuration },\n    })\n  })\n\n  it('should not compute dns timing when persistent connection or cache', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          domainLookupEnd: 12 as RelativeTime,\n          domainLookupStart: 12 as RelativeTime,\n          fetchStart: 12 as RelativeTime,\n        })\n      )\n    ).toEqual({\n      connect: { start: 5e6 as ServerDuration, duration: 2e6 as ServerDuration },\n      download: { start: 40e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 10e6 as ServerDuration, duration: 30e6 as ServerDuration },\n      redirect: { start: 0 as ServerDuration, duration: 1e6 as ServerDuration },\n      ssl: { start: 6e6 as ServerDuration, duration: 1e6 as ServerDuration },\n    })\n  })\n\n  it('should not compute ssl timing when no secure connection', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          secureConnectionStart: 0 as RelativeTime,\n        })\n      )\n    ).toEqual({\n      connect: { start: 5e6 as ServerDuration, duration: 2e6 as ServerDuration },\n      dns: { start: 3e6 as ServerDuration, duration: 1e6 as ServerDuration },\n      download: { start: 40e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 10e6 as ServerDuration, duration: 30e6 as ServerDuration },\n      redirect: { start: 0 as ServerDuration, duration: 1e6 as ServerDuration },\n    })\n  })\n\n  it('should not compute ssl timing when persistent connection', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          connectEnd: 12 as RelativeTime,\n          connectStart: 12 as RelativeTime,\n          domainLookupEnd: 12 as RelativeTime,\n          domainLookupStart: 12 as RelativeTime,\n          fetchStart: 12 as RelativeTime,\n          secureConnectionStart: 12 as RelativeTime,\n        })\n      )\n    ).toEqual({\n      download: { start: 40e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 10e6 as ServerDuration, duration: 30e6 as ServerDuration },\n      redirect: { start: 0 as ServerDuration, duration: 1e6 as ServerDuration },\n    })\n  })\n\n  it('should not compute connect timing when persistent connection', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          connectEnd: 12 as RelativeTime,\n          connectStart: 12 as RelativeTime,\n          domainLookupEnd: 12 as RelativeTime,\n          domainLookupStart: 12 as RelativeTime,\n          fetchStart: 12 as RelativeTime,\n          secureConnectionStart: 0 as RelativeTime,\n        })\n      )\n    ).toEqual({\n      download: { start: 40e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 10e6 as ServerDuration, duration: 30e6 as ServerDuration },\n      redirect: { start: 0 as ServerDuration, duration: 1e6 as ServerDuration },\n    })\n  })\n  ;[\n    {\n      reason: 'connectStart > connectEnd',\n      connectEnd: 10 as RelativeTime,\n      connectStart: 20 as RelativeTime,\n    },\n    {\n      reason: 'domainLookupStart > domainLookupEnd',\n      domainLookupEnd: 10 as RelativeTime,\n      domainLookupStart: 20 as RelativeTime,\n    },\n    {\n      reason: 'responseStart > responseEnd',\n      responseEnd: 10 as RelativeTime,\n      responseStart: 20 as RelativeTime,\n    },\n    {\n      reason: 'requestStart > responseStart',\n      requestStart: 20 as RelativeTime,\n      responseStart: 10 as RelativeTime,\n    },\n    {\n      reason: 'redirectStart > redirectEnd',\n      redirectEnd: 15 as RelativeTime,\n      redirectStart: 20 as RelativeTime,\n    },\n    {\n      connectEnd: 10 as RelativeTime,\n      reason: 'secureConnectionStart > connectEnd',\n      secureConnectionStart: 20 as RelativeTime,\n    },\n    {\n      connectEnd: 10 as RelativeTime,\n      connectStart: -3 as RelativeTime,\n      fetchStart: 10 as RelativeTime,\n      reason: 'negative timing start',\n    },\n  ].forEach(({ reason, ...overrides }) => {\n    it(`should not compute entry when ${reason}`, () => {\n      expect(computeResourceEntryDetails(generateResourceWith(overrides))).toBeUndefined()\n    })\n  })\n\n  it('should allow really fast document resource', () => {\n    expect(\n      computeResourceEntryDetails(\n        generateResourceWith({\n          connectEnd: 10 as RelativeTime,\n          connectStart: 10 as RelativeTime,\n          domainLookupEnd: 10 as RelativeTime,\n          domainLookupStart: 10 as RelativeTime,\n          fetchStart: 10 as RelativeTime,\n          redirectEnd: 0 as RelativeTime,\n          redirectStart: 0 as RelativeTime,\n          requestStart: 10 as RelativeTime,\n          responseEnd: 50 as RelativeTime,\n          responseStart: 40 as RelativeTime,\n          secureConnectionStart: 0 as RelativeTime,\n        })\n      )\n    ).toEqual({\n      download: { start: 30e6 as ServerDuration, duration: 10e6 as ServerDuration },\n      first_byte: { start: 0 as ServerDuration, duration: 30e6 as ServerDuration },\n    })\n  })\n})\n\ndescribe('computeResourceEntryDuration', () => {\n  it('should return the entry duration', () => {\n    expect(computeResourceEntryDuration(generateResourceWith({}))).toBe(50 as Duration)\n  })\n\n  it('should use other available timing if the duration is 0', () => {\n    expect(computeResourceEntryDuration(generateResourceWith({ duration: 0 as Duration }))).toBe(50 as Duration)\n  })\n})\n\ndescribe('shouldTrackResource', () => {\n  const intakeParameters = 'ddsource=browser&dd-api-key=xxxx&dd-request-id=1234567890'\n  it('should exclude requests on intakes endpoints', () => {\n    expect(isAllowedRequestUrl(`https://rum-intake.com/v1/input/abcde?${intakeParameters}`)).toBe(false)\n  })\n\n  it('should allow requests on intake endpoints when TRACK_INTAKE_REQUESTS is enabled', () => {\n    addExperimentalFeatures([ExperimentalFeature.TRACK_INTAKE_REQUESTS])\n    expect(isAllowedRequestUrl(`https://rum-intake.com/v1/input/abcde?${intakeParameters}`)).toBe(true)\n  })\n\n  it('should exclude requests on intakes endpoints with different client parameters', () => {\n    expect(isAllowedRequestUrl(`https://rum-intake.com/v1/input/wxyz?${intakeParameters}`)).toBe(false)\n  })\n\n  it('should allow requests on non intake domains', () => {\n    expect(isAllowedRequestUrl('https://my-domain.com/hello?a=b')).toBe(true)\n  })\n})\n\ndescribe('sanitizeIfLongDataUrl', () => {\n  const longString = new Array(MAX_RESOURCE_VALUE_CHAR_LENGTH).join('a')\n  it('returns truncated url when detects data url of json', () => {\n    expect(sanitizeIfLongDataUrl(`data:text/json; charset=utf-8,${longString}`)).toEqual(\n      'data:text/json; charset=utf-8,[...]'\n    )\n  })\n\n  it('returns truncated url when detects data url of html', () => {\n    const longDataUrl = `data:text/html,${longString}`\n    expect(sanitizeIfLongDataUrl(longDataUrl)).toEqual('data:text/html,[...]')\n  })\n\n  it('returns truncated url when detects data url of image', () => {\n    const longDataUrl = `data:image/svg+xml;base64,${longString}`\n    expect(sanitizeIfLongDataUrl(longDataUrl)).toEqual('data:image/svg+xml;base64,[...]')\n  })\n\n  it('returns truncated url when detects plain data url', () => {\n    const plainDataUrl = `data:,${longString}`\n    expect(sanitizeIfLongDataUrl(plainDataUrl)).toEqual('data:,[...]')\n  })\n\n  it('allows customized length limit', () => {\n    const customLength = MAX_RESOURCE_VALUE_CHAR_LENGTH + 100\n    const longDataUrl = `data:text/plain,${longString}`\n    expect(sanitizeIfLongDataUrl(longDataUrl, customLength)).toEqual(longDataUrl)\n  })\n\n  it('returns truncated url when detects data url with exotic mime type', () => {\n    const exoticTypeDataUrl = `data:application/vnd.openxmlformats;fileName=officedocument.presentationxml;base64,${longString}`\n    expect(sanitizeIfLongDataUrl(exoticTypeDataUrl)).toEqual(\n      'data:application/vnd.openxmlformats;fileName=officedocument.presentationxml;base64,[...]'\n    )\n  })\n\n  it('returns the original url when the data url is within limit', () => {\n    const shortDataUrl = `data:text/plain,${new Array(MAX_RESOURCE_VALUE_CHAR_LENGTH - 15).join('a')}`\n    expect(sanitizeIfLongDataUrl(shortDataUrl)).toEqual(shortDataUrl)\n  })\n\n  it('returns original string when no data url found', () => {\n    const normalUrl = 'https://example.com/resource.js'\n    expect(sanitizeIfLongDataUrl(normalUrl)).toEqual(normalUrl)\n  })\n\n  it('returns original string when data type match not found', () => {\n    const dataTypeTooLongUrl = `data:${new Array(100).join('a')},${longString}`\n    expect(sanitizeIfLongDataUrl(dataTypeTooLongUrl)).toEqual(dataTypeTooLongUrl)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/resourceUtils.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport {\n  elapsed,\n  getPathName,\n  isValidUrl,\n  ResourceType,\n  toServerDuration,\n  isIntakeUrl,\n  isExperimentalFeatureEnabled,\n  ExperimentalFeature,\n} from '@datadog/browser-core'\n\nimport type { RumPerformanceResourceTiming } from '../../browser/performanceObservable'\n\nimport type { ResourceEntryDetailsElement, DeliveryType } from '../../rawRumEvent.types'\n\nexport interface ResourceEntryDetails {\n  worker?: ResourceEntryDetailsElement\n  redirect?: ResourceEntryDetailsElement\n  dns?: ResourceEntryDetailsElement\n  connect?: ResourceEntryDetailsElement\n  ssl?: ResourceEntryDetailsElement\n  first_byte?: ResourceEntryDetailsElement\n  download?: ResourceEntryDetailsElement\n}\n\nexport const FAKE_INITIAL_DOCUMENT = 'initial_document'\n\nconst RESOURCE_TYPES: Array<[ResourceType, (initiatorType: string, path: string) => boolean]> = [\n  [ResourceType.DOCUMENT, (initiatorType: string) => FAKE_INITIAL_DOCUMENT === initiatorType],\n  [ResourceType.XHR, (initiatorType: string) => 'xmlhttprequest' === initiatorType],\n  [ResourceType.FETCH, (initiatorType: string) => 'fetch' === initiatorType],\n  [ResourceType.BEACON, (initiatorType: string) => 'beacon' === initiatorType],\n  [ResourceType.CSS, (_: string, path: string) => /\\.css$/i.test(path)],\n  [ResourceType.JS, (_: string, path: string) => /\\.js$/i.test(path)],\n  [\n    ResourceType.IMAGE,\n    (initiatorType: string, path: string) =>\n      ['image', 'img', 'icon'].includes(initiatorType) || /\\.(gif|jpg|jpeg|tiff|png|svg|ico)$/i.exec(path) !== null,\n  ],\n  [ResourceType.FONT, (_: string, path: string) => /\\.(woff|eot|woff2|ttf)$/i.exec(path) !== null],\n  [\n    ResourceType.MEDIA,\n    (initiatorType: string, path: string) =>\n      ['audio', 'video'].includes(initiatorType) || /\\.(mp3|mp4)$/i.exec(path) !== null,\n  ],\n]\n\nexport function computeResourceEntryType(entry: RumPerformanceResourceTiming) {\n  const url = entry.name\n  if (!isValidUrl(url)) {\n    return ResourceType.OTHER\n  }\n  const path = getPathName(url)\n  for (const [type, isType] of RESOURCE_TYPES) {\n    if (isType(entry.initiatorType, path)) {\n      return type\n    }\n  }\n  return ResourceType.OTHER\n}\n\nfunction areInOrder(...numbers: number[]) {\n  for (let i = 1; i < numbers.length; i += 1) {\n    if (numbers[i - 1] > numbers[i]) {\n      return false\n    }\n  }\n  return true\n}\n\nexport function isResourceEntryRequestType(entry: RumPerformanceResourceTiming) {\n  return entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch'\n}\n\nexport function computeResourceEntryDuration(entry: RumPerformanceResourceTiming): Duration {\n  const { duration, startTime, responseEnd } = entry\n\n  // Safari duration is always 0 on timings blocked by cross origin policies.\n  if (duration === 0 && startTime < responseEnd) {\n    return elapsed(startTime, responseEnd)\n  }\n\n  return duration\n}\n\nexport function computeResourceEntryDetails(entry: RumPerformanceResourceTiming): ResourceEntryDetails | undefined {\n  if (!hasValidResourceEntryTimings(entry)) {\n    return undefined\n  }\n  const {\n    startTime,\n    fetchStart,\n    workerStart,\n    redirectStart,\n    redirectEnd,\n    domainLookupStart,\n    domainLookupEnd,\n    connectStart,\n    secureConnectionStart,\n    connectEnd,\n    requestStart,\n    responseStart,\n    responseEnd,\n  } = entry\n\n  const details: ResourceEntryDetails = {\n    download: formatTiming(startTime, responseStart, responseEnd),\n    first_byte: formatTiming(startTime, requestStart, responseStart),\n  }\n\n  // Make sure a worker processing time is recorded\n  if (0 < workerStart && workerStart < fetchStart) {\n    details.worker = formatTiming(startTime, workerStart, fetchStart)\n  }\n\n  // Make sure a connection occurred\n  if (fetchStart < connectEnd) {\n    details.connect = formatTiming(startTime, connectStart, connectEnd)\n\n    // Make sure a secure connection occurred\n    if (connectStart <= secureConnectionStart && secureConnectionStart <= connectEnd) {\n      details.ssl = formatTiming(startTime, secureConnectionStart, connectEnd)\n    }\n  }\n\n  // Make sure a domain lookup occurred\n  if (fetchStart < domainLookupEnd) {\n    details.dns = formatTiming(startTime, domainLookupStart, domainLookupEnd)\n  }\n\n  // Make sure a redirection occurred\n  if (startTime < redirectEnd) {\n    details.redirect = formatTiming(startTime, redirectStart, redirectEnd)\n  }\n\n  return details\n}\n\n/**\n * Entries with negative duration are unexpected and should be dismissed. The intake will ignore RUM\n * Resource events with negative durations anyway.\n * Since Chromium 128, more entries have unexpected negative durations, see\n * https://issues.chromium.org/issues/363031537\n */\nexport function hasValidResourceEntryDuration(entry: RumPerformanceResourceTiming) {\n  return entry.duration >= 0\n}\n\nexport function hasValidResourceEntryTimings(entry: RumPerformanceResourceTiming) {\n  // Ensure timings are in the right order. On top of filtering out potential invalid\n  // RumPerformanceResourceTiming, it will ignore entries from requests where timings cannot be\n  // collected, for example cross origin requests without a \"Timing-Allow-Origin\" header allowing\n  // it.\n  const areCommonTimingsInOrder = areInOrder(\n    entry.startTime,\n    entry.fetchStart,\n    entry.domainLookupStart,\n    entry.domainLookupEnd,\n    entry.connectStart,\n    entry.connectEnd,\n    entry.requestStart,\n    entry.responseStart,\n    entry.responseEnd\n  )\n\n  const areRedirectionTimingsInOrder = hasRedirection(entry)\n    ? areInOrder(entry.startTime, entry.redirectStart, entry.redirectEnd, entry.fetchStart)\n    : true\n\n  return areCommonTimingsInOrder && areRedirectionTimingsInOrder\n}\n\nfunction hasRedirection(entry: RumPerformanceResourceTiming) {\n  return entry.redirectEnd > entry.startTime\n}\nfunction formatTiming(origin: RelativeTime, start: RelativeTime, end: RelativeTime) {\n  if (origin <= start && start <= end) {\n    return {\n      duration: toServerDuration(elapsed(start, end)),\n      start: toServerDuration(elapsed(origin, start)),\n    }\n  }\n}\n\n/**\n * The 'nextHopProtocol' is an empty string for cross-origin resources without CORS headers,\n * meaning the protocol is unknown, and we shouldn't report it.\n * https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/nextHopProtocol#cross-origin_resources\n */\nexport function computeResourceEntryProtocol(entry: RumPerformanceResourceTiming) {\n  return entry.nextHopProtocol === '' ? undefined : entry.nextHopProtocol\n}\n\n/**\n * Handles the 'deliveryType' property to distinguish between supported values ('cache', 'navigational-prefetch'),\n * undefined (unsupported in some browsers), and other cases ('other' for unknown or unrecognized values).\n * see: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType\n */\nexport function computeResourceEntryDeliveryType(entry: RumPerformanceResourceTiming): DeliveryType | undefined {\n  return entry.deliveryType === '' ? 'other' : entry.deliveryType\n}\n\nexport function computeResourceEntrySize(entry: RumPerformanceResourceTiming) {\n  // Make sure a request actually occurred\n  if (entry.startTime < entry.responseStart) {\n    const { encodedBodySize, decodedBodySize, transferSize } = entry\n    return {\n      size: decodedBodySize,\n      encoded_body_size: encodedBodySize,\n      decoded_body_size: decodedBodySize,\n      transfer_size: transferSize,\n    }\n  }\n  return {\n    size: undefined,\n    encoded_body_size: undefined,\n    decoded_body_size: undefined,\n    transfer_size: undefined,\n  }\n}\n\nexport function isAllowedRequestUrl(url: string) {\n  return url && (!isIntakeUrl(url) || isExperimentalFeatureEnabled(ExperimentalFeature.TRACK_INTAKE_REQUESTS))\n}\n\nconst DATA_URL_REGEX = /data:(.+)?(;base64)?,/g\nexport const MAX_RESOURCE_VALUE_CHAR_LENGTH = 24_000\n\nexport function sanitizeIfLongDataUrl(url: string, lengthLimit: number = MAX_RESOURCE_VALUE_CHAR_LENGTH): string {\n  if (url.length <= lengthLimit || !url.startsWith('data:')) {\n    return url\n  }\n  // truncate url first to a random length to prevent match error when the url is too long\n  const dataUrlMatchArray = url.substring(0, 100).match(DATA_URL_REGEX)\n  if (!dataUrlMatchArray) {\n    return url\n  }\n  return `${dataUrlMatchArray[0]}[...]`\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/retrieveInitialDocumentResourceTiming.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { replaceMockable } from '@datadog/browser-core/test'\nimport { createPerformanceEntry, mockDocumentReadyState, mockRumConfiguration } from '../../../test'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport { getNavigationEntry } from '../../browser/performanceUtils'\nimport { FAKE_INITIAL_DOCUMENT } from './resourceUtils'\nimport { retrieveInitialDocumentResourceTiming } from './retrieveInitialDocumentResourceTiming'\n\ndescribe('rum initial document resource', () => {\n  it('creates a resource timing for the initial document', (done) => {\n    retrieveInitialDocumentResourceTiming(mockRumConfiguration(), (timing) => {\n      expect(timing.entryType).toBe('resource')\n      expect(timing.initiatorType).toBe(FAKE_INITIAL_DOCUMENT)\n      expect(timing.duration).toBeGreaterThan(0)\n\n      // generate a performance entry like structure\n      const toJsonTiming = timing.toJSON()\n      expect(toJsonTiming.entryType).toEqual(timing.entryType)\n      expect(toJsonTiming.duration).toEqual(timing.duration)\n      expect((toJsonTiming as any).toJSON).toBeUndefined()\n      done()\n    })\n  })\n\n  it('waits until the document is interactive to notify the resource', () => {\n    const { triggerOnDomLoaded } = mockDocumentReadyState()\n    const spy = jasmine.createSpy()\n    retrieveInitialDocumentResourceTiming(mockRumConfiguration(), spy)\n    expect(spy).not.toHaveBeenCalled()\n    triggerOnDomLoaded()\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('uses the responseEnd to define the resource duration', (done) => {\n    replaceMockable(getNavigationEntry, () =>\n      createPerformanceEntry(RumPerformanceEntryType.NAVIGATION, {\n        responseEnd: 100 as RelativeTime,\n        duration: 200 as RelativeTime,\n      })\n    )\n\n    retrieveInitialDocumentResourceTiming(mockRumConfiguration(), (timing) => {\n      expect(timing.duration).toBe(100 as RelativeTime)\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/retrieveInitialDocumentResourceTiming.ts",
    "content": "import { mockable, runOnReadyState } from '@datadog/browser-core'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport type { RumPerformanceResourceTiming } from '../../browser/performanceObservable'\nimport type { RumConfiguration } from '../configuration'\nimport { getDocumentTraceId } from '../tracing/getDocumentTraceId'\nimport { getNavigationEntry } from '../../browser/performanceUtils'\nimport { FAKE_INITIAL_DOCUMENT } from './resourceUtils'\n\nexport function retrieveInitialDocumentResourceTiming(\n  configuration: RumConfiguration,\n  callback: (timing: RumPerformanceResourceTiming) => void\n) {\n  runOnReadyState(configuration, 'interactive', () => {\n    const navigationEntry = mockable(getNavigationEntry)()\n    const entry: RumPerformanceResourceTiming = Object.assign(navigationEntry.toJSON(), {\n      entryType: RumPerformanceEntryType.RESOURCE as const,\n      initiatorType: FAKE_INITIAL_DOCUMENT,\n      // The ResourceTiming duration entry should be `responseEnd - startTime`. With\n      // NavigationTiming entries, `startTime` is always 0, so set it to `responseEnd`.\n      duration: navigationEntry.responseEnd,\n      traceId: getDocumentTraceId(document),\n      toJSON: () => ({ ...entry, toJSON: undefined }),\n    })\n    callback(entry)\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/trackManualResources.spec.ts",
    "content": "import type { Duration, ServerDuration } from '@datadog/browser-core'\nimport { ResourceType } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock } from '@datadog/browser-core/test'\nimport { collectAndValidateRawRumEvents } from '../../../test'\nimport type { RawRumResourceEvent, RawRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport { type RawRumEventCollectedData, LifeCycle } from '../lifeCycle'\nimport { startEventTracker } from '../eventTracker'\nimport type { ManualResourceData } from './trackManualResources'\nimport { trackManualResources } from './trackManualResources'\n\ndescribe('trackManualResources', () => {\n  let lifeCycle: LifeCycle\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>>\n  let startResource: ReturnType<typeof trackManualResources>['startResource']\n  let stopResource: ReturnType<typeof trackManualResources>['stopResource']\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    lifeCycle = new LifeCycle()\n\n    const resourceTracker = startEventTracker<ManualResourceData>(lifeCycle)\n    const manualResources = trackManualResources(lifeCycle, resourceTracker)\n    startResource = manualResources.startResource\n    stopResource = manualResources.stopResource\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n  })\n\n  describe('basic functionality', () => {\n    it('should create resource with duration from url-based tracking', () => {\n      startResource('https://api.example.com/data')\n      clock.tick(500)\n      stopResource('https://api.example.com/data')\n\n      expect(rawRumEvents).toHaveSize(1)\n      expect(rawRumEvents[0].duration).toBe(500 as Duration)\n      expect(rawRumEvents[0].rawRumEvent).toEqual(\n        jasmine.objectContaining({\n          type: RumEventType.RESOURCE,\n          resource: jasmine.objectContaining({\n            url: 'https://api.example.com/data',\n            type: ResourceType.OTHER,\n          }),\n        })\n      )\n    })\n\n    it('should include duration in server format', () => {\n      startResource('https://api.example.com/data')\n      clock.tick(500)\n      stopResource('https://api.example.com/data')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.duration).toBe((500 * 1e6) as ServerDuration)\n    })\n  })\n\n  describe('resource types', () => {\n    it('should default to \"other\" type when not specified', () => {\n      startResource('https://api.example.com/data')\n      stopResource('https://api.example.com/data')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.type).toBe(ResourceType.OTHER)\n    })\n    ;[ResourceType.XHR, ResourceType.FETCH, ResourceType.IMAGE, ResourceType.JS, ResourceType.CSS].forEach(\n      (resourceType) => {\n        it(`should support ${resourceType} resource type`, () => {\n          startResource('https://api.example.com/data', { type: resourceType })\n          stopResource('https://api.example.com/data')\n\n          expect(rawRumEvents).toHaveSize(1)\n          const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n          expect(resourceEvent.resource.type).toBe(resourceType)\n        })\n      }\n    )\n\n    it('should override start type with stop type', () => {\n      startResource('https://api.example.com/data', { type: ResourceType.XHR })\n      stopResource('https://api.example.com/data', { type: ResourceType.FETCH })\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.type).toBe(ResourceType.FETCH)\n    })\n\n    it('should preserve start type when stop does not provide a type', () => {\n      startResource('https://api.example.com/data', { type: ResourceType.IMAGE })\n      stopResource('https://api.example.com/data')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.type).toBe(ResourceType.IMAGE)\n    })\n  })\n\n  describe('method and status_code', () => {\n    it('should include method and status_code when provided', () => {\n      startResource('https://api.example.com/data', { method: 'POST' })\n      stopResource('https://api.example.com/data', { statusCode: 200 })\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.method).toBe('POST')\n      expect(resourceEvent.resource.status_code).toBe(200)\n    })\n  })\n\n  describe('size', () => {\n    it('should include size when provided at stop', () => {\n      startResource('https://api.example.com/data')\n      stopResource('https://api.example.com/data', { size: 1234 })\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.size).toBe(1234)\n    })\n\n    it('should leave size undefined when not provided', () => {\n      startResource('https://api.example.com/data')\n      stopResource('https://api.example.com/data')\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.resource.size).toBeUndefined()\n    })\n  })\n\n  describe('resourceKey', () => {\n    it('should support resourceKey for tracking same url multiple times', () => {\n      startResource('https://api.example.com/data', { resourceKey: 'request1' })\n      startResource('https://api.example.com/data', { resourceKey: 'request2' })\n\n      clock.tick(100)\n      stopResource('https://api.example.com/data', { resourceKey: 'request2' })\n\n      clock.tick(100)\n      stopResource('https://api.example.com/data', { resourceKey: 'request1' })\n\n      expect(rawRumEvents).toHaveSize(2)\n      expect(rawRumEvents[0].duration).toBe(100 as Duration)\n      expect(rawRumEvents[1].duration).toBe(200 as Duration)\n    })\n\n    it('should not collide between url and resourceKey', () => {\n      startResource('https://api.example.com/foo/bar')\n      startResource('https://api.example.com/foo', { resourceKey: 'bar' })\n\n      stopResource('https://api.example.com/foo/bar')\n      stopResource('https://api.example.com/foo', { resourceKey: 'bar' })\n\n      expect(rawRumEvents).toHaveSize(2)\n      expect((rawRumEvents[0].rawRumEvent as RawRumResourceEvent).resource.url).toBe('https://api.example.com/foo/bar')\n      expect((rawRumEvents[1].rawRumEvent as RawRumResourceEvent).resource.url).toBe('https://api.example.com/foo')\n    })\n  })\n\n  describe('context merging', () => {\n    it('should merge contexts from start and stop', () => {\n      startResource('https://api.example.com/data', { context: { startKey: 'value1' } })\n      stopResource('https://api.example.com/data', { context: { stopKey: 'value2' } })\n\n      expect(rawRumEvents).toHaveSize(1)\n      const resourceEvent = rawRumEvents[0].rawRumEvent as RawRumResourceEvent\n      expect(resourceEvent.context).toEqual({\n        startKey: 'value1',\n        stopKey: 'value2',\n      })\n    })\n  })\n\n  describe('invalid URL handling', () => {\n    it('should handle stopping with undefined URL but valid resourceKey', () => {\n      startResource('https://api.example.com/data', { resourceKey: 'key1' })\n      stopResource(undefined as any, { resourceKey: 'key1' })\n\n      expect(rawRumEvents).toHaveSize(1)\n      expect((rawRumEvents[0].rawRumEvent as RawRumResourceEvent).resource.url).toBe('https://api.example.com/data')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/resource/trackManualResources.ts",
    "content": "import type { Context, ResourceType } from '@datadog/browser-core'\nimport { clocksNow, elapsed, ResourceType as ResourceTypeEnum, toServerDuration } from '@datadog/browser-core'\nimport type { RawRumResourceEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { EventTracker } from '../eventTracker'\nimport { sanitizeIfLongDataUrl } from './resourceUtils'\n\nexport interface ResourceOptions {\n  /**\n   * Resource type\n   *\n   * @default 'other'\n   */\n  type?: ResourceType\n\n  /**\n   * HTTP method\n   */\n  method?: string\n\n  /**\n   * Resource context\n   */\n  context?: Context\n\n  /**\n   * Resource key\n   */\n  resourceKey?: string\n}\n\nexport interface ResourceStopOptions {\n  /**\n   * Resource type\n   */\n  type?: ResourceType\n\n  /**\n   * HTTP status code\n   */\n  statusCode?: number\n\n  /**\n   * Resource size in bytes\n   */\n  size?: number\n\n  /**\n   * Resource context\n   */\n  context?: Context\n\n  /**\n   * Resource key\n   */\n  resourceKey?: string\n}\n\nexport interface ManualResourceData {\n  url: string\n  type?: ResourceType\n  method?: string\n  context?: Context\n}\n\nexport function trackManualResources(lifeCycle: LifeCycle, resourceTracker: EventTracker<ManualResourceData>) {\n  function startManualResource(url: string, options: ResourceOptions = {}, startClocks = clocksNow()) {\n    const lookupKey = options.resourceKey ?? url\n\n    resourceTracker.start(lookupKey, startClocks, {\n      url,\n      ...options,\n    })\n  }\n\n  function stopManualResource(url: string, options: ResourceStopOptions = {}, stopClocks = clocksNow()) {\n    const lookupKey = options.resourceKey ?? url\n\n    const stopped = resourceTracker.stop(lookupKey, stopClocks, {\n      context: options.context,\n      type: options.type,\n    })\n\n    if (!stopped) {\n      return\n    }\n\n    const duration = elapsed(stopped.startClocks.relative, stopClocks.relative)\n\n    const rawRumEvent: RawRumResourceEvent = {\n      date: stopped.startClocks.timeStamp,\n      type: RumEventType.RESOURCE,\n      resource: {\n        id: stopped.id,\n        type: stopped.type || ResourceTypeEnum.OTHER,\n        url: sanitizeIfLongDataUrl(stopped.url),\n        duration: toServerDuration(duration),\n        method: stopped.method,\n        status_code: options.statusCode,\n        size: options.size,\n      },\n      _dd: {},\n      context: stopped.context,\n    }\n\n    lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {\n      rawRumEvent,\n      startClocks: stopped.startClocks,\n      duration,\n      domainContext: { isManual: true },\n    })\n  }\n\n  return {\n    startResource: startManualResource,\n    stopResource: stopManualResource,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/rumSessionManager.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport {\n  STORAGE_POLL_DELAY,\n  SESSION_STORE_KEY,\n  setCookie,\n  stopSessionManager,\n  ONE_SECOND,\n  DOM_EVENT,\n  createTrackingConsentState,\n  TrackingConsent,\n  BridgeCapability,\n} from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport {\n  createNewEvent,\n  expireCookie,\n  getSessionState,\n  mockEventBridge,\n  mockClock,\n  registerCleanupTask,\n} from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../test'\nimport type { RumConfiguration } from './configuration'\n\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport {\n  RUM_SESSION_KEY,\n  RumTrackingType,\n  SessionReplayState,\n  startRumSessionManager,\n  startRumSessionManagerStub,\n} from './rumSessionManager'\n\ndescribe('rum session manager', () => {\n  const DURATION = 123456\n  let lifeCycle: LifeCycle\n  let expireSessionSpy: jasmine.Spy\n  let renewSessionSpy: jasmine.Spy\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    expireSessionSpy = jasmine.createSpy('expireSessionSpy')\n    renewSessionSpy = jasmine.createSpy('renewSessionSpy')\n    lifeCycle = new LifeCycle()\n    lifeCycle.subscribe(LifeCycleEventType.SESSION_EXPIRED, expireSessionSpy)\n    lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, renewSessionSpy)\n\n    registerCleanupTask(() => {\n      // remove intervals first\n      stopSessionManager()\n      // flush pending callbacks to avoid random failures\n      clock.tick(new Date().getTime())\n    })\n  })\n\n  describe('cookie storage', () => {\n    it('when tracked with session replay should store session type and id', () => {\n      startRumSessionManagerWithDefaults({ configuration: { sessionSampleRate: 100, sessionReplaySampleRate: 100 } })\n\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n\n      expect(getSessionState(SESSION_STORE_KEY).id).toMatch(/[a-f0-9-]/)\n      expect(getSessionState(SESSION_STORE_KEY)[RUM_SESSION_KEY]).toBe(RumTrackingType.TRACKED_WITH_SESSION_REPLAY)\n    })\n\n    it('when tracked without session replay should store session type and id', () => {\n      startRumSessionManagerWithDefaults({ configuration: { sessionSampleRate: 100, sessionReplaySampleRate: 0 } })\n\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      expect(getSessionState(SESSION_STORE_KEY).id).toMatch(/[a-f0-9-]/)\n      expect(getSessionState(SESSION_STORE_KEY)[RUM_SESSION_KEY]).toBe(RumTrackingType.TRACKED_WITHOUT_SESSION_REPLAY)\n    })\n\n    it('when not tracked should store session type', () => {\n      startRumSessionManagerWithDefaults({ configuration: { sessionSampleRate: 0 } })\n\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      expect(getSessionState(SESSION_STORE_KEY)[RUM_SESSION_KEY]).toBe(RumTrackingType.NOT_TRACKED)\n      expect(getSessionState(SESSION_STORE_KEY).id).not.toBeDefined()\n      expect(getSessionState(SESSION_STORE_KEY).isExpired).not.toBeDefined()\n    })\n\n    it('when tracked should keep existing session type and id', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION)\n\n      startRumSessionManagerWithDefaults()\n\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      expect(getSessionState(SESSION_STORE_KEY).id).toBe('abcdef')\n      expect(getSessionState(SESSION_STORE_KEY)[RUM_SESSION_KEY]).toBe(RumTrackingType.TRACKED_WITH_SESSION_REPLAY)\n    })\n\n    it('when not tracked should keep existing session type', () => {\n      setCookie(SESSION_STORE_KEY, 'rum=0', DURATION)\n\n      startRumSessionManagerWithDefaults()\n\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      expect(getSessionState(SESSION_STORE_KEY)[RUM_SESSION_KEY]).toBe(RumTrackingType.NOT_TRACKED)\n    })\n\n    it('should renew on activity after expiration', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION)\n\n      startRumSessionManagerWithDefaults({ configuration: { sessionSampleRate: 100, sessionReplaySampleRate: 100 } })\n\n      expireCookie()\n      expect(getSessionState(SESSION_STORE_KEY).isExpired).toBe('1')\n      expect(expireSessionSpy).not.toHaveBeenCalled()\n      expect(renewSessionSpy).not.toHaveBeenCalled()\n      clock.tick(STORAGE_POLL_DELAY)\n\n      document.dispatchEvent(createNewEvent(DOM_EVENT.CLICK))\n\n      expect(expireSessionSpy).toHaveBeenCalled()\n      expect(renewSessionSpy).toHaveBeenCalled()\n      expect(getSessionState(SESSION_STORE_KEY)[RUM_SESSION_KEY]).toBe(RumTrackingType.TRACKED_WITH_SESSION_REPLAY)\n      expect(getSessionState(SESSION_STORE_KEY).id).toMatch(/[a-f0-9-]/)\n    })\n  })\n\n  describe('findSession', () => {\n    it('should return the current session', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION)\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      expect(rumSessionManager.findTrackedSession()!.id).toBe('abcdef')\n    })\n\n    it('should return undefined if the session is not tracked', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=0', DURATION)\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      expect(rumSessionManager.findTrackedSession()).toBe(undefined)\n    })\n\n    it('should return undefined if the session has expired', () => {\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      expireCookie()\n      clock.tick(STORAGE_POLL_DELAY)\n      expect(rumSessionManager.findTrackedSession()).toBe(undefined)\n    })\n\n    it('should return session corresponding to start time', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION)\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      clock.tick(10 * ONE_SECOND)\n      expireCookie()\n      clock.tick(STORAGE_POLL_DELAY)\n      expect(rumSessionManager.findTrackedSession()).toBeUndefined()\n      expect(rumSessionManager.findTrackedSession(0 as RelativeTime)!.id).toBe('abcdef')\n    })\n\n    it('should return session TRACKED_WITH_SESSION_REPLAY', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=1', DURATION)\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.SAMPLED)\n    })\n\n    it('should return session TRACKED_WITHOUT_SESSION_REPLAY', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=2', DURATION)\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.OFF)\n    })\n\n    it('should update current entity when replay recording is forced', () => {\n      setCookie(SESSION_STORE_KEY, 'id=abcdef&rum=2', DURATION)\n      const rumSessionManager = startRumSessionManagerWithDefaults()\n      rumSessionManager.setForcedReplay()\n\n      expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(SessionReplayState.FORCED)\n    })\n  })\n\n  describe('session behaviors', () => {\n    ;[\n      {\n        description: 'TRACKED_WITH_SESSION_REPLAY should have replay',\n        sessionReplaySampleRate: 100,\n        expectSessionReplay: SessionReplayState.SAMPLED,\n      },\n      {\n        description: 'TRACKED_WITHOUT_SESSION_REPLAY should have no replay',\n        sessionReplaySampleRate: 0,\n        expectSessionReplay: SessionReplayState.OFF,\n      },\n    ].forEach(\n      ({\n        description,\n        sessionReplaySampleRate,\n        expectSessionReplay,\n      }: {\n        description: string\n        sessionReplaySampleRate: number\n        expectSessionReplay: SessionReplayState\n      }) => {\n        it(description, () => {\n          const rumSessionManager = startRumSessionManagerWithDefaults({\n            configuration: { sessionSampleRate: 100, sessionReplaySampleRate },\n          })\n          expect(rumSessionManager.findTrackedSession()!.sessionReplay).toBe(expectSessionReplay)\n        })\n      }\n    )\n  })\n\n  function startRumSessionManagerWithDefaults({ configuration }: { configuration?: Partial<RumConfiguration> } = {}) {\n    return startRumSessionManager(\n      mockRumConfiguration({\n        sessionSampleRate: 50,\n        sessionReplaySampleRate: 50,\n        trackResources: true,\n        trackLongTasks: true,\n        ...configuration,\n      }),\n      lifeCycle,\n      createTrackingConsentState(TrackingConsent.GRANTED)\n    )\n  }\n})\n\ndescribe('rum session manager stub', () => {\n  it('should return a tracked session with replay allowed when the event bridge support records', () => {\n    mockEventBridge({ capabilities: [BridgeCapability.RECORDS] })\n    expect(startRumSessionManagerStub().findTrackedSession()!.sessionReplay).toEqual(SessionReplayState.SAMPLED)\n  })\n\n  it('should return a tracked session without replay allowed when the event bridge support records', () => {\n    mockEventBridge({ capabilities: [] })\n    expect(startRumSessionManagerStub().findTrackedSession()!.sessionReplay).toEqual(SessionReplayState.OFF)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/rumSessionManager.ts",
    "content": "import type { RelativeTime, TrackingConsentState } from '@datadog/browser-core'\nimport {\n  BridgeCapability,\n  Observable,\n  SESSION_NOT_TRACKED,\n  bridgeSupports,\n  noop,\n  performDraw,\n  startSessionManager,\n} from '@datadog/browser-core'\nimport type { RumConfiguration } from './configuration'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\n\nexport const enum SessionType {\n  SYNTHETICS = 'synthetics',\n  USER = 'user',\n  CI_TEST = 'ci_test',\n}\n\nexport const RUM_SESSION_KEY = 'rum'\n\nexport interface RumSessionManager {\n  findTrackedSession: (startTime?: RelativeTime) => RumSession | undefined\n  expire: () => void\n  expireObservable: Observable<void>\n  setForcedReplay: () => void\n}\n\nexport interface RumSession {\n  id: string\n  sessionReplay: SessionReplayState\n  anonymousId?: string\n}\n\nexport const enum RumTrackingType {\n  NOT_TRACKED = SESSION_NOT_TRACKED,\n  TRACKED_WITH_SESSION_REPLAY = '1',\n  TRACKED_WITHOUT_SESSION_REPLAY = '2',\n}\n\nexport const enum SessionReplayState {\n  OFF,\n  SAMPLED,\n  FORCED,\n}\n\nexport function startRumSessionManager(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  trackingConsentState: TrackingConsentState\n): RumSessionManager {\n  const sessionManager = startSessionManager(\n    configuration,\n    RUM_SESSION_KEY,\n    (rawTrackingType) => computeTrackingType(configuration, rawTrackingType),\n    trackingConsentState\n  )\n\n  sessionManager.expireObservable.subscribe(() => {\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n  })\n\n  sessionManager.renewObservable.subscribe(() => {\n    lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n  })\n\n  sessionManager.sessionStateUpdateObservable.subscribe(({ previousState, newState }) => {\n    if (!previousState.forcedReplay && newState.forcedReplay) {\n      const sessionEntity = sessionManager.findSession()\n      if (sessionEntity) {\n        sessionEntity.isReplayForced = true\n      }\n    }\n  })\n  return {\n    findTrackedSession: (startTime) => {\n      const session = sessionManager.findSession(startTime)\n      if (!session || session.trackingType === RumTrackingType.NOT_TRACKED) {\n        return\n      }\n      return {\n        id: session.id,\n        sessionReplay:\n          session.trackingType === RumTrackingType.TRACKED_WITH_SESSION_REPLAY\n            ? SessionReplayState.SAMPLED\n            : session.isReplayForced\n              ? SessionReplayState.FORCED\n              : SessionReplayState.OFF,\n        anonymousId: session.anonymousId,\n      }\n    },\n    expire: sessionManager.expire,\n    expireObservable: sessionManager.expireObservable,\n    setForcedReplay: () => sessionManager.updateSessionState({ forcedReplay: '1' }),\n  }\n}\n\n/**\n * Start a tracked replay session stub\n */\nexport function startRumSessionManagerStub(): RumSessionManager {\n  const session: RumSession = {\n    id: '00000000-aaaa-0000-aaaa-000000000000',\n    sessionReplay: bridgeSupports(BridgeCapability.RECORDS) ? SessionReplayState.SAMPLED : SessionReplayState.OFF,\n  }\n  return {\n    findTrackedSession: () => session,\n    expire: noop,\n    expireObservable: new Observable(),\n    setForcedReplay: noop,\n  }\n}\n\nfunction computeTrackingType(configuration: RumConfiguration, rawTrackingType?: string) {\n  if (hasValidRumSession(rawTrackingType)) {\n    return rawTrackingType\n  }\n  if (!performDraw(configuration.sessionSampleRate)) {\n    return RumTrackingType.NOT_TRACKED\n  }\n  if (!performDraw(configuration.sessionReplaySampleRate)) {\n    return RumTrackingType.TRACKED_WITHOUT_SESSION_REPLAY\n  }\n  return RumTrackingType.TRACKED_WITH_SESSION_REPLAY\n}\n\nfunction hasValidRumSession(trackingType?: string): trackingType is RumTrackingType {\n  return (\n    trackingType === RumTrackingType.NOT_TRACKED ||\n    trackingType === RumTrackingType.TRACKED_WITH_SESSION_REPLAY ||\n    trackingType === RumTrackingType.TRACKED_WITHOUT_SESSION_REPLAY\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/sampler/sampler.spec.ts",
    "content": "import { isSampled, resetSampleDecisionCache, sampleUsingKnuthFactor } from './sampler'\n\n// UUID known to yield a low hash value using the Knuth formula, making it more likely to be sampled\nconst LOW_HASH_UUID = '29a4b5e3-9859-4290-99fa-4bc4a1a348b9'\n// UUID known to yield a high hash value using the Knuth formula, making it less likely to be\n// sampled\nconst HIGH_HASH_UUID = '5321b54a-d6ec-4b24-996d-dd70c617e09a'\n\n// UUID chosen arbitrarily, to be used when the test doesn't actually depend on it.\nconst ARBITRARY_UUID = '1ff81c8c-6e32-473b-869b-55af08048323'\n\ndescribe('isSampled', () => {\n  beforeEach(() => {\n    resetSampleDecisionCache()\n  })\n\n  it('returns true when sampleRate is 100', () => {\n    expect(isSampled(ARBITRARY_UUID, 100)).toBeTrue()\n  })\n\n  it('returns false when sampleRate is 0', () => {\n    expect(isSampled(ARBITRARY_UUID, 0)).toBeFalse()\n  })\n\n  describe('with bigint support', () => {\n    beforeEach(() => {\n      if (!window.BigInt) {\n        pending('BigInt is not supported')\n      }\n    })\n\n    it('a session id with a low hash value should be sampled with a rate close to 0%', () => {\n      expect(isSampled(LOW_HASH_UUID, 0.1)).toBeTrue()\n      resetSampleDecisionCache()\n      expect(isSampled(LOW_HASH_UUID, 0.01)).toBeTrue()\n      resetSampleDecisionCache()\n      expect(isSampled(LOW_HASH_UUID, 0.001)).toBeTrue()\n      resetSampleDecisionCache()\n      expect(isSampled(LOW_HASH_UUID, 0.0001)).toBeTrue()\n      resetSampleDecisionCache()\n      // At some point the sample rate is so low that the session is not sampled even if the hash\n      // is low. This is not an error: we can probably find a UUID with an even lower hash.\n      expect(isSampled(LOW_HASH_UUID, 0.0000000001)).toBeFalse()\n    })\n\n    it('a session id with a high hash value should not be sampled even if the rate is close to 100%', () => {\n      expect(isSampled(HIGH_HASH_UUID, 99.9)).toBeFalse()\n      resetSampleDecisionCache()\n      expect(isSampled(HIGH_HASH_UUID, 99.99)).toBeFalse()\n      resetSampleDecisionCache()\n      expect(isSampled(HIGH_HASH_UUID, 99.999)).toBeFalse()\n      resetSampleDecisionCache()\n      expect(isSampled(HIGH_HASH_UUID, 99.9999)).toBeFalse()\n      resetSampleDecisionCache()\n      // At some point the sample rate is so high that the session is sampled even if the hash is\n      // high. This is not an error: we can probably find a UUID with an even higher hash.\n      expect(isSampled(HIGH_HASH_UUID, 99.9999999999)).toBeTrue()\n    })\n  })\n\n  describe('without bigint support', () => {\n    beforeEach(() => {\n      // @ts-expect-error BigInt might not be defined depending on the browser where we execute\n      // the tests\n      if (window.BigInt) {\n        pending('BigInt is supported')\n      }\n    })\n\n    it('sampling decision should be cached', () => {\n      spyOn(Math, 'random').and.returnValues(0.2, 0.8)\n      expect(isSampled(ARBITRARY_UUID, 50)).toBeTrue()\n      expect(isSampled(ARBITRARY_UUID, 50)).toBeTrue()\n    })\n  })\n})\n\ndescribe('sampleUsingKnuthFactor', () => {\n  beforeEach(() => {\n    if (!window.BigInt) {\n      pending('BigInt is not supported')\n    }\n  })\n\n  it('sampling should be based on the trace id', () => {\n    // Generated using the dd-trace-go implementation with the following program: https://go.dev/play/p/CUrDJtze8E_e\n    const inputs: Array<[bigint, number, boolean]> = [\n      [BigInt('5577006791947779410'), 94.0509, true],\n      [BigInt('15352856648520921629'), 43.7714, true],\n      [BigInt('3916589616287113937'), 68.6823, true],\n      [BigInt('894385949183117216'), 30.0912, true],\n      [BigInt('12156940908066221323'), 46.889, true],\n\n      [BigInt('9828766684487745566'), 15.6519, false],\n      [BigInt('4751997750760398084'), 81.364, false],\n      [BigInt('11199607447739267382'), 38.0657, false],\n      [BigInt('6263450610539110790'), 21.8553, false],\n      [BigInt('1874068156324778273'), 36.0871, false],\n    ]\n\n    for (const [identifier, sampleRate, expected] of inputs) {\n      expect(sampleUsingKnuthFactor(identifier, sampleRate))\n        .withContext(`identifier=${identifier}, sampleRate=${sampleRate}`)\n        .toBe(expected)\n    }\n  })\n\n  it('should cache sampling decision per sampling rate', () => {\n    // For the same session id, the sampling decision should be different for trace and profiling, eg. trace should not cache profiling decisions and vice versa\n    expect(isSampled(HIGH_HASH_UUID, 99.9999999999)).toBeTrue()\n    expect(isSampled(HIGH_HASH_UUID, 0.0000001)).toBeFalse()\n    expect(isSampled(HIGH_HASH_UUID, 99.9999999999)).toBeTrue()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/sampler/sampler.ts",
    "content": "import { performDraw } from '@datadog/browser-core'\n\nconst sampleDecisionCache: Map<number, { sessionId: string; decision: boolean }> = new Map()\n\nexport function isSampled(sessionId: string, sampleRate: number) {\n  // Shortcuts for common cases. This is not strictly necessary, but it makes the code faster for\n  // customers willing to ingest all traces.\n  if (sampleRate === 100) {\n    return true\n  }\n\n  if (sampleRate === 0) {\n    return false\n  }\n\n  const cachedDecision = sampleDecisionCache.get(sampleRate)\n  if (cachedDecision && sessionId === cachedDecision.sessionId) {\n    return cachedDecision.decision\n  }\n\n  let decision: boolean\n  // @ts-expect-error BigInt might not be defined in every browser we support\n  if (window.BigInt) {\n    decision = sampleUsingKnuthFactor(BigInt(`0x${sessionId.split('-')[4]}`), sampleRate)\n  } else {\n    // For simplicity, we don't use consistent sampling for browser without BigInt support\n    // TODO: remove this when all browser we support have BigInt support\n    decision = performDraw(sampleRate)\n  }\n  sampleDecisionCache.set(sampleRate, { sessionId, decision })\n  return decision\n}\n\n// Exported for tests\nexport function resetSampleDecisionCache() {\n  sampleDecisionCache.clear()\n}\n\n/**\n * Perform sampling using the Knuth factor method. This method offer consistent sampling result\n * based on the provided identifier.\n *\n * @param identifier - The identifier to use for sampling.\n * @param sampleRate - The sample rate in percentage between 0 and 100.\n */\nexport function sampleUsingKnuthFactor(identifier: bigint, sampleRate: number) {\n  // The formula is:\n  //\n  //   (identifier * knuthFactor) % 2^64 < sampleRate * 2^64\n  //\n  // Because JavaScript numbers are 64-bit floats, we can't represent 64-bit integers, and the\n  // modulo would be incorrect. Thus, we are using BigInts here.\n  //\n  // Implementation in other languages:\n  // * Go     https://github.com/DataDog/dd-trace-go/blob/ec6fbb1f2d517b7b8e69961052adf7136f3af773/ddtrace/tracer/sampler.go#L86-L91\n  // * Python https://github.com/DataDog/dd-trace-py/blob/0cee2f066fb6e79aa15947c1514c0f406dea47c5/ddtrace/sampling_rule.py#L197\n  // * Ruby   https://github.com/DataDog/dd-trace-rb/blob/1a6e255cdcb7e7e22235ea5955f90f6dfa91045d/lib/datadog/tracing/sampling/rate_sampler.rb#L42\n  // * C++    https://github.com/DataDog/dd-trace-cpp/blob/159629edc438ae45f2bb318eb7bd51abd05e94b5/src/datadog/trace_sampler.cpp#L58\n  // * Java   https://github.com/DataDog/dd-trace-java/blob/896dd6b380533216e0bdee59614606c8272d313e/dd-trace-core/src/main/java/datadog/trace/common/sampling/DeterministicSampler.java#L48\n  //\n  // Note: All implementations have slight variations. Some of them use '<=' instead of '<', and\n  // use `sampleRate * 2^64 - 1` instead of `sampleRate * 2^64`. The following implementation\n  // should adhere to the spec and is a bit simpler than using a 2^64-1 limit as there are less\n  // BigInt arithmetic to write. In practice this does not matter, as we are using floating point\n  // numbers in the end, and Number(2n**64n-1n) === Number(2n**64n).\n  const knuthFactor = BigInt('1111111111111111111')\n  const twoPow64 = BigInt('0x10000000000000000') // 2n ** 64n\n  const hash = (identifier * knuthFactor) % twoPow64\n  return Number(hash) <= (sampleRate / 100) * Number(twoPow64)\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/startCustomerDataTelemetry.spec.ts",
    "content": "import type { FlushEvent, Context, Telemetry } from '@datadog/browser-core'\nimport { Observable } from '@datadog/browser-core'\nimport type { Clock, MockTelemetry } from '@datadog/browser-core/test'\nimport { mockClock, startMockTelemetry } from '@datadog/browser-core/test'\nimport type { AssembledRumEvent } from '../rawRumEvent.types'\nimport { RumEventType } from '../rawRumEvent.types'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport { MEASURES_PERIOD_DURATION, startCustomerDataTelemetry } from './startCustomerDataTelemetry'\n\ndescribe('customerDataTelemetry', () => {\n  let clock: Clock\n  let batchFlushObservable: Observable<FlushEvent>\n  let telemetry: MockTelemetry\n  let fakeContextBytesCount: number\n  let lifeCycle: LifeCycle\n  const viewEvent = { type: RumEventType.VIEW } as AssembledRumEvent\n\n  function generateBatch({\n    eventNumber,\n    batchBytesCount = 1,\n    contextBytesCount = fakeContextBytesCount,\n  }: {\n    eventNumber: number\n    eventType?: RumEventType | 'Telemetry'\n    batchBytesCount?: number\n    contextBytesCount?: number\n    context?: Context\n  }) {\n    fakeContextBytesCount = contextBytesCount\n\n    for (let index = 0; index < eventNumber; index++) {\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, viewEvent)\n    }\n    batchFlushObservable.notify({\n      reason: 'duration_limit',\n      bytesCount: batchBytesCount,\n      messagesCount: eventNumber,\n    })\n  }\n\n  function setupCustomerTelemetryCollection(metricsEnabled: boolean = true) {\n    batchFlushObservable = new Observable()\n    lifeCycle = new LifeCycle()\n    fakeContextBytesCount = 1\n\n    telemetry = startMockTelemetry()\n\n    startCustomerDataTelemetry({ metricsEnabled } as Telemetry, lifeCycle, batchFlushObservable)\n  }\n\n  beforeEach(() => {\n    clock = mockClock()\n  })\n\n  it('should collect customer data telemetry', async () => {\n    setupCustomerTelemetryCollection()\n\n    generateBatch({ eventNumber: 10, contextBytesCount: 10, batchBytesCount: 10 })\n    generateBatch({ eventNumber: 1, contextBytesCount: 1, batchBytesCount: 1 })\n    clock.tick(MEASURES_PERIOD_DURATION)\n\n    expect(await telemetry.getEvents()).toEqual([\n      jasmine.objectContaining({\n        type: 'log',\n        status: 'debug',\n        message: 'Customer data measures',\n        batchCount: 2,\n        batchBytesCount: { min: 1, max: 10, sum: 11 },\n        batchMessagesCount: { min: 1, max: 10, sum: 11 },\n      }),\n    ])\n  })\n\n  it('should collect customer data only if batches contains rum events, no just telemetry', async () => {\n    setupCustomerTelemetryCollection()\n\n    // Generate an initial batch with no RUM events. We should not generate any customer\n    // data telemetry.\n    batchFlushObservable.notify({ reason: 'duration_limit', bytesCount: 1, messagesCount: 1 })\n    clock.tick(MEASURES_PERIOD_DURATION)\n    expect(await telemetry.hasEvents()).toBe(false)\n\n    // Generate a batch with RUM events. We should generate customer data telemetry for\n    // this batch.\n    generateBatch({ eventNumber: 10, contextBytesCount: 10, batchBytesCount: 10 })\n    clock.tick(MEASURES_PERIOD_DURATION)\n    expect(await telemetry.getEvents()).toEqual([\n      jasmine.objectContaining({\n        type: 'log',\n        status: 'debug',\n        message: 'Customer data measures',\n        batchCount: 1,\n        batchBytesCount: { min: 10, max: 10, sum: 10 },\n        batchMessagesCount: { min: 10, max: 10, sum: 10 },\n      }),\n    ])\n    telemetry.reset()\n\n    // Generate another batch with no RUM events. We should not generate any customer data\n    // telemetry.\n    batchFlushObservable.notify({ reason: 'duration_limit', bytesCount: 1, messagesCount: 1 })\n    clock.tick(MEASURES_PERIOD_DURATION)\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n\n  it('should not collect contexts telemetry of a unfinished batches', async () => {\n    setupCustomerTelemetryCollection()\n\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, viewEvent)\n    batchFlushObservable.notify({ reason: 'duration_limit', bytesCount: 1, messagesCount: 1 })\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, viewEvent)\n    clock.tick(MEASURES_PERIOD_DURATION)\n\n    expect(await telemetry.getEvents()).toEqual([\n      jasmine.objectContaining({\n        batchMessagesCount: jasmine.objectContaining({ sum: 1 }),\n      }),\n    ])\n  })\n\n  it('should not collect customer data telemetry when telemetry disabled', async () => {\n    setupCustomerTelemetryCollection(false)\n\n    generateBatch({ eventNumber: 1 })\n    clock.tick(MEASURES_PERIOD_DURATION)\n\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/startCustomerDataTelemetry.ts",
    "content": "import type { Context, FlushEvent, Observable, Telemetry } from '@datadog/browser-core'\nimport { ONE_SECOND, addTelemetryMetrics, setInterval, TelemetryMetrics } from '@datadog/browser-core'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\n\nexport const MEASURES_PERIOD_DURATION = 10 * ONE_SECOND\n\ninterface Measure extends Context {\n  min: number\n  max: number\n  sum: number\n}\n\ninterface CurrentPeriodMeasures extends Context {\n  batchCount: number\n  batchBytesCount: Measure\n  batchMessagesCount: Measure\n}\n\nlet currentPeriodMeasures: CurrentPeriodMeasures\nlet batchHasRumEvent: boolean\n\nexport function startCustomerDataTelemetry(\n  telemetry: Telemetry,\n  lifeCycle: LifeCycle,\n  batchFlushObservable: Observable<FlushEvent>\n) {\n  if (!telemetry.metricsEnabled) {\n    return\n  }\n\n  initCurrentPeriodMeasures()\n  batchHasRumEvent = false\n  // We measure the data of every view updates even if there could only be one per batch due to the upsert\n  // It means that contexts bytes count sums can be higher than it really is\n  lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, () => {\n    batchHasRumEvent = true\n  })\n\n  batchFlushObservable.subscribe(({ bytesCount, messagesCount }) => {\n    // Don't measure batch that only contains telemetry events to avoid batch sending loop\n    // It could happen because after each batch we are adding a customer data measures telemetry event to the next one\n    if (!batchHasRumEvent) {\n      return\n    }\n    batchHasRumEvent = false\n\n    currentPeriodMeasures.batchCount += 1\n    updateMeasure(currentPeriodMeasures.batchBytesCount, bytesCount)\n    updateMeasure(currentPeriodMeasures.batchMessagesCount, messagesCount)\n  })\n\n  setInterval(sendCurrentPeriodMeasures, MEASURES_PERIOD_DURATION)\n}\n\nfunction sendCurrentPeriodMeasures() {\n  if (currentPeriodMeasures.batchCount === 0) {\n    return\n  }\n\n  // monitor-until: forever\n  addTelemetryMetrics(TelemetryMetrics.CUSTOMER_DATA_METRIC_NAME, currentPeriodMeasures)\n  initCurrentPeriodMeasures()\n}\n\nfunction createMeasure(): Measure {\n  return { min: Infinity, max: 0, sum: 0 }\n}\n\nfunction updateMeasure(measure: Measure, value: number) {\n  measure.sum += value\n  measure.min = Math.min(measure.min, value)\n  measure.max = Math.max(measure.max, value)\n}\n\nfunction initCurrentPeriodMeasures() {\n  currentPeriodMeasures = {\n    batchCount: 0,\n    batchBytesCount: createMeasure(),\n    batchMessagesCount: createMeasure(),\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/getDocumentTraceId.spec.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport {\n  createDocumentTraceData,\n  findTraceComment,\n  getDocumentTraceDataFromMeta,\n  getDocumentTraceId,\n  INITIAL_DOCUMENT_OUTDATED_TRACE_ID_THRESHOLD,\n} from './getDocumentTraceId'\n\nconst HTML_DOCTYPE = '\\n<!DOCTYPE html>\\n'\nconst HTML_CONTENT = '\\n<html><head></head><body></body></html>\\n'\n\ndescribe('getDocumentTraceId', () => {\n  it('gets a trace id found from a document comment', () => {\n    expect(\n      getDocumentTraceId(\n        createDocument(\n          `<!-- DATADOG;trace-id=foo;trace-time=${Date.now()} -->\n          ${HTML_DOCTYPE}\n          <html>\n            <head>\n            </head>\n            <body>\n            </body>\n          </html>`\n        )\n      )\n    ).toEqual('foo')\n  })\n\n  it('gets a trace id found from meta tags', () => {\n    expect(\n      getDocumentTraceId(\n        createDocument(\n          `${HTML_DOCTYPE}\n          <html>\n            <head>\n              <meta name=\"dd-trace-id\" content=\"foo\" />\n              <meta name=\"dd-trace-time\" content=\"${Date.now()}\" />\n            </head>\n            <body>\n            </body>\n          </html>`\n        )\n      )\n    ).toEqual('foo')\n  })\n\n  it('uses the meta strategy in priority', () => {\n    expect(\n      getDocumentTraceId(\n        createDocument(\n          `<!-- DATADOG;trace-id=comment;trace-time=${Date.now()} -->\n          ${HTML_DOCTYPE}\n          <html>\n            <head>\n              <meta name=\"dd-trace-id\" content=\"meta\" />\n              <meta name=\"dd-trace-time\" content=\"${Date.now()}\" />\n            </head>\n            <body>\n            </body>\n          </html>`\n        )\n      )\n    ).toEqual('meta')\n  })\n\n  it('returns undefined if nothing is present', () => {\n    expect(getDocumentTraceId(createDocument(HTML_DOCTYPE + HTML_CONTENT))).toEqual(undefined)\n  })\n\n  it('ignores the trace id if it has been created too long ago', () => {\n    expect(\n      getDocumentTraceId(\n        createDocument(`<!-- DATADOG;trace-id=foo;trace-time=${\n          Date.now() - INITIAL_DOCUMENT_OUTDATED_TRACE_ID_THRESHOLD\n        } -->\n          ${HTML_DOCTYPE}\n          <html>\n            <head>\n            </head>\n            <body>\n            </body>\n          </html>`)\n      )\n    ).toBe(undefined)\n  })\n})\n\ndescribe('getDocumentTraceDataFromMeta', () => {\n  it('gets data from meta', () => {\n    expect(\n      getDocumentTraceDataFromMeta(\n        createDocument(\n          `${HTML_DOCTYPE}\n          <html>\n            <head>\n              <meta name=\"dd-trace-id\" content=\"123\" />\n              <meta name=\"dd-trace-time\" content=\"456\" />\n            </head>\n            <body>\n            </body>\n          </html>`\n        )\n      )\n    ).toEqual({ traceId: '123', traceTime: 456 as TimeStamp })\n  })\n\n  it('returns undefined if a meta is missing', () => {\n    expect(\n      getDocumentTraceDataFromMeta(\n        createDocument(\n          `${HTML_DOCTYPE}\n          <html>\n            <head>\n              <meta name=\"dd-trace-id\" content=\"123\" />\n            </head>\n            <body>\n            </body>\n          </html>`\n        )\n      )\n    ).toEqual(undefined)\n  })\n})\n\ndescribe('findTraceComment', () => {\n  const DATADOG_COMMENT = '\\n<!-- DATADOG;foo=bar -->\\n'\n\n  it('returns undefined if no comment is present', () => {\n    expect(findTraceComment(createDocument(HTML_DOCTYPE + HTML_CONTENT))).toBe(undefined)\n  })\n\n  it('returns undefined if no body is present', () => {\n    expect(findTraceComment(createDocument(`${HTML_DOCTYPE}<html></html>`))).toBe(undefined)\n  })\n\n  it('finds a comment before the doctype', () => {\n    expect(findTraceComment(createDocument(DATADOG_COMMENT + HTML_DOCTYPE + HTML_CONTENT))).toBe('foo=bar')\n  })\n\n  it('finds a comment before the HTML content', () => {\n    expect(findTraceComment(createDocument(HTML_DOCTYPE + DATADOG_COMMENT + HTML_CONTENT))).toBe('foo=bar')\n  })\n\n  it('finds a comment after the HTML content', () => {\n    expect(findTraceComment(createDocument(HTML_DOCTYPE + HTML_CONTENT + DATADOG_COMMENT))).toBe('foo=bar')\n  })\n\n  it('finds a comment at the end of the body', () => {\n    expect(findTraceComment(createDocument(`${HTML_DOCTYPE}<html><body>${DATADOG_COMMENT}</body></html>`))).toBe(\n      'foo=bar'\n    )\n  })\n\n  it(\"doesn't match comments without the DATADOG; prefix\", () => {\n    expect(findTraceComment(createDocument(`${HTML_DOCTYPE}${HTML_CONTENT}<!-- foo=bar -->`))).toBe(undefined)\n  })\n\n  it(\"doesn't look for comments nested below the body\", () => {\n    expect(\n      findTraceComment(createDocument(`${HTML_DOCTYPE}<html><body><div>${DATADOG_COMMENT}</div></body></html>`))\n    ).toBe(undefined)\n  })\n\n  it('finds a comment surrounded by newlines', () => {\n    expect(findTraceComment(createDocument(`<!--\\nDATADOG;foo=bar\\n-->${HTML_DOCTYPE}${HTML_CONTENT}`))).toBe('foo=bar')\n  })\n})\n\ndescribe('createDocumentTraceData', () => {\n  it('parses a trace comment', () => {\n    expect(createDocumentTraceData('123', '456')).toEqual({\n      traceId: '123',\n      traceTime: 456 as TimeStamp,\n    })\n  })\n\n  it('returns undefined if the time is not a number', () => {\n    expect(createDocumentTraceData('123', '4x6')).toBe(undefined)\n  })\n\n  it('returns undefined if the time is missing', () => {\n    expect(createDocumentTraceData('123', undefined)).toBe(undefined)\n  })\n\n  it('returns undefined if the trace id is missing', () => {\n    expect(createDocumentTraceData(undefined, '456')).toBe(undefined)\n  })\n\n  it('returns undefined if the trace id is empty', () => {\n    expect(createDocumentTraceData('', '456')).toBe(undefined)\n  })\n})\n\nfunction createDocument(content: string) {\n  return new DOMParser().parseFromString(content, 'text/html')\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/getDocumentTraceId.ts",
    "content": "import type { TimeStamp } from '@datadog/browser-core'\nimport { dateNow, findCommaSeparatedValue, ONE_MINUTE } from '@datadog/browser-core'\nimport { isCommentNode, isTextNode } from '../../browser/htmlDomUtils'\n\ninterface DocumentTraceData {\n  traceId: string\n  traceTime: TimeStamp\n}\n\nexport const INITIAL_DOCUMENT_OUTDATED_TRACE_ID_THRESHOLD = 2 * ONE_MINUTE\n\nexport function getDocumentTraceId(document: Document): string | undefined {\n  const data = getDocumentTraceDataFromMeta(document) || getDocumentTraceDataFromComment(document)\n\n  if (!data || data.traceTime <= dateNow() - INITIAL_DOCUMENT_OUTDATED_TRACE_ID_THRESHOLD) {\n    return undefined\n  }\n\n  return data.traceId\n}\n\nexport function getDocumentTraceDataFromMeta(document: Document): DocumentTraceData | undefined {\n  const traceIdMeta = document.querySelector<HTMLMetaElement>('meta[name=dd-trace-id]')\n  const traceTimeMeta = document.querySelector<HTMLMetaElement>('meta[name=dd-trace-time]')\n  return createDocumentTraceData(traceIdMeta && traceIdMeta.content, traceTimeMeta && traceTimeMeta.content)\n}\n\nexport function getDocumentTraceDataFromComment(document: Document): DocumentTraceData | undefined {\n  const comment = findTraceComment(document)\n  if (!comment) {\n    return undefined\n  }\n  return createDocumentTraceData(\n    findCommaSeparatedValue(comment, 'trace-id'),\n    findCommaSeparatedValue(comment, 'trace-time')\n  )\n}\n\nexport function createDocumentTraceData(\n  traceId: string | undefined | null,\n  rawTraceTime: string | undefined | null\n): DocumentTraceData | undefined {\n  const traceTime = rawTraceTime && (Number(rawTraceTime) as TimeStamp)\n  if (!traceId || !traceTime) {\n    return undefined\n  }\n\n  return {\n    traceId,\n    traceTime,\n  }\n}\n\nexport function findTraceComment(document: Document): string | undefined {\n  // 1. Try to find the comment as a direct child of the document\n  // Note: TSLint advises to use a 'for of', but TS doesn't allow to use 'for of' if the iterated\n  // value is not an array or string (here, a NodeList).\n  for (let i = 0; i < document.childNodes.length; i += 1) {\n    const comment = getTraceCommentFromNode(document.childNodes[i])\n    if (comment) {\n      return comment\n    }\n  }\n\n  // 2. If the comment is placed after the </html> tag, but have some space or new lines before or\n  // after, the DOM parser will lift it (and the surrounding text) at the end of the <body> tag.\n  // Try to look for the comment at the end of the <body> by by iterating over its child nodes in\n  // reverse order, stopping if we come across a non-text node.\n  if (document.body) {\n    for (let i = document.body.childNodes.length - 1; i >= 0; i -= 1) {\n      const node = document.body.childNodes[i]\n      const comment = getTraceCommentFromNode(node)\n      if (comment) {\n        return comment\n      }\n      if (!isTextNode(node)) {\n        break\n      }\n    }\n  }\n}\n\nfunction getTraceCommentFromNode(node: Node | null) {\n  if (node && isCommentNode(node)) {\n    const match = /^\\s*DATADOG;(.*?)\\s*$/.exec(node.data)\n    if (match) {\n      return match[1]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/identifier.spec.ts",
    "content": "import { createSpanIdentifier, createTraceIdentifier, toPaddedHexadecimalString } from './identifier'\n\ndescribe('identifier', () => {\n  describe('TraceIdentifier', () => {\n    it('generates a random id', () => {\n      const identifier = createTraceIdentifier()\n      expect(identifier.toString()).toMatch(/^\\d+$/)\n    })\n\n    it('formats using base 16', () => {\n      mockRandomValues((buffer) => (buffer[0] = 0xff))\n      const identifier = createTraceIdentifier()\n      expect(identifier.toString(16)).toEqual('ff')\n    })\n\n    it('should generate a max value of 64 bits', () => {\n      mockRandomValues((buffer) => buffer.fill(0xff))\n      const identifier = createTraceIdentifier()\n      expect(identifier.toString(16)).toEqual('ffffffffffffffff')\n    })\n  })\n\n  describe('SpanIdentifier', () => {\n    it('generates a max value of 63 bits', () => {\n      mockRandomValues((buffer) => buffer.fill(0xff))\n      const identifier = createSpanIdentifier()\n      expect(identifier.toString(16)).toEqual('7fffffffffffffff')\n    })\n  })\n})\n\ndescribe('toPaddedHexadecimalString', () => {\n  it('should pad the string to 16 characters', () => {\n    mockRandomValues((buffer) => (buffer[0] = 0x01))\n    const identifier = createTraceIdentifier()\n    expect(toPaddedHexadecimalString(identifier)).toEqual('0000000000000001')\n  })\n})\n\nfunction mockRandomValues(cb: (buffer: Uint8Array) => void) {\n  spyOn(window.crypto, 'getRandomValues').and.callFake((bufferView) => {\n    cb(new Uint8Array(bufferView.buffer))\n    return bufferView\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/identifier.ts",
    "content": "interface BaseIdentifier {\n  toString(radix?: number): string\n}\n\nexport interface TraceIdentifier extends BaseIdentifier {\n  // We use a brand to distinguish between TraceIdentifier and SpanIdentifier, else TypeScript\n  // considers them as the same type\n  __brand: 'traceIdentifier'\n}\n\nexport interface SpanIdentifier extends BaseIdentifier {\n  __brand: 'spanIdentifier'\n}\n\nexport function createTraceIdentifier() {\n  return createIdentifier(64) as TraceIdentifier\n}\n\nexport function createSpanIdentifier() {\n  return createIdentifier(63) as SpanIdentifier\n}\n\nfunction createIdentifier(bits: 63 | 64): BaseIdentifier {\n  const buffer = crypto.getRandomValues(new Uint32Array(2))\n  if (bits === 63) {\n    // eslint-disable-next-line no-bitwise\n    buffer[buffer.length - 1] >>>= 1 // force 63-bit\n  }\n\n  // The `.toString` function is intentionally similar to Number and BigInt `.toString` method.\n  //\n  // JavaScript numbers can represent integers up to 48 bits, this is why we need two of them to\n  // represent a 64 bits identifier. But BigInts don't have this limitation and can represent larger\n  // integer values.\n  //\n  // In the future, when we drop browsers without BigInts support, we could use BigInts directly\n  // represent identifiers by simply returning a BigInt from this function (as all we need is a\n  // value with a `.toString` method).\n  //\n  // Examples:\n  //   const buffer = getCrypto().getRandomValues(new Uint32Array(2))\n  //   return BigInt(buffer[0]) + BigInt(buffer[1]) << 32n\n  //\n  //   // Alternative with BigUint64Array (different Browser support than plain bigints!):\n  //   return crypto.getRandomValues(new BigUint64Array(1))[0]\n  //\n  // For now, let's keep using two plain numbers as having two different implementations (one for\n  // browsers with BigInt support and one for older browsers) don't bring much value.\n  return {\n    toString(radix = 10) {\n      let high = buffer[1]\n      let low = buffer[0]\n      let str = ''\n\n      do {\n        const mod = (high % radix) * 4294967296 + low\n        high = Math.floor(high / radix)\n        low = Math.floor(mod / radix)\n        str = (mod % radix).toString(radix) + str\n      } while (high || low)\n\n      return str\n    },\n  }\n}\n\nexport function toPaddedHexadecimalString(id: BaseIdentifier) {\n  return id.toString(16).padStart(16, '0')\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/tracer.spec.ts",
    "content": "import type { ContextManager, ContextValue } from '@datadog/browser-core'\nimport { display, objectEntries, TraceContextInjection } from '@datadog/browser-core'\nimport type { RumSessionManagerMock } from '../../../test'\nimport { createRumSessionManagerMock } from '../../../test'\nimport type { RumFetchResolveContext, RumFetchStartContext, RumXhrStartContext } from '../requestCollection'\nimport type { RumInitConfiguration } from '../configuration'\nimport { validateAndBuildRumConfiguration } from '../configuration'\nimport { startTracer } from './tracer'\nimport type { SpanIdentifier, TraceIdentifier } from './identifier'\nimport { createSpanIdentifier, createTraceIdentifier } from './identifier'\n\ndescribe('tracer', () => {\n  const ALLOWED_DOMAIN_CONTEXT: Partial<RumXhrStartContext | RumFetchStartContext> = {\n    url: window.location.origin,\n  }\n  const DISALLOWED_DOMAIN_CONTEXT: Partial<RumXhrStartContext | RumFetchStartContext> = {\n    url: 'http://foo.com',\n  }\n\n  function startTracerWithDefaults({\n    initConfiguration,\n    sessionManager = createRumSessionManagerMock(),\n    userId = '1234',\n  }: {\n    initConfiguration?: Partial<RumInitConfiguration>\n    sessionManager?: RumSessionManagerMock\n    userId?: ContextValue\n  } = {}) {\n    const configuration = validateAndBuildRumConfiguration({\n      clientToken: 'xxx',\n      applicationId: 'xxx',\n      service: 'service',\n      allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['datadog'] }],\n      ...initConfiguration,\n    })!\n    const userContext = { getContext: () => ({ id: userId }) } as unknown as ContextManager\n    const accountContext = { getContext: () => ({ id: '5678' }) } as unknown as ContextManager\n    const tracer = startTracer(configuration, sessionManager, userContext, accountContext)\n    return tracer\n  }\n\n  describe('traceXhr', () => {\n    interface MockXhr {\n      headers: { [name: string]: string }\n      setRequestHeader(name: string, value: string): void\n    }\n    let xhr: MockXhr\n\n    beforeEach(() => {\n      xhr = {\n        setRequestHeader(this: MockXhr, name: string, value: string) {\n          this.headers[name] = value\n        },\n        headers: {} as MockXhr['headers'],\n      }\n    })\n\n    it('should add traceId and spanId to context and add tracing headers', () => {\n      const tracer = startTracerWithDefaults()\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n      expect(xhr.headers).toEqual(tracingHeadersFor(context.traceId!, context.spanId!, '1'))\n    })\n\n    it('should not trace request on disallowed domain', () => {\n      const tracer = startTracerWithDefaults()\n      const context = { ...DISALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(context.traceId).toBeUndefined()\n      expect(context.spanId).toBeUndefined()\n      expect(xhr.headers).toEqual({})\n    })\n\n    it('should not trace request during untracked session', () => {\n      const tracer = startTracerWithDefaults({\n        sessionManager: createRumSessionManagerMock().setNotTracked(),\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(context.traceId).toBeUndefined()\n      expect(context.spanId).toBeUndefined()\n      expect(xhr.headers).toEqual({})\n    })\n\n    it(\"should trace request with priority '1' when sampled\", () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: { traceSampleRate: 100 },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(context.traceSampled).toBe(true)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n      expect(xhr.headers).toEqual(tracingHeadersFor(context.traceId!, context.spanId!, '1'))\n    })\n\n    it(\"should trace request with priority '0' when not sampled and config set to all\", () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: { traceSampleRate: 0, traceContextInjection: TraceContextInjection.ALL },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(context.traceSampled).toBe(false)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n      expect(xhr.headers).toEqual(tracingHeadersFor(context.traceId!, context.spanId!, '0'))\n    })\n\n    it(\"should trace request with sampled set to '0' in OTel headers when not sampled and config set to all\", () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 0,\n          traceContextInjection: TraceContextInjection.ALL,\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['b3', 'tracecontext', 'b3multi'] }],\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers).toEqual(\n        jasmine.objectContaining({\n          b3: jasmine.stringMatching(/^[0-9a-f]{16}-[0-9a-f]{16}-0$/),\n          traceparent: jasmine.stringMatching(/^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-00$/),\n          tracestate: 'dd=s:0;o:rum',\n          'X-B3-Sampled': '0',\n        })\n      )\n    })\n\n    it('should trace requests on configured origins', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [\n            /^https?:\\/\\/qux\\.com/,\n            'http://bar.com',\n            (origin: string) => origin === 'http://dynamic.com',\n          ],\n        },\n      })\n      const stub = xhr as unknown as XMLHttpRequest\n\n      let context: Partial<RumXhrStartContext> = { url: 'http://qux.com' }\n      tracer.traceXhr(context, stub)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n\n      context = { url: 'http://bar.com' }\n      tracer.traceXhr(context, stub)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n\n      context = { url: 'http://dynamic.com' }\n      tracer.traceXhr(context, stub)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n    })\n\n    it('should add headers only for B3 Multiple propagator', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['b3multi'] }],\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers).toEqual(\n        jasmine.objectContaining({\n          'X-B3-TraceId': jasmine.stringMatching(/^[0-9a-f]{16}$/),\n          'X-B3-SpanId': jasmine.stringMatching(/^[0-9a-f]{16}$/),\n          'X-B3-Sampled': '1',\n        })\n      )\n\n      expect(xhr.headers['x-datadog-origin']).toBeUndefined()\n      expect(xhr.headers['x-datadog-parent-id']).toBeUndefined()\n      expect(xhr.headers['x-datadog-trace-id']).toBeUndefined()\n      expect(xhr.headers['x-datadog-sampling-priority']).toBeUndefined()\n    })\n\n    it('should add headers for B3 (single) and tracecontext propagators', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['b3', 'tracecontext'] }],\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers).toEqual(\n        jasmine.objectContaining({\n          b3: jasmine.stringMatching(/^[0-9a-f]{16}-[0-9a-f]{16}-1$/),\n          traceparent: jasmine.stringMatching(/^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-01$/),\n          tracestate: 'dd=s:1;o:rum',\n        })\n      )\n    })\n\n    it('should not add any headers', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: [] }],\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers['b3']).toBeUndefined()\n      expect(xhr.headers['traceparent']).toBeUndefined()\n      expect(xhr.headers['tracestate']).toBeUndefined()\n      expect(xhr.headers['x-datadog-trace-id']).toBeUndefined()\n      expect(xhr.headers['X-B3-TraceId']).toBeUndefined()\n    })\n\n    it('should not add any headers when trace not sampled and config set to sampled', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 0,\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers['x-datadog-trace-id']).toBeUndefined()\n      expect(xhr.headers['x-datadog-sampling-priority']).toBeUndefined()\n    })\n\n    it('should add headers when trace sampled and config set to sampled', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 100,\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers['x-datadog-trace-id']).toBeDefined()\n      expect(xhr.headers['x-datadog-sampling-priority']).toBeDefined()\n    })\n\n    it('should add headers when trace not sampled and config set to all', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 0,\n          traceContextInjection: TraceContextInjection.ALL,\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers['x-datadog-trace-id']).toBeDefined()\n      expect(xhr.headers['x-datadog-sampling-priority']).toBeDefined()\n    })\n\n    describe('baggage propagation header', () => {\n      function traceRequestAndGetBaggageHeader({\n        initConfiguration,\n        userId,\n      }: {\n        initConfiguration: Partial<RumInitConfiguration>\n        userId?: ContextValue\n      }) {\n        const tracer = startTracerWithDefaults({\n          initConfiguration,\n          userId,\n        })\n        const context = { ...ALLOWED_DOMAIN_CONTEXT }\n        tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n        return xhr.headers.baggage\n      }\n\n      it('should add user.id, account.id and session.id to baggage header when feature is enabled and propagateTraceBaggage is true', () => {\n        const baggage = traceRequestAndGetBaggageHeader({\n          initConfiguration: {\n            propagateTraceBaggage: true,\n          },\n        })\n        expect(baggage).toEqual('session.id=session-id,user.id=1234,account.id=5678')\n      })\n\n      it('should not add baggage header when propagateTraceBaggage is false', () => {\n        const baggage = traceRequestAndGetBaggageHeader({\n          initConfiguration: {\n            propagateTraceBaggage: false,\n          },\n        })\n        expect(baggage).toBeUndefined()\n      })\n\n      it('url-encodes baggage values', () => {\n        const baggage = traceRequestAndGetBaggageHeader({\n          initConfiguration: {\n            propagateTraceBaggage: true,\n          },\n          userId: '1234, 😀',\n        })\n        expect(baggage).toBe('session.id=session-id,user.id=1234%2C%20%F0%9F%98%80,account.id=5678')\n      })\n\n      it('skips non-string context values', () => {\n        const baggage = traceRequestAndGetBaggageHeader({\n          initConfiguration: {\n            propagateTraceBaggage: true,\n          },\n          userId: 1234,\n        })\n        expect(baggage).toBe('session.id=session-id,account.id=5678')\n      })\n    })\n\n    it('should ignore wrong propagator types', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['foo', 32, () => true] as any }],\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(xhr.headers['b3']).toBeUndefined()\n      expect(xhr.headers['traceparent']).toBeUndefined()\n      expect(xhr.headers['tracestate']).toBeUndefined()\n      expect(xhr.headers['x-datadog-trace-id']).toBeUndefined()\n      expect(xhr.headers['X-B3-TraceId']).toBeUndefined()\n    })\n\n    it('should display an error when a matching function throws', () => {\n      const displaySpy = spyOn(display, 'error')\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [\n            () => {\n              throw new Error('invalid')\n            },\n          ],\n        },\n      })\n      const context = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceXhr(context, xhr as unknown as XMLHttpRequest)\n\n      expect(displaySpy).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('traceFetch', () => {\n    it('should add traceId and spanId to context, and add tracing headers', () => {\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n      expect(context.init!.headers).toEqual(tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'))\n    })\n\n    it('should preserve original request init', () => {\n      const init = { method: 'POST' }\n      const context: Partial<RumFetchStartContext> = {\n        ...ALLOWED_DOMAIN_CONTEXT,\n        init,\n      }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.init).not.toBe(init)\n      expect(context.init!.method).toBe('POST')\n      expect(context.init!.headers).toEqual(tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'))\n    })\n\n    it('should preserve original headers object', () => {\n      const headers = new Headers()\n      headers.set('foo', 'bar')\n\n      const context: Partial<RumFetchStartContext> = {\n        ...ALLOWED_DOMAIN_CONTEXT,\n        init: { headers, method: 'POST' },\n      }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).not.toBe(headers)\n      expect(context.init!.headers).toEqual([\n        ['foo', 'bar'],\n        ...tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'),\n      ])\n      expect(toPlainObject(headers)).toEqual({\n        foo: 'bar',\n      })\n    })\n\n    it('should preserve original headers plain object', () => {\n      const headers = { foo: 'bar' }\n\n      const context: Partial<RumFetchStartContext> = {\n        ...ALLOWED_DOMAIN_CONTEXT,\n        init: { headers, method: 'POST' },\n      }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).not.toBe(headers)\n      expect(context.init!.headers).toEqual([\n        ['foo', 'bar'],\n        ...tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'),\n      ])\n\n      expect(headers).toEqual({\n        foo: 'bar',\n      })\n    })\n\n    it('should preserve original headers array', () => {\n      const headers: Array<[string, string]> = [\n        ['foo', 'bar'],\n        ['foo', 'baz'],\n      ]\n\n      const context: Partial<RumFetchStartContext> = {\n        ...ALLOWED_DOMAIN_CONTEXT,\n        init: { headers, method: 'POST' },\n      }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).not.toBe(headers)\n      expect(context.init!.headers).toEqual([\n        ['foo', 'bar'],\n        ['foo', 'baz'],\n        ...tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'),\n      ])\n\n      expect(headers).toEqual([\n        ['foo', 'bar'],\n        ['foo', 'baz'],\n      ])\n    })\n\n    it('should preserve original headers contained in a Request instance', () => {\n      const request = new Request(document.location.origin, {\n        headers: {\n          foo: 'bar',\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = {\n        ...ALLOWED_DOMAIN_CONTEXT,\n        input: request,\n      }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.init).toBe(undefined)\n      expect(context.input).not.toBe(request)\n      expect(headersAsArray((context.input as Request).headers)).toEqual([\n        ['foo', 'bar'],\n        ...tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'),\n      ])\n      expect(headersAsArray(request.headers)).toEqual([['foo', 'bar']])\n    })\n\n    it('should ignore headers from a Request instance if other headers are set', () => {\n      const context: Partial<RumFetchStartContext> = {\n        ...ALLOWED_DOMAIN_CONTEXT,\n        init: { headers: { 'x-init-header': 'baz' } },\n        input: new Request(document.location.origin, {\n          headers: { 'x-request-header': 'bar' },\n        }),\n      }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).toEqual([\n        ['x-init-header', 'baz'],\n        ...tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'),\n      ])\n    })\n\n    it('should not trace request on disallowed domain', () => {\n      const context: Partial<RumFetchStartContext> = { ...DISALLOWED_DOMAIN_CONTEXT }\n\n      const tracer = startTracerWithDefaults()\n      tracer.traceFetch(context)\n\n      expect(context.traceId).toBeUndefined()\n      expect(context.spanId).toBeUndefined()\n      expect(context.init).toBeUndefined()\n    })\n\n    it('should not trace request during untracked session', () => {\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n\n      const tracer = startTracerWithDefaults({\n        sessionManager: createRumSessionManagerMock().setNotTracked(),\n      })\n      tracer.traceFetch(context)\n\n      expect(context.traceId).toBeUndefined()\n      expect(context.spanId).toBeUndefined()\n      expect(context.init).toBeUndefined()\n    })\n\n    it(\"should trace request with priority '1' when sampled\", () => {\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n\n      const tracer = startTracerWithDefaults({ initConfiguration: { traceSampleRate: 100 } })\n      tracer.traceFetch(context)\n\n      expect(context.traceSampled).toBe(true)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n      expect(context.init!.headers).toEqual(tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '1'))\n    })\n\n    it(\"should trace request with priority '0' when not sampled and config set to all\", () => {\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n\n      const tracer = startTracerWithDefaults({\n        initConfiguration: { traceSampleRate: 0, traceContextInjection: TraceContextInjection.ALL },\n      })\n      tracer.traceFetch(context)\n\n      expect(context.traceSampled).toBe(false)\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n      expect(context.init!.headers).toEqual(tracingHeadersAsArrayFor(context.traceId!, context.spanId!, '0'))\n    })\n\n    it('should trace requests on configured urls', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [\n            /^https?:\\/\\/qux\\.com.*/,\n            'http://bar.com',\n            (origin: string) => origin === 'http://dynamic.com',\n          ],\n        },\n      })\n      const quxDomainContext: Partial<RumFetchStartContext> = { url: 'http://qux.com' }\n      const barDomainContext: Partial<RumFetchStartContext> = { url: 'http://bar.com' }\n      const dynamicDomainContext: Partial<RumFetchStartContext> = { url: 'http://dynamic.com' }\n\n      tracer.traceFetch(quxDomainContext)\n      tracer.traceFetch(barDomainContext)\n      tracer.traceFetch(dynamicDomainContext)\n      expect(quxDomainContext.traceId).toBeDefined()\n      expect(quxDomainContext.spanId).toBeDefined()\n      expect(barDomainContext.traceId).toBeDefined()\n      expect(barDomainContext.spanId).toBeDefined()\n      expect(dynamicDomainContext.traceId).toBeDefined()\n      expect(dynamicDomainContext.spanId).toBeDefined()\n    })\n\n    it('should add headers only for B3 Multiple propagator', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['b3multi'] }],\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['X-B3-TraceId']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['X-B3-SpanId']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['X-B3-Sampled']))\n\n      expect(context.init!.headers).toEqual(\n        jasmine.arrayContaining([\n          ['X-B3-TraceId', jasmine.stringMatching(/^[0-9a-f]{16}$/)],\n          ['X-B3-SpanId', jasmine.stringMatching(/^[0-9a-f]{16}$/)],\n          ['X-B3-Sampled', '1'],\n        ])\n      )\n\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['x-datadog-origin']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['x-datadog-parent-id']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['x-datadog-trace-id']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['x-datadog-sampling-priority']))\n    })\n\n    it('should add headers for b3 (single) and tracecontext propagators', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: ['b3', 'tracecontext'] }],\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).toEqual(\n        jasmine.arrayContaining([\n          ['b3', jasmine.stringMatching(/^[0-9a-f]{16}-[0-9a-f]{16}-1$/)],\n          ['traceparent', jasmine.stringMatching(/^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-01$/)],\n          ['tracestate', 'dd=s:1;o:rum'],\n        ])\n      )\n    })\n\n    it('should not add any headers with no propagatorTypes', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          allowedTracingUrls: [{ match: window.location.origin, propagatorTypes: [] }],\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['b3']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['traceparent']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['tracestate']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['x-datadog-trace-id']))\n      expect(context.init!.headers).not.toContain(jasmine.arrayContaining(['X-B3-TraceId']))\n    })\n    it('should not add headers when trace not sampled and config set to sampled', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 0,\n          traceContextInjection: TraceContextInjection.SAMPLED,\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceFetch(context)\n\n      expect(context.init).toBeUndefined()\n    })\n\n    it('should add headers when trace sampled and config set to sampled', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 100,\n          traceContextInjection: TraceContextInjection.SAMPLED,\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-origin']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-parent-id']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-trace-id']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-sampling-priority']))\n    })\n\n    it('should add headers when trace not sampled and config set to all', () => {\n      const tracer = startTracerWithDefaults({\n        initConfiguration: {\n          traceSampleRate: 0,\n          traceContextInjection: TraceContextInjection.ALL,\n        },\n      })\n\n      const context: Partial<RumFetchStartContext> = { ...ALLOWED_DOMAIN_CONTEXT }\n      tracer.traceFetch(context)\n\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-origin']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-parent-id']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-trace-id']))\n      expect(context.init!.headers).toContain(jasmine.arrayContaining(['x-datadog-sampling-priority']))\n    })\n  })\n\n  describe('clearTracingIfCancelled', () => {\n    it('should clear tracing if status is 0', () => {\n      const tracer = startTracerWithDefaults()\n      const context: RumFetchResolveContext = {\n        status: 0,\n\n        spanId: createSpanIdentifier(),\n        traceId: createTraceIdentifier(),\n      } satisfies Partial<RumFetchResolveContext> as any\n      tracer.clearTracingIfNeeded(context)\n\n      expect(context.traceId).toBeUndefined()\n      expect(context.spanId).toBeUndefined()\n    })\n\n    it('should not clear tracing if status is not 0', () => {\n      const tracer = startTracerWithDefaults()\n      const context: RumFetchResolveContext = {\n        status: 200,\n\n        spanId: createSpanIdentifier(),\n        traceId: createTraceIdentifier(),\n      } satisfies Partial<RumFetchResolveContext> as any\n      tracer.clearTracingIfNeeded(context)\n\n      expect(context.traceId).toBeDefined()\n      expect(context.spanId).toBeDefined()\n    })\n  })\n})\n\nfunction toPlainObject(headers: Headers) {\n  const result: { [key: string]: string } = {}\n  headers.forEach((value, key) => {\n    result[key] = value\n  })\n  return result\n}\n\nfunction tracingHeadersFor(traceId: TraceIdentifier, spanId: SpanIdentifier, samplingPriority: '1' | '0') {\n  return {\n    'x-datadog-origin': 'rum',\n    'x-datadog-parent-id': spanId.toString(),\n    'x-datadog-sampling-priority': samplingPriority,\n    'x-datadog-trace-id': traceId.toString(),\n  }\n}\n\nfunction tracingHeadersAsArrayFor(traceId: TraceIdentifier, spanId: SpanIdentifier, samplingPriority: '1' | '0') {\n  return objectEntries(tracingHeadersFor(traceId, spanId, samplingPriority))\n}\n\nfunction headersAsArray(headers: Headers) {\n  const result: Array<[string, string]> = []\n  headers.forEach((value, key) => {\n    result.push([key, value])\n  })\n  return result\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/tracer.ts",
    "content": "import type { ContextManager } from '@datadog/browser-core'\nimport { objectEntries, shallowClone, matchList, TraceContextInjection } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../configuration'\nimport type {\n  RumFetchResolveContext,\n  RumFetchStartContext,\n  RumXhrCompleteContext,\n  RumXhrStartContext,\n} from '../requestCollection'\nimport type { RumSessionManager } from '../rumSessionManager'\nimport { isSampled } from '../sampler/sampler'\nimport type { PropagatorType } from './tracer.types'\nimport type { SpanIdentifier, TraceIdentifier } from './identifier'\nimport { createSpanIdentifier, createTraceIdentifier, toPaddedHexadecimalString } from './identifier'\n\nexport interface Tracer {\n  traceFetch: (context: Partial<RumFetchStartContext>) => void\n  traceXhr: (context: Partial<RumXhrStartContext>, xhr: XMLHttpRequest) => void\n  clearTracingIfNeeded: (context: RumFetchResolveContext | RumXhrCompleteContext) => void\n}\n\ninterface TracingHeaders {\n  [key: string]: string\n}\n\n/**\n * Clear tracing information to avoid incomplete traces. Ideally, we should do it when the\n * request did not reach the server, but the browser does not expose this. So, we clear tracing\n * information if the request ended with status 0 without being aborted by the application.\n *\n * Reasoning:\n *\n * * Applications are usually aborting requests after a bit of time, for example when the user is\n * typing (autocompletion) or navigating away (in a SPA). With a performant device and good\n * network conditions, the request is likely to reach the server before being canceled.\n *\n * * Requests aborted otherwise (ex: lack of internet, CORS issue, blocked by a privacy extension)\n * are likely to finish quickly and without reaching the server.\n *\n * Of course, it might not be the case every time, but it should limit having incomplete traces a\n * bit.\n * */\nexport function clearTracingIfNeeded(context: RumFetchResolveContext | RumXhrCompleteContext) {\n  if (context.status === 0 && !context.isAborted) {\n    context.traceId = undefined\n    context.spanId = undefined\n    context.traceSampled = undefined\n  }\n}\n\nexport function startTracer(\n  configuration: RumConfiguration,\n  sessionManager: RumSessionManager,\n  userContext: ContextManager,\n  accountContext: ContextManager\n): Tracer {\n  return {\n    clearTracingIfNeeded,\n    traceFetch: (context) =>\n      injectHeadersIfTracingAllowed(\n        configuration,\n        context,\n        sessionManager,\n        userContext,\n        accountContext,\n        (tracingHeaders: TracingHeaders) => {\n          if (context.input instanceof Request && !context.init?.headers) {\n            context.input = new Request(context.input)\n            Object.keys(tracingHeaders).forEach((key) => {\n              ;(context.input as Request).headers.append(key, tracingHeaders[key])\n            })\n          } else {\n            context.init = shallowClone(context.init)\n            const headers: Array<[string, string]> = []\n            if (context.init.headers instanceof Headers) {\n              context.init.headers.forEach((value, key) => {\n                headers.push([key, value])\n              })\n            } else if (Array.isArray(context.init.headers)) {\n              context.init.headers.forEach((header) => {\n                headers.push(header)\n              })\n            } else if (context.init.headers) {\n              Object.keys(context.init.headers).forEach((key) => {\n                headers.push([key, (context.init!.headers as Record<string, string>)[key]])\n              })\n            }\n            context.init.headers = headers.concat(objectEntries(tracingHeaders))\n          }\n        }\n      ),\n    traceXhr: (context, xhr) =>\n      injectHeadersIfTracingAllowed(\n        configuration,\n        context,\n        sessionManager,\n        userContext,\n        accountContext,\n        (tracingHeaders: TracingHeaders) => {\n          Object.keys(tracingHeaders).forEach((name) => {\n            xhr.setRequestHeader(name, tracingHeaders[name])\n          })\n        }\n      ),\n  }\n}\n\nfunction injectHeadersIfTracingAllowed(\n  configuration: RumConfiguration,\n  context: Partial<RumFetchStartContext | RumXhrStartContext>,\n  sessionManager: RumSessionManager,\n  userContext: ContextManager,\n  accountContext: ContextManager,\n  inject: (tracingHeaders: TracingHeaders) => void\n) {\n  const session = sessionManager.findTrackedSession()\n  if (!session) {\n    return\n  }\n\n  const tracingOption = configuration.allowedTracingUrls.find((tracingOption) =>\n    matchList([tracingOption.match], context.url!, true)\n  )\n  if (!tracingOption) {\n    return\n  }\n\n  const traceSampled = isSampled(session.id, configuration.traceSampleRate)\n\n  const shouldInjectHeaders = traceSampled || configuration.traceContextInjection === TraceContextInjection.ALL\n  if (!shouldInjectHeaders) {\n    return\n  }\n\n  context.traceSampled = traceSampled\n  context.traceId = createTraceIdentifier()\n  context.spanId = createSpanIdentifier()\n\n  inject(\n    makeTracingHeaders(\n      context.traceId,\n      context.spanId,\n      context.traceSampled,\n      session.id,\n      tracingOption.propagatorTypes,\n      userContext,\n      accountContext,\n      configuration\n    )\n  )\n}\n\n/**\n * When trace is not sampled, set priority to '0' instead of not adding the tracing headers\n * to prepare the implementation for sampling delegation.\n */\nfunction makeTracingHeaders(\n  traceId: TraceIdentifier,\n  spanId: SpanIdentifier,\n  traceSampled: boolean,\n  sessionId: string,\n  propagatorTypes: PropagatorType[],\n  userContext: ContextManager,\n  accountContext: ContextManager,\n  configuration: RumConfiguration\n): TracingHeaders {\n  const tracingHeaders: TracingHeaders = {}\n\n  propagatorTypes.forEach((propagatorType) => {\n    switch (propagatorType) {\n      case 'datadog': {\n        Object.assign(tracingHeaders, {\n          'x-datadog-origin': 'rum',\n          'x-datadog-parent-id': spanId.toString(),\n          'x-datadog-sampling-priority': traceSampled ? '1' : '0',\n          'x-datadog-trace-id': traceId.toString(),\n        })\n        break\n      }\n      // https://www.w3.org/TR/trace-context/\n      case 'tracecontext': {\n        Object.assign(tracingHeaders, {\n          traceparent: `00-0000000000000000${toPaddedHexadecimalString(traceId)}-${toPaddedHexadecimalString(spanId)}-0${\n            traceSampled ? '1' : '0'\n          }`,\n          tracestate: `dd=s:${traceSampled ? '1' : '0'};o:rum`,\n        })\n        break\n      }\n      // https://github.com/openzipkin/b3-propagation\n      case 'b3': {\n        Object.assign(tracingHeaders, {\n          b3: `${toPaddedHexadecimalString(traceId)}-${toPaddedHexadecimalString(spanId)}-${traceSampled ? '1' : '0'}`,\n        })\n        break\n      }\n      case 'b3multi': {\n        Object.assign(tracingHeaders, {\n          'X-B3-TraceId': toPaddedHexadecimalString(traceId),\n          'X-B3-SpanId': toPaddedHexadecimalString(spanId),\n          'X-B3-Sampled': traceSampled ? '1' : '0',\n        })\n        break\n      }\n    }\n  })\n\n  if (configuration.propagateTraceBaggage) {\n    const baggageItems: Record<string, string> = {\n      'session.id': sessionId,\n    }\n\n    const userId = userContext.getContext().id\n    if (typeof userId === 'string') {\n      baggageItems['user.id'] = userId\n    }\n\n    const accountId = accountContext.getContext().id\n    if (typeof accountId === 'string') {\n      baggageItems['account.id'] = accountId\n    }\n\n    const baggageHeader = Object.entries(baggageItems)\n      .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)\n      .join(',')\n    if (baggageHeader) {\n      tracingHeaders['baggage'] = baggageHeader\n    }\n  }\n\n  return tracingHeaders\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/tracing/tracer.types.ts",
    "content": "import type { MatchOption } from '@datadog/browser-core'\n\n/**\n * datadog: Datadog (x-datadog-*)\n * tracecontext: W3C Trace Context (traceparent, tracestate)\n * b3: B3 Single Header (b3)\n * b3multi: B3 Multiple Headers (X-B3-*)\n */\nexport type PropagatorType = 'datadog' | 'b3' | 'b3multi' | 'tracecontext'\nexport interface TracingOption {\n  match: MatchOption\n  propagatorTypes: PropagatorType[]\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/trackEventCounts.spec.ts",
    "content": "import { objectValues } from '@datadog/browser-core'\nimport type { AssembledRumEvent } from '../rawRumEvent.types'\nimport { FrustrationType, RumEventType } from '../rawRumEvent.types'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport { trackEventCounts } from './trackEventCounts'\n\ndescribe('trackEventCounts', () => {\n  let lifeCycle: LifeCycle\n\n  beforeEach(() => {\n    lifeCycle = new LifeCycle()\n  })\n\n  function notifyCollectedRawRumEvent(partialEvent: Partial<AssembledRumEvent>) {\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, partialEvent as AssembledRumEvent)\n  }\n\n  it('tracks errors', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({ type: RumEventType.ERROR })\n    expect(eventCounts.errorCount).toBe(1)\n  })\n\n  it('tracks long tasks', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({ type: RumEventType.LONG_TASK })\n    expect(eventCounts.longTaskCount).toBe(1)\n  })\n  ;[RumEventType.VIEW, RumEventType.VITAL].forEach((eventType) => {\n    it(`doesn't track ${eventType} events`, () => {\n      const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n      notifyCollectedRawRumEvent({ type: eventType })\n      expect(objectValues(eventCounts as unknown as { [key: string]: number }).every((value) => value === 0)).toBe(true)\n    })\n  })\n\n  it('tracks actions', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({ type: RumEventType.ACTION, action: { type: 'custom' } })\n    expect(eventCounts.actionCount).toBe(1)\n  })\n\n  it('tracks non-discarded resources', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE })\n    expect(eventCounts.resourceCount).toBe(1)\n  })\n\n  it('does not track discarded resources', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE, _dd: { discarded: true, format_version: 2 } })\n    expect(eventCounts.resourceCount).toBe(0)\n  })\n\n  it('tracks frustration counts', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({\n      type: RumEventType.ACTION,\n      action: {\n        type: 'click',\n        frustration: {\n          type: [FrustrationType.ERROR_CLICK, FrustrationType.DEAD_CLICK],\n        },\n      },\n    })\n    expect(eventCounts.frustrationCount).toBe(2)\n  })\n\n  it('stops tracking when stop is called', () => {\n    const { eventCounts, stop } = trackEventCounts({ lifeCycle, isChildEvent: () => true })\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE })\n    expect(eventCounts.resourceCount).toBe(1)\n    stop()\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE })\n    expect(eventCounts.resourceCount).toBe(1)\n  })\n\n  it('invokes a potential callback when a count is increased', () => {\n    const spy = jasmine.createSpy<() => void>()\n    trackEventCounts({ lifeCycle, isChildEvent: () => true, onChange: spy })\n\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE })\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE })\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  it('does not take into account events that are not child events', () => {\n    const { eventCounts } = trackEventCounts({ lifeCycle, isChildEvent: () => false })\n    notifyCollectedRawRumEvent({ type: RumEventType.RESOURCE })\n    expect(eventCounts.resourceCount).toBe(0)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/trackEventCounts.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport { RumEventType } from '../rawRumEvent.types'\nimport type { RumActionEvent, RumErrorEvent, RumLongTaskEvent, RumResourceEvent } from '../rumEvent.types'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\n\nexport interface EventCounts {\n  errorCount: number\n  actionCount: number\n  longTaskCount: number\n  resourceCount: number\n  frustrationCount: number\n}\n\nexport function trackEventCounts({\n  lifeCycle,\n  isChildEvent,\n  onChange: callback = noop,\n}: {\n  lifeCycle: LifeCycle\n  isChildEvent: (event: RumActionEvent | RumErrorEvent | RumLongTaskEvent | RumResourceEvent) => boolean\n  onChange?: () => void\n}) {\n  const eventCounts: EventCounts = {\n    errorCount: 0,\n    longTaskCount: 0,\n    resourceCount: 0,\n    actionCount: 0,\n    frustrationCount: 0,\n  }\n\n  const subscription = lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, (event): void => {\n    if (event.type === 'view' || event.type === 'vital' || !isChildEvent(event)) {\n      return\n    }\n    switch (event.type) {\n      case RumEventType.ERROR:\n        eventCounts.errorCount += 1\n        callback()\n        break\n      case RumEventType.ACTION:\n        eventCounts.actionCount += 1\n        if (event.action.frustration) {\n          eventCounts.frustrationCount += event.action.frustration.type.length\n        }\n        callback()\n        break\n      case RumEventType.LONG_TASK:\n        eventCounts.longTaskCount += 1\n        callback()\n        break\n      case RumEventType.RESOURCE:\n        if (!event._dd?.discarded) {\n          eventCounts.resourceCount += 1\n          callback()\n        }\n        break\n    }\n  })\n\n  return {\n    stop: () => {\n      subscription.unsubscribe()\n    },\n    eventCounts,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/bfCacheSupport.spec.ts",
    "content": "import { createNewEvent, registerCleanupTask } from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../../test'\nimport { onBFCacheRestore } from './bfCacheSupport'\n\ndescribe('onBFCacheRestore', () => {\n  it('should invoke the callback only for BFCache restoration and stop listening when stopped', () => {\n    const configuration = mockRumConfiguration()\n    const callback = jasmine.createSpy('callback')\n\n    const stop = onBFCacheRestore(configuration, callback)\n    registerCleanupTask(stop)\n\n    window.dispatchEvent(createNewEvent('pageshow', { persisted: false }))\n    expect(callback).not.toHaveBeenCalled()\n\n    window.dispatchEvent(createNewEvent('pageshow', { persisted: true }))\n    expect(callback).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/bfCacheSupport.ts",
    "content": "import type { Configuration } from '@datadog/browser-core'\nimport { addEventListener, DOM_EVENT } from '@datadog/browser-core'\n\nexport function onBFCacheRestore(\n  configuration: Configuration,\n  callback: (event: PageTransitionEvent) => void\n): () => void {\n  const { stop } = addEventListener(\n    configuration,\n    window,\n    DOM_EVENT.PAGE_SHOW,\n    (event: PageTransitionEvent) => {\n      if (event.persisted) {\n        callback(event)\n      }\n    },\n    { capture: true }\n  )\n  return stop\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/setupViewTest.specHelper.ts",
    "content": "import { Observable, deepClone } from '@datadog/browser-core'\nimport { mockRumConfiguration, setupLocationObserver } from '../../../test'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { RumConfiguration } from '../configuration'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport type { ViewCreatedEvent, ViewEvent, ViewOptions, ViewEndedEvent } from './trackViews'\nimport { trackViews } from './trackViews'\n\nexport type ViewTest = ReturnType<typeof setupViewTest>\n\ninterface ViewTrackingContext {\n  lifeCycle: LifeCycle\n  initialLocation?: string\n  partialConfig?: Partial<RumConfiguration>\n}\n\nexport function setupViewTest(\n  { lifeCycle, initialLocation, partialConfig }: ViewTrackingContext,\n  initialViewOptions?: ViewOptions\n) {\n  const domMutationObservable = new Observable<RumMutationRecord[]>()\n  const windowOpenObservable = new Observable<void>()\n  const configuration = mockRumConfiguration(partialConfig)\n  const { locationChangeObservable, changeLocation } = setupLocationObserver(initialLocation)\n\n  const {\n    handler: viewUpdateHandler,\n    getViewEvent: getViewUpdate,\n    getHandledCount: getViewUpdateCount,\n  } = spyOnViews<ViewEvent>()\n  lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, viewUpdateHandler)\n\n  const {\n    handler: viewCreateHandler,\n    getViewEvent: getViewCreate,\n    getHandledCount: getViewCreateCount,\n  } = spyOnViews<ViewCreatedEvent>()\n  lifeCycle.subscribe(LifeCycleEventType.VIEW_CREATED, viewCreateHandler)\n\n  const {\n    handler: viewEndHandler,\n    getViewEvent: getViewEnd,\n    getHandledCount: getViewEndCount,\n  } = spyOnViews<ViewEndedEvent>()\n  lifeCycle.subscribe(LifeCycleEventType.VIEW_ENDED, viewEndHandler)\n\n  const {\n    stop,\n    startView,\n    setViewName,\n    setViewContext,\n    setViewContextProperty,\n    getViewContext,\n    addTiming,\n    setLoadingTime,\n  } = trackViews(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration,\n    locationChangeObservable,\n    !configuration.trackViewsManually,\n    initialViewOptions\n  )\n  return {\n    stop,\n    startView,\n    setViewContext,\n    setViewContextProperty,\n    getViewContext,\n    changeLocation,\n    setViewName,\n    addTiming,\n    setLoadingTime,\n    getViewUpdate,\n    getViewUpdateCount,\n    getViewCreate,\n    getViewCreateCount,\n    getViewEnd,\n    getViewEndCount,\n    getLatestViewContext: () => ({\n      id: getViewCreate(getViewCreateCount() - 1).id,\n    }),\n  }\n}\n\nfunction spyOnViews<Event>() {\n  const events: Event[] = []\n\n  return {\n    handler: (event: Event) => {\n      events.push(\n        // Some properties can be mutated later\n        deepClone(event)\n      )\n    },\n\n    getViewEvent: (index: number) => events[index],\n\n    getHandledCount: () => events.length,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/trackViewEventCounts.spec.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { AssembledRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport { trackViewEventCounts } from './trackViewEventCounts'\n\ndescribe('trackViewEventCounts', () => {\n  const lifeCycle = new LifeCycle()\n  let onChange: () => void\n\n  beforeEach(() => {\n    onChange = jasmine.createSpy('onChange')\n\n    const viewEventCountsTracking = trackViewEventCounts(lifeCycle, 'view-id', onChange)\n    registerCleanupTask(viewEventCountsTracking.stop)\n  })\n\n  it('should track events count', () => {\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n      type: RumEventType.ERROR,\n      view: { id: 'view-id' },\n    } as AssembledRumEvent)\n\n    expect(onChange).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not count child events unrelated to the view', () => {\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n      type: RumEventType.ERROR,\n      view: { id: 'unrelated-view-id' },\n    } as AssembledRumEvent)\n\n    expect(onChange).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/trackViewEventCounts.ts",
    "content": "import type { LifeCycle } from '../lifeCycle'\nimport { trackEventCounts } from '../trackEventCounts'\n\nexport function trackViewEventCounts(lifeCycle: LifeCycle, viewId: string, onChange: () => void) {\n  const { stop, eventCounts } = trackEventCounts({\n    lifeCycle,\n    isChildEvent: (event) => event.view.id === viewId,\n    onChange,\n  })\n\n  return {\n    stop,\n    eventCounts,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/trackViews.spec.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { PageExitReason, timeStampNow, display, relativeToClocks, relativeNow } from '@datadog/browser-core'\n\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask, createNewEvent } from '@datadog/browser-core/test'\nimport { createPerformanceEntry, mockPerformanceObserver } from '../../../test'\nimport type { AssembledRumEvent } from '../../rawRumEvent.types'\nimport { RumEventType, ViewLoadingType } from '../../rawRumEvent.types'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { RumPerformanceEntry } from '../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../browser/performanceObservable'\nimport { PAGE_ACTIVITY_END_DELAY } from '../waitPageActivityEnd'\nimport type { ViewEvent } from './trackViews'\nimport { SESSION_KEEP_ALIVE_INTERVAL, THROTTLE_VIEW_UPDATE_PERIOD, KEEP_TRACKING_AFTER_VIEW_DELAY } from './trackViews'\nimport type { ViewTest } from './setupViewTest.specHelper'\nimport { setupViewTest } from './setupViewTest.specHelper'\nimport { isLayoutShiftSupported } from './viewMetrics/trackCumulativeLayoutShift'\n\ndescribe('track views automatically', () => {\n  const lifeCycle = new LifeCycle()\n  let changeLocation: (to: string) => void\n  let viewTest: ViewTest\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n\n    viewTest = setupViewTest({ lifeCycle, initialLocation: 'http://foo.com/foo' }, { name: 'initial view name' })\n    changeLocation = viewTest.changeLocation\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  describe('initial view', () => {\n    it('should be created on start', () => {\n      const { getViewCreate, getViewCreateCount } = viewTest\n\n      expect(getViewCreateCount()).toBe(1)\n      expect(getViewCreate(0).name).toBe('initial view name')\n    })\n  })\n\n  describe('location changes', () => {\n    it('should create new view on path change', () => {\n      const { getViewCreateCount } = viewTest\n\n      expect(getViewCreateCount()).toBe(1)\n\n      changeLocation('/bar')\n\n      expect(getViewCreateCount()).toBe(2)\n    })\n\n    it('should create new view on hash change from history', () => {\n      const { getViewCreateCount } = viewTest\n\n      expect(getViewCreateCount()).toBe(1)\n\n      changeLocation('/foo#bar')\n\n      expect(getViewCreateCount()).toBe(2)\n    })\n\n    function mockGetElementById() {\n      const fakeGetElementById = (elementId: string) => (elementId === 'testHashValue') as any as HTMLElement\n      return spyOn(document, 'getElementById').and.callFake(fakeGetElementById)\n    }\n\n    it('should not create a new view when it is an Anchor navigation', () => {\n      const { getViewCreateCount } = viewTest\n      mockGetElementById()\n      expect(getViewCreateCount()).toBe(1)\n\n      changeLocation('/foo#testHashValue')\n\n      expect(getViewCreateCount()).toBe(1)\n    })\n\n    it('should not create a new view when the search part of the hash changes', () => {\n      const { getViewCreateCount } = viewTest\n      changeLocation('/foo#bar')\n      expect(getViewCreateCount()).toBe(2)\n\n      changeLocation('/foo#bar?search=1')\n      changeLocation('/foo#bar?search=2')\n      changeLocation('/foo#bar?')\n      changeLocation('/foo#bar')\n\n      expect(getViewCreateCount()).toBe(2)\n    })\n\n    it('should keep the same URL when updating a view ended by a URL change', () => {\n      const { getViewUpdateCount, getViewUpdate } = viewTest\n      expect(getViewUpdateCount()).toEqual(1)\n\n      changeLocation('/bar')\n\n      expect(getViewUpdateCount()).toEqual(3)\n      expect(getViewUpdate(0).location.href).toEqual('http://foo.com/foo')\n      expect(getViewUpdate(1).location.href).toEqual('http://foo.com/foo')\n      expect(getViewUpdate(2).location.href).toEqual('http://foo.com/bar')\n    })\n\n    it('should ignore URL parameter changes', () => {\n      expect(viewTest.getViewUpdateCount()).toEqual(1)\n\n      changeLocation('/foo?bar=bar')\n      changeLocation('/foo?bar=qux')\n\n      expect(viewTest.getViewUpdateCount()).toEqual(1)\n      expect(viewTest.getViewUpdate(0).location.href).toEqual('http://foo.com/foo')\n    })\n\n    it('should keep the same URL when updating an ended view', () => {\n      const initialView = viewTest.getViewUpdate(0)\n      changeLocation('/bar')\n      expect(viewTest.getViewUpdateCount()).toEqual(3)\n\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n        type: RumEventType.ERROR,\n        view: { id: initialView.id },\n      } as AssembledRumEvent)\n\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      expect(viewTest.getViewUpdateCount()).toEqual(4)\n      expect(viewTest.getViewUpdate(3).location.href).toEqual(initialView.location.href)\n      expect(viewTest.getViewUpdate(3).id).toEqual(initialView.id)\n    })\n  })\n})\n\ndescribe('view lifecycle', () => {\n  let lifeCycle: LifeCycle\n  let viewTest: ViewTest\n  let clock: Clock\n  let notifySpy: jasmine.Spy\n  let changeLocation: (to: string) => void\n\n  beforeEach(() => {\n    clock = mockClock()\n    lifeCycle = new LifeCycle()\n    notifySpy = spyOn(lifeCycle, 'notify').and.callThrough()\n\n    viewTest = setupViewTest(\n      { lifeCycle, initialLocation: '/foo' },\n      {\n        name: 'initial view name',\n        service: 'initial service',\n        version: 'initial version',\n      }\n    )\n\n    changeLocation = viewTest.changeLocation\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  describe('expire session', () => {\n    it('should end the view when the session expires', () => {\n      const { getViewEndCount } = viewTest\n\n      expect(getViewEndCount()).toBe(0)\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n      expect(getViewEndCount()).toBe(1)\n    })\n\n    it('should send a final view update', () => {\n      const { getViewUpdateCount, getViewUpdate } = viewTest\n\n      expect(getViewUpdateCount()).toBe(1)\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n      expect(getViewUpdateCount()).toBe(2)\n      expect(getViewUpdate(0).sessionIsActive).toBe(true)\n      expect(getViewUpdate(1).sessionIsActive).toBe(false)\n    })\n\n    it('should not start a new view if the session expired', () => {\n      const { getViewCreateCount } = viewTest\n\n      expect(getViewCreateCount()).toBe(1)\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n      expect(getViewCreateCount()).toBe(1)\n    })\n\n    it('should not end the view again if the view is already ended', () => {\n      const { getViewEndCount, getViewUpdateCount } = viewTest\n\n      expect(getViewEndCount()).toBe(0)\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n      expect(getViewEndCount()).toBe(1)\n      expect(getViewUpdateCount()).toBe(2)\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n      expect(getViewEndCount()).toBe(1)\n      expect(getViewUpdateCount()).toBe(2)\n    })\n  })\n\n  describe('renew session', () => {\n    it('should create new view on renew session', () => {\n      const { getViewCreateCount } = viewTest\n\n      expect(getViewCreateCount()).toBe(1)\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n      lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n      expect(getViewCreateCount()).toBe(2)\n    })\n\n    it('should use the current view name, service and version for the new view', () => {\n      const { getViewCreateCount, getViewCreate, startView } = viewTest\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n      lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n      startView({ name: 'view 1', service: 'service 1', version: 'version 1' })\n      startView({ name: 'view 2', service: 'service 2', version: 'version 2' })\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n      lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n      startView({ name: 'view 3', service: 'service 3', version: 'version 3' })\n      changeLocation('/bar')\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n      lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)\n\n      expect(getViewCreateCount()).toBe(8)\n\n      expect(getViewCreate(0)).toEqual(\n        jasmine.objectContaining({\n          name: 'initial view name',\n          service: 'initial service',\n          version: 'initial version',\n        })\n      )\n      expect(getViewCreate(1)).toEqual(\n        jasmine.objectContaining({\n          name: 'initial view name',\n          service: 'initial service',\n          version: 'initial version',\n        })\n      )\n      expect(getViewCreate(2)).toEqual(\n        jasmine.objectContaining({\n          name: 'view 1',\n          service: 'service 1',\n          version: 'version 1',\n        })\n      )\n      expect(getViewCreate(3)).toEqual(\n        jasmine.objectContaining({\n          name: 'view 2',\n          service: 'service 2',\n          version: 'version 2',\n        })\n      )\n      expect(getViewCreate(4)).toEqual(\n        jasmine.objectContaining({\n          name: 'view 2',\n          service: 'service 2',\n          version: 'version 2',\n        })\n      )\n      expect(getViewCreate(5)).toEqual(\n        jasmine.objectContaining({\n          name: 'view 3',\n          service: 'service 3',\n          version: 'version 3',\n        })\n      )\n      expect(getViewCreate(6)).toEqual(\n        jasmine.objectContaining({\n          name: undefined,\n          service: undefined,\n          version: undefined,\n        })\n      )\n      expect(getViewCreate(7)).toEqual(\n        jasmine.objectContaining({\n          name: undefined,\n          service: undefined,\n          version: undefined,\n        })\n      )\n    })\n  })\n\n  describe('session keep alive', () => {\n    it('should emit a view update periodically', () => {\n      const { getViewUpdateCount } = viewTest\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD) // make sure we don't have pending update\n\n      const previousViewUpdateCount = getViewUpdateCount()\n\n      clock.tick(SESSION_KEEP_ALIVE_INTERVAL)\n\n      expect(getViewUpdateCount()).toEqual(previousViewUpdateCount + 1)\n    })\n\n    it('should not send periodical updates after the session has expired', () => {\n      const { getViewUpdateCount } = viewTest\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD) // make sure we don't have pending update\n\n      lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n      const previousViewUpdateCount = getViewUpdateCount()\n\n      clock.tick(SESSION_KEEP_ALIVE_INTERVAL)\n\n      expect(getViewUpdateCount()).toBe(previousViewUpdateCount)\n    })\n  })\n\n  describe('page exit', () => {\n    ;[\n      { exitReason: PageExitReason.UNLOADING },\n      { exitReason: PageExitReason.FROZEN },\n      { exitReason: PageExitReason.HIDDEN },\n    ].forEach(({ exitReason }) => {\n      it(`should not end the current view when the page is exiting for reason ${exitReason}`, () => {\n        const { getViewEndCount } = viewTest\n\n        expect(getViewEndCount()).toEqual(0)\n\n        lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: exitReason })\n\n        expect(getViewEndCount()).toEqual(0)\n      })\n    })\n\n    it('should trigger a view update on unloading', () => {\n      const { getViewUpdateCount } = viewTest\n\n      expect(getViewUpdateCount()).toEqual(1)\n\n      lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.UNLOADING })\n\n      expect(getViewUpdateCount()).toEqual(2)\n    })\n\n    it('should not create a new view when ending the view on unloading', () => {\n      const { getViewCreateCount } = viewTest\n\n      expect(getViewCreateCount()).toEqual(1)\n\n      lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.UNLOADING })\n\n      expect(getViewCreateCount()).toEqual(1)\n    })\n\n    it('should not set the view as inactive on unloading', () => {\n      const { getViewUpdate, getViewUpdateCount } = viewTest\n\n      lifeCycle.notify(LifeCycleEventType.PAGE_MAY_EXIT, { reason: PageExitReason.UNLOADING })\n\n      expect(getViewUpdate(getViewUpdateCount() - 1).isActive).toBe(true)\n    })\n  })\n\n  it('should notify BEFORE_VIEW_CREATED before VIEW_CREATED', () => {\n    expect(notifySpy.calls.argsFor(0)[0]).toEqual(LifeCycleEventType.BEFORE_VIEW_CREATED)\n    expect(notifySpy.calls.argsFor(1)[0]).toEqual(LifeCycleEventType.VIEW_CREATED)\n  })\n\n  it('should notify AFTER_VIEW_ENDED after VIEW_ENDED', () => {\n    const callsCount = notifySpy.calls.count()\n\n    viewTest.stop()\n\n    expect(notifySpy.calls.argsFor(callsCount)[0]).toEqual(LifeCycleEventType.VIEW_ENDED)\n    expect(notifySpy.calls.argsFor(callsCount + 1)[0]).toEqual(LifeCycleEventType.AFTER_VIEW_ENDED)\n  })\n})\n\ndescribe('view loading type', () => {\n  const lifeCycle = new LifeCycle()\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    mockClock()\n\n    viewTest = setupViewTest({ lifeCycle })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should collect initial view type as \"initial_load\"', () => {\n    const { getViewUpdate } = viewTest\n\n    expect(getViewUpdate(0).loadingType).toEqual(ViewLoadingType.INITIAL_LOAD)\n  })\n\n  it('should collect view type as \"route_change\" after a view change', () => {\n    const { getViewUpdate, startView } = viewTest\n\n    startView()\n\n    expect(getViewUpdate(1).loadingType).toEqual(ViewLoadingType.INITIAL_LOAD)\n    expect(getViewUpdate(2).loadingType).toEqual(ViewLoadingType.ROUTE_CHANGE)\n  })\n})\n\ndescribe('view metrics', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let viewTest: ViewTest\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  beforeEach(() => {\n    clock = mockClock()\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n    viewTest = setupViewTest({ lifeCycle })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  describe('common view metrics', () => {\n    it('should be updated when notified with a PERFORMANCE_ENTRY_COLLECTED event (throttled)', () => {\n      if (!isLayoutShiftSupported()) {\n        pending('CLS web vital not supported')\n      }\n      const { getViewUpdateCount, getViewUpdate } = viewTest\n\n      expect(getViewUpdateCount()).toEqual(1)\n      expect(getViewUpdate(0).initialViewMetrics).toEqual({})\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT)])\n\n      expect(getViewUpdateCount()).toEqual(1)\n\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      expect(getViewUpdateCount()).toEqual(2)\n      expect(getViewUpdate(1).commonViewMetrics.cumulativeLayoutShift).toEqual({\n        value: 0.1,\n        targetSelector: undefined,\n        time: clock.relative(0),\n        previousRect: undefined,\n        currentRect: undefined,\n        devicePixelRatio: jasmine.any(Number),\n      })\n    })\n\n    it('should not be updated after view end', () => {\n      if (!isLayoutShiftSupported()) {\n        pending('CLS web vital not supported')\n      }\n      const { getViewUpdate, getViewUpdateCount, getViewCreateCount, startView } = viewTest\n      startView()\n      clock.tick(0) // run immediate timeouts (mostly for `trackNavigationTimings`)\n      expect(getViewCreateCount()).toEqual(2)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT)])\n\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      const latestUpdate = getViewUpdate(getViewUpdateCount() - 1)\n      const firstView = getViewUpdate(0)\n      expect(latestUpdate.id).not.toBe(firstView.id)\n    })\n  })\n\n  describe('initial view metrics', () => {\n    it('updates should be throttled', () => {\n      const { getViewUpdateCount, getViewUpdate } = viewTest\n      expect(getViewUpdateCount()).toEqual(1)\n      expect(getViewUpdate(0).initialViewMetrics).toEqual({})\n\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD - 1)\n\n      expect(getViewUpdateCount()).toEqual(1)\n      expect(getViewUpdate(0).initialViewMetrics).toEqual({})\n\n      clock.tick(1)\n\n      expect(getViewUpdateCount()).toEqual(2)\n      expect(getViewUpdate(1).initialViewMetrics.navigationTimings).toEqual(jasmine.any(Object))\n    })\n\n    it('should be updated for 5 min after view end', () => {\n      const { getViewCreateCount, getViewUpdate, getViewUpdateCount, startView } = viewTest\n      startView()\n      expect(getViewCreateCount()).toEqual(2)\n\n      const lcpEntry = createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT)\n      clock.tick(KEEP_TRACKING_AFTER_VIEW_DELAY - 1)\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.PAINT), lcpEntry])\n\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      const latestUpdate = getViewUpdate(getViewUpdateCount() - 1)\n      const firstView = getViewUpdate(0)\n      expect(latestUpdate.id).toBe(firstView.id)\n      expect(latestUpdate.initialViewMetrics.largestContentfulPaint?.value).toEqual(lcpEntry.startTime)\n    })\n\n    it('should not be updated 5 min after view end', () => {\n      const { getViewCreateCount, getViewUpdate, getViewUpdateCount, startView } = viewTest\n      startView()\n      expect(getViewCreateCount()).toEqual(2)\n\n      clock.tick(KEEP_TRACKING_AFTER_VIEW_DELAY)\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.PAINT),\n        createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT),\n      ])\n\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      const latestUpdate = getViewUpdate(getViewUpdateCount() - 1)\n      const firstView = getViewUpdate(0)\n      expect(latestUpdate.id).not.toBe(firstView.id)\n    })\n\n    describe('when load event happening after initial view end', () => {\n      let initialView: { init: ViewEvent; end: ViewEvent; last: ViewEvent }\n      let secondView: { init: ViewEvent; last: ViewEvent }\n      let viewDuration: Duration\n\n      beforeEach(() => {\n        const { getViewUpdateCount, getViewUpdate, startView } = viewTest\n\n        expect(getViewUpdateCount()).toEqual(1)\n\n        // `loadingTime` relies on the \"page activity\". To make sure we have a valid value, we need\n        // to wait for the page activity time to be known.\n        clock.tick(PAGE_ACTIVITY_END_DELAY)\n\n        viewDuration = relativeNow()\n\n        startView()\n\n        expect(getViewUpdateCount()).toEqual(3)\n\n        notifyPerformanceEntries([\n          createPerformanceEntry(RumPerformanceEntryType.PAINT),\n          createPerformanceEntry(RumPerformanceEntryType.NAVIGATION),\n          createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT),\n        ])\n\n        clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n        expect(getViewUpdateCount()).toEqual(4)\n\n        initialView = {\n          end: getViewUpdate(1),\n          init: getViewUpdate(0),\n          last: getViewUpdate(3),\n        }\n        secondView = {\n          init: getViewUpdate(2),\n          last: getViewUpdate(2),\n        }\n      })\n\n      it('should not be added on second view', () => {\n        expect(secondView.last.initialViewMetrics).toEqual({})\n      })\n\n      it('should be added only on the initial view', () => {\n        expect(initialView.last.initialViewMetrics).toEqual(\n          jasmine.objectContaining({\n            firstContentfulPaint: 123 as Duration,\n            navigationTimings: jasmine.any(Object),\n            largestContentfulPaint: {\n              value: 789 as Duration,\n              targetSelector: undefined,\n              resourceUrl: undefined,\n              subParts: {\n                loadDelay: 0,\n                loadTime: 0,\n                renderDelay: 666,\n              },\n            },\n          })\n        )\n      })\n\n      it('should not update the initial view duration when updating it with new timings', () => {\n        expect(initialView.end.duration).toBe(viewDuration)\n        expect(initialView.last.duration).toBe(viewDuration)\n      })\n\n      it('should update the initial view loadingTime following the loadEventEnd value', () => {\n        expect(initialView.last.commonViewMetrics.loadingTime).toEqual(jasmine.any(Number))\n      })\n    })\n  })\n})\n\ndescribe('view is active', () => {\n  const lifeCycle = new LifeCycle()\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    viewTest = setupViewTest({ lifeCycle })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should set initial view as active', () => {\n    const { getViewUpdate } = viewTest\n\n    expect(getViewUpdate(0).isActive).toBe(true)\n  })\n\n  it('should set old view as inactive and new one as active after a route change', () => {\n    const { getViewUpdate, startView } = viewTest\n\n    startView()\n\n    expect(getViewUpdate(1).isActive).toBe(false)\n    expect(getViewUpdate(2).isActive).toBe(true)\n  })\n})\n\ndescribe('view custom timings', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    clock = mockClock()\n    viewTest = setupViewTest({ lifeCycle, initialLocation: '/foo' })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should add custom timing to current view', () => {\n    clock.tick(0) // run immediate timeouts (mostly for `trackNavigationTimings`)\n    const { getViewUpdate, startView, addTiming } = viewTest\n\n    startView()\n\n    const currentViewId = getViewUpdate(2).id\n    clock.tick(20)\n    addTiming('foo')\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const view = getViewUpdate(3)\n    expect(view.id).toEqual(currentViewId)\n    expect(view.customTimings).toEqual({ foo: 20 as Duration })\n  })\n\n  it('should add multiple custom timings', () => {\n    const { getViewUpdate, addTiming } = viewTest\n\n    clock.tick(20)\n    addTiming('foo')\n\n    clock.tick(10)\n    addTiming('bar')\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const view = getViewUpdate(1)\n    expect(view.customTimings).toEqual({\n      bar: clock.relative(30),\n      foo: clock.relative(20),\n    })\n  })\n\n  it('should update custom timing', () => {\n    const { getViewUpdate, addTiming } = viewTest\n\n    clock.tick(20)\n    addTiming('foo')\n\n    clock.tick(10)\n    addTiming('bar')\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    let view = getViewUpdate(1)\n    expect(view.customTimings).toEqual({\n      bar: clock.relative(30),\n      foo: clock.relative(20),\n    })\n\n    clock.tick(20)\n    addTiming('foo')\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    view = getViewUpdate(2)\n    expect(view.customTimings).toEqual({\n      bar: clock.relative(30),\n      foo: clock.relative(THROTTLE_VIEW_UPDATE_PERIOD + 50),\n    })\n  })\n\n  it('should add custom timing with a specific timestamp', () => {\n    const { getViewUpdate, addTiming } = viewTest\n\n    clock.tick(1234)\n    addTiming('foo', timeStampNow())\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdate(1).customTimings).toEqual({\n      foo: clock.relative(1234),\n    })\n  })\n\n  it('should add custom timing with a specific relative time', () => {\n    const { getViewUpdate, addTiming } = viewTest\n\n    clock.tick(1234)\n    addTiming('foo', relativeNow())\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdate(1).customTimings).toEqual({\n      foo: clock.relative(1234),\n    })\n  })\n\n  it('should sanitized timing name', () => {\n    const { getViewUpdate, addTiming } = viewTest\n\n    const displaySpy = spyOn(display, 'warn')\n\n    clock.tick(1234)\n    addTiming('foo bar-qux.@zip_21%$*€👋', timeStampNow())\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdate(1).customTimings).toEqual({\n      'foo_bar-qux.@zip_21_$____': clock.relative(1234),\n    })\n    expect(displaySpy).toHaveBeenCalled()\n  })\n\n  it('should not add custom timing when the session has expired', () => {\n    clock.tick(0) // run immediate timeouts (mostly for `trackNavigationTimings`)\n    const { getViewUpdateCount, addTiming } = viewTest\n\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    expect(getViewUpdateCount()).toBe(2)\n\n    addTiming('foo', relativeNow())\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdateCount()).toBe(2)\n  })\n})\n\ndescribe('manual loading time', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    clock = mockClock()\n    viewTest = setupViewTest({ lifeCycle })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should set loading time on the current view', () => {\n    const { getViewUpdate, getViewUpdateCount, setLoadingTime } = viewTest\n\n    clock.tick(500)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const lastUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(lastUpdate.commonViewMetrics.loadingTime).toBe(clock.relative(500))\n  })\n\n  it('should overwrite loading time on subsequent calls (last-call-wins)', () => {\n    const { getViewUpdate, getViewUpdateCount, setLoadingTime } = viewTest\n\n    clock.tick(100)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const firstValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    clock.tick(200)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const lastUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(lastUpdate.commonViewMetrics.loadingTime).not.toBe(firstValue)\n  })\n\n  it('should not set loading time when the session has expired', () => {\n    clock.tick(0) // run immediate timeouts (mostly for `trackNavigationTimings`)\n    const { getViewUpdateCount, setLoadingTime } = viewTest\n\n    lifeCycle.notify(LifeCycleEventType.SESSION_EXPIRED)\n\n    const previousCount = getViewUpdateCount()\n\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdateCount()).toBe(previousCount)\n  })\n\n  it('should compute loading time relative to route-change view start', () => {\n    const { getViewUpdate, getViewUpdateCount, startView, setLoadingTime } = viewTest\n\n    clock.tick(2000)\n    startView()\n\n    clock.tick(500)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const lastUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(lastUpdate.loadingType).toBe(ViewLoadingType.ROUTE_CHANGE)\n    expect(lastUpdate.commonViewMetrics.loadingTime).toBe(500 as Duration)\n  })\n\n  it('should suppress auto-detected loading time after manual call', () => {\n    const { getViewUpdate, getViewUpdateCount, setLoadingTime } = viewTest\n\n    clock.tick(100)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const manualValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    clock.tick(PAGE_ACTIVITY_END_DELAY)\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const lastUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(lastUpdate.commonViewMetrics.loadingTime).toBe(manualValue)\n  })\n\n  it('should start with clean loading time state on new view', () => {\n    const { getViewUpdate, getViewUpdateCount, startView, setLoadingTime } = viewTest\n\n    clock.tick(100)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    startView()\n\n    clock.tick(200)\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const lastUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(lastUpdate.loadingType).toBe(ViewLoadingType.ROUTE_CHANGE)\n    expect(lastUpdate.commonViewMetrics.loadingTime).toBeDefined()\n  })\n\n  it('should trigger a view update after setLoadingTime', () => {\n    const { getViewUpdateCount, setLoadingTime } = viewTest\n\n    const countBefore = getViewUpdateCount()\n\n    setLoadingTime()\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdateCount()).toBeGreaterThan(countBefore)\n  })\n\n  it('should stop auto-detection tracking after first manual loading time', () => {\n    const { getViewUpdate, getViewUpdateCount, setLoadingTime } = viewTest\n\n    clock.tick(100)\n    setLoadingTime() // first call -- should stop auto-detection tracking\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const firstValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    clock.tick(200)\n    setLoadingTime() // second call\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const secondValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    // Let page activity end fire (would set auto-detected loading time if tracking wasn't stopped)\n    clock.tick(PAGE_ACTIVITY_END_DELAY)\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    // Auto-detection should not have replaced the second value\n    const finalUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(finalUpdate.commonViewMetrics.loadingTime).toBe(secondValue)\n    expect(finalUpdate.commonViewMetrics.loadingTime).not.toBe(firstValue)\n  })\n\n  it('should replace loading time on a route-change view with correct elapsed time', () => {\n    const { getViewUpdate, getViewUpdateCount, startView, setLoadingTime } = viewTest\n\n    clock.tick(2000) // 2s into session\n    startView() // new route-change view starts\n\n    clock.tick(300) // 300ms into new view\n    setLoadingTime() // first manual set: 300ms from view start\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const firstValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    clock.tick(200) // 200ms later (500ms + THROTTLE total from view start)\n    setLoadingTime() // second call replaces previous value\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const lastUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(lastUpdate.loadingType).toBe(ViewLoadingType.ROUTE_CHANGE)\n    expect(lastUpdate.commonViewMetrics.loadingTime).not.toBe(firstValue)\n    // Loading time should be relative to view start, not time origin\n    // Value = 300 + THROTTLE_VIEW_UPDATE_PERIOD + 200 (all ms from view start)\n    expect(lastUpdate.commonViewMetrics.loadingTime).toBe((300 + THROTTLE_VIEW_UPDATE_PERIOD + 200) as Duration)\n  })\n\n  it('should allow multiple calls, each replacing the previous value (last-call-wins)', () => {\n    const { getViewUpdate, getViewUpdateCount, setLoadingTime } = viewTest\n\n    clock.tick(100)\n    setLoadingTime() // first call: 100ms\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const firstValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    clock.tick(200)\n    setLoadingTime() // second call\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const secondValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    clock.tick(300)\n    setLoadingTime() // third call\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n    const thirdValue = getViewUpdate(getViewUpdateCount() - 1).commonViewMetrics.loadingTime\n\n    // Each value should be larger than the previous (more time elapsed)\n    expect(secondValue).toBeGreaterThan(firstValue as number)\n    expect(thirdValue).toBeGreaterThan(secondValue as number)\n    // Final value should be the cumulative elapsed time from time origin (initial view uses clocksOrigin)\n    expect(thirdValue).toBe(clock.relative(100 + THROTTLE_VIEW_UPDATE_PERIOD + 200 + THROTTLE_VIEW_UPDATE_PERIOD + 300))\n  })\n})\n\ndescribe('start view', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    clock = mockClock()\n    viewTest = setupViewTest({ lifeCycle })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should start a new view', () => {\n    const { getViewUpdateCount, getViewUpdate, startView } = viewTest\n\n    expect(getViewUpdateCount()).toBe(1)\n    const initialViewId = getViewUpdate(0).id\n\n    clock.tick(10)\n    startView()\n\n    expect(getViewUpdateCount()).toBe(3)\n\n    expect(getViewUpdate(1).id).toBe(initialViewId)\n    expect(getViewUpdate(1).isActive).toBe(false)\n    expect(getViewUpdate(1).startClocks.relative).toBe(0 as RelativeTime)\n    expect(getViewUpdate(1).duration).toBe(clock.relative(10))\n\n    expect(getViewUpdate(2).id).not.toBe(initialViewId)\n    expect(getViewUpdate(2).isActive).toBe(true)\n    expect(getViewUpdate(2).startClocks.relative).toBe(clock.relative(10))\n  })\n\n  it('should name the view', () => {\n    const { getViewUpdate, startView } = viewTest\n\n    startView()\n    startView({ name: 'foo' })\n    startView({ name: 'bar' })\n\n    expect(getViewUpdate(2).name).toBeUndefined()\n    expect(getViewUpdate(4).name).toBe('foo')\n    expect(getViewUpdate(6).name).toBe('bar')\n  })\n\n  it('should have service and version', () => {\n    const { getViewUpdate, startView } = viewTest\n\n    startView()\n    startView({ service: 'service 1', version: 'version 1' })\n    startView({ service: 'service 2', version: 'version 2' })\n\n    expect(getViewUpdate(2)).toEqual(\n      jasmine.objectContaining({\n        service: undefined,\n        version: undefined,\n      })\n    )\n    expect(getViewUpdate(4)).toEqual(\n      jasmine.objectContaining({\n        service: 'service 1',\n        version: 'version 1',\n      })\n    )\n    expect(getViewUpdate(6)).toEqual(\n      jasmine.objectContaining({\n        service: 'service 2',\n        version: 'version 2',\n      })\n    )\n  })\n\n  it('should ignore null service/version', () => {\n    const { getViewUpdate, startView } = viewTest\n\n    startView({ service: null, version: null })\n    expect(getViewUpdate(2)).toEqual(\n      jasmine.objectContaining({\n        service: undefined,\n        version: undefined,\n      })\n    )\n  })\n\n  it('should use the provided clock to stop the current view and start the new one', () => {\n    const { getViewUpdate, startView } = viewTest\n\n    clock.tick(100)\n    startView({ name: 'foo' }, relativeToClocks(50 as RelativeTime))\n\n    expect(getViewUpdate(1).duration).toBe(50 as Duration)\n    expect(getViewUpdate(2).startClocks.relative).toBe(50 as RelativeTime)\n  })\n\n  it('should create view with handling stack', () => {\n    const { startView, getViewUpdate } = viewTest\n\n    startView({ name: 'foo', handlingStack: 'Error\\n    at foo\\n    at bar' })\n\n    // The new view is at index 2 (after the initial view end and the new view start)\n    expect(getViewUpdate(2).handlingStack).toBe('Error\\n    at foo\\n    at bar')\n  })\n})\n\ndescribe('view event count', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    clock = mockClock()\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should be updated when notified with a RUM_EVENT_COLLECTED event', () => {\n    viewTest = setupViewTest({ lifeCycle })\n    const { getViewUpdate, getViewUpdateCount } = viewTest\n\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeActionEvent())\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    expect(getViewUpdate(getViewUpdateCount() - 1).eventCounts.actionCount).toBe(1)\n  })\n\n  it('should take child events occurring on view end into account', () => {\n    viewTest = setupViewTest({ lifeCycle, initialLocation: 'http://foo.com' })\n    const { getViewUpdate, getViewUpdateCount } = viewTest\n\n    lifeCycle.subscribe(LifeCycleEventType.VIEW_ENDED, () => {\n      lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, createFakeActionEvent())\n    })\n\n    viewTest.changeLocation('/bar')\n\n    expect(getViewUpdate(getViewUpdateCount() - 2).eventCounts.actionCount).toBe(1)\n  })\n\n  it('should be updated for 5 min after view end', () => {\n    viewTest = setupViewTest({ lifeCycle })\n    const { getViewUpdate, getViewUpdateCount, getViewCreateCount, startView } = viewTest\n    startView()\n    expect(getViewCreateCount()).toEqual(2)\n    const firstView = getViewUpdate(0)\n\n    clock.tick(KEEP_TRACKING_AFTER_VIEW_DELAY - 1)\n\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n      type: RumEventType.RESOURCE,\n      view: { id: firstView.id },\n    } as AssembledRumEvent)\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const latestUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(latestUpdate.id).toEqual(firstView.id)\n    expect(latestUpdate.eventCounts.resourceCount).toEqual(1)\n  })\n\n  it('should not be updated 5 min after view end', () => {\n    viewTest = setupViewTest({ lifeCycle })\n    const { getViewUpdate, getViewUpdateCount, getViewCreateCount, startView } = viewTest\n    startView()\n    expect(getViewCreateCount()).toEqual(2)\n    const firstView = getViewUpdate(0)\n\n    clock.tick(KEEP_TRACKING_AFTER_VIEW_DELAY)\n\n    lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, {\n      type: RumEventType.RESOURCE,\n      view: { id: firstView.id },\n    } as AssembledRumEvent)\n\n    clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n    const latestUpdate = getViewUpdate(getViewUpdateCount() - 1)\n    expect(latestUpdate.id).not.toEqual(firstView.id)\n  })\n\n  function createFakeActionEvent() {\n    return {\n      type: RumEventType.ACTION,\n      action: {},\n      view: viewTest.getLatestViewContext(),\n    } as AssembledRumEvent\n  }\n\n  describe('view specific context', () => {\n    it('should update view context if startView has context parameter', () => {\n      viewTest = setupViewTest({ lifeCycle })\n      const { getViewUpdate, startView } = viewTest\n\n      startView({ context: { foo: 'bar' } })\n      expect(getViewUpdate(2).context).toEqual({ foo: 'bar' })\n    })\n\n    it('should replace current context set on view event', () => {\n      viewTest = setupViewTest({ lifeCycle })\n      const { getViewUpdate, startView } = viewTest\n\n      startView({ context: { foo: 'bar' } })\n      expect(getViewUpdate(2).context).toEqual({ foo: 'bar' })\n\n      startView({ context: { bar: 'baz' } })\n      expect(getViewUpdate(4).context).toEqual({ bar: 'baz' })\n    })\n\n    it('should set view context with setViewContext', () => {\n      viewTest = setupViewTest({ lifeCycle })\n      const { getViewUpdate, setViewContext } = viewTest\n\n      setViewContext({ foo: 'bar' })\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      expect(getViewUpdate(1).context).toEqual({ foo: 'bar' })\n    })\n\n    it('should set view context with setViewContextProperty', () => {\n      viewTest = setupViewTest({ lifeCycle })\n      const { getViewUpdate, setViewContextProperty } = viewTest\n\n      setViewContextProperty('foo', 'bar')\n      clock.tick(THROTTLE_VIEW_UPDATE_PERIOD)\n\n      expect(getViewUpdate(1).context).toEqual({ foo: 'bar' })\n    })\n\n    it('should get view context with getViewContext', () => {\n      viewTest = setupViewTest({ lifeCycle })\n      const { getViewContext, setViewContextProperty } = viewTest\n\n      setViewContextProperty('foo', 'bar')\n      expect(getViewContext()).toEqual({ foo: 'bar' })\n    })\n  })\n\n  describe('set view name', () => {\n    it('should set an undefined view name', () => {\n      viewTest = setupViewTest({ lifeCycle })\n\n      const { getViewUpdate, startView, setViewName } = viewTest\n\n      startView()\n      setViewName('foo')\n      expect(getViewUpdate(3).name).toEqual('foo')\n    })\n\n    it('should set a defined view name', () => {\n      viewTest = setupViewTest({ lifeCycle })\n\n      const { getViewUpdate, startView, setViewName } = viewTest\n\n      startView({ name: 'initial view name' })\n      setViewName('foo')\n      expect(getViewUpdate(3).name).toEqual('foo')\n    })\n  })\n})\n\ndescribe('service and version', () => {\n  const lifeCycle = new LifeCycle()\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    mockClock()\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should come from the init configuration by default', () => {\n    viewTest = setupViewTest({ lifeCycle, partialConfig: { service: 'service', version: 'version' } })\n\n    const { getViewUpdate } = viewTest\n\n    expect(getViewUpdate(0).service).toEqual('service')\n    expect(getViewUpdate(0).version).toEqual('version')\n  })\n\n  it('should come from the view option if defined', () => {\n    viewTest = setupViewTest(\n      { lifeCycle, partialConfig: { service: 'service', version: 'version' } },\n      {\n        service: 'view service',\n        version: 'view version',\n      }\n    )\n\n    const { getViewUpdate } = viewTest\n\n    expect(getViewUpdate(0).service).toEqual('view service')\n    expect(getViewUpdate(0).version).toEqual('view version')\n  })\n})\n\ndescribe('BFCache views', () => {\n  const lifeCycle = new LifeCycle()\n  let viewTest: ViewTest\n\n  beforeEach(() => {\n    viewTest = setupViewTest({ lifeCycle, partialConfig: { trackBfcacheViews: true } })\n\n    registerCleanupTask(() => {\n      viewTest.stop()\n    })\n  })\n\n  it('should create a new \"bf_cache\" view when restoring from the BFCache', () => {\n    const { getViewCreateCount, getViewEndCount, getViewUpdate, getViewUpdateCount } = viewTest\n\n    expect(getViewCreateCount()).toBe(1)\n    expect(getViewEndCount()).toBe(0)\n\n    const event = createNewEvent('pageshow', { persisted: true })\n\n    window.dispatchEvent(event)\n\n    expect(getViewEndCount()).toBe(1)\n    expect(getViewCreateCount()).toBe(2)\n    expect(getViewUpdate(getViewUpdateCount() - 1).loadingType).toBe(ViewLoadingType.BF_CACHE)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/trackViews.ts",
    "content": "import type {\n  Duration,\n  ClocksState,\n  TimeStamp,\n  Subscription,\n  RelativeTime,\n  Context,\n  ContextValue,\n} from '@datadog/browser-core'\nimport {\n  noop,\n  PageExitReason,\n  shallowClone,\n  elapsed,\n  generateUUID,\n  ONE_MINUTE,\n  throttle,\n  clocksNow,\n  clocksOrigin,\n  relativeToClocks,\n  timeStampNow,\n  display,\n  looksLikeRelativeTime,\n  setInterval,\n  clearInterval,\n  setTimeout,\n  Observable,\n  createContextManager,\n  mockable,\n} from '@datadog/browser-core'\nimport type { ViewCustomTimings } from '../../rawRumEvent.types'\nimport { ViewLoadingType } from '../../rawRumEvent.types'\nimport type { LifeCycle } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { EventCounts } from '../trackEventCounts'\nimport type { LocationChange } from '../../browser/locationChangeObservable'\nimport type { RumConfiguration, RumInitConfiguration } from '../configuration'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { trackViewEventCounts } from './trackViewEventCounts'\nimport { trackInitialViewMetrics } from './viewMetrics/trackInitialViewMetrics'\nimport type { InitialViewMetrics } from './viewMetrics/trackInitialViewMetrics'\nimport type { CommonViewMetrics } from './viewMetrics/trackCommonViewMetrics'\nimport { trackCommonViewMetrics } from './viewMetrics/trackCommonViewMetrics'\nimport { onBFCacheRestore } from './bfCacheSupport'\nimport { trackBfcacheMetrics } from './viewMetrics/trackBfcacheMetrics'\n\nexport interface ViewEvent {\n  id: string\n  name?: string\n  service?: string\n  version?: string\n  context?: Context\n  location: Readonly<Location>\n  handlingStack?: string\n  commonViewMetrics: CommonViewMetrics\n  initialViewMetrics: InitialViewMetrics\n  customTimings: ViewCustomTimings\n  eventCounts: EventCounts\n  documentVersion: number\n  startClocks: ClocksState\n  duration: Duration\n  isActive: boolean\n  sessionIsActive: boolean\n  loadingType: ViewLoadingType\n}\n\nexport interface ViewCreatedEvent {\n  id: string\n  name?: string\n  service?: string\n  version?: string\n  context?: Context\n  startClocks: ClocksState\n  url?: string\n}\n\nexport interface BeforeViewUpdateEvent {\n  id: string\n  name?: string\n  context?: Context\n  startClocks: ClocksState\n  sessionIsActive: boolean\n}\n\nexport interface ViewEndedEvent {\n  endClocks: ClocksState\n}\n\nexport const THROTTLE_VIEW_UPDATE_PERIOD = 3000\nexport const SESSION_KEEP_ALIVE_INTERVAL = 5 * ONE_MINUTE\n\n// Some events or metrics can be captured after the end of the view. To avoid missing those;\n// an arbitrary delay is added for stopping their tracking after the view ends.\n//\n// Ideally, we would not stop and keep tracking events or metrics until the end of the session.\n// But this might have a small performance impact if there are many many views.\n// So let's have a fairly short delay improving the situation in most cases and avoid impacting performances too much.\nexport const KEEP_TRACKING_AFTER_VIEW_DELAY = 5 * ONE_MINUTE\n\nexport interface ViewOptions {\n  name?: string\n  service?: RumInitConfiguration['service']\n  version?: RumInitConfiguration['version']\n  context?: Context\n  handlingStack?: string\n  url?: string\n}\n\nexport function trackViews(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration,\n  locationChangeObservable: Observable<LocationChange>,\n  areViewsTrackedAutomatically: boolean,\n  initialViewOptions?: ViewOptions\n) {\n  const activeViews: Set<ReturnType<typeof newView>> = new Set()\n  let currentView = startNewView(ViewLoadingType.INITIAL_LOAD, clocksOrigin(), initialViewOptions)\n  let stopOnBFCacheRestore: (() => void) | undefined\n\n  startViewLifeCycle()\n\n  let locationChangeSubscription: Subscription\n  if (areViewsTrackedAutomatically) {\n    locationChangeSubscription = renewViewOnLocationChange(locationChangeObservable)\n    if (configuration.trackBfcacheViews) {\n      stopOnBFCacheRestore = onBFCacheRestore(configuration, (pageshowEvent) => {\n        currentView.end()\n        const startClocks = relativeToClocks(pageshowEvent.timeStamp as RelativeTime)\n        currentView = startNewView(ViewLoadingType.BF_CACHE, startClocks, undefined)\n      })\n    }\n  }\n\n  function startNewView(loadingType: ViewLoadingType, startClocks?: ClocksState, viewOptions?: ViewOptions) {\n    const newlyCreatedView = newView(\n      lifeCycle,\n      domMutationObservable,\n      windowOpenObservable,\n      configuration,\n      loadingType,\n      startClocks,\n      viewOptions\n    )\n    activeViews.add(newlyCreatedView)\n    newlyCreatedView.stopObservable.subscribe(() => {\n      activeViews.delete(newlyCreatedView)\n    })\n    return newlyCreatedView\n  }\n\n  function startViewLifeCycle() {\n    lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {\n      // Renew view on session renewal\n      currentView = startNewView(ViewLoadingType.ROUTE_CHANGE, undefined, {\n        name: currentView.name,\n        service: currentView.service,\n        version: currentView.version,\n        context: currentView.contextManager.getContext(),\n      })\n    })\n\n    lifeCycle.subscribe(LifeCycleEventType.SESSION_EXPIRED, () => {\n      currentView.end({ sessionIsActive: false })\n    })\n  }\n\n  function renewViewOnLocationChange(locationChangeObservable: Observable<LocationChange>) {\n    return locationChangeObservable.subscribe(({ oldLocation, newLocation }) => {\n      if (areDifferentLocation(oldLocation, newLocation)) {\n        currentView.end()\n        currentView = startNewView(ViewLoadingType.ROUTE_CHANGE)\n      }\n    })\n  }\n\n  return {\n    addTiming: (name: string, time: RelativeTime | TimeStamp = timeStampNow()) => {\n      currentView.addTiming(name, time)\n    },\n    setLoadingTime: (callTimestamp?: TimeStamp) => currentView.setLoadingTime(callTimestamp),\n    startView: (options?: ViewOptions, startClocks?: ClocksState) => {\n      currentView.end({ endClocks: startClocks })\n      currentView = startNewView(ViewLoadingType.ROUTE_CHANGE, startClocks, options)\n    },\n    setViewContext: (context: Context) => {\n      currentView.contextManager.setContext(context)\n    },\n    setViewContextProperty: (key: string, value: ContextValue) => {\n      currentView.contextManager.setContextProperty(key, value)\n    },\n    setViewName: (name: string) => {\n      currentView.setViewName(name)\n    },\n    getViewContext: () => currentView.contextManager.getContext(),\n\n    stop: () => {\n      if (locationChangeSubscription) {\n        locationChangeSubscription.unsubscribe()\n      }\n      if (stopOnBFCacheRestore) {\n        stopOnBFCacheRestore()\n      }\n      currentView.end()\n      activeViews.forEach((view) => view.stop())\n    },\n  }\n}\n\nfunction newView(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration,\n  loadingType: ViewLoadingType,\n  startClocks: ClocksState = clocksNow(),\n  viewOptions?: ViewOptions\n) {\n  // Setup initial values\n  const id = generateUUID()\n  const stopObservable = new Observable<void>()\n  const customTimings: ViewCustomTimings = {}\n  let documentVersion = 0\n  let endClocks: ClocksState | undefined\n  const location = shallowClone(mockable(window.location))\n  const contextManager = createContextManager()\n\n  let sessionIsActive = true\n  let name = viewOptions?.name\n  const service = viewOptions?.service || configuration.service\n  const version = viewOptions?.version || configuration.version\n  const context = viewOptions?.context\n  const handlingStack = viewOptions?.handlingStack\n\n  if (context) {\n    contextManager.setContext(context)\n  }\n\n  const viewCreatedEvent = {\n    id,\n    name,\n    startClocks,\n    service,\n    version,\n    context,\n    url: viewOptions?.url,\n  }\n  lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_CREATED, viewCreatedEvent)\n  lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, viewCreatedEvent)\n\n  // Update the view every time the measures are changing\n  const { throttled, cancel: cancelScheduleViewUpdate } = throttle(triggerViewUpdate, THROTTLE_VIEW_UPDATE_PERIOD, {\n    leading: false,\n  })\n\n  const {\n    setLoadEvent,\n    setViewEnd,\n    stop: stopCommonViewMetricsTracking,\n    stopINPTracking,\n    getCommonViewMetrics,\n    setLoadingTime,\n  } = trackCommonViewMetrics(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration,\n    scheduleViewUpdate,\n    loadingType,\n    startClocks\n  )\n\n  const { stop: stopInitialViewMetricsTracking, initialViewMetrics } =\n    loadingType === ViewLoadingType.INITIAL_LOAD\n      ? trackInitialViewMetrics(configuration, startClocks, setLoadEvent, scheduleViewUpdate)\n      : { stop: noop, initialViewMetrics: {} as InitialViewMetrics }\n\n  // Start BFCache-specific metrics when restoring from BFCache\n  if (loadingType === ViewLoadingType.BF_CACHE) {\n    trackBfcacheMetrics(startClocks, initialViewMetrics, scheduleViewUpdate)\n  }\n\n  const { stop: stopEventCountsTracking, eventCounts } = trackViewEventCounts(lifeCycle, id, scheduleViewUpdate)\n\n  // Session keep alive\n  const keepAliveIntervalId = setInterval(triggerViewUpdate, SESSION_KEEP_ALIVE_INTERVAL)\n\n  const pageMayExitSubscription = lifeCycle.subscribe(LifeCycleEventType.PAGE_MAY_EXIT, (pageMayExitEvent) => {\n    if (pageMayExitEvent.reason === PageExitReason.UNLOADING) {\n      triggerViewUpdate()\n    }\n  })\n\n  // Initial view update\n  triggerViewUpdate()\n\n  // View context update should always be throttled\n  contextManager.changeObservable.subscribe(scheduleViewUpdate)\n\n  function triggerBeforeViewUpdate() {\n    lifeCycle.notify(LifeCycleEventType.BEFORE_VIEW_UPDATED, {\n      id,\n      name,\n      context: contextManager.getContext(),\n      startClocks,\n      sessionIsActive,\n    })\n  }\n\n  function scheduleViewUpdate() {\n    triggerBeforeViewUpdate()\n    throttled()\n  }\n\n  function triggerViewUpdate() {\n    cancelScheduleViewUpdate()\n    triggerBeforeViewUpdate()\n\n    documentVersion += 1\n    const currentEnd = endClocks === undefined ? timeStampNow() : endClocks.timeStamp\n    lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, {\n      customTimings,\n      documentVersion,\n      id,\n      name,\n      service,\n      version,\n      context: contextManager.getContext(),\n      loadingType,\n      location,\n      handlingStack,\n      startClocks,\n      commonViewMetrics: getCommonViewMetrics(),\n      initialViewMetrics,\n      duration: elapsed(startClocks.timeStamp, currentEnd),\n      isActive: endClocks === undefined,\n      sessionIsActive,\n      eventCounts,\n    })\n  }\n\n  return {\n    get name() {\n      return name\n    },\n    service,\n    version,\n    contextManager,\n    stopObservable,\n    end(options: { endClocks?: ClocksState; sessionIsActive?: boolean } = {}) {\n      if (endClocks) {\n        // view already ended\n        return\n      }\n      endClocks = options.endClocks ?? clocksNow()\n      sessionIsActive = options.sessionIsActive ?? true\n\n      lifeCycle.notify(LifeCycleEventType.VIEW_ENDED, { endClocks })\n      lifeCycle.notify(LifeCycleEventType.AFTER_VIEW_ENDED, { endClocks })\n      clearInterval(keepAliveIntervalId)\n      setViewEnd(endClocks.relative)\n      stopCommonViewMetricsTracking()\n      pageMayExitSubscription.unsubscribe()\n      triggerViewUpdate()\n      setTimeout(() => {\n        this.stop()\n      }, KEEP_TRACKING_AFTER_VIEW_DELAY)\n    },\n    stop() {\n      stopInitialViewMetricsTracking()\n      stopEventCountsTracking()\n      stopINPTracking()\n      stopObservable.notify()\n    },\n    addTiming(name: string, time: RelativeTime | TimeStamp) {\n      if (endClocks) {\n        return\n      }\n      const relativeTime = looksLikeRelativeTime(time) ? time : elapsed(startClocks.timeStamp, time)\n      customTimings[sanitizeTiming(name)] = relativeTime\n      scheduleViewUpdate()\n    },\n    setLoadingTime,\n    setViewName(updatedName: string) {\n      name = updatedName\n      triggerViewUpdate()\n    },\n  }\n}\n\n/**\n * Timing name is used as facet path that must contain only letters, digits, or the characters - _ . @ $\n */\nfunction sanitizeTiming(name: string) {\n  const sanitized = name.replace(/[^a-zA-Z0-9-_.@$]/g, '_')\n  if (sanitized !== name) {\n    display.warn(`Invalid timing name: ${name}, sanitized to: ${sanitized}`)\n  }\n  return sanitized\n}\n\nfunction areDifferentLocation(currentLocation: Location, otherLocation: Location) {\n  return (\n    currentLocation.pathname !== otherLocation.pathname ||\n    (!isHashAnAnchor(otherLocation.hash) &&\n      getPathFromHash(otherLocation.hash) !== getPathFromHash(currentLocation.hash))\n  )\n}\n\nfunction isHashAnAnchor(hash: string) {\n  const correspondingId = hash.substring(1)\n  // check if the correspondingId is empty because on Firefox an empty string passed to getElementById() prints a consol warning\n  return correspondingId !== '' && !!document.getElementById(correspondingId)\n}\n\nfunction getPathFromHash(hash: string) {\n  const index = hash.indexOf('?')\n  return index < 0 ? hash : hash.slice(0, index)\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewCollection.spec.ts",
    "content": "import { DISCARDED, HookNames, Observable } from '@datadog/browser-core'\nimport type { Duration, RelativeTime, ServerDuration, TimeStamp } from '@datadog/browser-core'\nimport { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport type { RecorderApi } from '../../boot/rumPublicApi'\nimport { collectAndValidateRawRumEvents, mockRumConfiguration, mockViewHistory, noopRecorderApi } from '../../../test'\nimport type { RawRumEvent, RawRumViewEvent } from '../../rawRumEvent.types'\nimport { RumEventType, ViewLoadingType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport type { RumConfiguration } from '../configuration'\nimport type { LocationChange } from '../../browser/locationChangeObservable'\nimport type { ViewHistoryEntry } from '../contexts/viewHistory'\nimport type { AssembleHookParams, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport { createHooks } from '../hooks'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { startViewCollection } from './viewCollection'\nimport type { ViewEvent } from './trackViews'\n\nconst VIEW: ViewEvent = {\n  customTimings: {\n    bar: 20 as Duration,\n    foo: 10 as Duration,\n  },\n  documentVersion: 3,\n  duration: 100 as Duration,\n  eventCounts: {\n    errorCount: 10,\n    longTaskCount: 10,\n    resourceCount: 10,\n    actionCount: 10,\n    frustrationCount: 10,\n  },\n  id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',\n  name: undefined,\n  isActive: false,\n  loadingType: ViewLoadingType.INITIAL_LOAD,\n  location: {} as Location,\n  startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },\n  initialViewMetrics: {\n    navigationTimings: {\n      firstByte: 10 as Duration,\n      domComplete: 10 as Duration,\n      domContentLoaded: 10 as Duration,\n      domInteractive: 10 as Duration,\n      loadEvent: 10 as Duration,\n    },\n    firstInput: {\n      delay: 12 as Duration,\n      time: 10 as RelativeTime,\n    },\n    firstContentfulPaint: 10 as Duration,\n    largestContentfulPaint: { value: 10 as RelativeTime },\n  },\n  commonViewMetrics: {\n    loadingTime: 20 as Duration,\n    cumulativeLayoutShift: { value: 1, time: 100 as Duration },\n    interactionToNextPaint: { value: 10 as Duration, time: 100 as Duration },\n    scroll: {\n      maxDepth: 2000,\n      maxScrollHeight: 3000,\n      maxScrollHeightTime: 4000000000 as Duration,\n      maxDepthScrollTop: 1000,\n    },\n  },\n  sessionIsActive: true,\n}\n\ndescribe('viewCollection', () => {\n  const lifeCycle = new LifeCycle()\n  let hooks: Hooks\n  let getReplayStatsSpy: jasmine.Spy<RecorderApi['getReplayStats']>\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>> = []\n  function setupViewCollection(\n    partialConfiguration: Partial<RumConfiguration> = {},\n    viewHistoryEntry?: ViewHistoryEntry\n  ) {\n    hooks = createHooks()\n    const viewHistory = mockViewHistory(viewHistoryEntry)\n    getReplayStatsSpy = jasmine.createSpy()\n    const domMutationObservable = new Observable<RumMutationRecord[]>()\n    const windowOpenObservable = new Observable<void>()\n    const locationChangeObservable = new Observable<LocationChange>()\n    mockClock()\n\n    const collectionResult = startViewCollection(\n      lifeCycle,\n      hooks,\n      mockRumConfiguration(partialConfiguration),\n      domMutationObservable,\n      windowOpenObservable,\n      locationChangeObservable,\n      {\n        ...noopRecorderApi,\n        getReplayStats: getReplayStatsSpy,\n      },\n      viewHistory\n    )\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n\n    registerCleanupTask(() => {\n      collectionResult.stop()\n      viewHistory.stop()\n    })\n    return collectionResult\n  }\n\n  it('should create view from view update', () => {\n    setupViewCollection()\n    lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, VIEW)\n\n    expect(rawRumEvents[rawRumEvents.length - 1].startClocks.relative).toBe(1234 as RelativeTime)\n    expect(rawRumEvents[rawRumEvents.length - 1].rawRumEvent).toEqual({\n      _dd: {\n        document_version: 3,\n        replay_stats: undefined,\n        configuration: {\n          start_session_replay_recording_manually: jasmine.any(Boolean),\n        },\n        cls: undefined,\n      },\n      date: jasmine.any(Number),\n      type: RumEventType.VIEW,\n      view: {\n        action: {\n          count: 10,\n        },\n        frustration: {\n          count: 10,\n        },\n        cumulative_layout_shift: 1,\n        cumulative_layout_shift_target_selector: undefined,\n        cumulative_layout_shift_time: (100 * 1e6) as ServerDuration,\n        custom_timings: {\n          bar: (20 * 1e6) as ServerDuration,\n          foo: (10 * 1e6) as ServerDuration,\n        },\n        first_byte: (10 * 1e6) as ServerDuration,\n        dom_complete: (10 * 1e6) as ServerDuration,\n        dom_content_loaded: (10 * 1e6) as ServerDuration,\n        dom_interactive: (10 * 1e6) as ServerDuration,\n        error: {\n          count: 10,\n        },\n        first_contentful_paint: (10 * 1e6) as ServerDuration,\n        first_input_delay: (12 * 1e6) as ServerDuration,\n        first_input_time: (10 * 1e6) as ServerDuration,\n        first_input_target_selector: undefined,\n        interaction_to_next_paint: (10 * 1e6) as ServerDuration,\n        interaction_to_next_paint_target_selector: undefined,\n        interaction_to_next_paint_time: (100 * 1e6) as ServerDuration,\n        is_active: false,\n        name: undefined,\n        largest_contentful_paint: (10 * 1e6) as ServerDuration,\n        largest_contentful_paint_target_selector: undefined,\n        load_event: (10 * 1e6) as ServerDuration,\n        loading_time: (20 * 1e6) as ServerDuration,\n        loading_type: ViewLoadingType.INITIAL_LOAD,\n        long_task: {\n          count: 10,\n        },\n        performance: {\n          cls: {\n            score: 1,\n            timestamp: (100 * 1e6) as ServerDuration,\n            target_selector: undefined,\n            previous_rect: undefined,\n            current_rect: undefined,\n          },\n          fcp: {\n            timestamp: (10 * 1e6) as ServerDuration,\n          },\n          fid: {\n            duration: (12 * 1e6) as ServerDuration,\n            timestamp: (10 * 1e6) as ServerDuration,\n            target_selector: undefined,\n          },\n          inp: {\n            duration: (10 * 1e6) as ServerDuration,\n            timestamp: (100 * 1e6) as ServerDuration,\n            target_selector: undefined,\n            sub_parts: undefined,\n          },\n          lcp: {\n            timestamp: (10 * 1e6) as ServerDuration,\n            target_selector: undefined,\n            resource_url: undefined,\n            sub_parts: undefined,\n          },\n        },\n        resource: {\n          count: 10,\n        },\n        time_spent: (100 * 1e6) as ServerDuration,\n      },\n      display: {\n        scroll: {\n          max_depth: 2000,\n          max_depth_scroll_top: 1000,\n          max_scroll_height: 3000,\n          max_scroll_height_time: 4000000000000000 as ServerDuration,\n        },\n      },\n      privacy: { replay_level: 'mask' },\n      device: {\n        locale: jasmine.any(String),\n        locales: jasmine.any(Array),\n        time_zone: jasmine.any(String),\n      },\n    })\n  })\n\n  it('should discard negative loading time', () => {\n    setupViewCollection()\n    const view: ViewEvent = { ...VIEW, commonViewMetrics: { loadingTime: -20 as Duration } }\n    lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, view)\n    const rawRumViewEvent = rawRumEvents[rawRumEvents.length - 1].rawRumEvent as RawRumViewEvent\n\n    expect(rawRumViewEvent.view.loading_time).toBeUndefined()\n  })\n\n  it('should not include scroll metrics when there are not scroll metrics in the raw event', () => {\n    setupViewCollection()\n    lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, { ...VIEW, commonViewMetrics: { scroll: undefined } })\n    const rawRumViewEvent = rawRumEvents[rawRumEvents.length - 1].rawRumEvent as RawRumViewEvent\n\n    expect(rawRumViewEvent.display?.scroll).toBeUndefined()\n  })\n\n  describe('with configuration.start_session_replay_recording_manually set', () => {\n    it('should include startSessionReplayRecordingManually false', () => {\n      // when configured to false\n      setupViewCollection({ startSessionReplayRecordingManually: false })\n      lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, VIEW)\n\n      expect(\n        (rawRumEvents[rawRumEvents.length - 1].rawRumEvent as RawRumViewEvent)._dd.configuration\n          .start_session_replay_recording_manually\n      ).toBe(false)\n    })\n\n    it('should include startSessionReplayRecordingManually true', () => {\n      // when configured to true\n      setupViewCollection({ startSessionReplayRecordingManually: true })\n      lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, VIEW)\n\n      expect(\n        (rawRumEvents[rawRumEvents.length - 1].rawRumEvent as RawRumViewEvent)._dd.configuration\n          .start_session_replay_recording_manually\n      ).toBe(true)\n    })\n  })\n\n  describe('assembly hook', () => {\n    it('should add view properties from the history', () => {\n      setupViewCollection({ trackViewsManually: true }, VIEW)\n\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toEqual(\n        jasmine.objectContaining({\n          service: VIEW.service,\n          version: VIEW.version,\n          context: VIEW.context,\n          view: {\n            id: VIEW.id,\n            name: VIEW.name,\n          },\n        })\n      )\n    })\n\n    it('should discard the event if no view', () => {\n      const viewHistoryEntry = undefined\n      setupViewCollection({ trackViewsManually: true }, viewHistoryEntry)\n      const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {\n        eventType: 'view',\n        startTime: 0 as RelativeTime,\n      } as AssembleHookParams)\n\n      expect(defaultRumEventAttributes).toBe(DISCARDED)\n    })\n  })\n\n  describe('assemble telemetry hook', () => {\n    it('should add view id', () => {\n      setupViewCollection({ trackViewsManually: true }, VIEW)\n\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: VIEW.startClocks.relative,\n      }) as DefaultTelemetryEventAttributes\n\n      expect(telemetryEventAttributes.view?.id).toEqual('aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee')\n    })\n\n    it('should not add view id if no view', () => {\n      setupViewCollection({ trackViewsManually: true }, undefined)\n      const telemetryEventAttributes = hooks.triggerHook(HookNames.AssembleTelemetry, {\n        startTime: 0 as RelativeTime,\n      }) as DefaultTelemetryEventAttributes\n\n      expect(telemetryEventAttributes.view?.id).toBeUndefined()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewCollection.ts",
    "content": "import type { Duration, ServerDuration, Observable } from '@datadog/browser-core'\nimport { getTimeZone, DISCARDED, HookNames, isEmptyObject, mapValues, toServerDuration } from '@datadog/browser-core'\nimport { discardNegativeDuration } from '../discardNegativeDuration'\nimport type { RecorderApi } from '../../boot/rumPublicApi'\nimport type { RawRumViewEvent, ViewPerformanceData } from '../../rawRumEvent.types'\nimport { RumEventType } from '../../rawRumEvent.types'\nimport type { LifeCycle, RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { LocationChange } from '../../browser/locationChangeObservable'\nimport type { RumConfiguration } from '../configuration'\nimport type { ViewHistory } from '../contexts/viewHistory'\nimport type { DefaultRumEventAttributes, DefaultTelemetryEventAttributes, Hooks } from '../hooks'\nimport type { RumMutationRecord } from '../../browser/domMutationObservable'\nimport { trackViews } from './trackViews'\nimport type { ViewEvent, ViewOptions } from './trackViews'\nimport type { CommonViewMetrics } from './viewMetrics/trackCommonViewMetrics'\nimport type { InitialViewMetrics } from './viewMetrics/trackInitialViewMetrics'\n\nexport function startViewCollection(\n  lifeCycle: LifeCycle,\n  hooks: Hooks,\n  configuration: RumConfiguration,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  pageOpenObservable: Observable<void>,\n  locationChangeObservable: Observable<LocationChange>,\n  recorderApi: RecorderApi,\n  viewHistory: ViewHistory,\n  initialViewOptions?: ViewOptions\n) {\n  lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, (view) =>\n    lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processViewUpdate(view, configuration, recorderApi))\n  )\n\n  hooks.register(HookNames.Assemble, ({ startTime, eventType }): DefaultRumEventAttributes | DISCARDED => {\n    const view = viewHistory.findView(startTime)\n\n    if (!view) {\n      return DISCARDED\n    }\n\n    return {\n      type: eventType,\n      service: view.service,\n      version: view.version,\n      context: view.context,\n      view: {\n        id: view.id,\n        name: view.name,\n      },\n    }\n  })\n\n  hooks.register(\n    HookNames.AssembleTelemetry,\n    ({ startTime }): DefaultTelemetryEventAttributes => ({\n      view: {\n        id: viewHistory.findView(startTime)?.id,\n      },\n    })\n  )\n\n  return trackViews(\n    lifeCycle,\n    domMutationObservable,\n    pageOpenObservable,\n    configuration,\n    locationChangeObservable,\n    !configuration.trackViewsManually,\n    initialViewOptions\n  )\n}\n\nfunction processViewUpdate(\n  view: ViewEvent,\n  configuration: RumConfiguration,\n  recorderApi: RecorderApi\n): RawRumEventCollectedData<RawRumViewEvent> {\n  const replayStats = recorderApi.getReplayStats(view.id)\n  const clsDevicePixelRatio = view.commonViewMetrics?.cumulativeLayoutShift?.devicePixelRatio\n  const viewEvent: RawRumViewEvent = {\n    _dd: {\n      document_version: view.documentVersion,\n      replay_stats: replayStats,\n      cls: clsDevicePixelRatio\n        ? {\n            device_pixel_ratio: clsDevicePixelRatio,\n          }\n        : undefined,\n      configuration: {\n        start_session_replay_recording_manually: configuration.startSessionReplayRecordingManually,\n      },\n    },\n    date: view.startClocks.timeStamp,\n    type: RumEventType.VIEW,\n    view: {\n      action: {\n        count: view.eventCounts.actionCount,\n      },\n      frustration: {\n        count: view.eventCounts.frustrationCount,\n      },\n      cumulative_layout_shift: view.commonViewMetrics.cumulativeLayoutShift?.value,\n      cumulative_layout_shift_time: toServerDuration(view.commonViewMetrics.cumulativeLayoutShift?.time),\n      cumulative_layout_shift_target_selector: view.commonViewMetrics.cumulativeLayoutShift?.targetSelector,\n      first_byte: toServerDuration(view.initialViewMetrics.navigationTimings?.firstByte),\n      dom_complete: toServerDuration(view.initialViewMetrics.navigationTimings?.domComplete),\n      dom_content_loaded: toServerDuration(view.initialViewMetrics.navigationTimings?.domContentLoaded),\n      dom_interactive: toServerDuration(view.initialViewMetrics.navigationTimings?.domInteractive),\n      error: {\n        count: view.eventCounts.errorCount,\n      },\n      first_contentful_paint: toServerDuration(view.initialViewMetrics.firstContentfulPaint),\n      first_input_delay: toServerDuration(view.initialViewMetrics.firstInput?.delay),\n      first_input_time: toServerDuration(view.initialViewMetrics.firstInput?.time),\n      first_input_target_selector: view.initialViewMetrics.firstInput?.targetSelector,\n      interaction_to_next_paint: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.value),\n      interaction_to_next_paint_time: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.time),\n      interaction_to_next_paint_target_selector: view.commonViewMetrics.interactionToNextPaint?.targetSelector,\n      is_active: view.isActive,\n      name: view.name,\n      largest_contentful_paint: toServerDuration(view.initialViewMetrics.largestContentfulPaint?.value),\n      largest_contentful_paint_target_selector: view.initialViewMetrics.largestContentfulPaint?.targetSelector,\n      load_event: toServerDuration(view.initialViewMetrics.navigationTimings?.loadEvent),\n      loading_time: discardNegativeDuration(toServerDuration(view.commonViewMetrics.loadingTime)),\n      loading_type: view.loadingType,\n      long_task: {\n        count: view.eventCounts.longTaskCount,\n      },\n      performance: computeViewPerformanceData(view.commonViewMetrics, view.initialViewMetrics),\n      resource: {\n        count: view.eventCounts.resourceCount,\n      },\n      time_spent: toServerDuration(view.duration),\n    },\n    display: view.commonViewMetrics.scroll\n      ? {\n          scroll: {\n            max_depth: view.commonViewMetrics.scroll.maxDepth,\n            max_depth_scroll_top: view.commonViewMetrics.scroll.maxDepthScrollTop,\n            max_scroll_height: view.commonViewMetrics.scroll.maxScrollHeight,\n            max_scroll_height_time: toServerDuration(view.commonViewMetrics.scroll.maxScrollHeightTime),\n          },\n        }\n      : undefined,\n    privacy: {\n      replay_level: configuration.defaultPrivacyLevel,\n    },\n    device: {\n      locale: navigator.language,\n      locales: navigator.languages,\n      time_zone: getTimeZone(),\n    },\n  }\n\n  if (!isEmptyObject(view.customTimings)) {\n    viewEvent.view.custom_timings = mapValues(\n      view.customTimings,\n      toServerDuration as (duration: Duration) => ServerDuration\n    )\n  }\n\n  return {\n    rawRumEvent: viewEvent,\n    startClocks: view.startClocks,\n    duration: view.duration,\n    domainContext: {\n      location: view.location,\n      handlingStack: view.handlingStack,\n    },\n  }\n}\n\nfunction computeViewPerformanceData(\n  { cumulativeLayoutShift, interactionToNextPaint }: CommonViewMetrics,\n  { firstContentfulPaint, firstInput, largestContentfulPaint }: InitialViewMetrics\n): ViewPerformanceData {\n  return {\n    cls: cumulativeLayoutShift && {\n      score: cumulativeLayoutShift.value,\n      timestamp: toServerDuration(cumulativeLayoutShift.time),\n      target_selector: cumulativeLayoutShift.targetSelector,\n      previous_rect: cumulativeLayoutShift.previousRect,\n      current_rect: cumulativeLayoutShift.currentRect,\n    },\n    fcp: firstContentfulPaint && { timestamp: toServerDuration(firstContentfulPaint) },\n    fid: firstInput && {\n      duration: toServerDuration(firstInput.delay),\n      timestamp: toServerDuration(firstInput.time),\n      target_selector: firstInput.targetSelector,\n    },\n    inp: interactionToNextPaint && {\n      duration: toServerDuration(interactionToNextPaint.value),\n      timestamp: toServerDuration(interactionToNextPaint.time),\n      target_selector: interactionToNextPaint.targetSelector,\n      sub_parts: interactionToNextPaint.subParts\n        ? {\n            input_delay: toServerDuration(interactionToNextPaint.subParts.inputDelay),\n            processing_duration: toServerDuration(interactionToNextPaint.subParts.processingDuration),\n            presentation_delay: toServerDuration(interactionToNextPaint.subParts.presentationDelay),\n          }\n        : undefined,\n    },\n    lcp: largestContentfulPaint && {\n      timestamp: toServerDuration(largestContentfulPaint.value),\n      target_selector: largestContentfulPaint.targetSelector,\n      resource_url: largestContentfulPaint.resourceUrl,\n      sub_parts: largestContentfulPaint.subParts\n        ? {\n            load_delay: toServerDuration(largestContentfulPaint.subParts.loadDelay),\n            load_time: toServerDuration(largestContentfulPaint.subParts.loadTime),\n            render_delay: toServerDuration(largestContentfulPaint.subParts.renderDelay),\n          }\n        : undefined,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/getClsAttributionImpactedArea.spec.ts",
    "content": "import type { RumLayoutShiftAttribution } from '../../../browser/performanceObservable'\nimport { getClsAttributionImpactedArea } from './getClsAttributionImpactedArea'\nimport { isLayoutShiftSupported } from './trackCumulativeLayoutShift'\n\ndescribe('getClsAttributionImpactedArea', () => {\n  beforeEach(() => {\n    if (!isLayoutShiftSupported()) {\n      pending('No LayoutShift API support')\n    }\n  })\n  it('should calculate the impacted area when rectangles do not overlap', () => {\n    const source: RumLayoutShiftAttribution = {\n      node: null,\n      previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n      currentRect: DOMRectReadOnly.fromRect({ x: 20, y: 20, width: 10, height: 10 }),\n    }\n\n    expect(getClsAttributionImpactedArea(source)).toBe(200) // 100 (previous) + 100 (current) - 0 (intersection)\n  })\n\n  it('should calculate the impacted area when rectangles partially overlap', () => {\n    const source: RumLayoutShiftAttribution = {\n      node: null,\n      previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n      currentRect: DOMRectReadOnly.fromRect({ x: 5, y: 5, width: 10, height: 10 }),\n    }\n\n    /*\n              Visual representation:\n              Previous & current rects (10x10):\n              +---------+\n              |         |                     Intersection area (5x5):\n              |    +----+----+                 +----+\n              |    |    |    |                 |    |\n              +----+----+    |                 +----+\n                   |         |\n                   +---------+\n              */\n\n    expect(getClsAttributionImpactedArea(source)).toBe(175) // 100 (previous) + 100 (current) - 25 (intersection)\n  })\n\n  it('should calculate the impacted area when rectangles completely overlap', () => {\n    const source: RumLayoutShiftAttribution = {\n      node: null,\n      previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n      currentRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n    }\n    /*\n               Visual representation:\n               Previous & current rects (10x10):\n                  +---------+\n                  |         |\n                  |         |\n                  |         |\n                  +----+----+\n                  and also intersection area (10x10)      \n               */\n    expect(getClsAttributionImpactedArea(source)).toBe(100) // 100 (previous) + 100 (current) - 100 (intersection)\n  })\n\n  it('should calculate the impacted area when rectangles are adjacent', () => {\n    const source: RumLayoutShiftAttribution = {\n      node: null,\n      previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n      currentRect: DOMRectReadOnly.fromRect({ x: 10, y: 0, width: 10, height: 10 }),\n    }\n\n    expect(getClsAttributionImpactedArea(source)).toBe(200) // 100 (previous) + 100 (current) - 0 (intersection)\n  })\n\n  it('should calculate the impacted area for different sized rectangles', () => {\n    const source: RumLayoutShiftAttribution = {\n      node: null,\n      previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 5, height: 5 }),\n      currentRect: DOMRectReadOnly.fromRect({ x: 2, y: 2, width: 10, height: 10 }),\n    }\n\n    /*\n        Visual representation:\n        Previous rect (5x5):\n        +---------+\n        |         |                     Intersection area (3x3):\n        |    +----+----------+                 +----+\n        |    |    |          |                 |    |\n        +----+----+          |                 +----+\n             |               |\n             |               |\n             |               |\n             +--------------+\n           Current rect (10x10):          \n        */\n    expect(getClsAttributionImpactedArea(source)).toBe(116) // 25 (previous) + 100 (current) - 9 (intersection)\n  })\n\n  it('should handle rectangles with zero dimensions', () => {\n    const source: RumLayoutShiftAttribution = {\n      node: null,\n      previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 0, height: 0 }),\n      currentRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n    }\n\n    expect(getClsAttributionImpactedArea(source)).toBe(100) // 0 (previous) + 100 (current) - 0 (intersection)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/getClsAttributionImpactedArea.ts",
    "content": "import type { RumLayoutShiftAttribution } from '../../../browser/performanceObservable'\n\n/**\n * Calculates the area of a rectangle given its width and height\n */\nconst calculateArea = (width: number, height: number): number => width * height\n\n/**\n * Calculates the intersection area between two rectangles\n */\nconst calculateIntersectionArea = (rect1: DOMRectReadOnly, rect2: DOMRectReadOnly): number => {\n  const left = Math.max(rect1.left, rect2.left)\n  const top = Math.max(rect1.top, rect2.top)\n  const right = Math.min(rect1.right, rect2.right)\n  const bottom = Math.min(rect1.bottom, rect2.bottom)\n\n  if (left >= right || top >= bottom) {\n    return 0\n  }\n\n  return calculateArea(right - left, bottom - top)\n}\n\n/**\n * Calculates the total impacted area of a layout shift source\n * This is the sum of the previous and current areas minus their intersection\n */\nexport const getClsAttributionImpactedArea = (source: RumLayoutShiftAttribution): number => {\n  const previousArea = calculateArea(source.previousRect.width, source.previousRect.height)\n  const currentArea = calculateArea(source.currentRect.width, source.currentRect.height)\n  const intersectionArea = calculateIntersectionArea(source.previousRect, source.currentRect)\n\n  return previousArea + currentArea - intersectionArea\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/interactionCountPolyfill.ts",
    "content": "/**\n * performance.interactionCount polyfill\n *\n * The interactionCount is an integer which counts the total number of distinct user interactions,\n * for which there was a unique interactionId.\n *\n * The interactionCount polyfill is an estimate based on a convention specific to Chrome. Cf: https://github.com/GoogleChrome/web-vitals/pull/213\n * This is currently not an issue as the polyfill is only used for INP which is currently only supported on Chrome.\n * Hopefully when/if other browsers will support INP, they will also implement performance.interactionCount at the same time, so we won't need that polyfill.\n *\n * Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/main/src/lib/polyfills/interactionCountPolyfill.ts\n */\n\nimport { monitor } from '@datadog/browser-core'\nimport type {\n  BrowserWindow,\n  RumPerformanceEventTiming,\n  RumPerformanceObserver,\n} from '../../../browser/performanceObservable'\n\nlet observer: RumPerformanceObserver | undefined\n\nlet interactionCountEstimate = 0\nlet minKnownInteractionId = Infinity\nlet maxKnownInteractionId = 0\n\nexport function initInteractionCountPolyfill() {\n  if ('interactionCount' in performance || observer) {\n    return\n  }\n\n  observer = new (window as BrowserWindow).PerformanceObserver(\n    monitor((entries: PerformanceObserverEntryList) => {\n      entries.getEntries().forEach((e) => {\n        const entry = e as unknown as RumPerformanceEventTiming\n\n        if (entry.interactionId) {\n          minKnownInteractionId = Math.min(minKnownInteractionId, entry.interactionId)\n          maxKnownInteractionId = Math.max(maxKnownInteractionId, entry.interactionId)\n\n          interactionCountEstimate = (maxKnownInteractionId - minKnownInteractionId) / 7 + 1\n        }\n      })\n    })\n  )\n\n  observer.observe({ type: 'event', buffered: true, durationThreshold: 0 })\n}\n\n/**\n * Returns the `interactionCount` value using the native API (if available)\n * or the polyfill estimate in this module.\n */\nexport const getInteractionCount = () =>\n  observer ? interactionCountEstimate : (window as BrowserWindow).performance.interactionCount || 0\n\nexport function resetInteractionCountPolyfill() {\n  if (observer) {\n    observer.disconnect()\n\n    observer = undefined\n    interactionCountEstimate = 0\n    minKnownInteractionId = Infinity\n    maxKnownInteractionId = 0\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/startInitialViewMetricsTelemetry.spec.ts",
    "content": "import type { Telemetry, RelativeTime, Duration, RawTelemetryEvent } from '@datadog/browser-core'\nimport type { MockTelemetry } from '@datadog/browser-core/test'\nimport { registerCleanupTask, startMockTelemetry } from '@datadog/browser-core/test'\nimport { LifeCycle, LifeCycleEventType } from '../../lifeCycle'\nimport type { ViewEvent } from '../trackViews'\nimport { startInitialViewMetricsTelemetry } from './startInitialViewMetricsTelemetry'\nimport type { InitialViewMetrics } from './trackInitialViewMetrics'\n\nconst VIEW_METRICS: Partial<InitialViewMetrics> = {\n  largestContentfulPaint: {\n    value: 100 as RelativeTime,\n  },\n  navigationTimings: {\n    domComplete: 10 as Duration,\n    domContentLoaded: 20 as Duration,\n    domInteractive: 30 as Duration,\n    firstByte: 40 as Duration,\n    loadEvent: 50 as Duration,\n  },\n}\n\nconst TELEMETRY_FOR_VIEW_METRICS: RawTelemetryEvent = {\n  type: 'log',\n  status: 'debug',\n  message: 'Initial view metrics',\n  metrics: {\n    lcp: {\n      value: 100,\n    },\n    navigation: {\n      domComplete: 10,\n      domContentLoaded: 20,\n      domInteractive: 30,\n      firstByte: 40,\n      loadEvent: 50,\n    },\n  },\n}\n\ndescribe('startInitialViewMetricsTelemetry', () => {\n  const lifeCycle = new LifeCycle()\n  let telemetry: MockTelemetry\n\n  function generateViewUpdateWithInitialViewMetrics(initialViewMetrics: Partial<InitialViewMetrics>) {\n    lifeCycle.notify(LifeCycleEventType.VIEW_UPDATED, { initialViewMetrics } as ViewEvent)\n  }\n\n  function startInitialViewMetricsTelemetryCollection(metricsEnabled: boolean = true) {\n    telemetry = startMockTelemetry()\n    const { stop: stopInitialViewMetricsTelemetryCollection } = startInitialViewMetricsTelemetry(lifeCycle, {\n      metricsEnabled,\n    } as Telemetry)\n    registerCleanupTask(stopInitialViewMetricsTelemetryCollection)\n  }\n\n  it('should collect initial view metrics telemetry', async () => {\n    startInitialViewMetricsTelemetryCollection()\n    generateViewUpdateWithInitialViewMetrics(VIEW_METRICS)\n    expect(await telemetry.getEvents()).toEqual([jasmine.objectContaining(TELEMETRY_FOR_VIEW_METRICS)])\n  })\n\n  it('should not collect initial view metrics telemetry twice', async () => {\n    startInitialViewMetricsTelemetryCollection()\n\n    generateViewUpdateWithInitialViewMetrics(VIEW_METRICS)\n    expect(await telemetry.getEvents()).toEqual([jasmine.objectContaining(TELEMETRY_FOR_VIEW_METRICS)])\n    telemetry.reset()\n\n    generateViewUpdateWithInitialViewMetrics({\n      ...VIEW_METRICS,\n      largestContentfulPaint: {\n        value: 1000 as RelativeTime,\n      },\n    })\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n\n  it('should not collect initial view metrics telemetry until LCP is known', async () => {\n    startInitialViewMetricsTelemetryCollection()\n\n    generateViewUpdateWithInitialViewMetrics({\n      ...VIEW_METRICS,\n      largestContentfulPaint: undefined,\n    })\n    expect(await telemetry.hasEvents()).toBe(false)\n    telemetry.reset()\n\n    generateViewUpdateWithInitialViewMetrics(VIEW_METRICS)\n    expect(await telemetry.getEvents()).toEqual([jasmine.objectContaining(TELEMETRY_FOR_VIEW_METRICS)])\n  })\n\n  it('should not collect initial view metrics telemetry until navigation timings are known', async () => {\n    startInitialViewMetricsTelemetryCollection()\n\n    generateViewUpdateWithInitialViewMetrics({\n      ...VIEW_METRICS,\n      navigationTimings: undefined,\n    })\n    expect(await telemetry.hasEvents()).toBe(false)\n    telemetry.reset()\n\n    generateViewUpdateWithInitialViewMetrics(VIEW_METRICS)\n    expect(await telemetry.getEvents()).toEqual([jasmine.objectContaining(TELEMETRY_FOR_VIEW_METRICS)])\n  })\n\n  it('should not collect initial view metrics telemetry when telemetry is disabled', async () => {\n    startInitialViewMetricsTelemetryCollection(false)\n    generateViewUpdateWithInitialViewMetrics(VIEW_METRICS)\n    expect(await telemetry.hasEvents()).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/startInitialViewMetricsTelemetry.ts",
    "content": "import type { Context, Telemetry } from '@datadog/browser-core'\nimport { addTelemetryMetrics, noop, TelemetryMetrics } from '@datadog/browser-core'\nimport type { LifeCycle } from '../../lifeCycle'\nimport { LifeCycleEventType } from '../../lifeCycle'\nimport type { LargestContentfulPaint } from './trackLargestContentfulPaint'\nimport type { NavigationTimings } from './trackNavigationTimings'\n\ninterface CoreInitialViewMetrics extends Context {\n  lcp: {\n    value: number\n  }\n  navigation: {\n    domComplete: number\n    domContentLoaded: number\n    domInteractive: number\n    firstByte: number | undefined\n    loadEvent: number\n  }\n}\n\nexport function startInitialViewMetricsTelemetry(lifeCycle: LifeCycle, telemetry: Telemetry) {\n  if (!telemetry.metricsEnabled) {\n    return { stop: noop }\n  }\n\n  const { unsubscribe } = lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, ({ initialViewMetrics }) => {\n    if (!initialViewMetrics.largestContentfulPaint || !initialViewMetrics.navigationTimings) {\n      return\n    }\n\n    // The navigation timings become available shortly after the load event fires, so\n    // we're snapshotting the LCP value available at that point. However, more LCP values\n    // can be emitted until the page is scrolled or interacted with, so it's possible that\n    // the final LCP value may differ. These metrics are intended to help diagnose\n    // performance issues early in the page load process, and using LCP-at-page-load is a\n    // good fit for that use case, but it's important to be aware that this is not\n    // necessarily equivalent to the normal LCP metric.\n    // monitor-until: 2026-07-01\n    addTelemetryMetrics(TelemetryMetrics.INITIAL_VIEW_METRICS_TELEMETRY_NAME, {\n      metrics: createCoreInitialViewMetrics(\n        initialViewMetrics.largestContentfulPaint,\n        initialViewMetrics.navigationTimings\n      ),\n    })\n\n    unsubscribe()\n  })\n\n  return {\n    stop: unsubscribe,\n  }\n}\n\nfunction createCoreInitialViewMetrics(\n  lcp: LargestContentfulPaint,\n  navigation: NavigationTimings\n): CoreInitialViewMetrics {\n  return {\n    lcp: {\n      value: lcp.value,\n    },\n    navigation: {\n      domComplete: navigation.domComplete,\n      domContentLoaded: navigation.domContentLoaded,\n      domInteractive: navigation.domInteractive,\n      firstByte: navigation.firstByte,\n      loadEvent: navigation.loadEvent,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackBfcacheMetrics.spec.ts",
    "content": "import type { Duration, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { createNewEvent, mockClock } from '@datadog/browser-core/test'\nimport { trackBfcacheMetrics } from './trackBfcacheMetrics'\nimport type { InitialViewMetrics } from './trackInitialViewMetrics'\n\ndescribe('trackBfcacheMetrics', () => {\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n\n    spyOn(window, 'requestAnimationFrame').and.callFake((cb: FrameRequestCallback): number => {\n      cb(performance.now())\n      return 0\n    })\n  })\n\n  function createPageshowEvent() {\n    return createNewEvent('pageshow', { timeStamp: performance.now() })\n  }\n\n  it('should compute FCP and LCP from the next frame after BFCache restore', () => {\n    const pageshow = createPageshowEvent() as PageTransitionEvent\n\n    const metrics: InitialViewMetrics = {}\n    const scheduleSpy = jasmine.createSpy('schedule')\n\n    clock.tick(50)\n\n    const startClocks = {\n      relative: pageshow.timeStamp as RelativeTime,\n      timeStamp: 0 as TimeStamp,\n    }\n    trackBfcacheMetrics(startClocks, metrics, scheduleSpy)\n\n    expect(metrics.firstContentfulPaint).toEqual(50 as Duration)\n    expect(metrics.largestContentfulPaint?.value).toEqual(50 as RelativeTime)\n    expect(scheduleSpy).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackBfcacheMetrics.ts",
    "content": "import type { RelativeTime, ClocksState } from '@datadog/browser-core'\nimport type { InitialViewMetrics } from './trackInitialViewMetrics'\nimport { trackRestoredFirstContentfulPaint } from './trackFirstContentfulPaint'\n\n/**\n * BFCache keeps a full in-memory snapshot of the DOM. When the page is restored, nothing needs to be fetched, so the whole\n * viewport repaints in a single frame. Consequently, LCP almost always equals FCP.\n * (See: https://github.com/GoogleChrome/web-vitals/pull/87)\n */\nexport function trackBfcacheMetrics(\n  viewStart: ClocksState,\n  metrics: InitialViewMetrics,\n  scheduleViewUpdate: () => void\n) {\n  trackRestoredFirstContentfulPaint(viewStart.relative, (paintTime) => {\n    metrics.firstContentfulPaint = paintTime\n    metrics.largestContentfulPaint = { value: paintTime as RelativeTime }\n    scheduleViewUpdate()\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackCommonViewMetrics.spec.ts",
    "content": "import type { Duration } from '@datadog/browser-core'\nimport { clocksOrigin, Observable } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport { ViewLoadingType } from '../../../rawRumEvent.types'\nimport { createMutationRecord, mockGlobalPerformanceBuffer, mockRumConfiguration } from '../../../../test'\nimport { PAGE_ACTIVITY_END_DELAY, PAGE_ACTIVITY_VALIDATION_DELAY } from '../../waitPageActivityEnd'\nimport { LifeCycle } from '../../lifeCycle'\nimport type { RumMutationRecord } from '../../../browser/domMutationObservable'\nimport { trackCommonViewMetrics } from './trackCommonViewMetrics'\n\nconst BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY = (PAGE_ACTIVITY_VALIDATION_DELAY * 0.8) as Duration\nconst AFTER_PAGE_ACTIVITY_END_DELAY = PAGE_ACTIVITY_END_DELAY * 1.1\n\n// Tests trackCommonViewMetrics in isolation to verify loading time edge cases without the full view lifecycle setup\ndescribe('trackCommonViewMetrics', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let domMutationObservable: Observable<RumMutationRecord[]>\n  let windowOpenObservable: Observable<void>\n  let scheduleViewUpdateSpy: jasmine.Spy\n\n  beforeEach(() => {\n    mockGlobalPerformanceBuffer()\n    clock = mockClock()\n    domMutationObservable = new Observable()\n    windowOpenObservable = new Observable()\n    scheduleViewUpdateSpy = jasmine.createSpy('scheduleViewUpdate')\n  })\n\n  describe('manual loading time suppresses auto-detected loading time callback', () => {\n    it('should ignore auto-detected loading time when manual loading time was already set', () => {\n      const { setLoadEvent, setLoadingTime, getCommonViewMetrics, stop } = trackCommonViewMetrics(\n        lifeCycle,\n        domMutationObservable,\n        windowOpenObservable,\n        mockRumConfiguration(),\n        scheduleViewUpdateSpy,\n        ViewLoadingType.INITIAL_LOAD,\n        clocksOrigin()\n      )\n\n      registerCleanupTask(stop)\n\n      // Step 1: Trigger page activity and let it end.\n      // This sets isWaitingForActivityLoadingTime = false with a candidate,\n      // but isWaitingForLoadEvent is still true so the callback does not fire yet.\n      clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n      domMutationObservable.notify([createMutationRecord()])\n      clock.tick(AFTER_PAGE_ACTIVITY_END_DELAY)\n\n      // Step 2: Set manual loading time via setLoadingTime. This sets hasManualLoadingTime = true\n      // and calls stopLoadingTimeTracking (waitPageActivityEnd already completed).\n      setLoadingTime()\n      const manualLoadingTime = getCommonViewMetrics().loadingTime\n\n      expect(manualLoadingTime).toBeDefined()\n\n      // Step 3: Fire setLoadEvent, which completes the remaining wait condition.\n      // trackLoadingTime's invokeCallbackIfAllCandidatesAreReceived will now fire\n      // the loading time callback. The hasManualLoadingTime guard should prevent\n      // the auto-detected value from overwriting the manual one.\n      setLoadEvent(200 as Duration)\n\n      // Verify the manual value was preserved (not overwritten by auto-detection)\n      expect(getCommonViewMetrics().loadingTime).toBe(manualLoadingTime)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackCommonViewMetrics.ts",
    "content": "import type { ClocksState, Duration, Observable, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { elapsed, timeStampNow } from '@datadog/browser-core'\nimport type { ViewLoadingType } from '../../../rawRumEvent.types'\nimport type { RumConfiguration } from '../../configuration'\nimport type { LifeCycle } from '../../lifeCycle'\nimport type { RumMutationRecord } from '../../../browser/domMutationObservable'\nimport type { CumulativeLayoutShift } from './trackCumulativeLayoutShift'\nimport { trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'\nimport type { InteractionToNextPaint } from './trackInteractionToNextPaint'\nimport { trackInteractionToNextPaint } from './trackInteractionToNextPaint'\nimport { trackLoadingTime } from './trackLoadingTime'\nimport type { ScrollMetrics } from './trackScrollMetrics'\nimport { trackScrollMetrics } from './trackScrollMetrics'\n\nexport interface CommonViewMetrics {\n  loadingTime?: Duration\n  cumulativeLayoutShift?: CumulativeLayoutShift\n  interactionToNextPaint?: InteractionToNextPaint\n  scroll?: ScrollMetrics\n}\n\nexport function trackCommonViewMetrics(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration,\n  scheduleViewUpdate: () => void,\n  loadingType: ViewLoadingType,\n  viewStart: ClocksState\n) {\n  const commonViewMetrics: CommonViewMetrics = {}\n  let hasManualLoadingTime = false\n  let viewEnded = false\n\n  const { stop: stopLoadingTimeTracking, setLoadEvent } = trackLoadingTime(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration,\n    loadingType,\n    viewStart,\n    (newLoadingTime) => {\n      if (!hasManualLoadingTime) {\n        commonViewMetrics.loadingTime = newLoadingTime\n        scheduleViewUpdate()\n      }\n    }\n  )\n\n  const { stop: stopScrollMetricsTracking } = trackScrollMetrics(configuration, viewStart, (newScrollMetrics) => {\n    commonViewMetrics.scroll = newScrollMetrics\n  })\n\n  const { stop: stopCLSTracking } = trackCumulativeLayoutShift(\n    configuration,\n    viewStart.relative,\n    (cumulativeLayoutShift) => {\n      commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift\n      scheduleViewUpdate()\n    }\n  )\n\n  const {\n    stop: stopINPTracking,\n    getInteractionToNextPaint,\n    setViewEnd: setINPViewEnd,\n  } = trackInteractionToNextPaint(configuration, viewStart.relative, loadingType)\n\n  return {\n    stop: () => {\n      stopLoadingTimeTracking()\n      stopCLSTracking()\n      stopScrollMetricsTracking()\n    },\n    stopINPTracking,\n    setLoadEvent,\n    setViewEnd: (viewEndTime: RelativeTime) => {\n      viewEnded = true\n      setINPViewEnd(viewEndTime)\n    },\n    getCommonViewMetrics: () => {\n      commonViewMetrics.interactionToNextPaint = getInteractionToNextPaint()\n      return commonViewMetrics\n    },\n    setLoadingTime: (callTimestamp?: TimeStamp) => {\n      if (viewEnded) {\n        return\n      }\n      const loadingTime = elapsed(viewStart.timeStamp, callTimestamp ?? timeStampNow())\n      if (!hasManualLoadingTime) {\n        stopLoadingTimeTracking()\n      }\n      hasManualLoadingTime = true\n      commonViewMetrics.loadingTime = loadingTime\n      scheduleViewUpdate()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackCumulativeLayoutShift.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport { elapsed, ONE_SECOND } from '@datadog/browser-core'\nimport {\n  appendElement,\n  appendText,\n  createPerformanceEntry,\n  mockPerformanceObserver,\n  mockRumConfiguration,\n} from '../../../../test'\nimport type { RumPerformanceEntry } from '../../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport type { CumulativeLayoutShift } from './trackCumulativeLayoutShift'\nimport { isLayoutShiftSupported, MAX_WINDOW_DURATION, trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'\n\ninterface StartCLSTrackingArgs {\n  viewStart: RelativeTime\n  isLayoutShiftSupported: boolean\n}\n\ndescribe('trackCumulativeLayoutShift', () => {\n  let originalSupportedEntryTypes: PropertyDescriptor | undefined\n  let clsCallback: jasmine.Spy<(csl: CumulativeLayoutShift) => void>\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  function startCLSTracking({\n    viewStart = 0 as RelativeTime,\n    isLayoutShiftSupported = true,\n  }: Partial<StartCLSTrackingArgs> = {}) {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n\n    clsCallback = jasmine.createSpy()\n    originalSupportedEntryTypes = Object.getOwnPropertyDescriptor(PerformanceObserver, 'supportedEntryTypes')\n    Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', {\n      get: () => (isLayoutShiftSupported ? ['layout-shift'] : []),\n    })\n\n    const clsTrackingResult = trackCumulativeLayoutShift(mockRumConfiguration(), viewStart, clsCallback)\n\n    registerCleanupTask(() => {\n      clsTrackingResult.stop()\n      if (originalSupportedEntryTypes) {\n        Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', originalSupportedEntryTypes)\n      }\n    })\n  }\n\n  beforeEach(() => {\n    if (!isLayoutShiftSupported()) {\n      pending('No LayoutShift API support')\n    }\n  })\n\n  it('should be initialized to 0', () => {\n    startCLSTracking()\n    expect(clsCallback).toHaveBeenCalledOnceWith({ value: 0 })\n  })\n\n  it('should be initialized to undefined if layout-shift is not supported', () => {\n    startCLSTracking({ viewStart: 0 as RelativeTime, isLayoutShiftSupported: false })\n\n    expect(clsCallback).not.toHaveBeenCalled()\n  })\n\n  it('should accumulate layout shift values for the first session window', () => {\n    startCLSTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 1 as RelativeTime }),\n    ])\n\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.2, startTime: 2 as RelativeTime }),\n    ])\n\n    expect(clsCallback).toHaveBeenCalledTimes(3)\n    expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n      value: 0.3,\n      time: 2 as RelativeTime,\n      targetSelector: undefined,\n      previousRect: undefined,\n      currentRect: undefined,\n      devicePixelRatio: jasmine.any(Number),\n    })\n  })\n\n  it('should ignore layout shifts that happen before the view start', () => {\n    startCLSTracking({ viewStart: 100 as RelativeTime })\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 1 as RelativeTime }),\n    ])\n\n    expect(clsCallback).toHaveBeenCalledTimes(1)\n    expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n      value: 0,\n    })\n  })\n\n  it('should round the cumulative layout shift value to 4 decimals', () => {\n    startCLSTracking()\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 1.23456789 })])\n\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 1.11111111111 })])\n\n    expect(clsCallback).toHaveBeenCalledTimes(3)\n    expect(clsCallback.calls.mostRecent().args[0].value).toEqual(2.3457)\n  })\n\n  it('should ignore entries with recent input', () => {\n    startCLSTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.1,\n        hadRecentInput: true,\n      }),\n    ])\n\n    expect(clsCallback).toHaveBeenCalledTimes(1)\n    expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n      value: 0,\n    })\n  })\n\n  it('should create a new session window if the gap is more than 1 second', () => {\n    startCLSTracking()\n    // first session window\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 0 as RelativeTime }),\n    ])\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.2, startTime: 1 as RelativeTime }),\n    ])\n    // second session window\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.1,\n        startTime: (1 + ONE_SECOND) as RelativeTime,\n      }),\n    ])\n\n    expect(clsCallback).toHaveBeenCalledTimes(3)\n    expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n      value: 0.3,\n      time: 1 as RelativeTime,\n      targetSelector: undefined,\n      previousRect: undefined,\n      currentRect: undefined,\n      devicePixelRatio: jasmine.any(Number),\n    })\n  })\n\n  it('should create a new session window if the current session window is more than 5 second', () => {\n    startCLSTracking()\n    for (let i = 1; i <= 7; i++) {\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          value: 0.1,\n          startTime: (i * 999) as RelativeTime,\n        }),\n      ])\n    } // window 1: { value: 0.6, time: 999 } | window 2: { value: 0.1, time: 5994(6*999) }\n\n    expect(clsCallback).toHaveBeenCalledTimes(7)\n    expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n      value: 0.6,\n      time: 999 as RelativeTime,\n      targetSelector: undefined,\n      previousRect: undefined,\n      currentRect: undefined,\n      devicePixelRatio: jasmine.any(Number),\n    })\n  })\n\n  it('should get the max value sessions', () => {\n    startCLSTracking()\n    // first session window: { value: 0.3, time: 1 }\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 0 as RelativeTime }),\n    ])\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.2, startTime: 1 as RelativeTime }),\n    ])\n\n    // second session window: { value: 0.5, time: 5002 }\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.1,\n        startTime: (MAX_WINDOW_DURATION + 1) as RelativeTime,\n      }),\n    ])\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.2,\n        startTime: (MAX_WINDOW_DURATION + 2) as RelativeTime,\n      }),\n    ])\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.2,\n        startTime: (MAX_WINDOW_DURATION + 3) as RelativeTime,\n      }),\n    ])\n\n    // third session window: { value: 0.4, time: 10003 }\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.2,\n        startTime: (2 * MAX_WINDOW_DURATION + 3) as RelativeTime,\n      }),\n    ])\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n        value: 0.2,\n        startTime: (2 * MAX_WINDOW_DURATION + 4) as RelativeTime,\n      }),\n    ])\n\n    expect(clsCallback).toHaveBeenCalledTimes(4)\n    expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n      value: 0.5,\n      time: 5002 as RelativeTime,\n      targetSelector: undefined,\n      previousRect: undefined,\n      currentRect: undefined,\n      devicePixelRatio: jasmine.any(Number),\n    })\n  })\n\n  it('should get the time from the beginning of the view', () => {\n    const viewStart = 100 as RelativeTime\n    startCLSTracking({ viewStart, isLayoutShiftSupported: true })\n\n    const shiftStart = 110 as RelativeTime\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: shiftStart }),\n    ])\n\n    expect(clsCallback.calls.mostRecent().args[0].time).toEqual(elapsed(viewStart, shiftStart))\n  })\n\n  describe('cls target element', () => {\n    it('should return the first target element selector amongst all the shifted nodes', () => {\n      startCLSTracking()\n      const textNode = appendText('text')\n      const divElement = appendElement('<div id=\"div-element\"></div>')\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          sources: [\n            {\n              node: textNode,\n              previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n              currentRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n            },\n            {\n              node: divElement,\n              previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n              currentRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n            },\n            {\n              node: textNode,\n              previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n              currentRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n            },\n          ],\n        }),\n      ])\n\n      expect(clsCallback).toHaveBeenCalledTimes(2)\n      expect(clsCallback.calls.mostRecent().args[0].targetSelector).toEqual('#div-element')\n    })\n\n    it('should not return the target element when the element is detached from the DOM before the performance entry event is triggered', () => {\n      startCLSTracking()\n      // first session window\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          value: 0.2,\n          startTime: 0 as RelativeTime,\n        }),\n      ])\n\n      expect(clsCallback.calls.mostRecent().args[0].value).toEqual(0.2)\n      // second session window\n      // first shift with an element\n      const divElement = appendElement('<div id=\"div-element\"></div>')\n      divElement.remove()\n\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          value: 0.2,\n          startTime: 1001 as RelativeTime,\n          sources: [\n            {\n              node: divElement,\n              previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n              currentRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n            },\n          ],\n        }),\n      ])\n\n      expect(clsCallback.calls.mostRecent().args[0].value).toEqual(0.2)\n      expect(clsCallback.calls.mostRecent().args[0].targetSelector).toEqual(undefined)\n    })\n\n    it('should get the target element, time, and rects of the largest layout shift', () => {\n      startCLSTracking()\n      const divElement = appendElement('<div id=\"div-element\"></div>')\n\n      // first session window:  { value: 0.5, time: 1, targetSelector: '#div-element' }\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.1, startTime: 0 as RelativeTime }),\n      ])\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          value: 0.2,\n          startTime: 1 as RelativeTime,\n          sources: [\n            {\n              node: divElement,\n              previousRect: DOMRectReadOnly.fromRect({ x: 0, y: 0, width: 10, height: 10 }),\n              currentRect: DOMRectReadOnly.fromRect({ x: 50, y: 50, width: 10, height: 10 }),\n            },\n          ],\n        }),\n      ])\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, { value: 0.2, startTime: 2 as RelativeTime }),\n      ])\n\n      // second session window:  { value: 0.4, time: 5002, targetSelector: undefined }\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          value: 0.2,\n          startTime: (MAX_WINDOW_DURATION + 2) as RelativeTime,\n        }),\n      ])\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.LAYOUT_SHIFT, {\n          value: 0.2,\n          startTime: (MAX_WINDOW_DURATION + 3) as RelativeTime,\n        }),\n      ])\n\n      expect(clsCallback).toHaveBeenCalledTimes(4)\n      expect(clsCallback.calls.mostRecent().args[0]).toEqual({\n        value: 0.5,\n        time: 1 as RelativeTime,\n        targetSelector: '#div-element',\n        previousRect: { x: 0, y: 0, width: 10, height: 10 },\n        currentRect: { x: 50, y: 50, width: 10, height: 10 },\n        devicePixelRatio: jasmine.any(Number),\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackCumulativeLayoutShift.ts",
    "content": "import { round, ONE_SECOND, noop, elapsed } from '@datadog/browser-core'\nimport type { Duration, RelativeTime, WeakRef, WeakRefConstructor } from '@datadog/browser-core'\nimport { isElementNode } from '../../../browser/htmlDomUtils'\nimport type { RumLayoutShiftAttribution, RumLayoutShiftTiming } from '../../../browser/performanceObservable'\nimport {\n  supportPerformanceTimingEvent,\n  RumPerformanceEntryType,\n  createPerformanceObservable,\n} from '../../../browser/performanceObservable'\nimport { getSelectorFromElement } from '../../getSelectorFromElement'\nimport type { RumConfiguration } from '../../configuration'\nimport type { RumRect } from '../../../rumEvent.types'\nimport { getClsAttributionImpactedArea } from './getClsAttributionImpactedArea'\n\ndeclare const WeakRef: WeakRefConstructor\n\nexport interface CumulativeLayoutShift {\n  value: number\n  targetSelector?: string\n  time?: Duration\n  previousRect?: RumRect\n  currentRect?: RumRect\n  devicePixelRatio?: number\n}\n\ninterface LayoutShiftInstance {\n  target: WeakRef<Element> | undefined\n  time: Duration\n  previousRect: DOMRectReadOnly | undefined\n  currentRect: DOMRectReadOnly | undefined\n  devicePixelRatio: number\n}\n\n/**\n * Track the cumulative layout shifts (CLS).\n * Layout shifts are grouped into session windows.\n * The minimum gap between session windows is 1 second.\n * The maximum duration of a session window is 5 second.\n * The session window layout shift value is the sum of layout shifts inside it.\n * The CLS value is the max of session windows values.\n *\n * This yields a new value whenever the CLS value is updated (a higher session window value is computed).\n *\n * See isLayoutShiftSupported to check for browser support.\n *\n * Documentation:\n * https://web.dev/cls/\n * https://web.dev/evolving-cls/\n * Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getCLS.ts\n */\nexport function trackCumulativeLayoutShift(\n  configuration: RumConfiguration,\n  viewStart: RelativeTime,\n  callback: (cumulativeLayoutShift: CumulativeLayoutShift) => void\n) {\n  if (!isLayoutShiftSupported()) {\n    return {\n      stop: noop,\n    }\n  }\n\n  let maxClsValue = 0\n  let biggestShift: LayoutShiftInstance | undefined\n\n  // if no layout shift happen the value should be reported as 0\n  callback({\n    value: 0,\n  })\n\n  const slidingWindow = slidingSessionWindow()\n  const performanceSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.LAYOUT_SHIFT,\n    buffered: true,\n  }).subscribe((entries) => {\n    for (const entry of entries) {\n      if (entry.hadRecentInput || entry.startTime < viewStart) {\n        continue\n      }\n\n      const { cumulatedValue, isMaxValue } = slidingWindow.update(entry)\n\n      if (isMaxValue) {\n        const attribution = getTopImpactedElement(entry.sources)\n        biggestShift = {\n          target: attribution?.node ? new WeakRef(attribution.node) : undefined,\n          time: elapsed(viewStart, entry.startTime),\n          previousRect: attribution?.previousRect,\n          currentRect: attribution?.currentRect,\n          devicePixelRatio: window.devicePixelRatio,\n        }\n      }\n\n      if (cumulatedValue > maxClsValue) {\n        maxClsValue = cumulatedValue\n        const target = biggestShift?.target?.deref()\n\n        callback({\n          value: round(maxClsValue, 4),\n          targetSelector: target && getSelectorFromElement(target, configuration.actionNameAttribute),\n          time: biggestShift?.time,\n          previousRect: biggestShift?.previousRect ? asRumRect(biggestShift.previousRect) : undefined,\n          currentRect: biggestShift?.currentRect ? asRumRect(biggestShift.currentRect) : undefined,\n          devicePixelRatio: biggestShift?.devicePixelRatio,\n        })\n      }\n    }\n  })\n\n  return {\n    stop: () => {\n      performanceSubscription.unsubscribe()\n    },\n  }\n}\n\nfunction getTopImpactedElement(\n  sources: RumLayoutShiftAttribution[]\n): (RumLayoutShiftAttribution & { node: Element }) | undefined {\n  let topImpactedSource: (RumLayoutShiftAttribution & { node: Element }) | undefined\n  for (const source of sources) {\n    if (source.node && isElementNode(source.node)) {\n      const currentImpactedArea = getClsAttributionImpactedArea(source)\n      if (!topImpactedSource || getClsAttributionImpactedArea(topImpactedSource) < currentImpactedArea) {\n        topImpactedSource = source as RumLayoutShiftAttribution & { node: Element }\n      }\n    }\n  }\n  return topImpactedSource\n}\n\nfunction asRumRect({ x, y, width, height }: DOMRectReadOnly): RumRect {\n  return { x, y, width, height }\n}\n\nexport const MAX_WINDOW_DURATION = 5 * ONE_SECOND\nconst MAX_UPDATE_GAP = ONE_SECOND\n\nfunction slidingSessionWindow() {\n  let cumulatedValue = 0\n  let startTime: RelativeTime\n  let endTime: RelativeTime\n  let maxValue = 0\n\n  return {\n    update: (entry: RumLayoutShiftTiming) => {\n      const shouldCreateNewWindow =\n        startTime === undefined ||\n        entry.startTime - endTime >= MAX_UPDATE_GAP ||\n        entry.startTime - startTime >= MAX_WINDOW_DURATION\n\n      let isMaxValue: boolean\n\n      if (shouldCreateNewWindow) {\n        startTime = endTime = entry.startTime\n        maxValue = cumulatedValue = entry.value\n        isMaxValue = true\n      } else {\n        cumulatedValue += entry.value\n        endTime = entry.startTime\n        isMaxValue = entry.value > maxValue\n\n        if (isMaxValue) {\n          maxValue = entry.value\n        }\n      }\n\n      return {\n        cumulatedValue,\n        isMaxValue,\n      }\n    },\n  }\n}\n\n/**\n * Check whether `layout-shift` is supported by the browser.\n */\nexport function isLayoutShiftSupported() {\n  return supportPerformanceTimingEvent(RumPerformanceEntryType.LAYOUT_SHIFT) && 'WeakRef' in window\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { clocksOrigin } from '@datadog/browser-core'\nimport { registerCleanupTask, restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'\nimport type { RumPerformanceEntry } from '../../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport { createPerformanceEntry, mockPerformanceObserver, mockRumConfiguration } from '../../../../test'\nimport { FCP_MAXIMUM_DELAY, trackFirstContentfulPaint } from './trackFirstContentfulPaint'\nimport { trackFirstHidden } from './trackFirstHidden'\n\ndescribe('trackFirstContentfulPaint', () => {\n  let fcpCallback: jasmine.Spy<(value: RelativeTime) => void>\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  function startTrackingFCP() {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n\n    fcpCallback = jasmine.createSpy()\n    const firstHidden = trackFirstHidden(mockRumConfiguration(), clocksOrigin())\n    const firstContentfulPaint = trackFirstContentfulPaint(mockRumConfiguration(), firstHidden, fcpCallback)\n\n    registerCleanupTask(() => {\n      firstHidden.stop()\n      firstContentfulPaint.stop()\n      restorePageVisibility()\n    })\n  }\n\n  it('should provide the first contentful paint timing', () => {\n    startTrackingFCP()\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.PAINT)])\n\n    expect(fcpCallback).toHaveBeenCalledTimes(1 as RelativeTime)\n    expect(fcpCallback).toHaveBeenCalledWith(123 as RelativeTime)\n  })\n\n  it('should be discarded if the page is hidden', () => {\n    setPageVisibility('hidden')\n    startTrackingFCP()\n\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.PAINT)])\n    expect(fcpCallback).not.toHaveBeenCalled()\n  })\n\n  it('should be discarded if it is reported after a long time', () => {\n    startTrackingFCP()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.PAINT, { startTime: FCP_MAXIMUM_DELAY as RelativeTime }),\n    ])\n    expect(fcpCallback).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { ONE_MINUTE, elapsed, relativeNow } from '@datadog/browser-core'\nimport type { RumPerformancePaintTiming } from '../../../browser/performanceObservable'\nimport { createPerformanceObservable, RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport type { RumConfiguration } from '../../configuration'\nimport type { FirstHidden } from './trackFirstHidden'\n\n// Discard FCP timings above a certain delay to avoid incorrect data\n// It happens in some cases like sleep mode or some browser implementations\nexport const FCP_MAXIMUM_DELAY = 10 * ONE_MINUTE\n\nexport function trackFirstContentfulPaint(\n  configuration: RumConfiguration,\n  firstHidden: FirstHidden,\n  callback: (fcpTiming: RelativeTime) => void\n) {\n  const performanceSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.PAINT,\n    buffered: true,\n  }).subscribe((entries) => {\n    const fcpEntry = entries.find(\n      (entry): entry is RumPerformancePaintTiming =>\n        entry.name === 'first-contentful-paint' &&\n        entry.startTime < firstHidden.timeStamp &&\n        entry.startTime < FCP_MAXIMUM_DELAY\n    )\n    if (fcpEntry) {\n      callback(fcpEntry.startTime)\n    }\n  })\n  return {\n    stop: performanceSubscription.unsubscribe,\n  }\n}\n\n/**\n * Measure the First Contentful Paint after a BFCache restoration.\n * The DOM is restored synchronously, so we approximate the FCP with the first frame\n * rendered just after the pageshow event, using two nested requestAnimationFrame calls.\n */\nexport function trackRestoredFirstContentfulPaint(viewStartRelative: RelativeTime, callback: (fcp: Duration) => void) {\n  requestAnimationFrame(() => {\n    requestAnimationFrame(() => {\n      callback(elapsed(viewStartRelative, relativeNow()))\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackFirstHidden.spec.ts",
    "content": "import type { RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { clocksOrigin, DOM_EVENT } from '@datadog/browser-core'\nimport { createNewEvent, restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'\nimport { mockRumConfiguration, mockGlobalPerformanceBuffer } from '../../../../test'\nimport type { GlobalPerformanceBufferMock } from '../../../../test'\nimport { trackFirstHidden } from './trackFirstHidden'\n\ndescribe('trackFirstHidden', () => {\n  const configuration = mockRumConfiguration()\n  let firstHidden: { timeStamp: RelativeTime; stop: () => void }\n  let performanceBufferMock: GlobalPerformanceBufferMock\n\n  function trackFirstHiddenWithDefaults({\n    configuration = mockRumConfiguration(),\n    viewStart = clocksOrigin(),\n    eventTarget = window as Window,\n  }): ReturnType<typeof trackFirstHidden> {\n    return trackFirstHidden(configuration, viewStart, eventTarget)\n  }\n\n  afterEach(() => {\n    restorePageVisibility()\n    firstHidden.stop()\n  })\n\n  describe('the page is initially hidden', () => {\n    it('should return 0', () => {\n      setPageVisibility('hidden')\n      firstHidden = trackFirstHiddenWithDefaults({ configuration })\n\n      expect(firstHidden.timeStamp).toBe(0 as RelativeTime)\n    })\n\n    it('should ignore events', () => {\n      setPageVisibility('hidden')\n      const eventTarget = createWindowEventTarget()\n      firstHidden = trackFirstHiddenWithDefaults({ configuration, eventTarget })\n\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.PAGE_HIDE, { timeStamp: 100 }))\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.VISIBILITY_CHANGE, { timeStamp: 100 }))\n\n      expect(firstHidden.timeStamp).toBe(0 as RelativeTime)\n    })\n  })\n\n  describe('the page is initially visible', () => {\n    it('should return Infinity if the page was not hidden yet', () => {\n      setPageVisibility('visible')\n      firstHidden = trackFirstHiddenWithDefaults({ configuration })\n      expect(firstHidden.timeStamp).toBe(Infinity as RelativeTime)\n    })\n\n    it('should return the timestamp of the first pagehide event', () => {\n      const eventTarget = createWindowEventTarget()\n      firstHidden = trackFirstHiddenWithDefaults({ configuration, eventTarget })\n\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.PAGE_HIDE, { timeStamp: 100 }))\n\n      expect(firstHidden.timeStamp).toBe(100 as RelativeTime)\n    })\n\n    it('should return the timestamp of the first visibilitychange event if the page is hidden', () => {\n      const eventTarget = createWindowEventTarget()\n      firstHidden = trackFirstHiddenWithDefaults({ configuration, eventTarget })\n\n      setPageVisibility('hidden')\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.VISIBILITY_CHANGE, { timeStamp: 100 }))\n\n      expect(firstHidden.timeStamp).toBe(100 as RelativeTime)\n    })\n\n    it('should ignore visibilitychange event if the page is visible', () => {\n      const eventTarget = createWindowEventTarget()\n      firstHidden = trackFirstHiddenWithDefaults({ configuration, eventTarget })\n\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.VISIBILITY_CHANGE, { timeStamp: 100 }))\n\n      expect(firstHidden.timeStamp).toBe(Infinity as RelativeTime)\n    })\n\n    it('should ignore subsequent events', () => {\n      const eventTarget = createWindowEventTarget()\n      firstHidden = trackFirstHiddenWithDefaults({ configuration, eventTarget })\n\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.PAGE_HIDE, { timeStamp: 100 }))\n\n      // Subsequent events:\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.PAGE_HIDE, { timeStamp: 200 }))\n      setPageVisibility('hidden')\n      eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.VISIBILITY_CHANGE, { timeStamp: 200 }))\n\n      expect(firstHidden.timeStamp).toBe(100 as RelativeTime)\n    })\n  })\n\n  describe('using visibilityState entries', () => {\n    let originalSupportedEntryTypes: string[] | undefined\n    beforeEach(() => {\n      performanceBufferMock = mockGlobalPerformanceBuffer()\n      if (typeof PerformanceObserver !== 'undefined') {\n        originalSupportedEntryTypes = PerformanceObserver.supportedEntryTypes as string[]\n        Object.defineProperty(PerformanceObserver, 'supportedEntryTypes', {\n          get: () => [...(originalSupportedEntryTypes || []), 'visibility-state'],\n          configurable: true,\n        })\n      }\n    })\n    it('should set timestamp to earliest hidden event from performance entries', () => {\n      setPageVisibility('visible')\n\n      performanceBufferMock.addPerformanceEntry({\n        entryType: 'visibility-state',\n        name: 'hidden',\n        startTime: 23,\n      } as PerformanceEntry)\n\n      performanceBufferMock.addPerformanceEntry({\n        entryType: 'visibility-state',\n        name: 'hidden',\n        startTime: 23219031,\n      } as PerformanceEntry)\n\n      firstHidden = trackFirstHiddenWithDefaults({ configuration })\n      expect(firstHidden.timeStamp).toBe(23 as RelativeTime)\n    })\n\n    it('should ignore entries before view start', () => {\n      setPageVisibility('visible')\n\n      performanceBufferMock.addPerformanceEntry({\n        entryType: 'visibility-state',\n        name: 'hidden',\n        startTime: 23,\n      } as PerformanceEntry)\n\n      firstHidden = trackFirstHiddenWithDefaults({\n        configuration,\n        eventTarget: createWindowEventTarget(),\n        viewStart: { relative: 100 as RelativeTime, timeStamp: 100 as TimeStamp },\n      })\n      expect(firstHidden.timeStamp).toBe(Infinity as RelativeTime)\n    })\n\n    it('should return 0 when the page was loaded hidden', () => {\n      setPageVisibility('visible')\n\n      performanceBufferMock.addPerformanceEntry({\n        entryType: 'visibility-state',\n        name: 'hidden',\n        startTime: 0,\n      } as PerformanceEntry)\n\n      firstHidden = trackFirstHiddenWithDefaults({ configuration })\n      expect(firstHidden.timeStamp).toBe(0 as RelativeTime)\n    })\n  })\n\n  function createWindowEventTarget() {\n    return document.createElement('div') as unknown as Window\n  }\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackFirstHidden.ts",
    "content": "import type { ClocksState, RelativeTime } from '@datadog/browser-core'\nimport { addEventListeners, DOM_EVENT, noop } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../../configuration'\nimport { supportPerformanceTimingEvent, RumPerformanceEntryType } from '../../../browser/performanceObservable'\n\nexport type FirstHidden = ReturnType<typeof trackFirstHidden>\n\nexport interface Options {\n  viewStart: ClocksState\n}\n\nexport function trackFirstHidden(\n  configuration: RumConfiguration,\n  viewStart: ClocksState,\n  eventTarget: Window = window\n) {\n  if (document.visibilityState === 'hidden') {\n    return { timeStamp: 0 as RelativeTime, stop: noop }\n  }\n\n  if (supportPerformanceTimingEvent(RumPerformanceEntryType.VISIBILITY_STATE)) {\n    const firstHiddenEntry = performance\n      .getEntriesByType(RumPerformanceEntryType.VISIBILITY_STATE)\n      .filter((entry) => entry.name === 'hidden')\n      .find((entry) => entry.startTime >= viewStart.relative)\n\n    if (firstHiddenEntry) {\n      return { timeStamp: firstHiddenEntry.startTime as RelativeTime, stop: noop }\n    }\n  }\n\n  let timeStamp: RelativeTime = Infinity as RelativeTime\n\n  const { stop } = addEventListeners(\n    configuration,\n    eventTarget,\n    [DOM_EVENT.PAGE_HIDE, DOM_EVENT.VISIBILITY_CHANGE],\n    (event) => {\n      if (event.type === DOM_EVENT.PAGE_HIDE || document.visibilityState === 'hidden') {\n        timeStamp = event.timeStamp as RelativeTime\n        stop()\n      }\n    },\n    { capture: true }\n  )\n\n  return {\n    get timeStamp() {\n      return timeStamp\n    },\n    stop,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackFirstInput.spec.ts",
    "content": "import { clocksOrigin, type Duration, type RelativeTime } from '@datadog/browser-core'\nimport { registerCleanupTask, restorePageVisibility, setPageVisibility } from '@datadog/browser-core/test'\nimport {\n  appendElement,\n  appendText,\n  createPerformanceEntry,\n  mockPerformanceObserver,\n  mockRumConfiguration,\n} from '../../../../test'\nimport type { RumPerformanceEntry } from '../../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport type { FirstInput } from './trackFirstInput'\nimport { trackFirstInput } from './trackFirstInput'\nimport { trackFirstHidden } from './trackFirstHidden'\n\ndescribe('firstInputTimings', () => {\n  let fitCallback: jasmine.Spy<(firstInput: FirstInput) => void>\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  function startFirstInputTracking() {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n\n    const configuration = mockRumConfiguration()\n    fitCallback = jasmine.createSpy()\n\n    const firstHidden = trackFirstHidden(configuration, clocksOrigin())\n    const firstInputTimings = trackFirstInput(configuration, firstHidden, fitCallback)\n\n    registerCleanupTask(() => {\n      firstHidden.stop()\n      firstInputTimings.stop()\n      restorePageVisibility()\n    })\n  }\n\n  it('should provide the first input timings', () => {\n    startFirstInputTracking()\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT)])\n\n    expect(fitCallback).toHaveBeenCalledOnceWith({\n      delay: 100 as Duration,\n      time: 1000 as RelativeTime,\n      targetSelector: undefined,\n    })\n  })\n\n  it('should provide the first input target selector', () => {\n    startFirstInputTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT, {\n        target: appendElement('<button id=\"fid-target-element\"></button>'),\n      }),\n    ])\n\n    expect(fitCallback).toHaveBeenCalledOnceWith(\n      jasmine.objectContaining({\n        targetSelector: '#fid-target-element',\n      })\n    )\n  })\n\n  it(\"should not provide the first input target if it's not a DOM element\", () => {\n    startFirstInputTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT, {\n        target: appendText('text'),\n      }),\n    ])\n\n    expect(fitCallback).toHaveBeenCalledWith(\n      jasmine.objectContaining({\n        targetSelector: undefined,\n      })\n    )\n  })\n\n  it('should be discarded if the page is hidden', () => {\n    setPageVisibility('hidden')\n    startFirstInputTracking()\n\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT)])\n\n    expect(fitCallback).not.toHaveBeenCalled()\n  })\n\n  it('should be adjusted to 0 if the computed value would be negative due to browser timings imprecisions', () => {\n    startFirstInputTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT, {\n        processingStart: 900 as RelativeTime,\n        startTime: 1000 as RelativeTime,\n        duration: 0 as Duration,\n      }),\n    ])\n\n    expect(fitCallback).toHaveBeenCalledOnceWith(\n      jasmine.objectContaining({\n        delay: 0,\n        time: 1000,\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackFirstInput.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { elapsed } from '@datadog/browser-core'\nimport { isElementNode } from '../../../browser/htmlDomUtils'\nimport type { RumConfiguration } from '../../configuration'\nimport { createPerformanceObservable, RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport type { RumFirstInputTiming } from '../../../browser/performanceObservable'\nimport { getSelectorFromElement } from '../../getSelectorFromElement'\nimport type { FirstHidden } from './trackFirstHidden'\n\nexport interface FirstInput {\n  delay: Duration\n  time: RelativeTime\n  targetSelector?: string\n}\n\n/**\n * Track the first input occurring during the initial View to return:\n * - First Input Delay\n * - First Input Time\n * Callback is called at most one time.\n * Documentation: https://web.dev/fid/\n * Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getFID.ts\n */\nexport function trackFirstInput(\n  configuration: RumConfiguration,\n  firstHidden: FirstHidden,\n  callback: (firstInput: FirstInput) => void\n) {\n  const performanceFirstInputSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.FIRST_INPUT,\n    buffered: true,\n  }).subscribe((entries) => {\n    const firstInputEntry = entries.find(\n      (entry): entry is RumFirstInputTiming => entry.startTime < firstHidden.timeStamp\n    )\n    if (firstInputEntry) {\n      const firstInputDelay = elapsed(firstInputEntry.startTime, firstInputEntry.processingStart)\n      let firstInputTargetSelector\n\n      if (firstInputEntry.target && isElementNode(firstInputEntry.target)) {\n        firstInputTargetSelector = getSelectorFromElement(firstInputEntry.target, configuration.actionNameAttribute)\n      }\n\n      callback({\n        // Ensure firstInputDelay to be positive, see\n        // https://bugs.chromium.org/p/chromium/issues/detail?id=1185815\n        delay: firstInputDelay >= 0 ? firstInputDelay : (0 as Duration),\n        time: firstInputEntry.startTime,\n        targetSelector: firstInputTargetSelector,\n      })\n    }\n  })\n\n  return {\n    stop: () => {\n      performanceFirstInputSubscription.unsubscribe()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackInitialViewMetrics.spec.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { clocksOrigin } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport type { RumPerformanceEntry } from '../../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport { createPerformanceEntry, mockPerformanceObserver, mockRumConfiguration } from '../../../../test'\nimport { trackInitialViewMetrics } from './trackInitialViewMetrics'\n\ndescribe('trackInitialViewMetrics', () => {\n  let clock: Clock\n  let scheduleViewUpdateSpy: jasmine.Spy<() => void>\n  let trackInitialViewMetricsResult: ReturnType<typeof trackInitialViewMetrics>\n  let setLoadEventSpy: jasmine.Spy<(loadEvent: Duration) => void>\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  beforeEach(() => {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n\n    const configuration = mockRumConfiguration()\n    scheduleViewUpdateSpy = jasmine.createSpy()\n    setLoadEventSpy = jasmine.createSpy()\n    clock = mockClock()\n\n    trackInitialViewMetricsResult = trackInitialViewMetrics(\n      configuration,\n      clocksOrigin(),\n      setLoadEventSpy,\n      scheduleViewUpdateSpy\n    )\n\n    registerCleanupTask(trackInitialViewMetricsResult.stop)\n  })\n\n  it('should merge metrics from various sources', () => {\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.NAVIGATION),\n      createPerformanceEntry(RumPerformanceEntryType.PAINT),\n      createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT),\n    ])\n\n    clock.tick(0)\n\n    expect(scheduleViewUpdateSpy).toHaveBeenCalledTimes(3)\n    expect(trackInitialViewMetricsResult.initialViewMetrics).toEqual({\n      navigationTimings: jasmine.any(Object),\n      firstContentfulPaint: 123 as Duration,\n      firstInput: {\n        delay: 100 as Duration,\n        time: 1000 as RelativeTime,\n        targetSelector: undefined,\n      },\n    })\n  })\n\n  it('calls the `setLoadEvent` callback when the loadEvent timing is known', () => {\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.PAINT),\n      createPerformanceEntry(RumPerformanceEntryType.FIRST_INPUT),\n    ])\n\n    clock.tick(0)\n\n    expect(setLoadEventSpy).toHaveBeenCalledOnceWith(jasmine.any(Number))\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackInitialViewMetrics.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../../configuration'\nimport { trackFirstContentfulPaint } from './trackFirstContentfulPaint'\nimport type { FirstInput } from './trackFirstInput'\nimport { trackFirstInput } from './trackFirstInput'\nimport type { NavigationTimings } from './trackNavigationTimings'\nimport { trackNavigationTimings } from './trackNavigationTimings'\nimport type { LargestContentfulPaint } from './trackLargestContentfulPaint'\nimport { trackLargestContentfulPaint } from './trackLargestContentfulPaint'\nimport { trackFirstHidden } from './trackFirstHidden'\n\nexport interface InitialViewMetrics {\n  firstContentfulPaint?: Duration\n  navigationTimings?: NavigationTimings\n  largestContentfulPaint?: LargestContentfulPaint\n  firstInput?: FirstInput\n}\n\nexport function trackInitialViewMetrics(\n  configuration: RumConfiguration,\n  viewStart: ClocksState,\n  setLoadEvent: (loadEnd: Duration) => void,\n  scheduleViewUpdate: () => void\n) {\n  const initialViewMetrics: InitialViewMetrics = {}\n\n  const { stop: stopNavigationTracking } = trackNavigationTimings(configuration, (navigationTimings) => {\n    setLoadEvent(navigationTimings.loadEvent)\n    initialViewMetrics.navigationTimings = navigationTimings\n    scheduleViewUpdate()\n  })\n\n  const firstHidden = trackFirstHidden(configuration, viewStart)\n  const { stop: stopFCPTracking } = trackFirstContentfulPaint(configuration, firstHidden, (firstContentfulPaint) => {\n    initialViewMetrics.firstContentfulPaint = firstContentfulPaint\n    scheduleViewUpdate()\n  })\n\n  const { stop: stopLCPTracking } = trackLargestContentfulPaint(\n    configuration,\n    firstHidden,\n    window,\n    (largestContentfulPaint) => {\n      initialViewMetrics.largestContentfulPaint = largestContentfulPaint\n      scheduleViewUpdate()\n    }\n  )\n\n  const { stop: stopFIDTracking } = trackFirstInput(configuration, firstHidden, (firstInput) => {\n    initialViewMetrics.firstInput = firstInput\n    scheduleViewUpdate()\n  })\n\n  function stop() {\n    stopNavigationTracking()\n    stopFCPTracking()\n    stopLCPTracking()\n    stopFIDTracking()\n    firstHidden.stop()\n  }\n\n  return {\n    stop,\n    initialViewMetrics,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { elapsed, relativeNow } from '@datadog/browser-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport {\n  appendElement,\n  appendText,\n  createPerformanceEntry,\n  mockPerformanceObserver,\n  mockRumConfiguration,\n} from '../../../../test'\nimport { RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport type {\n  BrowserWindow,\n  RumFirstInputTiming,\n  RumPerformanceEntry,\n  RumPerformanceEventTiming,\n} from '../../../browser/performanceObservable'\nimport { ViewLoadingType } from '../../../rawRumEvent.types'\nimport { getInteractionSelector, updateInteractionSelector } from '../../action/interactionSelectorCache'\nimport {\n  trackInteractionToNextPaint,\n  trackViewInteractionCount,\n  isInteractionToNextPaintSupported,\n  MAX_INP_VALUE,\n} from './trackInteractionToNextPaint'\n\ndescribe('trackInteractionToNextPaint', () => {\n  let interactionCountMock: ReturnType<typeof mockInteractionCount>\n  let getInteractionToNextPaint: ReturnType<typeof trackInteractionToNextPaint>['getInteractionToNextPaint']\n  let setViewEnd: ReturnType<typeof trackInteractionToNextPaint>['setViewEnd']\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  function newInteraction(overrides: Partial<RumPerformanceEventTiming | RumFirstInputTiming>) {\n    if (overrides.interactionId) {\n      interactionCountMock.incrementInteractionCount()\n    }\n    const entry = createPerformanceEntry(overrides.entryType || RumPerformanceEntryType.EVENT, overrides)\n    notifyPerformanceEntries([entry])\n  }\n\n  function startINPTracking(viewStart = 0 as RelativeTime) {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n\n    interactionCountMock = mockInteractionCount()\n\n    const interactionToNextPaintTracking = trackInteractionToNextPaint(\n      mockRumConfiguration(),\n      viewStart,\n      ViewLoadingType.INITIAL_LOAD\n    )\n    getInteractionToNextPaint = interactionToNextPaintTracking.getInteractionToNextPaint\n    setViewEnd = interactionToNextPaintTracking.setViewEnd\n\n    registerCleanupTask(() => {\n      interactionToNextPaintTracking.stop()\n      interactionCountMock.clear()\n    })\n  }\n\n  beforeEach(() => {\n    if (!isInteractionToNextPaintSupported()) {\n      pending('No INP support')\n    }\n  })\n\n  it('should return undefined when there are no interactions', () => {\n    startINPTracking()\n    expect(getInteractionToNextPaint()).toEqual(undefined)\n  })\n\n  it('should ignore entries without interactionId', () => {\n    startINPTracking()\n    newInteraction({\n      interactionId: undefined,\n    })\n    expect(getInteractionToNextPaint()).toEqual(undefined)\n  })\n\n  it('should ignore entries that starts out of the view time bounds', () => {\n    startINPTracking()\n    setViewEnd(10 as RelativeTime)\n\n    newInteraction({\n      interactionId: 1,\n      duration: 10 as Duration,\n      startTime: -1 as RelativeTime,\n    })\n    newInteraction({\n      interactionId: 2,\n      duration: 10 as Duration,\n      startTime: 11 as RelativeTime,\n    })\n    expect(getInteractionToNextPaint()).toEqual(undefined)\n  })\n\n  it('should take into account entries that starts in view time bounds but finish after view end', () => {\n    startINPTracking()\n    setViewEnd(10 as RelativeTime)\n\n    newInteraction({\n      interactionId: 1,\n      duration: 100 as Duration,\n      startTime: 1 as RelativeTime,\n    })\n    expect(getInteractionToNextPaint()).toEqual({\n      value: 100 as Duration,\n      targetSelector: undefined,\n      time: 1 as RelativeTime,\n      subParts: { inputDelay: 1099 as Duration, processingDuration: 0 as Duration, presentationDelay: 0 as Duration },\n    })\n  })\n\n  it('should cap INP value', () => {\n    startINPTracking()\n    newInteraction({\n      interactionId: 1,\n      duration: (MAX_INP_VALUE + 1) as Duration,\n      startTime: 1 as RelativeTime,\n    })\n\n    expect(getInteractionToNextPaint()).toEqual({\n      value: MAX_INP_VALUE,\n      targetSelector: undefined,\n      time: 1 as RelativeTime,\n      subParts: {\n        inputDelay: 1099 as Duration,\n        processingDuration: 100 as Duration,\n        presentationDelay: (MAX_INP_VALUE - 1199) as Duration,\n      },\n    })\n  })\n\n  it('should return the p98 worst interaction', () => {\n    startINPTracking()\n    for (let index = 1; index <= 100; index++) {\n      newInteraction({\n        duration: index as Duration,\n        interactionId: index,\n        startTime: index as RelativeTime,\n      })\n    }\n    expect(getInteractionToNextPaint()).toEqual({\n      value: 98 as Duration,\n      targetSelector: undefined,\n      time: 98 as RelativeTime,\n      subParts: { inputDelay: 1004 as Duration, processingDuration: 0 as Duration, presentationDelay: 0 as Duration },\n    })\n  })\n\n  it('should return 0 when an interaction happened without generating a performance event (interaction duration below 40ms)', () => {\n    startINPTracking()\n    interactionCountMock.setInteractionCount(1 as Duration) // assumes an interaction happened but no PERFORMANCE_ENTRIES_COLLECTED have been triggered\n    expect(getInteractionToNextPaint()).toEqual({ value: 0 as Duration })\n  })\n\n  it('should take first-input entry into account', () => {\n    startINPTracking()\n    newInteraction({\n      interactionId: 1,\n      entryType: RumPerformanceEntryType.FIRST_INPUT,\n      startTime: 1 as RelativeTime,\n      duration: 40 as Duration,\n    })\n    expect(getInteractionToNextPaint()).toEqual({\n      value: 40 as Duration,\n      targetSelector: undefined,\n      time: 1 as RelativeTime,\n      subParts: { inputDelay: 1099 as Duration, processingDuration: 0 as Duration, presentationDelay: 0 as Duration },\n    })\n  })\n\n  it('should replace the entry in the list of worst interactions when an entry with the same interactionId exist', () => {\n    startINPTracking()\n    for (let index = 1; index <= 100; index++) {\n      newInteraction({\n        duration: index as Duration,\n        interactionId: 1,\n        startTime: index as RelativeTime,\n      })\n    }\n    // the p98 return 100 which shows that the entry has been updated\n    expect(getInteractionToNextPaint()).toEqual({\n      value: 100 as Duration,\n      targetSelector: undefined,\n      time: 100 as RelativeTime,\n      subParts: { inputDelay: 1099 as Duration, processingDuration: 0 as Duration, presentationDelay: 0 as Duration },\n    })\n  })\n\n  it('should get the time from the beginning of the view', () => {\n    const viewStart = 100 as RelativeTime\n    startINPTracking(viewStart)\n\n    const interactionStart = 110 as RelativeTime\n    newInteraction({\n      interactionId: 1,\n      duration: 10 as Duration,\n      startTime: interactionStart,\n    })\n    expect(getInteractionToNextPaint()!.time).toEqual(elapsed(viewStart, interactionStart))\n  })\n\n  describe('target selector', () => {\n    it('should be returned', () => {\n      startINPTracking()\n      newInteraction({\n        interactionId: 2,\n        target: appendElement('<button id=\"inp-target-element\"></button>'),\n      })\n\n      expect(getInteractionToNextPaint()?.targetSelector).toEqual('#inp-target-element')\n    })\n\n    it(\"should not be returned if it's not a DOM element\", () => {\n      startINPTracking()\n      newInteraction({\n        interactionId: 2,\n        target: appendText('text'),\n      })\n\n      expect(getInteractionToNextPaint()?.targetSelector).toEqual(undefined)\n    })\n\n    it('should not be recomputed if the INP has not changed', () => {\n      startINPTracking()\n      const element = appendElement('<button id=\"foo\"></button>')\n      newInteraction({\n        interactionId: 1,\n        duration: 10 as Duration,\n        target: element,\n      })\n\n      element.setAttribute('id', 'bar')\n\n      newInteraction({\n        interactionId: 2,\n        duration: 9 as Duration,\n        target: element,\n      })\n\n      expect(getInteractionToNextPaint()?.targetSelector).toEqual('#foo')\n    })\n\n    it('should be recomputed if the INP has changed', () => {\n      startINPTracking()\n      newInteraction({\n        interactionId: 1,\n        duration: 10 as Duration,\n        target: appendElement('<button id=\"foo\"></button>'),\n      })\n\n      newInteraction({\n        interactionId: 2,\n        duration: 11 as Duration,\n        target: appendElement('<button id=\"bar\"></button>'),\n      })\n\n      expect(getInteractionToNextPaint()?.targetSelector).toEqual('#bar')\n    })\n\n    it('should check interactionSelectorCache for entries', () => {\n      startINPTracking()\n      const startTime = relativeNow()\n      updateInteractionSelector(startTime, '#foo')\n\n      newInteraction({\n        interactionId: 1,\n        duration: 1 as Duration,\n        startTime,\n        target: undefined,\n      })\n\n      expect(getInteractionToNextPaint()?.targetSelector).toEqual('#foo')\n      expect(getInteractionSelector(startTime)).toBeUndefined()\n    })\n  })\n\n  describe('INP subparts', () => {\n    it('should not include subparts when INP is 0', () => {\n      startINPTracking()\n      interactionCountMock.setInteractionCount(1 as Duration)\n\n      expect(getInteractionToNextPaint()).toEqual({ value: 0 as Duration })\n    })\n    ;[\n      {\n        description: 'should calculate INP subparts correctly',\n        interaction: {\n          startTime: 1000,\n          processingStart: 1050,\n          processingEnd: 1200,\n          duration: 250,\n        },\n        expectedSubParts: {\n          inputDelay: 50, // 1050 - 1000\n          processingDuration: 150, // 1200 - 1050\n          presentationDelay: 50, // 1250 - 1200\n        },\n      },\n      {\n        description: 'should return undefined subparts when processingStart is missing',\n        interaction: {\n          startTime: 1000,\n          processingStart: undefined,\n          processingEnd: 1200,\n          duration: 250,\n        },\n        expectedSubParts: undefined,\n      },\n      {\n        description: 'should return undefined subparts when processingEnd is missing',\n        interaction: {\n          startTime: 1000,\n          processingStart: 1050,\n          processingEnd: undefined,\n          duration: 250,\n        },\n        expectedSubParts: undefined,\n      },\n      {\n        description: 'should clamp processingEnd to nextPaintTime',\n        interaction: {\n          startTime: 1000,\n          processingStart: 1050,\n          processingEnd: 1300, // Exceeds nextPaintTime (1000 + 250 = 1250)\n          duration: 250,\n        },\n        expectedSubParts: {\n          inputDelay: 50, // 1050 - 1000\n          processingDuration: 200, // 1250 - 1050 (clamped)\n          presentationDelay: 0, // 1250 - 1250\n        },\n      },\n    ].forEach(({ description, interaction, expectedSubParts }) => {\n      it(description, () => {\n        startINPTracking()\n\n        newInteraction({\n          interactionId: 1,\n          startTime: interaction.startTime as RelativeTime,\n          processingStart: interaction.processingStart as RelativeTime | undefined,\n          processingEnd: interaction.processingEnd as RelativeTime | undefined,\n          duration: interaction.duration as Duration,\n        })\n\n        const inp = getInteractionToNextPaint()\n\n        if (expectedSubParts === undefined) {\n          expect(inp?.subParts).toBeUndefined()\n        } else {\n          expect(inp?.subParts).toEqual({\n            inputDelay: expectedSubParts.inputDelay as Duration,\n            processingDuration: expectedSubParts.processingDuration as Duration,\n            presentationDelay: expectedSubParts.presentationDelay as Duration,\n          })\n          // Validate: subparts sum equals INP duration\n          const subPartsSum =\n            expectedSubParts.inputDelay + expectedSubParts.processingDuration + expectedSubParts.presentationDelay\n          expect(subPartsSum).toBe(interaction.duration)\n        }\n      })\n    })\n\n    it('should handle entry grouping with same interactionId by using group max processingEnd', () => {\n      startINPTracking()\n\n      newInteraction({\n        interactionId: 1,\n        startTime: 1000 as RelativeTime,\n        processingStart: 1050 as RelativeTime,\n        processingEnd: 1100 as RelativeTime,\n        duration: 250 as Duration,\n      })\n\n      newInteraction({\n        interactionId: 1,\n        startTime: 1005 as RelativeTime,\n        processingStart: 1060 as RelativeTime,\n        processingEnd: 1200 as RelativeTime,\n        duration: 245 as Duration,\n      })\n\n      const inp = getInteractionToNextPaint()\n      expect(inp?.value).toBe(250 as Duration)\n      expect(inp?.subParts).toEqual({\n        inputDelay: 50 as Duration,\n        processingDuration: 150 as Duration,\n        presentationDelay: 50 as Duration,\n      })\n    })\n\n    it('should group entries within 8ms renderTime window', () => {\n      startINPTracking()\n\n      newInteraction({\n        interactionId: 1,\n        startTime: 1000 as RelativeTime,\n        processingStart: 1050 as RelativeTime,\n        processingEnd: 1150 as RelativeTime,\n        duration: 250 as Duration,\n      })\n\n      // within 8ms renderTime window\n      newInteraction({\n        interactionId: 2,\n        startTime: 1010 as RelativeTime,\n        processingStart: 1055 as RelativeTime,\n        processingEnd: 1240 as RelativeTime,\n        duration: 245 as Duration,\n      })\n\n      // outside of 8ms renderTime window\n      newInteraction({\n        interactionId: 2,\n        startTime: 1020 as RelativeTime,\n        processingStart: 1070 as RelativeTime,\n        processingEnd: 1200 as RelativeTime,\n        duration: 190 as Duration,\n      })\n\n      const inp = getInteractionToNextPaint()\n      expect(inp?.value).toBe(250 as Duration)\n      expect(inp?.subParts).toEqual({\n        inputDelay: 50 as Duration,\n        processingDuration: 190 as Duration,\n        presentationDelay: 10 as Duration,\n      })\n    })\n\n    it('should keep correct subparts for p98 after interactions causing pruning', () => {\n      startINPTracking()\n\n      // The interaction that will remain the p98 throughout\n      newInteraction({\n        interactionId: 1,\n        startTime: 1000 as RelativeTime,\n        processingStart: 1050 as RelativeTime,\n        processingEnd: 1200 as RelativeTime,\n        duration: 1100 as Duration,\n      })\n\n      // Add more than MAX_INTERACTION_ENTRIES (10) shorter interactions to fill longestInteractions\n      // and trigger eviction and pruning of their groups\n      for (let i = 2; i <= 12; i++) {\n        newInteraction({\n          interactionId: i,\n          startTime: (i * 2000) as RelativeTime,\n          processingStart: (i * 2000 + 10) as RelativeTime,\n          processingEnd: (i * 2000 + 20) as RelativeTime,\n          duration: i as Duration,\n        })\n      }\n\n      const inp = getInteractionToNextPaint()\n      expect(inp?.value).toBe(1100 as Duration)\n      expect(inp?.subParts).toEqual({\n        inputDelay: 50 as Duration,\n        processingDuration: 150 as Duration,\n        presentationDelay: 900 as Duration,\n      })\n    })\n\n    it('should update subparts when INP changes to a different interaction', () => {\n      startINPTracking()\n\n      newInteraction({\n        interactionId: 1,\n        startTime: 1000 as RelativeTime,\n        processingStart: 1050 as RelativeTime,\n        processingEnd: 1150 as RelativeTime,\n        duration: 200 as Duration,\n      })\n\n      let inp = getInteractionToNextPaint()\n      expect(inp?.subParts?.inputDelay).toBe(50 as Duration)\n\n      newInteraction({\n        interactionId: 2,\n        startTime: 2000 as RelativeTime,\n        processingStart: 2100 as RelativeTime,\n        processingEnd: 2350 as RelativeTime,\n        duration: 400 as Duration,\n      })\n\n      inp = getInteractionToNextPaint()\n      expect(inp?.value).toBe(400 as Duration)\n      expect(inp?.subParts).toEqual({\n        inputDelay: 100 as Duration,\n        processingDuration: 250 as Duration,\n        presentationDelay: 50 as Duration,\n      })\n    })\n  })\n})\n\ndescribe('trackViewInteractionCount', () => {\n  let interactionCountMock: ReturnType<typeof mockInteractionCount>\n\n  beforeEach(() => {\n    interactionCountMock = mockInteractionCount()\n    interactionCountMock.setInteractionCount(5 as Duration)\n  })\n  afterEach(() => {\n    interactionCountMock.clear()\n  })\n\n  it('should count the interaction happening since the time origin when view loading type is initial_load', () => {\n    const { getViewInteractionCount } = trackViewInteractionCount(ViewLoadingType.INITIAL_LOAD)\n\n    expect(getViewInteractionCount()).toEqual(5)\n  })\n\n  it('should count the interaction from the moment the function is called when view loading type is route_change', () => {\n    const { getViewInteractionCount } = trackViewInteractionCount(ViewLoadingType.ROUTE_CHANGE)\n\n    expect(getViewInteractionCount()).toEqual(0)\n  })\n\n  it('should return the the last interaction count once stopped', () => {\n    const { getViewInteractionCount, stopViewInteractionCount } = trackViewInteractionCount(\n      ViewLoadingType.ROUTE_CHANGE\n    )\n    interactionCountMock.incrementInteractionCount()\n    stopViewInteractionCount()\n    interactionCountMock.incrementInteractionCount()\n    expect(getViewInteractionCount()).toEqual(1)\n  })\n})\n\nfunction mockInteractionCount() {\n  let interactionCount = 0\n  const originalInteractionCount = Object.getOwnPropertyDescriptor(window.performance, 'interactionCount')\n  Object.defineProperty(window.performance, 'interactionCount', { get: () => interactionCount, configurable: true })\n\n  return {\n    setInteractionCount: (newInteractionCount: Duration) => {\n      interactionCount = newInteractionCount\n    },\n    incrementInteractionCount() {\n      interactionCount++\n    },\n    clear: () => {\n      if (originalInteractionCount) {\n        Object.defineProperty(window.performance, 'interactionCount', originalInteractionCount)\n      } else {\n        delete ((window as BrowserWindow).performance as { interactionCount?: number }).interactionCount\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.ts",
    "content": "import type { Duration, RelativeTime } from '@datadog/browser-core'\nimport { elapsed, noop, ONE_MINUTE } from '@datadog/browser-core'\nimport type { RumFirstInputTiming, RumPerformanceEventTiming } from '../../../browser/performanceObservable'\nimport {\n  createPerformanceObservable,\n  RumPerformanceEntryType,\n  supportPerformanceTimingEvent,\n} from '../../../browser/performanceObservable'\nimport { ViewLoadingType } from '../../../rawRumEvent.types'\nimport { getSelectorFromElement } from '../../getSelectorFromElement'\nimport { isElementNode } from '../../../browser/htmlDomUtils'\nimport { getInteractionSelector } from '../../action/interactionSelectorCache'\nimport type { RumConfiguration } from '../../configuration'\nimport { getInteractionCount, initInteractionCountPolyfill } from './interactionCountPolyfill'\n\n// Arbitrary value to prevent unnecessary memory usage on views with lots of interactions.\nconst MAX_INTERACTION_ENTRIES = 10\n// Arbitrary value to cap INP outliers\nexport const MAX_INP_VALUE = (1 * ONE_MINUTE) as Duration\n\n// Event Timing API rounds duration values to the nearest 8 ms\nconst RENDER_TIME_GROUPING_THRESHOLD = 8 as Duration\n\nexport interface InteractionToNextPaint {\n  value: Duration\n  targetSelector?: string\n  time?: Duration\n  subParts?: {\n    inputDelay: Duration\n    processingDuration: Duration\n    presentationDelay: Duration\n  }\n}\ninterface EntriesGroup {\n  startTime: RelativeTime\n  processingStart: RelativeTime\n  processingEnd: RelativeTime\n  // Reference time used for grouping, set once at group creation — anchors the 8ms merge window\n  referenceRenderTime: RelativeTime\n}\n\n/**\n * Track the interaction to next paint (INP).\n * To avoid outliers, return the p98 worst interaction of the view.\n * Documentation: https://web.dev/inp/\n * Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/main/src/onINP.ts\n */\nexport function trackInteractionToNextPaint(\n  configuration: RumConfiguration,\n  viewStart: RelativeTime,\n  viewLoadingType: ViewLoadingType\n) {\n  if (!isInteractionToNextPaintSupported()) {\n    return {\n      getInteractionToNextPaint: () => undefined,\n      setViewEnd: noop,\n      stop: noop,\n    }\n  }\n\n  let viewEnd = Infinity as RelativeTime\n  let currentInp:\n    | {\n        duration: Duration\n        startTime: Duration\n        targetSelector?: string\n        subParts?: InteractionToNextPaint['subParts']\n      }\n    | undefined\n\n  const { getViewInteractionCount, stopViewInteractionCount } = trackViewInteractionCount(viewLoadingType)\n  const longestInteractions = trackLongestInteractions(getViewInteractionCount)\n  const subPartsTracker = createSubPartsTracker(longestInteractions)\n  const firstInputSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.FIRST_INPUT,\n    buffered: true,\n  }).subscribe(handleEntries)\n  const eventSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.EVENT,\n    // durationThreshold only impact PerformanceEventTiming entries used for INP computation which requires a threshold at 40 (default is 104ms)\n    // cf: https://github.com/GoogleChrome/web-vitals/blob/3806160ffbc93c3c4abf210a167b81228172b31c/src/onINP.ts#L202-L210\n    durationThreshold: 40,\n    buffered: true,\n  }).subscribe(handleEntries)\n\n  function handleEntries(entries: Array<RumPerformanceEventTiming | RumFirstInputTiming>) {\n    for (const entry of entries) {\n      if (\n        entry.interactionId &&\n        // Check the entry start time is inside the view bounds because some view interactions can be reported after the view end (if long duration).\n        entry.startTime >= viewStart &&\n        entry.startTime <= viewEnd\n      ) {\n        longestInteractions.process(entry)\n        subPartsTracker.process(entry)\n      }\n    }\n    subPartsTracker.pruneUntracked()\n    const candidate = longestInteractions.estimateP98Interaction()\n    if (candidate) {\n      updateCurrentInp(candidate)\n    }\n  }\n\n  function updateCurrentInp(candidate: RumPerformanceEventTiming | RumFirstInputTiming) {\n    const newStartTime = elapsed(viewStart, candidate.startTime)\n    // startTime catches identity changes when the p98 switches to a different interaction with the same duration,\n    // ensuring targetSelector and subParts always describe the same interaction.\n    if (!currentInp || candidate.duration !== currentInp.duration || newStartTime !== currentInp.startTime) {\n      let targetSelector = getInteractionSelector(candidate.startTime)\n      if (!targetSelector && candidate.target && isElementNode(candidate.target)) {\n        targetSelector = getSelectorFromElement(candidate.target, configuration.actionNameAttribute)\n      }\n      currentInp = {\n        duration: candidate.duration,\n        startTime: newStartTime,\n        targetSelector,\n      }\n    }\n    // Recomputed on every batch: the group for the p98 interaction may have been updated\n    // with new min/max timing even when the p98 identity (duration, startTime) is unchanged.\n    currentInp.subParts = subPartsTracker.computeSubParts(candidate, sanitizeInpValue(currentInp.duration))\n  }\n\n  return {\n    getInteractionToNextPaint: (): InteractionToNextPaint | undefined => {\n      // If no INP duration where captured because of the performanceObserver 40ms threshold\n      // but the view interaction count > 0 then report 0\n      if (currentInp) {\n        return {\n          value: sanitizeInpValue(currentInp.duration),\n          targetSelector: currentInp.targetSelector,\n          time: currentInp.startTime,\n          subParts: currentInp.subParts,\n        }\n      } else if (getViewInteractionCount()) {\n        return {\n          value: 0 as Duration,\n        }\n      }\n    },\n    setViewEnd: (viewEndTime: RelativeTime) => {\n      viewEnd = viewEndTime\n      stopViewInteractionCount()\n    },\n    stop: () => {\n      eventSubscription.unsubscribe()\n      firstInputSubscription.unsubscribe()\n      subPartsTracker.stop()\n    },\n  }\n}\n\n/**\n * Maintains a bounded list of the slowest interactions seen so far, used to estimate the p98\n * interaction duration without keeping every entry in memory.\n */\nfunction trackLongestInteractions(getViewInteractionCount: () => number) {\n  const longestInteractions: Array<RumPerformanceEventTiming | RumFirstInputTiming> = []\n\n  function sortAndTrimLongestInteractions() {\n    longestInteractions.sort((a, b) => b.duration - a.duration).splice(MAX_INTERACTION_ENTRIES)\n  }\n\n  return {\n    /**\n     * Process the performance entry:\n     * - if its duration is long enough, add the performance entry to the list of worst interactions\n     * - if an entry with the same interaction id exists and its duration is lower than the new one, then replace it in the list of worst interactions\n     */\n    process(entry: RumPerformanceEventTiming | RumFirstInputTiming) {\n      const interactionIndex = longestInteractions.findIndex(\n        (interaction) => entry.interactionId === interaction.interactionId\n      )\n\n      const minLongestInteraction = longestInteractions[longestInteractions.length - 1]\n\n      if (interactionIndex !== -1) {\n        if (entry.duration > longestInteractions[interactionIndex].duration) {\n          longestInteractions[interactionIndex] = entry\n          sortAndTrimLongestInteractions()\n        }\n      } else if (\n        longestInteractions.length < MAX_INTERACTION_ENTRIES ||\n        entry.duration > minLongestInteraction.duration\n      ) {\n        longestInteractions.push(entry)\n        sortAndTrimLongestInteractions()\n      }\n    },\n    /**\n     * Compute the p98 longest interaction.\n     * For better performance the computation is based on 10 longest interactions and the interaction count of the current view.\n     */\n    estimateP98Interaction(): RumPerformanceEventTiming | RumFirstInputTiming | undefined {\n      const interactionIndex = Math.min(longestInteractions.length - 1, Math.floor(getViewInteractionCount() / 50))\n      return longestInteractions[interactionIndex]\n    },\n\n    isTracked(interactionId: number): boolean {\n      return longestInteractions.some((i) => i.interactionId === interactionId)\n    },\n  }\n}\n\n/**\n * Tracks the number of interactions that occurred during the current view. Freezes the count\n * when the view ends so that the p98 estimate remains stable after `setViewEnd` is called.\n */\nexport function trackViewInteractionCount(viewLoadingType: ViewLoadingType) {\n  initInteractionCountPolyfill()\n  const previousInteractionCount = viewLoadingType === ViewLoadingType.INITIAL_LOAD ? 0 : getInteractionCount()\n  let state: { stopped: false } | { stopped: true; interactionCount: number } = { stopped: false }\n\n  function computeViewInteractionCount() {\n    return getInteractionCount() - previousInteractionCount\n  }\n\n  return {\n    getViewInteractionCount: () => {\n      if (state.stopped) {\n        return state.interactionCount\n      }\n\n      return computeViewInteractionCount()\n    },\n    stopViewInteractionCount: () => {\n      state = { stopped: true, interactionCount: computeViewInteractionCount() }\n    },\n  }\n}\n\n/**\n * Groups performance entries by interaction and render time to compute INP subparts\n * (input delay, processing duration, presentation delay). Entries sharing the same\n * interactionId, or whose render time falls within the 8 ms Event Timing rounding window,\n * are merged into a single group so that subparts always sum to the reported INP duration.\n */\nfunction createSubPartsTracker(longestInteractions: ReturnType<typeof trackLongestInteractions>) {\n  const groupsByInteractionId = new Map<number, EntriesGroup>()\n\n  function updateGroupWithEntry(group: EntriesGroup, entry: RumPerformanceEventTiming | RumFirstInputTiming) {\n    group.startTime = Math.min(entry.startTime, group.startTime) as RelativeTime\n    // For each group, we keep the biggest interval possible between processingStart and processingEnd\n    group.processingStart = Math.min(entry.processingStart, group.processingStart) as RelativeTime\n    group.processingEnd = Math.max(entry.processingEnd, group.processingEnd) as RelativeTime\n  }\n\n  return {\n    process(entry: RumPerformanceEventTiming | RumFirstInputTiming): void {\n      if (entry.interactionId === undefined || !entry.processingStart || !entry.processingEnd) {\n        return\n      }\n\n      const renderTime = (entry.startTime + entry.duration) as RelativeTime\n      const existingGroup = groupsByInteractionId.get(entry.interactionId)\n\n      if (existingGroup) {\n        // Update existing group with MIN/MAX values (keep original referenceRenderTime)\n        updateGroupWithEntry(existingGroup, entry)\n        return\n      }\n\n      // Try to find a group within 8ms window to merge with (different interactionId, same frame)\n      for (const [, group] of groupsByInteractionId.entries()) {\n        if (Math.abs(renderTime - group.referenceRenderTime) <= RENDER_TIME_GROUPING_THRESHOLD) {\n          updateGroupWithEntry(group, entry)\n          // Also store under this entry's interactionId for easy lookup\n          groupsByInteractionId.set(entry.interactionId, group)\n          return\n        }\n      }\n\n      // Create new group\n      groupsByInteractionId.set(entry.interactionId, {\n        startTime: entry.startTime,\n        processingStart: entry.processingStart,\n        processingEnd: entry.processingEnd,\n        referenceRenderTime: renderTime,\n      })\n    },\n\n    // Prune after all entries are grouped: groups not in longestInteractions can never affect p98 subparts.\n    // Keeps groupsByInteractionId capped at MAX_INTERACTION_ENTRIES\n    pruneUntracked(): void {\n      for (const [interactionId] of groupsByInteractionId) {\n        if (!longestInteractions.isTracked(interactionId)) {\n          groupsByInteractionId.delete(interactionId)\n        }\n      }\n    },\n\n    computeSubParts(\n      entry: RumPerformanceEventTiming | RumFirstInputTiming,\n      inpDuration: Duration\n    ): InteractionToNextPaint['subParts'] | undefined {\n      if (!entry.processingStart || !entry.processingEnd || entry.interactionId === undefined) {\n        return undefined\n      }\n\n      const group = groupsByInteractionId.get(entry.interactionId)\n      // Shouldn't happen since entries are grouped before p98 calculation.\n      if (!group) {\n        return undefined\n      }\n\n      // Use group.startTime consistently to ensure subparts sum to inpDuration\n      // Math.max prevents nextPaintTime from being before processingStart (Chrome implementation)\n      const nextPaintTime = Math.max(\n        (group.startTime + inpDuration) as RelativeTime,\n        group.processingStart\n      ) as RelativeTime\n\n      // Clamp processingEnd to not exceed nextPaintTime\n      const processingEnd = Math.min(group.processingEnd, nextPaintTime) as RelativeTime\n\n      return {\n        inputDelay: elapsed(group.startTime, group.processingStart),\n        processingDuration: elapsed(group.processingStart, processingEnd),\n        presentationDelay: elapsed(processingEnd, nextPaintTime),\n      }\n    },\n\n    stop(): void {\n      groupsByInteractionId.clear()\n    },\n  }\n}\n\nexport function isInteractionToNextPaintSupported() {\n  return (\n    supportPerformanceTimingEvent(RumPerformanceEntryType.EVENT) &&\n    window.PerformanceEventTiming &&\n    'interactionId' in PerformanceEventTiming.prototype\n  )\n}\n\nfunction sanitizeInpValue(inpValue: Duration) {\n  return Math.min(inpValue, MAX_INP_VALUE) as Duration\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.spec.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { clocksOrigin, DOM_EVENT } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport {\n  setPageVisibility,\n  createNewEvent,\n  restorePageVisibility,\n  registerCleanupTask,\n  mockClock,\n} from '@datadog/browser-core/test'\nimport type { RumPerformanceEntry } from '../../../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport { appendElement, createPerformanceEntry, mockPerformanceObserver, mockRumConfiguration } from '../../../../test'\nimport type { LargestContentfulPaint } from './trackLargestContentfulPaint'\nimport { LCP_MAXIMUM_DELAY, trackLargestContentfulPaint } from './trackLargestContentfulPaint'\nimport { trackFirstHidden } from './trackFirstHidden'\n\ninterface ResourceEntryOptions {\n  startTime: number\n  requestStart: number\n  responseEnd: number\n}\n\ninterface StartLCPTrackingOptions {\n  firstByte?: number\n  resources?: ResourceEntryOptions[]\n}\n\ndescribe('trackLargestContentfulPaint', () => {\n  let lcpCallback: jasmine.Spy<(lcp: LargestContentfulPaint) => void>\n  let eventTarget: Window\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n  let clock: Clock\n  let mockSubParts: LargestContentfulPaint['subParts']\n  const mockResourceName = 'https://example.com/image.jpg'\n\n  function startLCPTracking(options: StartLCPTrackingOptions = {}) {\n    const { firstByte = 789, resources = [] } = options\n\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n\n    // This ensures getNavigationEntry() returns controlled values for subParts calculation.\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.NAVIGATION, { responseStart: firstByte as RelativeTime }),\n    ])\n\n    // Add resource entries to the global performance buffer so findLcpResourceEntry can find them\n    // notifyPerformanceEntries adds entries to the global buffer via mockGlobalPerformanceBuffer\n    for (const resource of resources) {\n      notifyPerformanceEntries([\n        createPerformanceEntry(RumPerformanceEntryType.RESOURCE, {\n          name: mockResourceName,\n          startTime: resource.startTime as RelativeTime,\n          requestStart: resource.requestStart as RelativeTime,\n          responseEnd: resource.responseEnd as RelativeTime,\n        }),\n      ])\n    }\n\n    const firstHidden = trackFirstHidden(mockRumConfiguration(), clocksOrigin())\n    const largestContentfulPaint = trackLargestContentfulPaint(\n      mockRumConfiguration(),\n      firstHidden,\n      eventTarget,\n      lcpCallback\n    )\n\n    registerCleanupTask(() => {\n      firstHidden.stop()\n      largestContentfulPaint.stop()\n      restorePageVisibility()\n    })\n\n    mockSubParts = {\n      loadDelay: 0 as RelativeTime,\n      loadTime: 0 as RelativeTime,\n      renderDelay: 0 as RelativeTime,\n    }\n  }\n\n  beforeEach(() => {\n    lcpCallback = jasmine.createSpy()\n    eventTarget = document.createElement('div') as unknown as Window\n    // Mock clock and advance time so that responseStart: 789 passes the sanitizeFirstByte check\n    // which requires responseStart <= relativeNow()\n    clock = mockClock()\n    clock.tick(1000)\n  })\n\n  it('should provide the largest contentful paint timing', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT)])\n\n    expect(lcpCallback).toHaveBeenCalledOnceWith({\n      value: 789 as RelativeTime,\n      targetSelector: undefined,\n      resourceUrl: undefined,\n      subParts: mockSubParts,\n    })\n  })\n\n  it('should provide the largest contentful paint target selector', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        element: appendElement('<button id=\"lcp-target-element\"></button>'),\n      }),\n    ])\n\n    expect(lcpCallback).toHaveBeenCalledOnceWith({\n      value: 789 as RelativeTime,\n      targetSelector: '#lcp-target-element',\n      resourceUrl: undefined,\n      subParts: mockSubParts,\n    })\n  })\n\n  it('should provide the largest contentful paint target url', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        url: 'https://example.com/lcp-resource',\n      }),\n    ])\n\n    expect(lcpCallback).toHaveBeenCalledOnceWith({\n      value: 789 as RelativeTime,\n      targetSelector: undefined,\n      resourceUrl: 'https://example.com/lcp-resource',\n      subParts: mockSubParts,\n    })\n  })\n\n  it('should be discarded if it is reported after a user interaction', () => {\n    startLCPTracking()\n    eventTarget.dispatchEvent(createNewEvent(DOM_EVENT.KEY_DOWN, { timeStamp: 1 }))\n\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT)])\n\n    expect(lcpCallback).not.toHaveBeenCalled()\n  })\n\n  it('should be discarded if the page is hidden', () => {\n    setPageVisibility('hidden')\n    startLCPTracking()\n\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT)])\n\n    expect(lcpCallback).not.toHaveBeenCalled()\n  })\n\n  it('should be discarded if it is reported after a long time', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        startTime: LCP_MAXIMUM_DELAY as RelativeTime,\n      }),\n    ])\n\n    expect(lcpCallback).not.toHaveBeenCalled()\n  })\n\n  it('should be discarded if it has a size inferior to the previous LCP entry', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        startTime: 1 as RelativeTime,\n        size: 10,\n      }),\n    ])\n\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        startTime: 2 as RelativeTime,\n        size: 5,\n      }),\n    ])\n\n    expect(lcpCallback).toHaveBeenCalledOnceWith(jasmine.objectContaining({ value: 1 }))\n  })\n\n  it('should notify multiple times when the size is bigger than the previous entry', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        startTime: 1 as RelativeTime,\n        size: 5,\n      }),\n    ])\n\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        startTime: 2 as RelativeTime,\n        size: 10,\n      }),\n    ])\n    expect(lcpCallback).toHaveBeenCalledTimes(2)\n    expect(lcpCallback.calls.first().args[0]).toEqual(jasmine.objectContaining({ value: 1 }))\n    expect(lcpCallback.calls.mostRecent().args[0]).toEqual(jasmine.objectContaining({ value: 2 }))\n  })\n\n  it('should return undefined when LCP entry has an empty string as url', () => {\n    startLCPTracking()\n    notifyPerformanceEntries([\n      createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n        url: '',\n      }),\n    ])\n\n    expect(lcpCallback).toHaveBeenCalledOnceWith({\n      value: 789 as RelativeTime,\n      targetSelector: undefined,\n      resourceUrl: undefined,\n      subParts: mockSubParts,\n    })\n  })\n\n  describe('LCP subParts', () => {\n    it('should not provide subParts if the first byte is not available', () => {\n      // Negative responseStart makes sanitizeFirstByte return undefined\n      startLCPTracking({ firstByte: -1 })\n\n      notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT)])\n\n      expect(lcpCallback).toHaveBeenCalledOnceWith({\n        value: 789 as RelativeTime,\n        targetSelector: undefined,\n        resourceUrl: undefined,\n        subParts: undefined,\n      })\n    })\n    ;[\n      {\n        description: 'should cap lcpResponseEnd at LCP time for resources that complete after LCP',\n        firstByte: 200,\n        resource: {\n          startTime: 500,\n          requestStart: 500,\n          responseEnd: 5000, // Continues downloading long after LCP\n        },\n        lcpTime: 1200,\n        expectedSubParts: {\n          loadDelay: 300, // 500 - 200\n          loadTime: 700, // 1200 (capped) - 500\n          renderDelay: 0, // 1200 - 1200 (capped) = 0\n        },\n      },\n      {\n        description: 'should not cap lcpResponseEnd when resource completes before LCP',\n        firstByte: 200,\n        resource: {\n          startTime: 500,\n          requestStart: 500,\n          responseEnd: 1000,\n        },\n        lcpTime: 1200,\n        expectedSubParts: {\n          loadDelay: 300, // 500 - 200\n          loadTime: 500, // 1000 - 500 (not capped)\n          renderDelay: 200, // 1200 - 1000\n        },\n      },\n      {\n        description: 'should prefer requestStart over startTime when available (TAO enabled)',\n        firstByte: 200,\n        resource: {\n          startTime: 500, // Resource discovered at 500ms\n          requestStart: 700, // HTTP request started at 700ms (delayed)\n          responseEnd: 1000,\n        },\n        lcpTime: 1200,\n        expectedSubParts: {\n          loadDelay: 500, // 700 (requestStart) - 200, not 300 (startTime - 200)\n          loadTime: 300, // 1000 - 700 (requestStart)\n          renderDelay: 200, // 1200 - 1000\n        },\n      },\n      {\n        description: 'should fallback to startTime when requestStart is 0 (cross-origin without TAO)',\n        firstByte: 200,\n        resource: {\n          startTime: 500,\n          requestStart: 0, // Not available (cross-origin without TAO)\n          responseEnd: 1000,\n        },\n        lcpTime: 1200,\n        expectedSubParts: {\n          loadDelay: 300, // Falls back to: 500 (startTime) - 200\n          loadTime: 500, // 1000 - 500 (startTime)\n          renderDelay: 200, // 1200 - 1000\n        },\n      },\n      {\n        description: 'should handle TAO resource with normal completion',\n        firstByte: 100,\n        resource: {\n          startTime: 200, // Resource discovered\n          requestStart: 300, // HTTP request started (prefer this)\n          responseEnd: 700, // Download completed\n        },\n        lcpTime: 900,\n        expectedSubParts: {\n          loadDelay: 200, // 300 - 100\n          loadTime: 400, // 700 - 300\n          renderDelay: 200, // 900 - 700\n        },\n      },\n      {\n        description: 'should handle resource that completes exactly at LCP time',\n        firstByte: 100,\n        resource: {\n          startTime: 500,\n          requestStart: 500,\n          responseEnd: 1200, // Completes exactly at LCP time\n        },\n        lcpTime: 1200,\n        expectedSubParts: {\n          loadDelay: 400, // 500 - 100\n          loadTime: 700, // 1200 - 500\n          renderDelay: 0, // 1200 - 1200 = 0 (no render delay)\n        },\n      },\n      {\n        description: 'should handle LCP with no associated resource entry (text, data URL, inline image)',\n        firstByte: 200,\n        lcpTime: 1000,\n        lcpUrl: '', // No resource\n        expectedSubParts: {\n          loadDelay: 0, // No resource, so max(firstByte, 0) - firstByte = 0\n          loadTime: 0, // No resource, so max(firstByte, 0) - firstByte = 0\n          renderDelay: 800, // 1000 - 200 (firstByte is used as lcpResponseEnd when no resource)\n        },\n      },\n      {\n        description: 'should handle cached resource with incomplete timing data (cross-origin without TAO)',\n        firstByte: 150,\n        resource: {\n          startTime: 400,\n          requestStart: 0, // Not available (cross-origin)\n          responseEnd: 0, // Not available (cached)\n        },\n        lcpTime: 800,\n        expectedSubParts: {\n          // lcpRequestStart = max(150, 400 - 0) = 400 (falls back to startTime)\n          loadDelay: 250, // 400 - 150\n          // lcpResponseEnd = min(800, max(400, 0 - 0)) = min(800, 400) = 400\n          loadTime: 0, // 400 - 400\n          renderDelay: 400, // 800 - 400\n        },\n      },\n    ].forEach(({ description, firstByte, resource, lcpTime, lcpUrl, expectedSubParts }) => {\n      it(description, () => {\n        startLCPTracking({\n          firstByte,\n          resources: resource ? [resource] : [],\n        })\n\n        notifyPerformanceEntries([\n          createPerformanceEntry(RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT, {\n            startTime: lcpTime as RelativeTime,\n            url: lcpUrl === undefined ? mockResourceName : lcpUrl,\n          }),\n        ])\n\n        const result = lcpCallback.calls.mostRecent().args[0]\n\n        expect(result.subParts).toEqual(\n          expectedSubParts as {\n            loadDelay: RelativeTime\n            loadTime: RelativeTime\n            renderDelay: RelativeTime\n          }\n        )\n\n        // Validate: firstByte + loadDelay + loadTime + renderDelay = LCP value\n        const sum = Object.values(result.subParts!).reduce((acc, curr) => acc + curr, 0)\n        expect(sum + firstByte).toBe(result.value)\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.ts",
    "content": "import type { RelativeTime } from '@datadog/browser-core'\nimport { DOM_EVENT, ONE_MINUTE, addEventListeners, findLast } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../../configuration'\nimport { createPerformanceObservable, RumPerformanceEntryType } from '../../../browser/performanceObservable'\nimport { findLcpResourceEntry, getNavigationEntry, sanitizeFirstByte } from '../../../browser/performanceUtils'\nimport type { RumLargestContentfulPaintTiming } from '../../../browser/performanceObservable'\nimport { getSelectorFromElement } from '../../getSelectorFromElement'\nimport type { FirstHidden } from './trackFirstHidden'\n\n// Discard LCP timings above a certain delay to avoid incorrect data\n// It happens in some cases like sleep mode or some browser implementations\nexport const LCP_MAXIMUM_DELAY = 10 * ONE_MINUTE\n\nexport interface LargestContentfulPaint {\n  value: RelativeTime\n  targetSelector?: string\n  resourceUrl?: string\n  subParts?: {\n    loadDelay: RelativeTime\n    loadTime: RelativeTime\n    renderDelay: RelativeTime\n  }\n}\n\n/**\n * Track the largest contentful paint (LCP) occurring during the initial View.  This can yield\n * multiple values, only the most recent one should be used.\n * Documentation: https://web.dev/lcp/\n * Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/onLCP.ts\n */\nexport function trackLargestContentfulPaint(\n  configuration: RumConfiguration,\n  firstHidden: FirstHidden,\n  eventTarget: Window,\n  callback: (largestContentfulPaint: LargestContentfulPaint) => void\n) {\n  // Ignore entries that come after the first user interaction. According to the documentation, the\n  // browser should not send largest-contentful-paint entries after a user interact with the page,\n  // but the web-vitals reference implementation uses this as a safeguard.\n  let firstInteractionTimestamp = Infinity\n  const { stop: stopEventListener } = addEventListeners(\n    configuration,\n    eventTarget,\n    [DOM_EVENT.POINTER_DOWN, DOM_EVENT.KEY_DOWN],\n    (event) => {\n      firstInteractionTimestamp = event.timeStamp\n    },\n    { capture: true, once: true }\n  )\n\n  let biggestLcpSize = 0\n  const performanceLcpSubscription = createPerformanceObservable(configuration, {\n    type: RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT,\n    buffered: true,\n  }).subscribe((entries) => {\n    const lcpEntry = findLast(\n      entries,\n      (entry): entry is RumLargestContentfulPaintTiming =>\n        entry.entryType === RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT &&\n        entry.startTime < firstInteractionTimestamp &&\n        entry.startTime < firstHidden.timeStamp &&\n        entry.startTime < LCP_MAXIMUM_DELAY &&\n        // Ensure to get the LCP entry with the biggest size, see\n        // https://bugs.chromium.org/p/chromium/issues/detail?id=1516655\n        entry.size > biggestLcpSize\n    )\n    if (lcpEntry) {\n      let lcpTargetSelector\n      if (lcpEntry.element) {\n        lcpTargetSelector = getSelectorFromElement(lcpEntry.element, configuration.actionNameAttribute)\n      }\n\n      const resourceUrl = computeLcpEntryUrl(lcpEntry)\n      const lcpValue = lcpEntry.startTime\n\n      const subParts = computeLcpSubParts(resourceUrl, lcpValue)\n\n      callback({\n        value: lcpValue,\n        targetSelector: lcpTargetSelector,\n        resourceUrl,\n        subParts,\n      })\n      biggestLcpSize = lcpEntry.size\n    }\n  })\n\n  return {\n    stop: () => {\n      stopEventListener()\n      performanceLcpSubscription.unsubscribe()\n    },\n  }\n}\n\n// The property url report an empty string if the value is not available, we shouldn't report it in this case.\nfunction computeLcpEntryUrl(entry: RumLargestContentfulPaintTiming) {\n  return entry.url === '' ? undefined : entry.url\n}\n\n/**\n * Compute the LCP sub-parts breakdown (loadDelay, loadTime, renderDelay).\n * Returns undefined if navigation timing data or TTFB is unavailable.\n */\nfunction computeLcpSubParts(\n  resourceUrl: string | undefined,\n  lcpValue: RelativeTime\n): LargestContentfulPaint['subParts'] {\n  const firstByte = sanitizeFirstByte(getNavigationEntry())\n\n  if (firstByte === undefined) {\n    return undefined\n  }\n\n  const lcpResourceEntry = resourceUrl ? findLcpResourceEntry(resourceUrl, lcpValue) : undefined\n  const lcpRequestStart = lcpResourceEntry\n    ? (Math.max(firstByte, lcpResourceEntry.requestStart || lcpResourceEntry.startTime) as RelativeTime)\n    : firstByte\n\n  // Cap at LCP time to handle resources that continue downloading after LCP (e.g., videos)\n  const lcpResponseEnd = Math.min(lcpValue, Math.max(lcpRequestStart, lcpResourceEntry?.responseEnd || 0))\n\n  return {\n    loadDelay: (lcpRequestStart - firstByte) as RelativeTime,\n    loadTime: (lcpResponseEnd - lcpRequestStart) as RelativeTime,\n    renderDelay: (lcpValue - lcpResponseEnd) as RelativeTime,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackLoadingTime.spec.ts",
    "content": "import type { RelativeTime, Duration } from '@datadog/browser-core'\nimport { clocksNow, clocksOrigin, noop, Observable } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, setPageVisibility, restorePageVisibility } from '@datadog/browser-core/test'\nimport { ViewLoadingType } from '../../../rawRumEvent.types'\nimport {\n  createMutationRecord,\n  createPerformanceEntry,\n  type GlobalPerformanceBufferMock,\n  mockGlobalPerformanceBuffer,\n  mockRumConfiguration,\n} from '../../../../test'\nimport { PAGE_ACTIVITY_END_DELAY, PAGE_ACTIVITY_VALIDATION_DELAY } from '../../waitPageActivityEnd'\nimport { RumPerformanceEntryType, supportPerformanceTimingEvent } from '../../../browser/performanceObservable'\nimport { LifeCycle } from '../../lifeCycle'\nimport type { RumMutationRecord } from '../../../browser/domMutationObservable'\nimport { trackLoadingTime } from './trackLoadingTime'\n\nconst BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY = (PAGE_ACTIVITY_VALIDATION_DELAY * 0.8) as Duration\n\nconst AFTER_PAGE_ACTIVITY_END_DELAY = PAGE_ACTIVITY_END_DELAY * 1.1\n\nconst LOAD_EVENT_BEFORE_ACTIVITY_TIMING = (BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY * 0.8) as RelativeTime\n\nconst LOAD_EVENT_AFTER_ACTIVITY_TIMING = (BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY * 1.2) as RelativeTime\n\nconst RANDOM_VIEW_START = 50 as RelativeTime\n\ndescribe('trackLoadingTime', () => {\n  const lifeCycle = new LifeCycle()\n  let clock: Clock\n  let domMutationObservable: Observable<RumMutationRecord[]>\n  let windowOpenObservable: Observable<void>\n  let loadingTimeCallback: jasmine.Spy<(loadingTime: Duration) => void>\n  let setLoadEvent: (loadEvent: Duration) => void\n  let stopLoadingTimeTracking = noop\n  let performanceBufferMock: GlobalPerformanceBufferMock\n\n  function emulatePageActivityDuringViewLoading() {\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n    domMutationObservable.notify([createMutationRecord()])\n    clock.tick(AFTER_PAGE_ACTIVITY_END_DELAY)\n  }\n\n  beforeEach(() => {\n    performanceBufferMock = mockGlobalPerformanceBuffer()\n  })\n\n  function startLoadingTimeTracking(\n    loadType: ViewLoadingType = ViewLoadingType.ROUTE_CHANGE,\n    viewStart = clocksOrigin()\n  ) {\n    const loadingTimeTracking = trackLoadingTime(\n      lifeCycle,\n      domMutationObservable,\n      windowOpenObservable,\n      mockRumConfiguration(),\n      loadType,\n      viewStart,\n      loadingTimeCallback\n    )\n    setLoadEvent = loadingTimeTracking.setLoadEvent\n    stopLoadingTimeTracking = loadingTimeTracking.stop\n  }\n\n  beforeEach(() => {\n    clock = mockClock()\n    domMutationObservable = new Observable()\n    windowOpenObservable = new Observable()\n    loadingTimeCallback = jasmine.createSpy<(loadingTime: Duration) => void>()\n  })\n\n  afterEach(() => {\n    stopLoadingTimeTracking()\n    restorePageVisibility()\n  })\n\n  it('should have an undefined loading time if there is no activity on a route change', () => {\n    startLoadingTimeTracking()\n    expect(loadingTimeCallback).not.toHaveBeenCalled()\n  })\n\n  it('should have a loading time equal to the activity time if there is a unique activity on a route change', () => {\n    startLoadingTimeTracking()\n\n    emulatePageActivityDuringViewLoading()\n\n    expect(loadingTimeCallback).toHaveBeenCalledOnceWith(clock.relative(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY))\n  })\n\n  it('should use loadEventEnd for initial view when having no activity', () => {\n    const loadType = ViewLoadingType.INITIAL_LOAD\n    startLoadingTimeTracking(loadType)\n\n    const entry = createPerformanceEntry(RumPerformanceEntryType.NAVIGATION)\n\n    setLoadEvent(entry.loadEventEnd)\n    clock.tick(PAGE_ACTIVITY_END_DELAY)\n\n    expect(loadingTimeCallback).toHaveBeenCalledOnceWith(entry.loadEventEnd)\n  })\n\n  it('should use loadEventEnd for initial view when load event is bigger than computed loading time', () => {\n    const loadType = ViewLoadingType.INITIAL_LOAD\n    startLoadingTimeTracking(loadType)\n\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n\n    setLoadEvent(clock.relative(LOAD_EVENT_AFTER_ACTIVITY_TIMING))\n    domMutationObservable.notify([createMutationRecord()])\n    clock.tick(AFTER_PAGE_ACTIVITY_END_DELAY)\n\n    expect(loadingTimeCallback).toHaveBeenCalledOnceWith(clock.relative(LOAD_EVENT_AFTER_ACTIVITY_TIMING))\n  })\n\n  it('should use computed loading time for initial view when load event is smaller than computed loading time', () => {\n    const loadType = ViewLoadingType.INITIAL_LOAD\n    startLoadingTimeTracking(loadType)\n\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n\n    setLoadEvent(clock.relative(LOAD_EVENT_BEFORE_ACTIVITY_TIMING))\n\n    domMutationObservable.notify([createMutationRecord()])\n    clock.tick(AFTER_PAGE_ACTIVITY_END_DELAY)\n\n    expect(loadingTimeCallback).toHaveBeenCalledOnceWith(clock.relative(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY))\n  })\n\n  it('should use computed loading time from time origin for initial view', () => {\n    const loadType = ViewLoadingType.INITIAL_LOAD\n\n    // introduce a gap between time origin and tracking start\n    // ensure that `load event > activity delay` and `load event < activity delay + clock gap`\n    // to make the test fail if the clock gap is not correctly taken into account\n    const CLOCK_GAP = (LOAD_EVENT_AFTER_ACTIVITY_TIMING - BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY + 1) as Duration\n\n    clock.tick(CLOCK_GAP)\n\n    startLoadingTimeTracking(loadType)\n\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n\n    setLoadEvent(clock.relative(LOAD_EVENT_BEFORE_ACTIVITY_TIMING))\n\n    domMutationObservable.notify([createMutationRecord()])\n    clock.tick(AFTER_PAGE_ACTIVITY_END_DELAY)\n\n    expect(loadingTimeCallback).toHaveBeenCalledOnceWith(\n      clock.relative(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY + CLOCK_GAP)\n    )\n  })\n\n  it('should discard loading time if page is hidden before activity', () => {\n    setPageVisibility('hidden')\n    startLoadingTimeTracking()\n\n    emulatePageActivityDuringViewLoading()\n\n    expect(loadingTimeCallback).not.toHaveBeenCalled()\n  })\n\n  it('should not discard loading time if page was hidden before the view start', () => {\n    if (!supportPerformanceTimingEvent(RumPerformanceEntryType.VISIBILITY_STATE)) {\n      pending('Performance Timing Event is not supported')\n    }\n\n    performanceBufferMock.addPerformanceEntry({\n      entryType: 'visibility-state',\n      name: 'hidden',\n      startTime: performance.now(),\n    } as PerformanceEntry)\n\n    clock.tick(RANDOM_VIEW_START)\n\n    startLoadingTimeTracking(ViewLoadingType.ROUTE_CHANGE, clocksNow())\n\n    emulatePageActivityDuringViewLoading()\n\n    expect(loadingTimeCallback).toHaveBeenCalled()\n  })\n\n  it('should discard loading time if page was hidden during the loading time', () => {\n    if (!supportPerformanceTimingEvent(RumPerformanceEntryType.VISIBILITY_STATE)) {\n      pending('Performance Timing Event is not supported')\n    }\n\n    clock.tick(RANDOM_VIEW_START)\n\n    const viewStart = clocksNow()\n\n    clock.tick(10)\n\n    performanceBufferMock.addPerformanceEntry({\n      entryType: 'visibility-state',\n      name: 'hidden',\n      startTime: performance.now(),\n    } as PerformanceEntry)\n\n    startLoadingTimeTracking(ViewLoadingType.ROUTE_CHANGE, viewStart)\n\n    emulatePageActivityDuringViewLoading()\n\n    expect(loadingTimeCallback).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackLoadingTime.ts",
    "content": "import type { ClocksState, Duration, Observable } from '@datadog/browser-core'\nimport { elapsed } from '@datadog/browser-core'\nimport { waitPageActivityEnd } from '../../waitPageActivityEnd'\nimport type { RumConfiguration } from '../../configuration'\nimport type { LifeCycle } from '../../lifeCycle'\nimport { ViewLoadingType } from '../../../rawRumEvent.types'\nimport type { RumMutationRecord } from '../../../browser/domMutationObservable'\nimport { trackFirstHidden } from './trackFirstHidden'\n\n/**\n * For non-initial views (such as route changes or BFCache restores), the regular load event does not fire\n * In these cases, trackLoadingTime can only emit a loadingTime  if waitPageActivityEnd detects some post-restore activity.\n * If nothing happens after the view starts,no candidate is recorded and loadingTime stays undefined.\n */\n\nexport function trackLoadingTime(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration,\n  loadType: ViewLoadingType,\n  viewStart: ClocksState,\n  callback: (loadingTime: Duration) => void\n) {\n  let isWaitingForLoadEvent = loadType === ViewLoadingType.INITIAL_LOAD\n  let isWaitingForActivityLoadingTime = true\n  const loadingTimeCandidates: Duration[] = []\n  const firstHidden = trackFirstHidden(configuration, viewStart)\n\n  function invokeCallbackIfAllCandidatesAreReceived() {\n    if (!isWaitingForActivityLoadingTime && !isWaitingForLoadEvent && loadingTimeCandidates.length > 0) {\n      const loadingTime = Math.max(...loadingTimeCandidates)\n      // firstHidden is a relative time from time origin, so we use the relative start time of the view to compare with the loading time\n      if (loadingTime < firstHidden.timeStamp - viewStart.relative) {\n        callback(loadingTime as Duration)\n      }\n    }\n  }\n\n  const { stop } = waitPageActivityEnd(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration,\n    (event) => {\n      if (isWaitingForActivityLoadingTime) {\n        isWaitingForActivityLoadingTime = false\n        if (event.hadActivity) {\n          loadingTimeCandidates.push(elapsed(viewStart.timeStamp, event.end))\n        }\n        invokeCallbackIfAllCandidatesAreReceived()\n      }\n    }\n  )\n\n  return {\n    stop: () => {\n      stop()\n      firstHidden.stop()\n    },\n    setLoadEvent: (loadEvent: Duration) => {\n      if (isWaitingForLoadEvent) {\n        isWaitingForLoadEvent = false\n        loadingTimeCandidates.push(loadEvent)\n        invokeCallbackIfAllCandidatesAreReceived()\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackNavigationTimings.spec.ts",
    "content": "import { relativeNow, type Duration, type RelativeTime } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, registerCleanupTask, replaceMockable } from '@datadog/browser-core/test'\nimport { mockDocumentReadyState, mockRumConfiguration } from '../../../../test'\nimport { getNavigationEntry } from '../../../browser/performanceUtils'\nimport type { NavigationTimings, RelevantNavigationTiming } from './trackNavigationTimings'\nimport { trackNavigationTimings } from './trackNavigationTimings'\n\nconst FAKE_NAVIGATION_ENTRY: RelevantNavigationTiming = {\n  domComplete: 456 as RelativeTime,\n  domContentLoadedEventEnd: 345 as RelativeTime,\n  domInteractive: 234 as RelativeTime,\n  loadEventEnd: 567 as RelativeTime,\n  responseStart: 123 as RelativeTime,\n}\n\nconst FAKE_INCOMPLETE_NAVIGATION_ENTRY: RelevantNavigationTiming = {\n  domComplete: 0 as RelativeTime,\n  domContentLoadedEventEnd: 0 as RelativeTime,\n  domInteractive: 0 as RelativeTime,\n  loadEventEnd: 0 as RelativeTime,\n  responseStart: 0 as RelativeTime,\n}\n\ndescribe('trackNavigationTimings', () => {\n  let navigationTimingsCallback: jasmine.Spy<(timings: NavigationTimings) => void>\n  let stop: () => void\n  let clock: Clock\n\n  beforeEach(() => {\n    navigationTimingsCallback = jasmine.createSpy()\n    clock = mockClock()\n\n    registerCleanupTask(() => {\n      stop()\n    })\n  })\n\n  it('notifies navigation timings after the load event', () => {\n    replaceMockable(getNavigationEntry, () => FAKE_NAVIGATION_ENTRY)\n    ;({ stop } = trackNavigationTimings(mockRumConfiguration(), navigationTimingsCallback))\n\n    clock.tick(0)\n\n    expect(navigationTimingsCallback).toHaveBeenCalledOnceWith({\n      firstByte: 123 as Duration,\n      domComplete: 456 as Duration,\n      domContentLoaded: 345 as Duration,\n      domInteractive: 234 as Duration,\n      loadEvent: 567 as Duration,\n    })\n  })\n\n  it('does not report \"firstByte\" if \"responseStart\" is negative', () => {\n    replaceMockable(getNavigationEntry, () => ({\n      ...FAKE_NAVIGATION_ENTRY,\n      responseStart: -1 as RelativeTime,\n    }))\n    ;({ stop } = trackNavigationTimings(mockRumConfiguration(), navigationTimingsCallback))\n\n    clock.tick(0)\n\n    expect(navigationTimingsCallback.calls.mostRecent().args[0].firstByte).toBeUndefined()\n  })\n\n  it('does not report \"firstByte\" if \"responseStart\" is in the future', () => {\n    replaceMockable(getNavigationEntry, () => ({\n      ...FAKE_NAVIGATION_ENTRY,\n      responseStart: (relativeNow() + 1) as RelativeTime,\n    }))\n    ;({ stop } = trackNavigationTimings(mockRumConfiguration(), navigationTimingsCallback))\n\n    clock.tick(0)\n\n    expect(navigationTimingsCallback.calls.mostRecent().args[0].firstByte).toBeUndefined()\n  })\n\n  it('wait for the load event to provide navigation timing', () => {\n    replaceMockable(getNavigationEntry, () => FAKE_NAVIGATION_ENTRY)\n    mockDocumentReadyState()\n    ;({ stop } = trackNavigationTimings(mockRumConfiguration(), navigationTimingsCallback))\n\n    clock.tick(0)\n\n    expect(navigationTimingsCallback).not.toHaveBeenCalled()\n  })\n\n  it('discard incomplete navigation timing', () => {\n    replaceMockable(getNavigationEntry, () => FAKE_INCOMPLETE_NAVIGATION_ENTRY)\n    ;({ stop } = trackNavigationTimings(mockRumConfiguration(), navigationTimingsCallback))\n\n    clock.tick(0)\n\n    expect(navigationTimingsCallback).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackNavigationTimings.ts",
    "content": "import type { Duration, TimeoutId } from '@datadog/browser-core'\nimport { setTimeout, runOnReadyState, clearTimeout, mockable } from '@datadog/browser-core'\nimport type { RumPerformanceNavigationTiming } from '../../../browser/performanceObservable'\nimport { getNavigationEntry, sanitizeFirstByte } from '../../../browser/performanceUtils'\nimport type { RumConfiguration } from '../../configuration'\n\nexport interface NavigationTimings {\n  domComplete: Duration\n  domContentLoaded: Duration\n  domInteractive: Duration\n  loadEvent: Duration\n  firstByte: Duration | undefined\n}\n\n// This is a subset of \"RumPerformanceNavigationTiming\" that only contains the relevant fields for\n// computing navigation timings. This is useful to mock the navigation entry in tests.\nexport type RelevantNavigationTiming = Pick<\n  RumPerformanceNavigationTiming,\n  'domComplete' | 'domContentLoadedEventEnd' | 'domInteractive' | 'loadEventEnd' | 'responseStart'\n>\n\nexport function trackNavigationTimings(\n  configuration: RumConfiguration,\n  callback: (timings: NavigationTimings) => void\n) {\n  return waitAfterLoadEvent(configuration, () => {\n    const entry = mockable(getNavigationEntry)()\n\n    if (!isIncompleteNavigation(entry)) {\n      callback(processNavigationEntry(entry))\n    }\n  })\n}\n\nfunction processNavigationEntry(entry: RelevantNavigationTiming): NavigationTimings {\n  return {\n    domComplete: entry.domComplete,\n    domContentLoaded: entry.domContentLoadedEventEnd,\n    domInteractive: entry.domInteractive,\n    loadEvent: entry.loadEventEnd,\n    firstByte: sanitizeFirstByte(entry),\n  }\n}\n\nfunction isIncompleteNavigation(entry: RelevantNavigationTiming) {\n  return entry.loadEventEnd <= 0\n}\n\nfunction waitAfterLoadEvent(configuration: RumConfiguration, callback: () => void) {\n  let timeoutId: TimeoutId | undefined\n  const { stop: stopOnReadyState } = runOnReadyState(configuration, 'complete', () => {\n    // Invoke the callback a bit after the actual load event, so the \"loadEventEnd\" timing is accurate\n    timeoutId = setTimeout(() => callback())\n  })\n  return {\n    stop: () => {\n      stopOnReadyState()\n      clearTimeout(timeoutId)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackScrollMetrics.spec.ts",
    "content": "import type { RelativeTime, Subscription, TimeStamp } from '@datadog/browser-core'\nimport { DOM_EVENT, Observable } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { createNewEvent, mockClock, registerCleanupTask } from '@datadog/browser-core/test'\nimport { mockRumConfiguration } from '../../../../test'\nimport type { ScrollMetrics, ScrollValues } from './trackScrollMetrics'\nimport { createScrollValuesObservable, trackScrollMetrics } from './trackScrollMetrics'\n\ndescribe('createScrollValuesObserver', () => {\n  const scrollObservable = createScrollValuesObservable(mockRumConfiguration(), 0)\n  let subscription: Subscription\n\n  const newScroll = () => {\n    window.dispatchEvent(createNewEvent(DOM_EVENT.SCROLL))\n  }\n\n  const increaseHeight = () => {\n    const node = document.createElement('div')\n    node.style.height = '2000px'\n    document.body.innerHTML = ''\n    document.body.appendChild(node)\n  }\n\n  beforeEach(() => {\n    registerCleanupTask(() => {\n      subscription.unsubscribe()\n      document.body.innerHTML = ''\n    })\n  })\n\n  it('should produce a value when scrolling', () => {\n    newScroll()\n    subscription = scrollObservable.subscribe(({ scrollDepth }) => {\n      expect(scrollDepth).toBeGreaterThan(0)\n    })\n  })\n\n  it('should produce a value when the page is resized', () => {\n    increaseHeight()\n    subscription = scrollObservable.subscribe(({ scrollHeight }) => {\n      expect(scrollHeight).toBeGreaterThan(600)\n    })\n  })\n})\n\ndescribe('trackScrollMetrics', () => {\n  let clock: Clock\n  let scrollMetricsCallback: jasmine.Spy<(metrics: ScrollMetrics) => void>\n\n  const scrollObservable = new Observable<ScrollValues>()\n\n  beforeEach(() => {\n    scrollMetricsCallback = jasmine.createSpy()\n    clock = mockClock()\n    trackScrollMetrics(\n      mockRumConfiguration(),\n      { relative: 0 as RelativeTime, timeStamp: 0 as TimeStamp },\n      scrollMetricsCallback,\n      scrollObservable\n    )\n  })\n\n  afterEach(() => {\n    document.body.innerHTML = ''\n  })\n\n  const updateScrollValues = (scrollValues: ScrollValues) => {\n    clock.tick(100)\n    scrollObservable.notify(scrollValues)\n  }\n\n  it('should update scroll height and scroll depth', () => {\n    updateScrollValues({ scrollDepth: 700, scrollHeight: 2000, scrollTop: 100 })\n    expect(scrollMetricsCallback).toHaveBeenCalledOnceWith({\n      maxDepth: 700,\n      maxScrollHeight: 2000,\n      maxScrollHeightTime: clock.relative(100),\n      maxDepthScrollTop: 100,\n    })\n  })\n  it('should update time and scroll height only if it has increased', () => {\n    updateScrollValues({ scrollDepth: 700, scrollHeight: 2000, scrollTop: 100 })\n    updateScrollValues({ scrollDepth: 700, scrollHeight: 1900, scrollTop: 100 })\n    expect(scrollMetricsCallback).toHaveBeenCalledOnceWith({\n      maxDepth: 700,\n      maxScrollHeight: 2000,\n      maxScrollHeightTime: clock.relative(100),\n      maxDepthScrollTop: 100,\n    })\n  })\n\n  it('should update max depth only if it has increased', () => {\n    updateScrollValues({ scrollDepth: 700, scrollHeight: 2000, scrollTop: 100 })\n    updateScrollValues({ scrollDepth: 600, scrollHeight: 2000, scrollTop: 0 })\n    expect(scrollMetricsCallback).toHaveBeenCalledOnceWith({\n      maxDepth: 700,\n      maxScrollHeight: 2000,\n      maxScrollHeightTime: clock.relative(100),\n      maxDepthScrollTop: 100,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/view/viewMetrics/trackScrollMetrics.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport {\n  Observable,\n  ONE_SECOND,\n  elapsed,\n  relativeNow,\n  throttle,\n  addEventListener,\n  DOM_EVENT,\n  monitor,\n} from '@datadog/browser-core'\nimport type { RumConfiguration } from '../../configuration'\nimport { getScrollY } from '../../../browser/scroll'\nimport { getViewportDimension } from '../../../browser/viewportObservable'\n\n/** Arbitrary scroll throttle duration */\nexport const THROTTLE_SCROLL_DURATION = ONE_SECOND\n\nexport interface ScrollMetrics {\n  maxDepth: number\n  maxScrollHeight: number\n  maxDepthScrollTop: number\n  maxScrollHeightTime: Duration\n}\n\nexport function trackScrollMetrics(\n  configuration: RumConfiguration,\n  viewStart: ClocksState,\n  callback: (scrollMetrics: ScrollMetrics) => void,\n  scrollValues = createScrollValuesObservable(configuration)\n) {\n  let maxScrollDepth = 0\n  let maxScrollHeight = 0\n  let maxScrollHeightTime = 0 as Duration\n\n  const subscription = scrollValues.subscribe(({ scrollDepth, scrollTop, scrollHeight }) => {\n    let shouldUpdate = false\n\n    if (scrollDepth > maxScrollDepth) {\n      maxScrollDepth = scrollDepth\n      shouldUpdate = true\n    }\n\n    if (scrollHeight > maxScrollHeight) {\n      maxScrollHeight = scrollHeight\n      const now = relativeNow()\n      maxScrollHeightTime = elapsed(viewStart.relative, now)\n      shouldUpdate = true\n    }\n\n    if (shouldUpdate) {\n      callback({\n        maxDepth: Math.min(maxScrollDepth, maxScrollHeight),\n        maxDepthScrollTop: scrollTop,\n        maxScrollHeight,\n        maxScrollHeightTime,\n      })\n    }\n  })\n\n  return {\n    stop: () => subscription.unsubscribe(),\n  }\n}\n\nexport interface ScrollValues {\n  scrollDepth: number\n  scrollTop: number\n  scrollHeight: number\n}\n\nexport function computeScrollValues() {\n  const scrollTop = getScrollY()\n\n  const { height } = getViewportDimension()\n\n  const scrollHeight = Math.round((document.scrollingElement || document.documentElement).scrollHeight)\n\n  const scrollDepth = Math.round(height + scrollTop)\n\n  return {\n    scrollHeight,\n    scrollDepth,\n    scrollTop,\n  }\n}\n\nexport function createScrollValuesObservable(\n  configuration: RumConfiguration,\n  throttleDuration = THROTTLE_SCROLL_DURATION\n): Observable<ScrollValues> {\n  return new Observable<ScrollValues>((observable) => {\n    function notify() {\n      observable.notify(computeScrollValues())\n    }\n\n    if (window.ResizeObserver) {\n      const throttledNotify = throttle(notify, throttleDuration, {\n        leading: false,\n        trailing: true,\n      })\n\n      const observerTarget = document.scrollingElement || document.documentElement\n      const resizeObserver = new ResizeObserver(monitor(throttledNotify.throttled))\n      if (observerTarget) {\n        resizeObserver.observe(observerTarget)\n      }\n      const eventListener = addEventListener(configuration, window, DOM_EVENT.SCROLL, throttledNotify.throttled, {\n        passive: true,\n      })\n\n      return () => {\n        throttledNotify.cancel()\n        resizeObserver.disconnect()\n        eventListener.stop()\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/vital/vitalCollection.spec.ts",
    "content": "import type { Duration } from '@datadog/browser-core'\nimport { mockClock, type Clock } from '@datadog/browser-core/test'\nimport { addExperimentalFeatures, clocksNow, ExperimentalFeature, generateUUID } from '@datadog/browser-core'\nimport { collectAndValidateRawRumEvents, mockPageStateHistory } from '../../../test'\nimport type { RawRumEvent, RawRumVitalEvent } from '../../rawRumEvent.types'\nimport { VitalType, RumEventType } from '../../rawRumEvent.types'\nimport type { RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycle, LifeCycleEventType } from '../lifeCycle'\nimport { startDurationVital, stopDurationVital, startVitalCollection, createCustomVitalsState } from './vitalCollection'\n\nconst pageStateHistory = mockPageStateHistory()\n\nconst vitalsState = createCustomVitalsState()\n\ndescribe('vitalCollection', () => {\n  const lifeCycle = new LifeCycle()\n  let rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>> = []\n  let clock: Clock\n  let vitalCollection: ReturnType<typeof startVitalCollection>\n  let wasInPageStateDuringPeriodSpy: jasmine.Spy<jasmine.Func>\n\n  beforeEach(() => {\n    clock = mockClock()\n    wasInPageStateDuringPeriodSpy = spyOn(pageStateHistory, 'wasInPageStateDuringPeriod')\n    vitalCollection = startVitalCollection(lifeCycle, pageStateHistory, vitalsState)\n\n    rawRumEvents = collectAndValidateRawRumEvents(lifeCycle)\n  })\n\n  describe('custom duration', () => {\n    describe('startDurationVital', () => {\n      it('should create duration vital from a vital reference', () => {\n        const cbSpy = jasmine.createSpy()\n\n        const vitalRef = startDurationVital(vitalsState, 'foo')\n        clock.tick(100)\n        stopDurationVital(cbSpy, vitalsState, vitalRef)\n\n        expect(cbSpy).toHaveBeenCalledOnceWith(\n          jasmine.objectContaining({ id: jasmine.any(String), name: 'foo', duration: 100 })\n        )\n      })\n\n      it('should create duration vital from a vital name', () => {\n        const cbSpy = jasmine.createSpy()\n\n        startDurationVital(vitalsState, 'foo')\n        clock.tick(100)\n        stopDurationVital(cbSpy, vitalsState, 'foo')\n\n        expect(cbSpy).toHaveBeenCalledOnceWith(jasmine.objectContaining({ name: 'foo', duration: 100 }))\n      })\n\n      it('should only create a single duration vital from a vital name', () => {\n        const cbSpy = jasmine.createSpy()\n\n        startDurationVital(vitalsState, 'foo')\n        clock.tick(100)\n        stopDurationVital(cbSpy, vitalsState, 'foo')\n        clock.tick(100)\n        stopDurationVital(cbSpy, vitalsState, 'foo')\n\n        expect(cbSpy).toHaveBeenCalledOnceWith(jasmine.objectContaining({ name: 'foo', duration: 100 }))\n      })\n\n      it('should not create multiple duration vitals by calling \"stopDurationVital\" on the same vital ref multiple times', () => {\n        const cbSpy = jasmine.createSpy()\n\n        const vital = startDurationVital(vitalsState, 'foo')\n        stopDurationVital(cbSpy, vitalsState, vital)\n        stopDurationVital(cbSpy, vitalsState, vital)\n\n        expect(cbSpy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should not create multiple duration vitals by calling \"stopDurationVital\" on the same vital name multiple times', () => {\n        const cbSpy = jasmine.createSpy()\n\n        startDurationVital(vitalsState, 'bar')\n        stopDurationVital(cbSpy, vitalsState, 'bar')\n        stopDurationVital(cbSpy, vitalsState, 'bar')\n\n        expect(cbSpy).toHaveBeenCalledTimes(1)\n      })\n\n      it('should create multiple duration vitals from multiple vital refs', () => {\n        const cbSpy = jasmine.createSpy()\n\n        const vitalRef1 = startDurationVital(vitalsState, 'foo', { description: 'component 1' })\n        clock.tick(100)\n        const vitalRef2 = startDurationVital(vitalsState, 'foo', { description: 'component 2' })\n        clock.tick(100)\n        stopDurationVital(cbSpy, vitalsState, vitalRef2)\n        clock.tick(100)\n        stopDurationVital(cbSpy, vitalsState, vitalRef1)\n\n        expect(cbSpy).toHaveBeenCalledTimes(2)\n        expect(cbSpy.calls.argsFor(0)).toEqual([\n          jasmine.objectContaining({ description: 'component 2', duration: 100 }),\n        ])\n        expect(cbSpy.calls.argsFor(1)).toEqual([\n          jasmine.objectContaining({ description: 'component 1', duration: 300 }),\n        ])\n      })\n\n      it('should merge startDurationVital and stopDurationVital description', () => {\n        const cbSpy = jasmine.createSpy()\n\n        startDurationVital(vitalsState, 'both-undefined')\n        stopDurationVital(cbSpy, vitalsState, 'both-undefined')\n\n        startDurationVital(vitalsState, 'start-defined', { description: 'start-defined' })\n        stopDurationVital(cbSpy, vitalsState, 'start-defined')\n\n        startDurationVital(vitalsState, 'stop-defined')\n        stopDurationVital(cbSpy, vitalsState, 'stop-defined', { description: 'stop-defined' })\n\n        startDurationVital(vitalsState, 'both-defined', { description: 'start-defined' })\n        stopDurationVital(cbSpy, vitalsState, 'both-defined', { description: 'stop-defined' })\n\n        expect(cbSpy).toHaveBeenCalledTimes(4)\n        expect(cbSpy.calls.argsFor(0)).toEqual([jasmine.objectContaining({ description: undefined })])\n        expect(cbSpy.calls.argsFor(1)).toEqual([jasmine.objectContaining({ description: 'start-defined' })])\n        expect(cbSpy.calls.argsFor(2)).toEqual([jasmine.objectContaining({ description: 'stop-defined' })])\n        expect(cbSpy.calls.argsFor(3)).toEqual([jasmine.objectContaining({ description: 'stop-defined' })])\n      })\n\n      it('should merge startDurationVital and stopDurationVital contexts', () => {\n        const cbSpy = jasmine.createSpy()\n\n        const vitalRef1 = startDurationVital(vitalsState, 'both-undefined')\n        stopDurationVital(cbSpy, vitalsState, vitalRef1)\n\n        const vitalRef2 = startDurationVital(vitalsState, 'start-defined', {\n          context: { start: 'defined' },\n        })\n        stopDurationVital(cbSpy, vitalsState, vitalRef2)\n\n        const vitalRef3 = startDurationVital(vitalsState, 'stop-defined', {\n          context: { stop: 'defined' },\n        })\n        stopDurationVital(cbSpy, vitalsState, vitalRef3)\n\n        const vitalRef4 = startDurationVital(vitalsState, 'both-defined', {\n          context: { start: 'defined' },\n        })\n        stopDurationVital(cbSpy, vitalsState, vitalRef4, { context: { stop: 'defined' } })\n\n        const vitalRef5 = startDurationVital(vitalsState, 'stop-precedence', {\n          context: { precedence: 'start' },\n        })\n        stopDurationVital(cbSpy, vitalsState, vitalRef5, { context: { precedence: 'stop' } })\n\n        expect(cbSpy).toHaveBeenCalledTimes(5)\n        expect(cbSpy.calls.argsFor(0)[0].context).toEqual(undefined)\n        expect(cbSpy.calls.argsFor(1)[0].context).toEqual({ start: 'defined' })\n        expect(cbSpy.calls.argsFor(2)[0].context).toEqual({ stop: 'defined' })\n        expect(cbSpy.calls.argsFor(3)[0].context).toEqual({ start: 'defined', stop: 'defined' })\n        expect(cbSpy.calls.argsFor(4)[0].context).toEqual({ precedence: 'stop' })\n      })\n    })\n\n    describe('startVitalCollection', () => {\n      it('should create a vital from start API using name', () => {\n        vitalCollection.startDurationVital('foo', {\n          context: { foo: 'bar' },\n          description: 'baz',\n        })\n\n        clock.tick(100)\n\n        vitalCollection.stopDurationVital('foo')\n\n        expect(rawRumEvents.length).toBe(1)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.duration).toBe(100000000)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.description).toBe('baz')\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).context).toEqual({ foo: 'bar' })\n      })\n\n      it('should create a vital from start API using ref', () => {\n        const vital = vitalCollection.startDurationVital('foo', {\n          context: { foo: 'bar' },\n          description: 'baz',\n        })\n\n        clock.tick(100)\n\n        vitalCollection.stopDurationVital(vital)\n\n        expect(rawRumEvents.length).toBe(1)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.duration).toBe(100000000)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.description).toBe('baz')\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).context).toEqual({ foo: 'bar' })\n      })\n\n      it('should discard a vital for which a frozen state happened', () => {\n        wasInPageStateDuringPeriodSpy.and.returnValue(true)\n\n        vitalCollection.addDurationVital({\n          id: generateUUID(),\n          name: 'foo',\n          type: VitalType.DURATION,\n          startClocks: clocksNow(),\n          duration: 100 as Duration,\n        })\n\n        expect(rawRumEvents.length).toBe(0)\n      })\n\n      it('should collect raw rum event from duration vital', () => {\n        vitalCollection.startDurationVital('foo')\n        vitalCollection.stopDurationVital('foo')\n\n        expect(rawRumEvents[0].startClocks.relative).toEqual(jasmine.any(Number))\n        expect(rawRumEvents[0].rawRumEvent).toEqual({\n          date: jasmine.any(Number),\n          vital: {\n            id: jasmine.any(String),\n            type: VitalType.DURATION,\n            name: 'foo',\n            duration: 0,\n            description: undefined,\n          },\n          context: undefined,\n          type: RumEventType.VITAL,\n        })\n        expect(rawRumEvents[0].domainContext).toEqual({})\n      })\n\n      it('should create vital with handling stack', () => {\n        vitalCollection.startDurationVital('foo', {\n          handlingStack: 'Error\\n    at foo\\n    at bar',\n        })\n        vitalCollection.stopDurationVital('foo')\n\n        expect(rawRumEvents[0].domainContext).toEqual({\n          handlingStack: 'Error\\n    at foo\\n    at bar',\n        })\n      })\n\n      it('should collect raw rum event from operation step vital', () => {\n        addExperimentalFeatures([ExperimentalFeature.FEATURE_OPERATION_VITAL])\n        vitalCollection.addOperationStepVital('foo', 'start')\n\n        expect(rawRumEvents[0].startClocks.relative).toEqual(jasmine.any(Number))\n        expect(rawRumEvents[0].rawRumEvent).toEqual({\n          date: jasmine.any(Number),\n          vital: {\n            id: jasmine.any(String),\n            type: VitalType.OPERATION_STEP,\n            name: 'foo',\n            step_type: 'start',\n            operation_key: undefined,\n            failure_reason: undefined,\n            description: undefined,\n          },\n          context: undefined,\n          type: RumEventType.VITAL,\n        })\n        expect(rawRumEvents[0].domainContext).toEqual({})\n      })\n\n      it('should create operation step vital with handling stack in domainContext', () => {\n        addExperimentalFeatures([ExperimentalFeature.FEATURE_OPERATION_VITAL])\n        vitalCollection.addOperationStepVital('foo', 'start', {\n          handlingStack: 'Error\\n    at foo\\n    at bar',\n        })\n\n        expect(rawRumEvents[0].domainContext).toEqual({\n          handlingStack: 'Error\\n    at foo\\n    at bar',\n        })\n      })\n\n      it('should create a duration vital from add API', () => {\n        vitalCollection.addDurationVital({\n          id: generateUUID(),\n          name: 'foo',\n          type: VitalType.DURATION,\n          startClocks: clocksNow(),\n          duration: 100 as Duration,\n          context: { foo: 'bar' },\n          description: 'baz',\n        })\n\n        expect(rawRumEvents.length).toBe(1)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.duration).toBe(100000000)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.description).toBe('baz')\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).context).toEqual({ foo: 'bar' })\n      })\n\n      it('should create a operation step vital from add API', () => {\n        addExperimentalFeatures([ExperimentalFeature.FEATURE_OPERATION_VITAL])\n        vitalCollection.addOperationStepVital(\n          'foo',\n          'end',\n          {\n            operationKey: '00000000-0000-0000-0000-000000000000',\n            context: { foo: 'bar' },\n            description: 'baz',\n          },\n          'error'\n        )\n\n        expect(rawRumEvents.length).toBe(1)\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.step_type).toBe('end')\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.operation_key).toBe(\n          '00000000-0000-0000-0000-000000000000'\n        )\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.failure_reason).toBe('error')\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).vital.description).toBe('baz')\n        expect((rawRumEvents[0].rawRumEvent as RawRumVitalEvent).context).toEqual({ foo: 'bar' })\n      })\n\n      it('should notify lifecycle with vital started event when starting a duration vital', () => {\n        const subscriberSpy = jasmine.createSpy()\n        lifeCycle.subscribe(LifeCycleEventType.VITAL_STARTED, subscriberSpy)\n\n        vitalCollection.startDurationVital('foo')\n\n        expect(subscriberSpy).toHaveBeenCalledOnceWith(jasmine.objectContaining({ name: 'foo' }))\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/vital/vitalCollection.ts",
    "content": "import type { ClocksState, Duration } from '@datadog/browser-core'\nimport {\n  clocksNow,\n  combine,\n  elapsed,\n  ExperimentalFeature,\n  generateUUID,\n  isExperimentalFeatureEnabled,\n  sanitize,\n  toServerDuration,\n} from '@datadog/browser-core'\nimport type { LifeCycle, RawRumEventCollectedData } from '../lifeCycle'\nimport { LifeCycleEventType } from '../lifeCycle'\nimport type { RawRumVitalEvent } from '../../rawRumEvent.types'\nimport { RumEventType, VitalType } from '../../rawRumEvent.types'\nimport type { PageStateHistory } from '../contexts/pageStateHistory'\nimport { PageState } from '../contexts/pageStateHistory'\n\n/**\n * Vital options\n */\nexport interface VitalOptions {\n  /**\n   * Vital context\n   */\n  context?: any\n\n  /**\n   * Vital description\n   */\n  description?: string\n}\n\n/**\n * Duration vital options\n */\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface DurationVitalOptions extends VitalOptions {}\n\nexport interface FeatureOperationOptions extends VitalOptions {\n  operationKey?: string\n}\n\nexport type FailureReason = 'error' | 'abandoned' | 'other'\n\n/**\n * Add duration vital options\n */\nexport interface AddDurationVitalOptions extends DurationVitalOptions {\n  /**\n   * Vital start time, expects a UNIX timestamp in milliseconds (the number of milliseconds since January 1, 1970)\n   */\n  startTime: number\n\n  /**\n   * Vital duration, expects a duration in milliseconds\n   */\n  duration: number\n}\n\nexport interface DurationVitalReference {\n  __dd_vital_reference: true\n}\n\nexport interface DurationVitalStart extends DurationVitalOptions {\n  id: string\n  name: string\n  startClocks: ClocksState\n  handlingStack?: string\n}\n\ninterface BaseVital extends VitalOptions {\n  name: string\n  startClocks: ClocksState\n  handlingStack?: string\n}\nexport interface DurationVital extends BaseVital {\n  id: string\n  type: typeof VitalType.DURATION\n  duration: Duration\n}\n\nexport interface OperationStepVital extends BaseVital {\n  type: typeof VitalType.OPERATION_STEP\n  stepType: 'start' | 'end'\n  operationKey?: string\n  failureReason?: string\n}\n\nexport interface CustomVitalsState {\n  vitalsByName: Map<string, DurationVitalStart>\n  vitalsByReference: WeakMap<DurationVitalReference, DurationVitalStart>\n}\n\nexport function createCustomVitalsState() {\n  const vitalsByName = new Map<string, DurationVitalStart>()\n  const vitalsByReference = new WeakMap<DurationVitalReference, DurationVitalStart>()\n  return { vitalsByName, vitalsByReference }\n}\n\nexport function startVitalCollection(\n  lifeCycle: LifeCycle,\n  pageStateHistory: PageStateHistory,\n  customVitalsState: CustomVitalsState\n) {\n  function isValid(vital: DurationVital) {\n    return !pageStateHistory.wasInPageStateDuringPeriod(PageState.FROZEN, vital.startClocks.relative, vital.duration)\n  }\n\n  function addDurationVital(vital: DurationVital) {\n    if (isValid(vital)) {\n      lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processVital(vital))\n    }\n  }\n\n  function addOperationStepVital(\n    name: string,\n    stepType: 'start' | 'end',\n    options?: FeatureOperationOptions & { handlingStack?: string },\n    failureReason?: FailureReason\n  ) {\n    if (!isExperimentalFeatureEnabled(ExperimentalFeature.FEATURE_OPERATION_VITAL)) {\n      return\n    }\n\n    const { operationKey, context, description, handlingStack } = options || {}\n\n    const vital: OperationStepVital = {\n      name,\n      type: VitalType.OPERATION_STEP,\n      operationKey,\n      failureReason,\n      stepType,\n      startClocks: clocksNow(),\n      context: sanitize(context),\n      description,\n      handlingStack,\n    }\n    lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processVital(vital))\n  }\n\n  return {\n    addOperationStepVital,\n    addDurationVital,\n    startDurationVital: (name: string, options: DurationVitalOptions & { handlingStack?: string } = {}) => {\n      const ref = startDurationVital(customVitalsState, name, options)\n      const vitalState = customVitalsState.vitalsByReference.get(ref)\n      if (vitalState) {\n        lifeCycle.notify(LifeCycleEventType.VITAL_STARTED, vitalState)\n      }\n      return ref\n    },\n    stopDurationVital: (nameOrRef: string | DurationVitalReference, options: DurationVitalOptions = {}) => {\n      stopDurationVital(addDurationVital, customVitalsState, nameOrRef, options)\n    },\n  }\n}\n\nexport function startDurationVital(\n  { vitalsByName, vitalsByReference }: CustomVitalsState,\n  name: string,\n  options: DurationVitalOptions & { handlingStack?: string } = {}\n) {\n  const vital = {\n    id: generateUUID(),\n    name,\n    startClocks: clocksNow(),\n    ...options,\n  }\n\n  // To avoid leaking implementation details of the vital, we return a reference to it.\n  const reference: DurationVitalReference = { __dd_vital_reference: true }\n\n  vitalsByName.set(name, vital)\n\n  // To avoid memory leaks caused by the creation of numerous references (e.g., from improper useEffect implementations), we use a WeakMap.\n  vitalsByReference.set(reference, vital)\n\n  return reference\n}\n\nexport function stopDurationVital(\n  stopCallback: (vital: DurationVital) => void,\n  { vitalsByName, vitalsByReference }: CustomVitalsState,\n  nameOrRef: string | DurationVitalReference,\n  options: DurationVitalOptions = {}\n) {\n  const vitalStart = typeof nameOrRef === 'string' ? vitalsByName.get(nameOrRef) : vitalsByReference.get(nameOrRef)\n\n  if (!vitalStart) {\n    return\n  }\n\n  stopCallback(buildDurationVital(vitalStart, vitalStart.startClocks, options, clocksNow()))\n\n  if (typeof nameOrRef === 'string') {\n    vitalsByName.delete(nameOrRef)\n  } else {\n    vitalsByReference.delete(nameOrRef)\n  }\n}\n\nfunction buildDurationVital(\n  vitalStart: DurationVitalStart,\n  startClocks: ClocksState,\n  stopOptions: DurationVitalOptions,\n  stopClocks: ClocksState\n): DurationVital {\n  return {\n    id: vitalStart.id,\n    name: vitalStart.name,\n    type: VitalType.DURATION,\n    startClocks,\n    duration: elapsed(startClocks.timeStamp, stopClocks.timeStamp),\n    context: combine(vitalStart.context, stopOptions.context),\n    description: stopOptions.description ?? vitalStart.description,\n    handlingStack: vitalStart.handlingStack,\n  }\n}\n\nfunction processVital(vital: DurationVital | OperationStepVital): RawRumEventCollectedData<RawRumVitalEvent> {\n  const { startClocks, type, name, description, context, handlingStack } = vital\n  const vitalId = vital.type === VitalType.DURATION ? vital.id : undefined\n\n  const vitalData = {\n    id: vitalId ?? generateUUID(),\n    type,\n    name,\n    description,\n    ...(type === VitalType.DURATION\n      ? { duration: toServerDuration(vital.duration) }\n      : {\n          step_type: vital.stepType,\n          operation_key: vital.operationKey,\n          failure_reason: vital.failureReason,\n        }),\n  }\n\n  return {\n    rawRumEvent: {\n      date: startClocks.timeStamp,\n      vital: vitalData,\n      type: RumEventType.VITAL,\n      context,\n    },\n    startClocks,\n    duration: type === VitalType.DURATION ? vital.duration : undefined,\n    domainContext: handlingStack ? { handlingStack } : {},\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/src/domain/waitPageActivityEnd.spec.ts",
    "content": "import type { Subscription } from '@datadog/browser-core'\nimport { Observable, ONE_SECOND } from '@datadog/browser-core'\nimport type { Clock } from '@datadog/browser-core/test'\nimport { mockClock, replaceMockable } from '@datadog/browser-core/test'\nimport {\n  appendElement,\n  createMutationRecord,\n  createPerformanceEntry,\n  mockPerformanceObserver,\n  mockRumConfiguration,\n} from '../../test'\nimport type { RumPerformanceEntry } from '../browser/performanceObservable'\nimport { RumPerformanceEntryType } from '../browser/performanceObservable'\nimport type { RumMutationRecord } from '../browser/domMutationObservable'\nimport { LifeCycle, LifeCycleEventType } from './lifeCycle'\nimport type { RequestCompleteEvent, RequestStartEvent } from './requestCollection'\nimport type { PageActivityEvent, PageActivityEndEvent } from './waitPageActivityEnd'\nimport {\n  PAGE_ACTIVITY_END_DELAY,\n  PAGE_ACTIVITY_VALIDATION_DELAY,\n  waitPageActivityEnd,\n  createPageActivityObservable,\n  EXCLUDED_MUTATIONS_ATTRIBUTE,\n} from './waitPageActivityEnd'\nimport type { RumConfiguration } from './configuration'\n\n// Used to wait some time after the creation of an action\nconst BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY = PAGE_ACTIVITY_VALIDATION_DELAY * 0.8\n// Used to wait some time before the (potential) end of an action\nconst BEFORE_PAGE_ACTIVITY_END_DELAY = PAGE_ACTIVITY_END_DELAY * 0.8\n// Arbitrary maximum duration to be used to test page activities max duration\nconst MAX_DURATION = 10 * ONE_SECOND\n// A long delay used to wait after any action is finished.\nconst EXPIRE_DELAY = MAX_DURATION * 10\n\nconst FAKE_URL = 'https://example.com'\nconst EXCLUDED_FAKE_URL = 'https://example.com/excluded'\n\nfunction eventsCollector<T>() {\n  const events: T[] = []\n  beforeEach(() => {\n    events.length = 0\n  })\n  return {\n    events,\n    pushEvent: (event: T) => {\n      events.push(event)\n    },\n  }\n}\n\nconst RUM_CONFIGURATION = mockRumConfiguration()\n\ndescribe('createPageActivityObservable', () => {\n  const { events, pushEvent } = eventsCollector<PageActivityEvent>()\n\n  const lifeCycle = new LifeCycle()\n  const domMutationObservable = new Observable<RumMutationRecord[]>()\n  const windowOpenObservable = new Observable<void>()\n  let pageActivitySubscription: Subscription\n  let notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => void\n\n  function startListeningToPageActivities(\n    extraConfiguration: Partial<RumConfiguration> = { excludedActivityUrls: [EXCLUDED_FAKE_URL] }\n  ) {\n    const pageActivityObservable = createPageActivityObservable(\n      lifeCycle,\n      domMutationObservable,\n      windowOpenObservable,\n      {\n        ...RUM_CONFIGURATION,\n        ...extraConfiguration,\n      }\n    )\n    pageActivitySubscription = pageActivityObservable.subscribe(pushEvent)\n  }\n\n  beforeEach(() => {\n    ;({ notifyPerformanceEntries } = mockPerformanceObserver())\n  })\n\n  afterEach(() => {\n    pageActivitySubscription.unsubscribe()\n  })\n\n  describe('dom mutation', () => {\n    it('emits an activity event on dom mutation', () => {\n      startListeningToPageActivities()\n      domMutationObservable.notify([createMutationRecord()])\n      expect(events).toEqual([{ isBusy: false }])\n    })\n\n    describe('dom mutation ignoring', () => {\n      it('does not collect DOM mutation when an element is added and the parent is ignored', () => {\n        startListeningToPageActivities()\n        const target = appendElement(`<div ${EXCLUDED_MUTATIONS_ATTRIBUTE}><button /></div>`)\n\n        domMutationObservable.notify([createMutationRecord('childList', { target })])\n        expect(events).toEqual([])\n      })\n\n      it('does not collect DOM mutation in a deeply nested child of an ignored element', () => {\n        startListeningToPageActivities()\n        const target = appendElement(\n          `<div ${EXCLUDED_MUTATIONS_ATTRIBUTE}><div><div><button target /></div></div></div>`\n        )\n\n        domMutationObservable.notify([createMutationRecord('childList', { target })])\n        expect(events).toEqual([])\n      })\n\n      it('does not collect DOM mutation when a text node is added and the parent is ignored', () => {\n        startListeningToPageActivities()\n        const container = appendElement(`<div ${EXCLUDED_MUTATIONS_ATTRIBUTE}>foo</div>`)\n        const target = container.childNodes[0] as Text\n\n        domMutationObservable.notify([createMutationRecord('characterData', { target })])\n        expect(events).toEqual([])\n      })\n\n      it('does not collect DOM mutation on attribute creation of ignored element', () => {\n        startListeningToPageActivities()\n        const target = appendElement(`<div ${EXCLUDED_MUTATIONS_ATTRIBUTE}></div>`)\n\n        domMutationObservable.notify([createMutationRecord('attributes', { target })])\n        expect(events).toEqual([])\n      })\n    })\n  })\n\n  it('emits an activity event on resource collected', () => {\n    startListeningToPageActivities()\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.RESOURCE)])\n\n    expect(events).toEqual([{ isBusy: false }])\n  })\n\n  it('does not emit an activity event when a navigation occurs', () => {\n    startListeningToPageActivities()\n\n    notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.NAVIGATION)])\n\n    expect(events).toEqual([])\n  })\n\n  it('emits an activity event when `window.open` is used', () => {\n    startListeningToPageActivities()\n    windowOpenObservable.notify()\n    expect(events).toEqual([{ isBusy: false }])\n  })\n\n  it('stops emitting activities after calling stop()', () => {\n    startListeningToPageActivities()\n    domMutationObservable.notify([createMutationRecord()])\n    expect(events).toEqual([{ isBusy: false }])\n\n    pageActivitySubscription.unsubscribe()\n\n    domMutationObservable.notify([createMutationRecord()])\n    domMutationObservable.notify([createMutationRecord()])\n\n    expect(events).toEqual([{ isBusy: false }])\n  })\n\n  describe('programmatic requests', () => {\n    it('emits an activity event when a request starts', () => {\n      startListeningToPageActivities()\n      lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10))\n      expect(events).toEqual([{ isBusy: true }])\n    })\n\n    it('emits an activity event when a request completes', () => {\n      startListeningToPageActivities()\n      lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10))\n      lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10))\n      expect(events).toEqual([{ isBusy: true }, { isBusy: false }])\n    })\n\n    it('ignores requests that has started before', () => {\n      startListeningToPageActivities()\n      lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10))\n      expect(events).toEqual([])\n    })\n\n    it('keeps emitting busy events while all requests are not completed', () => {\n      startListeningToPageActivities()\n      lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10))\n      lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(11))\n      lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(9))\n      lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(11))\n      lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10))\n      expect(events).toEqual([{ isBusy: true }, { isBusy: true }, { isBusy: true }, { isBusy: false }])\n    })\n\n    describe('excludedActivityUrls', () => {\n      it('ignores resources that should be excluded by configuration', () => {\n        startListeningToPageActivities({\n          excludedActivityUrls: [\n            /^https?:\\/\\/qux\\.com.*/,\n            'http://bar.com',\n            (url: string) => url === 'http://dynamic.com',\n          ],\n        })\n\n        notifyPerformanceEntries([\n          createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: 'http://qux.com' }),\n          createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: 'http://bar.com' }),\n          createPerformanceEntry(RumPerformanceEntryType.RESOURCE, { name: 'http://dynamic.com' }),\n        ])\n\n        expect(events).toEqual([])\n      })\n\n      it('ignores requests that should be excluded by configuration', () => {\n        startListeningToPageActivities()\n        lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10, EXCLUDED_FAKE_URL))\n        lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10, EXCLUDED_FAKE_URL))\n        expect(events).toEqual([])\n      })\n\n      it(\"ignored requests don't interfere with pending requests count\", () => {\n        startListeningToPageActivities()\n        lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(9))\n        lifeCycle.notify(LifeCycleEventType.REQUEST_STARTED, makeFakeRequestStartEvent(10, EXCLUDED_FAKE_URL))\n        lifeCycle.notify(LifeCycleEventType.REQUEST_COMPLETED, makeFakeRequestCompleteEvent(10, EXCLUDED_FAKE_URL))\n        expect(events).toEqual([{ isBusy: true }])\n      })\n    })\n\n    function makeFakeRequestCompleteEvent(requestIndex: number, url = FAKE_URL) {\n      return { requestIndex, url } as RequestCompleteEvent\n    }\n    function makeFakeRequestStartEvent(requestIndex: number, url = FAKE_URL): RequestStartEvent {\n      return { requestIndex, url }\n    }\n  })\n})\n\ndescribe('waitPageActivityEnd', () => {\n  let clock: Clock\n  let idlPageActivityCallbackSpy: jasmine.Spy<(event: PageActivityEndEvent) => void>\n  let activityObservable: Observable<PageActivityEvent>\n\n  beforeEach(() => {\n    idlPageActivityCallbackSpy = jasmine.createSpy()\n    clock = mockClock()\n    activityObservable = new Observable<PageActivityEvent>()\n    replaceMockable(createPageActivityObservable, () => activityObservable)\n  })\n\n  it('should notify the callback after `EXPIRE_DELAY` when there is no activity', () => {\n    waitPageActivityEnd(\n      new LifeCycle(),\n      new Observable(),\n      new Observable(),\n      RUM_CONFIGURATION,\n      idlPageActivityCallbackSpy\n    )\n\n    clock.tick(EXPIRE_DELAY)\n\n    expect(idlPageActivityCallbackSpy).toHaveBeenCalledOnceWith({\n      hadActivity: false,\n    })\n  })\n\n  it('should notify the callback with the last activity timestamp', () => {\n    waitPageActivityEnd(\n      new LifeCycle(),\n      new Observable(),\n      new Observable(),\n      RUM_CONFIGURATION,\n      idlPageActivityCallbackSpy\n    )\n\n    clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n    activityObservable.notify({ isBusy: false })\n\n    clock.tick(EXPIRE_DELAY)\n\n    expect(idlPageActivityCallbackSpy).toHaveBeenCalledOnceWith({\n      hadActivity: true,\n      end: clock.timeStamp(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY),\n    })\n  })\n\n  describe('extend with activities', () => {\n    it('is extended while there is page activities', () => {\n      // Extend the action 10 times\n      const extendCount = 10\n\n      waitPageActivityEnd(\n        new LifeCycle(),\n        new Observable(),\n        new Observable(),\n        RUM_CONFIGURATION,\n        idlPageActivityCallbackSpy\n      )\n\n      for (let i = 0; i < extendCount; i += 1) {\n        clock.tick(BEFORE_PAGE_ACTIVITY_END_DELAY)\n        activityObservable.notify({ isBusy: false })\n      }\n\n      clock.tick(EXPIRE_DELAY)\n\n      expect(idlPageActivityCallbackSpy).toHaveBeenCalledOnceWith({\n        hadActivity: true,\n        end: clock.timeStamp(extendCount * BEFORE_PAGE_ACTIVITY_END_DELAY),\n      })\n    })\n\n    it('expires after a maximum duration', () => {\n      let stop = false\n\n      // Extend the action until it's more than MAX_DURATION\n      const extendCount = Math.ceil(MAX_DURATION / BEFORE_PAGE_ACTIVITY_END_DELAY + 1)\n\n      idlPageActivityCallbackSpy.and.callFake(() => {\n        stop = true\n      })\n      waitPageActivityEnd(\n        new LifeCycle(),\n        new Observable(),\n        new Observable(),\n        RUM_CONFIGURATION,\n        idlPageActivityCallbackSpy,\n        MAX_DURATION\n      )\n\n      for (let i = 0; i < extendCount && !stop; i += 1) {\n        clock.tick(BEFORE_PAGE_ACTIVITY_END_DELAY)\n        activityObservable.notify({ isBusy: false })\n      }\n\n      clock.tick(EXPIRE_DELAY)\n\n      expect(idlPageActivityCallbackSpy).toHaveBeenCalledOnceWith({\n        hadActivity: true,\n        end: clock.timeStamp(MAX_DURATION),\n      })\n    })\n  })\n\n  describe('busy activities', () => {\n    it('is extended while the page is busy', () => {\n      waitPageActivityEnd(\n        new LifeCycle(),\n        new Observable(),\n        new Observable(),\n        RUM_CONFIGURATION,\n        idlPageActivityCallbackSpy\n      )\n\n      clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n      activityObservable.notify({ isBusy: true })\n\n      clock.tick(PAGE_ACTIVITY_END_DELAY * 2)\n      activityObservable.notify({ isBusy: false })\n\n      clock.tick(EXPIRE_DELAY)\n\n      expect(idlPageActivityCallbackSpy).toHaveBeenCalledOnceWith({\n        hadActivity: true,\n        end: clock.timeStamp(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY + PAGE_ACTIVITY_END_DELAY * 2),\n      })\n    })\n\n    it('expires is the page is busy for too long', () => {\n      waitPageActivityEnd(\n        new LifeCycle(),\n        new Observable(),\n        new Observable(),\n        RUM_CONFIGURATION,\n        idlPageActivityCallbackSpy,\n        MAX_DURATION\n      )\n\n      clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY)\n      activityObservable.notify({ isBusy: true })\n\n      clock.tick(EXPIRE_DELAY)\n\n      expect(idlPageActivityCallbackSpy).toHaveBeenCalledOnceWith({\n        hadActivity: true,\n        end: clock.timeStamp(MAX_DURATION),\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/domain/waitPageActivityEnd.ts",
    "content": "import type { Subscription, TimeoutId, TimeStamp } from '@datadog/browser-core'\nimport { matchList, monitor, Observable, timeStampNow, setTimeout, clearTimeout, mockable } from '@datadog/browser-core'\nimport { createPerformanceObservable, RumPerformanceEntryType } from '../browser/performanceObservable'\nimport type { RumMutationRecord } from '../browser/domMutationObservable'\nimport { isElementNode } from '../browser/htmlDomUtils'\nimport type { RumConfiguration } from './configuration'\nimport type { LifeCycle } from './lifeCycle'\nimport { LifeCycleEventType } from './lifeCycle'\n\n// Delay to wait for a page activity to validate the tracking process\nexport const PAGE_ACTIVITY_VALIDATION_DELAY = 100\n// Delay to wait after a page activity to end the tracking process\nexport const PAGE_ACTIVITY_END_DELAY = 100\n\nexport const EXCLUDED_MUTATIONS_ATTRIBUTE = 'data-dd-excluded-activity-mutations'\n\nexport interface PageActivityEvent {\n  isBusy: boolean\n}\n\nexport type PageActivityEndEvent = { hadActivity: true; end: TimeStamp } | { hadActivity: false }\n\n/**\n * Wait for the page activity end\n *\n * Detection lifecycle:\n * ```\n *                        Wait page activity end\n *              .-------------------'--------------------.\n *              v                                        v\n *     [Wait for a page activity ]          [Wait for a maximum duration]\n *     [timeout: VALIDATION_DELAY]          [  timeout: maxDuration     ]\n *          /                  \\                           |\n *         v                    v                          |\n *  [No page activity]   [Page activity]                   |\n *         |                   |,----------------------.   |\n *         v                   v                       |   |\n *     (Discard)     [Wait for a page activity]        |   |\n *                   [   timeout: END_DELAY   ]        |   |\n *                       /                \\            |   |\n *                      v                  v           |   |\n *             [No page activity]    [Page activity]   |   |\n *                      |                 |            |   |\n *                      |                 '------------'   |\n *                      '-----------. ,--------------------'\n *                                   v\n *                                 (End)\n * ```\n *\n * Note: by assuming that maxDuration is greater than VALIDATION_DELAY, we are sure that if the\n * process is still alive after maxDuration, it has been validated.\n */\nexport function waitPageActivityEnd(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration,\n  pageActivityEndCallback: (event: PageActivityEndEvent) => void,\n  maxDuration?: number\n) {\n  const pageActivityObservable = mockable(createPageActivityObservable)(\n    lifeCycle,\n    domMutationObservable,\n    windowOpenObservable,\n    configuration\n  )\n\n  let pageActivityEndTimeoutId: TimeoutId\n  let hasCompleted = false\n\n  const validationTimeoutId = setTimeout(\n    monitor(() => complete({ hadActivity: false })),\n    PAGE_ACTIVITY_VALIDATION_DELAY\n  )\n  const maxDurationTimeoutId =\n    maxDuration !== undefined\n      ? setTimeout(\n          monitor(() => complete({ hadActivity: true, end: timeStampNow() })),\n          maxDuration\n        )\n      : undefined\n\n  const pageActivitySubscription = pageActivityObservable.subscribe(({ isBusy }) => {\n    clearTimeout(validationTimeoutId)\n    clearTimeout(pageActivityEndTimeoutId)\n    const lastChangeTime = timeStampNow()\n    if (!isBusy) {\n      pageActivityEndTimeoutId = setTimeout(\n        monitor(() => complete({ hadActivity: true, end: lastChangeTime })),\n        PAGE_ACTIVITY_END_DELAY\n      )\n    }\n  })\n\n  const stop = () => {\n    hasCompleted = true\n    clearTimeout(validationTimeoutId)\n    clearTimeout(pageActivityEndTimeoutId)\n    clearTimeout(maxDurationTimeoutId)\n    pageActivitySubscription.unsubscribe()\n  }\n\n  function complete(event: PageActivityEndEvent) {\n    if (hasCompleted) {\n      return\n    }\n    stop()\n    pageActivityEndCallback(event)\n  }\n  return { stop }\n}\n\nexport function createPageActivityObservable(\n  lifeCycle: LifeCycle,\n  domMutationObservable: Observable<RumMutationRecord[]>,\n  windowOpenObservable: Observable<void>,\n  configuration: RumConfiguration\n): Observable<PageActivityEvent> {\n  return new Observable<PageActivityEvent>((observable) => {\n    const subscriptions: Subscription[] = []\n    let firstRequestIndex: undefined | number\n    let pendingRequestsCount = 0\n\n    subscriptions.push(\n      domMutationObservable.subscribe((mutations) => {\n        if (!mutations.every(isExcludedMutation)) {\n          notifyPageActivity()\n        }\n      }),\n      windowOpenObservable.subscribe(notifyPageActivity),\n      createPerformanceObservable(configuration, { type: RumPerformanceEntryType.RESOURCE }).subscribe((entries) => {\n        if (entries.some((entry) => !isExcludedUrl(configuration, entry.name))) {\n          notifyPageActivity()\n        }\n      }),\n      lifeCycle.subscribe(LifeCycleEventType.REQUEST_STARTED, (startEvent) => {\n        if (isExcludedUrl(configuration, startEvent.url)) {\n          return\n        }\n        if (firstRequestIndex === undefined) {\n          firstRequestIndex = startEvent.requestIndex\n        }\n        pendingRequestsCount += 1\n        notifyPageActivity()\n      }),\n      lifeCycle.subscribe(LifeCycleEventType.REQUEST_COMPLETED, (request) => {\n        if (\n          isExcludedUrl(configuration, request.url) ||\n          firstRequestIndex === undefined ||\n          // If the request started before the tracking start, ignore it\n          request.requestIndex < firstRequestIndex\n        ) {\n          return\n        }\n        pendingRequestsCount -= 1\n        notifyPageActivity()\n      })\n    )\n\n    return () => {\n      subscriptions.forEach((s) => s.unsubscribe())\n    }\n\n    function notifyPageActivity() {\n      observable.notify({ isBusy: pendingRequestsCount > 0 })\n    }\n  })\n}\n\nfunction isExcludedUrl(configuration: RumConfiguration, requestUrl: string): boolean {\n  return matchList(configuration.excludedActivityUrls, requestUrl)\n}\n\nfunction isExcludedMutation(mutation: RumMutationRecord): boolean {\n  const targetElement = mutation.type === 'characterData' ? mutation.target.parentElement : mutation.target\n\n  return Boolean(\n    targetElement &&\n    isElementNode(targetElement) &&\n    targetElement.matches(`[${EXCLUDED_MUTATIONS_ATTRIBUTE}], [${EXCLUDED_MUTATIONS_ATTRIBUTE}] *`)\n  )\n}\n"
  },
  {
    "path": "packages/rum-core/src/domainContext.types.ts",
    "content": "/**\n * Keep these types in a separate file in order to reference it from the official doc\n */\n\nimport type { RumEventType } from './rawRumEvent.types'\n\nexport type RumEventDomainContext<T extends RumEventType = any> = T extends typeof RumEventType.VIEW\n  ? RumViewEventDomainContext\n  : T extends typeof RumEventType.ACTION\n    ? RumActionEventDomainContext\n    : T extends typeof RumEventType.RESOURCE\n      ?\n          | RumFetchResourceEventDomainContext\n          | RumXhrResourceEventDomainContext\n          | RumOtherResourceEventDomainContext\n          | RumManualResourceEventDomainContext\n      : T extends typeof RumEventType.ERROR\n        ? RumErrorEventDomainContext\n        : T extends typeof RumEventType.LONG_TASK\n          ? RumLongTaskEventDomainContext\n          : T extends typeof RumEventType.VITAL\n            ? RumVitalEventDomainContext\n            : never\n\nexport interface RumViewEventDomainContext {\n  location: Readonly<Location>\n  handlingStack?: string\n}\n\nexport interface RumActionEventDomainContext {\n  events?: Event[]\n  handlingStack?: string\n}\n\nexport interface RumFetchResourceEventDomainContext {\n  requestInit: RequestInit | undefined\n  requestInput: RequestInfo\n  response: Response | undefined\n  error: Error | undefined\n  performanceEntry: PerformanceEntry | undefined\n  isAborted: boolean\n  handlingStack: string | undefined\n}\n\nexport interface RumXhrResourceEventDomainContext {\n  xhr: XMLHttpRequest\n  performanceEntry: PerformanceEntry | undefined\n  isAborted: boolean\n  handlingStack: string | undefined\n}\n\nexport interface RumOtherResourceEventDomainContext {\n  performanceEntry: PerformanceEntry\n}\n\nexport interface RumManualResourceEventDomainContext {\n  /**\n   * Manual resources created via startResource/stopResource do not have\n   * a performance entry or request/response objects.\n   */\n  isManual: true\n}\n\nexport interface RumErrorEventDomainContext {\n  error: unknown\n  handlingStack?: string\n}\n\nexport interface RumLongTaskEventDomainContext {\n  performanceEntry: PerformanceEntry\n}\n\nexport interface RumVitalEventDomainContext {\n  handlingStack?: string\n}\n"
  },
  {
    "path": "packages/rum-core/src/index.ts",
    "content": "export type { RumPublicApi, RecorderApi, ProfilerApi, StartRecordingOptions, Strategy } from './boot/rumPublicApi'\nexport { makeRumPublicApi } from './boot/rumPublicApi'\nexport type { StartRum, StartRumResult } from './boot/startRum'\nexport type {\n  RumEvent,\n  RumActionEvent,\n  CommonProperties,\n  RumErrorEvent,\n  RumViewEvent,\n  RumResourceEvent,\n  RumLongTaskEvent,\n  RumVitalEvent,\n  ProfilingInternalContextSchema,\n} from './rumEvent.types'\nexport type {\n  RumLongTaskEventDomainContext,\n  RumErrorEventDomainContext,\n  RumOtherResourceEventDomainContext,\n  RumManualResourceEventDomainContext,\n  RumXhrResourceEventDomainContext,\n  RumFetchResourceEventDomainContext,\n  RumActionEventDomainContext,\n  RumViewEventDomainContext,\n  RumEventDomainContext,\n  RumVitalEventDomainContext,\n} from './domainContext.types'\nexport type { ReplayStats, RawRumActionEvent, RawRumEvent } from './rawRumEvent.types'\nexport { ActionType, RumEventType, FrustrationType, RumLongTaskEntryType } from './rawRumEvent.types'\nexport { startRum } from './boot/startRum'\nexport type { RawRumEventCollectedData } from './domain/lifeCycle'\nexport { LifeCycle, LifeCycleEventType } from './domain/lifeCycle'\nexport type { ViewCreatedEvent, ViewOptions } from './domain/view/trackViews'\nexport type { ViewHistoryEntry, ViewHistory } from './domain/contexts/viewHistory'\nexport { startViewHistory } from './domain/contexts/viewHistory'\nexport type { RumSessionManager, RumSession } from './domain/rumSessionManager'\nexport { getMutationObserverConstructor } from './browser/domMutationObservable'\nexport type {\n  RumMutationRecord,\n  RumAttributesMutationRecord,\n  RumChildListMutationRecord,\n  RumCharacterDataMutationRecord,\n} from './browser/domMutationObservable'\nexport type { ViewportDimension } from './browser/viewportObservable'\nexport { initViewportObservable, getViewportDimension } from './browser/viewportObservable'\nexport { getScrollX, getScrollY } from './browser/scroll'\nexport type {\n  RumInitConfiguration,\n  RumConfiguration,\n  RumBeforeSend,\n  FeatureFlagsForEvents,\n  RemoteConfiguration,\n  MatchHeader,\n} from './domain/configuration'\nexport { DEFAULT_TRACKED_RESOURCE_HEADERS } from './domain/configuration'\nexport { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/action/actionNameConstants'\nexport { STABLE_ATTRIBUTES } from './domain/getSelectorFromElement'\nexport * from './browser/htmlDomUtils'\nexport { getSessionReplayUrl } from './domain/getSessionReplayUrl'\nexport { sanitizeIfLongDataUrl } from './domain/resource/resourceUtils'\nexport * from './domain/privacy'\nexport * from './domain/privacyConstants'\nexport { SessionReplayState } from './domain/rumSessionManager'\nexport type { RumPlugin, OnRumStartOptions } from './domain/plugins'\nexport type { MouseEventOnElement } from './domain/action/listenActionEvents'\nexport { supportPerformanceTimingEvent } from './browser/performanceObservable'\nexport { RumPerformanceEntryType } from './browser/performanceObservable'\nexport type { AllowedRawRumEvent } from './domain/event/eventCollection'\nexport type {\n  DurationVitalReference,\n  DurationVitalStart,\n  AddDurationVitalOptions,\n  DurationVitalOptions,\n} from './domain/vital/vitalCollection'\nexport type { Hooks, DefaultRumEventAttributes, DefaultTelemetryEventAttributes } from './domain/hooks'\nexport { createHooks } from './domain/hooks'\nexport { isSampled } from './domain/sampler/sampler'\nexport type { TracingOption, PropagatorType } from './domain/tracing/tracer.types'\nexport type { TransportPayload } from './transport/formDataTransport'\nexport { createFormDataTransport } from './transport/formDataTransport'\n"
  },
  {
    "path": "packages/rum-core/src/rawRumEvent.types.ts",
    "content": "import type {\n  Duration,\n  ErrorSource,\n  ErrorHandling,\n  ResourceType,\n  ServerDuration,\n  TimeStamp,\n  RawErrorCause,\n  DefaultPrivacyLevel,\n  Csp,\n  Context,\n} from '@datadog/browser-core'\nimport type { GraphQlMetadata } from './domain/resource/graphql'\nimport type { PageState } from './domain/contexts/pageStateHistory'\nimport type {\n  RumActionEvent,\n  RumErrorEvent,\n  RumLongTaskEvent,\n  RumResourceEvent,\n  RumViewEvent,\n  RumVitalEvent,\n} from './rumEvent.types'\n\nexport const RumEventType = {\n  ACTION: 'action',\n  ERROR: 'error',\n  LONG_TASK: 'long_task',\n  VIEW: 'view',\n  RESOURCE: 'resource',\n  VITAL: 'vital',\n} as const\n\nexport type RumEventType = (typeof RumEventType)[keyof typeof RumEventType]\n\nexport type AssembledRumEvent = (\n  | RumViewEvent\n  | RumActionEvent\n  | RumResourceEvent\n  | RumErrorEvent\n  | RumVitalEvent\n  | RumLongTaskEvent\n) &\n  Context\n\nexport const RumLongTaskEntryType = {\n  LONG_TASK: 'long-task',\n  LONG_ANIMATION_FRAME: 'long-animation-frame',\n} as const\n\nexport type RumLongTaskEntryType = (typeof RumLongTaskEntryType)[keyof typeof RumLongTaskEntryType]\n\nexport interface RawRumResourceEvent {\n  date: TimeStamp\n  type: typeof RumEventType.RESOURCE\n  resource: {\n    type: ResourceType\n    id: string\n    duration?: ServerDuration\n    url: string\n    method?: string\n    status_code?: number\n    size?: number\n    encoded_body_size?: number\n    decoded_body_size?: number\n    transfer_size?: number\n    render_blocking_status?: string\n    redirect?: ResourceEntryDetailsElement\n    dns?: ResourceEntryDetailsElement\n    connect?: ResourceEntryDetailsElement\n    ssl?: ResourceEntryDetailsElement\n    worker?: ResourceEntryDetailsElement\n    first_byte?: ResourceEntryDetailsElement\n    download?: ResourceEntryDetailsElement\n    protocol?: string\n    delivery_type?: DeliveryType\n    graphql?: GraphQlMetadata\n    request?: ResourceRequest\n    response?: ResourceResponse\n  }\n  _dd: {\n    trace_id?: string\n    span_id?: string // not available for initial document tracing\n    rule_psr?: number\n    discarded?: boolean\n    page_states?: PageStateServerEntry[]\n  }\n  context?: Context\n}\n\nexport type NetworkHeaders = Record<string, string>\n\nexport interface ResourceRequest {\n  headers?: NetworkHeaders\n}\n\nexport interface ResourceResponse {\n  headers?: NetworkHeaders\n}\n\nexport interface ResourceEntryDetailsElement {\n  duration: ServerDuration\n  start: ServerDuration\n}\n\nexport interface RawRumErrorEvent {\n  date: TimeStamp\n  type: typeof RumEventType.ERROR\n  error: {\n    id: string\n    type?: string\n    stack?: string\n    handling_stack?: string\n    component_stack?: string\n    fingerprint?: string\n    source: ErrorSource\n    message: string\n    handling?: ErrorHandling\n    causes?: RawErrorCause[]\n    source_type: 'browser'\n    csp?: Csp\n  }\n  view?: {\n    in_foreground: boolean\n  }\n  context?: Context\n}\n\nexport interface RawRumViewEvent {\n  date: TimeStamp\n  type: typeof RumEventType.VIEW\n  view: {\n    loading_type: ViewLoadingType\n    first_byte?: ServerDuration\n    first_contentful_paint?: ServerDuration\n    first_input_delay?: ServerDuration\n    first_input_time?: ServerDuration\n    first_input_target_selector?: string\n    interaction_to_next_paint?: ServerDuration\n    interaction_to_next_paint_time?: ServerDuration\n    interaction_to_next_paint_target_selector?: string\n    cumulative_layout_shift?: number\n    cumulative_layout_shift_time?: ServerDuration\n    cumulative_layout_shift_target_selector?: string\n    custom_timings?: {\n      [key: string]: ServerDuration\n    }\n    largest_contentful_paint?: ServerDuration\n    largest_contentful_paint_target_selector?: string\n    dom_interactive?: ServerDuration\n    dom_content_loaded?: ServerDuration\n    dom_complete?: ServerDuration\n    load_event?: ServerDuration\n    loading_time?: ServerDuration\n    time_spent: ServerDuration\n    is_active: boolean\n    name?: string\n    error: Count\n    action: Count\n    long_task: Count\n    resource: Count\n    frustration: Count\n    performance?: ViewPerformanceData\n  }\n  display?: ViewDisplay\n  privacy?: {\n    replay_level: DefaultPrivacyLevel\n  }\n  _dd: {\n    document_version: number\n    replay_stats?: ReplayStats\n    page_states?: PageStateServerEntry[]\n    cls?: {\n      device_pixel_ratio: number\n    }\n    configuration: {\n      start_session_replay_recording_manually: boolean\n    }\n  }\n  device?: {\n    locale?: string\n    locales?: readonly string[]\n    time_zone?: string\n  }\n}\n\ninterface ViewDisplay {\n  scroll: {\n    max_depth?: number\n    max_depth_scroll_top?: number\n    max_scroll_height?: number\n    max_scroll_height_time?: ServerDuration\n  }\n}\n\nexport interface ViewPerformanceData {\n  cls?: {\n    score: number\n    timestamp?: ServerDuration\n    target_selector?: string\n    previous_rect?: RumRect\n    current_rect?: RumRect\n  }\n  fcp?: {\n    timestamp: number\n  }\n  fid?: {\n    duration: ServerDuration\n    timestamp: ServerDuration\n    target_selector?: string\n  }\n  inp?: {\n    duration: ServerDuration\n    timestamp?: ServerDuration\n    target_selector?: string\n    sub_parts?: {\n      input_delay: ServerDuration\n      processing_duration: ServerDuration\n      presentation_delay: ServerDuration\n    }\n  }\n  lcp?: {\n    timestamp: ServerDuration\n    target_selector?: string\n    resource_url?: string\n    sub_parts?: {\n      load_delay: ServerDuration\n      load_time: ServerDuration\n      render_delay: ServerDuration\n    }\n  }\n}\n\nexport interface RumRect {\n  x: number\n  y: number\n  width: number\n  height: number\n}\n\nexport interface PageStateServerEntry {\n  state: PageState\n  start: ServerDuration\n  [k: string]: unknown\n}\n\nexport const ViewLoadingType = {\n  INITIAL_LOAD: 'initial_load',\n  ROUTE_CHANGE: 'route_change',\n  BF_CACHE: 'bf_cache',\n} as const\n\nexport type ViewLoadingType = (typeof ViewLoadingType)[keyof typeof ViewLoadingType]\n\nexport interface ViewCustomTimings {\n  [key: string]: Duration\n}\n\nexport interface ReplayStats {\n  records_count: number\n  segments_count: number\n  segments_total_raw_size: number\n}\n\ninterface Count {\n  count: number\n}\n\nexport interface RawRumLongTaskEvent {\n  date: TimeStamp\n  type: typeof RumEventType.LONG_TASK\n  long_task: {\n    id: string\n    entry_type: typeof RumLongTaskEntryType.LONG_TASK\n    duration: ServerDuration\n  }\n  _dd: {\n    discarded: boolean\n  }\n}\n\nexport type DeliveryType = 'cache' | 'navigational-prefetch' | 'other'\n\nexport type InvokerType =\n  | 'user-callback'\n  | 'event-listener'\n  | 'resolve-promise'\n  | 'reject-promise'\n  | 'classic-script'\n  | 'module-script'\n\nexport interface RawRumLongAnimationFrameEvent {\n  date: TimeStamp\n  type: typeof RumEventType.LONG_TASK // LoAF are ingested as Long Task\n  long_task: {\n    id: string\n    entry_type: typeof RumLongTaskEntryType.LONG_ANIMATION_FRAME\n    duration: ServerDuration\n    blocking_duration: ServerDuration\n    first_ui_event_timestamp: ServerDuration\n    render_start: ServerDuration\n    style_and_layout_start: ServerDuration\n    start_time: ServerDuration\n    scripts: Array<{\n      duration: ServerDuration\n      pause_duration: ServerDuration\n      forced_style_and_layout_duration: ServerDuration\n      start_time: ServerDuration\n      execution_start: ServerDuration\n      source_url: string\n      source_function_name: string\n      source_char_position: number\n      invoker: string\n      invoker_type: InvokerType\n      window_attribution: string\n    }>\n  }\n  _dd: {\n    discarded: boolean\n  }\n}\n\nexport interface RawRumActionEvent {\n  date: TimeStamp\n  type: typeof RumEventType.ACTION\n  action: {\n    id: string\n    type: ActionType\n    loading_time?: ServerDuration\n    frustration?: {\n      type: FrustrationType[]\n    }\n    error?: Count\n    long_task?: Count\n    resource?: Count\n    target: {\n      name: string\n    }\n  }\n  view?: {\n    in_foreground: boolean\n  }\n  _dd?: {\n    action?: {\n      target?: {\n        selector?: string\n        width?: number\n        height?: number\n        composed_path_selector?: string\n      }\n      name_source?: string\n      position?: {\n        x: number\n        y: number\n      }\n      pointer_up_delay?: Duration\n    }\n  }\n  context?: Context\n}\n\nexport const ActionType = {\n  CLICK: 'click',\n  CUSTOM: 'custom',\n  TAP: 'tap',\n  SCROLL: 'scroll',\n  SWIPE: 'swipe',\n  APPLICATION_START: 'application_start',\n  BACK: 'back',\n} as const\n\nexport type ActionType = (typeof ActionType)[keyof typeof ActionType]\n\nexport const FrustrationType = {\n  RAGE_CLICK: 'rage_click',\n  ERROR_CLICK: 'error_click',\n  DEAD_CLICK: 'dead_click',\n} as const\n\nexport type FrustrationType = (typeof FrustrationType)[keyof typeof FrustrationType]\n\nexport interface RawRumVitalEvent {\n  date: TimeStamp\n  type: typeof RumEventType.VITAL\n  vital: {\n    id: string\n    name: string\n    type: VitalType\n    step_type?: string\n    operation_key?: string\n    failure_reason?: string\n    description?: string\n    duration?: number\n  }\n  _dd?: {\n    vital: {\n      computed_value: true\n    }\n  }\n  context?: Context\n}\n\nexport const VitalType = {\n  DURATION: 'duration',\n  OPERATION_STEP: 'operation_step',\n} as const\n\nexport type VitalType = (typeof VitalType)[keyof typeof VitalType]\n\nexport type RawRumEvent =\n  | RawRumErrorEvent\n  | RawRumResourceEvent\n  | RawRumViewEvent\n  | RawRumLongTaskEvent\n  | RawRumLongAnimationFrameEvent\n  | RawRumActionEvent\n  | RawRumVitalEvent\n"
  },
  {
    "path": "packages/rum-core/src/rumEvent.types.ts",
    "content": "/**\n * DO NOT MODIFY IT BY HAND. Run `yarn json-schemas:sync` instead.\n */\n\n/**\n * Schema of all properties of a RUM event\n */\nexport type RumEvent =\n  | RumActionEvent\n  | RumTransitionEvent\n  | RumErrorEvent\n  | RumLongTaskEvent\n  | RumResourceEvent\n  | RumViewEvent\n  | RumViewUpdateEvent\n  | RumVitalEvent\n/**\n * Schema of all properties of an Action event\n */\nexport type RumActionEvent = CommonProperties &\n  ViewContainerSchema & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'action'\n    /**\n     * Action properties\n     */\n    readonly action: {\n      /**\n       * Type of the action\n       */\n      readonly type: 'custom' | 'click' | 'tap' | 'scroll' | 'swipe' | 'application_start' | 'back'\n      /**\n       * UUID of the action\n       */\n      readonly id?: string\n      /**\n       * Duration in ns to the action is considered loaded\n       */\n      readonly loading_time?: number\n      /**\n       * Action target properties\n       */\n      readonly target?: {\n        /**\n         * Target name\n         */\n        name: string\n        [k: string]: unknown\n      }\n      /**\n       * Action frustration properties\n       */\n      readonly frustration?: {\n        /**\n         * Action frustration types\n         */\n        readonly type: ('rage_click' | 'dead_click' | 'error_click' | 'rage_tap' | 'error_tap')[]\n        [k: string]: unknown\n      }\n      /**\n       * Properties of the errors of the action\n       */\n      readonly error?: {\n        /**\n         * Number of errors that occurred on the action\n         */\n        readonly count: number\n        [k: string]: unknown\n      }\n      /**\n       * Properties of the crashes of the action\n       */\n      readonly crash?: {\n        /**\n         * Number of crashes that occurred on the action\n         */\n        readonly count: number\n        [k: string]: unknown\n      }\n      /**\n       * Properties of the long tasks of the action\n       */\n      readonly long_task?: {\n        /**\n         * Number of long tasks that occurred on the action\n         */\n        readonly count: number\n        [k: string]: unknown\n      }\n      /**\n       * Properties of the resources of the action\n       */\n      readonly resource?: {\n        /**\n         * Number of resources that occurred on the action\n         */\n        readonly count: number\n        [k: string]: unknown\n      }\n      [k: string]: unknown\n    }\n    /**\n     * View properties\n     */\n    readonly view?: {\n      /**\n       * Is the action starting in the foreground (focus in browser)\n       */\n      readonly in_foreground?: boolean\n      [k: string]: unknown\n    }\n    /**\n     * Internal properties\n     */\n    _dd?: {\n      /**\n       * Action properties\n       */\n      readonly action?: {\n        /**\n         * Action position properties\n         */\n        readonly position?: {\n          /**\n           * X coordinate relative to the target element of the action (in pixels)\n           */\n          readonly x: number\n          /**\n           * Y coordinate relative to the target element of the action (in pixels)\n           */\n          readonly y: number\n          [k: string]: unknown\n        }\n        /**\n         * Target properties\n         */\n        target?: {\n          /**\n           * CSS selector path of the target element\n           */\n          readonly selector?: string\n          /**\n           * Selector data based on the click event composed path\n           */\n          readonly composed_path_selector?: string\n          /**\n           * Width of the target element (in pixels)\n           */\n          readonly width?: number\n          /**\n           * Height of the target element (in pixels)\n           */\n          readonly height?: number\n          /**\n           * Mobile-only: a globally unique and stable identifier for this UI element, computed as the hash of the element's path (32 lowercase hex characters). Used to correlate actions with mobile session replay wireframes.\n           */\n          readonly permanent_id?: string\n          [k: string]: unknown\n        }\n        /**\n         * The strategy of how the auto click action name is computed\n         */\n        name_source?:\n          | 'custom_attribute'\n          | 'mask_placeholder'\n          | 'standard_attribute'\n          | 'text_content'\n          | 'mask_disallowed'\n          | 'blank'\n        [k: string]: unknown\n      }\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n/**\n * Schema of all properties of an Transition event\n */\nexport type RumTransitionEvent = CommonProperties & {\n  /**\n   * RUM event type\n   */\n  readonly type: 'transition'\n  /**\n   * Stream properties\n   */\n  readonly stream: {\n    /**\n     * UUID of the stream\n     */\n    readonly id: string\n    [k: string]: unknown\n  }\n  /**\n   * Transition properties\n   */\n  readonly transition: {\n    /**\n     * Type of the transition\n     */\n    readonly type: string\n    /**\n     * UUID of the transition\n     */\n    readonly id?: string\n    /**\n     * The player's current timestamp in milliseconds\n     */\n    readonly timestamp?: number\n    /**\n     * Buffer starvation duration, the amount of time spent rebuffering in milliseconds\n     */\n    readonly buffer_starvation_duration?: number\n    /**\n     * Media start delay, the amount of time spent loading before playing in milliseconds\n     */\n    readonly media_start_delay?: number\n    /**\n     * Error code, as reported by the player\n     */\n    readonly error_code?: number\n    /**\n     * Duration of the event in milliseconds\n     */\n    readonly duration?: number\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of all properties of an Error event\n */\nexport type RumErrorEvent = CommonProperties &\n  ActionChildProperties &\n  ViewContainerSchema & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'error'\n    /**\n     * Error properties\n     */\n    readonly error: {\n      /**\n       * UUID of the error\n       */\n      readonly id?: string\n      /**\n       * Error message\n       */\n      message: string\n      /**\n       * Source of the error\n       */\n      readonly source: 'network' | 'source' | 'console' | 'logger' | 'agent' | 'webview' | 'custom' | 'report'\n      /**\n       * Stacktrace of the error\n       */\n      stack?: string\n      /**\n       * Causes of the error\n       */\n      causes?: {\n        /**\n         * Error message\n         */\n        message: string\n        /**\n         * The type of the error\n         */\n        readonly type?: string\n        /**\n         * Stacktrace of the error\n         */\n        stack?: string\n        /**\n         * Source of the error\n         */\n        readonly source: 'network' | 'source' | 'console' | 'logger' | 'agent' | 'webview' | 'custom' | 'report'\n        [k: string]: unknown\n      }[]\n      /**\n       * Whether this error crashed the host application\n       */\n      readonly is_crash?: boolean\n      /**\n       * Fingerprint used for Error Tracking custom grouping\n       */\n      fingerprint?: string\n      /**\n       * The type of the error\n       */\n      readonly type?: string\n      /**\n       * The specific category of the error. It provides a high-level grouping for different types of errors.\n       */\n      readonly category?: 'ANR' | 'App Hang' | 'Exception' | 'Watchdog Termination' | 'Memory Warning' | 'Network'\n      /**\n       * Whether the error has been handled manually in the source code or not\n       */\n      readonly handling?: 'handled' | 'unhandled'\n      /**\n       * Handling call stack\n       */\n      handling_stack?: string\n      /**\n       * Source type of the error (the language or platform impacting the error stacktrace format)\n       */\n      readonly source_type?:\n        | 'android'\n        | 'browser'\n        | 'ios'\n        | 'react-native'\n        | 'flutter'\n        | 'roku'\n        | 'ndk'\n        | 'ios+il2cpp'\n        | 'ndk+il2cpp'\n        | 'windows'\n        | 'macos'\n        | 'linux'\n      /**\n       * Resource properties of the error\n       */\n      readonly resource?: {\n        /**\n         * HTTP method of the resource\n         */\n        readonly method: 'POST' | 'GET' | 'HEAD' | 'PUT' | 'DELETE' | 'PATCH' | 'TRACE' | 'OPTIONS' | 'CONNECT'\n        /**\n         * HTTP Status code of the resource\n         */\n        readonly status_code: number\n        /**\n         * URL of the resource\n         */\n        url: string\n        /**\n         * The provider for this resource\n         */\n        readonly provider?: {\n          /**\n           * The domain name of the provider\n           */\n          readonly domain?: string\n          /**\n           * The user friendly name of the provider\n           */\n          readonly name?: string\n          /**\n           * The type of provider\n           */\n          readonly type?:\n            | 'ad'\n            | 'advertising'\n            | 'analytics'\n            | 'cdn'\n            | 'content'\n            | 'customer-success'\n            | 'first party'\n            | 'hosting'\n            | 'marketing'\n            | 'other'\n            | 'social'\n            | 'tag-manager'\n            | 'utility'\n            | 'video'\n          [k: string]: unknown\n        }\n        readonly graphql?: RumGraphql\n        [k: string]: unknown\n      }\n      /**\n       * Description of each thread in the process when error happened.\n       */\n      threads?: {\n        /**\n         * Name of the thread (e.g. 'Thread 0').\n         */\n        readonly name: string\n        /**\n         * Tells if the thread crashed.\n         */\n        readonly crashed: boolean\n        /**\n         * Unsymbolicated stack trace of the given thread.\n         */\n        readonly stack: string\n        /**\n         * Platform-specific state of the thread when its state was captured (CPU registers dump for iOS, thread state enum for Android, etc.).\n         */\n        readonly state?: string\n        [k: string]: unknown\n      }[]\n      /**\n       * Description of each binary image (native libraries; for Android: .so files) loaded or referenced by the process/application.\n       */\n      readonly binary_images?: {\n        /**\n         * Build UUID that uniquely identifies the binary image.\n         */\n        readonly uuid: string\n        /**\n         * Name of the library.\n         */\n        readonly name: string\n        /**\n         * Determines if it's a system or user library.\n         */\n        readonly is_system: boolean\n        /**\n         * Library's load address (hexadecimal).\n         */\n        readonly load_address?: string\n        /**\n         * Max value from the library address range (hexadecimal).\n         */\n        readonly max_address?: string\n        /**\n         * CPU architecture from the library.\n         */\n        readonly arch?: string\n        [k: string]: unknown\n      }[]\n      /**\n       * A boolean value saying if any of the stack traces was truncated due to minification.\n       */\n      readonly was_truncated?: boolean\n      /**\n       * Platform-specific metadata of the error event.\n       */\n      readonly meta?: {\n        /**\n         * The CPU architecture of the process that crashed.\n         */\n        readonly code_type?: string\n        /**\n         * Parent process information.\n         */\n        readonly parent_process?: string\n        /**\n         * A client-generated 16-byte UUID of the incident.\n         */\n        readonly incident_identifier?: string\n        /**\n         * The name of the crashed process.\n         */\n        readonly process?: string\n        /**\n         * The name of the corresponding BSD termination signal. (in case of iOS crash)\n         */\n        readonly exception_type?: string\n        /**\n         * CPU specific information about the exception encoded into 64-bit hexadecimal number preceded by the signal code.\n         */\n        readonly exception_codes?: string\n        /**\n         * The location of the executable.\n         */\n        readonly path?: string\n        [k: string]: unknown\n      }\n      /**\n       * Content Security Violation properties\n       */\n      readonly csp?: {\n        /**\n         * In the context of CSP errors, indicates how the violated policy is configured to be treated by the user agent.\n         */\n        readonly disposition?: 'enforce' | 'report'\n        [k: string]: unknown\n      }\n      /**\n       * Time since application start when error happened (in milliseconds)\n       */\n      readonly time_since_app_start?: number\n      [k: string]: unknown\n    }\n    /**\n     * Properties of App Hang and ANR errors\n     */\n    readonly freeze?: {\n      /**\n       * Duration of the main thread freeze (in ns)\n       */\n      readonly duration: number\n      [k: string]: unknown\n    }\n    /**\n     * View properties\n     */\n    readonly view?: {\n      /**\n       * Is the error starting in the foreground (focus in browser)\n       */\n      readonly in_foreground?: boolean\n      [k: string]: unknown\n    }\n    /**\n     * Feature flags properties\n     */\n    readonly feature_flags?: {\n      [k: string]: unknown\n    }\n    /**\n     * Internal properties\n     */\n    readonly _dd?: RumTrace & {\n      /**\n       * Profiling context\n       */\n      profiling?: ProfilingInternalContextSchema\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n/**\n * Schema of all properties of a Long Task event\n */\nexport type RumLongTaskEvent = CommonProperties &\n  ActionChildProperties &\n  ViewContainerSchema & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'long_task'\n    /**\n     * Long Task properties\n     */\n    readonly long_task: {\n      /**\n       * UUID of the long task or long animation frame\n       */\n      readonly id?: string\n      /**\n       * Start time of the long animation frame\n       */\n      readonly start_time?: number\n      /**\n       * Type of the event: long task or long animation frame\n       */\n      readonly entry_type?: 'long-task' | 'long-animation-frame'\n      /**\n       * Duration in ns of the long task or long animation frame\n       */\n      readonly duration: number\n      /**\n       * Duration in ns for which the animation frame was being blocked\n       */\n      readonly blocking_duration?: number\n      /**\n       * Time difference (in ns) between the timeOrigin and the start time of the rendering cycle, which includes requestAnimationFrame callbacks, style and layout calculation, resize observer and intersection observer callbacks\n       */\n      readonly render_start?: number\n      /**\n       * Time difference (in ns) between the timeOrigin and the start time of the time period spent in style and layout calculations\n       */\n      readonly style_and_layout_start?: number\n      /**\n       * Time difference (in ns) between the timeOrigin and the start time of of the first UI event (mouse/keyboard and so on) to be handled during the course of this frame\n       */\n      readonly first_ui_event_timestamp?: number\n      /**\n       * Whether this long task is considered a frozen frame\n       */\n      readonly is_frozen_frame?: boolean\n      /**\n       * A list of long scripts that were executed over the course of the long frame\n       */\n      readonly scripts?: {\n        /**\n         * Duration in ns between startTime and when the subsequent microtask queue has finished processing\n         */\n        readonly duration?: number\n        /**\n         * Duration in ns of the total time spent in 'pausing' synchronous operations (alert, synchronous XHR)\n         */\n        readonly pause_duration?: number\n        /**\n         * Duration in ns of the the total time spent processing forced layout and style inside this function\n         */\n        readonly forced_style_and_layout_duration?: number\n        /**\n         * Time the entry function was invoked\n         */\n        readonly start_time?: number\n        /**\n         * Time after compilation\n         */\n        readonly execution_start?: number\n        /**\n         * The script resource name where available (or empty if not found)\n         */\n        source_url?: string\n        /**\n         * The script function name where available (or empty if not found)\n         */\n        readonly source_function_name?: string\n        /**\n         * The script character position where available (or -1 if not found)\n         */\n        readonly source_char_position?: number\n        /**\n         * Information about the invoker of the script\n         */\n        invoker?: string\n        /**\n         * Type of the invoker of the script\n         */\n        readonly invoker_type?:\n          | 'user-callback'\n          | 'event-listener'\n          | 'resolve-promise'\n          | 'reject-promise'\n          | 'classic-script'\n          | 'module-script'\n        /**\n         * The container (the top-level document, or an <iframe>) the long animation frame occurred in\n         */\n        readonly window_attribution?: string\n        [k: string]: unknown\n      }[]\n      [k: string]: unknown\n    }\n    /**\n     * Internal properties\n     */\n    readonly _dd?: {\n      /**\n       * Whether the long task should be discarded or indexed\n       */\n      readonly discarded?: boolean\n      /**\n       * Profiling context\n       */\n      profiling?: ProfilingInternalContextSchema\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n/**\n * Schema of all properties of a Resource event\n */\nexport type RumResourceEvent = CommonProperties &\n  ActionChildProperties &\n  ViewContainerSchema & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'resource'\n    /**\n     * Resource properties\n     */\n    readonly resource: {\n      /**\n       * UUID of the resource\n       */\n      readonly id?: string\n      /**\n       * Resource type\n       */\n      readonly type:\n        | 'document'\n        | 'xhr'\n        | 'beacon'\n        | 'fetch'\n        | 'css'\n        | 'js'\n        | 'image'\n        | 'font'\n        | 'media'\n        | 'other'\n        | 'native'\n      /**\n       * HTTP method of the resource\n       */\n      readonly method?: 'POST' | 'GET' | 'HEAD' | 'PUT' | 'DELETE' | 'PATCH' | 'TRACE' | 'OPTIONS' | 'CONNECT'\n      /**\n       * URL of the resource\n       */\n      url: string\n      /**\n       * HTTP status code of the resource\n       */\n      readonly status_code?: number\n      /**\n       * Duration of the resource\n       */\n      readonly duration?: number\n      /**\n       * Size in octet of the resource response body\n       */\n      readonly size?: number\n      /**\n       * Size in octet of the response body before removing any applied content encodings\n       */\n      readonly encoded_body_size?: number\n      /**\n       * Size in octet of the response body after removing any applied encoding\n       */\n      readonly decoded_body_size?: number\n      /**\n       * Size in octet of the fetched response resource\n       */\n      readonly transfer_size?: number\n      /**\n       * Render blocking status of the resource\n       */\n      readonly render_blocking_status?: 'blocking' | 'non-blocking'\n      /**\n       * Worker phase properties\n       */\n      readonly worker?: {\n        /**\n         * Duration in nanoseconds of the resource worker phase\n         */\n        readonly duration: number\n        /**\n         * Duration in nanoseconds between start of the request and start of the worker phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * Redirect phase properties\n       */\n      readonly redirect?: {\n        /**\n         * Duration in ns of the resource redirect phase\n         */\n        readonly duration: number\n        /**\n         * Duration in ns between start of the request and start of the redirect phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * DNS phase properties\n       */\n      readonly dns?: {\n        /**\n         * Duration in ns of the resource dns phase\n         */\n        readonly duration: number\n        /**\n         * Duration in ns between start of the request and start of the dns phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * Connect phase properties\n       */\n      readonly connect?: {\n        /**\n         * Duration in ns of the resource connect phase\n         */\n        readonly duration: number\n        /**\n         * Duration in ns between start of the request and start of the connect phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * SSL phase properties\n       */\n      readonly ssl?: {\n        /**\n         * Duration in ns of the resource ssl phase\n         */\n        readonly duration: number\n        /**\n         * Duration in ns between start of the request and start of the ssl phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * First Byte phase properties\n       */\n      readonly first_byte?: {\n        /**\n         * Duration in ns of the resource first byte phase\n         */\n        readonly duration: number\n        /**\n         * Duration in ns between start of the request and start of the first byte phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * Download phase properties\n       */\n      readonly download?: {\n        /**\n         * Duration in ns of the resource download phase\n         */\n        readonly duration: number\n        /**\n         * Duration in ns between start of the request and start of the download phase\n         */\n        readonly start: number\n        [k: string]: unknown\n      }\n      /**\n       * Network protocol used to fetch the resource (e.g., 'http/1.1', 'h2')\n       */\n      readonly protocol?: string\n      /**\n       * Delivery type of the resource\n       */\n      readonly delivery_type?: 'cache' | 'navigational-prefetch' | 'other'\n      /**\n       * The provider for this resource\n       */\n      readonly provider?: {\n        /**\n         * The domain name of the provider\n         */\n        readonly domain?: string\n        /**\n         * The user friendly name of the provider\n         */\n        readonly name?: string\n        /**\n         * The type of provider\n         */\n        readonly type?:\n          | 'ad'\n          | 'advertising'\n          | 'analytics'\n          | 'cdn'\n          | 'content'\n          | 'customer-success'\n          | 'first party'\n          | 'hosting'\n          | 'marketing'\n          | 'other'\n          | 'social'\n          | 'tag-manager'\n          | 'utility'\n          | 'video'\n        [k: string]: unknown\n      }\n      /**\n       * Request properties\n       */\n      readonly request?: {\n        /**\n         * Size in octet of the request body sent over the network (after encoding)\n         */\n        readonly encoded_body_size?: number\n        /**\n         * Size in octet of the request body before any encoding\n         */\n        readonly decoded_body_size?: number\n        /**\n         * HTTP headers of the resource request\n         */\n        readonly headers?: {\n          [k: string]: string\n        }\n        [k: string]: unknown\n      }\n      /**\n       * Response properties\n       */\n      readonly response?: {\n        /**\n         * HTTP headers of the resource response\n         */\n        readonly headers?: {\n          [k: string]: string\n        }\n        [k: string]: unknown\n      }\n      readonly graphql?: RumGraphql\n      [k: string]: unknown\n    }\n    /**\n     * Internal properties\n     */\n    readonly _dd?: RumTrace & {\n      /**\n       * Whether the resource should be discarded or indexed\n       */\n      readonly discarded?: boolean\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n/**\n * Schema of all properties of a View event\n */\nexport type RumViewEvent = CommonProperties &\n  ViewContainerSchema &\n  StreamSchema &\n  ViewProperties & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'view'\n    view: {\n      time_spent: number\n      action: {\n        [k: string]: unknown\n      }\n      error: {\n        [k: string]: unknown\n      }\n      resource: {\n        [k: string]: unknown\n      }\n      [k: string]: unknown\n    }\n    /**\n     * Internal properties\n     */\n    readonly _dd: {\n      /**\n       * Version of the update of the view event\n       */\n      readonly document_version: number\n      /**\n       * List of the page states during the view\n       */\n      readonly page_states?: {\n        /**\n         * Page state name\n         */\n        readonly state: 'active' | 'passive' | 'hidden' | 'frozen' | 'terminated'\n        /**\n         * Duration in ns between start of the view and start of the page state\n         */\n        readonly start: number\n        [k: string]: unknown\n      }[]\n      /**\n       * Debug metadata for Replay Sessions\n       */\n      replay_stats?: {\n        /**\n         * The number of records produced during this view lifetime\n         */\n        records_count?: number\n        /**\n         * The number of segments sent during this view lifetime\n         */\n        segments_count?: number\n        /**\n         * The total size in bytes of the segments sent during this view lifetime\n         */\n        segments_total_raw_size?: number\n        [k: string]: unknown\n      }\n      /**\n       * Additional information of the reported Cumulative Layout Shift\n       */\n      readonly cls?: {\n        /**\n         * Pixel ratio of the device where the layout shift was reported\n         */\n        readonly device_pixel_ratio?: number\n        [k: string]: unknown\n      }\n      /**\n       * Subset of the SDK configuration options in use during its execution\n       */\n      readonly configuration?: {\n        /**\n         * Whether session replay recording configured to start manually\n         */\n        readonly start_session_replay_recording_manually?: boolean\n        [k: string]: unknown\n      }\n      /**\n       * Profiling context\n       */\n      profiling?: ProfilingInternalContextSchema\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n/**\n * Schema of all properties of a View Update event\n */\nexport type RumViewUpdateEvent = ViewContainerSchema &\n  StreamSchema &\n  ViewProperties &\n  CommonProperties & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'view_update'\n    /**\n     * Internal properties\n     */\n    readonly _dd?: {\n      /**\n       * Version of the update of the view event\n       */\n      readonly document_version: number\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\nexport type RumVitalEvent = RumVitalDurationEvent | RumVitalOperationStepEvent\n/**\n * Schema for a duration vital event.\n */\nexport type RumVitalDurationEvent = RumVitalEventCommonProperties & {\n  /**\n   * Vital properties\n   */\n  readonly vital?: {\n    /**\n     * Type of the vital.\n     */\n    readonly type: 'duration'\n    /**\n     * Duration of the vital in nanoseconds.\n     */\n    readonly duration: number\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of common properties for a Vital event\n */\nexport type RumVitalEventCommonProperties = CommonProperties &\n  ViewContainerSchema & {\n    /**\n     * RUM event type\n     */\n    readonly type: 'vital'\n    /**\n     * Vital properties\n     */\n    readonly vital: {\n      /**\n       * UUID of the vital\n       */\n      readonly id: string\n      /**\n       * Name of the vital, as it is also used as facet path for its value, it must contain only letters, digits, or the characters - _ . @ $\n       */\n      readonly name?: string\n      /**\n       * Description of the vital. It can be used as a secondary identifier (URL, React component name...)\n       */\n      readonly description?: string\n      [k: string]: unknown\n    }\n    /**\n     * Internal properties\n     */\n    readonly _dd?: {\n      /**\n       * Profiling context\n       */\n      profiling?: ProfilingInternalContextSchema\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n/**\n * Schema for a vital operation step event.\n */\nexport type RumVitalOperationStepEvent = RumVitalEventCommonProperties & {\n  /**\n   * Vital properties\n   */\n  readonly vital?: {\n    /**\n     * Type of the vital.\n     */\n    readonly type: 'operation_step'\n    /**\n     * Optional key to distinguish between multiple operations of the same name running in parallel (e.g., 'photo_upload' with keys 'profile_pic' vs 'cover')\n     */\n    readonly operation_key?: string\n    /**\n     * Type of the step that triggered the vital, if applicable\n     */\n    readonly step_type: 'start' | 'update' | 'retry' | 'end'\n    /**\n     * Reason for the failure of the step, if applicable\n     */\n    readonly failure_reason?: 'error' | 'abandoned' | 'other'\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n\n/**\n * Schema of common properties of RUM events\n */\nexport interface CommonProperties {\n  /**\n   * Start of the event in ms from epoch\n   */\n  readonly date: number\n  /**\n   * Application properties\n   */\n  readonly application: {\n    /**\n     * UUID of the application\n     */\n    readonly id: string\n    /**\n     * The user's current locale as a language tag (language + region), computed from their preferences and the app's supported languages, e.g. 'es-FR'.\n     */\n    readonly current_locale?: string\n    [k: string]: unknown\n  }\n  /**\n   * The service name for this application\n   */\n  service?: string\n  /**\n   * The version for this application\n   */\n  version?: string\n  /**\n   * The build version for this application\n   */\n  readonly build_version?: string\n  /**\n   * Generated unique ID of the application build. Unlike version or build_version this field is not meant to be coming from the user, but rather generated by the tooling for each build.\n   */\n  readonly build_id?: string\n  /**\n   * Tags of the event in key:value format, separated by commas (e.g. 'env:prod,version:1.2.3')\n   */\n  readonly ddtags?: string\n  /**\n   * Session properties\n   */\n  readonly session: {\n    /**\n     * UUID of the session\n     */\n    readonly id: string\n    /**\n     * Type of the session\n     */\n    readonly type: 'user' | 'synthetics' | 'ci_test'\n    /**\n     * Whether this session has a replay\n     */\n    readonly has_replay?: boolean\n    [k: string]: unknown\n  }\n  /**\n   * The source of this event\n   */\n  readonly source?:\n    | 'android'\n    | 'ios'\n    | 'browser'\n    | 'flutter'\n    | 'react-native'\n    | 'roku'\n    | 'unity'\n    | 'kotlin-multiplatform'\n    | 'electron'\n    | 'rum-cpp'\n  /**\n   * View properties\n   */\n  readonly view: {\n    /**\n     * UUID of the view\n     */\n    readonly id: string\n    /**\n     * URL that linked to the initial view of the page\n     */\n    referrer?: string\n    /**\n     * URL of the view\n     */\n    url: string\n    /**\n     * User defined name of the view\n     */\n    name?: string\n    [k: string]: unknown\n  }\n  /**\n   * User properties\n   */\n  readonly usr?: {\n    /**\n     * Identifier of the user\n     */\n    readonly id?: string\n    /**\n     * Name of the user\n     */\n    readonly name?: string\n    /**\n     * Email of the user\n     */\n    readonly email?: string\n    /**\n     * Identifier of the user across sessions\n     */\n    readonly anonymous_id?: string\n    [k: string]: unknown\n  }\n  /**\n   * Account properties\n   */\n  readonly account?: {\n    /**\n     * Identifier of the account\n     */\n    readonly id: string\n    /**\n     * Name of the account\n     */\n    readonly name?: string\n    [k: string]: unknown\n  }\n  /**\n   * Tab properties\n   */\n  readonly tab?: {\n    /**\n     * UUID of the browser tab\n     */\n    readonly id: string\n    [k: string]: unknown\n  }\n  /**\n   * Device connectivity properties\n   */\n  connectivity?: {\n    /**\n     * Status of the device connectivity\n     */\n    readonly status: 'connected' | 'not_connected' | 'maybe'\n    /**\n     * The list of available network interfaces\n     */\n    readonly interfaces?: (\n      | 'bluetooth'\n      | 'cellular'\n      | 'ethernet'\n      | 'wifi'\n      | 'wimax'\n      | 'mixed'\n      | 'other'\n      | 'unknown'\n      | 'none'\n    )[]\n    /**\n     * Cellular connection type reflecting the measured network performance\n     */\n    readonly effective_type?: 'slow-2g' | '2g' | '3g' | '4g'\n    /**\n     * Cellular connectivity properties\n     */\n    readonly cellular?: {\n      /**\n       * The type of a radio technology used for cellular connection\n       */\n      readonly technology?: string\n      /**\n       * The name of the SIM carrier\n       */\n      readonly carrier_name?: string\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  /**\n   * Display properties\n   */\n  display?: {\n    /**\n     * The viewport represents the rectangular area that is currently being viewed. Content outside the viewport is not visible onscreen until scrolled into view.\n     */\n    readonly viewport?: {\n      /**\n       * Width of the viewport (in pixels)\n       */\n      readonly width: number\n      /**\n       * Height of the viewport (in pixels)\n       */\n      readonly height: number\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  /**\n   * Synthetics properties\n   */\n  readonly synthetics?: {\n    /**\n     * The identifier of the current Synthetics test\n     */\n    readonly test_id: string\n    /**\n     * The identifier of the current Synthetics test results\n     */\n    readonly result_id: string\n    /**\n     * Whether the event comes from a SDK instance injected by Synthetics\n     */\n    readonly injected?: boolean\n    [k: string]: unknown\n  }\n  /**\n   * CI Visibility properties\n   */\n  readonly ci_test?: {\n    /**\n     * The identifier of the current CI Visibility test execution\n     */\n    readonly test_execution_id: string\n    [k: string]: unknown\n  }\n  /**\n   * Operating system properties\n   */\n  os?: {\n    /**\n     * Operating system name, e.g. Android, iOS\n     */\n    readonly name: string\n    /**\n     * Full operating system version, e.g. 8.1.1\n     */\n    readonly version: string\n    /**\n     * Operating system build number, e.g. 15D21\n     */\n    readonly build?: string\n    /**\n     * Major operating system version, e.g. 8\n     */\n    readonly version_major: string\n    [k: string]: unknown\n  }\n  /**\n   * Device properties\n   */\n  device?: {\n    /**\n     * Device type info\n     */\n    readonly type?: 'mobile' | 'desktop' | 'tablet' | 'tv' | 'gaming_console' | 'bot' | 'other'\n    /**\n     * Device marketing name, e.g. Xiaomi Redmi Note 8 Pro, Pixel 5, etc.\n     */\n    readonly name?: string\n    /**\n     * Device SKU model, e.g. Samsung SM-988GN, etc. Quite often name and model can be the same.\n     */\n    readonly model?: string\n    /**\n     * Device marketing brand, e.g. Apple, OPPO, Xiaomi, etc.\n     */\n    readonly brand?: string\n    /**\n     * The CPU architecture of the device that is reporting the error\n     */\n    readonly architecture?: string\n    /**\n     * The user’s locale as a language tag combining language and region, e.g. 'en-US'.\n     */\n    readonly locale?: string\n    /**\n     * Ordered list of the user’s preferred system languages as IETF language tags.\n     */\n    readonly locales?: string[]\n    /**\n     * The device’s current time zone identifier, e.g. 'Europe/Berlin'.\n     */\n    readonly time_zone?: string\n    /**\n     * Current battery level of the device (0.0 to 1.0).\n     */\n    readonly battery_level?: number\n    /**\n     * Whether the device is in power saving mode.\n     */\n    readonly power_saving_mode?: boolean\n    /**\n     * Current screen brightness level (0.0 to 1.0).\n     */\n    readonly brightness_level?: number\n    /**\n     * Number of logical CPU cores available for scheduling on the device at runtime, as reported by the operating system.\n     */\n    readonly logical_cpu_count?: number\n    /**\n     * Total RAM in megabytes\n     */\n    readonly total_ram?: number\n    /**\n     * Whether the device is considered a low RAM device (Android)\n     */\n    readonly is_low_ram?: boolean\n    [k: string]: unknown\n  }\n  /**\n   * Internal properties\n   */\n  readonly _dd: {\n    /**\n     * Version of the RUM event format\n     */\n    readonly format_version: 2\n    /**\n     * Session-related internal properties\n     */\n    session?: {\n      /**\n       * Session plan: 1 is the plan without replay, 2 is the plan with replay (deprecated)\n       */\n      plan?: 1 | 2\n      /**\n       * The precondition that led to the creation of the session\n       */\n      readonly session_precondition?:\n        | 'user_app_launch'\n        | 'inactivity_timeout'\n        | 'max_duration'\n        | 'background_launch'\n        | 'prewarm'\n        | 'from_non_interactive_session'\n        | 'explicit_stop'\n      [k: string]: unknown\n    }\n    /**\n     * Subset of the SDK configuration options in use during its execution\n     */\n    readonly configuration?: {\n      /**\n       * The percentage of sessions tracked\n       */\n      readonly session_sample_rate: number\n      /**\n       * The percentage of sessions with RUM & Session Replay pricing tracked\n       */\n      readonly session_replay_sample_rate?: number\n      /**\n       * The percentage of sessions profiled\n       */\n      readonly profiling_sample_rate?: number\n      /**\n       * The percentage of sessions with traced resources\n       */\n      readonly trace_sample_rate?: number\n      [k: string]: unknown\n    }\n    /**\n     * Browser SDK version\n     */\n    readonly browser_sdk_version?: string\n    /**\n     * SDK name (e.g. 'logs', 'rum', 'rum-slim', etc.)\n     */\n    readonly sdk_name?: string\n    [k: string]: unknown\n  }\n  /**\n   * User provided context\n   */\n  context?: {\n    [k: string]: unknown\n  }\n  /**\n   * Stream properties\n   */\n  stream?: {\n    /**\n     * UUID of the stream\n     */\n    readonly id: string\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * View Container schema for views that are nested (webviews in mobile)\n */\nexport interface ViewContainerSchema {\n  /**\n   * View Container properties (view wrapping the current view)\n   */\n  readonly container?: {\n    /**\n     * Attributes of the view's container\n     */\n    readonly view: {\n      /**\n       * ID of the parent view\n       */\n      readonly id: string\n      [k: string]: unknown\n    }\n    /**\n     * Source of the parent view\n     */\n    readonly source:\n      | 'android'\n      | 'ios'\n      | 'browser'\n      | 'flutter'\n      | 'react-native'\n      | 'roku'\n      | 'unity'\n      | 'kotlin-multiplatform'\n      | 'electron'\n      | 'rum-cpp'\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of all properties of events that can have parent actions\n */\nexport interface ActionChildProperties {\n  /**\n   * Action properties\n   */\n  readonly action?: {\n    /**\n     * UUID of the action\n     */\n    readonly id: string | string[]\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * GraphQL request parameters\n */\nexport interface RumGraphql {\n  /**\n   * Type of the GraphQL operation\n   */\n  readonly operationType?: 'query' | 'mutation' | 'subscription'\n  /**\n   * Name of the GraphQL operation\n   */\n  readonly operationName?: string\n  /**\n   * Content of the GraphQL operation\n   */\n  payload?: string\n  /**\n   * String representation of the operation variables\n   */\n  variables?: string\n  /**\n   * Number of GraphQL errors in the response\n   */\n  readonly error_count?: number\n  /**\n   * Array of GraphQL errors from the response\n   */\n  readonly errors?: {\n    /**\n     * Error message\n     */\n    readonly message: string\n    /**\n     * Error code (used by some providers)\n     */\n    readonly code?: string\n    /**\n     * Array of error locations in the GraphQL query\n     */\n    readonly locations?: {\n      /**\n       * Line number where the error occurred\n       */\n      readonly line: number\n      /**\n       * Column number where the error occurred\n       */\n      readonly column: number\n      [k: string]: unknown\n    }[]\n    /**\n     * Path to the field that caused the error\n     */\n    readonly path?: (string | number)[]\n    [k: string]: unknown\n  }[]\n  [k: string]: unknown\n}\n/**\n * Trace context properties\n */\nexport interface RumTrace {\n  /**\n   * span identifier in decimal format\n   */\n  readonly span_id?: string\n  /**\n   * parent span identifier in decimal format\n   */\n  readonly parent_span_id?: string\n  /**\n   * trace identifier, either a 64 bit decimal number or a 128 bit hexadecimal number padded with 0s\n   */\n  readonly trace_id?: string\n  /**\n   * trace sample rate in decimal format\n   */\n  readonly rule_psr?: number\n  [k: string]: unknown\n}\n/**\n * RUM Profiler Internal Context schema\n */\nexport interface ProfilingInternalContextSchema {\n  /**\n   * Used to track the status of the RUM Profiler.\n   *\n   * They are defined in order of when they can happen, from the moment the SDK is initialized to the moment the Profiler is actually running.\n   *\n   * - `starting`: The Profiler is starting (i.e., when the SDK just started). This is the initial status.\n   * - `running`: The Profiler is running.\n   * - `stopped`: The Profiler is stopped.\n   * - `error`: The Profiler encountered an error. See `error_reason` for more details.\n   */\n  readonly status?: 'starting' | 'running' | 'stopped' | 'error'\n  /**\n   * The reason the Profiler encountered an error. This attribute is only present if the status is `error`.\n   *\n   * Possible values:\n   * - `not-supported-by-browser`: The browser does not support the Profiler (i.e., `window.Profiler` is not available).\n   * - `failed-to-lazy-load`: The Profiler script failed to be loaded by the browser (may be a connection issue or the chunk was not found).\n   * - `missing-document-policy-header`: The Profiler failed to start because its missing `Document-Policy: js-profiling` HTTP response header.\n   * - `unexpected-exception`: An exception occurred when starting the Profiler.\n   */\n  readonly error_reason?:\n    | 'not-supported-by-browser'\n    | 'failed-to-lazy-load'\n    | 'missing-document-policy-header'\n    | 'unexpected-exception'\n  [k: string]: unknown\n}\n/**\n * Stream schema for media streaming properties\n */\nexport interface StreamSchema {\n  /**\n   * Stream properties\n   */\n  readonly stream?: {\n    /**\n     * current bitrate at the time of collection\n     */\n    bitrate?: number\n    /**\n     * How long is the content (VOD only) (in ms)\n     */\n    readonly duration?: number\n    /**\n     * Stream format\n     */\n    readonly format?: string\n    /**\n     * current frames per second at the time of collection\n     */\n    fps?: number\n    /**\n     * Stream resolution\n     */\n    readonly resolution?: string\n    /**\n     * current timestamp at the time of collection\n     */\n    timestamp?: number\n    /**\n     * how much did the media progress since the last context update (in ms)\n     */\n    watch_time?: number\n    /**\n     * Percentage of amount of time watched relative to its total duration\n     */\n    completion_percent?: number\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Shared optional view-specific properties used by both view and view_update events\n */\nexport interface ViewProperties {\n  /**\n   * View properties\n   */\n  readonly view?: {\n    /**\n     * Duration in ns to the view is considered loaded\n     */\n    readonly loading_time?: number\n    /**\n     * Duration in ns from the moment the view was started until all the initial network requests settled\n     */\n    readonly network_settled_time?: number\n    /**\n     * Duration in ns to from the last interaction on previous view to the moment the current view was displayed\n     */\n    readonly interaction_to_next_view_time?: number\n    /**\n     * Type of the loading of the view\n     */\n    readonly loading_type?:\n      | 'initial_load'\n      | 'route_change'\n      | 'activity_display'\n      | 'activity_redisplay'\n      | 'fragment_display'\n      | 'fragment_redisplay'\n      | 'view_controller_display'\n      | 'view_controller_redisplay'\n    /**\n     * Time spent on the view in ns\n     */\n    readonly time_spent?: number\n    /**\n     * @deprecated\n     * Duration in ns to the first rendering (deprecated in favor of `view.performance.fcp.timestamp`)\n     */\n    readonly first_contentful_paint?: number\n    /**\n     * @deprecated\n     * Duration in ns to the largest contentful paint (deprecated in favor of `view.performance.lcp.timestamp`)\n     */\n    readonly largest_contentful_paint?: number\n    /**\n     * @deprecated\n     * CSS selector path of the largest contentful paint element (deprecated in favor of `view.performance.lcp.target_selector`)\n     */\n    readonly largest_contentful_paint_target_selector?: string\n    /**\n     * @deprecated\n     * Duration in ns of the first input event delay (deprecated in favor of `view.performance.fid.duration`)\n     */\n    readonly first_input_delay?: number\n    /**\n     * @deprecated\n     * Duration in ns to the first input (deprecated in favor of `view.performance.fid.timestamp`)\n     */\n    readonly first_input_time?: number\n    /**\n     * @deprecated\n     * CSS selector path of the first input target element (deprecated in favor of `view.performance.fid.target_selector`)\n     */\n    readonly first_input_target_selector?: string\n    /**\n     * @deprecated\n     * Longest duration in ns between an interaction and the next paint (deprecated in favor of `view.performance.inp.duration`)\n     */\n    readonly interaction_to_next_paint?: number\n    /**\n     * @deprecated\n     * Duration in ns between start of the view and start of the INP (deprecated in favor of `view.performance.inp.timestamp`)\n     */\n    readonly interaction_to_next_paint_time?: number\n    /**\n     * @deprecated\n     * CSS selector path of the interacted element corresponding to INP (deprecated in favor of `view.performance.inp.target_selector`)\n     */\n    readonly interaction_to_next_paint_target_selector?: string\n    /**\n     * @deprecated\n     * Total layout shift score that occurred on the view (deprecated in favor of `view.performance.cls.score`)\n     */\n    readonly cumulative_layout_shift?: number\n    /**\n     * @deprecated\n     * Duration in ns between start of the view and start of the largest layout shift contributing to CLS (deprecated in favor of `view.performance.cls.timestamp`)\n     */\n    readonly cumulative_layout_shift_time?: number\n    /**\n     * @deprecated\n     * CSS selector path of the first element (in document order) of the largest layout shift contributing to CLS (deprecated in favor of `view.performance.cls.target_selector`)\n     */\n    readonly cumulative_layout_shift_target_selector?: string\n    /**\n     * Duration in ns to the complete parsing and loading of the document and its sub resources\n     */\n    readonly dom_complete?: number\n    /**\n     * Duration in ns to the complete parsing and loading of the document without its sub resources\n     */\n    readonly dom_content_loaded?: number\n    /**\n     * Duration in ns to the end of the parsing of the document\n     */\n    readonly dom_interactive?: number\n    /**\n     * Duration in ns to the end of the load event handler execution\n     */\n    readonly load_event?: number\n    /**\n     * Duration in ns to the response start of the document request\n     */\n    readonly first_byte?: number\n    /**\n     * User custom timings of the view. As timing name is used as facet path, it must contain only letters, digits, or the characters - _ . @ $\n     */\n    readonly custom_timings?: {\n      [k: string]: number\n    }\n    /**\n     * Whether the View corresponding to this event is considered active\n     */\n    readonly is_active?: boolean\n    /**\n     * Whether the View had a low average refresh rate\n     */\n    readonly is_slow_rendered?: boolean\n    /**\n     * Properties of the actions of the view\n     */\n    readonly action?: {\n      /**\n       * Number of actions that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * Properties of the errors of the view\n     */\n    readonly error?: {\n      /**\n       * Number of errors that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * Properties of the crashes of the view\n     */\n    readonly crash?: {\n      /**\n       * Number of crashes that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * Properties of the long tasks of the view\n     */\n    readonly long_task?: {\n      /**\n       * Number of long tasks that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * Properties of the frozen frames of the view\n     */\n    readonly frozen_frame?: {\n      /**\n       * Number of frozen frames that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * List of slow frames during the view's lifetime\n     */\n    readonly slow_frames?: {\n      /**\n       * Duration in ns between start of the view and the start of the slow frame\n       */\n      readonly start: number\n      /**\n       * Duration in ns of the slow frame\n       */\n      readonly duration: number\n      [k: string]: unknown\n    }[]\n    /**\n     * Properties of the resources of the view\n     */\n    readonly resource?: {\n      /**\n       * Number of resources that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * Properties of the frustrations of the view\n     */\n    readonly frustration?: {\n      /**\n       * Number of frustrations that occurred on the view\n       */\n      readonly count: number\n      [k: string]: unknown\n    }\n    /**\n     * List of the periods of time the user had the view in foreground (focused in the browser)\n     */\n    readonly in_foreground_periods?: {\n      /**\n       * Duration in ns between start of the view and start of foreground period\n       */\n      readonly start: number\n      /**\n       * Duration in ns of the view foreground period\n       */\n      readonly duration: number\n      [k: string]: unknown\n    }[]\n    /**\n     * Average memory used during the view lifetime (in bytes)\n     */\n    readonly memory_average?: number\n    /**\n     * Peak memory used during the view lifetime (in bytes)\n     */\n    readonly memory_max?: number\n    /**\n     * Total number of cpu ticks during the view's lifetime\n     */\n    readonly cpu_ticks_count?: number\n    /**\n     * Average number of cpu ticks per second during the view's lifetime\n     */\n    readonly cpu_ticks_per_second?: number\n    /**\n     * Average refresh rate during the view's lifetime (in frames per second)\n     */\n    readonly refresh_rate_average?: number\n    /**\n     * Minimum refresh rate during the view's lifetime (in frames per second)\n     */\n    readonly refresh_rate_min?: number\n    /**\n     * Rate of slow frames during the view's lifetime (in milliseconds per second)\n     */\n    readonly slow_frames_rate?: number\n    /**\n     * Rate of freezes during the view's lifetime (in seconds per hour)\n     */\n    readonly freeze_rate?: number\n    /**\n     * Time taken for Flutter 'build' methods.\n     */\n    flutter_build_time?: RumPerfMetric\n    /**\n     * Time taken for Flutter to rasterize the view.\n     */\n    flutter_raster_time?: RumPerfMetric\n    /**\n     * The JavaScript refresh rate for React Native\n     */\n    js_refresh_rate?: RumPerfMetric\n    /**\n     * Performance data. (Web Vitals, etc.)\n     */\n    performance?: ViewPerformanceData\n    /**\n     * Accessibility properties of the view\n     */\n    accessibility?: ViewAccessibilityProperties\n    [k: string]: unknown\n  }\n  /**\n   * Session properties\n   */\n  readonly session?: {\n    /**\n     * Whether this session is currently active. Set to false to manually stop a session\n     */\n    readonly is_active?: boolean\n    /**\n     * Whether this session has been sampled for replay\n     */\n    readonly sampled_for_replay?: boolean\n    [k: string]: unknown\n  }\n  /**\n   * Feature flags properties\n   */\n  readonly feature_flags?: {\n    [k: string]: unknown\n  }\n  /**\n   * Privacy properties\n   */\n  readonly privacy?: {\n    /**\n     * The replay privacy level\n     */\n    readonly replay_level: 'allow' | 'mask' | 'mask-user-input'\n    [k: string]: unknown\n  }\n  /**\n   * Display properties\n   */\n  readonly display?: {\n    /**\n     * Scroll properties\n     */\n    readonly scroll?: {\n      /**\n       * Distance between the top and the lowest point reached on this view (in pixels)\n       */\n      readonly max_depth: number\n      /**\n       * Page scroll top (scrolled distance) when the maximum scroll depth was reached for this view (in pixels)\n       */\n      readonly max_depth_scroll_top: number\n      /**\n       * Maximum page scroll height (total height) for this view (in pixels)\n       */\n      readonly max_scroll_height: number\n      /**\n       * Duration between the view start and the time the max scroll height was reached for this view (in nanoseconds)\n       */\n      readonly max_scroll_height_time: number\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema of properties for a technical performance metric\n */\nexport interface RumPerfMetric {\n  /**\n   * The minimum value seen for this metric during the view's lifetime.\n   */\n  readonly min: number\n  /**\n   * The maximum value seen for this metric during the view's lifetime.\n   */\n  readonly max: number\n  /**\n   * The average value for this metric during the view's lifetime.\n   */\n  readonly average: number\n  /**\n   * The maximum possible value we could see for this metric, if such a max is relevant and can vary from session to session.\n   */\n  readonly metric_max?: number\n  [k: string]: unknown\n}\n/**\n * Schema for view-level RUM performance data (Web Vitals, etc.)\n */\nexport interface ViewPerformanceData {\n  /**\n   * Cumulative Layout Shift\n   */\n  readonly cls?: {\n    /**\n     * Total layout shift score that occurred on the view\n     */\n    readonly score: number\n    /**\n     * The time of the largest layout shift contributing to CLS, in ns since view start.\n     */\n    readonly timestamp?: number\n    /**\n     * CSS selector path of the first element (in document order) of the largest layout shift contributing to CLS\n     */\n    readonly target_selector?: string\n    /**\n     * Bounding client rect of the element before the layout shift\n     */\n    previous_rect?: RumRect\n    /**\n     * Bounding client rect of the element after the layout shift\n     */\n    current_rect?: RumRect\n    [k: string]: unknown\n  }\n  /**\n   * First Contentful Paint\n   */\n  readonly fcp?: {\n    /**\n     * The time of the first rendering, in ns since view start.\n     */\n    readonly timestamp: number\n    [k: string]: unknown\n  }\n  /**\n   * First Input Delay\n   */\n  readonly fid?: {\n    /**\n     * Duration in ns of the first input event delay\n     */\n    readonly duration: number\n    /**\n     * Time of the first input event, in ns since view start.\n     */\n    readonly timestamp: number\n    /**\n     * CSS selector path of the first input target element\n     */\n    readonly target_selector?: string\n    [k: string]: unknown\n  }\n  /**\n   * Interaction to Next Paint\n   */\n  readonly inp?: {\n    /**\n     * Longest duration in ns between an interaction and the next paint\n     */\n    readonly duration: number\n    /**\n     * Time of the start of the INP interaction, in ns since view start.\n     */\n    readonly timestamp?: number\n    /**\n     * CSS selector path of the interacted element for the INP interaction\n     */\n    readonly target_selector?: string\n    /**\n     * Sub-parts of the INP\n     */\n    sub_parts?: {\n      /**\n       * Time from the start of the input event to the start of the processing of the event\n       */\n      readonly input_delay: number\n      /**\n       * Event handler execution time\n       */\n      readonly processing_duration: number\n      /**\n       * Rendering time happening after processing\n       */\n      readonly presentation_delay: number\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  /**\n   * Largest Contentful Paint\n   */\n  readonly lcp?: {\n    /**\n     * Time of the largest contentful paint, in ns since view start.\n     */\n    readonly timestamp: number\n    /**\n     * CSS selector path of the largest contentful paint element\n     */\n    readonly target_selector?: string\n    /**\n     * URL of the largest contentful paint element\n     */\n    resource_url?: string\n    /**\n     * Sub-parts of the LCP\n     */\n    sub_parts?: {\n      /**\n       * Time between first_byte and the loading start of the resource associated with the LCP\n       */\n      readonly load_delay: number\n      /**\n       * Time to takes to load the resource attached to the LCP\n       */\n      readonly load_time: number\n      /**\n       * Time between the LCP resource finishes loading and the LCP element is fully rendered\n       */\n      readonly render_delay: number\n      [k: string]: unknown\n    }\n    [k: string]: unknown\n  }\n  /**\n   * First Build Complete (Flutter)\n   */\n  readonly fbc?: {\n    /**\n     * Time of all completed `build` methods after a route change, in ns since view start.\n     */\n    readonly timestamp: number\n    [k: string]: unknown\n  }\n  [k: string]: unknown\n}\n/**\n * Schema for DOMRect-like rectangles describing an element's bounding client rect\n */\nexport interface RumRect {\n  /**\n   * The x coordinate of the element's origin\n   */\n  readonly x: number\n  /**\n   * The y coordinate of the element's origin\n   */\n  readonly y: number\n  /**\n   * The element's width\n   */\n  readonly width: number\n  /**\n   * The element's height\n   */\n  readonly height: number\n  [k: string]: unknown\n}\n/**\n * Compact representation of accessibility features for a view\n */\nexport interface ViewAccessibilityProperties {\n  /**\n   * User’s preferred text scale relative to the default system size.\n   */\n  readonly text_size?: string\n  /**\n   * Indicates whether a screen reader is currently active.\n   */\n  readonly screen_reader_enabled?: boolean\n  /**\n   * Indicates whether the system-wide bold text accessibility setting is enabled.\n   */\n  readonly bold_text_enabled?: boolean\n  /**\n   * Indicates whether the system-wide reduce transparency setting is enabled.\n   */\n  readonly reduce_transparency_enabled?: boolean\n  /**\n   * Indicates whether the system-wide reduce motion setting is enabled.\n   */\n  readonly reduce_motion_enabled?: boolean\n  /**\n   * Indicates whether the system-wide button shapes setting is enabled.\n   */\n  readonly button_shapes_enabled?: boolean\n  /**\n   * Indicates whether the system-wide color inversion setting is enabled.\n   */\n  readonly invert_colors_enabled?: boolean\n  /**\n   * Indicates whether the system-wide increase contrast setting is enabled.\n   */\n  readonly increase_contrast_enabled?: boolean\n  /**\n   * Indicates whether an alternative input method like Switch Control or Switch Access is currently enabled.\n   */\n  readonly assistive_switch_enabled?: boolean\n  /**\n   * Indicates whether the system-wide AssistiveTouch feature is currently enabled.\n   */\n  readonly assistive_touch_enabled?: boolean\n  /**\n   * Indicates whether the video autoplay setting is enabled in the system or application.\n   */\n  readonly video_autoplay_enabled?: boolean\n  /**\n   * Indicates whether closed captioning is enabled for media playback.\n   */\n  readonly closed_captioning_enabled?: boolean\n  /**\n   * Indicates whether the system-wide mono audio setting is enabled.\n   */\n  readonly mono_audio_enabled?: boolean\n  /**\n   * Indicates whether the Shake to Undo feature is enabled.\n   */\n  readonly shake_to_undo_enabled?: boolean\n  /**\n   * Indicates whether the user prefers reduced animations or cross-fade transitions.\n   */\n  readonly reduced_animations_enabled?: boolean\n  /**\n   * Indicates whether the system should differentiate interface elements without relying solely on color.\n   */\n  readonly should_differentiate_without_color?: boolean\n  /**\n   * Indicates whether the device display is currently using grayscale mode.\n   */\n  readonly grayscale_enabled?: boolean\n  /**\n   * Indicates whether the device is currently locked to a single app through Guided Access or Screen Pinning.\n   */\n  readonly single_app_mode_enabled?: boolean\n  /**\n   * Indicates whether on/off switch labels are enabled in the system settings.\n   */\n  readonly on_off_switch_labels_enabled?: boolean\n  /**\n   * Indicates whether the Speak Screen feature is enabled.\n   */\n  readonly speak_screen_enabled?: boolean\n  /**\n   * Indicates whether the text-to-speech selection feature is enabled.\n   */\n  readonly speak_selection_enabled?: boolean\n  /**\n   * Indicates whether the right-to-left support is enabled.\n   */\n  readonly rtl_enabled?: boolean\n  [k: string]: unknown\n}\n"
  },
  {
    "path": "packages/rum-core/src/transport/formDataTransport.spec.ts",
    "content": "import { createIdentityEncoder, DeflateEncoderStreamId as CoreDeflateEncoderStreamId } from '@datadog/browser-core'\nimport { interceptRequests, readFormDataRequest } from '@datadog/browser-core/test'\nimport { LifeCycle } from '../domain/lifeCycle'\nimport { mockRumConfiguration } from '../../test'\nimport { createFormDataTransport } from './formDataTransport'\n\ndescribe('createFormDataTransport', () => {\n  function setup() {\n    const interceptor = interceptRequests()\n    const lifeCycle = new LifeCycle()\n    const transport = createFormDataTransport(\n      mockRumConfiguration(),\n      lifeCycle,\n      createIdentityEncoder,\n      CoreDeflateEncoderStreamId.REPLAY\n    )\n\n    return { interceptor, transport, lifeCycle }\n  }\n\n  it('should send event and attachments as FormData', async () => {\n    const { interceptor, transport } = setup()\n\n    const payload = {\n      event: { type: 'test-event', data: 'test-data' },\n      'attachment.json': { foo: 'bar' },\n    }\n\n    await transport.send(payload)\n\n    expect(interceptor.requests).toHaveSize(1)\n    expect(interceptor.requests[0].body).toBeInstanceOf(FormData)\n    expect(await readFormDataRequest(interceptor.requests[0])).toEqual(payload)\n  })\n})\n"
  },
  {
    "path": "packages/rum-core/src/transport/formDataTransport.ts",
    "content": "import type {\n  Uint8ArrayBuffer,\n  Encoder,\n  EncoderResult,\n  DeflateEncoderStreamId,\n  RawError,\n  Context,\n} from '@datadog/browser-core'\nimport { addTelemetryDebug, createHttpRequest, jsonStringify, objectEntries } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../domain/configuration'\nimport type { LifeCycle } from '../domain/lifeCycle'\nimport { LifeCycleEventType } from '../domain/lifeCycle'\n\n/**\n * transport payload consist of an event and one or more attachments\n */\nexport interface TransportPayload {\n  event: Context\n  [key: string]: Context\n}\n\nexport interface Transport<T extends TransportPayload> {\n  send: (data: T) => Promise<void>\n}\n\nexport function createFormDataTransport<T extends TransportPayload>(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  createEncoder: (streamId: DeflateEncoderStreamId) => Encoder,\n  streamId: DeflateEncoderStreamId\n) {\n  const reportError = (error: RawError) => {\n    lifeCycle.notify(LifeCycleEventType.RAW_ERROR_COLLECTED, { error })\n\n    // monitor-until: forever, to keep an eye on the errors reported to customers\n    addTelemetryDebug('Error reported to customer', { 'error.message': error.message })\n  }\n\n  const httpRequest = createHttpRequest([configuration.profilingEndpointBuilder], reportError)\n\n  const encoder = createEncoder(streamId)\n\n  return {\n    async send({ event, ...attachments }: T) {\n      const formData = new FormData()\n      const serializedEvent = jsonStringify(event)\n\n      if (!serializedEvent) {\n        throw new Error('Failed to serialize event')\n      }\n\n      formData.append('event', new Blob([serializedEvent], { type: 'application/json' }), 'event.json')\n\n      let bytesCount = serializedEvent.length\n\n      for (const [key, value] of objectEntries(attachments as Record<string, Context>)) {\n        const serializedValue = jsonStringify(value)\n\n        if (!serializedValue) {\n          throw new Error('Failed to serialize attachment')\n        }\n\n        const result = await encode(encoder, serializedValue)\n\n        bytesCount += result.outputBytesCount\n        formData.append(key, new Blob([result.output]), key)\n      }\n\n      httpRequest.send({\n        data: formData,\n        bytesCount,\n      })\n    },\n  }\n}\n\nfunction encode<T extends string | Uint8ArrayBuffer>(encoder: Encoder<T>, data: string): Promise<EncoderResult<T>> {\n  return new Promise((resolve) => {\n    encoder.write(data)\n\n    encoder.finish((encoderResult) => {\n      resolve(encoderResult)\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/src/transport/startRumBatch.ts",
    "content": "import type { Observable, RawError, PageMayExitEvent, Encoder } from '@datadog/browser-core'\nimport { createBatch, createFlushController, createHttpRequest, DeflateEncoderStreamId } from '@datadog/browser-core'\nimport type { RumConfiguration } from '../domain/configuration'\nimport type { LifeCycle } from '../domain/lifeCycle'\nimport { LifeCycleEventType } from '../domain/lifeCycle'\nimport type { AssembledRumEvent } from '../rawRumEvent.types'\nimport { RumEventType } from '../rawRumEvent.types'\n\nexport function startRumBatch(\n  configuration: RumConfiguration,\n  lifeCycle: LifeCycle,\n  reportError: (error: RawError) => void,\n  pageMayExitObservable: Observable<PageMayExitEvent>,\n  sessionExpireObservable: Observable<void>,\n  createEncoder: (streamId: DeflateEncoderStreamId) => Encoder\n) {\n  const endpoints = [configuration.rumEndpointBuilder]\n  if (configuration.replica) {\n    endpoints.push(configuration.replica.rumEndpointBuilder)\n  }\n\n  const batch = createBatch({\n    encoder: createEncoder(DeflateEncoderStreamId.RUM),\n    request: createHttpRequest(endpoints, reportError),\n    flushController: createFlushController({\n      pageMayExitObservable,\n      sessionExpireObservable,\n    }),\n  })\n\n  lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, (serverRumEvent: AssembledRumEvent) => {\n    if (serverRumEvent.type === RumEventType.VIEW) {\n      batch.upsert(serverRumEvent, serverRumEvent.view.id)\n    } else {\n      batch.add(serverRumEvent)\n    }\n  })\n\n  return batch\n}\n"
  },
  {
    "path": "packages/rum-core/src/transport/startRumEventBridge.ts",
    "content": "import { getEventBridge } from '@datadog/browser-core'\nimport type { LifeCycle } from '../domain/lifeCycle'\nimport { LifeCycleEventType } from '../domain/lifeCycle'\nimport type { RumEvent } from '../rumEvent.types'\n\nexport function startRumEventBridge(lifeCycle: LifeCycle) {\n  const bridge = getEventBridge<'rum', RumEvent>()!\n\n  lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, (serverRumEvent) => {\n    bridge.send('rum', serverRumEvent)\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/test/allJsonSchemas.d.ts",
    "content": "export const allJsonSchemas: object[]\n"
  },
  {
    "path": "packages/rum-core/test/allJsonSchemas.js",
    "content": "/* global require */\n\n// This file is not in TypeScript because it uses 'require.context', and we cannot type it\n// correctly because:\n//\n// * We don't want to declare this type as a global (via TS `declare global`), because it would be\n// declared all across the project.\n//\n// * We can't use something like `(globalThis as Something).require.context` because Webpack is\n// looking for `require.context` as a standalone statement at build time.\n\nconst requireSchema = require.context(\n  '../../../rum-events-format/schemas',\n  true /* use sub directories */,\n  /\\.json*$/,\n  'sync'\n)\n\nexport const allJsonSchemas = requireSchema.keys().map(requireSchema)\n"
  },
  {
    "path": "packages/rum-core/test/createFakeClick.ts",
    "content": "import { clocksNow, Observable, timeStampNow } from '@datadog/browser-core'\nimport { createNewEvent } from '@datadog/browser-core/test'\nimport type { Click } from '../src/domain/action/trackClickActions'\nimport type { MouseEventOnElement, UserActivity } from '../src/domain/action/listenActionEvents'\n\nexport type FakeClick = Readonly<ReturnType<typeof createFakeClick>>\n\nexport function createFakeClick({\n  hasError = false,\n  hasPageActivity = true,\n  userActivity,\n  event,\n}: {\n  hasError?: boolean\n  hasPageActivity?: boolean\n  userActivity?: Partial<UserActivity>\n  event?: Partial<MouseEventOnElement>\n} = {}) {\n  const stopObservable = new Observable<void>()\n  let isStopped = false\n\n  function clone() {\n    return createFakeClick({ userActivity, event })\n  }\n\n  return {\n    stopObservable,\n    isStopped: () => isStopped,\n    stop: () => {\n      isStopped = true\n      stopObservable.notify()\n    },\n    discard: jasmine.createSpy(),\n    validate: jasmine.createSpy(),\n    startClocks: clocksNow(),\n    hasError,\n    hasPageActivity,\n    getUserActivity: () => ({\n      selection: false,\n      input: false,\n      scroll: false,\n      ...userActivity,\n    }),\n    addFrustration: jasmine.createSpy<Click['addFrustration']>(),\n    clone: jasmine.createSpy<typeof clone>().and.callFake(clone),\n\n    event: createNewEvent('pointerup', {\n      clientX: 100,\n      clientY: 100,\n      timeStamp: timeStampNow(),\n      target: document.body,\n      ...event,\n    }),\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/test/dom.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\n\nexport function appendText(text: string, container: Element | ShadowRoot = document.body): Text {\n  const textNode = document.createTextNode(text)\n  container.appendChild(textNode)\n\n  registerCleanupTask(() => {\n    textNode.parentElement?.removeChild(textNode)\n  })\n\n  return textNode\n}\n\nexport function appendElement(html: string, container: Element | ShadowRoot = document.body): HTMLElement {\n  const tmp = document.createElement('div')\n  tmp.innerHTML = html.trim()\n\n  const target = tmp.querySelector('[target]') || tmp.children[0]\n  const nodes = Array.from(tmp.childNodes)\n\n  // Remove 'target' attributes as it's just used for easily selecting an element, but it might\n  // interfer with test assertions.\n  if (target?.getAttribute('target') === '') {\n    target.removeAttribute('target')\n  }\n\n  nodes.forEach((node) => container.appendChild(node))\n\n  registerCleanupTask(() => {\n    nodes.forEach((node) => node.parentNode?.removeChild(node))\n  })\n\n  return target as HTMLElement\n}\n"
  },
  {
    "path": "packages/rum-core/test/emulate/mockDocumentReadyState.ts",
    "content": "import { DOM_EVENT } from '@datadog/browser-core'\nimport { createNewEvent } from '../../../core/test'\n\nexport function mockDocumentReadyState() {\n  let readyState: DocumentReadyState = 'loading'\n  spyOnProperty(Document.prototype, 'readyState', 'get').and.callFake(() => readyState)\n  return {\n    triggerOnDomLoaded: () => {\n      readyState = 'interactive'\n      window.dispatchEvent(createNewEvent(DOM_EVENT.DOM_CONTENT_LOADED))\n    },\n    triggerOnLoad: () => {\n      readyState = 'complete'\n      window.dispatchEvent(createNewEvent(DOM_EVENT.LOAD))\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/test/emulate/mockGlobalPerformanceBuffer.ts",
    "content": "export interface GlobalPerformanceBufferMock {\n  addPerformanceEntry: (entry: PerformanceEntry) => void\n}\n\nexport function mockGlobalPerformanceBuffer(initialEntries: PerformanceEntry[] = []): GlobalPerformanceBufferMock {\n  const performanceEntries: PerformanceEntry[] = initialEntries\n\n  spyOn(performance, 'getEntries').and.callFake(() => performanceEntries.slice())\n  spyOn(performance, 'getEntriesByName').and.callFake((name) =>\n    performanceEntries.filter((entry) => entry.name === name)\n  )\n  spyOn(performance, 'getEntriesByType').and.callFake((type) =>\n    performanceEntries.filter((entry) => entry.entryType === type)\n  )\n\n  return {\n    addPerformanceEntry: (entry) => performanceEntries.push(entry),\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/test/emulate/mockPerformanceObserver.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\nimport { objectValues } from '@datadog/browser-core'\nimport { RumPerformanceEntryType, type RumPerformanceEntry } from '../../src/browser/performanceObservable'\nimport { mockGlobalPerformanceBuffer } from './mockGlobalPerformanceBuffer'\n\nexport function mockPerformanceObserver({\n  typeSupported = true,\n  emulateAllEntryTypesUnsupported = false,\n  supportedEntryTypes = objectValues(RumPerformanceEntryType),\n} = {}) {\n  const originalPerformanceObserver = window.PerformanceObserver\n  const instances = new Set<MockPerformanceObserver>()\n\n  const { addPerformanceEntry } = mockGlobalPerformanceBuffer([])\n\n  class MockPerformanceObserver {\n    static supportedEntryTypes = supportedEntryTypes\n\n    public entryTypes: string[] = []\n\n    constructor(public callback: PerformanceObserverCallback) {}\n\n    disconnect() {\n      instances.delete(this)\n    }\n\n    observe({ entryTypes, type, buffered }: PerformanceObserverInit) {\n      if (!typeSupported && type) {\n        throw new TypeError(\"Failed to execute 'observe' on 'PerformanceObserver\")\n      }\n      if (emulateAllEntryTypesUnsupported) {\n        throw new TypeError('entryTypes contained only unsupported types')\n      }\n      this.entryTypes = entryTypes || (type ? [type] : [])\n      instances.add(this)\n      if (buffered) {\n        for (const entryType of this.entryTypes) {\n          notify(this, performance.getEntriesByType(entryType) as RumPerformanceEntry[])\n        }\n      }\n    }\n\n    takeRecords() {\n      return []\n    }\n  }\n\n  window.PerformanceObserver = MockPerformanceObserver\n\n  registerCleanupTask(() => {\n    window.PerformanceObserver = originalPerformanceObserver\n    instances.clear()\n  })\n\n  function notify(observer: MockPerformanceObserver, entries: RumPerformanceEntry[]) {\n    const filteredEntries = entries.filter((entry) => observer.entryTypes.includes(entry.entryType))\n    if (!filteredEntries.length) {\n      return\n    }\n    observer.callback(\n      {\n        getEntries: () => filteredEntries as PerformanceEntryList,\n        getEntriesByName: () => filteredEntries as PerformanceEntryList,\n        getEntriesByType: () => filteredEntries as PerformanceEntryList,\n      },\n      observer\n    )\n  }\n\n  return {\n    notifyPerformanceEntries: (entries: RumPerformanceEntry[]) => {\n      for (const entry of entries) {\n        addPerformanceEntry(entry as PerformanceEntry)\n      }\n      instances.forEach((instance) => notify(instance, entries))\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/test/fixtures.ts",
    "content": "import type { Context, Duration, RelativeTime, ServerDuration, TimeStamp } from '@datadog/browser-core'\nimport { combine, ErrorHandling, ErrorSource, generateUUID, relativeNow, ResourceType } from '@datadog/browser-core'\nimport type { RumMutationRecord } from '@datadog/browser-rum-core'\nimport {\n  type RumPerformanceEntry,\n  type RumLayoutShiftAttribution,\n  type EntryTypeToReturnType,\n  RumPerformanceEntryType,\n} from '../src/browser/performanceObservable'\nimport type { RawRumEvent } from '../src/rawRumEvent.types'\nimport { VitalType, ActionType, RumEventType, ViewLoadingType, RumLongTaskEntryType } from '../src/rawRumEvent.types'\n\nexport function createRawRumEvent(type: RumEventType, overrides?: Context): RawRumEvent {\n  switch (type) {\n    case RumEventType.ACTION:\n      return combine(\n        {\n          type,\n          action: {\n            id: generateUUID(),\n            target: {\n              name: 'target',\n            },\n            type: ActionType.CUSTOM,\n          },\n          date: 0 as TimeStamp,\n        },\n        overrides\n      )\n    case RumEventType.VITAL:\n      return combine(\n        {\n          type,\n          date: 0 as TimeStamp,\n          vital: {\n            id: generateUUID(),\n            type: VitalType.DURATION,\n            name: 'timing',\n            duration: 0 as ServerDuration,\n          },\n        },\n        overrides\n      )\n    case RumEventType.LONG_TASK:\n      return combine(\n        {\n          type,\n          date: 0 as TimeStamp,\n          long_task: {\n            id: generateUUID(),\n            duration: 0 as ServerDuration,\n            entry_type: RumLongTaskEntryType.LONG_TASK,\n          },\n          _dd: {\n            discarded: false,\n          },\n        },\n        overrides\n      )\n    case RumEventType.ERROR:\n      return combine(\n        {\n          type,\n          date: 0 as TimeStamp,\n          error: {\n            id: generateUUID(),\n            message: 'oh snap',\n            source: ErrorSource.SOURCE,\n            handling: ErrorHandling.HANDLED,\n            source_type: 'browser',\n            causes: [],\n          },\n        },\n        overrides\n      )\n    case RumEventType.RESOURCE:\n      return combine(\n        {\n          type,\n          date: 0 as TimeStamp,\n          resource: {\n            id: generateUUID(),\n            duration: 0 as ServerDuration,\n            type: ResourceType.OTHER,\n            url: 'http://foo.bar',\n          },\n          _dd: {\n            discarded: false,\n          },\n        },\n        overrides\n      )\n    case RumEventType.VIEW:\n      return combine(\n        {\n          type,\n          _dd: {\n            document_version: 0,\n            configuration: {\n              start_session_replay_recording_manually: false,\n            },\n          },\n          date: 0 as TimeStamp,\n          view: {\n            id: generateUUID(),\n            action: { count: 0 },\n            frustration: { count: 0 },\n            error: { count: 0 },\n            is_active: true,\n            loading_type: ViewLoadingType.INITIAL_LOAD,\n            long_task: { count: 0 },\n            resource: { count: 0 },\n            time_spent: 0 as ServerDuration,\n          },\n          session: {\n            has_replay: undefined,\n            is_active: undefined,\n          },\n        },\n        overrides\n      )\n  }\n}\n\nexport function createPerformanceEntry<T extends RumPerformanceEntryType>(\n  entryType: T,\n  overrides?: Partial<EntryTypeToReturnType[T]>\n): EntryTypeToReturnType[T] {\n  type OmitToJSON<T> = T extends any ? Omit<T, 'toJSON'> : never\n  let entry: OmitToJSON<RumPerformanceEntry>\n\n  switch (entryType) {\n    case RumPerformanceEntryType.EVENT:\n      entry = {\n        entryType: RumPerformanceEntryType.EVENT,\n        startTime: 1000 as RelativeTime,\n        processingStart: 1100 as RelativeTime,\n        processingEnd: 1200 as RelativeTime,\n        duration: 200 as Duration,\n        name: 'click',\n      }\n      break\n\n    case RumPerformanceEntryType.FIRST_INPUT:\n      entry = {\n        entryType: RumPerformanceEntryType.FIRST_INPUT,\n        startTime: 1000 as RelativeTime,\n        processingStart: 1100 as RelativeTime,\n        processingEnd: 1200 as RelativeTime,\n        duration: 200 as Duration,\n      }\n      break\n\n    case RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT:\n      entry = {\n        entryType: RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT,\n        startTime: 789 as RelativeTime,\n        size: 10,\n      }\n      break\n\n    case RumPerformanceEntryType.LAYOUT_SHIFT:\n      entry = {\n        entryType: RumPerformanceEntryType.LAYOUT_SHIFT,\n        startTime: relativeNow(),\n        hadRecentInput: false,\n        value: 0.1,\n        sources: [] as RumLayoutShiftAttribution[],\n      }\n      break\n\n    case RumPerformanceEntryType.PAINT:\n      entry = {\n        entryType: RumPerformanceEntryType.PAINT,\n        name: 'first-contentful-paint',\n        startTime: 123 as RelativeTime,\n      }\n      break\n\n    case RumPerformanceEntryType.LONG_TASK:\n      entry = {\n        name: 'self',\n        duration: 100 as Duration,\n        entryType: RumPerformanceEntryType.LONG_TASK,\n        startTime: 1234 as RelativeTime,\n      }\n      break\n\n    case RumPerformanceEntryType.LONG_ANIMATION_FRAME:\n      entry = {\n        name: 'long-animation-frame',\n        entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,\n        startTime: 1234 as RelativeTime,\n        duration: 82 as Duration,\n        renderStart: 1421.5 as RelativeTime,\n        styleAndLayoutStart: 1428 as RelativeTime,\n        firstUIEventTimestamp: 0 as RelativeTime,\n        blockingDuration: 0 as Duration,\n        scripts: [\n          {\n            name: 'script',\n            entryType: 'script',\n            startTime: 1348 as RelativeTime,\n            duration: 6 as Duration,\n            invoker: 'http://example.com/script.js',\n            invokerType: 'classic-script',\n            windowAttribution: 'self',\n            executionStart: 1348.7 as RelativeTime,\n            forcedStyleAndLayoutDuration: 0 as Duration,\n            pauseDuration: 0 as Duration,\n            sourceURL: 'http://example.com/script.js',\n            sourceFunctionName: '',\n            sourceCharPosition: 9876,\n            window,\n          },\n        ],\n      }\n      break\n\n    case RumPerformanceEntryType.NAVIGATION:\n    case RumPerformanceEntryType.RESOURCE:\n      {\n        const baseEntry = {\n          connectEnd: 200 as RelativeTime,\n          connectStart: 200 as RelativeTime,\n          renderBlockingStatus: 'non-blocking',\n          deliveryType: 'cache' as const,\n          domainLookupEnd: 200 as RelativeTime,\n          domainLookupStart: 200 as RelativeTime,\n          workerStart: 200 as RelativeTime,\n          fetchStart: 200 as RelativeTime,\n          name: 'https://resource.com/valid',\n          redirectEnd: 200 as RelativeTime,\n          redirectStart: 200 as RelativeTime,\n          requestStart: 200 as RelativeTime,\n          responseEnd: 300 as RelativeTime,\n          responseStart: 200 as RelativeTime,\n          secureConnectionStart: 200 as RelativeTime,\n          responseStatus: 200,\n          nextHopProtocol: 'HTTP/1.0',\n          decodedBodySize: 1000,\n          encodedBodySize: 500,\n          transferSize: 500,\n        }\n        if (entryType === RumPerformanceEntryType.NAVIGATION) {\n          entry = {\n            ...baseEntry,\n            entryType: RumPerformanceEntryType.NAVIGATION,\n            initiatorType: 'navigation' as const,\n            startTime: 0 as RelativeTime,\n            responseStart: 123 as RelativeTime,\n            domComplete: 456 as RelativeTime,\n            domContentLoadedEventEnd: 345 as RelativeTime,\n            domInteractive: 234 as RelativeTime,\n            loadEventEnd: 567 as RelativeTime,\n            duration: 567 as Duration,\n          }\n        } else {\n          entry = {\n            ...baseEntry,\n            entryType: RumPerformanceEntryType.RESOURCE,\n            initiatorType: 'img' as const,\n            startTime: 200 as RelativeTime,\n            duration: 100 as Duration,\n          }\n        }\n      }\n      break\n\n    case RumPerformanceEntryType.VISIBILITY_STATE:\n      entry = {\n        entryType: RumPerformanceEntryType.VISIBILITY_STATE,\n        name: 'visible',\n        startTime: 0 as RelativeTime,\n      }\n      break\n\n    default:\n      throw new Error(`Unsupported entryType fixture: ${entryType}`)\n  }\n\n  Object.assign(entry, overrides)\n\n  const fullEntry = {\n    ...entry,\n    toJSON: () => entry,\n  }\n  return fullEntry as EntryTypeToReturnType[T]\n}\n\nexport function createMutationRecord<T extends RumMutationRecord['type']>(\n  type: T = 'childList' as T,\n  overrides: Partial<Exclude<RumMutationRecord, { type: T }>> = {}\n): RumMutationRecord {\n  return {\n    type,\n    target: document.body,\n\n    ...overrides,\n  } as RumMutationRecord\n}\n"
  },
  {
    "path": "packages/rum-core/test/formatValidation.ts",
    "content": "import ajv from 'ajv'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport type { TimeStamp, Context } from '@datadog/browser-core'\nimport { combine } from '@datadog/browser-core'\nimport type { CommonProperties } from '@datadog/browser-rum-core'\nimport type { LifeCycle, RawRumEventCollectedData } from '../src/domain/lifeCycle'\nimport { LifeCycleEventType } from '../src/domain/lifeCycle'\nimport type { RawRumEvent } from '../src/rawRumEvent.types'\nimport { allJsonSchemas } from './allJsonSchemas'\n\nexport function collectAndValidateRawRumEvents(lifeCycle: LifeCycle) {\n  const rawRumEvents: Array<RawRumEventCollectedData<RawRumEvent>> = []\n  const subscription = lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, (data) => {\n    rawRumEvents.push(data)\n    validateRumEventFormat(data.rawRumEvent)\n  })\n  registerCleanupTask(() => {\n    subscription.unsubscribe()\n  })\n\n  return rawRumEvents\n}\n\nfunction validateRumEventFormat(rawRumEvent: RawRumEvent) {\n  const fakeId = '00000000-aaaa-0000-aaaa-000000000000'\n  const fakeContext: Partial<CommonProperties> = {\n    _dd: {\n      format_version: 2,\n      drift: 0,\n      configuration: {\n        session_sample_rate: 40,\n        session_replay_sample_rate: 60,\n        profiling_sample_rate: 0,\n      },\n    },\n    application: {\n      id: fakeId,\n    },\n    date: 0 as TimeStamp,\n    source: 'browser',\n    session: {\n      id: fakeId,\n      type: 'user',\n    },\n    view: {\n      id: fakeId,\n      referrer: '',\n      url: 'fake url',\n    },\n    connectivity: {\n      status: 'connected',\n      interfaces: ['wifi'],\n      effective_type: '4g',\n    },\n    context: {},\n  }\n  validateRumFormat(combine(fakeContext as CommonProperties & Context, rawRumEvent))\n}\n\nfunction validateRumFormat(rumEvent: Context) {\n  const instance = new ajv({\n    allErrors: true,\n  })\n\n  instance.addSchema(allJsonSchemas)\n\n  void instance.validate('rum-events-schema.json', rumEvent)\n\n  if (instance.errors) {\n    const errors = instance.errors\n      .map((error) => {\n        let message = error.message\n        if (error.keyword === 'const') {\n          message += ` ${formatAllowedValues([error.params.allowedValue])}`\n        }\n        if (error.keyword === 'enum') {\n          message += ` ${formatAllowedValues(error.params.allowedValues)}`\n        }\n        if (error.keyword === 'additionalProperties') {\n          message += ` ${formatAllowedValues([error.params.additionalProperty])}`\n        }\n        return `  event${error.instancePath || ''} ${message}`\n      })\n      .join('\\n')\n    fail(`Invalid RUM event format:\\n${errors}`)\n  }\n}\n\nfunction formatAllowedValues(allowedValues: string[]) {\n  return allowedValues.map((v) => `'${v}'`).join(', ')\n}\n"
  },
  {
    "path": "packages/rum-core/test/index.ts",
    "content": "export * from './createFakeClick'\nexport * from './dom'\nexport * from './fixtures'\nexport * from './formatValidation'\nexport * from './mockCiVisibilityValues'\nexport * from './mockRumSessionManager'\nexport * from './noopRecorderApi'\nexport * from './noopProfilerApi'\nexport * from './emulate/mockPerformanceObserver'\nexport * from './emulate/mockDocumentReadyState'\nexport * from './emulate/mockGlobalPerformanceBuffer'\nexport * from './mockPageStateHistory'\nexport * from './mockRumConfiguration'\nexport * from './locationChangeSetup'\nexport * from './mockContexts'\n"
  },
  {
    "path": "packages/rum-core/test/locationChangeSetup.ts",
    "content": "import { buildLocation, replaceMockable } from '@datadog/browser-core/test'\nimport { Observable } from '@datadog/browser-core'\nimport type { LocationChange } from '../src/browser/locationChangeObservable'\n\nexport function setupLocationObserver(initialLocation?: string) {\n  const fakeLocation = initialLocation ? buildLocation(initialLocation) : location\n  const locationChangeObservable = new Observable<LocationChange>()\n\n  replaceMockable(location, fakeLocation)\n\n  function changeLocation(to: string) {\n    const currentLocation = { ...fakeLocation }\n    Object.assign(fakeLocation, buildLocation(to, fakeLocation.href))\n    locationChangeObservable.notify({\n      oldLocation: currentLocation as Location,\n      newLocation: fakeLocation,\n    })\n  }\n\n  return { locationChangeObservable, changeLocation }\n}\n"
  },
  {
    "path": "packages/rum-core/test/mockCiVisibilityValues.ts",
    "content": "import { ONE_MINUTE, resetInitCookies, deleteCookie, setCookie } from '@datadog/browser-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\nimport { CI_VISIBILITY_TEST_ID_COOKIE_NAME, type CiTestWindow } from '../src/domain/contexts/ciVisibilityContext'\n\n// Duration to create a cookie lasting at least until the end of the test\nconst COOKIE_DURATION = ONE_MINUTE\n\nexport function mockCiVisibilityValues(testExecutionId: unknown, method: 'globals' | 'cookies' = 'globals') {\n  switch (method) {\n    case 'globals':\n      ;(window as CiTestWindow).Cypress = {\n        env: (key: string) => {\n          if (typeof testExecutionId === 'string' && key === 'traceId') {\n            return testExecutionId\n          }\n        },\n      }\n\n      break\n    case 'cookies':\n      if (typeof testExecutionId === 'string') {\n        setCookie(CI_VISIBILITY_TEST_ID_COOKIE_NAME, testExecutionId, COOKIE_DURATION)\n      }\n      break\n  }\n  resetInitCookies()\n\n  registerCleanupTask(() => {\n    delete (window as CiTestWindow).Cypress\n    deleteCookie(CI_VISIBILITY_TEST_ID_COOKIE_NAME)\n    resetInitCookies()\n  })\n}\n"
  },
  {
    "path": "packages/rum-core/test/mockContexts.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { UrlContexts } from '../src/domain/contexts/urlContexts'\nimport type { ViewHistory, ViewHistoryEntry } from '../src/domain/contexts/viewHistory'\n\nexport function mockUrlContexts(fakeLocation: Location = location): UrlContexts {\n  return {\n    findUrl: () => ({\n      url: fakeLocation.href,\n      referrer: document.referrer,\n    }),\n    stop: noop,\n  }\n}\n\nexport function mockViewHistory(view?: Partial<ViewHistoryEntry>): ViewHistory {\n  return {\n    findView: () => view as ViewHistoryEntry,\n    stop: noop,\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/test/mockPageStateHistory.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { PageStateHistory } from '../src/domain/contexts/pageStateHistory'\n\nexport function mockPageStateHistory(partialPageStateHistory?: Partial<PageStateHistory>): PageStateHistory {\n  const pageStateHistory: PageStateHistory = {\n    addPageState: noop,\n    stop: noop,\n    wasInPageStateDuringPeriod: () => false,\n    ...partialPageStateHistory,\n  }\n\n  return pageStateHistory\n}\n"
  },
  {
    "path": "packages/rum-core/test/mockRumConfiguration.ts",
    "content": "import { SPEC_ENDPOINTS } from '@datadog/browser-core/test'\nimport type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { validateAndBuildRumConfiguration } from '../src/domain/configuration'\n\nexport function mockRumConfiguration(partialConfig: Partial<RumConfiguration> = {}): RumConfiguration {\n  const FAKE_APP_ID = 'appId'\n  const baseConfig: RumConfiguration = {\n    ...validateAndBuildRumConfiguration({\n      clientToken: 'xxx',\n      applicationId: FAKE_APP_ID,\n      trackResources: true,\n      trackLongTasks: true,\n      trackAnonymousUser: true,\n    })!,\n    ...SPEC_ENDPOINTS,\n  }\n  return { ...baseConfig, ...partialConfig }\n}\n"
  },
  {
    "path": "packages/rum-core/test/mockRumSessionManager.ts",
    "content": "import { Observable } from '@datadog/browser-core'\nimport { SessionReplayState, type RumSessionManager } from '../src/domain/rumSessionManager'\n\nexport interface RumSessionManagerMock extends RumSessionManager {\n  setId(id: string): RumSessionManagerMock\n  setNotTracked(): RumSessionManagerMock\n  setTrackedWithoutSessionReplay(): RumSessionManagerMock\n  setTrackedWithSessionReplay(): RumSessionManagerMock\n  setForcedReplay(): RumSessionManagerMock\n}\n\nconst DEFAULT_ID = 'session-id'\nconst enum SessionStatus {\n  TRACKED_WITH_SESSION_REPLAY,\n  TRACKED_WITHOUT_SESSION_REPLAY,\n  NOT_TRACKED,\n  EXPIRED,\n}\n\nexport function createRumSessionManagerMock(): RumSessionManagerMock {\n  let id = DEFAULT_ID\n  let sessionStatus: SessionStatus = SessionStatus.TRACKED_WITH_SESSION_REPLAY\n  let forcedReplay: boolean = false\n  return {\n    findTrackedSession() {\n      if (\n        sessionStatus !== SessionStatus.TRACKED_WITH_SESSION_REPLAY &&\n        sessionStatus !== SessionStatus.TRACKED_WITHOUT_SESSION_REPLAY\n      ) {\n        return undefined\n      }\n      return {\n        id,\n        sessionReplay:\n          sessionStatus === SessionStatus.TRACKED_WITH_SESSION_REPLAY\n            ? SessionReplayState.SAMPLED\n            : forcedReplay\n              ? SessionReplayState.FORCED\n              : SessionReplayState.OFF,\n        anonymousId: 'device-123',\n      }\n    },\n    expire() {\n      sessionStatus = SessionStatus.EXPIRED\n      this.expireObservable.notify()\n    },\n    expireObservable: new Observable(),\n    setId(newId) {\n      id = newId\n      return this\n    },\n    setNotTracked() {\n      sessionStatus = SessionStatus.NOT_TRACKED\n      return this\n    },\n    setTrackedWithoutSessionReplay() {\n      sessionStatus = SessionStatus.TRACKED_WITHOUT_SESSION_REPLAY\n      return this\n    },\n    setTrackedWithSessionReplay() {\n      sessionStatus = SessionStatus.TRACKED_WITH_SESSION_REPLAY\n      return this\n    },\n    setForcedReplay() {\n      forcedReplay = true\n      return this\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-core/test/noopProfilerApi.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { ProfilerApi } from '@datadog/browser-rum-core'\n\nexport const noopProfilerApi: ProfilerApi = {\n  stop: noop,\n  onRumStart: noop,\n}\n"
  },
  {
    "path": "packages/rum-core/test/noopRecorderApi.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { RecorderApi } from '@datadog/browser-rum-core'\n\nexport const noopRecorderApi: RecorderApi = {\n  start: noop,\n  stop: noop,\n  isRecording: () => false,\n  onRumStart: noop,\n  getReplayStats: () => undefined,\n  getSessionReplayLink: () => undefined,\n}\n"
  },
  {
    "path": "packages/rum-nextjs/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-nextjs/README.md",
    "content": "# RUM Browser Monitoring - NEXTJS integration\n\n**Note**: This integration is in Preview. Features and configuration are subject to change.\n\n## Overview\n\nThe Datadog RUM Next.js integration provides framework-specific instrumentation to help you monitor and debug Next.js applications. This integration adds:\n\n- **Automatic route change detection** for both the App Router and Pages Router\n- **View name normalization** that converts dynamic route segments into parameterized names (e.g. `/users/123` becomes `/users/[id]`)\n- **Error reporting** with built-in components for Next.js error boundaries\n- **Full-stack visibility** by correlating frontend performance with backend traces and logs\n\nCombined with Datadog RUM's core capabilities, you can debug performance bottlenecks, track user journeys, monitor Core Web Vitals, and analyze every user session with context.\n\n## Setup\n\nStart by setting up [Datadog RUM][1] in your Next.js application:\n\n- If you are creating a RUM application, select **Next.js** as the application type.\n- If Next.js is not available as an option, select **React** and follow the steps below to integrate the plugin manually.\n\nAfter configuration, the Datadog App provides instructions for integrating the [RUM-Next.js plugin][2] with the Browser SDK.\n\nBoth routers require **Next.js v15.3+**, which supports the [`instrumentation-client`][3] file convention.\n\n## App router usage\n\n### 1. Create an `instrumentation-client.js` file in the root of your Next.js project\n\nInitialize the Datadog RUM SDK with the `nextjsPlugin` and re-export `onRouterTransitionStart` so Next.js can call it on client-side navigations:\n\n```js\nimport { datadogRum } from '@datadog/browser-rum'\nimport { nextjsPlugin, onRouterTransitionStart } from '@datadog/browser-rum-nextjs'\n\nexport { onRouterTransitionStart }\n\ndatadogRum.init({\n  applicationId: '<APP_ID>',\n  clientToken: '<CLIENT_TOKEN>',\n  site: 'datadoghq.com',\n  plugins: [nextjsPlugin()],\n})\n```\n\n### 2. Call the DatadogAppRouter component from your root layout.\n\n```tsx\n// app/layout.tsx\nimport { DatadogAppRouter } from '@datadog/browser-rum-nextjs'\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <DatadogAppRouter />\n        {children}\n      </body>\n    </html>\n  )\n}\n```\n\n### 3. Report errors from error boundaries\n\nNext.js uses [error boundaries](https://nextjs.org/docs/app/api-reference/file-conventions/error) (`error.tsx` files) to catch uncaught exceptions in each route segment. Use `addNextjsError` inside these boundaries to report errors to Datadog RUM.\n\nFor **Server Component** errors, Next.js sends a generic message to the client and attaches `error.digest`, a hash that links the client-side error to your server-side logs. For **Client Component** errors, `error.message` is the original message and `digest` is absent.\n\n```tsx\n// app/error.tsx (or app/dashboard/error.tsx, etc.)\n'use client'\n\nimport { useEffect } from 'react'\nimport { addNextjsError } from '@datadog/browser-rum-nextjs'\n\nexport default function Error({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {\n  useEffect(() => {\n    addNextjsError(error)\n  }, [error])\n\n  return <button onClick={reset}>Try again</button>\n}\n```\n\nFor errors in the **root layout**, use `global-error.tsx`; it must provide its own `<html>` and `<body>` tags since the root layout is replaced:\n\n```tsx\n// app/global-error.tsx\n'use client'\n\nimport { useEffect } from 'react'\nimport { addNextjsError } from '@datadog/browser-rum-nextjs'\n\nexport default function GlobalError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {\n  useEffect(() => {\n    addNextjsError(error)\n  }, [error])\n\n  return (\n    <html>\n      <body>\n        <button onClick={reset}>Try again</button>\n      </body>\n    </html>\n  )\n}\n```\n\n## Pages router usage\n\n### 1. Create an `instrumentation-client.js` file in the root of your Next.js project\n\nInitialize the Datadog RUM SDK with the `nextjsPlugin`. The `onRouterTransitionStart` export is **not needed** for Pages Router.\n\n```js\nimport { datadogRum } from '@datadog/browser-rum'\nimport { nextjsPlugin } from '@datadog/browser-rum-nextjs'\n\ndatadogRum.init({\n  applicationId: '<APP_ID>',\n  clientToken: '<CLIENT_TOKEN>',\n  site: 'datadoghq.com',\n  plugins: [nextjsPlugin()],\n})\n```\n\n### 2. Call the DatadogPagesRouter component from your custom App.\n\n```tsx\n// pages/_app.tsx\nimport type { AppProps } from 'next/app'\nimport { DatadogPagesRouter } from '@datadog/browser-rum-nextjs'\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  return (\n    <>\n      <DatadogPagesRouter />\n      <Component {...pageProps} />\n    </>\n  )\n}\n```\n\n### 3. Report errors from error boundaries\n\nUse the `ErrorBoundary` component in your custom App to catch React rendering errors and report them to Datadog RUM:\n\n```tsx\n// pages/_app.tsx\nimport type { AppProps } from 'next/app'\nimport { DatadogPagesRouter, ErrorBoundary } from '@datadog/browser-rum-nextjs'\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  return (\n    <>\n      <DatadogPagesRouter />\n      <ErrorBoundary\n        fallback={({ resetError }) => (\n          <div>\n            <p>Something went wrong</p>\n            <button onClick={resetError}>Try again</button>\n          </div>\n        )}\n      >\n        <Component {...pageProps} />\n      </ErrorBoundary>\n    </>\n  )\n}\n```\n\n## Route tracking\n\nThe `DatadogPagesRouter` and `DatadogAppRouter` components automatically track route changes and normalize dynamic segments into parameterized view names:\n\n| Actual URL             | View name                        |\n| ---------------------- | -------------------------------- |\n| `/about`               | `/about`                         |\n| `/users/123`           | `/users/[id]`                    |\n| `/users/123/posts/456` | `/users/[userId]/posts/[postId]` |\n| `/docs/a/b/c`          | `/docs/[...slug]`                |\n\n## Go further with Datadog Next.js integration\n\n### Traces\n\nConnect your RUM and trace data to get a complete view of your application's performance. See [Connect RUM and Traces][4].\n\n### Logs\n\nTo forward your Next.js application's logs to Datadog, see [JavaScript Logs Collection][5].\n\n### Metrics\n\nTo generate custom metrics from your RUM application, see [Generate Metrics][6].\n\n## Troubleshooting\n\nNeed help? Contact [Datadog Support][7].\n\n[1]: https://docs.datadoghq.com/real_user_monitoring/browser/setup/client\n[2]: https://www.npmjs.com/package/@datadog/browser-rum-nextjs\n[3]: https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation-client\n[4]: https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum\n[5]: https://docs.datadoghq.com/logs/log_collection/javascript/\n[6]: https://docs.datadoghq.com/real_user_monitoring/generate_metrics\n[7]: https://docs.datadoghq.com/help/\n"
  },
  {
    "path": "packages/rum-nextjs/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-nextjs\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.*\",\n    \"!src/**/*.specHelper.*\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\",\n    \"@datadog/browser-rum-react\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"next\": \">=13.0.0\",\n    \"react\": \">=18.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"next\": {\n      \"optional\": true\n    },\n    \"react\": {\n      \"optional\": true\n    }\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-nextjs\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"19.2.14\",\n    \"next\": \"16.2.3\",\n    \"react\": \"19.2.5\",\n    \"react-dom\": \"19.2.5\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/error/addNextjsError.spec.ts",
    "content": "import { registerCleanupTask } from '@datadog/browser-core/test'\nimport { resetNextjsPlugin } from '../nextjsPlugin'\nimport { initializeNextjsPlugin } from '../../../test/initializeNextjsPlugin'\nimport { addNextjsError } from './addNextjsError'\n\ndescribe('addNextjsError', () => {\n  it('does nothing when the plugin is not initialized', () => {\n    registerCleanupTask(() => {\n      resetNextjsPlugin()\n    })\n    expect(() => addNextjsError(new Error('test'))).not.toThrow()\n  })\n\n  it('delegates the error to addError', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const originalError = new Error('test error')\n\n    addNextjsError(originalError, { componentStack: 'at ComponentSpy toto.js' })\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith({\n      error: originalError,\n      handlingStack: jasmine.any(String),\n      componentStack: 'at ComponentSpy toto.js',\n      startClocks: jasmine.any(Object),\n      context: { framework: 'nextjs' },\n    })\n  })\n\n  it('merges dd_context from the original error with nextjs error context', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const originalError = new Error('error message')\n    ;(originalError as any).dd_context = { component: 'Menu', param: 123 }\n\n    addNextjsError(originalError, {})\n\n    expect(addErrorSpy).toHaveBeenCalledWith(\n      jasmine.objectContaining({\n        error: originalError,\n        context: {\n          framework: 'nextjs',\n          component: 'Menu',\n          param: 123,\n        },\n      })\n    )\n  })\n\n  it('adds nextjs.digest context when error.digest is present', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const error = Object.assign(new Error('server error'), { digest: 'abc123' })\n\n    addNextjsError(error, {})\n\n    expect(addErrorSpy.calls.mostRecent().args[0]).toEqual(\n      jasmine.objectContaining({\n        context: jasmine.objectContaining({ framework: 'nextjs', nextjs: { digest: 'abc123' } }),\n      })\n    )\n  })\n\n  it('omits nextjs key when digest is undefined', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const error = new Error('client error')\n\n    addNextjsError(error)\n\n    expect(addErrorSpy.calls.mostRecent().args[0]).toEqual(\n      jasmine.objectContaining({\n        context: { framework: 'nextjs' },\n      })\n    )\n  })\n\n  it('omits componentStack when errorInfo is missing', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const error = new Error('client error')\n\n    addNextjsError(error)\n\n    expect(addErrorSpy.calls.mostRecent().args[0]).toEqual(\n      jasmine.objectContaining({\n        componentStack: undefined,\n      })\n    )\n  })\n\n  it('does not let error.dd_context overwrite framework', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const error = Object.assign(new Error('test error'), { dd_context: { framework: 'from-dd-context' } })\n\n    addNextjsError(error, {})\n\n    expect(addErrorSpy.calls.mostRecent().args[0]).toEqual(\n      jasmine.objectContaining({\n        context: jasmine.objectContaining({ framework: 'nextjs' }),\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/error/addNextjsError.ts",
    "content": "import { callMonitored, clocksNow, createHandlingStack } from '@datadog/browser-core'\nimport type { Context } from '@datadog/browser-core'\nimport type { ErrorInfo } from 'react'\nimport { onRumStart } from '../nextjsPlugin'\n\n/**\n * Add a Next.js error to the RUM session.\n *\n * @category Error\n * @example\n * ```ts\n * // app/error.tsx (or app/global-error.tsx)\n * 'use client'\n * import { useEffect } from 'react'\n * import { addNextjsError } from '@datadog/browser-rum-nextjs'\n *\n * export default function Error({ error }: { error: Error & { digest?: string } }) {\n *   useEffect(() => {\n *     addNextjsError(error)\n *   }, [error])\n *   return <div>Something went wrong</div>\n * }\n * ```\n */\nexport function addNextjsError(error: Error & { digest?: string }, errorInfo?: ErrorInfo) {\n  const handlingStack = createHandlingStack('nextjs error')\n  const startClocks = clocksNow()\n  onRumStart((addError) => {\n    callMonitored(() => {\n      addError({\n        error,\n        handlingStack,\n        componentStack: errorInfo?.componentStack ?? undefined,\n        startClocks,\n        context: {\n          ...(error as Error & { dd_context?: Context }).dd_context,\n          ...(error.digest && { nextjs: { digest: error.digest } }),\n          framework: 'nextjs',\n        },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/error/errorBoundary.spec.tsx",
    "content": "import React from 'react'\n\nimport { disableJasmineUncaughtExceptionTracking, ignoreConsoleLogs } from '@datadog/browser-core/test'\nimport { appendComponent } from '../../../../rum-react/test/appendComponent'\nimport { initReactOldBrowsersSupport } from '../../../../rum-react/test/reactOldBrowsersSupport'\nimport { initializeNextjsPlugin } from '../../../test/initializeNextjsPlugin'\nimport { ErrorBoundary } from './errorBoundary'\n\n// Component behavior (renders children, fallback, resetError) is tested via createErrorBoundary\n// in packages/rum-react/src/domain/error/errorBoundary.spec.tsx\n\ndescribe('NextjsErrorBoundary', () => {\n  it('reports the error through addNextjsError', () => {\n    ignoreConsoleLogs('error', 'Error: error')\n    disableJasmineUncaughtExceptionTracking()\n    initReactOldBrowsersSupport()\n\n    const addErrorSpy = jasmine.createSpy()\n    initializeNextjsPlugin({ addError: addErrorSpy })\n    const originalError = new Error('error')\n    const ComponentSpy = jasmine.createSpy().and.throwError(originalError)\n    ;(ComponentSpy as any).displayName = 'ComponentSpy'\n\n    appendComponent(\n      <ErrorBoundary fallback={() => null}>\n        <ComponentSpy />\n      </ErrorBoundary>\n    )\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith(\n      jasmine.objectContaining({\n        error: originalError,\n        handlingStack: jasmine.any(String),\n        startClocks: jasmine.any(Object),\n        context: jasmine.objectContaining({\n          framework: 'nextjs',\n        }),\n        componentStack: jasmine.stringContaining('ComponentSpy'),\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/error/errorBoundary.ts",
    "content": "'use client'\nimport { createErrorBoundary } from '@datadog/browser-rum-react/internal'\nexport type { ErrorBoundaryFallback, ErrorBoundaryProps } from '@datadog/browser-rum-react/internal'\nimport { addNextjsError } from './addNextjsError'\n\n/**\n * ErrorBoundary component to report React errors to Datadog using the Next.js error context.\n *\n * For more advanced error handling, you can use the {@link addNextjsError} function.\n *\n * @category Error\n * @example\n * ```ts\n * import { ErrorBoundary } from '@datadog/browser-rum-nextjs'\n *\n * <ErrorBoundary fallback={() => null}>\n *   <Component />\n * </ErrorBoundary>\n * ```\n */\n// eslint-disable-next-line local-rules/disallow-side-effects\nexport const ErrorBoundary = createErrorBoundary(addNextjsError)\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/nextJSRouter/computeViewNameFromParams.spec.ts",
    "content": "import type { useParams } from 'next/navigation'\nimport { computeViewNameFromParams } from './computeViewNameFromParams'\n\ntype Params = ReturnType<typeof useParams>\n\ndescribe('computeViewNameFromParams', () => {\n  // prettier-ignore\n  const cases: Array<[string, string, Params, string]> = [\n    // [description,                              pathname,                params,                                    expected]\n    // Static routes\n    ['static path',                                '/about',                {},                                        '/about'],\n    ['nested static path',                         '/static/page',          {},                                        '/static/page'],\n    // Single dynamic segment\n    ['single dynamic segment',                     '/users/123',            { id: '123' },                             '/users/[id]'],\n    // Multiple dynamic segments\n    ['multiple dynamic segments',                  '/users/123/posts/456',  { userId: '123', postId: '456' },          '/users/[userId]/posts/[postId]'],\n    // Catch-all routes\n    ['catch-all with multiple segments',           '/docs/a/b/c',           { slug: ['a', 'b', 'c'] },                '/docs/[...slug]'],\n    ['catch-all with single segment',              '/docs/intro',           { slug: ['intro'] },                       '/docs/[...slug]'],\n    // Ordering\n    ['longer values replaced first',               '/items/123/1',          { id: '123', subId: '1' },                '/items/[id]/[subId]'],\n    // Param value is a substring of another segment\n    ['does not match inside a static segment',     '/product/pro',          { id: 'pro' },                             '/product/[id]'],\n    ['catch-all does not match partial segments',  '/docs-extra/a/b',       { slug: ['a', 'b'] },                      '/docs-extra/[...slug]'],\n    // Catch-all processed before regular params (prevents a shared value being consumed by the regular param first)\n    ['catch-all takes priority over same-value regular param', '/x/a/b', { id: 'a', slug: ['a', 'b'] }, '/x/[...slug]'],\n    // Repeated param values\n    ['same value for multiple params: assigned left-to-right', '/toto/toto', { user: 'toto', view: 'toto' }, '/[user]/[view]'],\n    ['param value appears in static segment: first occurrence taken', '/toto/toto', { user: 'toto' }, '/[user]/toto'],\n    // Edge cases\n    ['undefined param values ignored',             '/users/123',            { id: '123', optional: undefined },        '/users/[id]'],\n    ['empty string param values ignored',          '/users/123',            { id: '123', empty: '' },                  '/users/[id]'],\n    ['empty catch-all array ignored',              '/docs',                 { slug: [] },                              '/docs'],\n  ]\n\n  cases.forEach(([description, pathname, params, expected]) => {\n    it(`${description}: \"${pathname}\" → \"${expected}\"`, () => {\n      expect(computeViewNameFromParams(pathname, params)).toBe(expected)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/nextJSRouter/computeViewNameFromParams.ts",
    "content": "import type { useParams } from 'next/navigation'\n\ntype Params = ReturnType<typeof useParams>\n\nexport function computeViewNameFromParams(pathname: string, params: Params): string {\n  if (Object.keys(params).length === 0) {\n    return pathname\n  }\n\n  const segments = pathname.split('/')\n\n  // Process catch-all (array) params first to prevent their segments from being\n  // consumed by regular param replacements when values overlap.\n  for (const [paramName, paramValue] of Object.entries(params)) {\n    if (!Array.isArray(paramValue) || paramValue.length === 0) {\n      continue\n    }\n    for (let i = 0; i < segments.length; i++) {\n      if (i + paramValue.length <= segments.length && paramValue.every((v, j) => segments[i + j] === v)) {\n        segments.splice(i, paramValue.length, `[...${paramName}]`)\n        break\n      }\n    }\n  }\n\n  // Process regular (string) params greedily left-to-right.\n  // When multiple params share the same value, names are assigned left-to-right in param iteration order.\n  // When a param value also appears in a static segment, the leftmost occurrence is assumed to be dynamic.\n  for (const [paramName, paramValue] of Object.entries(params)) {\n    if (typeof paramValue !== 'string' || !paramValue) {\n      continue\n    }\n    const index = segments.indexOf(paramValue)\n    if (index !== -1) {\n      segments[index] = `[${paramName}]`\n    }\n  }\n\n  return segments.join('/')\n}\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/nextJSRouter/datadogAppRouter.tsx",
    "content": "'use client'\n\nimport { useRef } from 'react'\nimport { usePathname, useParams } from 'next/navigation'\nimport { mockable } from '@datadog/browser-core'\nimport { startNextjsView } from '../nextjsPlugin'\nimport { computeViewNameFromParams } from './computeViewNameFromParams'\n\nexport function DatadogAppRouter() {\n  const pathname = mockable(usePathname)()\n  const params = mockable(useParams)()\n  const previousPathname = mockable(useRef)<string | null>(null)\n\n  if (previousPathname.current !== pathname) {\n    previousPathname.current = pathname\n    startNextjsView(computeViewNameFromParams(pathname, params))\n  }\n\n  return null\n}\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/nextJSRouter/datadogPagesRouter.tsx",
    "content": "import { useRef } from 'react'\nimport { useRouter } from 'next/router'\nimport { mockable } from '@datadog/browser-core'\nimport { startNextjsView } from '../nextjsPlugin'\n\nexport function DatadogPagesRouter() {\n  const router = mockable(useRouter)()\n  const previousPath = mockable(useRef)<string | null>(null)\n\n  if (!router.isReady) {\n    return null\n  }\n\n  // Extract the path portion of asPath (without query params or hash) to detect navigations.\n  const path = router.asPath.split(/[?#]/)[0]\n\n  if (previousPath.current !== path) {\n    // router.pathname is the route pattern (e.g., \"/user/[id]\") — used as the view name\n    // router.asPath is the actual URL (e.g., \"/user/42\") — used to detect navigations between\n    // different concrete URLs of the same dynamic route (e.g., /user/42 → /user/43)\n    previousPath.current = path\n    startNextjsView(router.pathname)\n  }\n\n  return null\n}\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/nextjsPlugin.spec.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../core/test'\nimport {\n  nextjsPlugin,\n  startNextjsView,\n  onRumInit,\n  onRumStart,\n  onRouterTransitionStart,\n  resetNextjsPlugin,\n} from './nextjsPlugin'\n\nconst INIT_CONFIGURATION = {} as RumInitConfiguration\n\nfunction createPublicApi() {\n  const startViewSpy = jasmine.createSpy('startView')\n  return { publicApi: { startView: startViewSpy } as unknown as RumPublicApi, startViewSpy }\n}\n\nfunction initPlugin() {\n  const { publicApi, startViewSpy } = createPublicApi()\n  const plugin = nextjsPlugin()\n  plugin.onInit({ publicApi, initConfiguration: { ...INIT_CONFIGURATION } })\n  return { plugin, publicApi, startViewSpy }\n}\n\ndescribe('nextjsPlugin', () => {\n  beforeEach(() => {\n    registerCleanupTask(() => {\n      resetNextjsPlugin()\n    })\n  })\n\n  it('returns a plugin object', () => {\n    const plugin = nextjsPlugin()\n\n    expect(plugin).toEqual(\n      jasmine.objectContaining({\n        name: 'nextjs',\n        onInit: jasmine.any(Function),\n        onRumStart: jasmine.any(Function),\n      })\n    )\n  })\n\n  it('sets trackViewsManually to true', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    const { publicApi } = createPublicApi()\n\n    nextjsPlugin().onInit({ publicApi, initConfiguration })\n\n    expect(initConfiguration.trackViewsManually).toBe(true)\n  })\n\n  it('does not start a view on init', () => {\n    const { startViewSpy } = initPlugin()\n\n    expect(startViewSpy).not.toHaveBeenCalled()\n  })\n\n  it('delegates startNextjsView to publicApi.startView with name', () => {\n    const { startViewSpy } = initPlugin()\n\n    startNextjsView('/about')\n\n    expect(startViewSpy).toHaveBeenCalledOnceWith({ name: '/about', url: undefined })\n  })\n\n  it('uses onRouterTransitionStart URL when available', () => {\n    const { startViewSpy } = initPlugin()\n\n    onRouterTransitionStart('/about?foo=bar')\n    startNextjsView('/about')\n\n    expect(startViewSpy).toHaveBeenCalledOnceWith({\n      name: '/about',\n      url: `${window.location.origin}/about?foo=bar`,\n    })\n  })\n\n  it('clears onRouterTransitionStart URL after startNextjsView consumes it', () => {\n    const { startViewSpy } = initPlugin()\n\n    onRouterTransitionStart('/about')\n    startNextjsView('/about')\n    startNextjsView('/other')\n\n    expect(startViewSpy.calls.mostRecent().args[0]).toEqual({ name: '/other', url: undefined })\n  })\n\n  describe('lifecycle subscribers', () => {\n    it('calls onRumInit subscribers during onInit', () => {\n      const callbackSpy = jasmine.createSpy()\n      const { publicApi } = createPublicApi()\n      onRumInit(callbackSpy)\n\n      expect(callbackSpy).not.toHaveBeenCalled()\n\n      nextjsPlugin().onInit({\n        publicApi,\n        initConfiguration: INIT_CONFIGURATION,\n      })\n\n      expect(callbackSpy).toHaveBeenCalledTimes(1)\n      expect(callbackSpy.calls.mostRecent().args[0]).toBe(publicApi)\n    })\n\n    it('calls onRumInit subscriber immediately if already initialized', () => {\n      const callbackSpy = jasmine.createSpy()\n      const { publicApi } = createPublicApi()\n\n      nextjsPlugin().onInit({\n        publicApi,\n        initConfiguration: INIT_CONFIGURATION,\n      })\n\n      onRumInit(callbackSpy)\n\n      expect(callbackSpy).toHaveBeenCalledTimes(1)\n      expect(callbackSpy.calls.mostRecent().args[0]).toBe(publicApi)\n    })\n\n    it('calls onRumStart subscribers during onRumStart', () => {\n      const callbackSpy = jasmine.createSpy()\n      const mockAddError = jasmine.createSpy()\n      onRumStart(callbackSpy)\n\n      const { plugin } = initPlugin()\n      plugin.onRumStart({ addError: mockAddError })\n\n      expect(callbackSpy).toHaveBeenCalledWith(mockAddError)\n    })\n\n    it('calls onRumStart subscriber immediately if already started', () => {\n      const mockAddError = jasmine.createSpy()\n      const { plugin } = initPlugin()\n      plugin.onRumStart({ addError: mockAddError })\n\n      const callbackSpy = jasmine.createSpy()\n      onRumStart(callbackSpy)\n\n      expect(callbackSpy).toHaveBeenCalledWith(mockAddError)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-nextjs/src/domain/nextjsPlugin.ts",
    "content": "import { buildUrl } from '@datadog/browser-core'\nimport type { RumPlugin, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\n\nexport type NextjsPlugin = Pick<Required<RumPlugin>, 'name' | 'onInit' | 'onRumStart'>\n\ntype InitSubscriber = (rumPublicApi: RumPublicApi) => void\ntype StartSubscriber = (addError: StartRumResult['addError']) => void\n\nlet globalPublicApi: RumPublicApi | undefined\nlet globalAddError: StartRumResult['addError'] | undefined\nlet lastNavigationUrl: string | undefined\n\nconst onRumInitSubscribers: InitSubscriber[] = []\nconst onRumStartSubscribers: StartSubscriber[] = []\n\nexport function nextjsPlugin(): NextjsPlugin {\n  return {\n    name: 'nextjs',\n    onInit({ publicApi, initConfiguration }) {\n      globalPublicApi = publicApi\n      initConfiguration.trackViewsManually = true\n\n      for (const subscriber of onRumInitSubscribers) {\n        subscriber(publicApi)\n      }\n    },\n    onRumStart({ addError }) {\n      globalAddError = addError\n      if (addError) {\n        for (const subscriber of onRumStartSubscribers) {\n          subscriber(addError)\n        }\n      }\n    },\n  } satisfies RumPlugin\n}\n\nexport function startNextjsView(viewName: string) {\n  if (globalPublicApi) {\n    // Use the URL captured by onRouterTransitionStart if available, since React renders before pushState updates window.location\n    const url = lastNavigationUrl ? buildUrl(lastNavigationUrl, window.location.origin).href : undefined\n    lastNavigationUrl = undefined\n    globalPublicApi.startView({ name: viewName, url })\n  }\n}\n\n// Must be re-exported from the user's instrumentation-client.ts so we can capture the URL before React renders\nexport function onRouterTransitionStart(url: string) {\n  lastNavigationUrl = url\n}\n\nexport function onRumInit(callback: InitSubscriber) {\n  if (globalPublicApi) {\n    callback(globalPublicApi)\n  } else {\n    onRumInitSubscribers.push(callback)\n  }\n}\n\nexport function onRumStart(callback: StartSubscriber) {\n  if (globalAddError) {\n    callback(globalAddError)\n  } else {\n    onRumStartSubscribers.push(callback)\n  }\n}\n\nexport function resetNextjsPlugin() {\n  globalPublicApi = undefined\n  globalAddError = undefined\n  onRumInitSubscribers.length = 0\n  onRumStartSubscribers.length = 0\n  lastNavigationUrl = undefined\n}\n"
  },
  {
    "path": "packages/rum-nextjs/src/entries/main.ts",
    "content": "export { nextjsPlugin, onRouterTransitionStart } from '../domain/nextjsPlugin'\nexport type { NextjsPlugin } from '../domain/nextjsPlugin'\nexport { DatadogAppRouter } from '../domain/nextJSRouter/datadogAppRouter'\nexport { DatadogPagesRouter } from '../domain/nextJSRouter/datadogPagesRouter'\nexport { addNextjsError } from '../domain/error/addNextjsError'\nexport { ErrorBoundary } from '../domain/error/errorBoundary'\nexport type { ErrorBoundaryFallback, ErrorBoundaryProps } from '../domain/error/errorBoundary'\n"
  },
  {
    "path": "packages/rum-nextjs/test/initializeNextjsPlugin.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\nimport { noop } from '@datadog/browser-core'\nimport { nextjsPlugin, resetNextjsPlugin } from '../src/domain/nextjsPlugin'\nimport { registerCleanupTask } from '../../core/test'\n\nexport function initializeNextjsPlugin({\n  initConfiguration = {},\n  publicApi = {},\n  addError = noop,\n}: {\n  initConfiguration?: Partial<RumInitConfiguration>\n  publicApi?: Partial<RumPublicApi>\n  addError?: StartRumResult['addError']\n} = {}) {\n  resetNextjsPlugin()\n  const plugin = nextjsPlugin()\n\n  plugin.onInit({\n    publicApi: publicApi as RumPublicApi,\n    initConfiguration: initConfiguration as RumInitConfiguration,\n  })\n  plugin.onRumStart({\n    addError,\n  })\n\n  registerCleanupTask(() => {\n    resetNextjsPlugin()\n  })\n}\n"
  },
  {
    "path": "packages/rum-nextjs/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"jasmine\"],\n    \"allowImportingTsExtensions\": true,\n    \"noEmit\": true\n  },\n  \"include\": [\"src\", \"test\"]\n}\n"
  },
  {
    "path": "packages/rum-nuxt/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-nuxt/README.md",
    "content": "# RUM Browser Monitoring - Nuxt integration\n\nThis package provides Nuxt-specific integrations for Datadog Browser RUM.\n"
  },
  {
    "path": "packages/rum-nuxt/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-nuxt\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"nuxt\": \"3 || 4\",\n    \"vue\": \"^3.5.0\",\n    \"vue-router\": \"^4.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-slim\": {\n      \"optional\": true\n    },\n    \"nuxt\": {\n      \"optional\": true\n    },\n    \"vue\": {\n      \"optional\": true\n    },\n    \"vue-router\": {\n      \"optional\": true\n    }\n  },\n  \"devDependencies\": {\n    \"vue\": \"3.5.32\",\n    \"vue-router\": \"5.0.4\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-nuxt\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"private\": true,\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-nuxt/src/domain/nuxtPlugin.spec.ts",
    "content": "import type { Router } from 'vue-router'\nimport { createRouter, createMemoryHistory } from 'vue-router'\nimport type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../core/test'\nimport { nuxtRumPlugin, resetNuxtPlugin } from './nuxtPlugin'\n\nconst PUBLIC_API = { startView: jasmine.createSpy() } as unknown as RumPublicApi\nconst INIT_CONFIGURATION = {} as RumInitConfiguration\n\nfunction makeRouter(): Router {\n  return createRouter({ history: createMemoryHistory(), routes: [{ path: '/', component: {} }] })\n}\n\ndescribe('nuxtRumPlugin', () => {\n  beforeEach(() => {\n    registerCleanupTask(() => resetNuxtPlugin())\n  })\n\n  it('returns a plugin object with name \"nuxt\"', () => {\n    expect(nuxtRumPlugin({ router: makeRouter() })).toEqual(jasmine.objectContaining({ name: 'nuxt' }))\n  })\n\n  it('sets trackViewsManually to true', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n\n    nuxtRumPlugin({ router: makeRouter() }).onInit({ publicApi: PUBLIC_API, initConfiguration })\n\n    expect(initConfiguration.trackViewsManually).toBe(true)\n  })\n\n  it('returns configuration telemetry', () => {\n    expect(nuxtRumPlugin({ router: makeRouter() }).getConfigurationTelemetry()).toEqual({ router: true, nuxt: true })\n  })\n})\n"
  },
  {
    "path": "packages/rum-nuxt/src/domain/nuxtPlugin.ts",
    "content": "import type { RumPlugin, RumPublicApi } from '@datadog/browser-rum-core'\nimport type { Router } from 'vue-router'\nimport { startTrackingNuxtViews } from './router/nuxtRouter'\n\nexport type NuxtPlugin = Pick<Required<RumPlugin>, 'name' | 'onInit' | 'getConfigurationTelemetry'>\n\nexport interface NuxtPluginConfiguration {\n  router: Router\n}\n\ntype InitSubscriber = (rumPublicApi: RumPublicApi) => void\n\nlet globalPublicApi: RumPublicApi | undefined\n\nconst onRumInitSubscribers: InitSubscriber[] = []\n\nexport function nuxtRumPlugin(configuration: NuxtPluginConfiguration): NuxtPlugin {\n  return {\n    name: 'nuxt',\n    onInit({ publicApi, initConfiguration }) {\n      globalPublicApi = publicApi\n      initConfiguration.trackViewsManually = true\n      startTrackingNuxtViews(publicApi, configuration.router)\n\n      for (const subscriber of onRumInitSubscribers) {\n        subscriber(publicApi)\n      }\n    },\n    getConfigurationTelemetry() {\n      return { router: !!configuration.router, nuxt: true }\n    },\n  } satisfies RumPlugin\n}\n\nexport function onRumInit(callback: InitSubscriber) {\n  if (globalPublicApi) {\n    callback(globalPublicApi)\n  } else {\n    onRumInitSubscribers.push(callback)\n  }\n}\n\nexport function resetNuxtPlugin() {\n  globalPublicApi = undefined\n  onRumInitSubscribers.length = 0\n}\n"
  },
  {
    "path": "packages/rum-nuxt/src/domain/router/nuxtRouter.spec.ts",
    "content": "import { createRouter, createMemoryHistory } from 'vue-router'\nimport type { RouteLocationMatched } from 'vue-router'\nimport type { RumPublicApi } from '@datadog/browser-rum-core'\nimport { startTrackingNuxtViews, computeNuxtViewName } from './nuxtRouter'\n\nfunction makePublicApi(startViewSpy: jasmine.Spy) {\n  return { startView: startViewSpy } as unknown as RumPublicApi\n}\n\ndescribe('startTrackingNuxtViews', () => {\n  it('tracks the initial view via afterEach when router is not yet ready', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/', component: {} }],\n    })\n\n    startTrackingNuxtViews(makePublicApi(startViewSpy), router)\n    expect(startViewSpy).not.toHaveBeenCalled()\n\n    router\n      .push('/')\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledOnceWith('/')\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('tracks the initial view immediately when router is already ready', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/', component: {} }],\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        startTrackingNuxtViews(makePublicApi(startViewSpy), router)\n        expect(startViewSpy).toHaveBeenCalledOnceWith('/')\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('tracks subsequent navigations', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [\n        { path: '/', component: {} },\n        { path: '/about', component: {} },\n      ],\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        startTrackingNuxtViews(makePublicApi(startViewSpy), router)\n        startViewSpy.calls.reset()\n        return router.push('/about')\n      })\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledOnceWith('/about')\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('does not track a new view when navigation fails', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [\n        { path: '/', component: {} },\n        { path: '/protected', component: {} },\n      ],\n    })\n\n    router.beforeEach((to) => {\n      if (to.path === '/protected') {\n        return false\n      }\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        startTrackingNuxtViews(makePublicApi(startViewSpy), router)\n        startViewSpy.calls.reset()\n        return router.push('/protected')\n      })\n      .then(() => {\n        expect(startViewSpy).not.toHaveBeenCalled()\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('does not track a new view when only query params change', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/products', component: {} }],\n    })\n\n    router\n      .push('/products?page=1')\n      .then(() => {\n        startTrackingNuxtViews(makePublicApi(startViewSpy), router)\n        startViewSpy.calls.reset()\n        return router.push('/products?page=2')\n      })\n      .then(() => {\n        expect(startViewSpy).not.toHaveBeenCalled()\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('tracks a new view when the hash changes', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/products', component: {} }],\n    })\n\n    router\n      .push('/products?page=1')\n      .then(() => {\n        startTrackingNuxtViews(makePublicApi(startViewSpy), router)\n        startViewSpy.calls.reset()\n        return router.push('/products#details')\n      })\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledOnceWith('/products')\n        done()\n      })\n      .catch(done.fail)\n  })\n})\n\ndescribe('computeNuxtViewName', () => {\n  // prettier-ignore\n  const cases: Array<[string, Array<{ path: string }>, string]> = [\n    // description,                       matched paths,                          expected\n    ['empty matched array',               [],                                     ''],\n    ['static route',                      [{ path: '/about' }],                  '/about'],\n    ['dynamic param',                     [{ path: '/user/:id' }],               '/user/[id]'],\n    ['dynamic param with empty constraint',[{ path: '/user/:id()' }],            '/user/[id]'],\n    ['optional param',                    [{ path: '/:slug?' }],                 '/[[slug]]'],\n    ['optional nested param',             [{ path: '/blog/:slug?' }],            '/blog/[[slug]]'],\n    ['catch-all param',                   [{ path: '/guides/:slug(.*)*' }],      '/guides/[...slug]'],\n    ['nested catch-all param',            [{ path: '/docs/:slug([^/]*)*/edit' }], '/docs/[...slug]/edit'],\n    ['pathMatch catch-all',               [{ path: '/:pathMatch(.*)*' }],        '/[...pathMatch]'],\n    ['multiple segments',                 [{ path: '/a/:b/:c' }],                '/a/[b]/[c]'],\n    ['mixed static and dynamic segment',  [{ path: '/users-:group()' }],         '/users-[group]'],\n    ['mixed static and optional segment', [{ path: '/users-:group?' }],          '/users-[[group]]'],\n    ['multiple mixed params in one segment', [{ path: '/users-:group()-:id()' }], '/users-[group]-[id]'],\n    ['mixed static and dynamic directories', [{ path: '/users-:group()/:id()' }], '/users-[group]/[id]'],\n    ['static route unchanged',            [{ path: '/static/path' }],            '/static/path'],\n  ]\n\n  cases.forEach(([description, matched, expected]) => {\n    it(`returns \"${expected}\" for ${description}`, () => {\n      expect(computeNuxtViewName(matched as unknown as RouteLocationMatched[])).toBe(expected)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-nuxt/src/domain/router/nuxtRouter.ts",
    "content": "import type { Router, RouteLocationMatched } from 'vue-router'\nimport type { RumPublicApi } from '@datadog/browser-rum-core'\n\nconst TERMINAL_CATCH_ALL_PARAM = '(.*)*'\nconst NESTED_CATCH_ALL_PARAM = '([^/]*)*'\nconst NORMALIZE_NUXT_PATH_REGEXP = /\\\\(.)|:([\\w.]+)(\\(\\.\\*\\)\\*|\\(\\[\\^\\/\\]\\*\\)\\*|\\?|\\(\\))?/g\n\nexport function startTrackingNuxtViews(rumPublicApi: RumPublicApi, router: Router) {\n  if (router.currentRoute.value.matched.length > 0) {\n    rumPublicApi.startView(computeNuxtViewName(router.currentRoute.value.matched))\n  }\n\n  router.afterEach((to, from, failure) => {\n    if (failure) {\n      return\n    }\n    if (from.matched.length > 0 && to.path === from.path && to.hash === from.hash) {\n      return\n    }\n    rumPublicApi.startView(computeNuxtViewName(to.matched))\n  })\n}\n\nexport function computeNuxtViewName(matched: RouteLocationMatched[]): string {\n  const viewName = computeViewName(matched)\n  if (!viewName) {\n    return viewName\n  }\n\n  return normalizeNuxtPath(viewName)\n}\n\nfunction computeViewName(matched: RouteLocationMatched[]): string {\n  for (let index = matched.length - 1; index >= 0; index--) {\n    const path = matched[index].path\n    if (path) {\n      return path\n    }\n  }\n\n  return ''\n}\n\n// Nuxt generates Vue Router paths with parameter syntax (for example `:id()`, `:slug?`,\n// `:slug(.*)*`). Convert the normalized Vue Router path back to Nuxt's file-based syntax.\nfunction normalizeNuxtPath(path: string): string {\n  return path.replace(\n    NORMALIZE_NUXT_PATH_REGEXP,\n    (_match: string, escapedChar?: string, paramName?: string, suffix?: string): string => {\n      if (escapedChar !== undefined) {\n        return escapedChar\n      }\n      if (!paramName) {\n        return ''\n      }\n      if (suffix === TERMINAL_CATCH_ALL_PARAM || suffix === NESTED_CATCH_ALL_PARAM) {\n        return `[...${paramName}]`\n      }\n      if (suffix === '?') {\n        return `[[${paramName}]]`\n      }\n      return `[${paramName}]`\n    }\n  )\n}\n"
  },
  {
    "path": "packages/rum-nuxt/src/entries/main.ts",
    "content": "export type { NuxtPlugin, NuxtPluginConfiguration } from '../domain/nuxtPlugin'\nexport { nuxtRumPlugin } from '../domain/nuxtPlugin'\n"
  },
  {
    "path": "packages/rum-nuxt/test/initializeNuxtPlugin.ts",
    "content": "import type { Router } from 'vue-router'\nimport { createRouter, createMemoryHistory } from 'vue-router'\nimport type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport { nuxtRumPlugin, resetNuxtPlugin } from '../src/domain/nuxtPlugin'\nimport { registerCleanupTask } from '../../core/test'\n\nexport function initializeNuxtPlugin({\n  initConfiguration = {},\n  publicApi = {},\n  router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/', component: {} }] }),\n}: {\n  initConfiguration?: Partial<RumInitConfiguration>\n  publicApi?: Partial<RumPublicApi>\n  router?: Router\n} = {}) {\n  resetNuxtPlugin()\n  const plugin = nuxtRumPlugin({ router })\n\n  plugin.onInit({\n    publicApi: publicApi as RumPublicApi,\n    initConfiguration: initConfiguration as RumInitConfiguration,\n  })\n  registerCleanupTask(() => resetNuxtPlugin())\n}\n"
  },
  {
    "path": "packages/rum-react/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/rum-react/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-react/README.md",
    "content": "# RUM Browser Monitoring - React integration\n\nThis package provides React and React ecosystem integrations for Datadog Browser RUM.\n\nSee the [dedicated Datadog documentation][1] for more details.\n\n[1]: https://docs.datadoghq.com/integrations/rum_react\n"
  },
  {
    "path": "packages/rum-react/internal/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-react/internal\",\n  \"private\": true,\n  \"main\": \"../cjs/entries/internal.js\",\n  \"module\": \"../esm/entries/internal.js\",\n  \"types\": \"../cjs/entries/internal.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum-react/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-react\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"internal\",\n    \"react-router-v6\",\n    \"react-router-v7\",\n    \"tanstack-router\",\n    \"!src/**/*.spec.*\",\n    \"!src/**/*.specHelper.*\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/react-router\": \">=1.64.0 <2\",\n    \"react\": \"18 || 19\",\n    \"react-router\": \"6 || 7\",\n    \"react-router-dom\": \"6 || 7\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-slim\": {\n      \"optional\": true\n    },\n    \"@tanstack/react-router\": {\n      \"optional\": true\n    },\n    \"react\": {\n      \"optional\": true\n    },\n    \"react-router\": {\n      \"optional\": true\n    },\n    \"react-router-dom\": {\n      \"optional\": true\n    }\n  },\n  \"devDependencies\": {\n    \"@tanstack/react-router\": \"1.168.22\",\n    \"@types/react\": \"19.2.14\",\n    \"@types/react-dom\": \"19.2.3\",\n    \"react\": \"19.2.5\",\n    \"react-dom\": \"19.2.5\",\n    \"react-router\": \"7.14.1\",\n    \"react-router-dom\": \"7.14.1\",\n    \"react-router-dom-6\": \"npm:react-router-dom@6.30.3\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-react\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-react/react-router-v6/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-react/react-router-v6\",\n  \"private\": true,\n  \"main\": \"../cjs/entries/reactRouterV6.js\",\n  \"module\": \"../esm/entries/reactRouterV6.js\",\n  \"types\": \"../cjs/entries/reactRouterV6.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum-react/react-router-v6/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"../src/entries/reactRouterV6.ts\"]\n}\n"
  },
  {
    "path": "packages/rum-react/react-router-v7/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-react/react-router-v7\",\n  \"private\": true,\n  \"main\": \"../cjs/entries/reactRouterV7.js\",\n  \"module\": \"../esm/entries/reactRouterV7.js\",\n  \"types\": \"../cjs/entries/reactRouterV7.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum-react/react-router-v7/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"../src/entries/reactRouterV7.ts\"]\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/error/addReactError.spec.ts",
    "content": "import { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { addReactError } from './addReactError'\n\ndescribe('addReactError', () => {\n  it('delegates the error to addError', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      addError: addErrorSpy,\n    })\n    const originalError = new Error('error message')\n\n    addReactError(originalError, { componentStack: 'at ComponentSpy toto.js' })\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith({\n      error: originalError,\n      handlingStack: jasmine.any(String),\n      componentStack: 'at ComponentSpy toto.js',\n      startClocks: jasmine.any(Object),\n      context: {\n        framework: 'react',\n      },\n    })\n  })\n\n  it('should merge dd_context from the original error with react error context', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      addError: addErrorSpy,\n    })\n    const originalError = new Error('error message')\n    ;(originalError as any).dd_context = { component: 'Menu', param: 123 }\n\n    addReactError(originalError, {})\n\n    expect(addErrorSpy).toHaveBeenCalledWith(\n      jasmine.objectContaining({\n        error: originalError,\n        context: {\n          framework: 'react',\n          component: 'Menu',\n          param: 123,\n        },\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/error/addReactError.ts",
    "content": "import type { ErrorInfo } from 'react'\nimport type { Context } from '@datadog/browser-core'\nimport { callMonitored, clocksNow, createHandlingStack } from '@datadog/browser-core'\nimport { onRumStart } from '../reactPlugin'\n\n/**\n * Add a React error to the RUM session.\n *\n * @category Error\n * @example\n * ```ts\n * import { createRoot } from 'react-dom/client'\n * import { datadogRum } from '@datadog/browser-rum'\n * import { addReactError } from '@datadog/browser-rum-react'\n *\n * const container = document.getElementById('root')\n * const root = createRoot(container, {\n *   onUncaughtError: (error, errorInfo) => {\n *     // Report uncaught errors to Datadog\n *     addReactError(error, errorInfo)\n *   }\n * })\n * // ...\n * ```\n */\nexport function addReactError(error: Error, info: ErrorInfo) {\n  const handlingStack = createHandlingStack('react error')\n  const startClocks = clocksNow()\n  onRumStart((addError) => {\n    callMonitored(() => {\n      addError({\n        error,\n        handlingStack,\n        componentStack: info.componentStack ?? undefined,\n        startClocks,\n        context: { ...(error as Error & { dd_context?: Context }).dd_context, framework: 'react' },\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/error/createErrorBoundary.spec.tsx",
    "content": "import React, { act } from 'react'\n\nimport { disableJasmineUncaughtExceptionTracking, ignoreConsoleLogs } from '../../../../core/test'\nimport { appendComponent } from '../../../test/appendComponent'\nimport { initReactOldBrowsersSupport } from '../../../test/reactOldBrowsersSupport'\nimport type { ErrorBoundaryFallback } from './errorBoundary'\nimport { createErrorBoundary } from './errorBoundary'\n\ntype FallbackFunctionComponent = Extract<ErrorBoundaryFallback, (...args: any[]) => any>\n\ndescribe('createErrorBoundary', () => {\n  beforeEach(() => {\n    ignoreConsoleLogs('error', 'Error: error')\n    disableJasmineUncaughtExceptionTracking()\n    initReactOldBrowsersSupport()\n  })\n\n  it('renders children', () => {\n    const TestErrorBoundary = createErrorBoundary(jasmine.createSpy(), 'TestErrorBoundary')\n    const container = appendComponent(<TestErrorBoundary fallback={() => null}>bar</TestErrorBoundary>)\n\n    expect(container.innerHTML).toBe('bar')\n  })\n\n  it('renders the fallback when an error occurs', () => {\n    const TestErrorBoundary = createErrorBoundary(jasmine.createSpy(), 'TestErrorBoundary')\n    const fallbackSpy = jasmine.createSpy<FallbackFunctionComponent>().and.returnValue('fallback')\n    const ComponentSpy = jasmine.createSpy().and.throwError(new Error('error'))\n    const container = appendComponent(\n      <TestErrorBoundary fallback={fallbackSpy}>\n        <ComponentSpy />\n      </TestErrorBoundary>\n    )\n\n    expect(fallbackSpy).toHaveBeenCalled()\n    fallbackSpy.calls.all().forEach(({ args }) => {\n      expect(args[0]).toEqual({\n        error: new Error('error'),\n        resetError: jasmine.any(Function),\n      })\n    })\n    expect(container.innerHTML).toBe('fallback')\n  })\n\n  it('resets the error when resetError is called', () => {\n    const TestErrorBoundary = createErrorBoundary(jasmine.createSpy(), 'TestErrorBoundary')\n    const fallbackSpy = jasmine.createSpy<FallbackFunctionComponent>().and.returnValue('fallback')\n    const ComponentSpy = jasmine.createSpy().and.throwError(new Error('error'))\n    const container = appendComponent(\n      <TestErrorBoundary fallback={fallbackSpy}>\n        <ComponentSpy />\n      </TestErrorBoundary>\n    )\n\n    ComponentSpy.and.returnValue('bar')\n\n    const { resetError } = fallbackSpy.calls.mostRecent().args[0]\n    act(() => {\n      resetError()\n    })\n\n    expect(container.innerHTML).toBe('bar')\n  })\n\n  it('passes error and errorInfo to the report callback', () => {\n    const reportErrorSpy = jasmine.createSpy()\n    const TestErrorBoundary = createErrorBoundary(reportErrorSpy, 'TestErrorBoundary')\n    const originalError = new Error('error')\n    const ComponentSpy = jasmine.createSpy().and.throwError(originalError)\n    ;(ComponentSpy as any).displayName = 'ComponentSpy'\n\n    appendComponent(\n      <TestErrorBoundary fallback={() => null}>\n        <ComponentSpy />\n      </TestErrorBoundary>\n    )\n\n    expect(reportErrorSpy).toHaveBeenCalledOnceWith(\n      originalError,\n      jasmine.objectContaining({\n        componentStack: jasmine.stringContaining('ComponentSpy'),\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/error/errorBoundary.spec.tsx",
    "content": "import React, { act } from 'react'\n\nimport { disableJasmineUncaughtExceptionTracking, ignoreConsoleLogs } from '../../../../core/test'\nimport { appendComponent } from '../../../test/appendComponent'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { initReactOldBrowsersSupport } from '../../../test/reactOldBrowsersSupport'\nimport type { ErrorBoundaryFallback } from './errorBoundary'\nimport { ErrorBoundary } from './errorBoundary'\n\ntype FallbackFunctionComponent = Extract<ErrorBoundaryFallback, (...args: any[]) => any>\n\ndescribe('ErrorBoundary', () => {\n  beforeEach(() => {\n    // Prevent React from displaying the error in the console\n    ignoreConsoleLogs('error', 'Error: error')\n\n    disableJasmineUncaughtExceptionTracking()\n    initReactOldBrowsersSupport()\n  })\n\n  it('renders children', () => {\n    const container = appendComponent(<ErrorBoundary fallback={() => null}>bar</ErrorBoundary>)\n    expect(container.innerHTML).toBe('bar')\n  })\n\n  it('renders the fallback function component when an error occurs', () => {\n    const fallbackSpy = jasmine.createSpy<FallbackFunctionComponent>().and.returnValue('fallback')\n    const ComponentSpy = jasmine.createSpy().and.throwError(new Error('error'))\n    const container = appendComponent(\n      <ErrorBoundary fallback={fallbackSpy}>\n        <ComponentSpy />\n      </ErrorBoundary>\n    )\n    expect(fallbackSpy).toHaveBeenCalled()\n    // React calls the component multiple times while rendering\n    fallbackSpy.calls.all().forEach(({ args }) => {\n      expect(args[0]).toEqual({\n        error: new Error('error'),\n        resetError: jasmine.any(Function),\n      })\n    })\n    expect(container.innerHTML).toBe('fallback')\n  })\n\n  it('renders the fallback class component when an error occurs', () => {\n    class FallbackComponent extends React.Component<{ error: Error; resetError: () => void }> {\n      constructor(props: { error: Error; resetError: () => void }) {\n        super(props)\n        expect(props).toEqual({ error: new Error('error'), resetError: jasmine.any(Function) })\n      }\n\n      render() {\n        return 'fallback'\n      }\n    }\n\n    const ComponentSpy = jasmine.createSpy().and.throwError(new Error('error'))\n    const container = appendComponent(\n      <ErrorBoundary fallback={FallbackComponent}>\n        <ComponentSpy />\n      </ErrorBoundary>\n    )\n    expect(container.innerHTML).toBe('fallback')\n  })\n\n  it('resets the error when resetError is called', () => {\n    const fallbackSpy = jasmine.createSpy<FallbackFunctionComponent>().and.returnValue('fallback')\n    const ComponentSpy = jasmine.createSpy().and.throwError(new Error('error'))\n    const container = appendComponent(\n      <ErrorBoundary fallback={fallbackSpy}>\n        <ComponentSpy />\n      </ErrorBoundary>\n    )\n\n    // Don't throw the second time\n    ComponentSpy.and.returnValue('bar')\n\n    const { resetError } = fallbackSpy.calls.mostRecent().args[0]\n    act(() => {\n      resetError()\n    })\n\n    expect(container.innerHTML).toBe('bar')\n  })\n\n  it('reports the error through addReactError', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      addError: addErrorSpy,\n    })\n    const originalError = new Error('error')\n    const ComponentSpy = jasmine.createSpy().and.throwError(originalError)\n    ;(ComponentSpy as any).displayName = 'ComponentSpy'\n\n    appendComponent(\n      <ErrorBoundary fallback={() => null}>\n        <ComponentSpy />\n      </ErrorBoundary>\n    )\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith(\n      jasmine.objectContaining({\n        error: originalError,\n        handlingStack: jasmine.any(String),\n        startClocks: jasmine.any(Object),\n        context: {\n          framework: 'react',\n        },\n        componentStack: jasmine.stringContaining('ComponentSpy'),\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/error/errorBoundary.ts",
    "content": "import React from 'react'\nimport type { ErrorInfo } from 'react'\nimport { addReactError } from './addReactError'\n\nexport interface ErrorBoundaryProps {\n  fallback: ErrorBoundaryFallback\n  children: React.ReactNode\n}\n\nexport type ErrorBoundaryFallback = React.ComponentType<{ error: Error; resetError: () => void }>\n\nexport type State =\n  | {\n      didCatch: false\n      error: null\n    }\n  | {\n      didCatch: true\n      error: Error\n    }\n\nconst INITIAL_STATE: State = { didCatch: false, error: null }\n\nexport function createErrorBoundary(\n  reportError: (error: Error, errorInfo: ErrorInfo) => void,\n  displayName = 'ErrorBoundary'\n) {\n  const DatadogErrorBoundary: React.ComponentClass<ErrorBoundaryProps> = class DatadogErrorBoundary extends React.Component<\n    ErrorBoundaryProps,\n    State\n  > {\n    constructor(props: ErrorBoundaryProps) {\n      super(props)\n      this.state = INITIAL_STATE\n    }\n\n    static getDerivedStateFromError(error: Error): State {\n      return { didCatch: true, error }\n    }\n\n    resetError = () => {\n      this.setState(INITIAL_STATE)\n    }\n\n    componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n      reportError(error, errorInfo)\n    }\n\n    render() {\n      if (this.state.didCatch) {\n        return React.createElement(this.props.fallback, {\n          error: this.state.error,\n          resetError: this.resetError,\n        })\n      }\n\n      return this.props.children\n    }\n  }\n\n  DatadogErrorBoundary.displayName = displayName\n\n  return DatadogErrorBoundary\n}\n\n/**\n * ErrorBoundary component to report React errors to Datadog.\n *\n * For more advanced error handling, you can use the {@link addReactError} function.\n *\n * @category Error\n * @example\n * ```ts\n * import { ErrorBoundary } from '@datadog/browser-rum-react'\n *\n * <ErrorBoundary fallback={() => null}>\n *   <Component />\n * </ErrorBoundary>\n * ```\n */\n// eslint-disable-next-line local-rules/disallow-side-effects\nexport const ErrorBoundary = createErrorBoundary(addReactError)\n"
  },
  {
    "path": "packages/rum-react/src/domain/error/index.ts",
    "content": "export { ErrorBoundary, createErrorBoundary } from './errorBoundary'\nexport type { State, ErrorBoundaryFallback, ErrorBoundaryProps } from './errorBoundary'\nexport { addReactError } from './addReactError'\n"
  },
  {
    "path": "packages/rum-react/src/domain/performance/addDurationVital.ts",
    "content": "import type { RumPublicApi } from '@datadog/browser-rum-core'\nimport { onRumInit } from '../reactPlugin'\n\nexport const addDurationVital: RumPublicApi['addDurationVital'] = (name, options) => {\n  onRumInit((_, rumPublicApi) => {\n    rumPublicApi.addDurationVital(name, options)\n  })\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/performance/index.ts",
    "content": "// eslint-disable-next-line camelcase\nexport { UNSTABLE_ReactComponentTracker } from './reactComponentTracker'\n"
  },
  {
    "path": "packages/rum-react/src/domain/performance/reactComponentTracker.spec.tsx",
    "content": "import React, { useEffect, useLayoutEffect, act } from 'react'\nimport { appendComponent } from '../../../test/appendComponent'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { initReactOldBrowsersSupport } from '../../../test/reactOldBrowsersSupport'\nimport type { Clock } from '../../../../core/test'\nimport { mockClock } from '../../../../core/test'\nimport { UNSTABLE_ReactComponentTracker as ReactComponentTracker } from './reactComponentTracker'\n\nconst RENDER_DURATION = 100\nconst EFFECT_DURATION = 101\nconst LAYOUT_EFFECT_DURATION = 102\nconst TOTAL_DURATION = RENDER_DURATION + EFFECT_DURATION + LAYOUT_EFFECT_DURATION\n\nfunction ChildComponent({ clock }: { clock: Clock }) {\n  clock.tick(RENDER_DURATION)\n  useEffect(() => clock.tick(EFFECT_DURATION))\n  useLayoutEffect(() => clock.tick(LAYOUT_EFFECT_DURATION))\n  return null\n}\n\ndescribe('UNSTABLE_ReactComponentTracker', () => {\n  let clock: Clock\n\n  beforeEach(() => {\n    clock = mockClock()\n    initReactOldBrowsersSupport()\n  })\n\n  it('should call addDurationVital after the component rendering', () => {\n    const addDurationVitalSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      publicApi: {\n        addDurationVital: addDurationVitalSpy,\n      },\n    })\n\n    appendComponent(\n      <ReactComponentTracker name=\"ChildComponent\">\n        <ChildComponent clock={clock} />\n      </ReactComponentTracker>\n    )\n\n    expect(addDurationVitalSpy).toHaveBeenCalledTimes(1)\n    const [name, options] = addDurationVitalSpy.calls.mostRecent().args\n    expect(name).toBe('reactComponentRender')\n    expect(options).toEqual({\n      description: 'ChildComponent',\n      startTime: clock.timeStamp(0),\n      duration: TOTAL_DURATION,\n      context: {\n        is_first_render: true,\n        render_phase_duration: RENDER_DURATION,\n        effect_phase_duration: EFFECT_DURATION,\n        layout_effect_phase_duration: LAYOUT_EFFECT_DURATION,\n        framework: 'react',\n      },\n    })\n  })\n\n  it('should call addDurationVital on rerender', () => {\n    const addDurationVitalSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      publicApi: {\n        addDurationVital: addDurationVitalSpy,\n      },\n    })\n\n    let forceUpdate: () => void\n\n    function App() {\n      const [, setState] = React.useState(0)\n      forceUpdate = () => setState((prev) => prev + 1)\n      return (\n        <>\n          <ReactComponentTracker name=\"ChildComponent\">\n            <ChildComponent clock={clock} />\n          </ReactComponentTracker>\n        </>\n      )\n    }\n\n    appendComponent(<App />)\n\n    clock.tick(1)\n\n    act(() => {\n      forceUpdate!()\n    })\n\n    expect(addDurationVitalSpy).toHaveBeenCalledTimes(2)\n    const options = addDurationVitalSpy.calls.mostRecent().args[1]\n    expect(options).toEqual({\n      description: 'ChildComponent',\n      startTime: clock.timeStamp(TOTAL_DURATION + 1),\n      duration: TOTAL_DURATION,\n      context: {\n        is_first_render: false,\n        render_phase_duration: RENDER_DURATION,\n        effect_phase_duration: EFFECT_DURATION,\n        layout_effect_phase_duration: LAYOUT_EFFECT_DURATION,\n        framework: 'react',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/performance/reactComponentTracker.tsx",
    "content": "import * as React from 'react'\nimport { createTimer } from './timer'\nimport { addDurationVital } from './addDurationVital'\n\n/**\n * Track the performance of a React component.\n *\n * @experimental\n */\n// eslint-disable-next-line\nexport const UNSTABLE_ReactComponentTracker = ({\n  name: componentName,\n  children,\n}: {\n  name: string\n  children?: React.ReactNode\n}) => {\n  const isFirstRender = React.useRef(true)\n\n  const renderTimer = createTimer()\n  const effectTimer = createTimer()\n  const layoutEffectTimer = createTimer()\n\n  const onEffectEnd = () => {\n    const renderDuration = renderTimer.getDuration() ?? 0\n    const effectDuration = effectTimer.getDuration() ?? 0\n    const layoutEffectDuration = layoutEffectTimer.getDuration() ?? 0\n\n    const totalRenderTime = renderDuration + effectDuration + layoutEffectDuration\n\n    addDurationVital('reactComponentRender', {\n      description: componentName,\n      startTime: renderTimer.getStartTime()!, // note: renderTimer should have been started at this point, so getStartTime should not return undefined\n      duration: totalRenderTime,\n      context: {\n        is_first_render: isFirstRender.current,\n        render_phase_duration: renderDuration,\n        effect_phase_duration: effectDuration,\n        layout_effect_phase_duration: layoutEffectDuration,\n        framework: 'react',\n      },\n    })\n\n    isFirstRender.current = false\n  }\n\n  // In react, children are rendered sequentially in the order they are defined. that's why we can\n  // measure perf timings of a component by starting recordings in the component above and stopping\n  // them in the component below.\n  return (\n    <>\n      <LifeCycle\n        onRender={renderTimer.startTimer}\n        onLayoutEffect={layoutEffectTimer.startTimer}\n        onEffect={effectTimer.startTimer}\n      />\n      {children}\n      <LifeCycle\n        onRender={renderTimer.stopTimer}\n        onLayoutEffect={layoutEffectTimer.stopTimer}\n        onEffect={() => {\n          effectTimer.stopTimer()\n          onEffectEnd()\n        }}\n      />\n    </>\n  )\n}\n\nfunction LifeCycle({\n  onRender,\n  onLayoutEffect,\n  onEffect,\n}: {\n  onRender: () => void\n  onLayoutEffect: () => void\n  onEffect: () => void\n}) {\n  onRender()\n  React.useLayoutEffect(onLayoutEffect)\n  React.useEffect(onEffect)\n  return null\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/performance/timer.spec.ts",
    "content": "import { mockClock } from '@datadog/browser-core/test'\nimport type { Duration } from '@datadog/browser-core'\nimport { createTimer } from './timer'\n\ndescribe('createTimer', () => {\n  it('is able to measure time', () => {\n    const clock = mockClock()\n\n    const timer = createTimer()\n    timer.startTimer()\n    clock.tick(1000)\n    timer.stopTimer()\n    expect(timer.getDuration()).toBe(1000 as Duration)\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/performance/timer.ts",
    "content": "import type { Duration, RelativeTime, TimeStamp } from '@datadog/browser-core'\nimport { elapsed, relativeNow, timeStampNow } from '@datadog/browser-core'\n\nexport function createTimer() {\n  let duration: Duration | undefined\n  let startTime: TimeStamp | undefined\n  let highPrecisionStartTime: RelativeTime | undefined\n\n  return {\n    startTimer(this: void) {\n      // timeStampNow uses Date.now() internally, which is not high precision, but this is what is\n      // used for other events, so we use it here as well.\n      startTime = timeStampNow()\n\n      // relativeNow uses performance.now() which is higher precision than Date.now(), so we use for\n      // the duration\n      highPrecisionStartTime = relativeNow()\n    },\n\n    stopTimer(this: void) {\n      duration = elapsed(highPrecisionStartTime!, relativeNow())\n    },\n\n    getDuration(this: void) {\n      return duration\n    },\n\n    getStartTime(this: void) {\n      return startTime\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactPlugin.spec.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport { onRumInit, onRumStart, reactPlugin, resetReactPlugin } from './reactPlugin'\n\nconst PUBLIC_API = {} as RumPublicApi\nconst INIT_CONFIGURATION = {} as RumInitConfiguration\n\ndescribe('reactPlugin', () => {\n  afterEach(() => {\n    resetReactPlugin()\n  })\n\n  it('returns a plugin object', () => {\n    const plugin = reactPlugin()\n    expect(plugin).toEqual(\n      jasmine.objectContaining({\n        name: 'react',\n        onInit: jasmine.any(Function),\n        onRumStart: jasmine.any(Function),\n      })\n    )\n  })\n\n  it('calls callbacks registered with onReactPluginInit during onInit', () => {\n    const callbackSpy = jasmine.createSpy()\n    const pluginConfiguration = {}\n    onRumInit(callbackSpy)\n\n    expect(callbackSpy).not.toHaveBeenCalled()\n\n    reactPlugin(pluginConfiguration).onInit({\n      publicApi: PUBLIC_API,\n      initConfiguration: INIT_CONFIGURATION,\n    })\n\n    expect(callbackSpy).toHaveBeenCalledTimes(1)\n    expect(callbackSpy.calls.mostRecent().args[0]).toBe(pluginConfiguration)\n    expect(callbackSpy.calls.mostRecent().args[1]).toBe(PUBLIC_API)\n  })\n\n  it('calls callbacks immediately if onInit was already invoked', () => {\n    const callbackSpy = jasmine.createSpy()\n    const pluginConfiguration = {}\n    reactPlugin(pluginConfiguration).onInit({\n      publicApi: PUBLIC_API,\n      initConfiguration: INIT_CONFIGURATION,\n    })\n\n    onRumInit(callbackSpy)\n\n    expect(callbackSpy).toHaveBeenCalledTimes(1)\n    expect(callbackSpy.calls.mostRecent().args[0]).toBe(pluginConfiguration)\n    expect(callbackSpy.calls.mostRecent().args[1]).toBe(PUBLIC_API)\n  })\n\n  it('enforce manual view tracking when router is enabled', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    reactPlugin({ router: true }).onInit({ publicApi: PUBLIC_API, initConfiguration })\n\n    expect(initConfiguration.trackViewsManually).toBe(true)\n  })\n\n  it('does not enforce manual view tracking when router is disabled', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    reactPlugin({ router: false }).onInit({ publicApi: PUBLIC_API, initConfiguration })\n\n    expect(initConfiguration.trackViewsManually).toBeUndefined()\n  })\n\n  it('returns the configuration telemetry', () => {\n    const pluginConfiguration = { router: true }\n    const plugin = reactPlugin(pluginConfiguration)\n\n    expect(plugin.getConfigurationTelemetry()).toEqual({ router: true })\n  })\n\n  it('calls onRumStart subscribers during onRumStart', () => {\n    const callbackSpy = jasmine.createSpy()\n    const addErrorSpy = jasmine.createSpy()\n    onRumStart(callbackSpy)\n\n    reactPlugin().onRumStart({ addError: addErrorSpy })\n\n    expect(callbackSpy).toHaveBeenCalledWith(addErrorSpy)\n  })\n\n  it('calls onRumStart subscribers immediately if already started', () => {\n    const addErrorSpy = jasmine.createSpy()\n    reactPlugin().onRumStart({ addError: addErrorSpy })\n\n    const callbackSpy = jasmine.createSpy()\n    onRumStart(callbackSpy)\n\n    expect(callbackSpy).toHaveBeenCalledWith(addErrorSpy)\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactPlugin.ts",
    "content": "import type { RumPlugin, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\n\nlet globalPublicApi: RumPublicApi | undefined\nlet globalConfiguration: ReactPluginConfiguration | undefined\nlet globalAddError: StartRumResult['addError'] | undefined\ntype InitSubscriber = (configuration: ReactPluginConfiguration, rumPublicApi: RumPublicApi) => void\ntype StartSubscriber = (addError: StartRumResult['addError']) => void\n\nconst onRumInitSubscribers: InitSubscriber[] = []\nconst onRumStartSubscribers: StartSubscriber[] = []\n\n/**\n * React plugin configuration.\n *\n * @category Main\n */\nexport interface ReactPluginConfiguration {\n  /**\n   * Enable router integration. Make sure to use functions from\n   * {@link @datadog/browser-rum-react/react-router-v6! | @datadog/browser-rum-react/react-router-v6},\n   * {@link @datadog/browser-rum-react/react-router-v7! | @datadog/browser-rum-react/react-router-v7}, or\n   * {@link @datadog/browser-rum-react/tanstack-router! | @datadog/browser-rum-react/tanstack-router}\n   * to create the router.\n   * ```\n   */\n  router?: boolean\n}\n\n/**\n * React plugin type.\n *\n * The plugins API is unstable and experimental, and may change without notice. Please don't use this type directly.\n *\n * @internal\n */\nexport type ReactPlugin = Required<RumPlugin>\n\n/**\n * React plugin constructor.\n *\n * @category Main\n * @example\n * ```ts\n * import { datadogRum } from '@datadog/browser-rum'\n * import { reactPlugin } from '@datadog/browser-rum-react'\n *\n * datadogRum.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   site: '<DATADOG_SITE>',\n *   plugins: [reactPlugin()],\n *   // ...\n * })\n * ```\n */\nexport function reactPlugin(configuration: ReactPluginConfiguration = {}): ReactPlugin {\n  return {\n    name: 'react',\n    onInit({ publicApi, initConfiguration }) {\n      globalPublicApi = publicApi\n      globalConfiguration = configuration\n      for (const subscriber of onRumInitSubscribers) {\n        subscriber(globalConfiguration, globalPublicApi)\n      }\n      if (configuration.router) {\n        initConfiguration.trackViewsManually = true\n      }\n    },\n    onRumStart({ addError }) {\n      globalAddError = addError\n      for (const subscriber of onRumStartSubscribers) {\n        if (addError) {\n          subscriber(addError)\n        }\n      }\n    },\n    getConfigurationTelemetry() {\n      return { router: !!configuration.router }\n    },\n  } satisfies RumPlugin\n}\n\nexport function onRumInit(callback: InitSubscriber) {\n  if (globalConfiguration && globalPublicApi) {\n    callback(globalConfiguration, globalPublicApi)\n  } else {\n    onRumInitSubscribers.push(callback)\n  }\n}\n\nexport function onRumStart(callback: StartSubscriber) {\n  if (globalAddError) {\n    callback(globalAddError)\n  } else {\n    onRumStartSubscribers.push(callback)\n  }\n}\n\nexport function resetReactPlugin() {\n  globalPublicApi = undefined\n  globalConfiguration = undefined\n  globalAddError = undefined\n  onRumInitSubscribers.length = 0\n  onRumStartSubscribers.length = 0\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/createRouter.spec.ts",
    "content": "import { createMemoryRouter as createMemoryRouterV7 } from 'react-router-dom'\nimport { createMemoryRouter as createMemoryRouterV6 } from 'react-router-dom-6'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { wrapCreateRouter } from './createRouter'\n\ndescribe('createRouter', () => {\n  const versions = [\n    { label: 'react-router v6', createMemoryRouter: wrapCreateRouter(createMemoryRouterV6) },\n    { label: 'react-router v7', createMemoryRouter: wrapCreateRouter(createMemoryRouterV7) },\n  ]\n\n  for (const { label, createMemoryRouter } of versions) {\n    describe(label, () => {\n      let startViewSpy: jasmine.Spy<(name?: string | object) => void>\n      let router: ReturnType<typeof createMemoryRouter>\n\n      beforeEach(() => {\n        if (!window.AbortController) {\n          pending('createMemoryRouter relies on AbortController')\n        }\n\n        startViewSpy = jasmine.createSpy()\n        initializeReactPlugin({\n          configuration: {\n            router: true,\n          },\n          publicApi: {\n            startView: startViewSpy,\n          },\n        })\n\n        router = createMemoryRouter(\n          [{ path: '/foo' }, { path: '/bar', children: [{ path: 'nested' }] }, { path: '*' }],\n          {\n            initialEntries: ['/foo'],\n          }\n        )\n      })\n\n      afterEach(() => {\n        router?.dispose()\n      })\n\n      it('creates a new view when the router is created', () => {\n        expect(startViewSpy).toHaveBeenCalledWith('/foo')\n      })\n\n      it('creates a new view when the router navigates', async () => {\n        startViewSpy.calls.reset()\n        await router.navigate('/bar')\n        expect(startViewSpy).toHaveBeenCalledWith('/bar')\n      })\n\n      it('creates a new view when the router navigates to a nested route', async () => {\n        await router.navigate('/bar')\n        startViewSpy.calls.reset()\n        await router.navigate('/bar/nested')\n        expect(startViewSpy).toHaveBeenCalledWith('/bar/nested')\n      })\n\n      it('creates a new view with the fallback route', async () => {\n        startViewSpy.calls.reset()\n        await router.navigate('/non-existent')\n        expect(startViewSpy).toHaveBeenCalledWith('/non-existent')\n      })\n\n      it('does not create a new view when navigating to the same URL', async () => {\n        await router.navigate('/bar')\n        startViewSpy.calls.reset()\n        await router.navigate('/bar')\n        expect(startViewSpy).not.toHaveBeenCalled()\n      })\n\n      it('does not create a new view when just changing query parameters', async () => {\n        await router.navigate('/bar')\n        startViewSpy.calls.reset()\n        await router.navigate('/bar?baz=1')\n        expect(startViewSpy).not.toHaveBeenCalled()\n      })\n    })\n  }\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/createRouter.ts",
    "content": "import { startReactRouterView } from './startReactRouterView'\nimport type { AnyCreateRouter } from './types'\n\nexport function wrapCreateRouter<CreateRouter extends AnyCreateRouter<any>>(\n  originalCreateRouter: CreateRouter\n): CreateRouter {\n  return ((routes, options) => {\n    const router = originalCreateRouter(routes, options)\n    let location = router.state.location.pathname\n    router.subscribe((routerState) => {\n      const newPathname = routerState.location.pathname\n      if (location !== newPathname) {\n        startReactRouterView(routerState.matches)\n        location = newPathname\n      }\n    })\n    startReactRouterView(router.state.matches)\n    return router\n  }) as CreateRouter\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/index.ts",
    "content": "export { wrapCreateRouter } from './createRouter'\nexport { wrapUseRoutes } from './useRoutes'\nexport { createRoutesComponent } from './routesComponent'\nexport { startReactRouterView, computeViewName } from './startReactRouterView'\nexport type { AnyLocation } from './types'\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/reactRouter.specHelper.ts",
    "content": "import { ignoreConsoleLogs } from '../../../../core/test'\n\nexport function ignoreReactRouterDeprecationWarnings() {\n  ignoreConsoleLogs('warn', 'React Router Future Flag Warning')\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/routesComponent.spec.tsx",
    "content": "import React, { act } from 'react'\nimport * as rrdom6 from 'react-router-dom-6'\nimport * as rrdom7 from 'react-router-dom'\nimport { ignoreConsoleLogs } from '../../../../core/test'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { initReactOldBrowsersSupport } from '../../../test/reactOldBrowsersSupport'\nimport { appendComponent } from '../../../test/appendComponent'\nimport { createRoutesComponent } from './routesComponent'\nimport { ignoreReactRouterDeprecationWarnings } from './reactRouter.specHelper'\nimport { wrapUseRoutes } from './useRoutes'\n;[\n  {\n    version: 'react-router-6',\n    MemoryRouter: rrdom6.MemoryRouter,\n    Route: rrdom6.Route,\n    useNavigate: rrdom6.useNavigate,\n    Routes: createRoutesComponent(\n      wrapUseRoutes({\n        useRoutes: rrdom6.useRoutes,\n        useLocation: rrdom6.useLocation,\n        matchRoutes: rrdom6.matchRoutes,\n      }),\n      rrdom6.createRoutesFromChildren\n    ),\n  },\n  {\n    version: 'react-router-7',\n    MemoryRouter: rrdom7.MemoryRouter,\n    Route: rrdom7.Route,\n    useNavigate: rrdom7.useNavigate,\n    Routes: createRoutesComponent(\n      wrapUseRoutes({\n        useRoutes: rrdom7.useRoutes,\n        useLocation: rrdom7.useLocation,\n        matchRoutes: rrdom7.matchRoutes,\n      }),\n      rrdom7.createRoutesFromChildren\n    ),\n  },\n].forEach(({ version, MemoryRouter, Route, useNavigate, Routes }) => {\n  type NavigateFunction = ReturnType<typeof useNavigate>\n\n  describe(`Routes component (${version})`, () => {\n    let startViewSpy: jasmine.Spy<(name?: string | object) => void>\n\n    beforeEach(() => {\n      ignoreReactRouterDeprecationWarnings()\n      initReactOldBrowsersSupport()\n      startViewSpy = jasmine.createSpy()\n      initializeReactPlugin({\n        configuration: {\n          router: true,\n        },\n        publicApi: {\n          startView: startViewSpy,\n        },\n      })\n    })\n\n    it('starts a new view as soon as it is rendered', () => {\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <Routes>\n            <Route path=\"/foo\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/foo')\n    })\n\n    it('renders the matching route', () => {\n      const container = appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <Routes>\n            <Route path=\"/foo\" element=\"foo\" />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      expect(container.innerHTML).toBe('foo')\n    })\n\n    it('does not start a new view on re-render', () => {\n      let forceUpdate: () => void\n\n      function App() {\n        const [, setState] = React.useState(0)\n        forceUpdate = () => setState((s) => s + 1)\n        return (\n          <MemoryRouter initialEntries={['/foo']}>\n            <Routes>\n              <Route path=\"/foo\" element={null} />\n            </Routes>\n          </MemoryRouter>\n        )\n      }\n\n      appendComponent(<App />)\n\n      expect(startViewSpy).toHaveBeenCalledTimes(1)\n\n      act(() => {\n        forceUpdate!()\n      })\n\n      expect(startViewSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('starts a new view on navigation', async () => {\n      let navigate: NavigateFunction\n\n      function NavBar() {\n        navigate = useNavigate()\n        return null\n      }\n\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <NavBar />\n          <Routes>\n            <Route path=\"/foo\" element={null} />\n            <Route path=\"/bar\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      startViewSpy.calls.reset()\n      await act(async () => {\n        await navigate!('/bar')\n      })\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/bar')\n    })\n\n    it('does not start a new view if the URL is the same', async () => {\n      let navigate: NavigateFunction\n\n      function NavBar() {\n        navigate = useNavigate()\n        return null\n      }\n\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <NavBar />\n          <Routes>\n            <Route path=\"/foo\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      startViewSpy.calls.reset()\n      await act(async () => {\n        await navigate!('/foo')\n      })\n\n      expect(startViewSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not start a new view if the path is the same but with different parameters', async () => {\n      let navigate: NavigateFunction\n\n      function NavBar() {\n        navigate = useNavigate()\n        return null\n      }\n\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <NavBar />\n          <Routes>\n            <Route path=\"/foo\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      startViewSpy.calls.reset()\n      await act(async () => {\n        await navigate!('/foo?bar=baz')\n      })\n\n      expect(startViewSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not start a new view if it does not match any route', () => {\n      // Prevent react router from showing a warning in the console when a route does not match\n      ignoreConsoleLogs('warn', 'No routes matched location')\n\n      appendComponent(\n        <MemoryRouter>\n          <Routes>\n            <Route path=\"/bar\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).not.toHaveBeenCalled()\n    })\n\n    it('allows passing a location object', () => {\n      appendComponent(\n        <MemoryRouter>\n          <Routes location={{ pathname: '/foo' }}>\n            <Route path=\"/foo\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/foo')\n    })\n\n    it('allows passing a location string', () => {\n      appendComponent(\n        <MemoryRouter>\n          <Routes location=\"/foo\">\n            <Route path=\"/foo\" element={null} />\n          </Routes>\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/foo')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/routesComponent.ts",
    "content": "import type { AnyLocation, AnyRouteObject, AnyUseRoute } from './types'\n// Same as react-router-dom Routes but with our useRoutes instead of the original one\n// https://github.com/remix-run/react-router/blob/5d66dbdbc8edf1d9c3a4d9c9d84073d046b5785b/packages/react-router/lib/components.tsx#L503-L508\nexport function createRoutesComponent<Location extends AnyLocation>(\n  useRoutes: AnyUseRoute<Location>,\n  createRoutesFromChildren: (children: React.ReactNode, parentPath?: number[]) => AnyRouteObject[]\n) {\n  return function Routes({ children, location }: { children?: React.ReactNode; location?: Location }) {\n    return useRoutes(createRoutesFromChildren(children), location)\n  }\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/startReactRouterView.spec.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport {\n  createMemoryRouter as createMemoryRouterV6,\n  type RouteObject as RouteObjectV6,\n  type RouteMatch as RouteMatchV6,\n} from 'react-router-dom-6'\nimport {\n  createMemoryRouter as createMemoryRouterV7,\n  type RouteObject as RouteObjectV7,\n  type RouteMatch as RouteMatchV7,\n} from 'react-router-dom'\nimport { registerCleanupTask } from '../../../../core/test'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { startReactRouterView, computeViewName } from './startReactRouterView'\nimport type { AnyRouteMatch } from './types'\n\nconst routerVersions = [\n  {\n    version: 'react-router-6',\n    createMemoryRouter: createMemoryRouterV6,\n  },\n  {\n    version: 'react-router-7',\n    createMemoryRouter: createMemoryRouterV7,\n  },\n]\n\nrouterVersions.forEach(({ version, createMemoryRouter }) => {\n  describe(`startReactRouterView (${version})`, () => {\n    describe('startReactRouterView', () => {\n      it('creates a new view with the computed view name', () => {\n        const startViewSpy = jasmine.createSpy()\n        initializeReactPlugin({\n          configuration: {\n            router: true,\n          },\n          publicApi: {\n            startView: startViewSpy,\n          },\n        })\n\n        startReactRouterView([\n          { route: { path: '/' } },\n          { route: { path: 'user' } },\n          { route: { path: ':id' } },\n        ] as unknown as AnyRouteMatch[])\n\n        expect(startViewSpy).toHaveBeenCalledOnceWith('/user/:id')\n      })\n\n      it('displays a warning if the router integration is not enabled', () => {\n        const displayWarnSpy = spyOn(display, 'warn')\n        initializeReactPlugin({\n          configuration: {},\n        })\n\n        startReactRouterView([] as unknown as RouteMatchV6[] & RouteMatchV7[])\n        expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n          '`router: true` is missing from the react plugin configuration, the view will not be tracked.'\n        )\n      })\n    })\n\n    describe('computeViewName', () => {\n      it('returns an empty string if there is no route match', () => {\n        expect(computeViewName([] as unknown as RouteMatchV6[] & RouteMatchV7[])).toBe('')\n      })\n\n      it('ignores routes without a path', () => {\n        expect(\n          computeViewName([\n            { route: { path: '/foo' } },\n            { route: {} },\n            { route: { path: ':id' } },\n          ] as unknown as RouteMatchV6[] & RouteMatchV7[])\n        ).toBe('/foo/:id')\n      })\n\n      // prettier-ignore\n      const cases = [\n        // route paths,         path,           expected view name\n\n        // Simple paths\n        ['/foo',                '/foo',         '/foo'],\n        ['/foo',                '/bar',         '/foo'], // apparently when the path doesn't match any route, React Router returns the last route as a matching route\n        ['/foo > bar',          '/foo/bar',     '/foo/bar'],\n        ['/foo > bar > :p',     '/foo/bar/1',   '/foo/bar/:p'],\n        [':p',                  '/foo',         '/:p'],\n        ['/foo/:p',             '/foo/bar',     '/foo/:p'],\n        ['/foo > :p',           '/foo/bar',     '/foo/:p'],\n        ['/:a/:b',              '/foo/bar',     '/:a/:b'],\n        ['/:a > :b',            '/foo/bar',     '/:a/:b'],\n        ['/foo-:a',             '/foo-1',       '/foo-:a'],\n        ['/foo/ > bar/ > :id/', '/foo/bar/1/',  '/foo/bar/:id/'],\n        ['/foo > /foo/bar > /foo/bar/:id',\n                                '/foo/bar/1',   '/foo/bar/:id'],\n\n        // Splats\n        ['*',                   '/foo/1',       '/foo/1'],\n        ['*',                   '/',            '/'],\n        ['/foo/*',              '/foo/1',       '/foo/1'],\n        ['/foo > *',            '/foo/1',       '/foo/1'],\n        ['* > *',               '/foo/1',       '/foo/1'],\n        ['* > *',               '/',            '/'],\n        ['/foo/* > *',          '/foo/1',       '/foo/1'],\n        ['* > foo/*',           '/foo/1',       '/foo/1'],\n        ['/foo/* > bar/*',      '/foo/bar/1',   '/foo/bar/1'],\n        ['/foo/* > bar',        '/foo/bar',     '/foo/bar'],\n        ['/foo/:p > *',         '/foo/bar/baz', '/foo/:p/baz'],\n        ['/:p > *',             '/foo/bar/1',   '/:p/bar/1'],\n        ['/foo/* > :p',         '/foo/bar',     '/foo/:p'],\n\n        // Extra edge cases - React Router does not provide the matched path in those case\n        ['/foo/*/bar',          '/foo/1/bar',   '/foo/*/bar'],\n        ['/foo/*-bar',          '/foo/1-bar',   '/foo/*-bar'],\n        ['*/*',                 '/foo/1',       '/*/*'],\n      ] as const\n\n      cases.forEach(([routePaths, path, expectedViewName]) => {\n        it(`returns \"${expectedViewName}\" for route \"${path}\" and config \"${routePaths}\"`, () => {\n          // Convert the routePaths representing nested routes paths delimited by ' > ' to an actual\n          // react-router route object. Example: '/foo > bar > :p' would be turned into\n          // { path: '/foo', children: [{ path: 'bar', children: [{ path: ':p' }] }] }\n          const route = routePaths\n            .split(' > ')\n            .reduceRight(\n              (childRoute, routePath) => ({ path: routePath, children: childRoute ? [childRoute] : undefined }),\n              undefined as RouteObjectV6 | RouteObjectV7 | undefined\n            )!\n\n          const router = createMemoryRouter([route] as any, {\n            initialEntries: [path],\n          })\n          registerCleanupTask(() => router.dispose())\n          expect(computeViewName(router.state.matches as any)).toEqual(expectedViewName)\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/startReactRouterView.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport { onRumInit } from '../reactPlugin'\nimport type { AnyRouteMatch } from './types'\n\nexport function startReactRouterView(routeMatches: AnyRouteMatch[]) {\n  onRumInit((configuration, rumPublicApi) => {\n    if (!configuration.router) {\n      display.warn('`router: true` is missing from the react plugin configuration, the view will not be tracked.')\n      return\n    }\n    rumPublicApi.startView(computeViewName(routeMatches))\n  })\n}\n\nexport function computeViewName(routeMatches: AnyRouteMatch[]) {\n  if (!routeMatches || routeMatches.length === 0) {\n    return ''\n  }\n\n  let viewName = '/'\n\n  for (const routeMatch of routeMatches) {\n    let path = routeMatch.route.path\n    if (!path) {\n      continue\n    }\n\n    path = substitutePathSplats(path, routeMatch.params, routeMatch === routeMatches[routeMatches.length - 1])\n\n    if (path.startsWith('/')) {\n      // Absolute path, replace the current view name\n      viewName = path\n    } else {\n      // Relative path, append to the current view name\n      if (!viewName.endsWith('/')) {\n        viewName += '/'\n      }\n      viewName += path\n    }\n  }\n\n  return viewName\n}\n\n/**\n * React-Router allows to define routes with \"splats\" (or \"catchall\" or \"star\") segments[1],\n * example: /files/*. It has been noticed that keeping those splats in the view name isn't helpful\n * as it \"hides\" too much information. This function replaces the splats with the actual URL path\n * name that they are matching.\n *\n * [1]: https://reactrouter.com/en/main/route/route#splats\n *\n * @example\n * substitutePathSplats('/files/*', { '*': 'path/to/file' }, true) // => '/files/path/to/file'\n */\nfunction substitutePathSplats(path: string, params: Record<string, string | undefined>, isLastMatchingRoute: boolean) {\n  if (\n    !path.includes('*') ||\n    // In some edge cases, react-router does not provide the `*` parameter, so we don't know what to\n    // replace it with. In this case, we keep the asterisk.\n    params['*'] === undefined\n  ) {\n    return path\n  }\n\n  // The `*` parameter is only related to the last matching route path.\n  if (isLastMatchingRoute) {\n    return path.replace(/\\*/, params['*'])\n  }\n\n  // Intermediary route paths with a `*` are kind of edge cases, and the `*` parameter is not\n  // relevant for them. We remove it from the path (along with a potential slash preceeding it) to\n  // have a coherent view name once everything is concatenated (see examples in spec file).\n  return path.replace(/\\/?\\*/, '')\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/types.ts",
    "content": "// Those types are used by our instrumentation functions to make them work with any react-router\n// version we support. We should not import react-router types as we don't know which version\n// will be used by the customer.\n//\n// Those types should be:\n// * compatible with all react-router-dom versions we support\n// * include the minimal set of attributes used by our instrumentation functions.\n\nexport interface AnyRouteObject {\n  path?: string | undefined\n  element?: React.ReactNode\n}\nexport type AnyUseRoute<Location extends AnyLocation> = (\n  routes: AnyRouteObject[],\n  location?: Location\n) => React.ReactElement | null\nexport interface AnyRouteMatch {\n  route: AnyRouteObject\n  params: Record<string, string | undefined>\n}\nexport type AnyLocation = { pathname?: string } | string\nexport type AnyCreateRouter<Options> = (\n  routes: AnyRouteObject[],\n  options?: Options\n) => {\n  state: { location: { pathname: string }; matches: AnyRouteMatch[] }\n  subscribe: (callback: (routerState: { location: { pathname: string }; matches: AnyRouteMatch[] }) => void) => void\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/useRoutes.spec.tsx",
    "content": "import React, { act } from 'react'\nimport * as rrdom6 from 'react-router-dom-6'\nimport * as rrdom7 from 'react-router-dom'\nimport { appendComponent } from '../../../test/appendComponent'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { initReactOldBrowsersSupport } from '../../../test/reactOldBrowsersSupport'\nimport { ignoreConsoleLogs } from '../../../../core/test'\nimport type { AnyRouteObject } from './types'\nimport { ignoreReactRouterDeprecationWarnings } from './reactRouter.specHelper'\nimport { wrapUseRoutes } from './useRoutes'\n\nconst versions = [\n  {\n    version: 'react-router-6',\n    MemoryRouter: rrdom6.MemoryRouter,\n    useNavigate: rrdom6.useNavigate,\n    useRoutes: wrapUseRoutes({\n      useRoutes: rrdom6.useRoutes,\n      useLocation: rrdom6.useLocation,\n      matchRoutes: rrdom6.matchRoutes,\n    }),\n  },\n  {\n    version: 'react-router-7',\n    MemoryRouter: rrdom7.MemoryRouter,\n    useNavigate: rrdom7.useNavigate,\n    useRoutes: wrapUseRoutes({\n      useRoutes: rrdom7.useRoutes,\n      useLocation: rrdom7.useLocation,\n      matchRoutes: rrdom7.matchRoutes,\n    }),\n  },\n]\n\nversions.forEach(({ version, MemoryRouter, useNavigate, useRoutes }) => {\n  type NavigateFunction = ReturnType<typeof useNavigate>\n\n  function RoutesRenderer({\n    routes,\n    location,\n  }: {\n    routes: AnyRouteObject[]\n    location?: { pathname: string } | string\n  }) {\n    return useRoutes(routes, location)\n  }\n\n  describe(`useRoutes (${version})`, () => {\n    let startViewSpy: jasmine.Spy<(name?: string | object) => void>\n\n    beforeEach(() => {\n      ignoreReactRouterDeprecationWarnings()\n      initReactOldBrowsersSupport()\n      startViewSpy = jasmine.createSpy()\n      initializeReactPlugin({\n        configuration: {\n          router: true,\n        },\n        publicApi: {\n          startView: startViewSpy,\n        },\n      })\n    })\n\n    it('starts a new view as soon as it is rendered', () => {\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <RoutesRenderer\n            routes={[\n              {\n                path: '/foo',\n                element: null,\n              },\n            ]}\n          />\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/foo')\n    })\n\n    it('renders the matching route', () => {\n      const container = appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <RoutesRenderer\n            routes={[\n              {\n                path: '/foo',\n                element: 'foo',\n              },\n            ]}\n          />\n        </MemoryRouter>\n      )\n\n      expect(container.innerHTML).toBe('foo')\n    })\n\n    it('does not start a new view on re-render', () => {\n      let forceUpdate: () => void\n\n      function App() {\n        const [, setState] = React.useState(0)\n        forceUpdate = () => setState((s) => s + 1)\n        return (\n          <MemoryRouter initialEntries={['/foo']}>\n            <RoutesRenderer\n              routes={[\n                {\n                  path: '/foo',\n                  element: null,\n                },\n              ]}\n            />\n          </MemoryRouter>\n        )\n      }\n\n      appendComponent(<App />)\n\n      expect(startViewSpy).toHaveBeenCalledTimes(1)\n\n      act(() => {\n        forceUpdate!()\n      })\n\n      expect(startViewSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('starts a new view on navigation', async () => {\n      let navigate: NavigateFunction\n\n      function NavBar() {\n        navigate = useNavigate()\n        return null\n      }\n\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <NavBar />\n          <RoutesRenderer\n            routes={[\n              { path: '/foo', element: null },\n              { path: '/bar', element: null },\n            ]}\n          />\n        </MemoryRouter>\n      )\n\n      startViewSpy.calls.reset()\n\n      await act(async () => {\n        await navigate!('/bar')\n      })\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/bar')\n    })\n\n    it('does not start a new view if the URL is the same', async () => {\n      let navigate: NavigateFunction\n\n      function NavBar() {\n        navigate = useNavigate()\n        return null\n      }\n\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <NavBar />\n          <RoutesRenderer routes={[{ path: '/foo', element: null }]} />\n        </MemoryRouter>\n      )\n\n      startViewSpy.calls.reset()\n\n      await act(async () => {\n        await navigate!('/foo')\n      })\n\n      expect(startViewSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not start a new view if the path is the same but with different parameters', async () => {\n      let navigate: NavigateFunction\n\n      function NavBar() {\n        navigate = useNavigate()\n        return null\n      }\n\n      appendComponent(\n        <MemoryRouter initialEntries={['/foo']}>\n          <NavBar />\n          <RoutesRenderer routes={[{ path: '/foo', element: null }]} />\n        </MemoryRouter>\n      )\n\n      startViewSpy.calls.reset()\n\n      await act(async () => {\n        await navigate!('/foo?bar=baz')\n      })\n\n      expect(startViewSpy).not.toHaveBeenCalled()\n    })\n\n    it('does not start a new view if it does not match any route', () => {\n      // Prevent react router from showing a warning in the console when a route does not match\n      ignoreConsoleLogs('warn', 'No routes matched location')\n\n      appendComponent(\n        <MemoryRouter>\n          <RoutesRenderer routes={[{ path: '/bar', element: null }]} />\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).not.toHaveBeenCalled()\n    })\n\n    it('allows passing a location object', () => {\n      appendComponent(\n        <MemoryRouter>\n          <RoutesRenderer routes={[{ path: '/foo', element: null }]} location={{ pathname: '/foo' }} />\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/foo')\n    })\n\n    it('allows passing a location string', () => {\n      appendComponent(\n        <MemoryRouter>\n          <RoutesRenderer\n            routes={[\n              {\n                path: '/foo',\n                element: null,\n              },\n            ]}\n            location=\"/foo\"\n          />\n        </MemoryRouter>\n      )\n\n      expect(startViewSpy).toHaveBeenCalledOnceWith('/foo')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-react/src/domain/reactRouter/useRoutes.ts",
    "content": "import { useRef } from 'react'\nimport { startReactRouterView } from './startReactRouterView'\nimport type { AnyUseRoute, AnyRouteObject, AnyRouteMatch } from './types'\n\nexport function wrapUseRoutes<T extends AnyUseRoute<any>>({\n  useRoutes,\n  useLocation,\n  matchRoutes,\n}: {\n  useRoutes: T\n  useLocation: () => { pathname: string }\n  matchRoutes: (routes: AnyRouteObject[], pathname: string) => AnyRouteMatch[] | null\n}): T {\n  return ((routes, locationArg) => {\n    const location = useLocation()\n    const pathname = typeof locationArg === 'string' ? locationArg : locationArg?.pathname || location.pathname\n    const pathnameRef = useRef<string | null>(null)\n\n    if (pathnameRef.current !== pathname) {\n      pathnameRef.current = pathname\n      const matchedRoutes = matchRoutes(routes, pathname)\n      if (matchedRoutes) {\n        startReactRouterView(matchedRoutes)\n      }\n    }\n\n    return useRoutes(routes, locationArg)\n  }) as T\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/tanstackRouter/startTanStackRouterView.spec.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { startTanStackRouterView, computeViewName } from './startTanStackRouterView'\nimport type { AnyTanStackRouteMatch } from './types'\n\ndescribe('startTanStackRouterView', () => {\n  it('creates a new view with the computed view name', () => {\n    const startViewSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      configuration: {\n        router: true,\n      },\n      publicApi: {\n        startView: startViewSpy,\n      },\n    })\n\n    startTanStackRouterView([\n      { fullPath: '/', pathname: '/', params: {} },\n      { fullPath: '/users/$userId', pathname: '/users/1', params: { userId: '1' } },\n    ])\n\n    expect(startViewSpy).toHaveBeenCalledOnceWith('/users/$userId')\n  })\n\n  it('displays a warning if the router integration is not enabled', () => {\n    const displayWarnSpy = spyOn(display, 'warn')\n    initializeReactPlugin({\n      configuration: {},\n    })\n\n    startTanStackRouterView([])\n    expect(displayWarnSpy).toHaveBeenCalledOnceWith(\n      '`router: true` is missing from the react plugin configuration, the view will not be tracked.'\n    )\n  })\n\n  describe('computeViewName', () => {\n    it('returns an empty string if there is no route match', () => {\n      expect(computeViewName([])).toBe('')\n    })\n\n    // prettier-ignore\n    const cases = [\n    // route paths,                path,           expected view name\n\n    // Simple paths\n    ['/foo',                      '/foo',         '/foo'],\n    ['/foo > /',                  '/foo',         '/foo'],\n    ['/foo > bar',                '/foo/bar',     '/foo/bar'],\n    ['/foo > bar > $p',           '/foo/bar/1',   '/foo/bar/$p'],\n    ['$p',                        '/foo',         '/$p'],\n    ['/foo/$p',                   '/foo/bar',     '/foo/$p'],\n    ['/foo > $p',                 '/foo/bar',     '/foo/$p'],\n    ['/$a/$b',                    '/foo/bar',     '/$a/$b'],\n    ['/$a > $b',                  '/foo/bar',     '/$a/$b'],\n\n    // Splats — TanStack uses \"$\" for catch-all segments, substituted with actual path\n    ['$',                         '/foo/1',       '/foo/1'],\n    ['$',                         '/',            '/'],\n    ['/foo/$',                    '/foo/1',       '/foo/1'],\n    ['/foo > $',                  '/foo/1',       '/foo/1'],\n    ['/foo/$p > $',               '/foo/bar/baz', '/foo/$p/baz'],\n    ['/$p > $',                   '/foo/bar/1',   '/$p/bar/1'],\n  ] as const\n\n    cases.forEach(([routePaths, path, expectedViewName]) => {\n      it(`returns \"${expectedViewName}\" for route \"${path}\" and config \"${routePaths}\"`, () => {\n        const router = buildRouter(routePaths, path)\n\n        expect(computeViewName(router.state.matches)).toEqual(expectedViewName)\n      })\n    })\n\n    it('keeps the splat pattern when _splat param is not available', () => {\n      expect(\n        computeViewName([\n          { fullPath: '/', pathname: '/', params: {} },\n          { fullPath: '/files/$', pathname: '/files/', params: {} },\n        ])\n      ).toBe('/files/$')\n    })\n  })\n})\n\n/**\n * Build a mock router that mimics TanStack Router's resolved state for a given route config and\n * path. The routePaths string uses ' > ' to delimit nested route segments (e.g. '/foo > bar > $p').\n */\nfunction buildRouter(routePaths: string, path: string) {\n  const segments = routePaths.split(' > ')\n  let fullPath = ''\n  for (const segment of segments) {\n    if (segment === '/') {\n      fullPath += '/'\n    } else if (segment.startsWith('/')) {\n      fullPath += segment\n    } else {\n      fullPath += `/${segment}`\n    }\n  }\n\n  const params: Record<string, string> = {}\n  const templateParts = fullPath.split('/')\n  const pathParts = path.split('/')\n\n  let pathIdx = 0\n  for (let i = 0; i < templateParts.length; i++) {\n    const tpl = templateParts[i]\n    if (tpl === '$') {\n      params._splat = pathParts.slice(pathIdx).join('/')\n      break\n    } else if (tpl.startsWith('$')) {\n      params[tpl.slice(1)] = pathParts[pathIdx] || ''\n    }\n    pathIdx++\n  }\n\n  return {\n    state: {\n      matches: [{ fullPath, pathname: path, params }] as AnyTanStackRouteMatch[],\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/tanstackRouter/startTanStackRouterView.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport { onRumInit } from '../reactPlugin'\nimport type { AnyTanStackRouteMatch } from './types'\n\nexport function startTanStackRouterView(routeMatches: AnyTanStackRouteMatch[]) {\n  onRumInit((configuration, rumPublicApi) => {\n    if (!configuration.router) {\n      display.warn('`router: true` is missing from the react plugin configuration, the view will not be tracked.')\n      return\n    }\n    rumPublicApi.startView(computeViewName(routeMatches))\n  })\n}\n\nexport function computeViewName(routeMatches: AnyTanStackRouteMatch[]) {\n  if (routeMatches.length === 0) {\n    return ''\n  }\n\n  // TanStack Router provides `fullPath` on each match, which is the route template\n  // with param placeholders (e.g., \"/posts/$postId\"). The last match is the most\n  // specific route, and its fullPath is the complete view name.\n  const lastMatch = routeMatches[routeMatches.length - 1]\n  let viewName = lastMatch.fullPath\n\n  // Handle splat routes: TanStack uses bare \"$\" for catch-all segments.\n  // Replace the splat placeholder with the actual matched path for better readability,\n  // consistent with how the React Router integration handles \"*\" splats.\n  viewName = substitutePathSplats(viewName, lastMatch.params)\n\n  // Remove trailing slash (e.g. \"/posts/\" → \"/posts\") happening when the last match is an index route\n  if (viewName.endsWith('/')) {\n    viewName = viewName.slice(0, -1)\n  }\n\n  return viewName || '/'\n}\n\n/**\n * TanStack Router uses a bare \"$\" for catch-all (splat) segments.\n * Example: \"/files/$\" with params._splat = \"path/to/file\" → \"/files/path/to/file\"\n *\n * Keeping the \"$\" in the view name isn't helpful as it hides information.\n * We replace it with the actual matched path, consistent with React Router's \"*\" handling.\n */\nfunction substitutePathSplats(path: string, params: Record<string, string | undefined>): string {\n  if (!path.endsWith('/$') || params._splat === undefined) {\n    return path\n  }\n\n  return path.replace(/\\/\\$$/, `/${params._splat}`)\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/tanstackRouter/types.ts",
    "content": "// Those types are used by our instrumentation functions to make them work with\n// TanStack Router without directly importing its types. This avoids version coupling\n// and ensures compatibility across TanStack Router v1 releases.\n//\n// Those types should be:\n// * compatible with all @tanstack/react-router v1 versions we support\n// * include the minimal set of attributes used by our instrumentation functions.\n\nexport interface AnyTanStackRouteMatch {\n  fullPath: string\n  pathname: string\n  params: Record<string, string | undefined>\n}\n\nexport interface AnyTanStackNavigationEvent {\n  type: string\n  pathChanged: boolean\n  toLocation: { pathname: string }\n}\n\nexport interface AnyTanStackRouterInstance {\n  state: {\n    location: { pathname: string }\n    matches: AnyTanStackRouteMatch[]\n  }\n  subscribe: (eventType: 'onLoad', fn: (event: AnyTanStackNavigationEvent) => void) => () => void\n}\n\nexport type AnyTanStackCreateRouter = (options: any) => AnyTanStackRouterInstance\n"
  },
  {
    "path": "packages/rum-react/src/domain/tanstackRouter/wrapCreateRouter.spec.ts",
    "content": "import { initializeReactPlugin } from '../../../test/initializeReactPlugin'\nimport { wrapCreateRouter } from './wrapCreateRouter'\nimport type { AnyTanStackCreateRouter, AnyTanStackNavigationEvent, AnyTanStackRouterInstance } from './types'\n\ndescribe('wrapCreateRouter', () => {\n  let startViewSpy: jasmine.Spy<(name?: string | object) => void>\n\n  beforeEach(() => {\n    startViewSpy = jasmine.createSpy()\n    initializeReactPlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n  })\n\n  it('should start a view when onLoad fires with pathChanged', () => {\n    const { triggerOnLoad } = createFakeRouter([\n      { fullPath: '/', pathname: '/', params: {} },\n      { fullPath: '/posts/$postId', pathname: '/posts/42', params: { postId: '42' } },\n    ])\n\n    triggerOnLoad({ type: 'onLoad', pathChanged: true, toLocation: { pathname: '/posts/42' } })\n\n    expect(startViewSpy).toHaveBeenCalledWith('/posts/$postId')\n  })\n\n  it('should not start a new view when only query params change', () => {\n    const { triggerOnLoad } = createFakeRouter([{ fullPath: '/', pathname: '/', params: {} }])\n\n    startViewSpy.calls.reset()\n    triggerOnLoad({ type: 'onLoad', pathChanged: false, toLocation: { pathname: '/' } })\n\n    expect(startViewSpy).not.toHaveBeenCalled()\n  })\n\n  it('should track the initial view via onLoad', () => {\n    const { triggerOnLoad } = createFakeRouter([{ fullPath: '/', pathname: '/', params: {} }])\n\n    triggerOnLoad({ type: 'onLoad', pathChanged: true, toLocation: { pathname: '/' } })\n\n    expect(startViewSpy).toHaveBeenCalledWith('/')\n  })\n\n  it('should use the last match fullPath as view name', () => {\n    const { triggerOnLoad } = createFakeRouter([\n      { fullPath: '/', pathname: '/', params: { userId: '1' } },\n      { fullPath: '/users/$userId', pathname: '/users/1', params: { userId: '1' } },\n    ])\n\n    triggerOnLoad({ type: 'onLoad', pathChanged: true, toLocation: { pathname: '/users/1' } })\n\n    expect(startViewSpy).toHaveBeenCalledWith('/users/$userId')\n  })\n\n  it('should substitute splat routes with actual path', () => {\n    const { triggerOnLoad } = createFakeRouter([\n      { fullPath: '/', pathname: '/', params: { _splat: 'deep/path' } },\n      { fullPath: '/files/$', pathname: '/files/deep/path', params: { _splat: 'deep/path' } },\n    ])\n\n    triggerOnLoad({ type: 'onLoad', pathChanged: true, toLocation: { pathname: '/files/deep/path' } })\n\n    expect(startViewSpy).toHaveBeenCalledWith('/files/deep/path')\n  })\n\n  it('should return \"/\" for root route', () => {\n    const { triggerOnLoad } = createFakeRouter([\n      { fullPath: '/', pathname: '/', params: {} },\n      { fullPath: '/', pathname: '/', params: {} },\n    ])\n\n    triggerOnLoad({ type: 'onLoad', pathChanged: true, toLocation: { pathname: '/' } })\n\n    expect(startViewSpy).toHaveBeenCalledWith('/')\n  })\n})\n\nfunction createFakeRouter(matches: AnyTanStackRouterInstance['state']['matches']) {\n  let onLoadCallback: ((event: AnyTanStackNavigationEvent) => void) | undefined\n\n  const fakeCreateRouter: AnyTanStackCreateRouter = () => ({\n    state: {\n      location: { pathname: matches[matches.length - 1]?.pathname || '/' },\n      matches,\n    },\n    subscribe: (_eventType: 'onLoad', fn: (event: AnyTanStackNavigationEvent) => void) => {\n      onLoadCallback = fn\n      return () => {\n        onLoadCallback = undefined\n      }\n    },\n  })\n\n  wrapCreateRouter(fakeCreateRouter)({})\n\n  return {\n    triggerOnLoad: (event: AnyTanStackNavigationEvent) => {\n      onLoadCallback?.(event)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/rum-react/src/domain/tanstackRouter/wrapCreateRouter.ts",
    "content": "import { startTanStackRouterView } from './startTanStackRouterView'\nimport type { AnyTanStackCreateRouter } from './types'\n\n/**\n * Wraps TanStack Router's `createRouter` to automatically track route changes as RUM views.\n *\n * Subscribes to the `onLoad` event which fires after loaders complete but before rendering.\n * This is the earliest event where route matches are up to date, ensuring rendering-related\n * events (resources, errors) are attributed to the correct view. Only creates a new view\n * when the pathname changes (query param and hash changes are ignored).\n */\nexport function wrapCreateRouter<CreateRouter extends AnyTanStackCreateRouter>(\n  originalCreateRouter: CreateRouter\n): CreateRouter {\n  return ((options: any) => {\n    const router = originalCreateRouter(options)\n\n    // onLoad fires for the initial navigation too, so no explicit initial view call is needed\n    router.subscribe('onLoad', (event) => {\n      if (!event.pathChanged) {\n        return\n      }\n      startTanStackRouterView(router.state.matches)\n    })\n\n    return router\n  }) as CreateRouter\n}\n"
  },
  {
    "path": "packages/rum-react/src/entries/internal.ts",
    "content": "export { createErrorBoundary } from '../domain/error'\nexport type { ErrorBoundaryFallback, ErrorBoundaryProps } from '../domain/error'\n"
  },
  {
    "path": "packages/rum-react/src/entries/main.ts",
    "content": "import type { ErrorBoundaryProps, ErrorBoundaryFallback } from '../domain/error'\n\nexport { ErrorBoundary, addReactError } from '../domain/error'\nexport type { ErrorBoundaryFallback, ErrorBoundaryProps } from '../domain/error'\nexport type { ReactPluginConfiguration, ReactPlugin } from '../domain/reactPlugin'\nexport { reactPlugin } from '../domain/reactPlugin'\n// eslint-disable-next-line camelcase\nexport { UNSTABLE_ReactComponentTracker } from '../domain/performance'\n\n/**\n * @deprecated Use {@link ErrorBoundaryProps} instead.\n */\nexport type Props = ErrorBoundaryProps\n\n/**\n * @deprecated Use {@link ErrorBoundaryFallback} instead.\n */\nexport type Fallback = ErrorBoundaryFallback\n"
  },
  {
    "path": "packages/rum-react/src/entries/reactRouterV6.ts",
    "content": "/**\n * React Router v6 integration.\n *\n * @packageDocumentation\n * @example\n * ```ts\n * import { RouterProvider } from 'react-router-dom'\n * import { datadogRum } from '@datadog/browser-rum'\n * import { reactPlugin } from '@datadog/browser-rum-react'\n *\n * // ⚠️ Use \"createBrowserRouter\" from `@datadog/browser-rum-react/react-router-v6` instead of `react-router-dom`\n * import { createBrowserRouter } from '@datadog/browser-rum-react/react-router-v6'\n *\n * datadogRum.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   plugins: [reactPlugin({ router: true })],\n *   // ...\n * })\n *\n * const router = createBrowserRouter([\n *   {\n *     path: '/',\n *     element: <Root />,\n *     // ...\n *   },\n * ])\n *\n * ReactDOM.createRoot(document.getElementById('root')).render(<RouterProvider router={router} />)\n * ```\n */\n/* eslint-disable local-rules/disallow-side-effects */\n\nimport {\n  createBrowserRouter as originalCreateBrowserRouter,\n  createHashRouter as originalCreateHashRouter,\n  createMemoryRouter as originalCreateMemoryRouter,\n  useRoutes as originalUseRoutes,\n  useLocation,\n  matchRoutes,\n  createRoutesFromChildren,\n} from 'react-router-dom'\nimport type { Routes as originalRoutes } from 'react-router-dom'\nimport { wrapCreateRouter, createRoutesComponent, wrapUseRoutes } from '../domain/reactRouter'\n\n/**\n * Use this function in place of `react-router-dom` `createBrowserRouter`. Every time a route is\n * rendered, a new RUM view is created.\n *\n * @see https://reactrouter.com/v6/routers/create-browser-router\n */\nexport const createBrowserRouter: typeof originalCreateBrowserRouter = wrapCreateRouter(originalCreateBrowserRouter)\n\n/**\n * Use this function in place of `react-router-dom` `createHashRouter`. Every time a route is\n * rendered, a new RUM view is created.\n *\n * @see https://reactrouter.com/v6/routers/create-hash-router\n */\nexport const createHashRouter: typeof originalCreateHashRouter = wrapCreateRouter(originalCreateHashRouter)\n\n/**\n * Use this function in place of `react-router-dom` `createMemoryRouter`. Every time a route is\n * rendered, a new RUM view is created.\n *\n * @see https://reactrouter.com/v6/routers/create-memory-router\n */\nexport const createMemoryRouter: typeof originalCreateMemoryRouter = wrapCreateRouter(originalCreateMemoryRouter)\n\n/**\n * Use this hook in place of `react-router-dom` `useRoutes`. Every time a route is rendered, a new\n * RUM view is created.\n *\n * @see https://reactrouter.com/docs/en/v6/hooks/use-routes\n */\nexport const useRoutes: typeof originalUseRoutes = wrapUseRoutes({\n  useRoutes: originalUseRoutes,\n  useLocation,\n  matchRoutes,\n})\n\n/**\n * Use this component in place of `react-router-dom` `Routes`. Every time a route is rendered, a new\n * RUM view is created.\n *\n * @see https://reactrouter.com/docs/en/v6/components/routes\n */\nexport const Routes: typeof originalRoutes = createRoutesComponent(useRoutes, createRoutesFromChildren)\n"
  },
  {
    "path": "packages/rum-react/src/entries/reactRouterV7.ts",
    "content": "/**\n * React Router v7 integration.\n *\n * @packageDocumentation\n * @example\n * ```ts\n * import { RouterProvider } from 'react-router'\n * import { datadogRum } from '@datadog/browser-rum'\n * import { reactPlugin } from '@datadog/browser-rum-react'\n *\n * // ⚠️ Use \"createBrowserRouter\" from `@datadog/browser-rum-react/react-router-v7` instead of `react-router`\n * import { createBrowserRouter } from '@datadog/browser-rum-react/react-router-v7'\n *\n * datadogRum.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   plugins: [reactPlugin({ router: true })],\n *   // ...\n * })\n *\n * const router = createBrowserRouter([\n *   {\n *     path: '/',\n *     element: <Root />,\n *     // ...\n *   },\n * ])\n *\n * ReactDOM.createRoot(document.getElementById('root')).render(<RouterProvider router={router} />)\n * ```\n */\n/* eslint-disable local-rules/disallow-side-effects */\n\nimport {\n  createBrowserRouter as originalCreateBrowserRouter,\n  createHashRouter as originalCreateHashRouter,\n  createMemoryRouter as originalCreateMemoryRouter,\n  useRoutes as originalUseRoutes,\n  useLocation,\n  matchRoutes,\n  createRoutesFromChildren,\n} from 'react-router'\nimport type { Routes as originalRoutes } from 'react-router'\nimport { wrapCreateRouter, createRoutesComponent, wrapUseRoutes } from '../domain/reactRouter'\n\n/**\n * Use this function in place of `react-router-dom` `createBrowserRouter`. Every time a route is\n * rendered, a new RUM view is created.\n *\n * @see https://reactrouter.com/v7/api/data-routers/createBrowserRouter\n */\nexport const createBrowserRouter: typeof originalCreateBrowserRouter = wrapCreateRouter(originalCreateBrowserRouter)\n\n/**\n * Use this function in place of `react-router-dom` `createHashRouter`. Every time a route is\n * rendered, a new RUM view is created.\n *\n * @see https://reactrouter.com/v7/api/data-routers/createHashRouter\n */\nexport const createHashRouter: typeof originalCreateHashRouter = wrapCreateRouter(originalCreateHashRouter)\n\n/**\n * Use this function in place of `react-router-dom` `createMemoryRouter`. Every time a route is\n * rendered, a new RUM view is created.\n *\n * @see https://reactrouter.com/v7/api/data-routers/createMemoryRouter\n */\nexport const createMemoryRouter: typeof originalCreateMemoryRouter = wrapCreateRouter(originalCreateMemoryRouter)\n\n/**\n * Use this hook in place of `react-router-dom` `useRoutes`. Every time a route is rendered, a new\n * RUM view is created.\n *\n * @see https://reactrouter.com/v7/api/hooks/useRoutes\n */\nexport const useRoutes: typeof originalUseRoutes = wrapUseRoutes({\n  useRoutes: originalUseRoutes,\n  useLocation,\n  matchRoutes,\n})\n\n/**\n * Use this component in place of `react-router-dom` `Routes`. Every time a route is rendered, a new\n * RUM view is created.\n *\n * @see https://reactrouter.com/v7/api/components/Routes\n */\nexport const Routes: typeof originalRoutes = createRoutesComponent(useRoutes, createRoutesFromChildren)\n"
  },
  {
    "path": "packages/rum-react/src/entries/tanstackRouter.ts",
    "content": "/**\n * TanStack Router integration.\n *\n * @packageDocumentation\n * @example\n * ```ts\n * import { datadogRum } from '@datadog/browser-rum'\n * import { reactPlugin } from '@datadog/browser-rum-react'\n *\n * // ⚠️ Use \"createRouter\" from `@datadog/browser-rum-react/tanstack-router` instead of `@tanstack/react-router`\n * import { createRouter } from '@datadog/browser-rum-react/tanstack-router'\n *\n * datadogRum.init({\n *   applicationId: '<DATADOG_APPLICATION_ID>',\n *   clientToken: '<DATADOG_CLIENT_TOKEN>',\n *   plugins: [reactPlugin({ router: true })],\n *   // ...\n * })\n *\n * const router = createRouter({ routeTree })\n *\n * ReactDOM.createRoot(document.getElementById('root')).render(<RouterProvider router={router} />)\n * ```\n */\n/* eslint-disable local-rules/disallow-side-effects */\n\nimport { createRouter as originalCreateRouter } from '@tanstack/react-router'\nimport { wrapCreateRouter } from '../domain/tanstackRouter/wrapCreateRouter'\n\n/**\n * Use this function in place of `@tanstack/react-router` `createRouter`. Every time a route is\n * resolved, a new RUM view is created.\n *\n * @see https://tanstack.com/router/latest/docs/framework/react/guide/creating-a-router\n */\nexport const createRouter: typeof originalCreateRouter = wrapCreateRouter(originalCreateRouter)\n"
  },
  {
    "path": "packages/rum-react/tanstack-router/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-react/tanstack-router\",\n  \"private\": true,\n  \"main\": \"../cjs/entries/tanstackRouter.js\",\n  \"module\": \"../esm/entries/tanstackRouter.js\",\n  \"types\": \"../cjs/entries/tanstackRouter.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum-react/test/appendComponent.ts",
    "content": "import { createRoot } from 'react-dom/client'\nimport { act } from 'react'\nimport { noop } from '@datadog/browser-core'\nimport { appendElement } from '../../rum-core/test'\nimport { registerCleanupTask } from '../../core/test'\n\nexport function appendComponent(component: React.ReactNode) {\n  const container = appendElement('<div></div>')\n  const root = createRoot(container, {\n    // Do nothing by default when an error occurs\n    onRecoverableError: noop,\n  })\n  act(() => {\n    root.render(component)\n  })\n  registerCleanupTask(() => {\n    act(() => {\n      root.unmount()\n    })\n  })\n  return container\n}\n"
  },
  {
    "path": "packages/rum-react/test/initializeReactPlugin.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\nimport { noop } from '@datadog/browser-core'\nimport type { ReactPluginConfiguration } from '../src/domain/reactPlugin'\nimport { reactPlugin, resetReactPlugin } from '../src/domain/reactPlugin'\nimport { registerCleanupTask } from '../../core/test'\n\nexport function initializeReactPlugin({\n  configuration = {},\n  initConfiguration = {},\n  publicApi = {},\n  addError = noop,\n}: {\n  configuration?: ReactPluginConfiguration\n  initConfiguration?: Partial<RumInitConfiguration>\n  publicApi?: Partial<RumPublicApi>\n  addError?: StartRumResult['addError']\n} = {}) {\n  resetReactPlugin()\n  const plugin = reactPlugin(configuration)\n\n  plugin.onInit({\n    publicApi: publicApi as RumPublicApi,\n    initConfiguration: initConfiguration as RumInitConfiguration,\n  })\n  plugin.onRumStart({\n    addError,\n  })\n\n  registerCleanupTask(() => {\n    resetReactPlugin()\n  })\n}\n"
  },
  {
    "path": "packages/rum-react/test/reactOldBrowsersSupport.ts",
    "content": "import { instrumentMethod } from '@datadog/browser-core'\nimport { registerCleanupTask } from '@datadog/browser-core/test'\n\nexport function initReactOldBrowsersSupport() {\n  // TODO next major, bump browsers to versions supporting measureOptions and remove this instrumentation\n  // see https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure\n  const instrumentation = instrumentMethod(performance, 'measure', ({ parameters }) => {\n    if (typeof parameters[1] === 'object') {\n      // remove unsupported parameters to avoid syntax errors\n      parameters[1] = undefined\n      parameters[2] = undefined\n    }\n  })\n\n  registerCleanupTask(() => {\n    instrumentation.stop()\n  })\n}\n"
  },
  {
    "path": "packages/rum-react/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/entries/main.ts\"]\n}\n"
  },
  {
    "path": "packages/rum-slim/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/rum-slim/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-slim/README.md",
    "content": "# RUM Browser Monitoring - slim package\n\n## Overview\n\nThis package is equivalent to the [RUM package](../rum), but without support for Session Replay\nrecording and the [`compressIntakeRequests`][1] initialization parameter.\n\n## Setup\n\nSee the [RUM package](../rum/README.md) documentation.\n\n[1]: https://docs.datadoghq.com/real_user_monitoring/browser/setup/client/?tab=rum#initialization-parameters:~:text=compressIntakeRequests\n"
  },
  {
    "path": "packages/rum-slim/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-slim\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"bundle/**/*.js\",\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules --bundle datadog-rum-slim.js\",\n    \"build:bundle\": \"node ../../scripts/build/build-package.ts --bundle datadog-rum-slim.js\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-logs\": \"6.32.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-logs\": {\n      \"optional\": true\n    }\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-slim\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-slim/src/boot/stubProfilerApi.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { ProfilerApi } from '@datadog/browser-rum-core'\n\nexport function makeProfilerApiStub(): ProfilerApi {\n  return {\n    onRumStart: noop,\n    stop: noop,\n  }\n}\n"
  },
  {
    "path": "packages/rum-slim/src/boot/stubRecorderApi.ts",
    "content": "import { noop } from '@datadog/browser-core'\nimport type { LifeCycle, RumConfiguration } from '@datadog/browser-rum-core'\nimport { getSessionReplayLink } from '../domain/getSessionReplayLink'\n\nexport function makeRecorderApiStub() {\n  let getSessionReplayLinkStrategy = noop as () => string | undefined\n  return {\n    start: noop,\n    stop: noop,\n    onRumStart(_lifeCycle: LifeCycle, configuration: RumConfiguration) {\n      getSessionReplayLinkStrategy = () => getSessionReplayLink(configuration)\n    },\n    isRecording: () => false,\n    getReplayStats: () => undefined,\n    getSessionReplayLink: () => getSessionReplayLinkStrategy(),\n  }\n}\n"
  },
  {
    "path": "packages/rum-slim/src/domain/getSessionReplayLink.spec.ts",
    "content": "import type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { getSessionReplayLink } from './getSessionReplayLink'\n\nconst DEFAULT_CONFIGURATION = {\n  site: 'datadoghq.com',\n} as RumConfiguration\n\ndescribe('getReplayLink (slim package)', () => {\n  it('should return the replay link with a \"slim-package\" error type', () => {\n    const link = getSessionReplayLink(DEFAULT_CONFIGURATION)\n\n    expect(link).toBe('https://app.datadoghq.com/rum/replay/sessions/no-session-id?error-type=slim-package')\n  })\n})\n"
  },
  {
    "path": "packages/rum-slim/src/domain/getSessionReplayLink.ts",
    "content": "import type { RumConfiguration } from '@datadog/browser-rum-core'\nimport { getSessionReplayUrl } from '@datadog/browser-rum-core'\n\nexport function getSessionReplayLink(configuration: RumConfiguration): string | undefined {\n  return getSessionReplayUrl(configuration, { errorType: 'slim-package' })\n}\n"
  },
  {
    "path": "packages/rum-slim/src/entries/main.ts",
    "content": "// Keep the following in sync with packages/rum/src/entries/main.ts\nimport { defineGlobal, getGlobalObject } from '@datadog/browser-core'\nimport type { RumPublicApi } from '@datadog/browser-rum-core'\nimport { makeRumPublicApi } from '@datadog/browser-rum-core'\nimport { makeRecorderApiStub } from '../boot/stubRecorderApi'\nimport { makeProfilerApiStub } from '../boot/stubProfilerApi'\n\nexport type {\n  User,\n  Account,\n  TraceContextInjection,\n  SessionPersistence,\n  TrackingConsent,\n  MatchOption,\n  ProxyFn,\n  Site,\n  Context,\n  ContextValue,\n  ContextArray,\n  RumInternalContext,\n} from '@datadog/browser-core'\n\n/**\n * @deprecated Use {@link DatadogRum} instead\n */\nexport type RumGlobal = RumPublicApi\n\nexport type {\n  RumPublicApi as DatadogRum,\n  RumInitConfiguration,\n  RumBeforeSend,\n  ViewOptions,\n  StartRecordingOptions,\n  AddDurationVitalOptions,\n  DurationVitalOptions,\n  DurationVitalReference,\n  TracingOption,\n  RumPlugin,\n  OnRumStartOptions,\n  PropagatorType,\n  FeatureFlagsForEvents,\n  MatchHeader,\n\n  // Events\n  CommonProperties,\n  RumEvent,\n  RumActionEvent,\n  RumErrorEvent,\n  RumLongTaskEvent,\n  RumResourceEvent,\n  RumViewEvent,\n  RumVitalEvent,\n\n  // Events context\n  RumEventDomainContext,\n  RumViewEventDomainContext,\n  RumErrorEventDomainContext,\n  RumActionEventDomainContext,\n  RumVitalEventDomainContext,\n  RumFetchResourceEventDomainContext,\n  RumXhrResourceEventDomainContext,\n  RumOtherResourceEventDomainContext,\n  RumLongTaskEventDomainContext,\n} from '@datadog/browser-rum-core'\nexport { DEFAULT_TRACKED_RESOURCE_HEADERS } from '@datadog/browser-rum-core'\nexport { DefaultPrivacyLevel } from '@datadog/browser-core'\n\n/**\n * The global RUM instance. Use this to call RUM methods.\n *\n * @category Main\n * @see {@link DatadogRum}\n * @see [RUM Browser Monitoring Setup](https://docs.datadoghq.com/real_user_monitoring/browser/)\n */\nexport const datadogRum = makeRumPublicApi(makeRecorderApiStub(), makeProfilerApiStub(), {\n  sdkName: 'rum-slim',\n})\n\ninterface BrowserWindow extends Window {\n  DD_RUM?: RumPublicApi\n}\ndefineGlobal(getGlobalObject<BrowserWindow>(), 'DD_RUM', datadogRum)\n"
  },
  {
    "path": "packages/rum-slim/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/entries/main.ts\"]\n}\n"
  },
  {
    "path": "packages/rum-vue/.yarnrc",
    "content": "save-exact true\n"
  },
  {
    "path": "packages/rum-vue/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/rum-vue/README.md",
    "content": "# RUM Browser Monitoring - Vue integration\n\n**Note**: This integration is in Preview. Features and configuration are subject to change.\n\n## Overview\n\nThe Datadog RUM Vue integration provides framework-specific instrumentation to help you monitor and debug Vue 3 applications. This integration adds:\n\n- **Automatic route change detection** using Vue Router v4\n- **View name normalization** that maps dynamic route segments to their parameterized definitions (e.g. `/users/123` becomes `/users/:id`)\n- **Error reporting** through Vue's global error handler with full component stack traces\n- **Full-stack visibility** by correlating frontend performance with backend traces and logs\n\nCombined with Datadog RUM's core capabilities, you can debug performance bottlenecks, track user journeys, monitor Core Web Vitals, and analyze every user session with context.\n\n## Setup\n\nStart by setting up [Datadog RUM][1] in your Vue application:\n\n- If you are creating a RUM application, select **Vue** as the application type.\n- If Vue is not available as an option, select **JavaScript** and follow the steps below to integrate the plugin manually.\n\nAfter configuration, the Datadog App provides instructions for integrating the [RUM-Vue plugin][2] with the Browser SDK.\n\nThis integration requires **Vue v3.5+** and **Vue Router v4+** (if using router view tracking).\n\n## Basic usage\n\n### 1. Initialize the Datadog RUM SDK with the Vue plugin\n\nIn your `main.ts` (or `main.js`):\n\n```js\nimport { datadogRum } from '@datadog/browser-rum'\nimport { vuePlugin } from '@datadog/browser-rum-vue'\n\ndatadogRum.init({\n  applicationId: '<APP_ID>',\n  clientToken: '<CLIENT_TOKEN>',\n  site: 'datadoghq.com',\n  plugins: [vuePlugin()],\n})\n```\n\n### 2. Attach the Vue error handler\n\nUse `addVueError` as your application's global error handler to automatically report Vue errors to Datadog RUM with component stack traces:\n\n```js\nimport { createApp } from 'vue'\nimport { addVueError } from '@datadog/browser-rum-vue'\nimport App from './App.vue'\n\nconst app = createApp(App)\napp.config.errorHandler = addVueError\napp.mount('#app')\n```\n\n## Router view tracking\n\nTo automatically track route changes as RUM views, enable the `router` option in the plugin and use the Datadog `createRouter` wrapper instead of Vue Router's native one.\n\n### 1. Initialize the RUM SDK with router tracking enabled\n\n```js\nimport { datadogRum } from '@datadog/browser-rum'\nimport { vuePlugin } from '@datadog/browser-rum-vue'\n\ndatadogRum.init({\n  applicationId: '<APP_ID>',\n  clientToken: '<CLIENT_TOKEN>',\n  site: 'datadoghq.com',\n  plugins: [vuePlugin({ router: true })],\n})\n```\n\n### 2. Create your router with the Datadog wrapper\n\nReplace Vue Router's `createRouter` with the one from `@datadog/browser-rum-vue/vue-router-v4`:\n\n```js\nimport { createWebHistory } from 'vue-router'\nimport { createRouter } from '@datadog/browser-rum-vue/vue-router-v4'\n\nconst router = createRouter({\n  history: createWebHistory(),\n  routes: [\n    { path: '/', component: Home },\n    { path: '/users', component: Users },\n    { path: '/users/:id', component: UserDetail },\n  ],\n})\n```\n\n### 3. Wire everything together\n\n```js\nimport { createApp } from 'vue'\nimport { createWebHistory } from 'vue-router'\nimport { datadogRum } from '@datadog/browser-rum'\nimport { vuePlugin, addVueError } from '@datadog/browser-rum-vue'\nimport { createRouter } from '@datadog/browser-rum-vue/vue-router-v4'\nimport App from './App.vue'\n\ndatadogRum.init({\n  applicationId: '<APP_ID>',\n  clientToken: '<CLIENT_TOKEN>',\n  site: 'datadoghq.com',\n  plugins: [vuePlugin({ router: true })],\n})\n\nconst router = createRouter({\n  history: createWebHistory(),\n  routes: [\n    { path: '/', component: Home },\n    { path: '/users', component: Users },\n    { path: '/users/:id', component: UserDetail },\n  ],\n})\n\nconst app = createApp(App)\napp.config.errorHandler = addVueError\napp.use(router)\napp.mount('#app')\n```\n\n## Route tracking\n\nThe `createRouter` wrapper automatically tracks route changes and normalizes dynamic segments into parameterized view names:\n\n| Actual URL             | View name                  |\n| ---------------------- | -------------------------- |\n| `/about`               | `/about`                   |\n| `/users/123`           | `/users/:id`               |\n| `/users/123/posts/456` | `/users/:id/posts/:postId` |\n| `/docs/a/b/c`          | `/docs/:pathMatch(.*)* `   |\n\n## Go further with Datadog Vue integration\n\n### Traces\n\nConnect your RUM and trace data to get a complete view of your application's performance. See [Connect RUM and Traces][3].\n\n### Logs\n\nTo forward your Vue application's logs to Datadog, see [JavaScript Logs Collection][4].\n\n### Metrics\n\nTo generate custom metrics from your RUM application, see [Generate Metrics][5].\n\n## Troubleshooting\n\nNeed help? Contact [Datadog Support][6].\n\n[1]: https://docs.datadoghq.com/real_user_monitoring/browser/setup/client\n[2]: https://www.npmjs.com/package/@datadog/browser-rum-vue\n[3]: https://docs.datadoghq.com/real_user_monitoring/platform/connect_rum_and_traces/?tab=browserrum\n[4]: https://docs.datadoghq.com/logs/log_collection/javascript/\n[5]: https://docs.datadoghq.com/real_user_monitoring/generate_metrics\n[6]: https://docs.datadoghq.com/help/\n"
  },
  {
    "path": "packages/rum-vue/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-vue\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"cjs/entries/main.js\",\n  \"module\": \"esm/entries/main.js\",\n  \"types\": \"cjs/entries/main.d.ts\",\n  \"files\": [\n    \"cjs\",\n    \"esm\",\n    \"src\",\n    \"vue-router-v4\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --modules\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\",\n    \"@datadog/browser-rum-core\": \"6.32.0\"\n  },\n  \"peerDependencies\": {\n    \"vue\": \"^3.5.0\",\n    \"vue-router\": \"^4.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-slim\": {\n      \"optional\": true\n    },\n    \"vue\": {\n      \"optional\": true\n    },\n    \"vue-router\": {\n      \"optional\": true\n    }\n  },\n  \"devDependencies\": {\n    \"@vue/test-utils\": \"2.4.6\",\n    \"vue\": \"3.5.32\",\n    \"vue-router\": \"5.0.4\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/rum-vue\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/rum-vue/src/domain/error/addVueError.spec.ts",
    "content": "import type { ComponentInternalInstance, ComponentPublicInstance } from 'vue'\nimport { initializeVuePlugin } from '../../../test/initializeVuePlugin'\nimport { addVueError } from './addVueError'\n\ndescribe('addVueError', () => {\n  it('reports the error to the SDK with info as first line of component_stack', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeVuePlugin({ addError: addErrorSpy })\n\n    const error = new Error('something broke')\n    addVueError(error, null, 'mounted hook')\n\n    expect(addErrorSpy).toHaveBeenCalledOnceWith(\n      jasmine.objectContaining({\n        error,\n        handlingStack: jasmine.any(String),\n        componentStack: 'mounted hook',\n        startClocks: jasmine.any(Object),\n        context: { framework: 'vue' },\n      })\n    )\n  })\n\n  it('includes component hierarchy in component_stack when instance is provided', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeVuePlugin({ addError: addErrorSpy })\n\n    // Build a mock instance chain without @vue/test-utils to avoid\n    // Object.fromEntries compatibility issues on older browsers\n    const parentInternal = { type: { name: 'ParentComponent' }, parent: null } as unknown as ComponentInternalInstance\n    const childInternal = {\n      type: { name: 'ChildComponent' },\n      parent: parentInternal,\n    } as unknown as ComponentInternalInstance\n    const mockInstance = { $: childInternal } as unknown as ComponentPublicInstance\n\n    addVueError(new Error('oops'), mockInstance, 'mounted hook')\n\n    const componentStack = addErrorSpy.calls.mostRecent().args[0].componentStack as string\n    expect(componentStack).toContain('mounted hook')\n    expect(componentStack).toContain('at <ChildComponent>')\n    expect(componentStack).toContain('at <ParentComponent>')\n  })\n\n  it('handles empty info gracefully', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeVuePlugin({ addError: addErrorSpy })\n    addVueError(new Error('oops'), null, '')\n    expect(addErrorSpy).toHaveBeenCalledTimes(1)\n    expect(addErrorSpy.calls.mostRecent().args[0].componentStack).toBeUndefined()\n  })\n\n  it('should merge dd_context from the original error with vue error context', () => {\n    const addErrorSpy = jasmine.createSpy()\n    initializeVuePlugin({ addError: addErrorSpy })\n    const originalError = new Error('error message')\n    ;(originalError as any).dd_context = { component: 'Menu', param: 123 }\n\n    addVueError(originalError, null, 'mounted hook')\n\n    expect(addErrorSpy.calls.mostRecent().args[0].context).toEqual({\n      framework: 'vue',\n      component: 'Menu',\n      param: 123,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-vue/src/domain/error/addVueError.ts",
    "content": "import type { ComponentInternalInstance, ComponentPublicInstance } from 'vue'\nimport { callMonitored, clocksNow, createHandlingStack } from '@datadog/browser-core'\nimport { onRumStart } from '../vuePlugin'\n\n/**\n * Add a Vue error to the RUM session.\n *\n * @category Error\n * @example\n * ```ts\n * import { createApp } from 'vue'\n * import { addVueError } from '@datadog/browser-rum-vue'\n *\n * const app = createApp(App)\n * // Report all Vue errors to Datadog automatically\n * app.config.errorHandler = addVueError\n * ```\n */\nexport function addVueError(error: unknown, instance: ComponentPublicInstance | null, info: string) {\n  const handlingStack = createHandlingStack('vue error')\n  const startClocks = clocksNow()\n  onRumStart((addError) => {\n    callMonitored(() => {\n      addError({\n        error,\n        handlingStack,\n        componentStack: buildComponentStack(instance, info),\n        startClocks,\n        context: {\n          ...(typeof error === 'object' && error !== null ? (error as { dd_context?: object }).dd_context : undefined),\n          framework: 'vue',\n        },\n      })\n    })\n  })\n}\n\nfunction buildComponentStack(instance: ComponentPublicInstance | null, info: string): string | undefined {\n  const parts: string[] = []\n\n  if (info) {\n    parts.push(info)\n  }\n\n  let current: ComponentInternalInstance | null = instance?.$ ?? null\n  while (current) {\n    const name =\n      current.type &&\n      ('name' in current.type\n        ? current.type.name\n        : '__name' in current.type\n          ? (current.type as { __name?: string }).__name\n          : undefined)\n    if (name) {\n      parts.push(`at <${name}>`)\n    }\n    current = current.parent\n  }\n\n  return parts.length > 0 ? parts.join('\\n') : undefined\n}\n"
  },
  {
    "path": "packages/rum-vue/src/domain/router/startVueRouterView.spec.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport type { RouteLocationMatched } from 'vue-router'\nimport { initializeVuePlugin } from '../../../test/initializeVuePlugin'\nimport { startVueRouterView, computeViewName } from './startVueRouterView'\n\ndescribe('startVueRouterView', () => {\n  it('starts a new view with the computed view name', () => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    startVueRouterView(\n      [{ path: '/' }, { path: 'user' }, { path: ':id' }] as unknown as RouteLocationMatched[],\n      '/user/1'\n    )\n\n    expect(startViewSpy).toHaveBeenCalledOnceWith('/user/:id')\n  })\n\n  it('warns if router: true is missing from plugin config', () => {\n    const warnSpy = spyOn(display, 'warn')\n    initializeVuePlugin({ configuration: {} })\n    startVueRouterView([] as unknown as RouteLocationMatched[], '/')\n    expect(warnSpy).toHaveBeenCalledOnceWith(\n      '`router: true` is missing from the vue plugin configuration, the view will not be tracked.'\n    )\n  })\n})\n\ndescribe('computeViewName', () => {\n  it('returns an empty string if there is no route match', () => {\n    expect(computeViewName([] as unknown as RouteLocationMatched[], '/')).toBe('')\n  })\n\n  it('ignores routes without a path', () => {\n    expect(\n      computeViewName(\n        [{ path: '/foo' }, { path: '' }, { path: '/foo/:id' }] as unknown as RouteLocationMatched[],\n        '/foo/1'\n      )\n    ).toBe('/foo/:id')\n  })\n\n  // prettier-ignore\n  // Vue Router normalizes all matched paths to absolute paths, so unlike React Router there are\n  // no relative segments. The test structure mirrors the React Router spec for consistency.\n  const cases: Array<[string, Array<{ path: string }>, string, string]> = [\n    // description,                         matched paths,                                                    path,                expected\n\n    // Simple paths\n    ['single static segment',               [{ path: '/foo' }],                                              '/foo',              '/foo'],\n    ['nested static segments',              [{ path: '/foo' }, { path: '/foo/bar' }],                        '/foo/bar',          '/foo/bar'],\n    ['nested with param',                   [{ path: '/foo' }, { path: '/foo/bar' }, { path: '/foo/bar/:p' }], '/foo/bar/1',      '/foo/bar/:p'],\n    ['root param',                          [{ path: '/:p' }],                                               '/foo',              '/:p'],\n    ['param in single segment',             [{ path: '/foo/:p' }],                                           '/foo/bar',          '/foo/:p'],\n    ['nested param',                        [{ path: '/foo' }, { path: '/foo/:p' }],                         '/foo/bar',          '/foo/:p'],\n    ['multiple params',                     [{ path: '/:a/:b' }],                                            '/foo/bar',          '/:a/:b'],\n    ['nested multiple params',              [{ path: '/:a' }, { path: '/:a/:b' }],                           '/foo/bar',          '/:a/:b'],\n    ['param with prefix',                   [{ path: '/foo-:a' }],                                           '/foo-1',            '/foo-:a'],\n    ['trailing slashes',                    [{ path: '/foo/' }, { path: '/foo/bar/' }, { path: '/foo/bar/:id/' }], '/foo/bar/1/',  '/foo/bar/:id/'],\n    ['absolute nested override',            [{ path: '/foo' }, { path: '/foo/bar' }, { path: '/foo/bar/:id' }], '/foo/bar/1',     '/foo/bar/:id'],\n\n    // Catch-all routes (Vue Router uses /:pathMatch(.*)* instead of bare * like React Router)\n    ['catch-all at root',                   [{ path: '/:pathMatch(.*)*' }],                                  '/foo/1',            '/foo/1'],\n    ['catch-all at root (index)',           [{ path: '/:pathMatch(.*)*' }],                                  '/',                 '/'],\n    ['nested catch-all',                    [{ path: '/foo' }, { path: '/foo/:pathMatch(.*)*' }],             '/foo/1',            '/foo/1'],\n    ['deeply nested catch-all',             [{ path: '/foo' }, { path: '/foo/bar' }, { path: '/foo/bar/:pathMatch(.*)*' }], '/foo/bar/baz', '/foo/bar/baz'],\n    ['static sibling before catch-all',     [{ path: '/foo' }, { path: '/foo/:pathMatch(.*)*' }],             '/foo/bar',          '/foo/bar'],\n    ['param before catch-all',              [{ path: '/foo/:p' }, { path: '/foo/:p/:pathMatch(.*)*' }],       '/foo/bar/baz',      '/foo/:p/baz'],\n    ['multiple params before catch-all',    [{ path: '/org/:orgId' }, { path: '/org/:orgId/:pathMatch(.*)*' }], '/org/123/some/page', '/org/:orgId/some/page'],\n  ]\n\n  cases.forEach(([description, matched, path, expected]) => {\n    it(`returns \"${expected}\" for ${description}`, () => {\n      expect(computeViewName(matched as unknown as RouteLocationMatched[], path)).toBe(expected)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/rum-vue/src/domain/router/startVueRouterView.ts",
    "content": "import { display } from '@datadog/browser-core'\nimport type { RouteLocationMatched } from 'vue-router'\nimport { onRumInit } from '../vuePlugin'\n\nexport function startVueRouterView(matched: RouteLocationMatched[], path: string) {\n  onRumInit((configuration, rumPublicApi) => {\n    if (!configuration.router) {\n      display.warn('`router: true` is missing from the vue plugin configuration, the view will not be tracked.')\n      return\n    }\n    rumPublicApi.startView(computeViewName(matched, path))\n  })\n}\n\nexport function computeViewName(matched: RouteLocationMatched[], path: string): string {\n  if (!matched || matched.length === 0) {\n    return ''\n  }\n\n  let viewName = '/'\n\n  for (const routeRecord of matched) {\n    const routePath = routeRecord.path\n    if (!routePath) {\n      continue\n    }\n\n    // Note: Vue Router normalizes all paths in the matched array to absolute paths,\n    // so the relative-path branch below is purely defensive and not expected to be\n    // hit in practice. It mirrors the React Router implementation for consistency.\n    if (routePath.startsWith('/')) {\n      viewName = routePath\n    } else {\n      if (!viewName.endsWith('/')) {\n        viewName += '/'\n      }\n      viewName += routePath\n    }\n  }\n\n  return substituteCatchAll(viewName, path)\n}\n\n/**\n * Vue Router catch-all routes use `/:pathMatch(.*)*` instead of bare `*` like React Router.\n * Keeping the raw pattern as the view name isn't helpful, it hides information about which\n * path was actually visited. This function replaces only the catch-all segment with the\n * corresponding portion of the actual URL path, preserving any parameterized segments that\n * precede it. This aligns with how the React integration substitutes splats.\n *\n * We match the full `/:pathMatch(.*)*` pattern rather than just `:pathMatch(` to avoid\n * false positives on custom regex params (e.g. `/:pathMatch([a-z]+)`).\n *\n * @example\n * substituteCatchAll('/:pathMatch(.*)*', '/unknown/page') // => '/unknown/page'\n * substituteCatchAll('/org/:orgId/:pathMatch(.*)*', '/org/123/some/page') // => '/org/:orgId/some/page'\n */\nfunction substituteCatchAll(viewName: string, path: string): string {\n  const catchAllIndex = viewName.indexOf('/:pathMatch(.*)*')\n  if (catchAllIndex === -1) {\n    return viewName\n  }\n\n  // Keep parameterized segments before the catch-all intact\n  const prefix = viewName.substring(0, catchAllIndex)\n\n  // Count the number of path segments in the prefix to find the matching point in the actual path\n  const prefixSegmentCount = prefix === '' ? 0 : prefix.split('/').length - 1\n  const pathSegments = path.split('/')\n  const suffix = pathSegments.slice(prefixSegmentCount + 1).join('/')\n\n  return prefix + (suffix ? `/${suffix}` : '') || '/'\n}\n"
  },
  {
    "path": "packages/rum-vue/src/domain/router/vueRouter.spec.ts",
    "content": "import { createMemoryHistory } from 'vue-router'\nimport { initializeVuePlugin } from '../../../test/initializeVuePlugin'\nimport { createRouter } from './vueRouter'\n\ndescribe('createRouter (wrapped)', () => {\n  it('calls startView on navigation', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [\n        { path: '/', component: {} },\n        { path: '/about', component: {} },\n      ],\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledWith('/')\n        return router.push('/about')\n      })\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledWith('/about')\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('does not call startView when navigation is duplicated', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/', component: {} }],\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        startViewSpy.calls.reset()\n        return router.push('/')\n      })\n      .then(() => {\n        expect(startViewSpy).not.toHaveBeenCalled()\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('does not call startView when only query params change', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/products', component: {} }],\n    })\n\n    router\n      .push('/products?page=1')\n      .then(() => {\n        startViewSpy.calls.reset()\n        return router.push('/products?page=2')\n      })\n      .then(() => {\n        expect(startViewSpy).not.toHaveBeenCalled()\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('calls startView on initial navigation to /', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [{ path: '/', component: {} }],\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledOnceWith('/')\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('substitutes catch-all pattern with the actual path', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [\n        { path: '/', component: {} },\n        { path: '/:pathMatch(.*)*', component: {} },\n      ],\n    })\n\n    router\n      .push('/unknown/page')\n      .then(() => {\n        expect(startViewSpy).toHaveBeenCalledWith('/unknown/page')\n        done()\n      })\n      .catch(done.fail)\n  })\n\n  it('does not call startView when navigation is blocked', (done) => {\n    const startViewSpy = jasmine.createSpy()\n    initializeVuePlugin({\n      configuration: { router: true },\n      publicApi: { startView: startViewSpy },\n    })\n\n    const router = createRouter({\n      history: createMemoryHistory(),\n      routes: [\n        { path: '/', component: {} },\n        { path: '/protected', component: {} },\n      ],\n    })\n\n    // Block all navigations to /protected\n    router.beforeEach((to) => {\n      if (to.path === '/protected') {\n        return false\n      }\n    })\n\n    router\n      .push('/')\n      .then(() => {\n        startViewSpy.calls.reset()\n        return router.push('/protected')\n      })\n      .then(() => {\n        expect(startViewSpy).not.toHaveBeenCalled()\n        done()\n      })\n      .catch(done.fail)\n  })\n})\n"
  },
  {
    "path": "packages/rum-vue/src/domain/router/vueRouter.ts",
    "content": "import { createRouter as originalCreateRouter } from 'vue-router'\nimport type { RouterOptions, Router } from 'vue-router'\nimport { startVueRouterView } from './startVueRouterView'\n\nexport function createRouter(options: RouterOptions): Router {\n  const router = originalCreateRouter(options)\n\n  // afterEach fires for the initial navigation when the app is mounted via app.use(router).\n  // In tests without mounting, an explicit router.push() is needed to trigger the hook.\n  // Skip any failed navigation (blocked by a guard, cancelled, duplicated, etc.).\n  // Skip query-only changes (to.path stays the same): those don't constitute a new view,\n  // consistent with how the SDK's automatic view tracking ignores query string changes.\n  // from.matched.length === 0 identifies the initial START_LOCATION so the first\n  // navigation is always tracked, even when the app starts at '/'.\n  router.afterEach((to, from, failure) => {\n    if (failure) {\n      return\n    }\n    if (from.matched.length > 0 && to.path === from.path) {\n      return\n    }\n    startVueRouterView(to.matched, to.path)\n  })\n\n  return router\n}\n"
  },
  {
    "path": "packages/rum-vue/src/domain/vuePlugin.spec.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport { registerCleanupTask } from '../../../core/test'\nimport { onRumInit, vuePlugin, resetVuePlugin } from './vuePlugin'\n\nconst PUBLIC_API = {} as RumPublicApi\nconst INIT_CONFIGURATION = {} as RumInitConfiguration\n\ndescribe('vuePlugin', () => {\n  beforeEach(() => {\n    registerCleanupTask(() => resetVuePlugin())\n  })\n\n  it('returns a plugin object with name \"vue\"', () => {\n    expect(vuePlugin()).toEqual(jasmine.objectContaining({ name: 'vue' }))\n  })\n\n  it('calls callbacks registered with onRumInit during onInit', () => {\n    const spy = jasmine.createSpy()\n    const config = {}\n    onRumInit(spy)\n    vuePlugin(config).onInit({ publicApi: PUBLIC_API, initConfiguration: INIT_CONFIGURATION })\n    expect(spy).toHaveBeenCalledOnceWith(config, PUBLIC_API)\n  })\n\n  it('calls callbacks immediately if onInit was already invoked', () => {\n    const spy = jasmine.createSpy()\n    const config = {}\n    vuePlugin(config).onInit({ publicApi: PUBLIC_API, initConfiguration: INIT_CONFIGURATION })\n    onRumInit(spy)\n    expect(spy).toHaveBeenCalledOnceWith(config, PUBLIC_API)\n  })\n\n  it('sets trackViewsManually when router is true', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    vuePlugin({ router: true }).onInit({ publicApi: PUBLIC_API, initConfiguration })\n    expect(initConfiguration.trackViewsManually).toBe(true)\n  })\n\n  it('does not set trackViewsManually when router is false', () => {\n    const initConfiguration = { ...INIT_CONFIGURATION }\n    vuePlugin({ router: false }).onInit({ publicApi: PUBLIC_API, initConfiguration })\n    expect(initConfiguration.trackViewsManually).toBeUndefined()\n  })\n\n  it('returns configuration telemetry', () => {\n    expect(vuePlugin({ router: true }).getConfigurationTelemetry()).toEqual({ router: true })\n  })\n})\n"
  },
  {
    "path": "packages/rum-vue/src/domain/vuePlugin.ts",
    "content": "import type { RumPlugin, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\n\nlet globalPublicApi: RumPublicApi | undefined\nlet globalConfiguration: VuePluginConfiguration | undefined\nlet globalAddError: StartRumResult['addError'] | undefined\n\ntype InitSubscriber = (configuration: VuePluginConfiguration, rumPublicApi: RumPublicApi) => void\ntype StartSubscriber = (addError: StartRumResult['addError']) => void\n\nconst onRumInitSubscribers: InitSubscriber[] = []\nconst onRumStartSubscribers: StartSubscriber[] = []\n\nexport interface VuePluginConfiguration {\n  router?: boolean\n}\n\nexport type VuePlugin = Required<RumPlugin>\n\nexport function vuePlugin(configuration: VuePluginConfiguration = {}): VuePlugin {\n  return {\n    name: 'vue',\n    onInit({ publicApi, initConfiguration }) {\n      globalPublicApi = publicApi\n      globalConfiguration = configuration\n      for (const subscriber of onRumInitSubscribers) {\n        subscriber(globalConfiguration, globalPublicApi)\n      }\n      if (configuration.router) {\n        initConfiguration.trackViewsManually = true\n      }\n    },\n    onRumStart({ addError }) {\n      globalAddError = addError\n      if (addError) {\n        for (const subscriber of onRumStartSubscribers) {\n          subscriber(addError)\n        }\n      }\n    },\n    getConfigurationTelemetry() {\n      return { router: !!configuration.router }\n    },\n  } satisfies RumPlugin\n}\n\nexport function onRumInit(callback: InitSubscriber) {\n  if (globalConfiguration && globalPublicApi) {\n    callback(globalConfiguration, globalPublicApi)\n  } else {\n    onRumInitSubscribers.push(callback)\n  }\n}\n\nexport function onRumStart(callback: StartSubscriber) {\n  if (globalAddError) {\n    callback(globalAddError)\n  } else {\n    onRumStartSubscribers.push(callback)\n  }\n}\n\nexport function resetVuePlugin() {\n  globalPublicApi = undefined\n  globalConfiguration = undefined\n  globalAddError = undefined\n  onRumInitSubscribers.length = 0\n  onRumStartSubscribers.length = 0\n}\n"
  },
  {
    "path": "packages/rum-vue/src/entries/main.ts",
    "content": "export type { VuePluginConfiguration, VuePlugin } from '../domain/vuePlugin'\nexport { vuePlugin } from '../domain/vuePlugin'\nexport { addVueError } from '../domain/error/addVueError'\n"
  },
  {
    "path": "packages/rum-vue/src/entries/vueRouter.ts",
    "content": "export { createRouter } from '../domain/router/vueRouter'\n"
  },
  {
    "path": "packages/rum-vue/test/initializeVuePlugin.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi, StartRumResult } from '@datadog/browser-rum-core'\nimport { noop } from '@datadog/browser-core'\nimport type { VuePluginConfiguration } from '../src/domain/vuePlugin'\nimport { vuePlugin, resetVuePlugin } from '../src/domain/vuePlugin'\nimport { registerCleanupTask } from '../../core/test'\n\nexport function initializeVuePlugin({\n  configuration = {},\n  initConfiguration = {},\n  publicApi = {},\n  addError = noop,\n}: {\n  configuration?: VuePluginConfiguration\n  initConfiguration?: Partial<RumInitConfiguration>\n  publicApi?: Partial<RumPublicApi>\n  addError?: StartRumResult['addError']\n} = {}) {\n  resetVuePlugin()\n  const plugin = vuePlugin(configuration)\n  plugin.onInit({\n    publicApi: publicApi as RumPublicApi,\n    initConfiguration: initConfiguration as RumInitConfiguration,\n  })\n  plugin.onRumStart({ addError })\n  registerCleanupTask(() => resetVuePlugin())\n}\n"
  },
  {
    "path": "packages/rum-vue/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"src/entries/main.ts\"]\n}\n"
  },
  {
    "path": "packages/rum-vue/vue-router-v4/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-rum-vue/vue-router-v4\",\n  \"private\": true,\n  \"main\": \"../cjs/entries/vueRouter.js\",\n  \"module\": \"../esm/entries/vueRouter.js\",\n  \"types\": \"../cjs/entries/vueRouter.d.ts\"\n}\n"
  },
  {
    "path": "packages/rum-vue/vue-router-v4/typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"entryPoints\": [\"../src/entries/vueRouter.ts\"]\n}\n"
  },
  {
    "path": "packages/worker/.yarnrc",
    "content": "save-exact true\n\n"
  },
  {
    "path": "packages/worker/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019-Present Datadog, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "packages/worker/README.md",
    "content": "# `worker`\n\nDatadog browser web Worker.\n"
  },
  {
    "path": "packages/worker/package.json",
    "content": "{\n  \"name\": \"@datadog/browser-worker\",\n  \"version\": \"6.32.0\",\n  \"license\": \"Apache-2.0\",\n  \"main\": \"bundle/worker.js\",\n  \"files\": [\n    \"bundle/**/*.js\",\n    \"src\",\n    \"!src/**/*.spec.ts\",\n    \"!src/**/*.specHelper.ts\"\n  ],\n  \"scripts\": {\n    \"build\": \"node ../../scripts/build/build-package.ts --bundle worker.js\",\n    \"build:bundle\": \"yarn build\",\n    \"prepack\": \"yarn build\"\n  },\n  \"dependencies\": {\n    \"@datadog/browser-core\": \"6.32.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/DataDog/browser-sdk.git\",\n    \"directory\": \"packages/worker\"\n  },\n  \"volta\": {\n    \"extends\": \"../../package.json\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"devDependencies\": {\n    \"webpack\": \"5.106.2\"\n  }\n}\n"
  },
  {
    "path": "packages/worker/src/boot/startWorker.spec.ts",
    "content": "import type { DeflateWorkerAction, DeflateWorkerResponse } from '@datadog/browser-core'\nimport type { WorkerScope } from './startWorker'\nimport { startWorker } from './startWorker'\n\n// Arbitrary stream ids used for tests\nconst TEST_STREAM_ID = 5\nconst OTHER_TEST_STREAM_ID = 6\n\n// Zlib streams using a default compression are starting with bytes 120 156 (0x78 0x9c)\n// https://stackoverflow.com/a/9050274\nconst STREAM_START = [120, 156]\n\n// Deflate block generated when compressing \"foo\" alone\nconst FOO_COMPRESSED = [74, 203, 207, 7, 0, 0, 0, 255, 255]\n// Zlib trailer when finishing the stream after compressing \"foo\"\nconst FOO_COMPRESSED_TRAILER = [3, 0, 2, 130, 1, 69] // empty deflate block + adler32 checksum\n\n// Deflate block generated when compressing \"bar\" alone\nconst BAR_COMPRESSED = [74, 74, 44, 2, 0, 0, 0, 255, 255]\n// Zlib trailer when finishing the stream after compressing \"bar\"\nconst BAR_COMPRESSED_TRAILER = [3, 0, 2, 93, 1, 54]\n\n// Deflate block generated when compressing \"baz\" alone\nconst BAZ_COMPRESSED = [74, 74, 172, 2, 0, 0, 0, 255, 255]\n\n// Zlib trailer when finishing the stream after compressing \"foo\" then \"bar\"\nconst FOO_BAR_COMPRESSED_TRAILER = [3, 0, 8, 171, 2, 122]\n// Zlib trailer when finishing the stream after compressing \"foo\" then \"bar\" then \"baz\"\nconst FOO_BAR_BAZ_COMPRESSED_TRAILER = [3, 0, 18, 123, 3, 183]\n// Zlib trailer when finishing the stream after compressing \"foo\" then \"baz\"\nconst FOO_BAZ_COMPRESSED_TRAILER = [3, 0, 8, 179, 2, 130]\n\ndescribe('startWorker', () => {\n  let workerScope: {\n    addEventListener: jasmine.Spy<WorkerScope['addEventListener']>\n    postMessage: jasmine.Spy<WorkerScope['postMessage']>\n  }\n\n  beforeEach(() => {\n    workerScope = {\n      addEventListener: jasmine.createSpy(),\n      postMessage: jasmine.createSpy(),\n    }\n    startWorker(workerScope)\n  })\n\n  function emulateAction(message: DeflateWorkerAction): DeflateWorkerResponse {\n    workerScope.postMessage.calls.reset()\n    workerScope.addEventListener.calls.allArgs().forEach(([eventName, listener]) => {\n      if (eventName === 'message') {\n        listener({ data: message } as MessageEvent)\n      }\n    })\n    return workerScope.postMessage.calls.mostRecent()?.args[0]\n  }\n\n  it('buffers data and responds with the buffer deflated result when writing', () => {\n    expect(emulateAction({ id: 0, streamId: TEST_STREAM_ID, action: 'write', data: 'foo' })).toEqual({\n      type: 'wrote',\n      id: 0,\n      streamId: TEST_STREAM_ID,\n      result: new Uint8Array([...STREAM_START, ...FOO_COMPRESSED]),\n      trailer: new Uint8Array(FOO_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n\n    expect(emulateAction({ id: 1, streamId: TEST_STREAM_ID, action: 'write', data: 'bar' })).toEqual({\n      type: 'wrote',\n      id: 1,\n      streamId: TEST_STREAM_ID,\n      result: new Uint8Array(BAR_COMPRESSED),\n      trailer: new Uint8Array(FOO_BAR_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n\n    expect(emulateAction({ id: 2, streamId: TEST_STREAM_ID, action: 'write', data: 'baz' })).toEqual({\n      type: 'wrote',\n      id: 2,\n      streamId: TEST_STREAM_ID,\n      result: new Uint8Array(BAZ_COMPRESSED),\n      trailer: new Uint8Array(FOO_BAR_BAZ_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n  })\n\n  it('resets the stream state', () => {\n    expect(emulateAction({ action: 'write', id: 0, streamId: TEST_STREAM_ID, data: 'foo' })).toEqual({\n      type: 'wrote',\n      id: 0,\n      streamId: TEST_STREAM_ID,\n      result: new Uint8Array([...STREAM_START, ...FOO_COMPRESSED]),\n      trailer: new Uint8Array(FOO_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n    expect(emulateAction({ action: 'reset', streamId: TEST_STREAM_ID })).toBeUndefined()\n    expect(emulateAction({ action: 'write', id: 1, streamId: TEST_STREAM_ID, data: 'bar' })).toEqual({\n      type: 'wrote',\n      id: 1,\n      streamId: TEST_STREAM_ID,\n      // As the result starts with the beginning of a stream, we are sure that `reset` was\n      // effective\n      result: new Uint8Array([...STREAM_START, ...BAR_COMPRESSED]),\n      trailer: new Uint8Array(BAR_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n    expect(emulateAction({ action: 'reset', streamId: TEST_STREAM_ID })).toBeUndefined()\n  })\n\n  it('support writing to different streams at the same time', () => {\n    expect(\n      emulateAction({\n        id: 0,\n        streamId: TEST_STREAM_ID,\n        action: 'write',\n        data: 'foo',\n      })\n    ).toEqual({\n      type: 'wrote',\n      id: 0,\n      streamId: TEST_STREAM_ID,\n      result: new Uint8Array([...STREAM_START, ...FOO_COMPRESSED]),\n      trailer: new Uint8Array(FOO_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n\n    expect(\n      emulateAction({\n        id: 1,\n        streamId: OTHER_TEST_STREAM_ID,\n        action: 'write',\n        data: 'bar',\n      })\n    ).toEqual({\n      type: 'wrote',\n      id: 1,\n      streamId: OTHER_TEST_STREAM_ID,\n      result: new Uint8Array([...STREAM_START, ...BAR_COMPRESSED]),\n      trailer: new Uint8Array(BAR_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n\n    expect(\n      emulateAction({\n        streamId: OTHER_TEST_STREAM_ID,\n        action: 'reset',\n      })\n    ).toBeUndefined()\n\n    expect(\n      emulateAction({\n        id: 2,\n        streamId: TEST_STREAM_ID,\n        action: 'write',\n        data: 'baz',\n      })\n    ).toEqual({\n      type: 'wrote',\n      id: 2,\n      streamId: TEST_STREAM_ID,\n      result: new Uint8Array(BAZ_COMPRESSED),\n      trailer: new Uint8Array(FOO_BAZ_COMPRESSED_TRAILER),\n      additionalBytesCount: 3,\n    })\n  })\n\n  it('reports an error when an unexpected exception occurs', () => {\n    expect(emulateAction(null as any)).toEqual({\n      type: 'errored',\n      error: jasmine.any(TypeError),\n      streamId: undefined,\n    })\n  })\n\n  it('reports an error when an unexpected exception occurs while writing on a stream', () => {\n    if (!window.TextEncoder) {\n      pending('No TextEncoder support')\n    }\n    spyOn(TextEncoder.prototype, 'encode').and.callFake(() => {\n      throw new Error('Something went wrong!')\n    })\n    expect(\n      emulateAction({\n        id: 2,\n        streamId: TEST_STREAM_ID,\n        action: 'write',\n        data: 'baz',\n      })\n    ).toEqual({\n      type: 'errored',\n      error: new Error('Something went wrong!'),\n      streamId: TEST_STREAM_ID,\n    })\n  })\n\n  it('use the string representation of the error when it fails to send it through postMessage', () => {\n    workerScope.postMessage.and.callFake((response) => {\n      if (response.type === 'errored' && response.error instanceof Error) {\n        throw new DOMException(\"Failed to execute 'postMessage' on 'WorkerScope'\")\n      }\n    })\n    expect(emulateAction(null as any)).toEqual({\n      type: 'errored',\n      error: jasmine.stringContaining('TypeError'),\n      streamId: undefined,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/worker/src/boot/startWorker.ts",
    "content": "import type { DeflateWorkerAction, DeflateWorkerResponse, Uint8ArrayBuffer } from '@datadog/browser-core'\nimport { concatBuffers } from '@datadog/browser-core'\nimport { Deflate, constants, string2buf } from '../domain/deflate'\n\ndeclare const __BUILD_ENV__SDK_VERSION__: string\n\nexport interface WorkerScope {\n  addEventListener(eventName: 'message', listener: (event: MessageEvent<DeflateWorkerAction>) => void): void\n  postMessage(response: DeflateWorkerResponse): void\n}\n\nexport function startWorker(workerScope: WorkerScope = self) {\n  try {\n    const streams = new Map<number, Deflate>()\n    workerScope.addEventListener('message', (event: MessageEvent<DeflateWorkerAction>) => {\n      try {\n        const response = handleAction(streams, event.data)\n        if (response) {\n          workerScope.postMessage(response)\n        }\n      } catch (error) {\n        sendError(workerScope, error, event.data && 'streamId' in event.data ? event.data.streamId : undefined)\n      }\n    })\n  } catch (error) {\n    sendError(workerScope, error)\n  }\n}\n\nfunction sendError(workerScope: WorkerScope, error: unknown, streamId?: number) {\n  try {\n    workerScope.postMessage({\n      type: 'errored',\n      error: error as Error,\n      streamId,\n    })\n  } catch {\n    // DATA_CLONE_ERR, cf https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm\n    workerScope.postMessage({\n      type: 'errored',\n      error: String(error),\n      streamId,\n    })\n  }\n}\n\nfunction handleAction(streams: Map<number, Deflate>, message: DeflateWorkerAction): DeflateWorkerResponse | undefined {\n  switch (message.action) {\n    case 'init':\n      return {\n        type: 'initialized',\n        version: __BUILD_ENV__SDK_VERSION__,\n      }\n\n    case 'write': {\n      let deflate = streams.get(message.streamId)\n      if (!deflate) {\n        deflate = new Deflate()\n        streams.set(message.streamId, deflate)\n      }\n      const previousChunksLength = deflate.chunks.length\n\n      // TextEncoder is not supported on old browser version like Edge 18, therefore we use string2buf\n      const binaryData = string2buf(message.data)\n      deflate.push(binaryData, constants.Z_SYNC_FLUSH)\n\n      return {\n        type: 'wrote',\n        id: message.id,\n        streamId: message.streamId,\n        result: concatBuffers(deflate.chunks.slice(previousChunksLength)),\n        trailer: makeTrailer(deflate),\n        additionalBytesCount: binaryData.length,\n      }\n    }\n\n    case 'reset':\n      streams.delete(message.streamId)\n      break\n  }\n}\n\n/**\n * Creates a buffer of bytes to append to the end of the Zlib stream to finish it. It is composed of\n * two parts:\n * * an empty deflate block as specified in https://www.rfc-editor.org/rfc/rfc1951.html#page-13 ,\n * which happens to be always 3, 0\n * * an adler32 checksum as specified in https://www.rfc-editor.org/rfc/rfc1950.html#page-4\n *\n * This is essentially what pako writes to the stream when invoking `deflate.push('',\n * constants.Z_FINISH)` operation after some data has been pushed with \"Z_SYNC_FLUSH\", but doing so\n * ends the stream and no more data can be pushed into it.\n *\n * Since we want to let the main thread end the stream synchronously at any point without needing to\n * send a message to the worker to flush it, we send back a trailer in each \"wrote\" response so the\n * main thread can just append it to the compressed data to end the stream.\n *\n * Beside creating a valid zlib stream, those 6 bits are expected to be here so the Datadog backend\n * can merge streams together (see internal doc).\n */\nfunction makeTrailer(deflate: Deflate): Uint8ArrayBuffer {\n  /* eslint-disable no-bitwise */\n  const adler = deflate.strm.adler\n  return new Uint8Array([\n    // Empty deflate block\n    3,\n    0,\n    // Adler32 checksum\n    (adler >>> 24) & 0xff,\n    (adler >>> 16) & 0xff,\n    (adler >>> 8) & 0xff,\n    adler & 0xff,\n  ])\n  /* eslint-enable no-bitwise */\n}\n"
  },
  {
    "path": "packages/worker/src/domain/deflate.d.ts",
    "content": "import type { Uint8ArrayBuffer } from '@datadog/browser-core'\n\n// eslint-disable-next-line no-restricted-syntax\nexport class Deflate {\n  chunks: Uint8ArrayBuffer[]\n  result: Uint8ArrayBuffer\n  strm: { adler: number }\n  push(data: Uint8ArrayBuffer | ArrayBuffer | string, flushMode: number | boolean): boolean\n}\n\nexport const constants: {\n  [name: string]: number\n}\n\nexport function string2buf(input: string): Uint8ArrayBuffer\n"
  },
  {
    "path": "packages/worker/src/domain/deflate.js",
    "content": "/* eslint-disable camelcase, no-bitwise */\n// This file comes from and was trimmed from unused code https://github.com/nodeca/pako/blob/034669ba0f1a4c0590e45f7c2820128200f972b3/dist/pako_deflate.es5.js\n\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n/* Public constants ========================================================== */\n\n/* =========================================================================== */\n// const Z_FILTERED          = 1;\n// const Z_HUFFMAN_ONLY      = 2;\n// const Z_RLE               = 3;\n\nvar Z_FIXED = 4 // const Z_DEFAULT_STRATEGY  = 0;\n\n/* Possible values of the data_type field (though see inflate()) */\n\nvar Z_BINARY = 0\nvar Z_TEXT = 1 // const Z_ASCII             = 1; // = Z_TEXT\n\nvar Z_UNKNOWN = 2\n/* ============================================================================ */\n\nfunction zero(buf) {\n  var len = buf.length\n\n  while (--len >= 0) {\n    buf[len] = 0\n  }\n} // From zutil.h\n\nvar STORED_BLOCK = 0\nvar STATIC_TREES = 1\nvar DYN_TREES = 2\n/* The three kinds of block type */\n\nvar MIN_MATCH = 3\nvar MAX_MATCH = 258\n/* The minimum and maximum match lengths */\n// From deflate.h\n\n/* ===========================================================================\n * Internal compression state.\n */\n\nvar LENGTH_CODES = 29\n/* number of length codes, not counting the special END_BLOCK code */\n\nvar LITERALS = 256\n/* number of literal bytes 0..255 */\n\nvar L_CODES = LITERALS + 1 + LENGTH_CODES\n/* number of Literal or Length codes, including the END_BLOCK code */\n\nvar D_CODES = 30\n/* number of distance codes */\n\nvar BL_CODES = 19\n/* number of codes used to transfer the bit lengths */\n\nvar HEAP_SIZE = 2 * L_CODES + 1\n/* maximum heap size */\n\nvar MAX_BITS = 15\n/* All codes must not exceed MAX_BITS bits */\n\nvar Buf_size = 16\n/* size of bit buffer in bi_buf */\n\n/* ===========================================================================\n * Constants\n */\n\nvar MAX_BL_BITS = 7\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\nvar END_BLOCK = 256\n/* end of block literal code */\n\nvar REP_3_6 = 16\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\nvar REPZ_3_10 = 17\n/* repeat a zero length 3-10 times  (3 bits of repeat count) */\n\nvar REPZ_11_138 = 18\n/* repeat a zero length 11-138 times  (7 bits of repeat count) */\n\nvar extra_lbits =\n  /* extra bits for each length code */\n  new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0])\nvar extra_dbits =\n  /* extra bits for each distance code */\n  new Uint8Array([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13])\nvar extra_blbits =\n  /* extra bits for each bit length code */\n  new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7])\nvar bl_order = new Uint8Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15])\n\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\n/* ===========================================================================\n * Local data. These are initialized only once.\n */\n// We pre-fill arrays with 0 to avoid uninitialized gaps\n\nvar DIST_CODE_LEN = 512\n/* see definition of array dist_code below */\n// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1\n\nvar static_ltree = new Array((L_CODES + 2) * 2)\nzero(static_ltree)\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see _tr_init\n * below).\n */\n\nvar static_dtree = new Array(D_CODES * 2)\nzero(static_dtree)\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nvar _dist_code = new Array(DIST_CODE_LEN)\n\nzero(_dist_code)\n/* Distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nvar _length_code = new Array(MAX_MATCH - MIN_MATCH + 1)\n\nzero(_length_code)\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nvar base_length = new Array(LENGTH_CODES)\nzero(base_length)\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nvar base_dist = new Array(D_CODES)\nzero(base_dist)\n/* First normalized distance for each code (0 = distance of 1) */\n\nfunction StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {\n  this.static_tree = static_tree\n  /* static tree or NULL */\n\n  this.extra_bits = extra_bits\n  /* extra bits for each code or NULL */\n\n  this.extra_base = extra_base\n  /* base index for extra_bits */\n\n  this.elems = elems\n  /* max number of elements in the tree */\n\n  this.max_length = max_length\n  /* max bit length for the codes */\n  // show if `static_tree` has data or dummy - needed for monomorphic objects\n\n  this.has_stree = static_tree && static_tree.length\n}\n\nvar static_l_desc\nvar static_d_desc\nvar static_bl_desc\n\nfunction TreeDesc(dyn_tree, stat_desc) {\n  this.dyn_tree = dyn_tree\n  /* the dynamic tree */\n\n  this.max_code = 0\n  /* largest code with non zero frequency */\n\n  this.stat_desc = stat_desc\n  /* the corresponding static tree */\n}\n\nvar d_code = function d_code(dist) {\n  return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]\n}\n/* ===========================================================================\n * Output a short LSB first on the stream.\n * IN assertion: there is enough room in pendingBuf.\n */\n\nvar put_short = function put_short(s, w) {\n  //    put_byte(s, (uch)((w) & 0xff));\n  //    put_byte(s, (uch)((ush)(w) >> 8));\n  s.pending_buf[s.pending++] = w & 0xff\n  s.pending_buf[s.pending++] = (w >>> 8) & 0xff\n}\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\n\nvar send_bits = function send_bits(s, value, length) {\n  if (s.bi_valid > Buf_size - length) {\n    s.bi_buf |= (value << s.bi_valid) & 0xffff\n    put_short(s, s.bi_buf)\n    s.bi_buf = value >> (Buf_size - s.bi_valid)\n    s.bi_valid += length - Buf_size\n  } else {\n    s.bi_buf |= (value << s.bi_valid) & 0xffff\n    s.bi_valid += length\n  }\n}\n\nvar send_code = function send_code(s, c, tree) {\n  send_bits(\n    s,\n    tree[c * 2],\n    /* .Code */\n    tree[c * 2 + 1]\n    /* .Len */\n  )\n}\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\n\nvar bi_reverse = function bi_reverse(code, len) {\n  var res = 0\n\n  do {\n    res |= code & 1\n    code >>>= 1\n    res <<= 1\n  } while (--len > 0)\n\n  return res >>> 1\n}\n/* ===========================================================================\n * Flush the bit buffer, keeping at most 7 bits in it.\n */\n\nvar bi_flush = function bi_flush(s) {\n  if (s.bi_valid === 16) {\n    put_short(s, s.bi_buf)\n    s.bi_buf = 0\n    s.bi_valid = 0\n  } else if (s.bi_valid >= 8) {\n    s.pending_buf[s.pending++] = s.bi_buf & 0xff\n    s.bi_buf >>= 8\n    s.bi_valid -= 8\n  }\n}\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n *    above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n *     array bl_count contains the frequencies for each bit length.\n *     The length opt_len is updated; static_len is also updated if stree is\n *     not null.\n */\n\nvar gen_bitlen = function gen_bitlen(\n  s,\n  desc //    deflate_state *s; //    tree_desc *desc;    /* the tree descriptor */\n) {\n  var tree = desc.dyn_tree\n  var max_code = desc.max_code\n  var stree = desc.stat_desc.static_tree\n  var has_stree = desc.stat_desc.has_stree\n  var extra = desc.stat_desc.extra_bits\n  var base = desc.stat_desc.extra_base\n  var max_length = desc.stat_desc.max_length\n  var h\n  /* heap index */\n\n  var n\n  var m\n  /* iterate over the tree elements */\n\n  var bits\n  /* bit length */\n\n  var xbits\n  /* extra bits */\n\n  var f\n  /* frequency */\n\n  var overflow = 0\n  /* number of elements with bit length too large */\n\n  for (bits = 0; bits <= MAX_BITS; bits++) {\n    s.bl_count[bits] = 0\n  }\n  /* In a first pass, compute the optimal bit lengths (which may\n   * overflow in the case of the bit length tree).\n   */\n\n  tree[s.heap[s.heap_max] * 2 + 1] =\n    /* .Len */\n    0\n  /* root of the heap */\n\n  for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {\n    n = s.heap[h]\n    bits =\n      tree[\n        tree[n * 2 + 1] *\n          /* .Dad */\n          2 +\n          1\n      ] +\n      /* .Len */\n      1\n\n    if (bits > max_length) {\n      bits = max_length\n      overflow++\n    }\n\n    tree[n * 2 + 1] =\n      /* .Len */\n      bits\n    /* We overwrite tree[n].Dad which is no longer needed */\n\n    if (n > max_code) {\n      continue\n    }\n    /* not a leaf node */\n\n    s.bl_count[bits]++\n    xbits = 0\n\n    if (n >= base) {\n      xbits = extra[n - base]\n    }\n\n    f = tree[n * 2]\n    /* .Freq */\n    s.opt_len += f * (bits + xbits)\n\n    if (has_stree) {\n      s.static_len +=\n        f *\n        (stree[n * 2 + 1] +\n          /* .Len */\n          xbits)\n    }\n  }\n\n  if (overflow === 0) {\n    return\n  } // Trace((stderr,\"\\nbit length overflow\\n\"));\n\n  /* This happens for example on obj2 and pic of the Calgary corpus */\n\n  /* Find the first bit length which could increase: */\n\n  do {\n    bits = max_length - 1\n\n    while (s.bl_count[bits] === 0) {\n      bits--\n    }\n\n    s.bl_count[bits]--\n    /* move one leaf down the tree */\n\n    s.bl_count[bits + 1] += 2\n    /* move one overflow item as its brother */\n\n    s.bl_count[max_length]--\n    /* The brother of the overflow item also moves one step up,\n     * but this does not affect bl_count[max_length]\n     */\n\n    overflow -= 2\n  } while (overflow > 0)\n  /* Now recompute all bit lengths, scanning in increasing frequency.\n   * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n   * lengths instead of fixing only the wrong ones. This idea is taken\n   * from 'ar' written by Haruhiko Okumura.)\n   */\n\n  for (bits = max_length; bits !== 0; bits--) {\n    n = s.bl_count[bits]\n\n    while (n !== 0) {\n      m = s.heap[--h]\n\n      if (m > max_code) {\n        continue\n      }\n\n      if (\n        tree[m * 2 + 1] !==\n        /* .Len */\n        bits\n      ) {\n        // Trace((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n        s.opt_len +=\n          (bits - tree[m * 2 + 1]) *\n          /* .Len */\n          tree[m * 2]\n        /* .Freq */\n        tree[m * 2 + 1] =\n          /* .Len */\n          bits\n      }\n\n      n--\n    }\n  }\n}\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n *     zero code length.\n */\n\nvar gen_codes = function gen_codes(\n  tree,\n  max_code,\n  bl_count\n  //    ct_data *tree;             /* the tree to decorate */\n  //    int max_code;              /* largest code with non zero frequency */\n  //    ushf *bl_count;            /* number of codes at each bit length */\n) {\n  var next_code = new Array(MAX_BITS + 1)\n  /* next code value for each bit length */\n\n  var code = 0\n  /* running code value */\n\n  var bits\n  /* bit index */\n\n  var n\n  /* code index */\n\n  /* The distribution counts are first used to generate the code values\n   * without bit reversal.\n   */\n\n  for (bits = 1; bits <= MAX_BITS; bits++) {\n    next_code[bits] = code = (code + bl_count[bits - 1]) << 1\n  }\n  /* Check that the bit counts in bl_count are consistent. The last code\n   * must be all ones.\n   */\n  // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,\n  //        \"inconsistent bit counts\");\n  // Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n  for (n = 0; n <= max_code; n++) {\n    var len = tree[n * 2 + 1]\n    /* .Len */\n    if (len === 0) {\n      continue\n    }\n    /* Now reverse the bits */\n\n    tree[n * 2] =\n      /* .Code */\n      bi_reverse(next_code[len]++, len) // Tracecv(tree != static_ltree, (stderr,\"\\nn %3d %c l %2d c %4x (%x) \",\n    //     n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));\n  }\n}\n/* ===========================================================================\n * Initialize the various 'constant' tables.\n */\n\nvar tr_static_init = function tr_static_init() {\n  var n\n  /* iterates over tree elements */\n\n  var bits\n  /* bit counter */\n\n  var length\n  /* length value */\n\n  var code\n  /* code value */\n\n  var dist\n  /* distance index */\n\n  var bl_count = new Array(MAX_BITS + 1)\n  /* number of codes at each bit length for an optimal tree */\n  // do check in _tr_init()\n  // if (static_init_done) return;\n\n  /* For some embedded targets, global variables are not initialized: */\n\n  /* #ifdef NO_INIT_GLOBAL_POINTERS\n      static_l_desc.static_tree = static_ltree;\n      static_l_desc.extra_bits = extra_lbits;\n      static_d_desc.static_tree = static_dtree;\n      static_d_desc.extra_bits = extra_dbits;\n      static_bl_desc.extra_bits = extra_blbits;\n    #endif */\n\n  /* Initialize the mapping length (0..255) -> length code (0..28) */\n\n  length = 0\n\n  for (code = 0; code < LENGTH_CODES - 1; code++) {\n    base_length[code] = length\n\n    for (n = 0; n < 1 << extra_lbits[code]; n++) {\n      _length_code[length++] = code\n    }\n  } // Assert (length == 256, \"tr_static_init: length != 256\");\n\n  /* Note that the length 255 (match length 258) can be represented\n   * in two different ways: code 284 + 5 bits or code 285, so we\n   * overwrite length_code[255] to use the best encoding:\n   */\n\n  _length_code[length - 1] = code\n  /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n\n  dist = 0\n\n  for (code = 0; code < 16; code++) {\n    base_dist[code] = dist\n\n    for (n = 0; n < 1 << extra_dbits[code]; n++) {\n      _dist_code[dist++] = code\n    }\n  } // Assert (dist == 256, \"tr_static_init: dist != 256\");\n\n  dist >>= 7\n  /* from now on, all distances are divided by 128 */\n\n  for (; code < D_CODES; code++) {\n    base_dist[code] = dist << 7\n\n    for (n = 0; n < 1 << (extra_dbits[code] - 7); n++) {\n      _dist_code[256 + dist++] = code\n    }\n  } // Assert (dist == 256, \"tr_static_init: 256+dist != 512\");\n\n  /* Construct the codes of the static literal tree */\n\n  for (bits = 0; bits <= MAX_BITS; bits++) {\n    bl_count[bits] = 0\n  }\n\n  n = 0\n\n  while (n <= 143) {\n    static_ltree[n * 2 + 1] =\n      /* .Len */\n      8\n    n++\n    bl_count[8]++\n  }\n\n  while (n <= 255) {\n    static_ltree[n * 2 + 1] =\n      /* .Len */\n      9\n    n++\n    bl_count[9]++\n  }\n\n  while (n <= 279) {\n    static_ltree[n * 2 + 1] =\n      /* .Len */\n      7\n    n++\n    bl_count[7]++\n  }\n\n  while (n <= 287) {\n    static_ltree[n * 2 + 1] =\n      /* .Len */\n      8\n    n++\n    bl_count[8]++\n  }\n  /* Codes 286 and 287 do not exist, but we must include them in the\n   * tree construction to get a canonical Huffman tree (longest code\n   * all ones)\n   */\n\n  gen_codes(static_ltree, L_CODES + 1, bl_count)\n  /* The static distance tree is trivial: */\n\n  for (n = 0; n < D_CODES; n++) {\n    static_dtree[n * 2 + 1] =\n      /* .Len */\n      5\n    static_dtree[n * 2] =\n      /* .Code */\n      bi_reverse(n, 5)\n  } // Now data ready and we can init static trees\n\n  static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS)\n  static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS)\n  static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS)\n  // static_init_done = true;\n}\n/* ===========================================================================\n * Initialize a new block.\n */\n\nvar init_block = function init_block(s) {\n  var n\n  /* iterates over tree elements */\n\n  /* Initialize the trees. */\n\n  for (n = 0; n < L_CODES; n++) {\n    s.dyn_ltree[n * 2] =\n      /* .Freq */\n      0\n  }\n\n  for (n = 0; n < D_CODES; n++) {\n    s.dyn_dtree[n * 2] =\n      /* .Freq */\n      0\n  }\n\n  for (n = 0; n < BL_CODES; n++) {\n    s.bl_tree[n * 2] =\n      /* .Freq */\n      0\n  }\n\n  s.dyn_ltree[END_BLOCK * 2] =\n    /* .Freq */\n    1\n  s.opt_len = s.static_len = 0\n  s.last_lit = s.matches = 0\n}\n/* ===========================================================================\n * Flush the bit buffer and align the output on a byte boundary\n */\n\nvar bi_windup = function bi_windup(s) {\n  if (s.bi_valid > 8) {\n    put_short(s, s.bi_buf)\n  } else if (s.bi_valid > 0) {\n    // put_byte(s, (Byte)s->bi_buf);\n    s.pending_buf[s.pending++] = s.bi_buf\n  }\n\n  s.bi_buf = 0\n  s.bi_valid = 0\n}\n/* ===========================================================================\n * Copy a stored block, storing first the length and its\n * one's complement if requested.\n */\n\nvar copy_block = function copy_block(\n  s,\n  buf,\n  len,\n  header\n  // DeflateState *s;\n  // charf    *buf;    /* the input data */\n  // unsigned len;     /* its length */\n  // int      header;  /* true if block header must be written */\n) {\n  bi_windup(s)\n  /* align on byte boundary */\n\n  if (header) {\n    put_short(s, len)\n    put_short(s, ~len)\n  }\n  //  while (len--) {\n  //    put_byte(s, *buf++);\n  //  }\n\n  s.pending_buf.set(s.window.subarray(buf, buf + len), s.pending)\n  s.pending += len\n}\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\n\nvar smaller = function smaller(tree, n, m, depth) {\n  var _n2 = n * 2\n\n  var _m2 = m * 2\n\n  return (\n    tree[_n2] <\n      /* .Freq */\n      tree[_m2] ||\n    /* .Freq */\n    (tree[_n2] ===\n      /* .Freq */\n      tree[_m2] &&\n      /* .Freq */\n      depth[n] <= depth[m])\n  )\n}\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\n\nvar pqdownheap = function pqdownheap(\n  s,\n  tree,\n  k\n  //    deflate_state *s;\n  //    ct_data *tree;  /* the tree to restore */\n  //    int k;               /* node to move down */\n) {\n  var v = s.heap[k]\n  var j = k << 1\n  /* left son of k */\n\n  while (j <= s.heap_len) {\n    /* Set j to the smallest of the two sons: */\n    if (j < s.heap_len && smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {\n      j++\n    }\n    /* Exit if v is smaller than both sons */\n\n    if (smaller(tree, v, s.heap[j], s.depth)) {\n      break\n    }\n    /* Exchange v with the smallest son */\n\n    s.heap[k] = s.heap[j]\n    k = j\n    /* And continue down the tree, setting j to the left son of k */\n\n    j <<= 1\n  }\n\n  s.heap[k] = v\n} // inlined manually\n// const SMALLEST = 1;\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\n\nvar compress_block = function compress_block(\n  s,\n  ltree,\n  dtree\n  //    deflate_state *s;\n  //    const ct_data *ltree; /* literal tree */\n  //    const ct_data *dtree; /* distance tree */\n) {\n  var dist\n  /* distance of matched string */\n\n  var lc\n  /* match length or unmatched char (if dist == 0) */\n\n  var lx = 0\n  /* running index in l_buf */\n\n  var code\n  /* the code to send */\n\n  var extra\n  /* number of extra bits to send */\n\n  if (s.last_lit !== 0) {\n    do {\n      dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | s.pending_buf[s.d_buf + lx * 2 + 1]\n      lc = s.pending_buf[s.l_buf + lx]\n      lx++\n\n      if (dist === 0) {\n        send_code(s, lc, ltree)\n        /* send a literal byte */\n        // Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n      } else {\n        /* Here, lc is the match length - MIN_MATCH */\n        code = _length_code[lc]\n        send_code(s, code + LITERALS + 1, ltree)\n        /* send the length code */\n\n        extra = extra_lbits[code]\n\n        if (extra !== 0) {\n          lc -= base_length[code]\n          send_bits(s, lc, extra)\n          /* send the extra length bits */\n        }\n\n        dist--\n        /* dist is now the match distance - 1 */\n\n        code = d_code(dist) // Assert (code < D_CODES, \"bad d_code\");\n\n        send_code(s, code, dtree)\n        /* send the distance code */\n\n        extra = extra_dbits[code]\n\n        if (extra !== 0) {\n          dist -= base_dist[code]\n          send_bits(s, dist, extra)\n          /* send the extra distance bits */\n        }\n      }\n      /* literal or match pair ? */\n\n      /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */\n      // Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,\n      //       \"pendingBuf overflow\");\n    } while (lx < s.last_lit)\n  }\n\n  send_code(s, END_BLOCK, ltree)\n}\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n *     and corresponding code. The length opt_len is updated; static_len is\n *     also updated if stree is not null. The field max_code is set.\n */\n\nvar build_tree = function build_tree(\n  s,\n  desc //    deflate_state *s; //    tree_desc *desc; /* the tree descriptor */\n) {\n  var tree = desc.dyn_tree\n  var stree = desc.stat_desc.static_tree\n  var has_stree = desc.stat_desc.has_stree\n  var elems = desc.stat_desc.elems\n  var n\n  var m\n  /* iterate over heap elements */\n\n  var max_code = -1\n  /* largest code with non zero frequency */\n\n  var node\n  /* new node being created */\n\n  /* Construct the initial heap, with least frequent element in\n   * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n   * heap[0] is not used.\n   */\n\n  s.heap_len = 0\n  s.heap_max = HEAP_SIZE\n\n  for (n = 0; n < elems; n++) {\n    if (\n      tree[n * 2] !==\n      /* .Freq */\n      0\n    ) {\n      s.heap[++s.heap_len] = max_code = n\n      s.depth[n] = 0\n    } else {\n      tree[n * 2 + 1] =\n        /* .Len */\n        0\n    }\n  }\n  /* The pkzip format requires that at least one distance code exists,\n   * and that at least one bit should be sent even if there is only one\n   * possible code. So to avoid special checks later on we force at least\n   * two codes of non zero frequency.\n   */\n\n  while (s.heap_len < 2) {\n    node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0\n    tree[node * 2] =\n      /* .Freq */\n      1\n    s.depth[node] = 0\n    s.opt_len--\n\n    if (has_stree) {\n      s.static_len -= stree[node * 2 + 1]\n      /* .Len */\n    }\n    /* node is 0 or 1 so it does not have extra bits */\n  }\n\n  desc.max_code = max_code\n  /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n   * establish sub-heaps of increasing lengths:\n   */\n\n  for (\n    n = s.heap_len >> 1;\n    /* int /2 */\n    n >= 1;\n    n--\n  ) {\n    pqdownheap(s, tree, n)\n  }\n  /* Construct the Huffman tree by repeatedly combining the least two\n   * frequent nodes.\n   */\n\n  node = elems\n  /* next internal node of the tree */\n\n  do {\n    // pqremove(s, tree, n);  /* n = node of least frequency */\n\n    /** * pqremove ** */\n    n = s.heap[1]\n    /* SMALLEST */\n    s.heap[1] = s.heap[s.heap_len--]\n    /* SMALLEST */\n    pqdownheap(\n      s,\n      tree,\n      1\n      /* SMALLEST */\n    )\n    /***/\n\n    m = s.heap[1]\n    /* SMALLEST */\n    /* m = node of next least frequency */\n\n    s.heap[--s.heap_max] = n\n    /* keep the nodes sorted by frequency */\n\n    s.heap[--s.heap_max] = m\n    /* Create a new node father of n and m */\n\n    tree[node * 2] =\n      /* .Freq */\n      tree[n * 2] +\n      /* .Freq */\n      tree[m * 2]\n    /* .Freq */\n    s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1\n    tree[n * 2 + 1] =\n      /* .Dad */\n      tree[m * 2 + 1] =\n        /* .Dad */\n        node\n    /* and insert the new node in the heap */\n\n    s.heap[1] = node++\n    /* SMALLEST */\n    pqdownheap(\n      s,\n      tree,\n      1\n      /* SMALLEST */\n    )\n  } while (s.heap_len >= 2)\n\n  s.heap[--s.heap_max] = s.heap[1]\n  /* SMALLEST */\n  /* At this point, the fields freq and dad are set. We can now\n   * generate the bit lengths.\n   */\n\n  gen_bitlen(s, desc)\n  /* The field len is now set, we can generate the bit codes */\n\n  gen_codes(tree, max_code, s.bl_count)\n}\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree.\n */\n\nvar scan_tree = function scan_tree(\n  s,\n  tree,\n  max_code\n  //    deflate_state *s;\n  //    ct_data *tree;   /* the tree to be scanned */\n  //    int max_code;    /* and its largest code of non zero frequency */\n) {\n  var n\n  /* iterates over all tree elements */\n\n  var prevlen = -1\n  /* last emitted length */\n\n  var curlen\n  /* length of current code */\n\n  var nextlen = tree[0 * 2 + 1]\n  /* .Len */\n  /* length of next code */\n\n  var count = 0\n  /* repeat count of the current code */\n\n  var max_count = 7\n  /* max repeat count */\n\n  var min_count = 4\n  /* min repeat count */\n\n  if (nextlen === 0) {\n    max_count = 138\n    min_count = 3\n  }\n\n  tree[(max_code + 1) * 2 + 1] =\n    /* .Len */\n    0xffff\n  /* guard */\n\n  for (n = 0; n <= max_code; n++) {\n    curlen = nextlen\n    nextlen = tree[(n + 1) * 2 + 1]\n    /* .Len */\n\n    if (++count < max_count && curlen === nextlen) {\n      continue\n    } else if (count < min_count) {\n      s.bl_tree[curlen * 2] +=\n        /* .Freq */\n        count\n    } else if (curlen !== 0) {\n      if (curlen !== prevlen) {\n        s.bl_tree[curlen * 2] /* .Freq */++\n      }\n\n      s.bl_tree[REP_3_6 * 2] /* .Freq */++\n    } else if (count <= 10) {\n      s.bl_tree[REPZ_3_10 * 2] /* .Freq */++\n    } else {\n      s.bl_tree[REPZ_11_138 * 2] /* .Freq */++\n    }\n\n    count = 0\n    prevlen = curlen\n\n    if (nextlen === 0) {\n      max_count = 138\n      min_count = 3\n    } else if (curlen === nextlen) {\n      max_count = 6\n      min_count = 3\n    } else {\n      max_count = 7\n      min_count = 4\n    }\n  }\n}\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\n\nvar send_tree = function send_tree(\n  s,\n  tree,\n  max_code\n  //    deflate_state *s;\n  //    ct_data *tree; /* the tree to be scanned */\n  //    int max_code;       /* and its largest code of non zero frequency */\n) {\n  var n\n  /* iterates over all tree elements */\n\n  var prevlen = -1\n  /* last emitted length */\n\n  var curlen\n  /* length of current code */\n\n  var nextlen = tree[0 * 2 + 1]\n  /* .Len */\n  /* length of next code */\n\n  var count = 0\n  /* repeat count of the current code */\n\n  var max_count = 7\n  /* max repeat count */\n\n  var min_count = 4\n  /* min repeat count */\n\n  /* tree[max_code+1].Len = -1; */\n\n  /* guard already set */\n\n  if (nextlen === 0) {\n    max_count = 138\n    min_count = 3\n  }\n\n  for (n = 0; n <= max_code; n++) {\n    curlen = nextlen\n    nextlen = tree[(n + 1) * 2 + 1]\n    /* .Len */\n\n    if (++count < max_count && curlen === nextlen) {\n      continue\n    } else if (count < min_count) {\n      do {\n        send_code(s, curlen, s.bl_tree)\n      } while (--count !== 0)\n    } else if (curlen !== 0) {\n      if (curlen !== prevlen) {\n        send_code(s, curlen, s.bl_tree)\n        count--\n      } // Assert(count >= 3 && count <= 6, \" 3_6?\");\n\n      send_code(s, REP_3_6, s.bl_tree)\n      send_bits(s, count - 3, 2)\n    } else if (count <= 10) {\n      send_code(s, REPZ_3_10, s.bl_tree)\n      send_bits(s, count - 3, 3)\n    } else {\n      send_code(s, REPZ_11_138, s.bl_tree)\n      send_bits(s, count - 11, 7)\n    }\n\n    count = 0\n    prevlen = curlen\n\n    if (nextlen === 0) {\n      max_count = 138\n      min_count = 3\n    } else if (curlen === nextlen) {\n      max_count = 6\n      min_count = 3\n    } else {\n      max_count = 7\n      min_count = 4\n    }\n  }\n}\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\n\nvar build_bl_tree = function build_bl_tree(s) {\n  var max_blindex\n  /* index of last bit length code of non zero freq */\n\n  /* Determine the bit length frequencies for literal and distance trees */\n\n  scan_tree(s, s.dyn_ltree, s.l_desc.max_code)\n  scan_tree(s, s.dyn_dtree, s.d_desc.max_code)\n  /* Build the bit length tree: */\n\n  build_tree(s, s.bl_desc)\n  /* opt_len now includes the length of the tree representations, except\n   * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n   */\n\n  /* Determine the number of bit length codes to send. The pkzip format\n   * requires that at least 4 bit length codes be sent. (appnote.txt says\n   * 3 but the actual value used is 4.)\n   */\n\n  for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {\n    if (\n      s.bl_tree[bl_order[max_blindex] * 2 + 1] !==\n      /* .Len */\n      0\n    ) {\n      break\n    }\n  }\n  /* Update opt_len to include the bit length tree and counts */\n\n  s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4 // Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\",\n  //        s->opt_len, s->static_len));\n\n  return max_blindex\n}\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\n\nvar send_all_trees = function send_all_trees(\n  s,\n  lcodes,\n  dcodes,\n  blcodes //    deflate_state *s; //    int lcodes, dcodes, blcodes; /* number of codes for each tree */\n) {\n  var rank\n  /* index in bl_order */\n  // Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n  // Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n  //        \"too many codes\");\n  // Tracev((stderr, \"\\nbl counts: \"));\n\n  send_bits(s, lcodes - 257, 5)\n  /* not +255 as stated in appnote.txt */\n\n  send_bits(s, dcodes - 1, 5)\n  send_bits(s, blcodes - 4, 4)\n  /* not -3 as stated in appnote.txt */\n\n  for (rank = 0; rank < blcodes; rank++) {\n    // Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n    send_bits(\n      s,\n      s.bl_tree[bl_order[rank] * 2 + 1],\n      /* .Len */\n      3\n    )\n  } // Tracev((stderr, \"\\nbl tree: sent %ld\", s->bits_sent));\n\n  send_tree(s, s.dyn_ltree, lcodes - 1)\n  /* literal tree */\n  // Tracev((stderr, \"\\nlit tree: sent %ld\", s->bits_sent));\n\n  send_tree(s, s.dyn_dtree, dcodes - 1)\n  /* distance tree */\n  // Tracev((stderr, \"\\ndist tree: sent %ld\", s->bits_sent));\n}\n/* ===========================================================================\n * Check if the data type is TEXT or BINARY, using the following algorithm:\n * - TEXT if the two conditions below are satisfied:\n *    a) There are no non-portable control characters belonging to the\n *       \"black list\" (0..6, 14..25, 28..31).\n *    b) There is at least one printable character belonging to the\n *       \"white list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n * - The following partially-portable control characters form a\n *   \"gray list\" that is ignored in this detection algorithm:\n *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n * IN assertion: the fields Freq of dyn_ltree are set.\n */\n\nvar detect_data_type = function detect_data_type(s) {\n  /* black_mask is the bit mask of black-listed bytes\n   * set bits 0..6, 14..25, and 28..31\n   * 0xf3ffc07f = binary 11110011111111111100000001111111\n   */\n  var black_mask = 0xf3ffc07f\n  var n\n  /* Check for non-textual (\"black-listed\") bytes. */\n\n  for (n = 0; n <= 31; n++, black_mask >>>= 1) {\n    if (\n      black_mask & 1 &&\n      s.dyn_ltree[n * 2] !==\n        /* .Freq */\n        0\n    ) {\n      return Z_BINARY\n    }\n  }\n  /* Check for textual (\"white-listed\") bytes. */\n\n  if (\n    s.dyn_ltree[9 * 2] !==\n      /* .Freq */\n      0 ||\n    s.dyn_ltree[10 * 2] !==\n      /* .Freq */\n      0 ||\n    s.dyn_ltree[13 * 2] !==\n      /* .Freq */\n      0\n  ) {\n    return Z_TEXT\n  }\n\n  for (n = 32; n < LITERALS; n++) {\n    if (\n      s.dyn_ltree[n * 2] !==\n      /* .Freq */\n      0\n    ) {\n      return Z_TEXT\n    }\n  }\n  /* There are no \"black-listed\" or \"white-listed\" bytes:\n   * this stream either is empty or has tolerated (\"gray-listed\") bytes only.\n   */\n\n  return Z_BINARY\n}\n\nvar static_init_done = false\n/* ===========================================================================\n * Initialize the tree data structures for a new zlib stream.\n */\n\nvar _tr_init = function _tr_init(s) {\n  if (!static_init_done) {\n    tr_static_init()\n    static_init_done = true\n  }\n\n  s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc)\n  s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc)\n  s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc)\n  s.bi_buf = 0\n  s.bi_valid = 0\n  /* Initialize the first block of the first file: */\n\n  init_block(s)\n}\n/* ===========================================================================\n * Send a stored block\n */\n\nvar _tr_stored_block = function _tr_stored_block(\n  s,\n  buf,\n  stored_len,\n  last\n  // DeflateState *s;\n  // charf *buf;       /* input block */\n  // ulg stored_len;   /* length of input block */\n  // int last;         /* one if this is the last block for a file */\n) {\n  send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3)\n  /* send block type */\n\n  copy_block(s, buf, stored_len, true)\n  /* with header */\n}\n/* ===========================================================================\n * Send one empty static block to give enough lookahead for inflate.\n * This takes 10 bits, of which 7 may remain in the bit buffer.\n */\n\nvar _tr_align = function _tr_align(s) {\n  send_bits(s, STATIC_TREES << 1, 3)\n  send_code(s, END_BLOCK, static_ltree)\n  bi_flush(s)\n}\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and output the encoded block to the zip file.\n */\n\nvar _tr_flush_block = function _tr_flush_block(\n  s,\n  buf,\n  stored_len,\n  last\n  // DeflateState *s;\n  // charf *buf;       /* input block, or NULL if too old */\n  // ulg stored_len;   /* length of input block */\n  // int last;         /* one if this is the last block for a file */\n) {\n  var opt_lenb\n  var static_lenb\n  /* opt_len and static_len in bytes */\n\n  var max_blindex = 0\n  /* index of last bit length code of non zero freq */\n\n  /* Build the Huffman trees unless a stored block is forced */\n\n  if (s.level > 0) {\n    /* Check if the file is binary or text */\n    if (s.strm.data_type === Z_UNKNOWN) {\n      s.strm.data_type = detect_data_type(s)\n    }\n    /* Construct the literal and distance trees */\n\n    build_tree(s, s.l_desc) // Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", s->opt_len,\n    //        s->static_len));\n\n    build_tree(s, s.d_desc) // Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", s->opt_len,\n    //        s->static_len));\n\n    /* At this point, opt_len and static_len are the total bit lengths of\n     * the compressed block data, excluding the tree representations.\n     */\n\n    /* Build the bit length tree for the above two trees, and get the index\n     * in bl_order of the last bit length code to send.\n     */\n\n    max_blindex = build_bl_tree(s)\n    /* Determine the best encoding. Compute the block lengths in bytes. */\n\n    opt_lenb = (s.opt_len + 3 + 7) >>> 3\n    static_lenb = (s.static_len + 3 + 7) >>> 3 // Tracev((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u \",\n    //        opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,\n    //        s->last_lit));\n\n    if (static_lenb <= opt_lenb) {\n      opt_lenb = static_lenb\n    }\n  } else {\n    // Assert(buf != (char*)0, \"lost buf\");\n    opt_lenb = static_lenb = stored_len + 5\n    /* force a stored block */\n  }\n\n  if (stored_len + 4 <= opt_lenb && buf !== -1) {\n    /* 4: two words for the lengths */\n\n    /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n     * Otherwise we can't have processed more than WSIZE input bytes since\n     * the last block flush, because compression would have been\n     * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n     * transform a block into a stored block.\n     */\n    _tr_stored_block(s, buf, stored_len, last)\n  } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {\n    send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3)\n    compress_block(s, static_ltree, static_dtree)\n  } else {\n    send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3)\n    send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1)\n    compress_block(s, s.dyn_ltree, s.dyn_dtree)\n  } // Assert (s->compressed_len == s->bits_sent, \"bad compressed size\");\n\n  /* The above check is made mod 2^32, for files larger than 512 MB\n   * and uLong implemented on 32 bits.\n   */\n\n  init_block(s)\n\n  if (last) {\n    bi_windup(s)\n  } // Tracev((stderr,\"\\ncomprlen %lu(%lu) \", s->compressed_len>>3,\n  //       s->compressed_len-7*last));\n}\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\n\nvar _tr_tally = function _tr_tally(\n  s,\n  dist,\n  lc\n  //    deflate_state *s;\n  //    unsigned dist;  /* distance of matched string */\n  //    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */\n) {\n  // let out_length, in_length, dcode;\n  s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff\n  s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff\n  s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff\n  s.last_lit++\n\n  if (dist === 0) {\n    /* lc is the unmatched char */\n    s.dyn_ltree[lc * 2] /* .Freq */++\n  } else {\n    s.matches++\n    /* Here, lc is the match length - MIN_MATCH */\n\n    dist--\n    /* dist = match distance - 1 */\n    // Assert((ush)dist < (ush)MAX_DIST(s) &&\n    //       (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n    //       (ush)d_code(dist) < (ush)D_CODES,  \"_tr_tally: bad match\");\n\n    s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2] /* .Freq */++\n    s.dyn_dtree[d_code(dist) * 2] /* .Freq */++\n  } // (!) This block is disabled in zlib defaults,\n  // don't enable it for binary compatibility\n  // #ifdef TRUNCATE_BLOCK\n  //  /* Try to guess if it is profitable to stop the current block here */\n  //  if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {\n  //    /* Compute an upper bound for the compressed length */\n  //    out_length = s.last_lit*8;\n  //    in_length = s.strstart - s.block_start;\n  //\n  //    for (dcode = 0; dcode < D_CODES; dcode++) {\n  //      out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);\n  //    }\n  //    out_length >>>= 3;\n  //    //Tracev((stderr,\"\\nlast_lit %u, in %ld, out ~%ld(%ld%%) \",\n  //    //       s->last_lit, in_length, out_length,\n  //    //       100L - out_length*100L/in_length));\n  //    if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {\n  //      return true;\n  //    }\n  //  }\n  // #endif\n\n  return s.last_lit === s.lit_bufsize - 1\n  /* We avoid equality with lit_bufsize because of wraparound at 64K\n   * on 16 bit machines and because stored blocks are restricted to\n   * 64K-1 bytes.\n   */\n}\n\nvar _tr_init_1 = _tr_init\nvar _tr_stored_block_1 = _tr_stored_block\nvar _tr_flush_block_1 = _tr_flush_block\nvar _tr_tally_1 = _tr_tally\nvar _tr_align_1 = _tr_align\nvar trees = {\n  _tr_init: _tr_init_1,\n  _tr_stored_block: _tr_stored_block_1,\n  _tr_flush_block: _tr_flush_block_1,\n  _tr_tally: _tr_tally_1,\n  _tr_align: _tr_align_1,\n}\n\n// It isn't worth it to make additional optimizations as in original.\n// Small size is preferable.\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar adler32 = function adler32(adler, buf, len, pos) {\n  var s1 = (adler & 0xffff) | 0\n  var s2 = ((adler >>> 16) & 0xffff) | 0\n  var n = 0\n\n  while (len !== 0) {\n    // Set limit ~ twice less than 5552, to keep\n    // s2 in 31-bits, because we force signed ints.\n    // in other case %= will fail.\n    n = len > 2000 ? 2000 : len\n    len -= n\n\n    do {\n      s1 = (s1 + buf[pos++]) | 0\n      s2 = (s2 + s1) | 0\n    } while (--n)\n\n    s1 %= 65521\n    s2 %= 65521\n  }\n\n  return s1 | (s2 << 16) | 0\n}\n\nvar adler32_1 = adler32\n\n// So write code to minimize size - no pregenerated tables\n// and array tools dependencies.\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n// Use ordinary array, since untyped makes no boost here\n\nvar makeTable = function makeTable() {\n  var c\n  var table = []\n\n  for (var n = 0; n < 256; n++) {\n    c = n\n\n    for (var k = 0; k < 8; k++) {\n      c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1\n    }\n\n    table[n] = c\n  }\n\n  return table\n} // Create table on load. Just 255 signed longs. Not a problem.\n\nvar crcTable = new Uint32Array(makeTable())\n\nvar crc32 = function crc32(crc, buf, len, pos) {\n  var t = crcTable\n  var end = pos + len\n  crc ^= -1\n\n  for (var i = pos; i < end; i++) {\n    crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xff]\n  }\n\n  return crc ^ -1 // >>> 0;\n}\n\nvar crc32_1 = crc32\n\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar messages = {\n  2: 'need dictionary',\n\n  /* Z_NEED_DICT       2  */\n  1: 'stream end',\n\n  /* Z_STREAM_END      1  */\n  0: '',\n\n  /* Z_OK              0  */\n  '-1': 'file error',\n\n  /* Z_ERRNO         (-1) */\n  '-2': 'stream error',\n\n  /* Z_STREAM_ERROR  (-2) */\n  '-3': 'data error',\n\n  /* Z_DATA_ERROR    (-3) */\n  '-4': 'insufficient memory',\n\n  /* Z_MEM_ERROR     (-4) */\n  '-5': 'buffer error',\n\n  /* Z_BUF_ERROR     (-5) */\n  '-6': 'incompatible version',\n  /* Z_VERSION_ERROR (-6) */\n}\n\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nexport var constants = {\n  /* Allowed flush values; see deflate() and inflate() below for details */\n  Z_NO_FLUSH: 0,\n  Z_PARTIAL_FLUSH: 1,\n  Z_SYNC_FLUSH: 2,\n  Z_FULL_FLUSH: 3,\n  Z_FINISH: 4,\n  Z_BLOCK: 5,\n  Z_TREES: 6,\n\n  /* Return codes for the compression/decompression functions. Negative values\n   * are errors, positive values are used for special but normal events.\n   */\n  Z_OK: 0,\n  Z_STREAM_END: 1,\n  Z_NEED_DICT: 2,\n  Z_ERRNO: -1,\n  Z_STREAM_ERROR: -2,\n  Z_DATA_ERROR: -3,\n  Z_MEM_ERROR: -4,\n  Z_BUF_ERROR: -5,\n  // Z_VERSION_ERROR: -6,\n\n  /* compression levels */\n  Z_NO_COMPRESSION: 0,\n  Z_BEST_SPEED: 1,\n  Z_BEST_COMPRESSION: 9,\n  Z_DEFAULT_COMPRESSION: -1,\n  Z_FILTERED: 1,\n  Z_HUFFMAN_ONLY: 2,\n  Z_RLE: 3,\n  Z_FIXED: 4,\n  Z_DEFAULT_STRATEGY: 0,\n\n  /* Possible values of the data_type field (though see inflate()) */\n  Z_BINARY: 0,\n  Z_TEXT: 1,\n  // Z_ASCII:                1, // = Z_TEXT (deprecated)\n  Z_UNKNOWN: 2,\n\n  /* The deflate compression method */\n  Z_DEFLATED: 8, // Z_NULL:                 null // Use -1 or null inline, depending on var type\n}\n\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar _tr_init$1 = trees._tr_init\nvar _tr_stored_block$1 = trees._tr_stored_block\nvar _tr_flush_block$1 = trees._tr_flush_block\nvar _tr_tally$1 = trees._tr_tally\nvar _tr_align$1 = trees._tr_align\n/* Public constants ========================================================== */\n\n/* =========================================================================== */\n\nvar Z_NO_FLUSH = constants.Z_NO_FLUSH\nvar Z_PARTIAL_FLUSH = constants.Z_PARTIAL_FLUSH\nvar Z_FULL_FLUSH = constants.Z_FULL_FLUSH\nvar Z_FINISH = constants.Z_FINISH\nvar Z_BLOCK = constants.Z_BLOCK\nvar Z_OK = constants.Z_OK\nvar Z_STREAM_END = constants.Z_STREAM_END\nvar Z_STREAM_ERROR = constants.Z_STREAM_ERROR\nvar Z_DATA_ERROR = constants.Z_DATA_ERROR\nvar Z_BUF_ERROR = constants.Z_BUF_ERROR\nvar Z_DEFAULT_COMPRESSION = constants.Z_DEFAULT_COMPRESSION\nvar Z_FILTERED = constants.Z_FILTERED\nvar Z_HUFFMAN_ONLY = constants.Z_HUFFMAN_ONLY\nvar Z_RLE = constants.Z_RLE\nvar Z_FIXED$1 = constants.Z_FIXED\nvar Z_DEFAULT_STRATEGY = constants.Z_DEFAULT_STRATEGY\nvar Z_UNKNOWN$1 = constants.Z_UNKNOWN\nvar Z_DEFLATED = constants.Z_DEFLATED\n/* ============================================================================ */\n\nvar MAX_MEM_LEVEL = 9\n/* Maximum value for memLevel in deflateInit2 */\n\nvar MAX_WBITS = 15\n/* 32K LZ77 window */\n\nvar DEF_MEM_LEVEL = 8\nvar LENGTH_CODES$1 = 29\n/* number of length codes, not counting the special END_BLOCK code */\n\nvar LITERALS$1 = 256\n/* number of literal bytes 0..255 */\n\nvar L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1\n/* number of Literal or Length codes, including the END_BLOCK code */\n\nvar D_CODES$1 = 30\n/* number of distance codes */\n\nvar BL_CODES$1 = 19\n/* number of codes used to transfer the bit lengths */\n\nvar HEAP_SIZE$1 = 2 * L_CODES$1 + 1\n/* maximum heap size */\n\nvar MAX_BITS$1 = 15\n/* All codes must not exceed MAX_BITS bits */\n\nvar MIN_MATCH$1 = 3\nvar MAX_MATCH$1 = 258\nvar MIN_LOOKAHEAD = MAX_MATCH$1 + MIN_MATCH$1 + 1\nvar PRESET_DICT = 0x20\nvar INIT_STATE = 42\nvar EXTRA_STATE = 69\nvar NAME_STATE = 73\nvar COMMENT_STATE = 91\nvar HCRC_STATE = 103\nvar BUSY_STATE = 113\nvar FINISH_STATE = 666\nvar BS_NEED_MORE = 1\n/* block not completed, need more input or more output */\n\nvar BS_BLOCK_DONE = 2\n/* block flush performed */\n\nvar BS_FINISH_STARTED = 3\n/* finish started, need only more output at next deflate */\n\nvar BS_FINISH_DONE = 4\n/* finish done, accept no more input or output */\n\nvar OS_CODE = 0x03 // Unix :) . Don't detect, use this default.\n\nvar err = function err(strm, errorCode) {\n  strm.msg = messages[errorCode]\n  return errorCode\n}\n\nvar rank = function rank(f) {\n  return (f << 1) - (f > 4 ? 9 : 0)\n}\n\nvar zero$1 = function zero(buf) {\n  var len = buf.length\n\n  while (--len >= 0) {\n    buf[len] = 0\n  }\n}\n\nvar HASH_ZLIB = function HASH_ZLIB(s, prev, data) {\n  return ((prev << s.hash_shift) ^ data) & s.hash_mask\n} // This hash causes less collisions, https://github.com/nodeca/pako/issues/135\n// But breaks binary compatibility\n// let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask;\n\nvar HASH = HASH_ZLIB\n/* =========================================================================\n * Flush as much pending output as possible. All deflate() output goes\n * through this function so some applications may wish to modify it\n * to avoid allocating a large strm->output buffer and copying into it.\n * (See also read_buf()).\n */\n\nvar flush_pending = function flush_pending(strm) {\n  var s = strm.state // _tr_flush_bits(s);\n\n  var len = s.pending\n\n  if (len > strm.avail_out) {\n    len = strm.avail_out\n  }\n\n  if (len === 0) {\n    return\n  }\n\n  strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out)\n  strm.next_out += len\n  s.pending_out += len\n  strm.total_out += len\n  strm.avail_out -= len\n  s.pending -= len\n\n  if (s.pending === 0) {\n    s.pending_out = 0\n  }\n}\n\nvar flush_block_only = function flush_block_only(s, last) {\n  _tr_flush_block$1(s, s.block_start >= 0 ? s.block_start : -1, s.strstart - s.block_start, last)\n\n  s.block_start = s.strstart\n  flush_pending(s.strm)\n}\n\nvar put_byte = function put_byte(s, b) {\n  s.pending_buf[s.pending++] = b\n}\n/* =========================================================================\n * Put a short in the pending buffer. The 16-bit value is put in MSB order.\n * IN assertion: the stream state is correct and there is enough room in\n * pending_buf.\n */\n\nvar putShortMSB = function putShortMSB(s, b) {\n  //  put_byte(s, (Byte)(b >> 8));\n  //  put_byte(s, (Byte)(b & 0xff));\n  s.pending_buf[s.pending++] = (b >>> 8) & 0xff\n  s.pending_buf[s.pending++] = b & 0xff\n}\n/* ===========================================================================\n * Read a new buffer from the current input stream, update the adler32\n * and total number of bytes read.  All deflate() input goes through\n * this function so some applications may wish to modify it to avoid\n * allocating a large strm->input buffer and copying from it.\n * (See also flush_pending()).\n */\n\nvar read_buf = function read_buf(strm, buf, start, size) {\n  var len = strm.avail_in\n\n  if (len > size) {\n    len = size\n  }\n\n  if (len === 0) {\n    return 0\n  }\n\n  strm.avail_in -= len // zmemcpy(buf, strm->next_in, len);\n\n  buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start)\n\n  if (strm.state.wrap === 1) {\n    strm.adler = adler32_1(strm.adler, buf, len, start)\n  } else if (strm.state.wrap === 2) {\n    strm.adler = crc32_1(strm.adler, buf, len, start)\n  }\n\n  strm.next_in += len\n  strm.total_in += len\n  return len\n}\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n * OUT assertion: the match length is not greater than s->lookahead.\n */\n\nvar longest_match = function longest_match(s, cur_match) {\n  var chain_length = s.max_chain_length\n  /* max hash chain length */\n\n  var scan = s.strstart\n  /* current string */\n\n  var match\n  /* matched string */\n\n  var len\n  /* length of current match */\n\n  var best_len = s.prev_length\n  /* best match length so far */\n\n  var nice_match = s.nice_match\n  /* stop if match long enough */\n\n  var limit = s.strstart > s.w_size - MIN_LOOKAHEAD ? s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0\n  /* NIL */\n  var _win = s.window // shortcut\n\n  var wmask = s.w_mask\n  var prev = s.prev\n  /* Stop when cur_match becomes <= limit. To simplify the code,\n   * we prevent matches with the string of window index 0.\n   */\n\n  var strend = s.strstart + MAX_MATCH$1\n  var scan_end1 = _win[scan + best_len - 1]\n  var scan_end = _win[scan + best_len]\n  /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n   * It is easy to get rid of this optimization if necessary.\n   */\n  // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n  /* Do not waste too much time if we already have a good match: */\n\n  if (s.prev_length >= s.good_match) {\n    chain_length >>= 2\n  }\n  /* Do not look for matches beyond the end of the input. This is necessary\n   * to make deflate deterministic.\n   */\n\n  if (nice_match > s.lookahead) {\n    nice_match = s.lookahead\n  } // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, \"need lookahead\");\n\n  do {\n    // Assert(cur_match < s->strstart, \"no future\");\n    match = cur_match\n    /* Skip to next match if the match length cannot increase\n     * or if the match length is less than 2.  Note that the checks below\n     * for insufficient lookahead only occur occasionally for performance\n     * reasons.  Therefore uninitialized memory will be accessed, and\n     * conditional jumps will be made that depend on those values.\n     * However the length of the match is limited to the lookahead, so\n     * the output of deflate is not affected by the uninitialized values.\n     */\n\n    if (\n      _win[match + best_len] !== scan_end ||\n      _win[match + best_len - 1] !== scan_end1 ||\n      _win[match] !== _win[scan] ||\n      _win[++match] !== _win[scan + 1]\n    ) {\n      continue\n    }\n    /* The check at best_len-1 can be removed because it will be made\n     * again later. (This heuristic is not always a win.)\n     * It is not necessary to compare scan[2] and match[2] since they\n     * are always equal when the other bytes match, given that\n     * the hash keys are equal and that HASH_BITS >= 8.\n     */\n\n    scan += 2\n    match++ // Assert(*scan == *match, \"match[2]?\");\n\n    /* We check for insufficient lookahead only every 8th comparison;\n     * the 256th check will be made at strstart+258.\n     */\n\n    do {\n      /* jshint noempty:false */\n    } while (\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      _win[++scan] === _win[++match] &&\n      scan < strend\n    ) // Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n\n    len = MAX_MATCH$1 - (strend - scan)\n    scan = strend - MAX_MATCH$1\n\n    if (len > best_len) {\n      s.match_start = cur_match\n      best_len = len\n\n      if (len >= nice_match) {\n        break\n      }\n\n      scan_end1 = _win[scan + best_len - 1]\n      scan_end = _win[scan + best_len]\n    }\n  } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0)\n\n  if (best_len <= s.lookahead) {\n    return best_len\n  }\n\n  return s.lookahead\n}\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n *    At least one byte has been read, or avail_in == 0; reads are\n *    performed for at least two bytes (required for the zip translate_eol\n *    option -- not supported here).\n */\n\nvar fill_window = function fill_window(s) {\n  var _w_size = s.w_size\n  var p\n  var n\n  var m\n  var more\n  var str // Assert(s->lookahead < MIN_LOOKAHEAD, \"already enough lookahead\");\n\n  do {\n    more = s.window_size - s.lookahead - s.strstart // JS ints have 32 bit, block below not needed\n\n    /* Deal with !@#$% 64K limit: */\n    // if (sizeof(int) <= 2) {\n    //    if (more == 0 && s->strstart == 0 && s->lookahead == 0) {\n    //        more = wsize;\n    //\n    //  } else if (more == (unsigned)(-1)) {\n    //        /* Very unlikely, but possible on 16 bit machine if\n    //         * strstart == 0 && lookahead == 1 (input done a byte at time)\n    //         */\n    //        more--;\n    //    }\n    // }\n\n    /* If the window is almost full and there is insufficient lookahead,\n     * move the upper half to the lower one to make room in the upper half.\n     */\n\n    if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {\n      s.window.set(s.window.subarray(_w_size, _w_size + _w_size), 0)\n      s.match_start -= _w_size\n      s.strstart -= _w_size\n      /* we now have strstart >= MAX_DIST */\n\n      s.block_start -= _w_size\n      /* Slide the hash table (could be avoided with 32 bit values\n         at the expense of memory usage). We slide even when level == 0\n         to keep the hash table consistent if we switch back to level > 0\n         later. (Using level 0 permanently is not an optimal usage of\n         zlib, so we don't care about this pathological case.)\n         */\n\n      n = s.hash_size\n      p = n\n\n      do {\n        m = s.head[--p]\n        s.head[p] = m >= _w_size ? m - _w_size : 0\n      } while (--n)\n\n      n = _w_size\n      p = n\n\n      do {\n        m = s.prev[--p]\n        s.prev[p] = m >= _w_size ? m - _w_size : 0\n        /* If n is not on any hash chain, prev[n] is garbage but\n         * its value will never be used.\n         */\n      } while (--n)\n\n      more += _w_size\n    }\n\n    if (s.strm.avail_in === 0) {\n      break\n    }\n    /* If there was no sliding:\n     *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n     *    more == window_size - lookahead - strstart\n     * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n     * => more >= window_size - 2*WSIZE + 2\n     * In the BIG_MEM or MMAP case (not yet supported),\n     *   window_size == input_size + MIN_LOOKAHEAD  &&\n     *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n     * Otherwise, window_size == 2*WSIZE so more >= 2.\n     * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n     */\n    // Assert(more >= 2, \"more < 2\");\n\n    n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more)\n    s.lookahead += n\n    /* Initialize the hash value now that we have some input: */\n\n    if (s.lookahead + s.insert >= MIN_MATCH$1) {\n      str = s.strstart - s.insert\n      s.ins_h = s.window[str]\n      /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */\n\n      s.ins_h = HASH(s, s.ins_h, s.window[str + 1]) // #if MIN_MATCH != 3\n      //        Call update_hash() MIN_MATCH-3 more times\n      // #endif\n\n      while (s.insert) {\n        /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n        s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH$1 - 1])\n        s.prev[str & s.w_mask] = s.head[s.ins_h]\n        s.head[s.ins_h] = str\n        str++\n        s.insert--\n\n        if (s.lookahead + s.insert < MIN_MATCH$1) {\n          break\n        }\n      }\n    }\n    /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n     * but this is not important since only literal bytes will be emitted.\n     */\n  } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0)\n  /* If the WIN_INIT bytes after the end of the current data have never been\n   * written, then zero those bytes in order to avoid memory check reports of\n   * the use of uninitialized (or uninitialised as Julian writes) bytes by\n   * the longest match routines.  Update the high water mark for the next\n   * time through here.  WIN_INIT is set to MAX_MATCH since the longest match\n   * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.\n   */\n  //  if (s.high_water < s.window_size) {\n  //    const curr = s.strstart + s.lookahead;\n  //    let init = 0;\n  //\n  //    if (s.high_water < curr) {\n  //      /* Previous high water mark below current data -- zero WIN_INIT\n  //       * bytes or up to end of window, whichever is less.\n  //       */\n  //      init = s.window_size - curr;\n  //      if (init > WIN_INIT)\n  //        init = WIN_INIT;\n  //      zmemzero(s->window + curr, (unsigned)init);\n  //      s->high_water = curr + init;\n  //    }\n  //    else if (s->high_water < (ulg)curr + WIN_INIT) {\n  //      /* High water mark at or above current data, but below current data\n  //       * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up\n  //       * to end of window, whichever is less.\n  //       */\n  //      init = (ulg)curr + WIN_INIT - s->high_water;\n  //      if (init > s->window_size - s->high_water)\n  //        init = s->window_size - s->high_water;\n  //      zmemzero(s->window + s->high_water, (unsigned)init);\n  //      s->high_water += init;\n  //    }\n  //  }\n  //\n  //  Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n  //    \"not enough room for search\");\n}\n/* ===========================================================================\n * Copy without compression as much as possible from the input stream, return\n * the current block state.\n * This function does not insert new strings in the dictionary since\n * uncompressible data is probably not useful. This function is used\n * only for the level=0 compression option.\n * NOTE: this function should be optimized to avoid extra copying from\n * window to pending_buf.\n */\n\nvar deflate_stored = function deflate_stored(s, flush) {\n  /* Stored blocks are limited to 0xffff bytes, pending_buf is limited\n   * to pending_buf_size, and each stored block has a 5 byte header:\n   */\n  var max_block_size = 0xffff\n\n  if (max_block_size > s.pending_buf_size - 5) {\n    max_block_size = s.pending_buf_size - 5\n  }\n  /* Copy as much as possible from input to output: */\n\n  for (;;) {\n    /* Fill the window as much as possible: */\n    if (s.lookahead <= 1) {\n      // Assert(s->strstart < s->w_size+MAX_DIST(s) ||\n      //  s->block_start >= (long)s->w_size, \"slide too late\");\n      //      if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||\n      //        s.block_start >= s.w_size)) {\n      //        throw  new Error(\"slide too late\");\n      //      }\n      fill_window(s)\n\n      if (s.lookahead === 0 && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE\n      }\n\n      if (s.lookahead === 0) {\n        break\n      }\n      /* flush the current block */\n    } // Assert(s->block_start >= 0L, \"block gone\");\n    //    if (s.block_start < 0) throw new Error(\"block gone\");\n\n    s.strstart += s.lookahead\n    s.lookahead = 0\n    /* Emit a stored block if pending_buf will be full: */\n\n    var max_start = s.block_start + max_block_size\n\n    if (s.strstart === 0 || s.strstart >= max_start) {\n      /* strstart == 0 is possible when wraparound on 16-bit machine */\n      s.lookahead = s.strstart - max_start\n      s.strstart = max_start\n      /** * FLUSH_BLOCK(s, 0); ** */\n\n      flush_block_only(s, false)\n\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE\n      }\n      /***/\n    }\n    /* Flush if we may have to slide, otherwise block_start may become\n     * negative and the data will be gone:\n     */\n\n    if (s.strstart - s.block_start >= s.w_size - MIN_LOOKAHEAD) {\n      /** * FLUSH_BLOCK(s, 0); ** */\n      flush_block_only(s, false)\n\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE\n      }\n      /***/\n    }\n  }\n\n  s.insert = 0\n\n  if (flush === Z_FINISH) {\n    /** * FLUSH_BLOCK(s, 1); ** */\n    flush_block_only(s, true)\n\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED\n    }\n    /***/\n\n    return BS_FINISH_DONE\n  }\n\n  if (s.strstart > s.block_start) {\n    /** * FLUSH_BLOCK(s, 0); ** */\n    flush_block_only(s, false)\n\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE\n    }\n    /***/\n  }\n\n  return BS_NEED_MORE\n}\n/* ===========================================================================\n * Compress as much as possible from the input stream, return the current\n * block state.\n * This function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\n\nvar deflate_fast = function deflate_fast(s, flush) {\n  var hash_head\n  /* head of the hash chain */\n\n  var bflush\n  /* set if current block must be flushed */\n\n  for (;;) {\n    /* Make sure that we always have enough lookahead, except\n     * at the end of the input file. We need MAX_MATCH bytes\n     * for the next match, plus MIN_MATCH bytes to insert the\n     * string following the next match.\n     */\n    if (s.lookahead < MIN_LOOKAHEAD) {\n      fill_window(s)\n\n      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE\n      }\n\n      if (s.lookahead === 0) {\n        break\n        /* flush the current block */\n      }\n    }\n    /* Insert the string window[strstart .. strstart+2] in the\n     * dictionary, and set hash_head to the head of the hash chain:\n     */\n\n    hash_head = 0\n    /* NIL */\n\n    if (s.lookahead >= MIN_MATCH$1) {\n      /** * INSERT_STRING(s, s.strstart, hash_head); ** */\n      s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1])\n      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]\n      s.head[s.ins_h] = s.strstart\n      /***/\n    }\n    /* Find the longest match, discarding those <= prev_length.\n     * At this point we have always match_length < MIN_MATCH\n     */\n\n    if (\n      hash_head !== 0 &&\n      /* NIL */\n      s.strstart - hash_head <= s.w_size - MIN_LOOKAHEAD\n    ) {\n      /* To simplify the code, we prevent matches with the string\n       * of window index 0 (in particular we have to avoid a match\n       * of the string with itself at the start of the input file).\n       */\n      s.match_length = longest_match(s, hash_head)\n      /* longest_match() sets match_start */\n    }\n\n    if (s.match_length >= MIN_MATCH$1) {\n      // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only\n\n      /**\n       * _tr_tally_dist(s, s.strstart - s.match_start,\n                       s.match_length - MIN_MATCH, bflush); **\n       */\n      bflush = _tr_tally$1(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1)\n      s.lookahead -= s.match_length\n      /* Insert new strings in the hash table only if the match length\n       * is not too large. This saves time but degrades compression.\n       */\n\n      if (\n        s.match_length <= s.max_lazy_match &&\n        /* max_insert_length */\n        s.lookahead >= MIN_MATCH$1\n      ) {\n        s.match_length--\n        /* string at strstart already in table */\n\n        do {\n          s.strstart++\n          /** * INSERT_STRING(s, s.strstart, hash_head); ** */\n\n          s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1])\n          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]\n          s.head[s.ins_h] = s.strstart\n          /***/\n\n          /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n           * always MIN_MATCH bytes ahead.\n           */\n        } while (--s.match_length !== 0)\n\n        s.strstart++\n      } else {\n        s.strstart += s.match_length\n        s.match_length = 0\n        s.ins_h = s.window[s.strstart]\n        /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */\n\n        s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]) // #if MIN_MATCH != 3\n        //                Call UPDATE_HASH() MIN_MATCH-3 more times\n        // #endif\n\n        /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n         * matter since it will be recomputed at next deflate call.\n         */\n      }\n    } else {\n      /* No match, output a literal byte */\n      // Tracevv((stderr,\"%c\", s.window[s.strstart]));\n\n      /** * _tr_tally_lit(s, s.window[s.strstart], bflush); ** */\n      bflush = _tr_tally$1(s, 0, s.window[s.strstart])\n      s.lookahead--\n      s.strstart++\n    }\n\n    if (bflush) {\n      /** * FLUSH_BLOCK(s, 0); ** */\n      flush_block_only(s, false)\n\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE\n      }\n      /***/\n    }\n  }\n\n  s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1\n\n  if (flush === Z_FINISH) {\n    /** * FLUSH_BLOCK(s, 1); ** */\n    flush_block_only(s, true)\n\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED\n    }\n    /***/\n\n    return BS_FINISH_DONE\n  }\n\n  if (s.last_lit) {\n    /** * FLUSH_BLOCK(s, 0); ** */\n    flush_block_only(s, false)\n\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE\n    }\n    /***/\n  }\n\n  return BS_BLOCK_DONE\n}\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\n\nvar deflate_slow = function deflate_slow(s, flush) {\n  var hash_head\n  /* head of hash chain */\n\n  var bflush\n  /* set if current block must be flushed */\n\n  var max_insert\n  /* Process the input block. */\n\n  for (;;) {\n    /* Make sure that we always have enough lookahead, except\n     * at the end of the input file. We need MAX_MATCH bytes\n     * for the next match, plus MIN_MATCH bytes to insert the\n     * string following the next match.\n     */\n    if (s.lookahead < MIN_LOOKAHEAD) {\n      fill_window(s)\n\n      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE\n      }\n\n      if (s.lookahead === 0) {\n        break\n      }\n      /* flush the current block */\n    }\n    /* Insert the string window[strstart .. strstart+2] in the\n     * dictionary, and set hash_head to the head of the hash chain:\n     */\n\n    hash_head = 0\n    /* NIL */\n\n    if (s.lookahead >= MIN_MATCH$1) {\n      /** * INSERT_STRING(s, s.strstart, hash_head); ** */\n      s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1])\n      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]\n      s.head[s.ins_h] = s.strstart\n      /***/\n    }\n    /* Find the longest match, discarding those <= prev_length.\n     */\n\n    s.prev_length = s.match_length\n    s.prev_match = s.match_start\n    s.match_length = MIN_MATCH$1 - 1\n\n    if (\n      hash_head !== 0 &&\n      /* NIL */\n      s.prev_length < s.max_lazy_match &&\n      s.strstart - hash_head <= s.w_size - MIN_LOOKAHEAD\n      /* MAX_DIST(s) */\n    ) {\n      /* To simplify the code, we prevent matches with the string\n       * of window index 0 (in particular we have to avoid a match\n       * of the string with itself at the start of the input file).\n       */\n      s.match_length = longest_match(s, hash_head)\n      /* longest_match() sets match_start */\n\n      if (\n        s.match_length <= 5 &&\n        (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096))\n        /* TOO_FAR */\n      ) {\n        /* If prev_match is also MIN_MATCH, match_start is garbage\n         * but we will ignore the current match anyway.\n         */\n        s.match_length = MIN_MATCH$1 - 1\n      }\n    }\n    /* If there was a match at the previous step and the current\n     * match is not better, output the previous match:\n     */\n\n    if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) {\n      max_insert = s.strstart + s.lookahead - MIN_MATCH$1\n      /* Do not insert strings in hash table beyond this. */\n      // check_match(s, s.strstart-1, s.prev_match, s.prev_length);\n\n      /**\n       *_tr_tally_dist(s, s.strstart - 1 - s.prev_match,\n                       s.prev_length - MIN_MATCH, bflush);**\n       */\n\n      bflush = _tr_tally$1(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1)\n      /* Insert in hash table all strings up to the end of the match.\n       * strstart-1 and strstart are already inserted. If there is not\n       * enough lookahead, the last two strings are not inserted in\n       * the hash table.\n       */\n\n      s.lookahead -= s.prev_length - 1\n      s.prev_length -= 2\n\n      do {\n        if (++s.strstart <= max_insert) {\n          /** * INSERT_STRING(s, s.strstart, hash_head); ** */\n          s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH$1 - 1])\n          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]\n          s.head[s.ins_h] = s.strstart\n          /***/\n        }\n      } while (--s.prev_length !== 0)\n\n      s.match_available = 0\n      s.match_length = MIN_MATCH$1 - 1\n      s.strstart++\n\n      if (bflush) {\n        /** * FLUSH_BLOCK(s, 0); ** */\n        flush_block_only(s, false)\n\n        if (s.strm.avail_out === 0) {\n          return BS_NEED_MORE\n        }\n        /***/\n      }\n    } else if (s.match_available) {\n      /* If there was no match at the previous position, output a\n       * single literal. If there was a match but the current match\n       * is longer, truncate the previous match to a single literal.\n       */\n      // Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n\n      /** * _tr_tally_lit(s, s.window[s.strstart-1], bflush); ** */\n      bflush = _tr_tally$1(s, 0, s.window[s.strstart - 1])\n\n      if (bflush) {\n        /** * FLUSH_BLOCK_ONLY(s, 0) ** */\n        flush_block_only(s, false)\n        /***/\n      }\n\n      s.strstart++\n      s.lookahead--\n\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE\n      }\n    } else {\n      /* There is no previous match to compare with, wait for\n       * the next step to decide.\n       */\n      s.match_available = 1\n      s.strstart++\n      s.lookahead--\n    }\n  } // Assert (flush != Z_NO_FLUSH, \"no flush?\");\n\n  if (s.match_available) {\n    // Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n\n    /** * _tr_tally_lit(s, s.window[s.strstart-1], bflush); ** */\n    bflush = _tr_tally$1(s, 0, s.window[s.strstart - 1])\n    s.match_available = 0\n  }\n\n  s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1\n\n  if (flush === Z_FINISH) {\n    /** * FLUSH_BLOCK(s, 1); ** */\n    flush_block_only(s, true)\n\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED\n    }\n    /***/\n\n    return BS_FINISH_DONE\n  }\n\n  if (s.last_lit) {\n    /** * FLUSH_BLOCK(s, 0); ** */\n    flush_block_only(s, false)\n\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE\n    }\n    /***/\n  }\n\n  return BS_BLOCK_DONE\n}\n/* ===========================================================================\n * For Z_RLE, simply look for runs of bytes, generate matches only of distance\n * one.  Do not maintain a hash table.  (It will be regenerated if this run of\n * deflate switches away from Z_RLE.)\n */\n\nvar deflate_rle = function deflate_rle(s, flush) {\n  var bflush\n  /* set if current block must be flushed */\n\n  var prev\n  /* byte at distance one to match */\n\n  var scan\n  var strend\n  /* scan goes up to strend for length of run */\n\n  var _win = s.window\n\n  for (;;) {\n    /* Make sure that we always have enough lookahead, except\n     * at the end of the input file. We need MAX_MATCH bytes\n     * for the longest run, plus one for the unrolled loop.\n     */\n    if (s.lookahead <= MAX_MATCH$1) {\n      fill_window(s)\n\n      if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE\n      }\n\n      if (s.lookahead === 0) {\n        break\n      }\n      /* flush the current block */\n    }\n    /* See how many times the previous byte repeats */\n\n    s.match_length = 0\n\n    if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) {\n      scan = s.strstart - 1\n      prev = _win[scan]\n\n      if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {\n        strend = s.strstart + MAX_MATCH$1\n\n        do {\n          /* jshint noempty:false */\n        } while (\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          prev === _win[++scan] &&\n          scan < strend\n        )\n\n        s.match_length = MAX_MATCH$1 - (strend - scan)\n\n        if (s.match_length > s.lookahead) {\n          s.match_length = s.lookahead\n        }\n      } // Assert(scan <= s->window+(uInt)(s->window_size-1), \"wild scan\");\n    }\n    /* Emit match if have run of MIN_MATCH or longer, else emit literal */\n\n    if (s.match_length >= MIN_MATCH$1) {\n      // check_match(s, s.strstart, s.strstart - 1, s.match_length);\n\n      /** * _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ** */\n      bflush = _tr_tally$1(s, 1, s.match_length - MIN_MATCH$1)\n      s.lookahead -= s.match_length\n      s.strstart += s.match_length\n      s.match_length = 0\n    } else {\n      /* No match, output a literal byte */\n      // Tracevv((stderr,\"%c\", s->window[s->strstart]));\n\n      /** * _tr_tally_lit(s, s.window[s.strstart], bflush); ** */\n      bflush = _tr_tally$1(s, 0, s.window[s.strstart])\n      s.lookahead--\n      s.strstart++\n    }\n\n    if (bflush) {\n      /** * FLUSH_BLOCK(s, 0); ** */\n      flush_block_only(s, false)\n\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE\n      }\n      /***/\n    }\n  }\n\n  s.insert = 0\n\n  if (flush === Z_FINISH) {\n    /** * FLUSH_BLOCK(s, 1); ** */\n    flush_block_only(s, true)\n\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED\n    }\n    /***/\n\n    return BS_FINISH_DONE\n  }\n\n  if (s.last_lit) {\n    /** * FLUSH_BLOCK(s, 0); ** */\n    flush_block_only(s, false)\n\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE\n    }\n    /***/\n  }\n\n  return BS_BLOCK_DONE\n}\n/* ===========================================================================\n * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.\n * (It will be regenerated if this run of deflate switches away from Huffman.)\n */\n\nvar deflate_huff = function deflate_huff(s, flush) {\n  var bflush\n  /* set if current block must be flushed */\n\n  for (;;) {\n    /* Make sure that we have a literal to write. */\n    if (s.lookahead === 0) {\n      fill_window(s)\n\n      if (s.lookahead === 0) {\n        if (flush === Z_NO_FLUSH) {\n          return BS_NEED_MORE\n        }\n\n        break\n        /* flush the current block */\n      }\n    }\n    /* Output a literal byte */\n\n    s.match_length = 0 // Tracevv((stderr,\"%c\", s->window[s->strstart]));\n\n    /** * _tr_tally_lit(s, s.window[s.strstart], bflush); ** */\n\n    bflush = _tr_tally$1(s, 0, s.window[s.strstart])\n    s.lookahead--\n    s.strstart++\n\n    if (bflush) {\n      /** * FLUSH_BLOCK(s, 0); ** */\n      flush_block_only(s, false)\n\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE\n      }\n      /***/\n    }\n  }\n\n  s.insert = 0\n\n  if (flush === Z_FINISH) {\n    /** * FLUSH_BLOCK(s, 1); ** */\n    flush_block_only(s, true)\n\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED\n    }\n    /***/\n\n    return BS_FINISH_DONE\n  }\n\n  if (s.last_lit) {\n    /** * FLUSH_BLOCK(s, 0); ** */\n    flush_block_only(s, false)\n\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE\n    }\n    /***/\n  }\n\n  return BS_BLOCK_DONE\n}\n/* Values for max_lazy_match, good_match and max_chain_length, depending on\n * the desired pack level (0..9). The values given below have been tuned to\n * exclude worst case performance for pathological files. Better values may be\n * found for specific files.\n */\n\nfunction Config(good_length, max_lazy, nice_length, max_chain, func) {\n  this.good_length = good_length\n  this.max_lazy = max_lazy\n  this.nice_length = nice_length\n  this.max_chain = max_chain\n  this.func = func\n}\n\nvar configuration_table = [\n  /*      good lazy nice chain */\n  new Config(0, 0, 0, 0, deflate_stored),\n  /* 0 store only */\n  new Config(4, 4, 8, 4, deflate_fast),\n  /* 1 max speed, no lazy matches */\n  new Config(4, 5, 16, 8, deflate_fast),\n  /* 2 */\n  new Config(4, 6, 32, 32, deflate_fast),\n  /* 3 */\n  new Config(4, 4, 16, 16, deflate_slow),\n  /* 4 lazy matches */\n  new Config(8, 16, 32, 32, deflate_slow),\n  /* 5 */\n  new Config(8, 16, 128, 128, deflate_slow),\n  /* 6 */\n  new Config(8, 32, 128, 256, deflate_slow),\n  /* 7 */\n  new Config(32, 128, 258, 1024, deflate_slow),\n  /* 8 */\n  new Config(32, 258, 258, 4096, deflate_slow),\n  /* 9 max compression */\n]\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new zlib stream\n */\n\nvar lm_init = function lm_init(s) {\n  s.window_size = 2 * s.w_size\n  /** * CLEAR_HASH(s); ** */\n\n  zero$1(s.head) // Fill with NIL (= 0);\n\n  /* Set the default configuration parameters:\n   */\n\n  s.max_lazy_match = configuration_table[s.level].max_lazy\n  s.good_match = configuration_table[s.level].good_length\n  s.nice_match = configuration_table[s.level].nice_length\n  s.max_chain_length = configuration_table[s.level].max_chain\n  s.strstart = 0\n  s.block_start = 0\n  s.lookahead = 0\n  s.insert = 0\n  s.match_length = s.prev_length = MIN_MATCH$1 - 1\n  s.match_available = 0\n  s.ins_h = 0\n}\n\nfunction DeflateState() {\n  this.strm = null\n  /* pointer back to this zlib stream */\n\n  this.status = 0\n  /* as the name implies */\n\n  this.pending_buf = null\n  /* output still pending */\n\n  this.pending_buf_size = 0\n  /* size of pending_buf */\n\n  this.pending_out = 0\n  /* next pending byte to output to the stream */\n\n  this.pending = 0\n  /* nb of bytes in the pending buffer */\n\n  this.wrap = 0\n  /* bit 0 true for zlib, bit 1 true for gzip */\n\n  this.gzhead = null\n  /* gzip header information to write */\n\n  this.gzindex = 0\n  /* where in extra, name, or comment */\n\n  this.method = Z_DEFLATED\n  /* can only be DEFLATED */\n\n  this.last_flush = -1\n  /* value of flush param for previous deflate call */\n\n  this.w_size = 0\n  /* LZ77 window size (32K by default) */\n\n  this.w_bits = 0\n  /* log2(w_size)  (8..16) */\n\n  this.w_mask = 0\n  /* w_size - 1 */\n\n  this.window = null\n  /* Sliding window. Input bytes are read into the second half of the window,\n   * and move to the first half later to keep a dictionary of at least wSize\n   * bytes. With this organization, matches are limited to a distance of\n   * wSize-MAX_MATCH bytes, but this ensures that IO is always\n   * performed with a length multiple of the block size.\n   */\n\n  this.window_size = 0\n  /* Actual size of window: 2*wSize, except when the user input buffer\n   * is directly used as sliding window.\n   */\n\n  this.prev = null\n  /* Link to older string with same hash index. To limit the size of this\n   * array to 64K, this link is maintained only for the last 32K strings.\n   * An index in this array is thus a window index modulo 32K.\n   */\n\n  this.head = null\n  /* Heads of the hash chains or NIL. */\n\n  this.ins_h = 0\n  /* hash index of string to be inserted */\n\n  this.hash_size = 0\n  /* number of elements in hash table */\n\n  this.hash_bits = 0\n  /* log2(hash_size) */\n\n  this.hash_mask = 0\n  /* hash_size-1 */\n\n  this.hash_shift = 0\n  /* Number of bits by which ins_h must be shifted at each input\n   * step. It must be such that after MIN_MATCH steps, the oldest\n   * byte no longer takes part in the hash key, that is:\n   *   hash_shift * MIN_MATCH >= hash_bits\n   */\n\n  this.block_start = 0\n  /* Window position at the beginning of the current output block. Gets\n   * negative when the window is moved backwards.\n   */\n\n  this.match_length = 0\n  /* length of best match */\n\n  this.prev_match = 0\n  /* previous match */\n\n  this.match_available = 0\n  /* set if previous match exists */\n\n  this.strstart = 0\n  /* start of string to insert */\n\n  this.match_start = 0\n  /* start of matching string */\n\n  this.lookahead = 0\n  /* number of valid bytes ahead in window */\n\n  this.prev_length = 0\n  /* Length of the best match at previous step. Matches not greater than this\n   * are discarded. This is used in the lazy match evaluation.\n   */\n\n  this.max_chain_length = 0\n  /* To speed up deflation, hash chains are never searched beyond this\n   * length.  A higher limit improves compression ratio but degrades the\n   * speed.\n   */\n\n  this.max_lazy_match = 0\n  /* Attempt to find a better match only when the current match is strictly\n   * smaller than this value. This mechanism is used only for compression\n   * levels >= 4.\n   */\n  // That's alias to max_lazy_match, don't use directly\n  // this.max_insert_length = 0;\n\n  /* Insert new strings in the hash table only if the match length is not\n   * greater than this length. This saves time but degrades compression.\n   * max_insert_length is used only for compression levels <= 3.\n   */\n\n  this.level = 0\n  /* compression level (1..9) */\n\n  this.strategy = 0\n  /* favor or force Huffman coding */\n\n  this.good_match = 0\n  /* Use a faster search when the previous match is longer than this */\n\n  this.nice_match = 0\n  /* Stop searching when current match exceeds this */\n\n  /* used by trees.c: */\n\n  /* Didn't use ct_data typedef below to suppress compiler warning */\n  // struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */\n  // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */\n  // struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */\n  // Use flat array of DOUBLE size, with interleaved fata,\n  // because JS does not support effective\n\n  this.dyn_ltree = new Uint16Array(HEAP_SIZE$1 * 2)\n  this.dyn_dtree = new Uint16Array((2 * D_CODES$1 + 1) * 2)\n  this.bl_tree = new Uint16Array((2 * BL_CODES$1 + 1) * 2)\n  zero$1(this.dyn_ltree)\n  zero$1(this.dyn_dtree)\n  zero$1(this.bl_tree)\n  this.l_desc = null\n  /* desc. for literal tree */\n\n  this.d_desc = null\n  /* desc. for distance tree */\n\n  this.bl_desc = null\n  /* desc. for bit length tree */\n  // ush bl_count[MAX_BITS+1];\n\n  this.bl_count = new Uint16Array(MAX_BITS$1 + 1)\n  /* number of codes at each bit length for an optimal tree */\n  // int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */\n\n  this.heap = new Uint16Array(2 * L_CODES$1 + 1)\n  /* heap used to build the Huffman trees */\n\n  zero$1(this.heap)\n  this.heap_len = 0\n  /* number of elements in the heap */\n\n  this.heap_max = 0\n  /* element of largest frequency */\n\n  /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n   * The same heap array is used to build all trees.\n   */\n\n  this.depth = new Uint16Array(2 * L_CODES$1 + 1) // uch depth[2*L_CODES+1];\n\n  zero$1(this.depth)\n  /* Depth of each subtree used as tie breaker for trees of equal frequency\n   */\n\n  this.l_buf = 0\n  /* buffer index for literals or lengths */\n\n  this.lit_bufsize = 0\n  /* Size of match buffer for literals/lengths.  There are 4 reasons for\n   * limiting lit_bufsize to 64K:\n   *   - frequencies can be kept in 16 bit counters\n   *   - if compression is not successful for the first block, all input\n   *     data is still in the window so we can still emit a stored block even\n   *     when input comes from standard input.  (This can also be done for\n   *     all blocks if lit_bufsize is not greater than 32K.)\n   *   - if compression is not successful for a file smaller than 64K, we can\n   *     even emit a stored file instead of a stored block (saving 5 bytes).\n   *     This is applicable only for zip (not gzip or zlib).\n   *   - creating new Huffman trees less frequently may not provide fast\n   *     adaptation to changes in the input data statistics. (Take for\n   *     example a binary file with poorly compressible code followed by\n   *     a highly compressible string table.) Smaller buffer sizes give\n   *     fast adaptation but have of course the overhead of transmitting\n   *     trees more frequently.\n   *   - I can't count above 4\n   */\n\n  this.last_lit = 0\n  /* running index in l_buf */\n\n  this.d_buf = 0\n  /* Buffer index for distances. To simplify the code, d_buf and l_buf have\n   * the same number of elements. To use different lengths, an extra flag\n   * array would be necessary.\n   */\n\n  this.opt_len = 0\n  /* bit length of current block with optimal trees */\n\n  this.static_len = 0\n  /* bit length of current block with static trees */\n\n  this.matches = 0\n  /* number of string matches in current block */\n\n  this.insert = 0\n  /* bytes at end of window left to insert */\n\n  this.bi_buf = 0\n  /* Output buffer. bits are inserted starting at the bottom (least\n   * significant bits).\n   */\n\n  this.bi_valid = 0\n  /* Number of valid bits in bi_buf.  All bits above the last valid bit\n   * are always zero.\n   */\n  // Used for window memory init. We safely ignore it for JS. That makes\n  // sense only for pointers and memory check tools.\n  // this.high_water = 0;\n\n  /* High water mark offset in window for initialized bytes -- bytes above\n   * this are set to zero in order to avoid memory check warnings when\n   * longest match routines access bytes past the input.  This is then\n   * updated to the new high water mark.\n   */\n}\n\nvar deflateResetKeep = function deflateResetKeep(strm) {\n  if (!strm || !strm.state) {\n    return err(strm, Z_STREAM_ERROR)\n  }\n\n  strm.total_in = strm.total_out = 0\n  strm.data_type = Z_UNKNOWN$1\n  var s = strm.state\n  s.pending = 0\n  s.pending_out = 0\n\n  if (s.wrap < 0) {\n    s.wrap = -s.wrap\n    /* was made negative by deflate(..., Z_FINISH); */\n  }\n\n  s.status = s.wrap ? INIT_STATE : BUSY_STATE\n  strm.adler =\n    s.wrap === 2\n      ? 0 // crc32(0, Z_NULL, 0)\n      : 1 // adler32(0, Z_NULL, 0)\n\n  s.last_flush = Z_NO_FLUSH\n\n  _tr_init$1(s)\n\n  return Z_OK\n}\n\nvar deflateReset = function deflateReset(strm) {\n  var ret = deflateResetKeep(strm)\n\n  if (ret === Z_OK) {\n    lm_init(strm.state)\n  }\n\n  return ret\n}\n\nvar deflateSetHeader = function deflateSetHeader(strm, head) {\n  if (!strm || !strm.state) {\n    return Z_STREAM_ERROR\n  }\n\n  if (strm.state.wrap !== 2) {\n    return Z_STREAM_ERROR\n  }\n\n  strm.state.gzhead = head\n  return Z_OK\n}\n\nvar deflateInit2 = function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {\n  if (!strm) {\n    // === Z_NULL\n    return Z_STREAM_ERROR\n  }\n\n  var wrap = 1\n\n  if (level === Z_DEFAULT_COMPRESSION) {\n    level = 6\n  }\n\n  if (windowBits < 0) {\n    /* suppress zlib wrapper */\n    wrap = 0\n    windowBits = -windowBits\n  } else if (windowBits > 15) {\n    wrap = 2\n    /* write gzip wrapper instead */\n\n    windowBits -= 16\n  }\n\n  if (\n    memLevel < 1 ||\n    memLevel > MAX_MEM_LEVEL ||\n    method !== Z_DEFLATED ||\n    windowBits < 8 ||\n    windowBits > 15 ||\n    level < 0 ||\n    level > 9 ||\n    strategy < 0 ||\n    strategy > Z_FIXED$1\n  ) {\n    return err(strm, Z_STREAM_ERROR)\n  }\n\n  if (windowBits === 8) {\n    windowBits = 9\n  }\n  /* until 256-byte window bug fixed */\n\n  var s = new DeflateState()\n  strm.state = s\n  s.strm = strm\n  s.wrap = wrap\n  s.gzhead = null\n  s.w_bits = windowBits\n  s.w_size = 1 << s.w_bits\n  s.w_mask = s.w_size - 1\n  s.hash_bits = memLevel + 7\n  s.hash_size = 1 << s.hash_bits\n  s.hash_mask = s.hash_size - 1\n  s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1)\n  s.window = new Uint8Array(s.w_size * 2)\n  s.head = new Uint16Array(s.hash_size)\n  s.prev = new Uint16Array(s.w_size) // Don't need mem init magic for JS.\n  // s.high_water = 0;  /* nothing written to s->window yet */\n\n  s.lit_bufsize = 1 << (memLevel + 6)\n  /* 16K elements by default */\n\n  s.pending_buf_size = s.lit_bufsize * 4\n  // overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);\n  // s->pending_buf = (uchf *) overlay;\n\n  // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)\n  s.pending_buf = new Uint8Array(s.pending_buf_size)\n  // s->d_buf = overlay + s->lit_bufsize/sizeof(ush);\n\n  s.d_buf = 1 * s.lit_bufsize // s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;\n\n  s.l_buf = (1 + 2) * s.lit_bufsize\n  s.level = level\n  s.strategy = strategy\n  s.method = method\n  return deflateReset(strm)\n}\n\nvar deflateInit = function deflateInit(strm, level) {\n  return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY)\n}\n\nvar deflate = function deflate(strm, flush) {\n  var beg\n  var val // for gzip header write only\n\n  if (!strm || !strm.state || flush > Z_BLOCK || flush < 0) {\n    return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR\n  }\n\n  var s = strm.state\n\n  if (!strm.output || (!strm.input && strm.avail_in !== 0) || (s.status === FINISH_STATE && flush !== Z_FINISH)) {\n    return err(strm, strm.avail_out === 0 ? Z_BUF_ERROR : Z_STREAM_ERROR)\n  }\n\n  s.strm = strm\n  /* just in case */\n\n  var old_flush = s.last_flush\n  s.last_flush = flush\n  /* Write the header */\n\n  if (s.status === INIT_STATE) {\n    if (s.wrap === 2) {\n      // GZIP header\n      strm.adler = 0 // crc32(0L, Z_NULL, 0);\n\n      put_byte(s, 31)\n      put_byte(s, 139)\n      put_byte(s, 8)\n\n      if (!s.gzhead) {\n        // s->gzhead == Z_NULL\n        put_byte(s, 0)\n        put_byte(s, 0)\n        put_byte(s, 0)\n        put_byte(s, 0)\n        put_byte(s, 0)\n        put_byte(s, s.level === 9 ? 2 : s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? 4 : 0)\n        put_byte(s, OS_CODE)\n        s.status = BUSY_STATE\n      } else {\n        put_byte(\n          s,\n          (s.gzhead.text ? 1 : 0) +\n            (s.gzhead.hcrc ? 2 : 0) +\n            (!s.gzhead.extra ? 0 : 4) +\n            (!s.gzhead.name ? 0 : 8) +\n            (!s.gzhead.comment ? 0 : 16)\n        )\n        put_byte(s, s.gzhead.time & 0xff)\n        put_byte(s, (s.gzhead.time >> 8) & 0xff)\n        put_byte(s, (s.gzhead.time >> 16) & 0xff)\n        put_byte(s, (s.gzhead.time >> 24) & 0xff)\n        put_byte(s, s.level === 9 ? 2 : s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? 4 : 0)\n        put_byte(s, s.gzhead.os & 0xff)\n\n        if (s.gzhead.extra && s.gzhead.extra.length) {\n          put_byte(s, s.gzhead.extra.length & 0xff)\n          put_byte(s, (s.gzhead.extra.length >> 8) & 0xff)\n        }\n\n        if (s.gzhead.hcrc) {\n          strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0)\n        }\n\n        s.gzindex = 0\n        s.status = EXTRA_STATE\n      }\n    } // DEFLATE header\n    else {\n      var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8\n      var level_flags = -1\n\n      if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {\n        level_flags = 0\n      } else if (s.level < 6) {\n        level_flags = 1\n      } else if (s.level === 6) {\n        level_flags = 2\n      } else {\n        level_flags = 3\n      }\n\n      header |= level_flags << 6\n\n      if (s.strstart !== 0) {\n        header |= PRESET_DICT\n      }\n\n      header += 31 - (header % 31)\n      s.status = BUSY_STATE\n      putShortMSB(s, header)\n      /* Save the adler32 of the preset dictionary: */\n\n      if (s.strstart !== 0) {\n        putShortMSB(s, strm.adler >>> 16)\n        putShortMSB(s, strm.adler & 0xffff)\n      }\n\n      strm.adler = 1 // adler32(0L, Z_NULL, 0);\n    }\n  } // #ifdef GZIP\n\n  if (s.status === EXTRA_STATE) {\n    if (\n      s.gzhead.extra\n      /* != Z_NULL */\n    ) {\n      beg = s.pending\n      /* start of bytes to update crc */\n\n      while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {\n        if (s.pending === s.pending_buf_size) {\n          if (s.gzhead.hcrc && s.pending > beg) {\n            strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg)\n          }\n\n          flush_pending(strm)\n          beg = s.pending\n\n          if (s.pending === s.pending_buf_size) {\n            break\n          }\n        }\n\n        put_byte(s, s.gzhead.extra[s.gzindex] & 0xff)\n        s.gzindex++\n      }\n\n      if (s.gzhead.hcrc && s.pending > beg) {\n        strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg)\n      }\n\n      if (s.gzindex === s.gzhead.extra.length) {\n        s.gzindex = 0\n        s.status = NAME_STATE\n      }\n    } else {\n      s.status = NAME_STATE\n    }\n  }\n\n  if (s.status === NAME_STATE) {\n    if (\n      s.gzhead.name\n      /* != Z_NULL */\n    ) {\n      beg = s.pending\n      /* start of bytes to update crc */\n      // int val;\n\n      do {\n        if (s.pending === s.pending_buf_size) {\n          if (s.gzhead.hcrc && s.pending > beg) {\n            strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg)\n          }\n\n          flush_pending(strm)\n          beg = s.pending\n\n          if (s.pending === s.pending_buf_size) {\n            val = 1\n            break\n          }\n        } // JS specific: little magic to add zero terminator to end of string\n\n        if (s.gzindex < s.gzhead.name.length) {\n          val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff\n        } else {\n          val = 0\n        }\n\n        put_byte(s, val)\n      } while (val !== 0)\n\n      if (s.gzhead.hcrc && s.pending > beg) {\n        strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg)\n      }\n\n      if (val === 0) {\n        s.gzindex = 0\n        s.status = COMMENT_STATE\n      }\n    } else {\n      s.status = COMMENT_STATE\n    }\n  }\n\n  if (s.status === COMMENT_STATE) {\n    if (\n      s.gzhead.comment\n      /* != Z_NULL */\n    ) {\n      beg = s.pending\n      /* start of bytes to update crc */\n      // int val;\n\n      do {\n        if (s.pending === s.pending_buf_size) {\n          if (s.gzhead.hcrc && s.pending > beg) {\n            strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg)\n          }\n\n          flush_pending(strm)\n          beg = s.pending\n\n          if (s.pending === s.pending_buf_size) {\n            val = 1\n            break\n          }\n        } // JS specific: little magic to add zero terminator to end of string\n\n        if (s.gzindex < s.gzhead.comment.length) {\n          val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff\n        } else {\n          val = 0\n        }\n\n        put_byte(s, val)\n      } while (val !== 0)\n\n      if (s.gzhead.hcrc && s.pending > beg) {\n        strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg)\n      }\n\n      if (val === 0) {\n        s.status = HCRC_STATE\n      }\n    } else {\n      s.status = HCRC_STATE\n    }\n  }\n\n  if (s.status === HCRC_STATE) {\n    if (s.gzhead.hcrc) {\n      if (s.pending + 2 > s.pending_buf_size) {\n        flush_pending(strm)\n      }\n\n      if (s.pending + 2 <= s.pending_buf_size) {\n        put_byte(s, strm.adler & 0xff)\n        put_byte(s, (strm.adler >> 8) & 0xff)\n        strm.adler = 0 // crc32(0L, Z_NULL, 0);\n\n        s.status = BUSY_STATE\n      }\n    } else {\n      s.status = BUSY_STATE\n    }\n  } // #endif\n\n  /* Flush as much pending output as possible */\n\n  if (s.pending !== 0) {\n    flush_pending(strm)\n\n    if (strm.avail_out === 0) {\n      /* Since avail_out is 0, deflate will be called again with\n       * more output space, but possibly with both pending and\n       * avail_in equal to zero. There won't be anything to do,\n       * but this is not an error situation so make sure we\n       * return OK instead of BUF_ERROR at next call of deflate:\n       */\n      s.last_flush = -1\n      return Z_OK\n    }\n    /* Make sure there is something to do and avoid duplicate consecutive\n     * flushes. For repeated and useless calls with Z_FINISH, we keep\n     * returning Z_STREAM_END instead of Z_BUF_ERROR.\n     */\n  } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && flush !== Z_FINISH) {\n    return err(strm, Z_BUF_ERROR)\n  }\n  /* User must not provide more input after the first FINISH: */\n\n  if (s.status === FINISH_STATE && strm.avail_in !== 0) {\n    return err(strm, Z_BUF_ERROR)\n  }\n  /* Start a new block or continue the current one.\n   */\n\n  if (strm.avail_in !== 0 || s.lookahead !== 0 || (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {\n    var bstate =\n      s.strategy === Z_HUFFMAN_ONLY\n        ? deflate_huff(s, flush)\n        : s.strategy === Z_RLE\n          ? deflate_rle(s, flush)\n          : configuration_table[s.level].func(s, flush)\n\n    if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {\n      s.status = FINISH_STATE\n    }\n\n    if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {\n      if (strm.avail_out === 0) {\n        s.last_flush = -1\n        /* avoid BUF_ERROR next call, see above */\n      }\n\n      return Z_OK\n      /* If flush != Z_NO_FLUSH && avail_out == 0, the next call\n       * of deflate should use the same flush parameter to make sure\n       * that the flush is complete. So we don't have to output an\n       * empty block here, this will be done at next call. This also\n       * ensures that for a very small output buffer, we emit at most\n       * one empty block.\n       */\n    }\n\n    if (bstate === BS_BLOCK_DONE) {\n      if (flush === Z_PARTIAL_FLUSH) {\n        _tr_align$1(s)\n      } else if (flush !== Z_BLOCK) {\n        /* FULL_FLUSH or SYNC_FLUSH */\n        _tr_stored_block$1(s, 0, 0, false)\n        /* For a full flush, this empty block will be recognized\n         * as a special marker by inflate_sync().\n         */\n\n        if (flush === Z_FULL_FLUSH) {\n          /** * CLEAR_HASH(s); ** */\n\n          /* forget history */\n          zero$1(s.head) // Fill with NIL (= 0);\n\n          if (s.lookahead === 0) {\n            s.strstart = 0\n            s.block_start = 0\n            s.insert = 0\n          }\n        }\n      }\n\n      flush_pending(strm)\n\n      if (strm.avail_out === 0) {\n        s.last_flush = -1\n        /* avoid BUF_ERROR at next call, see above */\n\n        return Z_OK\n      }\n    }\n  } // Assert(strm->avail_out > 0, \"bug2\");\n  // if (strm.avail_out <= 0) { throw new Error(\"bug2\");}\n\n  if (flush !== Z_FINISH) {\n    return Z_OK\n  }\n\n  if (s.wrap <= 0) {\n    return Z_STREAM_END\n  }\n  /* Write the trailer */\n\n  if (s.wrap === 2) {\n    put_byte(s, strm.adler & 0xff)\n    put_byte(s, (strm.adler >> 8) & 0xff)\n    put_byte(s, (strm.adler >> 16) & 0xff)\n    put_byte(s, (strm.adler >> 24) & 0xff)\n    put_byte(s, strm.total_in & 0xff)\n    put_byte(s, (strm.total_in >> 8) & 0xff)\n    put_byte(s, (strm.total_in >> 16) & 0xff)\n    put_byte(s, (strm.total_in >> 24) & 0xff)\n  } else {\n    putShortMSB(s, strm.adler >>> 16)\n    putShortMSB(s, strm.adler & 0xffff)\n  }\n\n  flush_pending(strm)\n  /* If avail_out is zero, the application will call deflate again\n   * to flush the rest.\n   */\n\n  if (s.wrap > 0) {\n    s.wrap = -s.wrap\n  }\n  /* write the trailer only once! */\n\n  return s.pending !== 0 ? Z_OK : Z_STREAM_END\n}\n\nvar deflateEnd = function deflateEnd(strm) {\n  if (\n    !strm ||\n    /* == Z_NULL */\n    !strm.state\n    /* == Z_NULL */\n  ) {\n    return Z_STREAM_ERROR\n  }\n\n  var status = strm.state.status\n\n  if (\n    status !== INIT_STATE &&\n    status !== EXTRA_STATE &&\n    status !== NAME_STATE &&\n    status !== COMMENT_STATE &&\n    status !== HCRC_STATE &&\n    status !== BUSY_STATE &&\n    status !== FINISH_STATE\n  ) {\n    return err(strm, Z_STREAM_ERROR)\n  }\n\n  strm.state = null\n  return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK\n}\n/* =========================================================================\n * Initializes the compression dictionary from the given byte\n * sequence without producing any compressed output.\n */\n\nvar deflateSetDictionary = function deflateSetDictionary(strm, dictionary) {\n  var dictLength = dictionary.length\n\n  if (\n    !strm ||\n    /* == Z_NULL */\n    !strm.state\n    /* == Z_NULL */\n  ) {\n    return Z_STREAM_ERROR\n  }\n\n  var s = strm.state\n  var wrap = s.wrap\n\n  if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {\n    return Z_STREAM_ERROR\n  }\n  /* when using zlib wrappers, compute Adler-32 for provided dictionary */\n\n  if (wrap === 1) {\n    /* adler32(strm->adler, dictionary, dictLength); */\n    strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0)\n  }\n\n  s.wrap = 0\n  /* avoid computing Adler-32 in read_buf */\n\n  /* if dictionary would fill window, just replace the history */\n\n  if (dictLength >= s.w_size) {\n    if (wrap === 0) {\n      /* already empty otherwise */\n\n      /** * CLEAR_HASH(s); ** */\n      zero$1(s.head) // Fill with NIL (= 0);\n\n      s.strstart = 0\n      s.block_start = 0\n      s.insert = 0\n    }\n    /* use the tail */\n    // dictionary = dictionary.slice(dictLength - s.w_size);\n\n    var tmpDict = new Uint8Array(s.w_size)\n    tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0)\n    dictionary = tmpDict\n    dictLength = s.w_size\n  }\n  /* insert dictionary into window and hash */\n\n  var avail = strm.avail_in\n  var next = strm.next_in\n  var input = strm.input\n  strm.avail_in = dictLength\n  strm.next_in = 0\n  strm.input = dictionary\n  fill_window(s)\n\n  while (s.lookahead >= MIN_MATCH$1) {\n    var str = s.strstart\n    var n = s.lookahead - (MIN_MATCH$1 - 1)\n\n    do {\n      /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n      s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH$1 - 1])\n      s.prev[str & s.w_mask] = s.head[s.ins_h]\n      s.head[s.ins_h] = str\n      str++\n    } while (--n)\n\n    s.strstart = str\n    s.lookahead = MIN_MATCH$1 - 1\n    fill_window(s)\n  }\n\n  s.strstart += s.lookahead\n  s.block_start = s.strstart\n  s.insert = s.lookahead\n  s.lookahead = 0\n  s.match_length = s.prev_length = MIN_MATCH$1 - 1\n  s.match_available = 0\n  strm.next_in = next\n  strm.input = input\n  strm.avail_in = avail\n  s.wrap = wrap\n  return Z_OK\n}\n\nvar deflateInit_1 = deflateInit\nvar deflateInit2_1 = deflateInit2\nvar deflateReset_1 = deflateReset\nvar deflateResetKeep_1 = deflateResetKeep\nvar deflateSetHeader_1 = deflateSetHeader\nvar deflate_2 = deflate\nvar deflateEnd_1 = deflateEnd\nvar deflateSetDictionary_1 = deflateSetDictionary\nvar deflateInfo = 'pako deflate (from Nodeca project)'\n/* Not implemented\n  module.exports.deflateBound = deflateBound;\n  module.exports.deflateCopy = deflateCopy;\n  module.exports.deflateParams = deflateParams;\n  module.exports.deflatePending = deflatePending;\n  module.exports.deflatePrime = deflatePrime;\n  module.exports.deflateTune = deflateTune;\n  */\n\nvar deflate_1 = {\n  deflateInit: deflateInit_1,\n  deflateInit2: deflateInit2_1,\n  deflateReset: deflateReset_1,\n  deflateResetKeep: deflateResetKeep_1,\n  deflateSetHeader: deflateSetHeader_1,\n  deflate: deflate_2,\n  deflateEnd: deflateEnd_1,\n  deflateSetDictionary: deflateSetDictionary_1,\n  deflateInfo,\n}\n\n// Join array of chunks to single array.\nfunction flattenChunks(chunks) {\n  // calculate data length\n  var len = 0\n\n  for (var i = 0, l = chunks.length; i < l; i++) {\n    len += chunks[i].length\n  } // join chunks\n\n  var result = new Uint8Array(len)\n\n  for (var _i = 0, pos = 0, _l = chunks.length; _i < _l; _i++) {\n    var chunk = chunks[_i]\n    result.set(chunk, pos)\n    pos += chunk.length\n  }\n\n  return result\n}\n\n// String encode/decode helpers\n//\n// - apply(Array) can fail on Android 2.2\n// - apply(Uint8Array) can fail on iOS 5.1 Safari\n//\n\n// Table with utf8 lengths (calculated by first byte of sequence)\n// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,\n// because max possible codepoint is 0x10ffff\n\nvar _utf8len = new Uint8Array(256)\n\nfor (var q = 0; q < 256; q++) {\n  _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1\n}\n\n_utf8len[254] = _utf8len[254] = 1 // Invalid sequence start\n// convert string to array (typed, when possible)\n\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction ZStream() {\n  /* next input byte */\n  this.input = null // JS specific, because we have no pointers\n\n  this.next_in = 0\n  /* number of bytes available at input */\n\n  this.avail_in = 0\n  /* total number of input bytes read so far */\n\n  this.total_in = 0\n  /* next output byte should be put there */\n\n  this.output = null // JS specific, because we have no pointers\n\n  this.next_out = 0\n  /* remaining free space at output */\n\n  this.avail_out = 0\n  /* total number of bytes output so far */\n\n  this.total_out = 0\n  /* last error message, NULL if no error */\n\n  this.msg = ''\n  /* Z_NULL */\n  /* not visible by applications */\n\n  this.state = null\n  /* best guess about the data type: binary or text */\n\n  this.data_type = 2\n  /* Z_UNKNOWN */\n  /* adler32 value of the uncompressed data */\n\n  this.adler = 0\n}\n\nvar zstream = ZStream\n\n// eslint-disable-next-line @typescript-eslint/unbound-method\nvar toString = Object.prototype.toString\n/* Public constants ========================================================== */\n\n/* =========================================================================== */\n\nvar Z_NO_FLUSH$1 = constants.Z_NO_FLUSH\nvar Z_SYNC_FLUSH = constants.Z_SYNC_FLUSH\nvar Z_FULL_FLUSH$1 = constants.Z_FULL_FLUSH\nvar Z_FINISH$1 = constants.Z_FINISH\nvar Z_OK$1 = constants.Z_OK\nvar Z_STREAM_END$1 = constants.Z_STREAM_END\nvar Z_DEFAULT_COMPRESSION$1 = constants.Z_DEFAULT_COMPRESSION\nvar Z_DEFAULT_STRATEGY$1 = constants.Z_DEFAULT_STRATEGY\nvar Z_DEFLATED$1 = constants.Z_DEFLATED\n/* =========================================================================== */\n\n/**\n * class Deflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[deflate]],\n * [[deflateRaw]] and [[gzip]].\n * */\n\n/* internal\n * Deflate.chunks -> Array\n *\n * Chunks of output data, if [[Deflate#onData]] not overridden.\n * */\n\n/**\n * Deflate.result -> Uint8Array\n *\n * Compressed result, generated by default [[Deflate#onData]]\n * and [[Deflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Deflate#push]] with `Z_FINISH` / `true` param).\n * */\n\n/**\n * Deflate.err -> Number\n *\n * Error code after deflate finished. 0 (Z_OK) on success.\n * You will not need it in real life, because deflate errors\n * are possible only on wrong options or bad `onData` / `onEnd`\n * custom handlers.\n * */\n\n/**\n * Deflate.msg -> String\n *\n * Error message, if [[Deflate.err]] != 0\n * */\n\n/**\n * new Deflate(options)\n * - options (Object): zlib deflate options.\n *\n * Creates new deflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `level`\n * - `windowBits`\n * - `memLevel`\n * - `strategy`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * * `chunkSize` - size of generated data chunks (16K by default)\n * * `raw` (Boolean) - do raw deflate\n * * `gzip` (Boolean) - create gzip wrapper\n * * `header` (Object) - custom header for gzip\n * ** `text` (Boolean) - true if compressed data believed to be text\n * ** `time` (Number) - modification time, unix timestamp\n * ** `os` (Number) - operation system code\n * ** `extra` (Array) - array of bytes with extra data (max 65536)\n * ** `name` (String) - file name (binary string)\n * ** `comment` (String) - comment (binary string)\n * ** `hcrc` (Boolean) - true if header crc should be added\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n *   , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])\n *   , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * const deflate = new pako.Deflate({ level: 3});\n *\n * deflate.push(chunk1, false);\n * deflate.push(chunk2, true);  // true -> last chunk\n *\n * if (deflate.err) { throw new Error(deflate.err); }\n *\n * console.log(deflate.result);\n * ```\n * */\n\nexport function Deflate() {\n  this.options = {\n    level: Z_DEFAULT_COMPRESSION$1,\n    method: Z_DEFLATED$1,\n    chunkSize: 16384,\n    windowBits: 15,\n    memLevel: 8,\n    strategy: Z_DEFAULT_STRATEGY$1,\n  }\n  var opt = this.options\n\n  if (opt.raw && opt.windowBits > 0) {\n    opt.windowBits = -opt.windowBits\n  } else if (opt.gzip && opt.windowBits > 0 && opt.windowBits < 16) {\n    opt.windowBits += 16\n  }\n\n  this.err = 0 // error code, if happens (0 = Z_OK)\n\n  this.msg = '' // error message\n\n  this.ended = false // used to avoid multiple onEnd() calls\n\n  this.chunks = [] // chunks of compressed data\n\n  this.strm = new zstream()\n  this.strm.avail_out = 0\n  var status = deflate_1.deflateInit2(this.strm, opt.level, opt.method, opt.windowBits, opt.memLevel, opt.strategy)\n\n  if (status !== Z_OK$1) {\n    throw new Error(messages[status])\n  }\n\n  if (opt.header) {\n    deflate_1.deflateSetHeader(this.strm, opt.header)\n  }\n\n  if (opt.dictionary) {\n    var dict // Convert data if needed\n\n    if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {\n      dict = new Uint8Array(opt.dictionary)\n    } else {\n      dict = opt.dictionary\n    }\n\n    status = deflate_1.deflateSetDictionary(this.strm, dict)\n\n    if (status !== Z_OK$1) {\n      throw new Error(messages[status])\n    }\n\n    this._dict_set = true\n  }\n}\n/**\n * Deflate#push(data[, flush_mode]) -> Boolean\n * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be\n * converted to utf8 byte sequence.\n * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.\n * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.\n *\n * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with\n * new compressed chunks. Returns `true` on success. The last data block must\n * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending\n * buffers and call [[Deflate#onEnd]].\n *\n * On fail call [[Deflate#onEnd]] with error code and return false.\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true);  // push last chunk\n * ```\n * */\n\nDeflate.prototype.push = function (data, flush_mode) {\n  var strm = this.strm\n  var chunkSize = this.options.chunkSize\n\n  var status\n  var _flush_mode\n\n  if (this.ended) {\n    return false\n  }\n\n  if (flush_mode === ~~flush_mode) {\n    _flush_mode = flush_mode\n  } else {\n    _flush_mode = flush_mode === true ? Z_FINISH$1 : Z_NO_FLUSH$1\n  } // Convert data if needed\n\n  if (toString.call(data) === '[object ArrayBuffer]') {\n    strm.input = new Uint8Array(data)\n  } else {\n    strm.input = data\n  }\n\n  strm.next_in = 0\n  strm.avail_in = strm.input.length\n\n  for (;;) {\n    if (strm.avail_out === 0) {\n      strm.output = new Uint8Array(chunkSize)\n      strm.next_out = 0\n      strm.avail_out = chunkSize\n    } // Make sure avail_out > 6 to avoid repeating markers\n\n    if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH$1) && strm.avail_out <= 6) {\n      this.onData(strm.output.subarray(0, strm.next_out))\n      strm.avail_out = 0\n      continue\n    }\n\n    status = deflate_1.deflate(strm, _flush_mode) // Ended => flush and finish\n\n    if (status === Z_STREAM_END$1) {\n      if (strm.next_out > 0) {\n        this.onData(strm.output.subarray(0, strm.next_out))\n      }\n\n      status = deflate_1.deflateEnd(this.strm)\n      this.onEnd(status)\n      this.ended = true\n      return status === Z_OK$1\n    } // Flush if out buffer full\n\n    if (strm.avail_out === 0) {\n      this.onData(strm.output)\n      continue\n    } // Flush if requested and has data\n\n    if (_flush_mode > 0 && strm.next_out > 0) {\n      this.onData(strm.output.subarray(0, strm.next_out))\n      strm.avail_out = 0\n      continue\n    }\n\n    if (strm.avail_in === 0) {\n      break\n    }\n  }\n\n  return true\n}\n/**\n * Deflate#onData(chunk) -> Void\n * - chunk (Uint8Array): output data.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n * */\n\nDeflate.prototype.onData = function (chunk) {\n  this.chunks.push(chunk)\n}\n/**\n * Deflate#onEnd(status) -> Void\n * - status (Number): deflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called once after you tell deflate that the input stream is\n * complete (Z_FINISH). By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n * */\n\nDeflate.prototype.onEnd = function (status) {\n  // On success - join\n  if (status === Z_OK$1) {\n    this.result = flattenChunks(this.chunks)\n  }\n\n  this.chunks = []\n  this.err = status\n  this.msg = this.strm.msg\n}\n\n// https://github.com/nodeca/pako/blob/26dff4fb3472c5532b3bd8856421146d35ab7592/lib/utils/strings.js#L26\nexport function string2buf(str) {\n  if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {\n    return new TextEncoder().encode(str)\n  }\n\n  let buf\n  let c\n  let c2\n  let m_pos\n  let i\n  let str_len = str.length\n  let buf_len = 0\n\n  // count binary size\n  for (m_pos = 0; m_pos < str_len; m_pos++) {\n    c = str.charCodeAt(m_pos)\n    if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) {\n      c2 = str.charCodeAt(m_pos + 1)\n      if ((c2 & 0xfc00) === 0xdc00) {\n        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00)\n        m_pos++\n      }\n    }\n    buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4\n  }\n\n  // allocate buffer\n  buf = new Uint8Array(buf_len)\n\n  // convert\n  for (i = 0, m_pos = 0; i < buf_len; m_pos++) {\n    c = str.charCodeAt(m_pos)\n    if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) {\n      c2 = str.charCodeAt(m_pos + 1)\n      if ((c2 & 0xfc00) === 0xdc00) {\n        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00)\n        m_pos++\n      }\n    }\n    if (c < 0x80) {\n      /* one byte */\n      buf[i++] = c\n    } else if (c < 0x800) {\n      /* two bytes */\n      buf[i++] = 0xc0 | (c >>> 6)\n      buf[i++] = 0x80 | (c & 0x3f)\n    } else if (c < 0x10000) {\n      /* three bytes */\n      buf[i++] = 0xe0 | (c >>> 12)\n      buf[i++] = 0x80 | ((c >>> 6) & 0x3f)\n      buf[i++] = 0x80 | (c & 0x3f)\n    } else {\n      /* four bytes */\n      buf[i++] = 0xf0 | (c >>> 18)\n      buf[i++] = 0x80 | ((c >>> 12) & 0x3f)\n      buf[i++] = 0x80 | ((c >>> 6) & 0x3f)\n      buf[i++] = 0x80 | (c & 0x3f)\n    }\n  }\n\n  return buf\n}\n"
  },
  {
    "path": "packages/worker/src/entries/main.ts",
    "content": "/* eslint-disable local-rules/disallow-side-effects */\nimport { startWorker } from '../boot/startWorker'\n\nstartWorker()\n"
  },
  {
    "path": "packages/worker/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"rootDir\": \"./src/\"\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./src/**/*.spec.ts\", \"./src/**/*.specHelper.ts\"]\n}\n"
  },
  {
    "path": "remote-configuration/README.md",
    "content": "# Remote configuration\n\nThis directory contains the schema of the remote configuration. This schema is duplicated here as the main version lives in an internal repository.\n"
  },
  {
    "path": "remote-configuration/rum-sdk-config.json",
    "content": "{\n  \"$id\": \"rum-sdk-config\",\n  \"type\": \"object\",\n  \"additionalProperties\": false,\n  \"description\": \"RUM Browser & Mobile SDKs Remote Configuration properties\",\n  \"$defs\": {\n    \"MatchOption\": {\n      \"type\": \"object\",\n      \"additionalProperties\": false,\n      \"required\": [\"rcSerializedType\", \"value\"],\n      \"properties\": {\n        \"rcSerializedType\": {\n          \"type\": \"string\",\n          \"enum\": [\"string\", \"regex\"],\n          \"description\": \"Remote config serialized type of match\"\n        },\n        \"value\": {\n          \"type\": \"string\",\n          \"description\": \"Match value\"\n        }\n      }\n    },\n    \"SerializedRegex\": {\n      \"type\": \"object\",\n      \"additionalProperties\": false,\n      \"required\": [\"rcSerializedType\", \"value\"],\n      \"properties\": {\n        \"rcSerializedType\": {\n          \"type\": \"string\",\n          \"const\": \"regex\",\n          \"description\": \"Remote config serialized type for regex extraction\"\n        },\n        \"value\": {\n          \"type\": \"string\",\n          \"description\": \"Regex pattern for value extraction\"\n        }\n      }\n    },\n    \"DynamicOption\": {\n      \"anyOf\": [\n        {\n          \"type\": \"object\",\n          \"required\": [\"rcSerializedType\", \"strategy\", \"path\"],\n          \"properties\": {\n            \"rcSerializedType\": {\n              \"type\": \"string\",\n              \"const\": \"dynamic\"\n            },\n            \"strategy\": {\n              \"type\": \"string\",\n              \"const\": \"js\"\n            },\n            \"path\": {\n              \"type\": \"string\"\n            },\n            \"extractor\": {\n              \"$ref\": \"#/$defs/SerializedRegex\"\n            }\n          }\n        },\n        {\n          \"type\": \"object\",\n          \"required\": [\"rcSerializedType\", \"strategy\", \"name\"],\n          \"properties\": {\n            \"rcSerializedType\": {\n              \"type\": \"string\",\n              \"const\": \"dynamic\"\n            },\n            \"strategy\": {\n              \"type\": \"string\",\n              \"const\": \"cookie\"\n            },\n            \"name\": {\n              \"type\": \"string\"\n            },\n            \"extractor\": {\n              \"$ref\": \"#/$defs/SerializedRegex\"\n            }\n          }\n        },\n        {\n          \"type\": \"object\",\n          \"required\": [\"rcSerializedType\", \"strategy\", \"selector\"],\n          \"properties\": {\n            \"rcSerializedType\": {\n              \"type\": \"string\",\n              \"const\": \"dynamic\"\n            },\n            \"strategy\": {\n              \"type\": \"string\",\n              \"const\": \"dom\"\n            },\n            \"selector\": {\n              \"type\": \"string\"\n            },\n            \"attribute\": {\n              \"type\": \"string\"\n            },\n            \"extractor\": {\n              \"$ref\": \"#/$defs/SerializedRegex\"\n            }\n          }\n        },\n        {\n          \"type\": \"object\",\n          \"required\": [\"rcSerializedType\", \"strategy\", \"key\"],\n          \"properties\": {\n            \"rcSerializedType\": {\n              \"type\": \"string\",\n              \"const\": \"dynamic\"\n            },\n            \"strategy\": {\n              \"type\": \"string\",\n              \"const\": \"localStorage\"\n            },\n            \"key\": {\n              \"type\": \"string\"\n            },\n            \"extractor\": {\n              \"$ref\": \"#/$defs/SerializedRegex\"\n            }\n          }\n        }\n      ]\n    },\n    \"ContextItem\": {\n      \"type\": \"object\",\n      \"additionalProperties\": false,\n      \"required\": [\"key\", \"value\"],\n      \"properties\": {\n        \"key\": {\n          \"type\": \"string\"\n        },\n        \"value\": {\n          \"$ref\": \"#/$defs/DynamicOption\"\n        }\n      }\n    }\n  },\n  \"properties\": {\n    \"rum\": {\n      \"type\": \"object\",\n      \"description\": \"RUM feature Remote Configuration properties\",\n      \"additionalProperties\": false,\n      \"required\": [\"applicationId\"],\n      \"properties\": {\n        \"applicationId\": {\n          \"type\": \"string\",\n          \"description\": \"UUID of the application\",\n          \"pattern\": \"^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$\"\n        },\n        \"service\": {\n          \"type\": \"string\",\n          \"description\": \"The service name for this application\"\n        },\n        \"env\": {\n          \"type\": \"string\",\n          \"description\": \"The environment for this application\"\n        },\n        \"version\": {\n          \"$ref\": \"#/$defs/DynamicOption\",\n          \"description\": \"The version for this application\"\n        },\n        \"sessionSampleRate\": {\n          \"type\": \"number\",\n          \"description\": \"The percentage of sessions tracked\",\n          \"minimum\": 0,\n          \"maximum\": 100\n        },\n        \"sessionReplaySampleRate\": {\n          \"type\": \"number\",\n          \"description\": \"The percentage of sessions with RUM & Session Replay pricing tracked\",\n          \"minimum\": 0,\n          \"maximum\": 100\n        },\n        \"defaultPrivacyLevel\": {\n          \"type\": \"string\",\n          \"description\": \"Session replay default privacy level\"\n        },\n        \"enablePrivacyForActionName\": {\n          \"type\": \"boolean\",\n          \"description\": \"Privacy control for action name\"\n        },\n        \"allowedTracingUrls\": {\n          \"type\": \"array\",\n          \"description\": \"URLs where tracing is allowed\",\n          \"items\": {\n            \"type\": \"object\",\n            \"additionalProperties\": false,\n            \"required\": [\"match\"],\n            \"properties\": {\n              \"match\": {\n                \"$ref\": \"#/$defs/MatchOption\"\n              },\n              \"propagatorTypes\": {\n                \"type\": [\"array\", \"null\"],\n                \"description\": \"List of propagator types\",\n                \"items\": {\n                  \"type\": \"string\",\n                  \"enum\": [\"datadog\", \"b3\", \"b3multi\", \"tracecontext\"]\n                }\n              }\n            }\n          }\n        },\n        \"allowedTrackingOrigins\": {\n          \"type\": \"array\",\n          \"description\": \"Origins where tracking is allowed\",\n          \"items\": {\n            \"$ref\": \"#/$defs/MatchOption\"\n          }\n        },\n        \"traceSampleRate\": {\n          \"type\": \"number\",\n          \"description\": \"The percentage of traces sampled\",\n          \"minimum\": 0,\n          \"maximum\": 100\n        },\n        \"trackSessionAcrossSubdomains\": {\n          \"type\": \"boolean\",\n          \"description\": \"Whether to track sessions across subdomains\"\n        },\n        \"user\": {\n          \"type\": \"array\",\n          \"description\": \"Function to define user information\",\n          \"contains\": {\n            \"type\": \"object\",\n            \"additionalProperties\": false,\n            \"required\": [\"key\", \"value\"],\n            \"properties\": {\n              \"key\": {\n                \"const\": \"id\"\n              },\n              \"value\": {\n                \"$ref\": \"#/$defs/DynamicOption\"\n              }\n            }\n          },\n          \"items\": {\n            \"$ref\": \"#/$defs/ContextItem\"\n          }\n        },\n        \"context\": {\n          \"type\": \"array\",\n          \"description\": \"Function to define global context\",\n          \"items\": {\n            \"$ref\": \"#/$defs/ContextItem\"\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "renovate.json",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\":dependencyDashboard\", \"group:monorepos\", \"group:recommended\"],\n  \"labels\": [\"dependencies\"],\n  \"commitMessagePrefix\": \"👷 \",\n  \"minimumReleaseAge\": \"7 days\",\n  \"internalChecksFilter\": \"strict\",\n  \"prCreation\": \"not-pending\",\n  \"prConcurrentLimit\": 5,\n  \"prHourlyLimit\": 1,\n  \"ignoreDeps\": [\"registry.ddbuild.io/dd-octo-sts\"],\n  \"schedule\": [\"every weekend\"],\n  \"postUpdateOptions\": [\"yarnDedupeHighest\"],\n  \"lockFileMaintenance\": {\n    \"enabled\": true\n  },\n  \"packageRules\": [\n    {\n      \"groupName\": \"all non-major dependencies\",\n      \"groupSlug\": \"all-minor-patch\",\n      \"matchUpdateTypes\": [\"minor\", \"patch\"],\n      \"matchPackageNames\": [\"!karma-webpack\", \"!@playwright/test\"]\n    },\n    {\n      \"matchFileNames\": [\"test/apps/vanilla/**\"],\n      \"matchDepNames\": [\"typescript\"],\n      \"enabled\": false\n    },\n    {\n      \"matchFileNames\": [\"test/apps/react-router-v6-app/**\"],\n      \"matchDepNames\": [\"react-router-dom\"],\n      \"enabled\": false\n    }\n  ],\n  \"toolSettings\": {\n    \"nodeMaxMemory\": 4096\n  }\n}\n"
  },
  {
    "path": "repository.datadog.yml",
    "content": "---\nschema-version: v1\nkind: mergequeue\nteam: rum-browser\nto_staging_enable: true\n---\nschema-version: v1\nkind: integration-branch\nname: $CURRENT_STAGING\nteam: rum-browser\nupdate_automatically: false # update_automatically is updating the integration branch on a schedule, instead we're updating it in a CI job for any commit to the base branch.\nreset_pattern: '' # use `staging-reset.js` instead so that a new staging branch is created weekly\ncontacts:\n  - type: slack\n    contact: browser-sdk-deploy\n---\nschema-version: v1\nkind: integration-branch\nname: v7\nteam: rum-browser\nephemeral: false\nupdate_automatically: false # update_automatically is updating the integration branch on a schedule, instead we're updating it in a CI job for any commit to the base branch.\nreset_pattern: '' # This branch should never be reseted\nhide_reset_branch_instructions_on_conflict: true\ncontacts:\n  - type: slack\n    contact: browser-sdk-deploy\n---\nschema-version: v1\nkind: buildimpactanalysis\nteam: ci-platforms\nenabled_strategies:\n  - yarn_berry_strategy\npreprocess: true\n---\nschema-version: v2\nkind: adms # Automated Dependency Management Service\nauto-version-updates:\n  disabled:\n    reason: We use renovate for now\n"
  },
  {
    "path": "scripts/AGENTS.md",
    "content": "# Scripts and Automation\n\nThe `scripts/` directory contains TypeScript scripts for CI automation and developer tools.\n\n## Directory Structure\n\n```\nscripts/\n├── build/           # Build automation\n├── deploy/          # Deployment (CI only)\n├── performance/     # Performance benchmarking (CI only)\n├── release/         # Release automation (CI only)\n├── test/            # Test infrastructure (CI only)\n└── lib/             # Shared utilities\n```\n\n**Pattern**: Each subdirectory has a `lib/` folder for domain-specific utilities.\n\n## Writing Scripts\n\n### TypeScript & Node.js Version\n\nScripts run on the **latest Node.js version** (see `volta.node` in `package.json`):\n\n- Use modern TypeScript and latest Node.js APIs\n- Prefer built-in Node.js modules over dependencies\n- Always use `node:` prefix for Node.js imports\n\n```typescript\n// ✅ Good - built-in Node.js APIs\nimport { globSync } from 'node:fs'\nimport { parseArgs } from 'node:util'\nimport * as path from 'node:path'\n\n// ❌ Bad - unnecessary dependencies\nimport glob from 'glob'\nimport minimist from 'minimist'\n```\n\n### Basic Structure\n\nAll scripts follow this pattern:\n\n```typescript\nimport { printLog, runMain } from './lib/executionUtils.ts'\nimport { command } from './lib/command.ts'\n\nrunMain(async () => {\n  printLog('Starting task...')\n\n  // Script logic here\n  command`yarn build`.run()\n\n  printLog('Task completed.')\n})\n```\n\n**Key conventions:**\n\n- Use `runMain()` wrapper for proper async handling and error reporting\n- Use `printLog()` for console output\n- Use `command` template literal for shell commands\n- Import with `.ts` extension (required for Node.js ESM)\n\n## Testing Scripts\n\nScripts can have spec files using Node.js built-in test runner:\n\n```typescript\n// deploy.spec.ts\nimport { test } from 'node:test'\nimport assert from 'node:assert'\n\ntest('should deploy to staging', () => {\n  // Test logic\n  assert.strictEqual(actual, expected)\n})\n```\n\n```\nscripts/deploy/\n├── deploy.ts\n└── deploy.spec.ts  # Tests using node:test\n```\n\nRun script tests:\n\n```bash\nyarn test:script\n```\n\n## Shared Utilities (`scripts/lib/`)\n\nCore utilities available to all scripts:\n\n- `executionUtils.ts` - `runMain()`, `printLog()`, error handling\n- `command.ts` - Shell command builder with fluent API\n- `filesUtils.ts` - File operations (read, write, modify, iterate)\n- `gitUtils.ts` - Git operations (branches, tags, commits, PRs)\n- `buildEnv.ts` - Detect environment (CI, local, staging, production)\n- `datacenter.ts` - Datadog datacenter configuration\n- `packagesDirectoryNames.ts` - Package directory listing\n"
  },
  {
    "path": "scripts/CLAUDE.md",
    "content": "# Scripts and Automation\n\nSee @./AGENTS.md for documentation on writing and organizing scripts in this codebase.\n"
  },
  {
    "path": "scripts/build/build-package.ts",
    "content": "import fs from 'node:fs/promises'\nimport { parseArgs } from 'node:util'\nimport path from 'node:path'\nimport { globSync } from 'node:fs'\nimport ts from 'typescript'\nimport webpack from 'webpack'\nimport webpackBase from '../../webpack.base.ts'\n\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { modifyFile } from '../lib/filesUtils.ts'\nimport { buildEnvKeys, getBuildEnvValue } from '../lib/buildEnv.ts'\n\nrunMain(async () => {\n  const { values } = parseArgs({\n    options: {\n      modules: {\n        type: 'boolean',\n      },\n      bundle: {\n        type: 'string',\n      },\n      verbose: {\n        type: 'boolean',\n        default: false,\n      },\n    },\n  })\n\n  if (values.modules) {\n    printLog('Building modules...')\n    await buildModules({\n      outDir: './cjs',\n      module: 'commonjs',\n      verbose: values.verbose,\n    })\n    await buildModules({\n      outDir: './esm',\n      module: 'es2020',\n      verbose: values.verbose,\n    })\n  }\n\n  if (values.bundle) {\n    printLog('Building bundle...')\n    await buildBundle({\n      filename: values.bundle,\n      verbose: values.verbose,\n    })\n  }\n\n  printLog('Done.')\n})\n\nasync function buildBundle({ filename, verbose }: { filename: string; verbose: boolean }) {\n  await fs.rm('./bundle', { recursive: true, force: true })\n  return new Promise<void>((resolve, reject) => {\n    webpack(\n      webpackBase({\n        mode: 'production',\n        entry: './src/entries/main.ts',\n        filename,\n      }),\n      (error, stats) => {\n        if (error) {\n          reject(error)\n        } else if (!stats) {\n          reject(new Error('Webpack did not return stats'))\n        } else if (stats.hasErrors()) {\n          printStats(stats)\n          reject(new Error('Failed to build bundle due to Webpack errors'))\n        } else {\n          if (verbose) {\n            printStats(stats)\n          }\n          resolve()\n        }\n      }\n    )\n  })\n\n  function printStats(stats: webpack.Stats) {\n    console.log(stats.toString({ colors: true }))\n  }\n}\n\nasync function buildModules({ outDir, module, verbose }: { outDir: string; module: string; verbose: boolean }) {\n  await fs.rm(outDir, { recursive: true, force: true })\n\n  // TODO: in the future, consider building packages with something else than typescript (ex:\n  // rspack, tsdown...)\n\n  const diagnostics = buildWithTypeScript({\n    extends: '../../tsconfig.base.json',\n    compilerOptions: {\n      declaration: true,\n      allowJs: true,\n      module,\n      rootDir: './src/',\n      outDir,\n      paths: {},\n    },\n    include: ['./src'],\n    exclude: ['./src/**/*.spec.*', './src/**/*.specHelper.*'],\n  })\n\n  if (diagnostics.length) {\n    printTypeScriptDiagnostics(diagnostics)\n    throw new Error('Failed to build package due to TypeScript errors')\n  }\n\n  await replaceBuildEnvInDirectory(outDir, { verbose })\n}\n\nasync function replaceBuildEnvInDirectory(dir: string, { verbose }: { verbose: boolean }) {\n  for (const relativePath of globSync('**/*.js', { cwd: dir })) {\n    const absolutePath = path.resolve(dir, relativePath)\n    if (await modifyFile(absolutePath, (content: string) => replaceBuildEnv(content))) {\n      if (verbose) {\n        printLog(`Replaced BuildEnv in ${absolutePath}`)\n      }\n    }\n  }\n\n  function replaceBuildEnv(content: string): string {\n    return buildEnvKeys.reduce(\n      (content, key) => content.replaceAll(`__BUILD_ENV__${key}__`, () => JSON.stringify(getBuildEnvValue(key))),\n      content\n    )\n  }\n}\n\nfunction buildWithTypeScript(configuration: { [key: string]: unknown }) {\n  const parsedConfiguration = ts.parseJsonConfigFileContent(\n    configuration,\n    ts.sys,\n    process.cwd(),\n    undefined,\n    'tsconfig.json' // just used in messages\n  )\n\n  const host = ts.createCompilerHost(parsedConfiguration.options)\n  const program = ts.createProgram({\n    rootNames: parsedConfiguration.fileNames,\n    options: parsedConfiguration.options,\n    host,\n  })\n\n  const emitResult = program.emit()\n  if (emitResult.emitSkipped) {\n    throw new Error('No files were emitted')\n  }\n\n  return [...ts.getPreEmitDiagnostics(program), ...emitResult.diagnostics]\n}\n\nfunction printTypeScriptDiagnostics(diagnostics: ts.Diagnostic[]) {\n  const formatHost: ts.FormatDiagnosticsHost = {\n    getCanonicalFileName: (f) => f,\n    // eslint-disable-next-line @typescript-eslint/unbound-method\n    getCurrentDirectory: ts.sys.getCurrentDirectory,\n    getNewLine: () => ts.sys.newLine,\n  }\n  console.error(ts.formatDiagnosticsWithColorAndContext(diagnostics, formatHost))\n}\n"
  },
  {
    "path": "scripts/build/build-test-apps.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { parseArgs } from 'node:util'\n\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { modifyFile } from '../lib/filesUtils.ts'\n\ntype AppConfig<T extends AppBuilderOptions = AppBuilderOptions> =\n  | {\n      name: string\n      deps?: string[]\n    }\n  | {\n      name: string\n      builderFn(appName: string, options?: T): Promise<void> | void\n      options?: T\n      deps?: string[]\n    }\n\ntype AppBuilderOptions = Record<string, unknown>\n\nconst APPS: AppConfig[] = [\n  { name: 'vanilla' },\n  { name: 'react-heavy-spa' },\n  { name: 'react-shopist-like' },\n  { name: 'microfrontend' },\n  { name: 'nextjs' },\n  { name: 'angular-app' },\n  { name: 'vue-router-app' },\n  { name: 'nuxt-app' },\n\n  // React Router apps\n  { name: 'react-router-v6-app' },\n  { name: 'tanstack-router-app' },\n  { name: 'react-router-v7-app', builderFn: buildReactRouterv7App },\n\n  // browser extensions\n  { name: 'base-extension' },\n  {\n    name: 'cdn-extension',\n    builderFn: buildExtension,\n    deps: ['base-extension'],\n  },\n  {\n    name: 'appendChild-extension',\n    builderFn: buildExtension,\n    options: { runAt: 'document_start' },\n    deps: ['base-extension'],\n  },\n]\n\nrunMain(async () => {\n  const { values } = parseArgs({\n    options: {\n      app: {\n        type: 'string',\n        multiple: true,\n        short: 'a',\n      },\n      help: {\n        type: 'boolean',\n        short: 'h',\n      },\n    },\n  })\n\n  if (values.help) {\n    showHelpAndExit()\n  }\n\n  const appsToBuild = values.app ? APPS.filter((app) => values.app!.includes(app.name)) : APPS\n\n  if (appsToBuild.length === 0) {\n    printLog('No valid app specified. Use --help to see available options.')\n    process.exit(1)\n  }\n\n  printLog('Packing packages...')\n  command`yarn run pack`.run()\n\n  const built = new Set<string>()\n  for (const app of appsToBuild) {\n    for (const dep of app.deps ?? []) {\n      if (!built.has(dep)) {\n        buildApp(dep)\n        built.add(dep)\n      }\n    }\n    if ('builderFn' in app) {\n      await app.builderFn(app.name, app.options)\n    } else {\n      buildApp(app.name)\n    }\n    built.add(app.name)\n  }\n\n  printLog('Test apps and extensions built successfully.')\n})\n\nfunction showHelpAndExit() {\n  console.log('Usage: node build-test-apps.ts [--app <name>] [--help]')\n  console.log('')\n  console.log('Options:')\n  console.log('  --app, -a  Build a specific app (can be repeated for multiple apps)')\n  console.log('  --help, -h  Show this help message')\n  console.log('')\n  console.log('Available apps:')\n  for (const app of APPS) {\n    console.log(`  ${app.name}`)\n  }\n  process.exit(0)\n}\n\nfunction buildApp(appName: string) {\n  const appPath = `test/apps/${appName}`\n  printLog(`Building app at ${appPath}...`)\n  command`yarn install --no-immutable`.withCurrentWorkingDirectory(appPath).run()\n\n  // install peer dependencies if any\n  // intent: renovate does not allow to generate local packages before install\n  // so local packages are marked as optional peer dependencies and only installed when we build the test apps\n  const packageJson = JSON.parse(fs.readFileSync(path.join(appPath, 'package.json'), 'utf-8'))\n  if (packageJson.peerDependencies) {\n    // For each peer dependency, install it\n    for (const [name] of Object.entries(packageJson.peerDependencies)) {\n      const resolution = packageJson.resolutions?.[name]\n      const specifier = resolution ? `${name}@${resolution}` : name\n      command`yarn add -D ${specifier}`.withCurrentWorkingDirectory(appPath).run()\n    }\n    // revert package.json & yarn.lock changes if they are versioned\n    const areFilesVersioned = command`git ls-files package.json yarn.lock`.withCurrentWorkingDirectory(appPath).run()\n    if (areFilesVersioned) {\n      command`git checkout package.json yarn.lock`.withCurrentWorkingDirectory(appPath).run()\n    }\n  }\n\n  command`yarn build`.withCurrentWorkingDirectory(appPath).run()\n}\n\nasync function buildReactRouterv7App() {\n  const baseAppPath = 'test/apps/react-router-v6-app'\n  const appPath = 'test/apps/react-router-v7-app'\n\n  fs.rmSync(appPath, { recursive: true, force: true })\n  fs.cpSync(baseAppPath, appPath, { recursive: true })\n\n  await modifyFile(path.join(appPath, 'package.json'), (content: string) =>\n    content\n      .replace(/\"name\": \"react-router-v6-app\"/, '\"name\": \"react-router-v7-app\"')\n      .replace(/\"react-router-dom\": \"[^\"]*\"/, '\"react-router\": \"7.0.2\"')\n  )\n\n  await modifyFile(path.join(appPath, 'app.tsx'), (content: string) =>\n    content\n      .replace('@datadog/browser-rum-react/react-router-v6', '@datadog/browser-rum-react/react-router-v7')\n      .replace(\"from 'react-router-dom'\", \"from 'react-router'\")\n  )\n\n  await modifyFile(path.join(appPath, 'webpack.config.js'), (content: string) =>\n    content\n      .replace('react-router-v6-app.js', 'react-router-v7-app.js')\n      .replace('react-router-v6-app.js', 'react-router-v7-app.js')\n  )\n\n  buildApp('react-router-v7-app')\n}\n\nasync function buildExtension(appName: string, options?: { runAt?: string }): Promise<void> {\n  const baseExtDir = 'test/apps/base-extension'\n  const targetDir = `test/apps/${appName}`\n\n  printLog(`Building app at ${targetDir}...`)\n\n  fs.rmSync(targetDir, { recursive: true, force: true })\n  fs.cpSync(baseExtDir, targetDir, { recursive: true })\n\n  const manifestPath = path.join(targetDir, 'manifest.json')\n  await modifyFile(manifestPath, (originalContent: string) => {\n    const filename = appName.replace('-extension', '')\n    let content = originalContent.replace('dist/base.js', `dist/${filename}.js`)\n\n    if (options?.runAt) {\n      content = content.replace('document_end', options.runAt)\n    }\n    return content\n  })\n}\n"
  },
  {
    "path": "scripts/check-licenses.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as readline from 'node:readline'\nimport { printLog, printError, runMain } from './lib/executionUtils.ts'\nimport { findPackageJsonFiles } from './lib/filesUtils.ts'\n\nconst LICENSE_FILE = 'LICENSE-3rdparty.csv'\n\nrunMain(async () => {\n  const packageJsonFiles = findPackageJsonFiles()\n\n  printLog(\n    'Looking for dependencies in:\\n',\n    packageJsonFiles.map((packageJsonFile) => packageJsonFile.relativePath),\n    '\\n'\n  )\n  const declaredDependencies = withoutDuplicates(packageJsonFiles.flatMap(retrievePackageDependencies)).sort()\n\n  const declaredLicenses = (await retrieveLicenses()).sort()\n\n  if (JSON.stringify(declaredDependencies) !== JSON.stringify(declaredLicenses)) {\n    printError(`Package.json dependencies and ${LICENSE_FILE} mismatch`)\n    printError(\n      `In package.json but not in ${LICENSE_FILE}:\\n`,\n      declaredDependencies.filter((d) => !declaredLicenses.includes(d))\n    )\n    printError(\n      `In ${LICENSE_FILE} but not in package.json:\\n`,\n      declaredLicenses.filter((d) => !declaredDependencies.includes(d))\n    )\n    throw new Error('Dependencies mismatch')\n  }\n  printLog('Dependencies check done.')\n})\n\nfunction retrievePackageDependencies(packageJsonFile: { content: any }): string[] {\n  return Object.entries(packageJsonFile.content.dependencies || {})\n    .concat(Object.entries(packageJsonFile.content.devDependencies || {}))\n    .map(([dependency, version]) => {\n      if (typeof version === 'string' && version.startsWith('npm:')) {\n        // Extract the original dependency name from the npm protocol version string. Example:\n        // npm:react@17  ->  react\n        return version.slice(4).split('@')[0]\n      }\n      return dependency\n    })\n    .filter((dependency) => !dependency.includes('@datadog'))\n}\n\nfunction withoutDuplicates<T>(a: T[]): T[] {\n  return [...new Set(a)]\n}\n\nasync function retrieveLicenses(): Promise<string[]> {\n  const fileStream = fs.createReadStream(path.join(import.meta.dirname, '..', LICENSE_FILE))\n  const rl = readline.createInterface({ input: fileStream })\n  const licenses: string[] = []\n  let header = true\n  for await (const line of rl) {\n    const csvColumns = line.split(',')\n    if (!header && csvColumns[0] !== 'file') {\n      if (!csvColumns[1]) {\n        console.log(csvColumns)\n      }\n      licenses.push(csvColumns[1])\n    }\n    header = false\n  }\n  return licenses\n}\n"
  },
  {
    "path": "scripts/check-node-version.ts",
    "content": "import * as fs from 'node:fs'\nimport * as readline from 'node:readline'\nimport * as path from 'node:path'\nimport packageJson from '../package.json' with { type: 'json' }\nimport { printLog, printError, runMain } from './lib/executionUtils.ts'\n\nrunMain(async () => {\n  printLog('Check that node version across configurations are matching...\\n')\n\n  const dockerVersion = await retrieveDockerVersion()\n  printLog(`docker: ${dockerVersion}`)\n\n  const voltaVersion = packageJson.volta.node\n  printLog(`volta: ${voltaVersion}`)\n\n  const processVersion = retrieveProcessVersion()\n  printLog(`process: ${processVersion}`)\n\n  if (dockerVersion !== voltaVersion || dockerVersion !== processVersion) {\n    printError('Different node versions detected!\\n')\n    printError('Ensure to:')\n    printError(`- run \\`volta pin node@${dockerVersion}\\``)\n    printError('- bump `CURRENT_CI_IMAGE` and run `ci-image` gitlab job\\n')\n    process.exit(1)\n  }\n})\n\nasync function retrieveDockerVersion(): Promise<string> {\n  const fileStream = fs.createReadStream(path.join(import.meta.dirname, '..', 'Dockerfile'))\n  const rl = readline.createInterface({ input: fileStream })\n  for await (const line of rl) {\n    // node image on first line\n    return extractVersion(line)\n  }\n  throw new Error('Could not find node version in Dockerfile')\n}\n\nfunction retrieveProcessVersion(): string {\n  // process.version returns vX.Y.Z\n  return extractVersion(process.version)\n}\n\nfunction extractVersion(input: string): string {\n  const match = /\\d+\\.\\d+\\.\\d+/.exec(input)\n  if (!match) {\n    throw new Error(`Could not extract version from: ${input}`)\n  }\n  return match[0]\n}\n"
  },
  {
    "path": "scripts/check-packages.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { globSync } from 'node:fs'\nimport { minimatch } from 'minimatch'\nimport { printLog, runMain } from './lib/executionUtils.ts'\nimport { command } from './lib/command.ts'\nimport { checkPackageJsonFiles } from './lib/checkBrowserSdkPackageJsonFiles.ts'\n\nrunMain(() => {\n  checkPackageJsonFiles()\n\n  for (const packagePath of globSync('packages/*')) {\n    checkBrowserSdkPackage(packagePath)\n  }\n\n  for (const packagePath of globSync('test/apps/*')) {\n    checkTestAppPackage(packagePath)\n  }\n\n  printLog('Packages check done.')\n})\n\nfunction checkBrowserSdkPackage(packagePath: string) {\n  const packageJson = getPackageJson(packagePath)\n\n  printLog(`Checking ${packagePath}`)\n\n  const packageFiles = getPackageFiles(packagePath)\n\n  checkExpectedFiles(packagePath, packageFiles)\n  checkPackageJsonEntryPoints(packageJson, packageFiles)\n  checkFilesField(packageJson, packageFiles)\n}\n\nfunction checkExpectedFiles(packagePath: string, packageFiles: string[]) {\n  const expectedFiles = ['package.json', 'README.md', 'LICENSE']\n\n  for (const file of expectedFiles) {\n    if (!packageFiles.includes(file)) {\n      throw new Error(`File ${file} is missing from ${packagePath}`)\n    }\n  }\n}\n\nfunction getPackageFiles(packagePath: string): string[] {\n  const output = command`yarn pack --dry-run --json`.withCurrentWorkingDirectory(packagePath).run()\n  return output\n    .trim()\n    .split('\\n')\n    .map((line) => JSON.parse(line) as Record<string, unknown>)\n    .filter((entry): entry is { location: string } => 'location' in entry)\n    .map((entry) => entry.location)\n}\n\nfunction checkPackageJsonEntryPoints(packageJson: PackageJson, packageFiles: string[]) {\n  const filesFromPackageJsonEntryPoints = [packageJson.main, packageJson.module, packageJson.types].filter(Boolean)\n\n  for (const file of filesFromPackageJsonEntryPoints) {\n    if (!packageFiles.includes(file)) {\n      throw new Error(`File ${file} used as an entry point in ${packageJson.name} is missing from the package`)\n    }\n  }\n}\n\n// Files always included by yarn/npm regardless of the `files` field\nconst ALWAYS_INCLUDED_FILES = new Set(['package.json', 'README.md', 'LICENSE'])\n\nfunction checkFilesField(packageJson: PackageJson, packageFiles: string[]) {\n  if (!packageJson.files) {\n    throw new Error(`Package ${packageJson.name} is missing the \"files\" field`)\n  }\n\n  const unexpectedFiles = packageFiles.filter((file) => {\n    if (ALWAYS_INCLUDED_FILES.has(file)) {\n      return false\n    }\n    let matched = false\n    for (let pattern of packageJson.files!) {\n      const negated = pattern.startsWith('!')\n      if (negated) {\n        pattern = pattern.slice(1)\n      }\n      // Normalize directory patterns (e.g. \"cjs\" → \"cjs/**\") for glob matching\n      pattern = pattern.includes('*') || pattern.includes('?') ? pattern : `${pattern}/**`\n      if (minimatch(file, pattern)) {\n        matched = !negated\n      }\n    }\n    return !matched\n  })\n\n  if (unexpectedFiles.length > 0) {\n    throw new Error(\n      `Package ${packageJson.name} contains files not covered by the \"files\" field:\\n${unexpectedFiles.map((f) => `  - ${f}`).join('\\n')}`\n    )\n  }\n}\n\nfunction checkTestAppPackage(packagePath: string) {\n  const packageJson = getPackageJson(packagePath)\n\n  if (!packageJson) {\n    return\n  }\n\n  printLog(`Checking ${packagePath}`)\n\n  const datadogDeps = Object.keys(packageJson.dependencies ?? {}).filter((name) => name.startsWith('@datadog/'))\n\n  if (datadogDeps.length > 0) {\n    throw new Error(\n      `${packagePath} has @datadog/* packages in \"dependencies\": ${datadogDeps.join(', ')}. ` +\n        'Use \"peerDependencies\" instead (see other test apps for the pattern).'\n    )\n  }\n}\n\nfunction getPackageJson(packagePath: string) {\n  return globSync(path.join(packagePath, 'package.json')).map(\n    (packageJsonFile) => JSON.parse(fs.readFileSync(packageJsonFile, 'utf8')) as PackageJson\n  )[0]\n}\n\ninterface PackageJson {\n  name: string\n  private?: boolean\n  main: string\n  module: string\n  types: string\n  files?: string[]\n  dependencies?: Record<string, string>\n}\n"
  },
  {
    "path": "scripts/check-schemas.ts",
    "content": "import { printLog, printError, runMain } from './lib/executionUtils.ts'\nimport { command } from './lib/command.ts'\n\nrunMain(() => {\n  if (command`git status --porcelain`.run()) {\n    throw new Error('This script should be run from a clean working tree')\n  }\n\n  printLog('Regenerating schemas...')\n  command`scripts/cli build_json2type`.run()\n  command`node scripts/generate-schema-types.ts`.run()\n\n  printLog('Checking untracked changes...')\n  const diff = command`git diff --color`.run()\n  if (diff) {\n    printLog(diff)\n    printError(`\nUntracked changes detected.\n* If your PR requires rum-events-format changes, make sure to run \\`yarn json-schemas:sync\\`.\n* Else, you probably updated the rum-events-format submodule by mistake. To revert it, run something like:\n  git checkout $(git merge-base main HEAD) rum-events-format\n  git submodule update rum-events-format\n`)\n\n    process.exit(1)\n  }\n})\n"
  },
  {
    "path": "scripts/check-typescript-compatibility.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { printLog, runMain } from './lib/executionUtils.ts'\nimport { command } from './lib/command.ts'\n\nconst TEST_APP_DIR = path.join(import.meta.dirname, '..', 'test', 'apps', 'vanilla')\n\ninterface TypeScriptCheck {\n  title: string\n  version: string\n  compilerOptions?: Partial<any>\n}\n\nrunMain(() => {\n  printLog('Building and packing project...')\n  command`yarn run pack`.run()\n\n  printLog('Setting up test environment...')\n  command`yarn install --no-immutable`.withCurrentWorkingDirectory(TEST_APP_DIR).run()\n\n  const checks: TypeScriptCheck[] = [\n    {\n      title: 'TypeScript 3.8.2 compatibility',\n      version: '3.8.2',\n      compilerOptions: { moduleResolution: 'node' },\n    },\n    {\n      title: 'TypeScript isolated modules compatibility',\n      compilerOptions: { isolatedModules: true, moduleResolution: 'node' },\n      version: '3.8.2',\n    },\n    {\n      title: 'TypeScript 4.1.6 compatibility',\n      version: '4.1.6',\n      compilerOptions: { moduleResolution: 'node' },\n    },\n    {\n      title: 'TypeScript latest compatibility',\n      version: 'latest',\n      compilerOptions: { ignoreDeprecations: '6.0' },\n    },\n    {\n      title: 'exactOptionalPropertyTypes compatibility',\n      version: 'latest', // Not available in 3.8.2\n      compilerOptions: { exactOptionalPropertyTypes: true, ignoreDeprecations: '6.0' },\n    },\n    {\n      title: 'ESNext compatibility',\n      version: 'latest',\n      compilerOptions: { lib: ['ESNext', 'DOM'], ignoreDeprecations: '6.0' },\n    },\n  ]\n\n  for (const { title, compilerOptions, version } of checks) {\n    printLog(`Checking ${title}...`)\n    if (compilerOptions) {\n      modifyTestAppConfig(compilerOptions)\n    }\n    command`yarn add --dev typescript@${version}`.withCurrentWorkingDirectory(TEST_APP_DIR).run()\n    try {\n      command`yarn compat:tsc`.withCurrentWorkingDirectory(TEST_APP_DIR).run()\n    } catch (error) {\n      throw new Error(`${title} compatibility broken`, { cause: error })\n    } finally {\n      command`git checkout -- ${TEST_APP_DIR}`.run()\n    }\n  }\n\n  printLog('All TypeScript compatibility checks passed.')\n})\n\nfunction modifyTestAppConfig(partialCompilerOptions: any): void {\n  const configPath = path.join(TEST_APP_DIR, 'tsconfig.json')\n  const originalConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'))\n  fs.writeFileSync(\n    configPath,\n    JSON.stringify({ compilerOptions: { ...originalConfig.compilerOptions, ...partialCompilerOptions } }, null, 2)\n  )\n}\n"
  },
  {
    "path": "scripts/cli",
    "content": "#!/bin/bash\n\nset -euo pipefail\n\nPATH=\"$PATH:node_modules/.bin\"\n\nmain () {\n  if [[ $# -lt 1 ]]; then\n    cmd_help\n  fi\n\n  local command=\"cmd_$1\"\n  shift\n\n  \"$command\" \"$@\"\n}\n\ncmd_help () {\n  local available_commands=$(set | perl -nle'print $& while m{^cmd_\\K\\w+}g')\n  echo -e \"Available commands:\\n$available_commands\"\n  exit 1\n}\n\ncmd_typecheck () {\n  local project_path=\"${1}\"\n  tsc -p \"$project_path\" --noEmit true\n}\n\ncmd_init_submodule () {\n  git submodule update --init\n}\n\ncmd_update_submodule () {\n  git submodule update --init\n  git submodule update --remote\n}\n\n# needed because using fork instead of the npm package\n# TODO remove me when json-schema-to-typescript natively supports readOnly\ncmd_build_json2type () {\n  cd ./node_modules/json-schema-to-typescript\n  rm -rf dist\n  # due to installation on node_modules, some of these steps can fail\n  # built version still behaves correctly though\n  set +e\n  npm i\n  npm run clean\n\n  # With yarn 3, the 'test/' folder is not present, so all built files are put directly in the\n  # 'dist/' folder instead of 'dist/src/'.\n  #\n  # Using an explicit '--rootDir' fixes this issue.\n  npm exec -- tsc --declaration --rootDir .\n\n  set -e\n}\n\n\ncmd_woke () {\n  command -v woke || fail 'woke not installed, see https://github.com/get-woke/woke#installation'\n  woke --exit-1-on-failure\n}\n\ncmd_check_server_side_rendering_compatibility () {\n  yarn run pack\n  cd test/apps/vanilla\n  rm -rf node_modules\n  yarn install --no-immutable\n  yarn compat:ssr || fail 'server side rendering compatibility broken'\n}\n\nfail () {\n  echo\n  echo \"❌ ${1}\"\n  echo\n\n  exit 1\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "scripts/deploy/deploy-prod-dc.spec.ts",
    "content": "import assert from 'node:assert/strict'\nimport path from 'node:path'\nimport { beforeEach, before, after, describe, it, mock, type Mock } from 'node:test'\nimport { browserSdkVersion } from '../lib/browserSdkVersion.ts'\nimport type { CommandDetail } from './lib/testHelpers.ts'\nimport { mockModule, mockCommandImplementation, mockFetchHandlingError } from './lib/testHelpers.ts'\n\nconst currentBrowserSdkVersionMajor = browserSdkVersion.split('.')[0]\n\ndescribe('deploy-prod-dc', () => {\n  const commandMock = mock.fn()\n  const checkTelemetryErrorsMock: Mock<(datacenters: string[], version: string) => Promise<void>> = mock.fn()\n  const fetchHandlingErrorMock = mock.fn()\n\n  let commands: CommandDetail[]\n  let checkTelemetryErrorsCalls: Array<{ version: string; datacenters: string[] }>\n  let mockTime: number\n  const originalDateNow = Date.now\n\n  before(async () => {\n    mockFetchHandlingError(fetchHandlingErrorMock)\n    await mockModule(path.resolve(import.meta.dirname, '../lib/command.ts'), { command: commandMock })\n    await mockModule(path.resolve(import.meta.dirname, '../lib/executionUtils.ts'), {\n      fetchHandlingError: fetchHandlingErrorMock,\n      timeout: (ms: number) => {\n        mockTime += ms\n        return Promise.resolve()\n      },\n    })\n    await mockModule(path.resolve(import.meta.dirname, './lib/checkTelemetryErrors.ts'), {\n      checkTelemetryErrors: checkTelemetryErrorsMock,\n    })\n  })\n\n  beforeEach(() => {\n    commands = mockCommandImplementation(commandMock)\n    checkTelemetryErrorsCalls = []\n    checkTelemetryErrorsMock.mock.mockImplementation((datacenters: string[], version: string) => {\n      checkTelemetryErrorsCalls.push({ version, datacenters })\n      return Promise.resolve()\n    })\n\n    // Mock time control\n    mockTime = Date.UTC(2026, 0, 16, 12, 0, 0)\n    Date.now = () => mockTime\n  })\n\n  after(() => {\n    // Restore original Date.now\n    Date.now = originalDateNow\n  })\n\n  it('should deploy a given datacenter', async () => {\n    await runScript('./deploy-prod-dc.ts', 'v6', 'us1')\n\n    // Should not call checkTelemetryErrors by default (no flag)\n    assert.strictEqual(checkTelemetryErrorsCalls.length, 0)\n\n    assert.deepEqual(commands, [\n      { command: 'node ./scripts/deploy/deploy.ts prod v6 us1' },\n      { command: 'node ./scripts/deploy/upload-source-maps.ts v6 us1' },\n    ])\n  })\n\n  it('should deploy a given datacenter with check telemetry errors', async () => {\n    await runScript('./deploy-prod-dc.ts', 'v6', 'us1', '--check-telemetry-errors')\n\n    // Should call checkTelemetryErrors 31 times: 1 initial + 30 during gating\n    assert.strictEqual(checkTelemetryErrorsCalls.length, 31)\n    assert.deepEqual(checkTelemetryErrorsCalls[0], {\n      version: `${currentBrowserSdkVersionMajor}.*`,\n      datacenters: ['us1'],\n    }) // Initial check\n    assert.deepEqual(checkTelemetryErrorsCalls[30], { version: browserSdkVersion, datacenters: ['us1'] }) // Last gating check\n\n    assert.deepEqual(commands, [\n      { command: 'node ./scripts/deploy/deploy.ts prod v6 us1' },\n      { command: 'node ./scripts/deploy/upload-source-maps.ts v6 us1' },\n    ])\n  })\n\n  it('should deploy all minor datacenters', async () => {\n    await runScript('./deploy-prod-dc.ts', 'v6', 'minor-dcs', '--no-check-telemetry-errors')\n\n    // Should not call checkTelemetryErrors when --no-check-telemetry-errors is used\n    assert.strictEqual(checkTelemetryErrorsCalls.length, 0)\n\n    assert.deepEqual(commands, [\n      { command: 'node ./scripts/deploy/deploy.ts prod v6 ap1,ap2,us3,us5' },\n      { command: 'node ./scripts/deploy/upload-source-maps.ts v6 ap1,ap2,us3,us5' },\n    ])\n  })\n\n  it('should deploy all private regions', async () => {\n    await runScript('./deploy-prod-dc.ts', 'v6', 'private-regions', '--no-check-telemetry-errors')\n\n    // Should not call checkTelemetryErrors when --no-check-telemetry-errors is used\n    assert.strictEqual(checkTelemetryErrorsCalls.length, 0)\n\n    assert.deepEqual(commands, [\n      { command: 'node ./scripts/deploy/deploy.ts prod v6 prtest00,prtest01' },\n      { command: 'node ./scripts/deploy/upload-source-maps.ts v6 prtest00,prtest01' },\n    ])\n  })\n\n  it('should deploy gov datacenters to the root upload path and skip all telemetry error checks', async () => {\n    await runScript('./deploy-prod-dc.ts', 'v6', 'gov', '--check-telemetry-errors')\n\n    // gov datacenters should not be checked for telemetry errors\n    assert.strictEqual(checkTelemetryErrorsCalls.length, 0)\n\n    assert.deepEqual(commands, [\n      { command: 'node ./scripts/deploy/deploy.ts prod v6 root' },\n      { command: 'node ./scripts/deploy/upload-source-maps.ts v6 root' },\n    ])\n  })\n})\n\nasync function runScript(scriptPath: string, ...args: string[]): Promise<void> {\n  const { main } = (await import(scriptPath)) as { main: (...args: string[]) => Promise<void> }\n\n  return main(...args)\n}\n"
  },
  {
    "path": "scripts/deploy/deploy-prod-dc.ts",
    "content": "import { parseArgs } from 'node:util'\nimport { printLog, runMain, timeout } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { DatacenterType, getAllDatacentersMetadata } from '../lib/datacenter.ts'\nimport { browserSdkVersion } from '../lib/browserSdkVersion.ts'\nimport { checkTelemetryErrors } from './lib/checkTelemetryErrors.ts'\n\n/**\n * Orchestrate the deployments of the artifacts for specific DCs\n * Usage:\n * node deploy-prod-dc.ts vXXX us1,eu1,... true|false\n */\nconst ONE_MINUTE_IN_SECOND = 60\nconst GATE_DURATION = 30 * ONE_MINUTE_IN_SECOND\nconst GATE_INTERVAL = ONE_MINUTE_IN_SECOND\n\nif (!process.env.NODE_TEST_CONTEXT) {\n  runMain(() => main(...process.argv.slice(2)))\n}\n\nexport async function main(...args: string[]): Promise<void> {\n  const {\n    values: { 'check-telemetry-errors': checkTelemetryErrorsFlag },\n    positionals,\n  } = parseArgs({\n    args,\n    allowPositionals: true,\n    allowNegative: true,\n    options: {\n      'check-telemetry-errors': {\n        type: 'boolean',\n        default: false,\n      },\n    },\n  })\n\n  const version = positionals[0]\n  const datacenters = await getDatacenters(positionals[1])\n\n  if (!datacenters) {\n    throw new Error('DATACENTER argument is required')\n  }\n\n  // Skip all telemetry error checks for gov datacenter deployments\n  const shouldCheckTelemetryErrors = checkTelemetryErrorsFlag && !datacenters.every((dc) => dc === 'gov')\n\n  if (shouldCheckTelemetryErrors) {\n    // Make sure system is in a good state before deploying\n    const currentBrowserSdkVersionMajor = browserSdkVersion.split('.')[0]\n    await checkTelemetryErrors(datacenters, `${currentBrowserSdkVersionMajor}.*`)\n  }\n\n  const uploadPathTypes = toDatacenterUploadPathType(datacenters).join(',')\n\n  command`node ./scripts/deploy/deploy.ts prod ${version} ${uploadPathTypes}`.withLogs().run()\n  command`node ./scripts/deploy/upload-source-maps.ts ${version} ${uploadPathTypes}`.withLogs().run()\n\n  if (shouldCheckTelemetryErrors) {\n    await gateTelemetryErrors(datacenters)\n  }\n}\n\nasync function gateTelemetryErrors(datacenters: string[]): Promise<void> {\n  printLog(`Check telemetry errors for ${datacenters.join(',')} during ${GATE_DURATION / ONE_MINUTE_IN_SECOND} minutes`)\n\n  const startTime = Date.now()\n  const endTime = startTime + GATE_DURATION * 1000\n\n  while (Date.now() < endTime) {\n    await checkTelemetryErrors(datacenters, browserSdkVersion)\n    const elapsed = Math.round((Date.now() - startTime) / 1000 / 60)\n    printLog(`✓ Check completed (${elapsed}/${GATE_DURATION / ONE_MINUTE_IN_SECOND} minutes)`)\n    await timeout(GATE_INTERVAL * 1000)\n  }\n}\n\nasync function getDatacenters(datacenterGroup: string): Promise<string[]> {\n  const datacenters = await getAllDatacentersMetadata()\n\n  if (datacenterGroup === 'minor-dcs') {\n    return datacenters.filter((dc) => dc.type === DatacenterType.MINOR).map((dc) => dc.name)\n  }\n\n  if (datacenterGroup === 'private-regions') {\n    return datacenters.filter((dc) => dc.type === DatacenterType.PRIVATE).map((dc) => dc.name)\n  }\n\n  return datacenterGroup.split(',')\n}\n\nfunction toDatacenterUploadPathType(datacenters: string[]): string[] {\n  return datacenters.map((datacenter) => {\n    if (datacenter === 'gov') {\n      return 'root'\n    }\n\n    return datacenter\n  })\n}\n"
  },
  {
    "path": "scripts/deploy/deploy.spec.ts",
    "content": "import assert from 'node:assert/strict'\nimport { beforeEach, before, describe, it, mock } from 'node:test'\nimport path from 'node:path'\nimport type { CommandDetail } from './lib/testHelpers.ts'\nimport {\n  mockModule,\n  mockCommandImplementation,\n  replaceChunkHashes,\n  FAKE_AWS_ENV_CREDENTIALS,\n  FAKE_CHUNK_HASH,\n} from './lib/testHelpers.ts'\n\ninterface PullRequest {\n  ['number']: number\n}\n\ndescribe('deploy', () => {\n  const commandMock = mock.fn()\n  const fetchPRMock = mock.fn<() => Promise<PullRequest>>()\n  let deploy: (env: string, version: string, uploadPathTypes: string[]) => Promise<void>\n  const env = FAKE_AWS_ENV_CREDENTIALS\n\n  let commands: CommandDetail[]\n\n  function getS3Commands(): CommandDetail[] {\n    return commands.filter(({ command }) => command.includes('aws s3 cp')).map(replaceChunkHashes)\n  }\n\n  function getCloudfrontCommands(): CommandDetail[] {\n    return commands\n      .filter(({ command }) => command.includes('aws cloudfront create-invalidation'))\n      .map(replaceChunkHashes)\n  }\n\n  before(async () => {\n    await mockModule(path.resolve(import.meta.dirname, '../lib/command.ts'), { command: commandMock })\n    await mockModule(path.resolve(import.meta.dirname, '../lib/gitUtils.ts'), { fetchPR: fetchPRMock })\n\n    // This MUST be a dynamic import because that is the only way to ensure the\n    // import starts after the mock has been set up.\n    ;({ main: deploy } = await import('./deploy.ts'))\n  })\n\n  beforeEach(() => {\n    commands = mockCommandImplementation(commandMock)\n  })\n\n  it('should deploy root packages', async () => {\n    await deploy('prod', 'v6', ['root'])\n\n    assert.deepEqual(getS3Commands(), [\n      {\n        // Logs bundle\n        command:\n          'aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/logs/bundle/datadog-logs.js s3://browser-agent-artifacts-prod/datadog-logs-v6.js',\n        env,\n      },\n      {\n        // Profiler chunk\n        command: `aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum/bundle/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-prod/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        // RUM chunks: We don't suffix chunk names as they are referenced by the main bundle. Renaming them would require updates via Webpack, adding unnecessary complexity for minimal value.\n        command: `aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum/bundle/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-prod/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      // RUM bundle\n      {\n        command:\n          'aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum/bundle/datadog-rum.js s3://browser-agent-artifacts-prod/datadog-rum-v6.js',\n        env,\n      },\n      // RUM slim bundle\n      {\n        command:\n          'aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum-slim/bundle/datadog-rum-slim.js s3://browser-agent-artifacts-prod/datadog-rum-slim-v6.js',\n        env,\n      },\n    ])\n\n    assert.deepEqual(getCloudfrontCommands(), [\n      {\n        command: `aws cloudfront create-invalidation --distribution-id EGB08BYCT1DD9 --paths /datadog-logs-v6.js,/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js,/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js,/datadog-rum-v6.js,/datadog-rum-slim-v6.js`,\n        env,\n      },\n    ])\n  })\n\n  it('should deploy datacenter packages', async () => {\n    await deploy('prod', 'v6', ['us1'])\n\n    assert.deepEqual(getS3Commands(), [\n      {\n        command:\n          'aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/logs/bundle/datadog-logs.js s3://browser-agent-artifacts-prod/us1/v6/datadog-logs.js',\n        env,\n      },\n      // RUM Profiler Chunk\n      {\n        command: `aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum/bundle/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-prod/us1/v6/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        command: `aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum/bundle/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-prod/us1/v6/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        command:\n          'aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum/bundle/datadog-rum.js s3://browser-agent-artifacts-prod/us1/v6/datadog-rum.js',\n        env,\n      },\n      {\n        command:\n          'aws s3 cp --cache-control max-age=14400, s-maxage=60 packages/rum-slim/bundle/datadog-rum-slim.js s3://browser-agent-artifacts-prod/us1/v6/datadog-rum-slim.js',\n        env,\n      },\n    ])\n    assert.deepEqual(getCloudfrontCommands(), [\n      {\n        command: `aws cloudfront create-invalidation --distribution-id EGB08BYCT1DD9 --paths /us1/v6/datadog-logs.js,/us1/v6/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js,/us1/v6/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js,/us1/v6/datadog-rum.js,/us1/v6/datadog-rum-slim.js`,\n        env,\n      },\n    ])\n  })\n\n  it('should deploy staging packages', async () => {\n    await deploy('staging', 'staging', ['root'])\n\n    assert.deepEqual(getS3Commands(), [\n      {\n        command:\n          'aws s3 cp --cache-control max-age=900, s-maxage=60 packages/logs/bundle/datadog-logs.js s3://browser-agent-artifacts-staging/datadog-logs-staging.js',\n        env,\n      },\n      // RUM Profiler Chunk\n      {\n        command: `aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum/bundle/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-staging/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        command: `aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum/bundle/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-staging/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        command:\n          'aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum/bundle/datadog-rum.js s3://browser-agent-artifacts-staging/datadog-rum-staging.js',\n        env,\n      },\n      {\n        command:\n          'aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum-slim/bundle/datadog-rum-slim.js s3://browser-agent-artifacts-staging/datadog-rum-slim-staging.js',\n        env,\n      },\n    ])\n\n    assert.deepEqual(getCloudfrontCommands(), [\n      {\n        command: `aws cloudfront create-invalidation --distribution-id E2FP11ZSCFD3EU --paths /datadog-logs-staging.js,/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js,/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js,/datadog-rum-staging.js,/datadog-rum-slim-staging.js`,\n        env,\n      },\n    ])\n  })\n\n  it('should deploy PR packages', async () => {\n    // mock the PR number fetch\n    fetchPRMock.mock.mockImplementation(() => Promise.resolve({ ['number']: 123 }))\n\n    await deploy('staging', 'pull-request', ['pull-request'])\n\n    assert.deepEqual(getS3Commands(), [\n      {\n        command:\n          'aws s3 cp --cache-control max-age=900, s-maxage=60 packages/logs/bundle/datadog-logs.js s3://browser-agent-artifacts-staging/pull-request/123/datadog-logs.js',\n        env,\n      },\n      // RUM Profiler Chunk\n      {\n        command: `aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum/bundle/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-staging/pull-request/123/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        command: `aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum/bundle/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js s3://browser-agent-artifacts-staging/pull-request/123/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js`,\n        env,\n      },\n      {\n        command:\n          'aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum/bundle/datadog-rum.js s3://browser-agent-artifacts-staging/pull-request/123/datadog-rum.js',\n        env,\n      },\n      {\n        command:\n          'aws s3 cp --cache-control max-age=900, s-maxage=60 packages/rum-slim/bundle/datadog-rum-slim.js s3://browser-agent-artifacts-staging/pull-request/123/datadog-rum-slim.js',\n        env,\n      },\n    ])\n\n    assert.deepEqual(getCloudfrontCommands(), [\n      {\n        command: `aws cloudfront create-invalidation --distribution-id E2FP11ZSCFD3EU --paths /pull-request/123/datadog-logs.js,/pull-request/123/chunks/profiler-${FAKE_CHUNK_HASH}-datadog-rum.js,/pull-request/123/chunks/recorder-${FAKE_CHUNK_HASH}-datadog-rum.js,/pull-request/123/datadog-rum.js,/pull-request/123/datadog-rum-slim.js`,\n        env,\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "scripts/deploy/deploy.ts",
    "content": "import { printLog, runMain } from '../lib/executionUtils.ts'\nimport { fetchPR, LOCAL_BRANCH } from '../lib/gitUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { forEachFile } from '../lib/filesUtils.ts'\n\nimport {\n  buildRootUploadPath,\n  buildDatacenterUploadPath,\n  buildBundleFolder,\n  buildPullRequestUploadPath,\n  packages,\n} from './lib/deploymentUtils.ts'\n\ninterface AwsConfig {\n  accountId: number\n  bucketName: string\n  distributionId: string\n}\n\ninterface AwsCredentials {\n  AccessKeyId: string\n  SecretAccessKey: string\n  SessionToken: string\n}\n\ninterface EnvironmentVars extends Record<string, string> {\n  AWS_ACCESS_KEY_ID: string\n  AWS_SECRET_ACCESS_KEY: string\n  AWS_SESSION_TOKEN: string\n}\n\nconst ONE_MINUTE_IN_SECOND = 60\nconst ONE_HOUR_IN_SECOND = 60 * ONE_MINUTE_IN_SECOND\nconst AWS_CONFIG: Record<string, AwsConfig> = {\n  prod: {\n    accountId: 464622532012,\n    bucketName: 'browser-agent-artifacts-prod',\n    distributionId: 'EGB08BYCT1DD9',\n  },\n  staging: {\n    accountId: 727006795293,\n    bucketName: 'browser-agent-artifacts-staging',\n    distributionId: 'E2FP11ZSCFD3EU',\n  },\n}\n\n/**\n * Deploy SDK files to CDN\n * Usage:\n * node deploy.ts staging|prod staging|canary|pull-request|vXXX root,pull-request,us1,eu1,...\n */\nif (!process.env.NODE_TEST_CONTEXT) {\n  const env: string = process.argv[2]\n  const version: string = process.argv[3]\n  const uploadPathTypes: string[] = process.argv[4].split(',')\n  runMain(async () => {\n    await main(env, version, uploadPathTypes)\n  })\n}\n\nexport async function main(env: string, version: string, uploadPathTypes: string[]): Promise<void> {\n  const awsConfig = AWS_CONFIG[env]\n  const cloudfrontPathsToInvalidate: string[] = []\n  for (const { packageName } of packages) {\n    const pathsToInvalidate = await uploadPackage(awsConfig, packageName, version, uploadPathTypes)\n    cloudfrontPathsToInvalidate.push(...pathsToInvalidate)\n  }\n  invalidateCloudfront(awsConfig, cloudfrontPathsToInvalidate)\n}\n\nasync function uploadPackage(\n  awsConfig: AwsConfig,\n  packageName: string,\n  version: string,\n  uploadPathTypes: string[]\n): Promise<string[]> {\n  const cloudfrontPathsToInvalidate: string[] = []\n  const bundleFolder = buildBundleFolder(packageName)\n\n  for (const uploadPathType of uploadPathTypes) {\n    await forEachFile(bundleFolder, async (bundlePath: string) => {\n      if (!bundlePath.endsWith('.js')) {\n        return\n      }\n\n      const relativeBundlePath = bundlePath.replace(`${bundleFolder}/`, '')\n      const uploadPath = await generateUploadPath(uploadPathType, relativeBundlePath, version)\n\n      uploadToS3(awsConfig, bundlePath, uploadPath, version)\n      cloudfrontPathsToInvalidate.push(`/${uploadPath}`)\n    })\n  }\n\n  return cloudfrontPathsToInvalidate\n}\n\nasync function generateUploadPath(uploadPathType: string, filePath: string, version: string): Promise<string> {\n  let uploadPath: string\n\n  if (uploadPathType === 'pull-request') {\n    const pr = await fetchPR(LOCAL_BRANCH as string)\n    if (!pr) {\n      console.log('No pull requests found for the branch')\n      process.exit(0)\n    }\n    uploadPath = buildPullRequestUploadPath(filePath, pr.number.toString())\n  } else if (uploadPathType === 'root') {\n    uploadPath = buildRootUploadPath(filePath, version)\n  } else {\n    uploadPath = buildDatacenterUploadPath(uploadPathType, filePath, version)\n  }\n\n  return uploadPath\n}\n\nfunction uploadToS3(awsConfig: AwsConfig, bundlePath: string, uploadPath: string, version: string): void {\n  const accessToS3 = generateEnvironmentForRole(awsConfig.accountId, 'build-stable-browser-agent-artifacts-s3-write')\n\n  const browserCache =\n    version === 'staging' || version === 'canary' || version === 'pull-request'\n      ? 15 * ONE_MINUTE_IN_SECOND\n      : 4 * ONE_HOUR_IN_SECOND\n  const cacheControl = `max-age=${browserCache}, s-maxage=60`\n\n  printLog(`Upload ${bundlePath} to s3://${awsConfig.bucketName}/${uploadPath}`)\n  command`\n  aws s3 cp --cache-control ${cacheControl} ${bundlePath} s3://${awsConfig.bucketName}/${uploadPath}`\n    .withEnvironment(accessToS3)\n    .run()\n}\n\nfunction invalidateCloudfront(awsConfig: AwsConfig, pathsToInvalidate: string[]): void {\n  const accessToCloudfront = generateEnvironmentForRole(awsConfig.accountId, 'build-stable-cloudfront-invalidation')\n\n  printLog(`Trigger invalidation on ${awsConfig.distributionId} for: ${pathsToInvalidate.join(', ')}`)\n  command`\n    aws cloudfront create-invalidation --distribution-id ${awsConfig.distributionId} --paths ${pathsToInvalidate}`\n    .withEnvironment(accessToCloudfront)\n    .run()\n}\n\nfunction generateEnvironmentForRole(awsAccountId: number, roleName: string): EnvironmentVars {\n  const rawCredentials = command`\n  aws sts assume-role\n    --role-arn arn:aws:iam::${awsAccountId}:role/${roleName}\n    --role-session-name AWSCLI-Session`.run()\n  const credentials: AwsCredentials = JSON.parse(rawCredentials)['Credentials']\n  return {\n    AWS_ACCESS_KEY_ID: credentials.AccessKeyId,\n    AWS_SECRET_ACCESS_KEY: credentials.SecretAccessKey,\n    AWS_SESSION_TOKEN: credentials.SessionToken,\n  }\n}\n"
  },
  {
    "path": "scripts/deploy/lib/checkTelemetryErrors.spec.ts",
    "content": "import assert from 'node:assert/strict'\nimport path from 'node:path'\nimport type { Mock } from 'node:test'\nimport { afterEach, before, describe, it, mock } from 'node:test'\nimport { mockModule } from './testHelpers.ts'\nimport type { QueryResultBucket } from './checkTelemetryErrors.ts'\n\nconst FAKE_API_KEY = 'FAKE_API_KEY'\nconst FAKE_APPLICATION_KEY = 'FAKE_APPLICATION_KEY'\n\nconst NO_TELEMETRY_ERRORS_MOCK = [{ computes: { c0: 40 }, by: {} }]\nconst NO_TELEMETRY_ERRORS_ON_SPECIFIC_ORG_MOCK = [\n  { by: { '@org_id': 123456 }, computes: { c0: 22 } },\n  { by: { '@org_id': 789012 }, computes: { c0: 3 } },\n  { by: { '@org_id': 345678 }, computes: { c0: 3 } },\n]\nconst NO_TELEMETRY_ERROR_ON_SPECIFIC_MESSAGE_MOCK = [\n  { by: { 'issue.id': 'b4a4bf0c-e64a-11ef-aa16-da7ad0900002' }, computes: { c0: 16 } },\n  { by: { 'issue.id': '0aedaf4a-da09-11ed-baef-da7ad0900002' }, computes: { c0: 9 } },\n  { by: { 'issue.id': '118a6a40-1454-11f0-82c6-da7ad0900002' }, computes: { c0: 1 } },\n  { by: { 'issue.id': '144e312a-919a-11ef-8519-da7ad0900002' }, computes: { c0: 1 } },\n]\nconst TELEMETRY_ERRORS_MOCK = [{ computes: { c0: 10000 }, by: {} }]\nconst TELEMETRY_ERRORS_ON_SPECIFIC_ORG_MOCK = [\n  { by: { '@org_id': 123456 }, computes: { c0: 500 } },\n  { by: { '@org_id': 789012 }, computes: { c0: 3 } },\n  { by: { '@org_id': 345678 }, computes: { c0: 3 } },\n]\nconst TELEMETRY_ERROR_ON_SPECIFIC_MESSAGE_MOCK = [\n  { by: { 'issue.id': 'b4a4bf0c-e64a-11ef-aa16-da7ad0900002' }, computes: { c0: 1600 } },\n  { by: { 'issue.id': '0aedaf4a-da09-11ed-baef-da7ad0900002' }, computes: { c0: 9 } },\n  { by: { 'issue.id': '118a6a40-1454-11f0-82c6-da7ad0900002' }, computes: { c0: 1 } },\n  { by: { 'issue.id': '144e312a-919a-11ef-8519-da7ad0900002' }, computes: { c0: 1 } },\n]\n\ndescribe('check-telemetry-errors', () => {\n  let checkTelemetryErrors: (datacenters: string[], version: string) => Promise<void>\n  const fetchMock: Mock<typeof globalThis.fetch> = mock.fn()\n\n  function mockFetch(responseBuckets: [QueryResultBucket[], QueryResultBucket[], QueryResultBucket[]]): void {\n    for (let i = 0; i < 3; i++) {\n      fetchMock.mock.mockImplementationOnce(\n        () =>\n          Promise.resolve({\n            ok: true,\n            json: () =>\n              Promise.resolve({\n                data: {\n                  buckets: responseBuckets[i],\n                },\n              }),\n          } as unknown as Response),\n        i\n      )\n    }\n  }\n\n  before(async () => {\n    await mockModule(path.resolve(import.meta.dirname, '../../lib/secrets.ts'), {\n      getTelemetryOrgApiKey: () => FAKE_API_KEY,\n      getTelemetryOrgApplicationKey: () => FAKE_APPLICATION_KEY,\n    })\n\n    await mockModule('undici', { fetch: fetchMock })\n\n    await mockModule(path.resolve(import.meta.dirname, '../../lib/executionUtils.ts'), {\n      timeout: mock.fn(() => Promise.resolve()),\n    })\n\n    await mockModule(path.resolve(import.meta.dirname, '../../lib/datacenter.ts'), {\n      getDatacenterMetadata: () =>\n        Promise.resolve({\n          name: 'us1',\n          site: 'datadoghq.com',\n          type: 'major' as const,\n        }),\n    })\n\n    checkTelemetryErrors = (await import('./checkTelemetryErrors.ts')).checkTelemetryErrors\n  })\n\n  afterEach(() => {\n    fetchMock.mock.resetCalls()\n  })\n\n  it('should not throw an error if no telemetry errors are found for a given datacenter', async () => {\n    mockFetch([\n      NO_TELEMETRY_ERRORS_MOCK,\n      NO_TELEMETRY_ERRORS_ON_SPECIFIC_ORG_MOCK,\n      NO_TELEMETRY_ERROR_ON_SPECIFIC_MESSAGE_MOCK,\n    ])\n\n    await assert.doesNotReject(() => checkTelemetryErrors(['us1'], '6.2.1'))\n  })\n\n  it('should throw an error if telemetry errors are found for a given datacenter', async () => {\n    mockFetch([\n      TELEMETRY_ERRORS_MOCK,\n      NO_TELEMETRY_ERRORS_ON_SPECIFIC_ORG_MOCK,\n      NO_TELEMETRY_ERROR_ON_SPECIFIC_MESSAGE_MOCK,\n    ])\n    await assert.rejects(() => checkTelemetryErrors(['us1'], '6.2.1'), /Telemetry errors found in the last 5 minutes/)\n  })\n\n  it('should throw an error if telemetry errors on specific org are found for a given datacenter', async () => {\n    mockFetch([\n      NO_TELEMETRY_ERRORS_MOCK,\n      TELEMETRY_ERRORS_ON_SPECIFIC_ORG_MOCK,\n      NO_TELEMETRY_ERROR_ON_SPECIFIC_MESSAGE_MOCK,\n    ])\n\n    await assert.rejects(\n      () => checkTelemetryErrors(['us1'], '6.2.1'),\n      /Telemetry errors on specific org found in the last 5 minutes/\n    )\n  })\n\n  it('should throw an error if telemetry errors on specific message are found for a given datacenter', async () => {\n    mockFetch([\n      NO_TELEMETRY_ERRORS_MOCK,\n      NO_TELEMETRY_ERRORS_ON_SPECIFIC_ORG_MOCK,\n      TELEMETRY_ERROR_ON_SPECIFIC_MESSAGE_MOCK,\n    ])\n\n    await assert.rejects(\n      () => checkTelemetryErrors(['us1'], '6.2.1'),\n      /Telemetry error on specific message found in the last 5 minutes/\n    )\n  })\n\n  it('should throw an error if the API returns an unexpected response format', async () => {\n    // Mock first API call with invalid response (missing data.buckets)\n    fetchMock.mock.mockImplementationOnce(\n      () =>\n        Promise.resolve({\n          ok: true,\n          json: () =>\n            Promise.resolve({\n              error: 'Something went wrong',\n            }),\n        } as unknown as Response),\n      0\n    )\n\n    await assert.rejects(() => checkTelemetryErrors(['us1'], '6.2.1'), /Unexpected response from the API/)\n  })\n\n  it('should throw an error if buckets have invalid structure', async () => {\n    // Mock first API call with invalid bucket structure (missing computes.c0)\n    fetchMock.mock.mockImplementationOnce(\n      () =>\n        Promise.resolve({\n          ok: true,\n          json: () =>\n            Promise.resolve({\n              data: {\n                buckets: [{ by: {}, computes: {} }], // Missing c0\n              },\n            }),\n        } as unknown as Response),\n      0\n    )\n\n    await assert.rejects(() => checkTelemetryErrors(['us1'], '6.2.1'), /Unexpected response from the API/)\n  })\n})\n"
  },
  {
    "path": "scripts/deploy/lib/checkTelemetryErrors.ts",
    "content": "/**\n * Check telemetry errors\n */\nimport { Agent, fetch, type Response } from 'undici'\nimport { printLog, timeout, createFetchError } from '../../lib/executionUtils.ts'\nimport { getTelemetryOrgApiKey, getTelemetryOrgApplicationKey } from '../../lib/secrets.ts'\nimport { getDatacenterMetadata } from '../../lib/datacenter.ts'\n\nconst TIME_WINDOW_IN_MINUTES = 5\n// Rate limit: 2 requests per 10 seconds. Wait 6 seconds between requests to be safe.\nconst RATE_LIMIT_DELAY_MS = 6000\nconst MAX_RETRIES = 3\n\n/**\n * Dedicated HTTP agent for telemetry API calls.\n * This ensures a clean connection pool isolated from other network operations,\n * preventing ECONNRESET errors from stale or conflicting connections.\n */\nfunction createTelemetryAgent(): Agent {\n  return new Agent({\n    connections: 10, // Limit concurrent connections per host\n    keepAliveTimeout: 10000, // 10s keepalive\n    keepAliveMaxTimeout: 30000, // 30s max keepalive\n  })\n}\n\nfunction getQueries(version: string): Query[] {\n  const query = `source:browser status:error version:${version}`\n\n  return [\n    {\n      name: 'Telemetry errors',\n      query,\n      threshold: 300,\n    },\n    {\n      name: 'Telemetry errors on specific org',\n      query,\n      groupBy: '@org_id',\n      threshold: 100,\n    },\n    {\n      name: 'Telemetry error on specific message',\n      query,\n      groupBy: 'issue.id',\n      threshold: 100,\n    },\n  ]\n}\n\n/**\n * Check telemetry errors for given datacenters\n *\n * @param datacenters - Array of datacenter names to check\n * @param version - Browser SDK version to check errors for\n */\nexport async function checkTelemetryErrors(datacenters: string[], version: string): Promise<void> {\n  const queries = getQueries(version)\n\n  // Create a fresh HTTP agent for this batch of telemetry checks\n  const agent = createTelemetryAgent()\n\n  try {\n    // Check all datacenters in parallel since rate limits are per datacenter\n    await Promise.all(datacenters.map((datacenter) => checkDatacenterTelemetryErrors(datacenter, queries, agent)))\n  } finally {\n    // Always close the agent to release resources\n    await agent.close()\n  }\n}\n\nasync function checkDatacenterTelemetryErrors(datacenter: string, queries: Query[], agent: Agent): Promise<void> {\n  const datacenterMetadata = await getDatacenterMetadata(datacenter)\n\n  if (!datacenterMetadata?.site) {\n    printLog(`No site is configured for datacenter ${datacenter}. skipping...`)\n    return\n  }\n\n  const site = datacenterMetadata.site\n\n  const apiKey = getTelemetryOrgApiKey(site)\n  const applicationKey = getTelemetryOrgApplicationKey(site)\n\n  if (!apiKey || !applicationKey) {\n    printLog(`No API key or application key found for ${site}, skipping...`)\n    return\n  }\n\n  for (let i = 0; i < queries.length; i++) {\n    const query = queries[i]\n    const buckets = await queryLogsApi(site, apiKey, applicationKey, query, agent)\n\n    // buckets are sorted by count, so we only need to check the first one\n    if (buckets[0]?.computes?.c0 > query.threshold) {\n      throw new Error(`${query.name} found in the last ${TIME_WINDOW_IN_MINUTES} minutes,\nsee ${computeLogsLink(site, query)}`)\n    }\n\n    // Skip rate limit delay after last query\n    if (i < queries.length - 1) {\n      await timeout(RATE_LIMIT_DELAY_MS)\n    }\n  }\n}\n\nasync function queryLogsApi(\n  site: string,\n  apiKey: string,\n  applicationKey: string,\n  query: Query,\n  agent: Agent,\n  attempt: number = 1\n): Promise<QueryResultBucket[]> {\n  const response = await fetch(`https://api.${site}/api/v2/logs/analytics/aggregate`, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      'DD-API-KEY': apiKey,\n      'DD-APPLICATION-KEY': applicationKey,\n    },\n    body: JSON.stringify({\n      compute: [\n        {\n          aggregation: 'count',\n        },\n      ],\n      ...(query.groupBy\n        ? {\n            group_by: [\n              {\n                facet: query.groupBy,\n                sort: {\n                  type: 'measure',\n                  aggregation: 'count',\n                },\n              },\n            ],\n          }\n        : {}),\n      filter: {\n        from: `now-${TIME_WINDOW_IN_MINUTES}m`,\n        to: 'now',\n        query: query.query,\n      },\n    }),\n    // Use dedicated agent to avoid connection pool conflicts.\n    dispatcher: agent,\n  })\n\n  if (shouldRetry(response, attempt)) {\n    printLog(\n      `503 Service Unavailable, retrying in ${RATE_LIMIT_DELAY_MS / 1000}s (attempt ${attempt}/${MAX_RETRIES})...`\n    )\n    await timeout(RATE_LIMIT_DELAY_MS)\n    return queryLogsApi(site, apiKey, applicationKey, query, agent, attempt + 1)\n  }\n\n  if (!response.ok) {\n    throw await createFetchError(response)\n  }\n\n  const data = (await response.json()) as QueryResult\n\n  if (!isValidData(data)) {\n    throw new Error(`Unexpected response from the API: ${JSON.stringify(data)}`)\n  }\n\n  return data.data.buckets\n}\n\nfunction shouldRetry(response: Response, attempt: number): boolean {\n  return response.status === 503 && attempt < MAX_RETRIES\n}\n\nfunction isValidData(data: QueryResult): boolean {\n  return (\n    data?.data &&\n    Array.isArray(data.data.buckets) &&\n    data.data.buckets.every((bucket) => bucket.computes && typeof bucket.computes.c0 === 'number')\n  )\n}\n\nfunction computeLogsLink(site: string, query: Query): string {\n  const now = Date.now()\n  const timeWindowAgo = now - TIME_WINDOW_IN_MINUTES * 60 * 1000\n\n  const queryParams = new URLSearchParams({\n    query: query.query,\n    ...(query.groupBy\n      ? {\n          agg_q: query.groupBy,\n          agg_t: 'count',\n          viz: 'toplist',\n        }\n      : {}),\n    from_ts: `${timeWindowAgo}`,\n    to_ts: `${now}`,\n  })\n\n  return `https://${computeTelemetryOrgDomain(site)}/logs?${queryParams.toString()}`\n}\n\nfunction computeTelemetryOrgDomain(site: string): string {\n  switch (site) {\n    case 'datadoghq.com':\n    case 'datadoghq.eu':\n      return `dd-rum-telemetry.${site}`\n    default:\n      return site\n  }\n}\n\ninterface Query {\n  name: string\n  query: string\n  groupBy?: string\n  threshold: number\n}\n\ninterface QueryResult {\n  data: {\n    buckets: QueryResultBucket[]\n  }\n}\n\nexport interface QueryResultBucket {\n  by: { [key: string]: number | string }\n  computes: { c0: number }\n}\n"
  },
  {
    "path": "scripts/deploy/lib/deploymentUtils.ts",
    "content": "interface Package {\n  packageName: string\n  service: string\n}\n\nexport const packages: Package[] = [\n  { packageName: 'logs', service: 'browser-logs-sdk' },\n  { packageName: 'rum', service: 'browser-rum-sdk' },\n  { packageName: 'rum-slim', service: 'browser-rum-sdk' },\n]\n\n// ex: datadog-rum-v4.js, chunks/recorder-8d8a8dfab6958424038f-datadog-rum.js\nexport const buildRootUploadPath = (filePath: string, version: string): string => {\n  // We don't suffix chunk names as they are referenced by the main bundle. Renaming them would require updates via Webpack, adding unnecessary complexity for minimal value.\n  if (filePath.includes('chunks')) {\n    return filePath\n  }\n\n  const [basePath, ...extensions] = filePath.split('.')\n  const ext = extensions.join('.') // allow to handle multiple extensions like `.js.map`\n\n  return `${basePath}-${version}.${ext}`\n}\n\n// ex: us1/v4/datadog-rum.js, eu1/v4/chunks/recorder-8d8a8dfab6958424038f-datadog-rum.js\nexport const buildDatacenterUploadPath = (datacenter: string, filePath: string, version: string): string =>\n  `${datacenter}/${version}/${filePath}`\n\n// ex: pull-request/2781/datadog-rum.js, pull-request/2781/chunks/recorder-8d8a8dfab6958424038f-datadog-rum.js\nexport const buildPullRequestUploadPath = (filePath: string, version: string): string =>\n  `pull-request/${version}/${filePath}`\n\n// ex: packages/rum/bundle\nexport const buildBundleFolder = (packageName: string): string => `packages/${packageName}/bundle`\n"
  },
  {
    "path": "scripts/deploy/lib/testHelpers.ts",
    "content": "import { mock, type Mock } from 'node:test'\n\nexport async function mockModule(modulePath: string, mockObject: Record<string, any>): Promise<void> {\n  const moduleExports = await import(modulePath)\n\n  // If the module only has named exports (no default export)\n  if (!moduleExports.default) {\n    mock.module(modulePath, {\n      namedExports: {\n        ...moduleExports,\n        ...mockObject,\n      },\n    })\n  } else {\n    // If the module has a default export\n    const { default: defaultExport, ...namedExports } = moduleExports\n\n    mock.module(modulePath, {\n      defaultExport,\n      namedExports: {\n        ...namedExports,\n        ...mockObject,\n      },\n    })\n  }\n}\n\nexport const FAKE_AWS_ENV_CREDENTIALS = {\n  AWS_ACCESS_KEY_ID: 'FAKEACCESSKEYID123456',\n  AWS_SECRET_ACCESS_KEY: 'FAKESECRETACCESSKEY123456',\n  AWS_SESSION_TOKEN: 'FAKESESSIONTOKEN123456',\n} as const\n\nexport const FAKE_CHUNK_HASH = 'FAKEHASHd7628536637b074ddc3b'\nexport const FAKE_RUNTIME_METADATA_SERVICE_TOKEN = 'FAKE_RUNTIME_METADATA_SERVICE_TOKEN'\n\nexport interface CommandDetail {\n  command: string\n  env?: Record<string, string>\n}\n\ninterface CommandChain {\n  withInput: () => CommandChain\n  withEnvironment: (env: Record<string, string>) => CommandChain\n  withCurrentWorkingDirectory: () => CommandChain\n  withLogs: () => CommandChain\n  run: () => string | undefined\n}\n\nexport function mockCommandImplementation(mockFn: Mock<(...args: any[]) => void>): CommandDetail[] {\n  const commands: CommandDetail[] = []\n\n  mockFn.mock.mockImplementation((template: TemplateStringsArray, ...values: any[]): CommandChain => {\n    const command = rebuildStringTemplate(template, ...values)\n    const commandDetail: CommandDetail = { command }\n\n    const result: CommandChain = {\n      withInput: () => result,\n      withEnvironment: (newEnv: Record<string, string>) => {\n        commandDetail.env = newEnv\n        return result\n      },\n      withCurrentWorkingDirectory: () => result,\n      withLogs: () => result,\n      run(): string | undefined {\n        if (command.startsWith('aws sts assume-role')) {\n          return JSON.stringify({\n            Credentials: {\n              AccessKeyId: FAKE_AWS_ENV_CREDENTIALS.AWS_ACCESS_KEY_ID,\n              SecretAccessKey: FAKE_AWS_ENV_CREDENTIALS.AWS_SECRET_ACCESS_KEY,\n              SessionToken: FAKE_AWS_ENV_CREDENTIALS.AWS_SESSION_TOKEN,\n            },\n          })\n        }\n\n        // don't push command details for the above mock commands\n        commands.push(commandDetail)\n      },\n    }\n    return result\n  })\n\n  return commands\n}\n\nexport const MOCK_DATACENTER_RESPONSE = [\n  { name: 'ap1.prod.dog', site: 'ap1.datadoghq.com' },\n  { name: 'ap2.prod.dog', site: 'ap2.datadoghq.com' },\n  { name: 'eu1.prod.dog', site: 'datadoghq.eu' },\n  { name: 'us1.prod.dog', site: 'datadoghq.com' },\n  { name: 'us3.prod.dog', site: 'us3.datadoghq.com' },\n  { name: 'us5.prod.dog', site: 'us5.datadoghq.com' },\n  { name: 'prtest00.prod.dog', site: 'prtest00.datadoghq.com' },\n  { name: 'prtest01.prod.dog', site: 'prtest01.datadoghq.com' },\n]\n\ntype FetchMockHandler = (url: string, options?: RequestInit) => Promise<Response> | undefined\n\n/**\n * Creates a mock Response object for testing fetch calls.\n *\n * @param options - Configuration options for the mock response\n * @param options.status - HTTP status code (default: 200)\n * @param options.json - JSON data to return (default: {})\n * @returns A mock Response object\n */\nexport function createMockResponse({ status = 200, json = {} }: { status?: number; json?: any } = {}): Response {\n  return {\n    ok: status < 300,\n    status,\n    json: () => Promise.resolve(json),\n    text: () => Promise.resolve(JSON.stringify(json)),\n  } as unknown as Response\n}\n\n/**\n * Configure a fetchHandlingError mock with datacenter API support.\n * Can be extended with an additional handler for test-specific API calls.\n *\n * @param fetchHandlingErrorMock - The mock function to configure\n * @param additionalHandler - Optional custom handler that runs before default handlers.\n * Should return a Response promise if it handles the URL, or undefined to let default handlers try.\n * @example\n * // Simple usage with just datacenter mocks\n * mockFetchHandlingError(fetchMock)\n * @example\n * // Extended with telemetry API mock\n * mockFetchHandlingError(fetchMock, (url) => {\n *   if (url.includes('api.datadoghq.com')) {\n *     return Promise.resolve({ json: () => Promise.resolve({ data: [] }) } as Response)\n *   }\n * })\n */\nexport function mockFetchHandlingError(\n  fetchHandlingErrorMock: Mock<(...args: any[]) => any>,\n  additionalHandler?: FetchMockHandler\n): void {\n  fetchHandlingErrorMock.mock.mockImplementation((url: string, options?: RequestInit) => {\n    // Try additional handler first (for test-specific mocks)\n    if (additionalHandler) {\n      const result = additionalHandler(url, options)\n      if (result) {\n        return result\n      }\n    }\n\n    // Vault token request\n    if (url.includes('/v1/identity/oidc/token/runtime-metadata-service')) {\n      return Promise.resolve(\n        createMockResponse({\n          json: {\n            data: {\n              token: FAKE_RUNTIME_METADATA_SERVICE_TOKEN,\n            },\n          },\n        })\n      )\n    }\n\n    // Datacenters request\n    if (url.includes('runtime-metadata-service')) {\n      return Promise.resolve(createMockResponse({ json: { datacenters: MOCK_DATACENTER_RESPONSE } }))\n    }\n\n    // Default response\n    return Promise.resolve(createMockResponse())\n  })\n}\n\nfunction rebuildStringTemplate(template: TemplateStringsArray, ...values: any[]): string {\n  const combinedString = template.reduce((acc, part, i) => acc + part + (values[i] || ''), '')\n  const normalizedString = combinedString.replace(/\\s+/g, ' ').trim()\n  return normalizedString\n}\n\nexport function replaceChunkHashes(commandDetail: CommandDetail): CommandDetail {\n  return {\n    ...commandDetail,\n    command: commandDetail.command.replace(/-[a-f0-9]+-datadog-rum/g, `-${FAKE_CHUNK_HASH}-datadog-rum`),\n  }\n}\n"
  },
  {
    "path": "scripts/deploy/publish-developer-extension.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport chromeWebstoreUpload from 'chrome-webstore-upload'\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport {\n  getChromeWebStoreClientId,\n  getChromeWebStoreClientSecret,\n  getChromeWebStoreRefreshToken,\n} from '../lib/secrets.ts'\n\nconst ZIP_FILE_NAME = 'developer-extension.zip'\n\nrunMain(async () => {\n  printLog('Building the project')\n  command`yarn build`.withEnvironment({ BUILD_MODE: 'release' }).run()\n\n  printLog('Zipping extension files')\n  const zipPath = path.resolve(ZIP_FILE_NAME)\n  command`zip -r ${zipPath} .`.withCurrentWorkingDirectory('developer-extension/dist/chrome-mv3').run()\n\n  printLog('Publish Developer extension')\n  await uploadAndPublish()\n\n  printLog('Developer extension published.')\n})\n\nasync function uploadAndPublish(): Promise<void> {\n  const zipFile = fs.createReadStream(ZIP_FILE_NAME)\n  const api = chromeWebstoreUpload({\n    extensionId: 'boceobohkgenpcpogecpjlnmnfbdigda',\n    clientId: getChromeWebStoreClientId(),\n    clientSecret: getChromeWebStoreClientSecret(),\n    refreshToken: getChromeWebStoreRefreshToken(),\n  })\n\n  try {\n    printLog('Fetching the token')\n    const token = await api.fetchToken()\n\n    printLog('Uploading the archive')\n    await api.uploadExisting(zipFile, token)\n\n    printLog('Publishing')\n    await api.publish()\n  } catch (error) {\n    const body = (error as any)?.response?.body\n\n    if (body) {\n      throw body\n    }\n    throw error\n  }\n}\n"
  },
  {
    "path": "scripts/deploy/publish-npm.ts",
    "content": "import { parseArgs } from 'node:util'\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { getNpmToken } from '../lib/secrets.ts'\n\nrunMain(() => {\n  const {\n    values: { 'dry-run': dryRun },\n  } = parseArgs({\n    options: {\n      'dry-run': { type: 'boolean', default: false },\n    },\n  })\n\n  printLog(dryRun ? 'Publishing (dry run)' : 'Publishing')\n  command`yarn workspaces foreach --verbose --all --topological --no-private npm publish --tolerate-republish --access public ${dryRun ? ['--dry-run'] : []}`\n    .withEnvironment({\n      YARN_NPM_AUTH_TOKEN: dryRun ? '' : getNpmToken(),\n      BUILD_MODE: 'release',\n    })\n    .withLogs()\n    .run()\n})\n"
  },
  {
    "path": "scripts/deploy/upload-source-maps.spec.ts",
    "content": "import assert from 'node:assert/strict'\nimport path from 'node:path'\nimport { beforeEach, before, describe, it, mock, afterEach } from 'node:test'\nimport type { Datacenter } from '../lib/datacenter.ts'\nimport { mockModule, mockCommandImplementation, replaceChunkHashes, mockFetchHandlingError } from './lib/testHelpers.ts'\n\nconst FAKE_API_KEY = 'FAKE_API_KEY'\nconst ORG2_API_KEY = 'ORG2_API_KEY'\nconst ENV_STAGING = {\n  DATADOG_API_KEY: FAKE_API_KEY,\n  DATADOG_SITE: 'datad0g.com',\n}\nconst ENV_PROD = {\n  DATADOG_API_KEY: FAKE_API_KEY,\n  DATADOG_SITE: 'datadoghq.com',\n}\nconst ENV_ORG2_PROD = {\n  DATADOG_API_KEY: ORG2_API_KEY,\n  DATADOG_SITE: 'datadoghq.com',\n}\n\ninterface CommandDetail {\n  command: string\n  env?: Record<string, string>\n}\n\ndescribe('upload-source-maps', () => {\n  const commandMock = mock.fn()\n  const fetchHandlingErrorMock = mock.fn()\n  let commands: CommandDetail[]\n\n  let uploadSourceMaps: (version: string, uploadPathTypes: string[]) => Promise<void>\n  let getAllDatacentersMetadata: () => Promise<Datacenter[]>\n\n  function getSourceMapCommands(): CommandDetail[] {\n    return commands.filter(\n      ({ command, env }) => command.includes('datadog-ci sourcemaps') && env?.DATADOG_API_KEY === FAKE_API_KEY\n    )\n  }\n\n  function getOrg2SourceMapCommands(): CommandDetail[] {\n    return commands.filter(\n      ({ command, env }) => command.includes('datadog-ci sourcemaps') && env?.DATADOG_API_KEY === ORG2_API_KEY\n    )\n  }\n\n  function getFileRenamingCommands(): CommandDetail[] {\n    return commands.filter(({ command }) => command.includes('mv')).map(replaceChunkHashes)\n  }\n\n  before(async () => {\n    mockFetchHandlingError(fetchHandlingErrorMock)\n    await mockModule(path.resolve(import.meta.dirname, '../lib/command.ts'), { command: commandMock })\n    await mockModule(path.resolve(import.meta.dirname, '../lib/executionUtils.ts'), {\n      fetchHandlingError: fetchHandlingErrorMock,\n    })\n    await mockModule(path.resolve(import.meta.dirname, '../lib/secrets.ts'), {\n      getTelemetryOrgApiKey: () => FAKE_API_KEY,\n      getOrg2ApiKey: () => ORG2_API_KEY,\n    })\n\n    // These MUST be dynamic imports because that is the only way to ensure the\n    // import starts after the mock has been set up.\n    const uploadModule = await import('./upload-source-maps.ts')\n    uploadSourceMaps = uploadModule.main\n    const datacenterModule = await import('../lib/datacenter.ts')\n    getAllDatacentersMetadata = datacenterModule.getAllDatacentersMetadata\n  })\n\n  beforeEach(() => {\n    commands = mockCommandImplementation(commandMock)\n  })\n\n  afterEach(() => {\n    mock.restoreAll()\n  })\n\n  async function forEachDatacenter(callback: (site: string) => void): Promise<void> {\n    const datacenters = await getAllDatacentersMetadata()\n    for (const datacenter of datacenters) {\n      callback(datacenter.site)\n    }\n  }\n\n  it('should upload root packages source maps', async () => {\n    await uploadSourceMaps('v6', ['root'])\n\n    await forEachDatacenter((site) => {\n      const commandsByDatacenter = commands.filter(\n        ({ env }) => env?.DATADOG_SITE === site && env?.DATADOG_API_KEY === FAKE_API_KEY\n      )\n      const env = { DATADOG_API_KEY: FAKE_API_KEY, DATADOG_SITE: site }\n\n      // rename the files with the version suffix\n      assert.deepEqual(getFileRenamingCommands(), [\n        {\n          command: 'mv packages/logs/bundle/datadog-logs.js packages/logs/bundle/datadog-logs-v6.js',\n        },\n        {\n          command: 'mv packages/logs/bundle/datadog-logs.js.map packages/logs/bundle/datadog-logs-v6.js.map',\n        },\n        {\n          command: 'mv packages/rum/bundle/datadog-rum.js packages/rum/bundle/datadog-rum-v6.js',\n        },\n        {\n          command: 'mv packages/rum/bundle/datadog-rum.js.map packages/rum/bundle/datadog-rum-v6.js.map',\n        },\n        {\n          command: 'mv packages/rum-slim/bundle/datadog-rum-slim.js packages/rum-slim/bundle/datadog-rum-slim-v6.js',\n        },\n        {\n          command:\n            'mv packages/rum-slim/bundle/datadog-rum-slim.js.map packages/rum-slim/bundle/datadog-rum-slim-v6.js.map',\n        },\n      ])\n\n      // upload the source maps\n      assert.deepEqual(commandsByDatacenter, [\n        {\n          command:\n            'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n          env,\n        },\n        {\n          command:\n            'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n          env,\n        },\n        {\n          command:\n            'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n          env,\n        },\n      ])\n    })\n\n    // upload the source maps to org2\n    assert.deepEqual(getOrg2SourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n    ])\n  })\n\n  it('should upload datacenter packages source maps', async () => {\n    await uploadSourceMaps('v6', ['us1'])\n\n    assert.deepEqual(getSourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix /us1/v6 --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix /us1/v6 --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix /us1/v6 --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n    ])\n\n    assert.deepEqual(getOrg2SourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net/us1/v6 --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net/us1/v6 --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net/us1/v6 --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n    ])\n  })\n\n  it('should upload staging packages source maps', async () => {\n    await uploadSourceMaps('staging', ['root'])\n\n    // rename the files with the version suffix\n    assert.deepEqual(getFileRenamingCommands(), [\n      {\n        command: 'mv packages/logs/bundle/datadog-logs.js packages/logs/bundle/datadog-logs-staging.js',\n      },\n      {\n        command: 'mv packages/logs/bundle/datadog-logs.js.map packages/logs/bundle/datadog-logs-staging.js.map',\n      },\n      {\n        command: 'mv packages/rum/bundle/datadog-rum.js packages/rum/bundle/datadog-rum-staging.js',\n      },\n      {\n        command: 'mv packages/rum/bundle/datadog-rum.js.map packages/rum/bundle/datadog-rum-staging.js.map',\n      },\n      {\n        command: 'mv packages/rum-slim/bundle/datadog-rum-slim.js packages/rum-slim/bundle/datadog-rum-slim-staging.js',\n      },\n      {\n        command:\n          'mv packages/rum-slim/bundle/datadog-rum-slim.js.map packages/rum-slim/bundle/datadog-rum-slim-staging.js.map',\n      },\n    ])\n\n    // upload the source maps\n    assert.deepEqual(getSourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_STAGING,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_STAGING,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_STAGING,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n    ])\n\n    assert.deepEqual(getOrg2SourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n    ])\n  })\n\n  it('should upload canary packages source maps', async () => {\n    await uploadSourceMaps('canary', ['root'])\n\n    // rename the files with the version suffix\n    assert.deepEqual(getFileRenamingCommands(), [\n      {\n        command: 'mv packages/logs/bundle/datadog-logs.js packages/logs/bundle/datadog-logs-canary.js',\n      },\n      {\n        command: 'mv packages/logs/bundle/datadog-logs.js.map packages/logs/bundle/datadog-logs-canary.js.map',\n      },\n      {\n        command: 'mv packages/rum/bundle/datadog-rum.js packages/rum/bundle/datadog-rum-canary.js',\n      },\n      {\n        command: 'mv packages/rum/bundle/datadog-rum.js.map packages/rum/bundle/datadog-rum-canary.js.map',\n      },\n      {\n        command: 'mv packages/rum-slim/bundle/datadog-rum-slim.js packages/rum-slim/bundle/datadog-rum-slim-canary.js',\n      },\n      {\n        command:\n          'mv packages/rum-slim/bundle/datadog-rum-slim.js.map packages/rum-slim/bundle/datadog-rum-slim-canary.js.map',\n      },\n    ])\n\n    // upload the source maps only to datadoghq.com\n    assert.deepEqual(getSourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n    ])\n\n    assert.deepEqual(getOrg2SourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n    ])\n  })\n\n  it('should upload versioned canary packages source maps (e.g. v7-canary)', async () => {\n    await uploadSourceMaps('v7-canary', ['root'])\n\n    // rename the files with the version suffix\n    assert.deepEqual(getFileRenamingCommands(), [\n      {\n        command: 'mv packages/logs/bundle/datadog-logs.js packages/logs/bundle/datadog-logs-v7-canary.js',\n      },\n      {\n        command: 'mv packages/logs/bundle/datadog-logs.js.map packages/logs/bundle/datadog-logs-v7-canary.js.map',\n      },\n      {\n        command: 'mv packages/rum/bundle/datadog-rum.js packages/rum/bundle/datadog-rum-v7-canary.js',\n      },\n      {\n        command: 'mv packages/rum/bundle/datadog-rum.js.map packages/rum/bundle/datadog-rum-v7-canary.js.map',\n      },\n      {\n        command:\n          'mv packages/rum-slim/bundle/datadog-rum-slim.js packages/rum-slim/bundle/datadog-rum-slim-v7-canary.js',\n      },\n      {\n        command:\n          'mv packages/rum-slim/bundle/datadog-rum-slim.js.map packages/rum-slim/bundle/datadog-rum-slim-v7-canary.js.map',\n      },\n    ])\n\n    // upload the source maps only to datadoghq.com (same as plain 'canary')\n    assert.deepEqual(getSourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix / --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_PROD,\n      },\n    ])\n\n    assert.deepEqual(getOrg2SourceMapCommands(), [\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/logs/bundle --service browser-logs-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-logs/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n      {\n        command:\n          'datadog-ci sourcemaps upload packages/rum-slim/bundle --service browser-rum-sdk --release-version dev --minified-path-prefix https://d20xtzwzcl0ceb.cloudfront.net --project-path @datadog/browser-rum-slim/ --repository-url https://www.github.com/datadog/browser-sdk',\n        env: ENV_ORG2_PROD,\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "scripts/deploy/upload-source-maps.ts",
    "content": "import path from 'node:path'\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { getBuildEnvValue } from '../lib/buildEnv.ts'\nimport { getTelemetryOrgApiKey, getOrg2ApiKey } from '../lib/secrets.ts'\nimport { getAllDatacentersMetadata, getDatacenterMetadata } from '../lib/datacenter.ts'\nimport { forEachFile } from '../lib/filesUtils.ts'\nimport { buildRootUploadPath, buildDatacenterUploadPath, buildBundleFolder, packages } from './lib/deploymentUtils.ts'\n\n/**\n * Upload source maps to datadog\n * Usage:\n * BUILD_MODE=canary|release node upload-source-maps.ts staging|canary|vXXX root,us1,eu1,...\n */\n\nasync function getSitesByVersion(version: string): Promise<string[]> {\n  if (version === 'staging') {\n    return ['datad0g.com', 'datadoghq.com']\n  }\n  if (version.endsWith('canary')) {\n    return ['datadoghq.com']\n  }\n  return (await getAllDatacentersMetadata()).map((dc) => dc.site)\n}\n\nif (!process.env.NODE_TEST_CONTEXT) {\n  const version = process.argv[2]\n  const uploadPathTypes = process.argv[3].split(',')\n\n  runMain(async () => {\n    await main(version, uploadPathTypes)\n  })\n}\n\nexport async function main(version: string, uploadPathTypes: string[]): Promise<void> {\n  for (const { packageName, service } of packages) {\n    await uploadSourceMaps(packageName, service, version, uploadPathTypes)\n  }\n  printLog('Source maps upload done.')\n}\n\nasync function uploadSourceMaps(\n  packageName: string,\n  service: string,\n  version: string,\n  uploadPathTypes: string[]\n): Promise<void> {\n  const bundleFolder = buildBundleFolder(packageName)\n\n  for (const uploadPathType of uploadPathTypes) {\n    let sites: string[]\n    let uploadPath: string\n    if (uploadPathType === 'root') {\n      sites = await getSitesByVersion(version)\n      uploadPath = buildRootUploadPath(packageName, version)\n      await renameFilesWithVersionSuffix(bundleFolder, version)\n    } else {\n      const datacenterMetadata = await getDatacenterMetadata(uploadPathType)\n\n      if (!datacenterMetadata) {\n        throw new Error(`No datacenter metadata found for ${uploadPathType}`)\n      }\n\n      sites = [datacenterMetadata.site]\n      uploadPath = buildDatacenterUploadPath(uploadPathType, packageName, version)\n    }\n    const prefix = path.dirname(`/${uploadPath}`)\n    uploadToDatadog(packageName, service, prefix, bundleFolder, sites)\n    uploadToOrg2(packageName, service, prefix, bundleFolder)\n  }\n}\n\nasync function renameFilesWithVersionSuffix(bundleFolder: string, version: string): Promise<void> {\n  // The datadog-ci CLI is taking a directory as an argument. It will scan every source map files in\n  // it and upload those along with the minified bundle. The file names must match the one from the\n  // CDN, thus we need to rename the bundles with the right suffix.\n  await forEachFile(bundleFolder, (bundlePath: string) => {\n    const uploadPath = buildRootUploadPath(bundlePath, version)\n\n    if (bundlePath === uploadPath) {\n      return\n    }\n\n    console.log(`Renaming ${bundlePath} to ${uploadPath}`)\n    command`mv ${bundlePath} ${uploadPath}`.run()\n  })\n}\n\nconst ORG2_CLOUDFRONT_BASE_URL = 'https://d20xtzwzcl0ceb.cloudfront.net'\n\nfunction uploadToOrg2(packageName: string, service: string, prefix: string, bundleFolder: string): void {\n  const apiKey = getOrg2ApiKey()\n  const org2Prefix = `${ORG2_CLOUDFRONT_BASE_URL}${prefix === '/' ? '' : prefix}`\n\n  printLog(`Uploading ${packageName} source maps with prefix ${org2Prefix} for org2...`)\n\n  command`\n    datadog-ci sourcemaps upload ${bundleFolder}\n      --service ${service}\n      --release-version ${getBuildEnvValue('SDK_VERSION')}\n      --minified-path-prefix ${org2Prefix}\n      --project-path @datadog/browser-${packageName}/\n      --repository-url https://www.github.com/datadog/browser-sdk\n  `\n    .withEnvironment({\n      DATADOG_API_KEY: apiKey,\n      DATADOG_SITE: 'datadoghq.com',\n    })\n    .run()\n}\n\nfunction uploadToDatadog(\n  packageName: string,\n  service: string,\n  prefix: string,\n  bundleFolder: string,\n  sites: string[]\n): void {\n  for (const site of sites) {\n    const apiKey = getTelemetryOrgApiKey(site)\n\n    if (!apiKey) {\n      printLog(`No API key configured for ${site}, skipping...`)\n      continue\n    }\n\n    printLog(`Uploading ${packageName} source maps with prefix ${prefix} for ${site}...`)\n\n    command`\n      datadog-ci sourcemaps upload ${bundleFolder}\n        --service ${service}\n        --release-version ${getBuildEnvValue('SDK_VERSION')}\n        --minified-path-prefix ${prefix}\n        --project-path @datadog/browser-${packageName}/\n        --repository-url https://www.github.com/datadog/browser-sdk\n    `\n      .withEnvironment({\n        DATADOG_API_KEY: apiKey,\n        DATADOG_SITE: site,\n      })\n      .run()\n  }\n}\n"
  },
  {
    "path": "scripts/dev-server/index.ts",
    "content": "import { runMain, printLog } from '../lib/executionUtils.ts'\nimport { start } from './lib/commands/start.ts'\nimport { stop } from './lib/commands/stop.ts'\nimport { logs } from './lib/commands/logs.ts'\nimport { status } from './lib/commands/status.ts'\nimport { intake } from './lib/commands/intake.ts'\n\nconst COMMANDS: Array<{ name: string; description: string; run: (args: string[]) => void | Promise<void> }> = [\n  {\n    name: 'start',\n    description: 'Start the dev server in the background',\n    run: start,\n  },\n  {\n    name: 'stop',\n    description: 'Stop the dev server',\n    run: stop,\n  },\n  {\n    name: 'status',\n    description: 'Show the dev server status',\n    run: status,\n  },\n  {\n    name: 'logs',\n    description: 'Show the dev server logs',\n    run: logs,\n  },\n  {\n    name: 'intake',\n    description: 'Show intake requests received by the dev server',\n    run: intake,\n  },\n]\n\nrunMain(async () => {\n  const [commandName, ...commandArgs] = process.argv.slice(2)\n\n  if (!commandName || commandName === '--help' || commandName === '-h') {\n    printLog(`Usage: yarn dev-server <command> [args]\n\nCommands:\n${COMMANDS.map((c) => `  ${c.name.padEnd(10)} ${c.description}`).join('\\n')}\n\nOptions:\n  -h, --help     Show this message`)\n    return\n  }\n\n  const command = COMMANDS.find((c) => c.name === commandName)\n  if (!command) {\n    throw new Error(`Unknown command: ${commandName}. Available: ${COMMANDS.map((c) => c.name).join(', ')}`)\n  }\n\n  await command.run(commandArgs)\n})\n"
  },
  {
    "path": "scripts/dev-server/lib/commands/intake.ts",
    "content": "import * as fs from 'node:fs'\nimport * as util from 'node:util'\nimport { parseArgs } from 'node:util'\nimport type { RumEvent } from '@datadog/browser-rum-core/src/rumEvent.types'\nimport type {\n  TelemetryEvent,\n  TelemetryErrorEvent,\n  TelemetryConfigurationEvent,\n  TelemetryUsageEvent,\n} from '@datadog/browser-core/src/domain/telemetry/telemetryEvent.types'\nimport type {\n  IntakeRequest,\n  LogsIntakeRequest,\n  ProfileIntakeRequest,\n  RumIntakeRequest,\n  ReplayIntakeRequest,\n  // eslint-disable-next-line local-rules/disallow-test-import-export-from-src, local-rules/disallow-protected-directory-import\n} from '../../../../test/e2e/lib/framework/intakeProxyMiddleware.ts'\nimport { printLog, printWarning } from '../../../lib/executionUtils.ts'\nimport { INTAKE_REQUESTS_FILE } from '../state.ts'\n\nexport function intake(args: string[]): void {\n  const { positionals, values } = parseArgs({\n    args,\n    allowPositionals: true,\n    options: {\n      help: { type: 'boolean', short: 'h' },\n      format: { type: 'string', default: process.stdout.isTTY ? 'pretty' : 'json' },\n    },\n  })\n\n  const [selectorName = 'requests'] = positionals\n\n  if (values.help) {\n    printLog(`Usage: yarn dev-server intake [selector]\n\nSelectors:\n${SELECTORS.map((s) => `  ${s.name.padEnd(20)} ${s.description}`).join('\\n')}\n\nCommands:\n  clear                Clear all recorded intake requests\n\nOptions:\n  --format       Output format: json or pretty (default: pretty when TTY, json otherwise)\n  -h, --help     Show this message\n\nExamples:\n  yarn dev-server intake rum-views | jq .view.loading_time\n  yarn dev-server intake rum-errors | jq .error.message\n  yarn dev-server intake rum-actions | jq .action.target.name\n  yarn dev-server intake logs-events | jq .message`)\n    return\n  }\n\n  if (selectorName === 'clear') {\n    fs.writeFileSync(INTAKE_REQUESTS_FILE, '')\n    printLog('Intake requests cleared.')\n    return\n  }\n\n  const selector = SELECTORS.find((s) => s.name === selectorName)\n  if (!selector) {\n    throw new Error(`Unknown selector: ${selectorName}. Available: ${SELECTORS.map((s) => s.name).join(', ')}`)\n  }\n\n  if (!fs.existsSync(INTAKE_REQUESTS_FILE)) {\n    printWarning('No intake requests found.')\n    return\n  }\n\n  const requests = fs\n    .readFileSync(INTAKE_REQUESTS_FILE, 'utf8')\n    .split('\\n')\n    .filter(Boolean)\n    .map((line) => JSON.parse(line) as IntakeRequest)\n\n  for (const item of selector.select(requests)) {\n    if (values.format === 'json') {\n      console.log(JSON.stringify(item))\n    } else {\n      console.log(util.inspect(item, { colors: true, depth: null }))\n    }\n  }\n}\n\nconst SELECTORS: Array<{ name: string; description: string; select: (requests: IntakeRequest[]) => unknown[] }> = [\n  {\n    name: 'requests',\n    description: 'All intake requests',\n    select: (requests) => requests,\n  },\n  {\n    name: 'rum-requests',\n    description: 'RUM intake requests',\n    select: (requests) => rumRequests(requests),\n  },\n  {\n    name: 'rum-events',\n    description: 'All RUM events',\n    select: (requests) => rumEvents(requests),\n  },\n  {\n    name: 'rum-actions',\n    description: 'RUM action events',\n    select: (requests) => rumEvents(requests).filter((e) => e.type === 'action'),\n  },\n  {\n    name: 'rum-errors',\n    description: 'RUM error events',\n    select: (requests) => rumEvents(requests).filter((e) => e.type === 'error'),\n  },\n  {\n    name: 'rum-resources',\n    description: 'RUM resource events',\n    select: (requests) => rumEvents(requests).filter((e) => e.type === 'resource'),\n  },\n  {\n    name: 'rum-long-tasks',\n    description: 'RUM long task events',\n    select: (requests) => rumEvents(requests).filter((e) => e.type === 'long_task'),\n  },\n  {\n    name: 'rum-views',\n    description: 'RUM view events',\n    select: (requests) => rumEvents(requests).filter((e) => e.type === 'view'),\n  },\n  {\n    name: 'rum-vitals',\n    description: 'RUM vital events',\n    select: (requests) => rumEvents(requests).filter((e) => e.type === 'vital'),\n  },\n  {\n    name: 'logs-requests',\n    description: 'Logs intake requests',\n    select: (requests) => logsRequests(requests),\n  },\n  {\n    name: 'logs-events',\n    description: 'Logs events',\n    select: (requests) => logsRequests(requests).flatMap((r) => r.events),\n  },\n  {\n    name: 'telemetry-events',\n    description: 'Telemetry events',\n    select: (requests) => telemetryEvents(requests),\n  },\n  {\n    name: 'telemetry-error-events',\n    description: 'Telemetry error events',\n    select: (requests) =>\n      telemetryEvents(requests).filter((e): e is TelemetryErrorEvent => e.telemetry.status === 'error'),\n  },\n  {\n    name: 'telemetry-configuration-events',\n    description: 'Telemetry configuration events',\n    select: (requests) =>\n      telemetryEvents(requests).filter((e): e is TelemetryConfigurationEvent => e.telemetry.type === 'configuration'),\n  },\n  {\n    name: 'telemetry-usage-events',\n    description: 'Telemetry usage events',\n    select: (requests) =>\n      telemetryEvents(requests).filter((e): e is TelemetryUsageEvent => e.telemetry.type === 'usage'),\n  },\n  {\n    name: 'replay-segments',\n    description: 'Session replay segments',\n    select: (requests) => replayRequests(requests).map((r) => r.segment),\n  },\n  {\n    name: 'replay-records',\n    description: 'Session replay records',\n    select: (requests) => replayRequests(requests).flatMap((r) => r.segment.records),\n  },\n  {\n    name: 'profile-requests',\n    description: 'Profiling intake requests',\n    select: (requests) => profileRequests(requests),\n  },\n  {\n    name: 'profile-events',\n    description: 'Profiling events',\n    select: (requests) => profileRequests(requests).map((r) => r.event),\n  },\n]\n\nfunction rumRequests(requests: IntakeRequest[]): RumIntakeRequest[] {\n  return requests.filter((r): r is RumIntakeRequest => r.intakeType === 'rum')\n}\n\nfunction logsRequests(requests: IntakeRequest[]): LogsIntakeRequest[] {\n  return requests.filter((r): r is LogsIntakeRequest => r.intakeType === 'logs')\n}\n\nfunction replayRequests(requests: IntakeRequest[]): ReplayIntakeRequest[] {\n  return requests.filter((r): r is ReplayIntakeRequest => r.intakeType === 'replay')\n}\n\nfunction profileRequests(requests: IntakeRequest[]): ProfileIntakeRequest[] {\n  return requests.filter((r): r is ProfileIntakeRequest => r.intakeType === 'profile')\n}\n\nfunction rumEvents(requests: IntakeRequest[]): RumEvent[] {\n  return rumRequests(requests).flatMap((r) => r.events.filter((e): e is RumEvent => e.type !== 'telemetry'))\n}\n\nfunction telemetryEvents(requests: IntakeRequest[]): TelemetryEvent[] {\n  return rumRequests(requests).flatMap((r) => r.events.filter((e): e is TelemetryEvent => e.type === 'telemetry'))\n}\n"
  },
  {
    "path": "scripts/dev-server/lib/commands/logs.ts",
    "content": "import * as fs from 'node:fs'\nimport { spawn } from 'node:child_process'\nimport { Transform } from 'node:stream'\nimport { parseArgs } from 'node:util'\nimport { printLog, printWarning } from '../../../lib/executionUtils.ts'\nimport { LOG_FILE } from '../state.ts'\n\nexport function logs(args: string[]): void {\n  const { values } = parseArgs({\n    args,\n    options: {\n      help: { type: 'boolean', short: 'h' },\n      follow: { type: 'boolean', short: 'f' },\n    },\n  })\n\n  if (values.help) {\n    printLog(`Usage: yarn dev-server logs [options]\n\nOptions:\n  -f, --follow   Follow log output\n  -h, --help     Show this message`)\n    return\n  }\n\n  if (!fs.existsSync(LOG_FILE)) {\n    printWarning('No dev server logs found.')\n    return\n  }\n\n  let stream: NodeJS.ReadableStream\n\n  if (values.follow) {\n    const tail = spawn('tail', ['-f', LOG_FILE], { stdio: ['ignore', 'pipe', 'inherit'] })\n    stream = tail.stdout\n  } else {\n    stream = fs.createReadStream(LOG_FILE)\n  }\n\n  if (!process.stdout.isTTY) {\n    stream = stream.pipe(stripAnsi())\n  }\n  stream.pipe(process.stdout)\n}\n\nfunction stripAnsi(): Transform {\n  return new Transform({\n    transform(chunk: Buffer, _encoding, callback) {\n      // eslint-disable-next-line no-control-regex\n      callback(null, chunk.toString().replace(/\\x1B\\[[\\d;]*[A-Za-z]/g, ''))\n    },\n  })\n}\n"
  },
  {
    "path": "scripts/dev-server/lib/commands/start.ts",
    "content": "import { spawn } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { parseArgs } from 'node:util'\nimport { readState, writeState, isRunning, printStatus, LOG_FILE } from '../state.ts'\nimport { printLog } from '../../../lib/executionUtils.ts'\n\nconst DAEMON_SCRIPT = path.join(import.meta.dirname, '../daemon.ts')\nconst STARTUP_TIMEOUT_MS = 10_000\n\nexport async function start(args: string[]): Promise<void> {\n  const { values } = parseArgs({\n    args,\n    options: {\n      help: { type: 'boolean', short: 'h' },\n      'no-daemon': { type: 'boolean', default: false },\n    },\n  })\n\n  if (values.help) {\n    printLog(`Usage: yarn dev-server start [options]\n\nOptions:\n  --no-daemon    Run in the foreground instead of as a background daemon\n  -h, --help     Show this message`)\n    return\n  }\n\n  if (values['no-daemon']) {\n    const { runServer } = await import('../server.ts')\n    runServer({ writeIntakeFile: false })\n    return\n  }\n\n  const existingState = readState()\n  if (existingState && isRunning(existingState.pid)) {\n    printStatus(existingState)\n    return\n  }\n\n  fs.mkdirSync(path.dirname(LOG_FILE), { recursive: true })\n  const logFd = fs.openSync(LOG_FILE, 'w')\n  const child = spawn(process.execPath, [...process.execArgv, DAEMON_SCRIPT], {\n    detached: true,\n    stdio: ['ignore', logFd, logFd, 'ipc'],\n    cwd: process.cwd(),\n    env: { ...process.env, FORCE_COLOR: '1' },\n  })\n  fs.closeSync(logFd)\n\n  const signal = AbortSignal.timeout(STARTUP_TIMEOUT_MS)\n\n  await new Promise<void>((resolve, reject) => {\n    const onAbort = () => {\n      child.kill()\n      reject(new Error(`Dev server did not start within ${STARTUP_TIMEOUT_MS / 1000}s`))\n    }\n    signal.addEventListener('abort', onAbort)\n\n    child.on('message', (msg: { port: number }) => {\n      signal.removeEventListener('abort', onAbort)\n      const url = `http://localhost:${msg.port}`\n      const state = { pid: child.pid!, port: msg.port, url }\n      writeState(state)\n      printStatus(state)\n      child.disconnect()\n      child.unref()\n      resolve()\n    })\n\n    child.on('error', (err) => {\n      signal.removeEventListener('abort', onAbort)\n      reject(err)\n    })\n\n    child.on('exit', (code) => {\n      signal.removeEventListener('abort', onAbort)\n      reject(new Error(`Dev server process exited with code ${code}`))\n    })\n  })\n}\n"
  },
  {
    "path": "scripts/dev-server/lib/commands/status.ts",
    "content": "import { parseArgs } from 'node:util'\nimport { printLog, printWarning } from '../../../lib/executionUtils.ts'\nimport { readState, isRunning, printStatus } from '../state.ts'\n\nexport function status(args: string[]): void {\n  const { values } = parseArgs({\n    args,\n    options: { help: { type: 'boolean', short: 'h' } },\n  })\n\n  if (values.help) {\n    printLog(`Usage: yarn dev-server status\n\nOptions:\n  -h, --help     Show this message`)\n    return\n  }\n\n  const state = readState()\n\n  if (state && isRunning(state.pid)) {\n    printStatus(state)\n  } else {\n    printWarning('Dev server is not running.')\n  }\n}\n"
  },
  {
    "path": "scripts/dev-server/lib/commands/stop.ts",
    "content": "import { parseArgs } from 'node:util'\nimport { printLog, printWarning } from '../../../lib/executionUtils.ts'\nimport { readState, clearState, isRunning } from '../state.ts'\n\nexport function stop(args: string[]): void {\n  const { values } = parseArgs({\n    args,\n    options: { help: { type: 'boolean', short: 'h' } },\n  })\n\n  if (values.help) {\n    printLog(`Usage: yarn dev-server stop\n\nOptions:\n  -h, --help     Show this message`)\n    return\n  }\n\n  const state = readState()\n\n  if (!state || !isRunning(state.pid)) {\n    printWarning('Dev server is not running.')\n    clearState()\n    return\n  }\n\n  process.kill(state.pid)\n  clearState()\n  printLog('Dev server stopped.')\n}\n"
  },
  {
    "path": "scripts/dev-server/lib/daemon.ts",
    "content": "import { runServer } from './server.ts'\n\nvoid runServer()\n"
  },
  {
    "path": "scripts/dev-server/lib/server.ts",
    "content": "import type { AddressInfo } from 'node:net'\nimport { appendFileSync, writeFileSync } from 'node:fs'\nimport express from 'express'\nimport middleware from 'webpack-dev-middleware'\nimport HtmlWebpackPlugin from 'html-webpack-plugin'\nimport webpack from 'webpack'\nimport cors from 'cors'\nimport webpackBase from '../../../webpack.base.ts'\nimport { printLog } from '../../lib/executionUtils.ts'\n// eslint-disable-next-line local-rules/disallow-test-import-export-from-src, local-rules/disallow-protected-directory-import\nimport { createIntakeProxyMiddleware } from '../../../test/e2e/lib/framework/intakeProxyMiddleware.ts'\nimport { INTAKE_REQUESTS_FILE } from './state.ts'\n\nconst sandboxPath = './sandbox'\nconst START_PORT = 8080\nconst MAX_PORT = 8180\n\nconst PACKAGES_WITH_BUNDLE = ['rum', 'rum-slim', 'logs', 'worker']\n\nexport function runServer({ writeIntakeFile = true }: { writeIntakeFile?: boolean } = {}): void {\n  if (writeIntakeFile) {\n    writeFileSync(INTAKE_REQUESTS_FILE, '')\n  }\n\n  process.on('SIGTERM', () => {\n    printLog('Dev server exiting.')\n    process.exit(0)\n  })\n\n  const app = express()\n\n  app.use((_req, res, next) => {\n    res.setHeader('Document-Policy', 'js-profiling')\n    next()\n  })\n\n  app.post(\n    '/proxy',\n    createIntakeProxyMiddleware({\n      onRequest: (request) => {\n        if (writeIntakeFile) {\n          appendFileSync(INTAKE_REQUESTS_FILE, `${JSON.stringify(request)}\\n`)\n        }\n      },\n    })\n  )\n\n  app.use(createStaticSandboxApp())\n\n  app.use('/react-app', createReactApp())\n\n  listenOnAvailablePort(app, START_PORT)\n}\n\nfunction listenOnAvailablePort(app: express.Application, port: number): void {\n  const server = app.listen(port)\n  server.on('listening', () => {\n    const actualPort = (server.address() as AddressInfo).port\n    printLog(`Dev server listening on port ${actualPort}.`)\n    if (process.send) {\n      process.send({ port: actualPort })\n    }\n  })\n  server.on('error', (err: NodeJS.ErrnoException) => {\n    if (err.code === 'EADDRINUSE' && port < MAX_PORT) {\n      printLog(`Port ${port} is already in use, trying ${port + 1}...`)\n      server.close(() => listenOnAvailablePort(app, port + 1))\n    } else {\n      throw err\n    }\n  })\n}\n\nfunction createStaticSandboxApp(): express.Application {\n  const app = express()\n  app.use(cors())\n  app.use(express.static(sandboxPath))\n  for (const packageName of PACKAGES_WITH_BUNDLE) {\n    const packagePath = `./packages/${packageName}`\n    app.use(\n      middleware(\n        webpack(\n          webpackBase({\n            mode: 'development',\n            entry: `${packagePath}/src/entries/main.ts`,\n            filename: packageName === 'worker' ? 'worker.js' : `datadog-${packageName}.js`,\n          })\n        ),\n        { stats: 'minimal' }\n      )\n    )\n  }\n\n  // Redirect suffixed files\n  app.use((req, res, next) => {\n    const matches = /(.*)-(canary|staging|v\\d*)\\.js/.exec(req.url)\n    if (matches) {\n      res.redirect(`${matches[1]}.js`)\n    } else {\n      next()\n    }\n  })\n\n  return app\n}\n\nfunction createReactApp(): express.Application {\n  const app = express()\n\n  // Redirect requests to the \"index.html\" file, so that the React app can handle routing\n  app.use((req, _, next) => {\n    if (req.url !== '/main.js') {\n      req.url = '/index.html'\n    }\n    next()\n  })\n\n  app.use(\n    middleware(\n      webpack(\n        webpackBase({\n          entry: `${sandboxPath}/react-app/main.tsx`,\n          plugins: [new HtmlWebpackPlugin({ publicPath: '/react-app/' })],\n          mode: 'development',\n        })\n      ),\n      { stats: 'minimal' }\n    )\n  )\n\n  return app\n}\n"
  },
  {
    "path": "scripts/dev-server/lib/state.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { printLog } from '../../lib/executionUtils.ts'\n\nconst DEV_SERVER_DIR = path.resolve('.dev-server')\nexport const LOG_FILE = path.join(DEV_SERVER_DIR, 'logs')\nexport const INTAKE_REQUESTS_FILE = path.join(DEV_SERVER_DIR, 'intake-requests.json')\nconst STATE_FILE = path.join(DEV_SERVER_DIR, 'state.json')\n\nexport interface DevServerState {\n  pid: number\n  port: number\n  url: string\n}\n\nexport function readState(): DevServerState | null {\n  try {\n    return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8')) as DevServerState\n  } catch {\n    return null\n  }\n}\n\nexport function writeState(state: DevServerState): void {\n  fs.mkdirSync(DEV_SERVER_DIR, { recursive: true })\n  fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2))\n}\n\nexport function clearState(): void {\n  try {\n    fs.unlinkSync(STATE_FILE)\n  } catch {\n    // ignore\n  }\n}\n\nexport function printStatus(state: DevServerState): void {\n  printLog(`\\\nDev server is running at ${state.url}\nProcess id: ${state.pid}\nLogs: ./${path.relative(process.cwd(), LOG_FILE)}\nIntake requests: ./${path.relative(process.cwd(), INTAKE_REQUESTS_FILE)}`)\n}\n\nexport function isRunning(pid: number): boolean {\n  try {\n    process.kill(pid, 0)\n    return true\n  } catch {\n    return false\n  }\n}\n"
  },
  {
    "path": "scripts/generate-schema-types.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nimport { compileFromFile } from 'json-schema-to-typescript'\nimport { resolveConfig } from 'prettier'\nimport { printLog, runMain } from './lib/executionUtils.ts'\nimport { SCHEMAS } from './lib/generatedSchemaTypes.ts'\n\nconst prettierConfigPath = path.join(import.meta.dirname, '../.prettierrc.yml')\n\nrunMain(async () => {\n  const prettierConfig = await resolveConfig(prettierConfigPath)\n\n  for (const { typesPath, schemaPath, options = {} } of SCHEMAS) {\n    const absoluteSchemaPath = path.join(import.meta.dirname, '..', schemaPath)\n    const absoluteTypesPath = path.join(import.meta.dirname, '..', typesPath)\n\n    printLog(`Compiling ${schemaPath}...`)\n\n    const compiledTypes = await compileFromFile(absoluteSchemaPath, {\n      cwd: path.dirname(absoluteSchemaPath),\n      bannerComment: '/**\\n * DO NOT MODIFY IT BY HAND. Run `yarn json-schemas:sync` instead.\\n*/',\n      style: prettierConfig || {},\n      ...options,\n    })\n    printLog(`Writing ${absoluteTypesPath}...`)\n    fs.writeFileSync(absoluteTypesPath, compiledTypes)\n    printLog('Generation done.')\n  }\n})\n"
  },
  {
    "path": "scripts/lib/browserSdkVersion.ts",
    "content": "import packageJson from '../../package.json' with { type: 'json' }\n\nexport const browserSdkVersion = packageJson.version\n"
  },
  {
    "path": "scripts/lib/bsUtils.ts",
    "content": "import { type RequestInit } from 'undici'\nimport { fetchHandlingError } from './executionUtils.ts'\n\ninterface BrowserStackRequestOptions extends RequestInit {\n  headers?: Record<string, string>\n}\n\nexport async function browserStackRequest(url: string, options: BrowserStackRequestOptions = {}): Promise<any> {\n  const response = await fetchHandlingError(url, {\n    headers: {\n      Authorization: `Basic ${Buffer.from(`${process.env.BS_USERNAME}:${process.env.BS_ACCESS_KEY}`).toString('base64')}`,\n    },\n    ...options,\n  })\n  return response.json()\n}\n"
  },
  {
    "path": "scripts/lib/buildEnv.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { execSync } from 'node:child_process'\nimport { browserSdkVersion } from './browserSdkVersion.ts'\nimport { command } from './command.ts'\n\ntype BuildMode = 'dev' | 'release' | 'canary'\ntype SdkSetup = 'npm' | 'cdn'\n\n/**\n * Allows to define which sdk_version to send to the intake.\n */\nconst BUILD_MODES: BuildMode[] = [\n  // Used while developing. This is the default if the BUILD_MODE environment variable is empty.\n  'dev',\n  // Used for public releases.\n  'release',\n  // Used on staging and production Datadog web app.\n  'canary',\n]\n\n/**\n * Allows to define which sdk setup to send to the telemetry.\n */\nconst SDK_SETUPS: SdkSetup[] = ['npm', 'cdn']\n\nconst WORKER_PATH = path.join(import.meta.dirname, '../../packages/worker')\n\nconst buildEnvCache = new Map<string, string>()\n\ntype BuildEnvFactories = {\n  [K in 'SDK_VERSION' | 'SDK_SETUP' | 'WORKER_STRING']: () => string\n}\n\nconst buildEnvFactories: BuildEnvFactories = {\n  SDK_VERSION: () => {\n    switch (getBuildMode()) {\n      case 'release':\n        return browserSdkVersion\n      case 'canary': {\n        const commitSha1 = execSync('git rev-parse HEAD').toString().trim()\n        // TODO when tags would allow '+' characters\n        //  use build separator (+) instead of prerelease separator (-)\n        return `${browserSdkVersion}-${commitSha1}`\n      }\n      default:\n        return 'dev'\n    }\n  },\n  SDK_SETUP: () => getSdkSetup(),\n  WORKER_STRING: () => {\n    if (needsWorkerRebuild()) {\n      command`yarn build`.withCurrentWorkingDirectory(WORKER_PATH).run()\n    }\n    return fs.readFileSync(path.join(WORKER_PATH, 'bundle/worker.js'), {\n      encoding: 'utf-8',\n    })\n  },\n}\n\nexport const buildEnvKeys = Object.keys(buildEnvFactories) as Array<keyof BuildEnvFactories>\n\nexport function getBuildEnvValue(key: keyof BuildEnvFactories): string {\n  let value = buildEnvCache.get(key)\n  if (!value) {\n    value = buildEnvFactories[key]()\n    buildEnvCache.set(key, value)\n  }\n  return value\n}\n\nfunction getBuildMode(): BuildMode {\n  if (!process.env.BUILD_MODE) {\n    return BUILD_MODES[0]\n  }\n  if (BUILD_MODES.includes(process.env.BUILD_MODE as BuildMode)) {\n    return process.env.BUILD_MODE as BuildMode\n  }\n  console.log(`Invalid build mode \"${process.env.BUILD_MODE}\". Possible build modes are: ${BUILD_MODES.join(', ')}`)\n  process.exit(1)\n}\n\nfunction getSdkSetup(): SdkSetup {\n  if (!process.env.SDK_SETUP) {\n    return SDK_SETUPS[0] // npm\n  }\n  if (SDK_SETUPS.includes(process.env.SDK_SETUP as SdkSetup)) {\n    return process.env.SDK_SETUP as SdkSetup\n  }\n  console.log(`Invalid SDK setup \"${process.env.SDK_SETUP}\". Possible SDK setups are: ${SDK_SETUPS.join(', ')}`)\n  process.exit(1)\n}\n\nfunction needsWorkerRebuild(): boolean {\n  const bundlePath = path.join(WORKER_PATH, 'bundle/worker.js')\n\n  if (!fs.existsSync(bundlePath)) {\n    return true\n  }\n\n  const bundleMtime = fs.statSync(bundlePath).mtimeMs\n\n  return fs.globSync('src/**/*', { cwd: WORKER_PATH }).some((file) => {\n    const filePath = path.join(WORKER_PATH, file)\n    const stats = fs.statSync(filePath)\n    return stats.isFile() && stats.mtimeMs > bundleMtime\n  })\n}\n"
  },
  {
    "path": "scripts/lib/checkBrowserSdkPackageJsonFiles.ts",
    "content": "import { browserSdkVersion as releaseVersion } from './browserSdkVersion.ts'\nimport { printLog } from './executionUtils.ts'\nimport type { PackageJsonInfo } from './filesUtils.ts'\nimport { findPackageJsonFiles } from './filesUtils.ts'\n\nexport function checkPackageJsonFiles(): void {\n  const packageJsonFiles = findPackageJsonFiles()\n\n  printLog(\n    `Checking package.json files:\n   - ${packageJsonFiles.map((packageJsonFile) => packageJsonFile.relativePath).join('\\n   - ')}\n`\n  )\n\n  for (const packageJsonFile of packageJsonFiles) {\n    checkPackageJsonVersion(packageJsonFile)\n    checkPackageDependencyVersions(packageJsonFile)\n  }\n}\nfunction checkPackageJsonVersion(packageJsonInfo: PackageJsonInfo): void {\n  if (packageJsonInfo.content.private) {\n    // The developer extension is a private package, but it should still have a version\n    if (\n      packageJsonInfo.content.version &&\n      packageJsonInfo.content.name !== '@datadog/browser-sdk-developer-extension' &&\n      packageJsonInfo.relativePath !== 'package.json'\n    ) {\n      throw new Error(`Private package ${packageJsonInfo.relativePath} should not have a version`)\n    }\n  } else if (packageJsonInfo.content.version !== releaseVersion) {\n    throw new Error(\n      `Invalid version for ${packageJsonInfo.relativePath}: expected ${releaseVersion}, got ${packageJsonInfo.content.version}`\n    )\n  }\n}\nfunction checkPackageDependencyVersions(packageJsonInfo: PackageJsonInfo): void {\n  if (packageJsonInfo.content.private) {\n    return\n  }\n\n  for (const dependencies of [\n    packageJsonInfo.content.dependencies,\n    packageJsonInfo.content.devDependencies,\n    packageJsonInfo.content.peerDependencies,\n  ]) {\n    if (!dependencies) {\n      continue\n    }\n\n    for (const [dependencyName, dependencyVersion] of Object.entries(dependencies)) {\n      if (isBrowserSdkPackageName(dependencyName) && dependencyVersion !== releaseVersion) {\n        throw new Error(\n          `Invalid dependency version for ${dependencyName} in ${packageJsonInfo.relativePath}: expected ${releaseVersion}, got ${dependencyVersion}`\n        )\n      }\n    }\n  }\n}\nfunction isBrowserSdkPackageName(name: string): boolean {\n  return name?.startsWith('@datadog/')\n}\n"
  },
  {
    "path": "scripts/lib/command.spec.ts",
    "content": "import { test } from 'node:test'\nimport assert from 'node:assert'\nimport { parseCommandTemplateArguments } from './command.ts'\n\ntest('splits on white spaces', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo bar`, ['foo', 'bar'])\n})\n\ntest('interpolates a variable as a separate argument when surrounded by spaces', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo ${'bar'} baz`, ['foo', 'bar', 'baz'])\n})\n\ntest('appends a variable to the previous argument when no leading space', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo${'bar'} baz`, ['foobar', 'baz'])\n})\n\ntest('prepends a variable to the next argument when no trailing space', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo ${'bar'}baz`, ['foo', 'barbaz'])\n})\n\ntest('merges variable into surrounding argument when no spaces on either side', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo${'bar'}baz`, ['foobarbaz'])\n})\n\ntest('does not split a variable value on white spaces', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo ${'bar baz'}`, ['foo', 'bar baz'])\n})\n\ntest('spreads array variables as separate arguments', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo ${['bar', 'baz']}`, ['foo', 'bar', 'baz'])\n})\n\ntest('keeps empty string as a distinct argument', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo ${''} bar`, ['foo', '', 'bar'])\n})\n\ntest('ignores empty array, producing no extra arguments', () => {\n  assert.deepStrictEqual(parseCommandTemplateArguments`foo ${[]} bar`, ['foo', 'bar'])\n})\n\ntest('real-world: git commit with message', () => {\n  const commitMessage = 'my commit message'\n  assert.deepStrictEqual(parseCommandTemplateArguments`git commit -c ${commitMessage}`, [\n    'git',\n    'commit',\n    '-c',\n    'my commit message',\n  ])\n})\n"
  },
  {
    "path": "scripts/lib/command.ts",
    "content": "import childProcess from 'node:child_process'\nimport { printDebug, printError } from './executionUtils.ts'\n\ninterface CommandOptions {\n  cwd?: string\n  stdio?: 'inherit' | 'pipe'\n}\n\ninterface CommandBuilder {\n  withInput(newInput: string): CommandBuilder\n  withEnvironment(newEnv: Record<string, string>): CommandBuilder\n  withCurrentWorkingDirectory(newCurrentWorkingDirectory: string): CommandBuilder\n  withLogs(): CommandBuilder\n  run(): string\n}\n\n/**\n * Helper to run executables. This has been introduced to work around Shell injections[0] while\n * keeping a good developer experience. The template string is split on white spaces and passed to\n * a child_process method that don't use a shell.\n *\n * Prefer this helper over using other child_process methods. Avoid using `child_process.exec`,\n * `child_process.execSync` or the `shell` option of other `child_process` functions.\n *\n * Use this as a tagged string template. Example:\n *\n * > command`git ls-files ${directory}`.run()\n *\n * [0]: https://matklad.github.io/2021/07/30/shell-injection.html\n */\nexport function command(...templateArguments: [TemplateStringsArray, ...any[]]): CommandBuilder {\n  const [commandName, ...commandArguments] = parseCommandTemplateArguments(...templateArguments)\n\n  let input = ''\n  let env: Record<string, string> | undefined\n  const extraOptions: CommandOptions = {}\n\n  return {\n    withInput(newInput: string) {\n      input = newInput\n      return this\n    },\n\n    withEnvironment(newEnv: Record<string, string>) {\n      env = newEnv\n      return this\n    },\n\n    withCurrentWorkingDirectory(newCurrentWorkingDirectory: string) {\n      extraOptions.cwd = newCurrentWorkingDirectory\n      return this\n    },\n\n    withLogs() {\n      extraOptions.stdio = 'inherit'\n      return this\n    },\n\n    run(): string {\n      const formattedCommand = `${commandName} ${commandArguments.join(' ')}`\n      printDebug(`Running command: ${formattedCommand}`)\n\n      const commandResult = childProcess.spawnSync(commandName, commandArguments, {\n        input,\n        env: { ...process.env, ...env },\n        encoding: 'utf-8',\n        ...extraOptions,\n      })\n\n      if (commandResult.status !== 0) {\n        const formattedStderr = commandResult.stderr ? `\\n---- stderr: ----\\n${commandResult.stderr}\\n----` : ''\n        const formattedStdout = commandResult.stdout ? `\\n---- stdout: ----\\n${commandResult.stdout}\\n----` : ''\n        const exitCause =\n          commandResult.signal !== null\n            ? ` due to signal ${commandResult.signal}`\n            : commandResult.status !== null\n              ? ` with exit status ${commandResult.status}`\n              : ''\n        throw new Error(`Command failed${exitCause}: ${formattedCommand}${formattedStderr}${formattedStdout}`, {\n          cause: commandResult.error,\n        })\n      }\n\n      if (commandResult.stderr) {\n        printError(commandResult.stderr)\n      }\n\n      return commandResult.stdout\n    },\n  }\n}\n\n/**\n * Parse template values passed to the `command` template tag, and return a list of arguments to run\n * the command.\n *\n * It expects the same parameters as a template tag: the first parameter is a list of template\n * strings, and the other parameters are template variables. See MDN for tagged template\n * documentation[1].\n *\n * The resulting command arguments is a list of strings generated as if the template literal was\n * split on white spaces. For example:\n *\n * parseCommandTemplateArguments`foo bar` == ['foo', 'bar']\n * parseCommandTemplateArguments`foo ${'bar'} baz` == ['foo', 'bar', 'baz']\n *\n * Template variables are considered as part of the previous or next command argument if they are\n * not separated with a space:\n *\n * parseCommandTemplateArguments`foo${'bar'} baz` == ['foobar', 'baz']\n * parseCommandTemplateArguments`foo ${'bar'}baz` == ['foo', 'barbaz']\n * parseCommandTemplateArguments`foo${'bar'}baz` == ['foobarbaz']\n *\n * Template variables are never split on white spaces, allowing to pass any arbitrary argument to\n * the command without worrying on shell escaping:\n *\n * parseCommandTemplateArguments`foo ${'bar baz'}` == ['foo', 'bar baz']\n *\n * To pass template variables as different command arguments use an array as template argument:\n *\n * parseCommandTemplateArguments`foo ${['bar', 'baz']}` == ['foo', 'bar', 'baz']\n *\n *\n * const commitMessage = 'my commit message'\n * parseCommandTemplateArguments`git commit -c ${commitMessage}` == ['git', 'commit', '-c', 'my commit message']\n *\n * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates\n */\nexport function parseCommandTemplateArguments(\n  templateStrings: TemplateStringsArray,\n  ...templateVariables: any[]\n): string[] {\n  const parsedArguments: string[] = []\n  for (let i = 0; i < templateStrings.length; i += 1) {\n    if (i > 0) {\n      // Interleave variables with template strings\n      if (!parsedArguments.length || templateStrings[i - 1].match(/\\s$/)) {\n        // If the latest string ends with a space, consider the variable as separate argument(s)\n        const variable = templateVariables[i - 1]\n        if (Array.isArray(variable)) {\n          parsedArguments.push(...variable)\n        } else {\n          parsedArguments.push(variable)\n        }\n      } else {\n        // Else, append the variable to the latest argument\n        parsedArguments[parsedArguments.length - 1] += templateVariables[i - 1]\n      }\n    }\n\n    const words = templateStrings[i].split(/\\s+/).filter((word) => word)\n\n    if (parsedArguments.length && words.length && !templateStrings[i].match(/^\\s/)) {\n      // If the string does not start with a space, append it to the latest argument\n      parsedArguments[parsedArguments.length - 1] += words.shift()!\n    }\n\n    parsedArguments.push(...words)\n  }\n  return parsedArguments\n}\n"
  },
  {
    "path": "scripts/lib/computeBundleSize.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport zlib from 'node:zlib'\n\nconst packages = ['rum', 'logs', 'rum-slim', 'worker'] as const\n\ninterface BundleSize {\n  uncompressed: number\n  gzipped: number\n}\n\ninterface BundleSizes {\n  [key: string]: BundleSize\n}\n\nfunction getPackageName(file: string): string | undefined {\n  if (file.includes('chunk')) {\n    const { chunkName, packageName } =\n      file.match(/chunks\\/(?<chunkName>[a-z0-9]*)-[a-z0-9]*-datadog-(?<packageName>[a-z-]*)\\.js/)?.groups ?? {}\n    return `${packageName}_${chunkName}`\n  }\n\n  return file\n    .replace('datadog-', '')\n    .replace('-', '_') // rename rum-slim to rum_slim\n    .replace('.js', '')\n}\n\nfunction getGzippedBundleSize(filePath: string): number {\n  try {\n    const content = fs.readFileSync(filePath)\n    const gzipped = zlib.gzipSync(content)\n\n    return gzipped.length\n  } catch (error) {\n    throw new Error('Failed to get gzipped bundle size', { cause: error })\n  }\n}\n\nfunction getUncompressedBundleSize(filePath: string): number {\n  try {\n    const file = fs.statSync(filePath)\n\n    return file.size\n  } catch (error) {\n    throw new Error('Failed to get bundle size', { cause: error })\n  }\n}\n\nfunction getPackageSize(packageName: string): BundleSizes {\n  const bundleSizes: BundleSizes = {}\n  const packagePath = path.join(import.meta.dirname, `../../packages/${packageName}/bundle/`)\n\n  for (const file of fs.globSync('**/*.js', { cwd: packagePath })) {\n    const name = getPackageName(file)\n\n    if (!name) {\n      continue\n    }\n\n    const filePath = path.join(packagePath, file)\n\n    bundleSizes[name] = {\n      uncompressed: getUncompressedBundleSize(filePath),\n      gzipped: getGzippedBundleSize(filePath),\n    }\n  }\n\n  return bundleSizes\n}\n\nexport function calculateBundleSizes(): BundleSizes {\n  const bundleSizes: BundleSizes = {}\n\n  for (const pkg of packages) {\n    Object.assign(bundleSizes, getPackageSize(pkg))\n  }\n\n  return bundleSizes\n}\n"
  },
  {
    "path": "scripts/lib/datacenter.spec.ts",
    "content": "import { describe, it, before, mock, type Mock } from 'node:test'\nimport assert from 'node:assert'\nimport path from 'node:path'\nimport { mockModule, mockFetchHandlingError, FAKE_RUNTIME_METADATA_SERVICE_TOKEN } from '../deploy/lib/testHelpers.ts'\nimport type { fetchHandlingError } from './executionUtils.ts'\n\ndescribe('datacenter', () => {\n  const fetchHandlingErrorMock: Mock<typeof fetchHandlingError> = mock.fn()\n\n  before(async () => {\n    // Setup mock before importing the module\n    mockFetchHandlingError(fetchHandlingErrorMock)\n\n    await mockModule(path.resolve(import.meta.dirname, './executionUtils.ts'), {\n      fetchHandlingError: fetchHandlingErrorMock,\n    })\n  })\n\n  it('should fetch all datacenters from runtime-metadata-service', async () => {\n    const { getAllDatacentersMetadata, DatacenterType } = await import('./datacenter.ts')\n    const datacenters = await getAllDatacentersMetadata()\n\n    assert.deepStrictEqual(datacenters, [\n      {\n        name: 'ap1',\n        site: 'ap1.datadoghq.com',\n        type: DatacenterType.MINOR,\n      },\n      {\n        name: 'ap2',\n        site: 'ap2.datadoghq.com',\n        type: DatacenterType.MINOR,\n      },\n      {\n        name: 'eu1',\n        site: 'datadoghq.eu',\n        type: DatacenterType.MAJOR,\n      },\n      {\n        name: 'us1',\n        site: 'datadoghq.com',\n        type: DatacenterType.MAJOR,\n      },\n      {\n        name: 'us3',\n        site: 'us3.datadoghq.com',\n        type: DatacenterType.MINOR,\n      },\n      {\n        name: 'us5',\n        site: 'us5.datadoghq.com',\n        type: DatacenterType.MINOR,\n      },\n      {\n        name: 'prtest00',\n        site: 'prtest00.datadoghq.com',\n        type: DatacenterType.PRIVATE,\n      },\n      {\n        name: 'prtest01',\n        site: 'prtest01.datadoghq.com',\n        type: DatacenterType.PRIVATE,\n      },\n    ])\n  })\n\n  it('should fetch vault token with correct headers', async () => {\n    const { getAllDatacentersMetadata } = await import('./datacenter.ts')\n    await getAllDatacentersMetadata()\n\n    const vaultCall = fetchHandlingErrorMock.mock.calls.find((call) =>\n      call.arguments[0].includes('/v1/identity/oidc/token/runtime-metadata-service')\n    )\n    assert.ok(vaultCall)\n    assert.deepStrictEqual(vaultCall.arguments[1]?.headers, { 'X-Vault-Request': 'true' })\n  })\n\n  it('should fetch datacenters with vault token authorization', async () => {\n    const { getAllDatacentersMetadata } = await import('./datacenter.ts')\n    await getAllDatacentersMetadata()\n\n    const datacentersCall = fetchHandlingErrorMock.mock.calls.find((call) =>\n      call.arguments[0].includes('runtime-metadata-service.us1.ddbuild.io/v2/datacenters')\n    )\n    assert.ok(datacentersCall)\n    assert.ok(\n      datacentersCall.arguments[0].includes(\n        `selector=${encodeURIComponent('datacenter.environment == \"prod\" && datacenter.flavor == \"site\"')}`\n      ),\n      'URL should include selector for prod environment and site flavor'\n    )\n    assert.deepStrictEqual(datacentersCall.arguments[1]?.headers, {\n      accept: 'application/json',\n      Authorization: `Bearer ${FAKE_RUNTIME_METADATA_SERVICE_TOKEN}`,\n    })\n  })\n\n  it('should cache datacenter metadata across multiple calls', async () => {\n    const { getAllDatacentersMetadata } = await import('./datacenter.ts')\n\n    // Module may already be initialized from previous tests\n    // Make multiple calls and verify no additional API calls are made\n    const initialCallCount = fetchHandlingErrorMock.mock.calls.length\n\n    await getAllDatacentersMetadata()\n    await getAllDatacentersMetadata()\n    await getAllDatacentersMetadata()\n\n    const finalCallCount = fetchHandlingErrorMock.mock.calls.length\n\n    // Should not make any new API calls since data is cached (whether cached from this test or previous tests)\n    assert.strictEqual(finalCallCount, initialCallCount, 'Should not make additional API calls when cached')\n  })\n})\n"
  },
  {
    "path": "scripts/lib/datacenter.ts",
    "content": "import { fetchHandlingError } from './executionUtils.ts'\n\nexport const DatacenterType = {\n  // Minor DCs are the ones that are deployed first, all at once.\n  MINOR: 'minor',\n\n  // Private DCs are deployed next, all at once\n  PRIVATE: 'private',\n\n  // Major DCs are the ones that are deployed last, one after the other.\n  // (i.e. they have their own step jobs in `deploy-manual.yml` and `deploy-auto.yml`)\n  MAJOR: 'major',\n} as const\n\nexport type DatacenterType = (typeof DatacenterType)[keyof typeof DatacenterType]\n\nexport interface Datacenter {\n  name: string\n  site: string\n  type: DatacenterType\n}\n\ninterface DatacentersResponse {\n  datacenters: Array<{\n    name: string\n    site: string\n  }>\n}\n\nconst MAJOR_DCS = ['gov', 'us1', 'eu1']\n\nconst VAULT_ADDR = process.env.VAULT_ADDR || 'https://vault.us1.ddbuild.io'\nconst RUNTIME_METADATA_SERVICE_URL = 'https://runtime-metadata-service.us1.ddbuild.io/v2/datacenters'\n\nexport async function getDatacenterMetadata(name: string): Promise<Datacenter | undefined> {\n  const datacentersMetadata = await getAllDatacentersMetadata()\n\n  return datacentersMetadata.find((dc) => dc.name === name)\n}\n\nlet cachedDatacentersPromise: Promise<Datacenter[]> | undefined\n\nexport function getAllDatacentersMetadata(): Promise<Datacenter[]> {\n  if (cachedDatacentersPromise) {\n    return cachedDatacentersPromise\n  }\n\n  cachedDatacentersPromise = fetchDatacentersFromRuntimeMetadataService().then((datacenters) => {\n    const cachedDatacenters: Datacenter[] = []\n\n    for (const datacenter of datacenters) {\n      const shortName = datacenter.name.split('.')[0]\n\n      cachedDatacenters.push({\n        name: shortName,\n        site: datacenter.site,\n        type: getDatacenterType(shortName),\n      })\n    }\n\n    return cachedDatacenters\n  })\n\n  return cachedDatacentersPromise\n}\n\nasync function fetchDatacentersFromRuntimeMetadataService(): Promise<DatacentersResponse['datacenters']> {\n  const token = await getVaultToken()\n\n  // Filter for production environment and site flavor only\n  const selector = 'datacenter.environment == \"prod\" && datacenter.flavor == \"site\"'\n\n  const response = await fetchHandlingError(\n    `${RUNTIME_METADATA_SERVICE_URL}?selector=${encodeURIComponent(selector)}`,\n    {\n      headers: {\n        accept: 'application/json',\n        Authorization: `Bearer ${token}`,\n      },\n    }\n  )\n\n  const data = (await response.json()) as DatacentersResponse\n  return data.datacenters\n}\n\nasync function getVaultToken(): Promise<string> {\n  const response = await fetchHandlingError(`${VAULT_ADDR}/v1/identity/oidc/token/runtime-metadata-service`, {\n    headers: {\n      'X-Vault-Request': 'true',\n    },\n  })\n\n  const data = (await response.json()) as { data: { token: string } }\n  return data.data.token\n}\n\nfunction getDatacenterType(name: string): DatacenterType {\n  if (name.startsWith('pr')) {\n    return DatacenterType.PRIVATE\n  }\n\n  if (MAJOR_DCS.includes(name)) {\n    return DatacenterType.MAJOR\n  }\n\n  return DatacenterType.MINOR\n}\n"
  },
  {
    "path": "scripts/lib/executionUtils.spec.ts",
    "content": "import assert from 'node:assert/strict'\nimport { describe, it } from 'node:test'\nimport { findError } from './executionUtils.ts'\n\ndescribe('findError', () => {\n  it('finds the provided error', () => {\n    const error = new Error('foo')\n    assert.equal(findError(error, Error), error)\n  })\n\n  it('finds an error in the cause chain', () => {\n    class MyError extends Error {}\n    const cause = new MyError('foo')\n    const error = new Error('bar', { cause })\n    assert.equal(findError(error, MyError), cause)\n  })\n})\n"
  },
  {
    "path": "scripts/lib/executionUtils.ts",
    "content": "import util from 'node:util'\nimport { spawn } from 'node:child_process'\nimport { fetch, type RequestInit, type Response } from 'undici'\n\n/**\n * Helper to run executables asynchronously, in a shell. This function does not prevent Shell\n * injections[0], so please use carefully. Only use it to run commands with trusted arguments.\n * Prefer the `command` helper for most use cases.\n *\n * [0]: https://matklad.github.io/2021/07/30/shell-injection.html\n */\nexport function spawnCommand(command: string, args: string[]): Promise<number | null> {\n  return new Promise((resolve, reject) => {\n    const child = spawn(command, args || [], { stdio: 'inherit', shell: true })\n    child.on('error', reject)\n    child.on('close', resolve)\n    child.on('exit', resolve)\n  })\n}\n\nexport function runMain(mainFunction: () => void | Promise<void>): void {\n  Promise.resolve()\n    // The main function can be either synchronous or asynchronous, so let's wrap it in an async\n    // callback that will catch both thrown errors and rejected promises\n    .then(() => mainFunction())\n    .catch((error) => {\n      printError('\\nScript exited with error:', error)\n      process.exit(1)\n    })\n}\n\nconst resetColor = '\\x1b[0m'\nconst redColor = '\\x1b[31;1m'\nconst greenColor = '\\x1b[32;1m'\nconst yellowColor = '\\x1b[33;1m'\nconst greyColor = '\\x1b[90m'\n\nexport function printError(...params: any[]): void {\n  printWithColor(redColor, params)\n}\n\nexport function printLog(...params: any[]): void {\n  printWithColor(greenColor, params)\n}\n\nexport function printWarning(...params: any[]): void {\n  printWithColor(yellowColor, params)\n}\n\nexport function printDebug(...params: any[]): void {\n  if (process.env.DEBUG) {\n    printWithColor(greyColor, params)\n  }\n}\n\nfunction printWithColor(color: string, params: any[]): void {\n  console.log(`${color}${util.format(...params)}${resetColor}`)\n}\n\nexport function formatSize(bytes: number | null, { includeSign = false } = {}): string {\n  if (bytes === null) {\n    return 'N/A'\n  }\n\n  const sign = includeSign && bytes > 0 ? '+' : ''\n\n  if (bytes > -1024 && bytes < 1024) {\n    return `${sign}${Math.round(bytes)} B`\n  }\n\n  return `${sign}${(bytes / 1024).toFixed(2)} KiB`\n}\n\nexport function formatPercentage(percentage: number, { includeSign = false } = {}): string {\n  const sign = includeSign && percentage > 0 ? '+' : ''\n  return `${sign}${(percentage * 100).toFixed(2)}%`\n}\n\n/**\n * Find an error of type T in the provided error or its causes.\n */\nexport function findError<T>(error: unknown, type: new (...args: any[]) => T): T | undefined {\n  while (error) {\n    if (error instanceof type) {\n      return error\n    }\n    if (error instanceof Error && error.cause) {\n      error = error.cause\n    } else {\n      break\n    }\n  }\n}\n\nexport class FetchError extends Error {\n  public readonly response: Response\n\n  constructor(response: Response, options?: ErrorOptions) {\n    super(`HTTP Error Response: ${response.status} ${response.statusText}`, options)\n    this.response = response\n  }\n}\n\nexport async function createFetchError(response: Response): Promise<FetchError> {\n  let cause: unknown\n  const body = await response.text()\n  try {\n    cause = JSON.parse(body)\n  } catch {\n    cause = body\n  }\n  return new FetchError(response, { cause })\n}\n\nexport async function fetchHandlingError(url: string, options?: RequestInit): Promise<Response> {\n  const response = await fetch(url, options)\n  if (!response.ok) {\n    throw await createFetchError(response)\n  }\n\n  return response\n}\n\nexport function timeout(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n"
  },
  {
    "path": "scripts/lib/filesUtils.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport fsPromises from 'node:fs/promises'\nimport { command } from './command.ts'\n\nexport const CI_FILE = '.gitlab-ci.yml'\n\nexport function readCiFileVariable(variableName: string): string | undefined {\n  const regexp = new RegExp(`${variableName}: (.*)`)\n  const ciFileContent = fs.readFileSync(CI_FILE, { encoding: 'utf-8' })\n  return regexp.exec(ciFileContent)?.[1]\n}\n\nexport async function forEachFile(\n  directoryPath: string,\n  callback: (filePath: string) => Promise<void> | void\n): Promise<void> {\n  for (const entry of fs.readdirSync(directoryPath, { withFileTypes: true })) {\n    const entryPath = `${directoryPath}/${entry.name}`\n    if (entry.isFile()) {\n      await callback(entryPath)\n    } else if (entry.isDirectory()) {\n      await forEachFile(entryPath, callback)\n    }\n  }\n}\n\nexport async function replaceCiFileVariable(variableName: string, value: string): Promise<void> {\n  await modifyFile(CI_FILE, (content) =>\n    content.replace(new RegExp(`${variableName}: .*`), `${variableName}: ${value}`)\n  )\n}\n\n/**\n * Modify a file.\n *\n * @param filePath - {string}\n * @param modifier - {(content: string) => string | Promise<string>}\n */\nexport async function modifyFile(\n  filePath: string,\n  modifier: (content: string) => string | Promise<string>\n): Promise<boolean> {\n  const content = await fsPromises.readFile(filePath, { encoding: 'utf-8' })\n  const modifiedContent = await modifier(content)\n  if (content !== modifiedContent) {\n    await fsPromises.writeFile(filePath, modifiedContent)\n    return true\n  }\n  return false\n}\n\nexport interface PackageJsonInfo {\n  relativePath: string\n  path: string\n  content: PackageJson\n}\n\ninterface PackageJson {\n  name?: string\n  private?: boolean\n  version?: string\n  dependencies?: Record<string, string>\n  devDependencies?: Record<string, string>\n  peerDependencies?: Record<string, string>\n}\n\nexport function findPackageJsonFiles(): PackageJsonInfo[] {\n  const manifestPaths = command`git ls-files -- package.json */package.json`.run()\n  return manifestPaths\n    .trim()\n    .split('\\n')\n    .map((manifestPath) => {\n      const absoluteManifestPath = path.join(import.meta.dirname, '../..', manifestPath)\n      return {\n        relativePath: manifestPath,\n        path: absoluteManifestPath,\n        content: JSON.parse(fs.readFileSync(absoluteManifestPath, 'utf-8')),\n      }\n    })\n}\n"
  },
  {
    "path": "scripts/lib/generatedSchemaTypes.ts",
    "content": "import type { Options } from 'json-schema-to-typescript'\n\nexport interface SchemaConfig {\n  typesPath: string\n  schemaPath: string\n  options?: Partial<Options>\n}\n\nexport const SCHEMAS: SchemaConfig[] = [\n  {\n    typesPath: 'packages/rum-core/src/rumEvent.types.ts',\n    schemaPath: 'rum-events-format/schemas/rum-events-browser-schema.json',\n  },\n  {\n    typesPath: 'packages/core/src/domain/telemetry/telemetryEvent.types.ts',\n    schemaPath: 'rum-events-format/schemas/telemetry-events-schema.json',\n  },\n  {\n    typesPath: 'packages/rum/src/types/sessionReplay.ts',\n    schemaPath: 'rum-events-format/schemas/session-replay-browser-schema.json',\n    options: { additionalProperties: false },\n  },\n  {\n    typesPath: 'packages/rum/src/types/profiling.ts',\n    schemaPath: 'rum-events-format/schemas/profiling-browser-schema.json',\n    options: { additionalProperties: false },\n  },\n  {\n    typesPath: 'packages/rum-core/src/domain/configuration/remoteConfiguration.types.ts',\n    schemaPath: 'remote-configuration/rum-sdk-config.json',\n  },\n]\n"
  },
  {
    "path": "scripts/lib/gitUtils.ts",
    "content": "import os from 'node:os'\nimport fs from 'node:fs'\nimport { command } from './command.ts'\nimport {\n  getGithubDeployKey,\n  getGithubReadToken,\n  getGithubReleaseToken,\n  getGithubPullRequestToken,\n  type OctoStsToken,\n} from './secrets.ts'\nimport { FetchError, fetchHandlingError, findError } from './executionUtils.ts'\n\ninterface GitHubPR {\n  // eslint-disable-next-line id-denylist\n  number: number\n  title: string\n  body: string\n  base: {\n    ref: string\n  }\n}\n\ninterface GitHubRelease {\n  html_url: string\n}\n\ninterface GitHubReleaseParams {\n  version: string\n  body: string\n}\n\nexport async function fetchPR(localBranch: string): Promise<GitHubPR | null> {\n  using readToken = getGithubReadToken()\n  const pr = await callGitHubApi<GitHubPR[]>('GET', `pulls?head=DataDog:${localBranch}`, readToken)\n  if (pr && pr.length > 1) {\n    throw new Error('Multiple pull requests found for the branch')\n  }\n  return pr ? pr[0] : null\n}\n\n/**\n * Create a GitHub release.\n *\n * @param params - The parameters for the GitHub release.\n * @param params.version - The version to create a release for.\n * @param params.body - The body of the release.\n */\nexport async function createGitHubRelease({ version, body }: GitHubReleaseParams): Promise<GitHubRelease> {\n  using readToken = getGithubReadToken()\n  try {\n    await callGitHubApi('GET', `releases/tags/${version}`, readToken)\n    throw new Error(`Release ${version} already exists`)\n  } catch (error) {\n    const fetchError = findError(error, FetchError)\n    if (!fetchError || fetchError.response.status !== 404) {\n      throw error\n    }\n  }\n\n  // content write\n  using releaseToken = getGithubReleaseToken()\n  return await callGitHubApi<GitHubRelease>('POST', 'releases', releaseToken, {\n    tag_name: version,\n    name: version,\n    body,\n  })\n}\n\nexport function createPullRequest(mainBranch: string) {\n  using token = getGithubPullRequestToken()\n  command`gh auth login --with-token`.withInput(token.value).run()\n  const pullRequestUrl = command`gh pr create --fill --base ${mainBranch}`.run()\n  return pullRequestUrl.trim()\n}\n\nexport function getLastCommonCommit(baseBranch: string): string {\n  try {\n    command`git fetch --depth=100 origin ${baseBranch}`.run()\n    const commandOutput = command`git merge-base origin/${baseBranch} HEAD`.run()\n    return commandOutput.trim()\n  } catch (error) {\n    throw new Error('Failed to get last common commit', { cause: error })\n  }\n}\n\nexport function initGitConfig(repository: string): void {\n  const homedir = os.homedir()\n\n  // ssh-add expects a new line at the end of the PEM-formatted private key\n  // https://stackoverflow.com/a/59595773\n  command`ssh-add -`.withInput(`${getGithubDeployKey()}\\n`).run()\n  command`mkdir -p ${homedir}/.ssh`.run()\n  command`chmod 700 ${homedir}/.ssh`.run()\n  const sshHost = command`ssh-keyscan -H github.com`.run()\n  fs.appendFileSync(`${homedir}/.ssh/known_hosts`, sshHost)\n  command`git config user.email ci.browser-sdk@datadoghq.com`.run()\n  command`git config user.name ci.browser-sdk`.run()\n  command`git remote set-url origin ${repository}`.run()\n}\nexport const LOCAL_BRANCH = process.env.CI_COMMIT_REF_NAME\n\nasync function callGitHubApi<T>(method: string, path: string, token: OctoStsToken, body?: any): Promise<T> {\n  try {\n    const response = await fetchHandlingError(`https://api.github.com/repos/DataDog/browser-sdk/${path}`, {\n      method,\n      headers: {\n        Authorization: `token ${token.value}`,\n        'X-GitHub-Api-Version': '2022-11-28',\n      },\n      body: body ? JSON.stringify(body) : undefined,\n    })\n    return (await response.json()) as Promise<T>\n  } catch (error) {\n    throw new Error(`Failed to call GitHub API: ${method} ${path}`, { cause: error })\n  }\n}\n"
  },
  {
    "path": "scripts/lib/global.d.ts",
    "content": "declare module 'emoji-name-map' {\n  export function get(emoji: string): string | undefined\n}\n\n// Declare the `json-schema-to-typescript` types because the package might not be always built.\ndeclare module 'json-schema-to-typescript' {\n  export type Options = any\n  export function compileFromFile(schemaPath: string, options: Partial<Options>): Promise<string>\n}\n"
  },
  {
    "path": "scripts/lib/packagesDirectoryNames.ts",
    "content": "import { readdirSync } from 'node:fs'\n\nexport const packagesDirectoryNames: string[] = readdirSync('packages', { withFileTypes: true })\n  .filter((entry) => entry.isDirectory())\n  .map((entry) => entry.name)\n"
  },
  {
    "path": "scripts/lib/secrets.ts",
    "content": "import { command } from './command.ts'\n\nexport function getGithubDeployKey(): string {\n  return getSecretKey('ci.browser-sdk.github_deploy_key')\n}\n\nexport class OctoStsToken {\n  readonly value: string\n\n  constructor(name: string) {\n    this.value = command`dd-octo-sts token --scope DataDog/browser-sdk --policy self.gitlab.${name}`.run().trim()\n  }\n\n  [Symbol.dispose]() {\n    command`dd-octo-sts revoke --token ${this.value}`.run()\n  }\n}\n\n/**\n * This token is scoped to main branch only.\n */\nexport function getGithubPullRequestToken() {\n  return new OctoStsToken('pull_request')\n}\n\n/**\n * This token is scoped to tags only.\n */\nexport function getGithubReleaseToken() {\n  return new OctoStsToken('release')\n}\n\nexport function getGithubReadToken() {\n  return new OctoStsToken('read')\n}\n\nexport function getOrg2ApiKey(): string {\n  return getSecretKey('ci.browser-sdk.datadog_ci_api_key')\n}\n\nexport function getOrg2AppKey(): string {\n  return getSecretKey('ci.browser-sdk.datadog_ci_application_key')\n}\n\nexport function getTelemetryOrgApiKey(site: string): string | undefined {\n  const normalizedSite = site.replaceAll('.', '-')\n  try {\n    return getSecretKey(`ci.browser-sdk.source-maps.${normalizedSite}.ci_api_key`)\n  } catch {\n    return\n  }\n}\n\nexport function getTelemetryOrgApplicationKey(site: string): string | undefined {\n  const normalizedSite = site.replaceAll('.', '-')\n  try {\n    return getSecretKey(`ci.browser-sdk.telemetry.${normalizedSite}.ci_app_key`)\n  } catch {\n    return\n  }\n}\n\nexport function getNpmToken(): string {\n  return getSecretKey('ci.browser-sdk.npm_token')\n}\n\nexport function getChromeWebStoreClientId(): string {\n  return getSecretKey('ci.browser-sdk.chrome_web_store.client_id')\n}\n\nexport function getChromeWebStoreClientSecret(): string {\n  return getSecretKey('ci.browser-sdk.chrome_web_store.client_secret')\n}\n\nexport function getChromeWebStoreRefreshToken(): string {\n  return getSecretKey('ci.browser-sdk.chrome_web_store.refresh_token')\n}\n\nexport function getBrowserStackUsername(): string {\n  return getSecretKey('ci.browser-sdk.bs_username')\n}\n\nexport function getBrowserStackAccessKey(): string {\n  return getSecretKey('ci.browser-sdk.bs_access_key')\n}\n\nfunction getSecretKey(name: string): string {\n  return command`\n    aws ssm get-parameter --region=us-east-1 --with-decryption --query=Parameter.Value --out=text --name=${name}\n  `\n    .run()\n    .trim()\n}\n"
  },
  {
    "path": "scripts/performance/index.ts",
    "content": "import { printLog, runMain } from '../lib/executionUtils.ts'\nimport { fetchPR, LOCAL_BRANCH, getLastCommonCommit } from '../lib/gitUtils.ts'\nimport { Pr } from './lib/reportAsAPrComment.ts'\nimport { computeAndReportMemoryPerformance } from './lib/memoryPerformance.ts'\nimport { computeAndReportBundleSizes } from './lib/bundleSizes.ts'\nimport { computeAndReportCpuPerformance } from './lib/cpuPerformance.ts'\n\nrunMain(async () => {\n  const githubPr = await fetchPR(LOCAL_BRANCH!)\n  let pr: Pr | undefined\n  if (!githubPr) {\n    printLog('No pull requests found for the branch, reporting only (normal for main)')\n  } else {\n    const lastCommonCommit = getLastCommonCommit(githubPr.base.ref)\n    // Truncate to 8 characters to match the format used in Datadog metrics\n    pr = new Pr(githubPr.number, lastCommonCommit.substring(0, 8))\n  }\n\n  printLog('Bundle sizes...')\n  await computeAndReportBundleSizes(pr)\n\n  printLog('Memory performance...')\n  await computeAndReportMemoryPerformance(pr)\n\n  printLog('CPU performance...')\n  await computeAndReportCpuPerformance(pr)\n})\n"
  },
  {
    "path": "scripts/performance/lib/bundleSizes.ts",
    "content": "import { formatPercentage, formatSize } from '../../lib/executionUtils.ts'\nimport { calculateBundleSizes } from '../../lib/computeBundleSize.ts'\nimport type { PerformanceMetric } from './fetchPerformanceMetrics.ts'\nimport { fetchPerformanceMetrics } from './fetchPerformanceMetrics.ts'\nimport { markdownArray, type Pr } from './reportAsAPrComment.ts'\nimport { reportToDatadog } from './reportToDatadog.ts'\n\n// The value is set to 5% as it's around 10 times the average value for small PRs.\nconst SIZE_INCREASE_THRESHOLD = 5\n\nexport async function computeAndReportBundleSizes(pr?: Pr) {\n  const localBundleSizes = extractUncompressedBundleSizes(calculateBundleSizes())\n  await reportToDatadog({\n    message: 'Browser SDK bundles sizes',\n    bundle_sizes: Object.fromEntries(localBundleSizes.map(({ name, value }) => [name, value])),\n  })\n  if (!pr) {\n    return\n  }\n  let baseBundleSizes: PerformanceMetric[]\n  try {\n    baseBundleSizes = await fetchPerformanceMetrics(\n      'bundle',\n      localBundleSizes.map((bundleSize) => bundleSize.name),\n      pr.lastCommonCommit\n    )\n  } catch (e) {\n    await pr.setBundleSizes('Error fetching base bundle sizes')\n    throw e\n  }\n\n  await pr.setBundleSizes(\n    formatBundleSizes({\n      baseBundleSizes,\n      localBundleSizes,\n    })\n  )\n}\n\nfunction extractUncompressedBundleSizes(bundleSizes: Record<string, { uncompressed: number }>): PerformanceMetric[] {\n  return Object.entries(bundleSizes).map(([key, size]) => ({ name: key, value: size.uncompressed }))\n}\n\nexport function formatBundleSizes({\n  baseBundleSizes,\n  localBundleSizes,\n}: {\n  baseBundleSizes: PerformanceMetric[]\n  localBundleSizes: PerformanceMetric[]\n}) {\n  let highIncreaseDetected = false\n  let message = markdownArray({\n    headers: [\n      { label: '📦 Bundle Name', align: 'left' },\n      { label: 'Base Size', align: 'right' },\n      { label: 'Local Size', align: 'right' },\n      { label: '𝚫', align: 'right' },\n      { label: '𝚫%', align: 'right' },\n      { label: 'Status', align: 'center' },\n    ],\n    rows: localBundleSizes.map((localBundleSize) => {\n      const baseBundleSize = baseBundleSizes.find((baseBundleSize) => baseBundleSize.name === localBundleSize.name)\n\n      if (!baseBundleSize) {\n        return [formatBundleName(localBundleSize.name), 'N/A', formatSize(localBundleSize.value), 'N/A', 'N/A', 'N/A']\n      }\n\n      const percentageChange = (localBundleSize.value - baseBundleSize.value) / baseBundleSize.value\n\n      let status = '✅'\n      if (percentageChange > SIZE_INCREASE_THRESHOLD) {\n        status = '⚠️'\n        highIncreaseDetected = true\n      }\n      return [\n        formatBundleName(localBundleSize.name),\n        formatSize(baseBundleSize.value),\n        formatSize(localBundleSize.value),\n        formatSize(localBundleSize.value - baseBundleSize.value, { includeSign: true }),\n        formatPercentage(percentageChange, { includeSign: true }),\n        status,\n      ]\n    }),\n  })\n\n  if (highIncreaseDetected) {\n    message += `\\n⚠️ The increase is particularly high and exceeds ${SIZE_INCREASE_THRESHOLD}%. Please check the changes.`\n  }\n\n  return message\n}\n\nfunction formatBundleName(bundleName: string): string {\n  return bundleName\n    .split('_')\n    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n    .join(' ')\n}\n"
  },
  {
    "path": "scripts/performance/lib/constants.ts",
    "content": "export interface Test {\n  name: string\n  button: string\n  property: string\n}\n\nexport const TESTS: Test[] = [\n  {\n    name: 'RUM - add global context',\n    button: '#rum-add-global-context',\n    property: 'addglobalcontext',\n  },\n  {\n    name: 'RUM - add action',\n    button: '#rum-add-action',\n    property: 'addaction',\n  },\n  {\n    name: 'RUM - add error',\n    button: '#rum-add-error',\n    property: 'adderror',\n  },\n  {\n    name: 'RUM - add timing',\n    button: '#rum-add-timing',\n    property: 'addtiming',\n  },\n  {\n    name: 'RUM - start view',\n    button: '#rum-start-view',\n    property: 'startview',\n  },\n  {\n    name: 'RUM - start/stop session replay recording',\n    button: '#rum-start-stop-session-replay-recording',\n    property: 'startstopsessionreplayrecording',\n  },\n  {\n    name: 'Logs - log message',\n    button: '#logs-log-message',\n    property: 'logmessage',\n  },\n]\n"
  },
  {
    "path": "scripts/performance/lib/cpuPerformance.ts",
    "content": "import { fetchHandlingError, formatPercentage, timeout } from '../../lib/executionUtils.ts'\nimport { getOrg2ApiKey, getOrg2AppKey } from '../../lib/secrets.ts'\nimport { fetchPR, LOCAL_BRANCH } from '../../lib/gitUtils.ts'\nimport type { Pr } from './reportAsAPrComment.ts'\nimport { markdownArray } from './reportAsAPrComment.ts'\nimport type { PerformanceMetric } from './fetchPerformanceMetrics.ts'\nimport { fetchPerformanceMetrics } from './fetchPerformanceMetrics.ts'\nimport { TESTS } from './constants.ts'\n\nconst API_KEY = getOrg2ApiKey()\nconst APP_KEY = getOrg2AppKey()\nconst TIMEOUT_IN_MS = 15000\nconst TEST_PUBLIC_ID = 'vcg-7rk-5av'\nconst RETRIES_NUMBER = 6\nconst LOCAL_COMMIT_SHA = process.env.CI_COMMIT_SHORT_SHA\n\ninterface SyntheticsTestResult {\n  results: Array<{\n    result_id: string\n  }>\n}\n\ninterface SyntheticsTestStatus {\n  length: number\n  status?: number\n}\n\nexport async function computeAndReportCpuPerformance(pr?: Pr) {\n  const localCpuPerformances = await computeCpuPerformance()\n  // local metrics reported directly by synthetics tests\n  if (!pr) {\n    return\n  }\n  let baseCpuPerformances: PerformanceMetric[]\n  try {\n    baseCpuPerformances = await fetchPerformanceMetrics(\n      'cpu',\n      localCpuPerformances.map((cpuPerformance) => cpuPerformance.name),\n      pr.lastCommonCommit\n    )\n  } catch (error) {\n    await pr.setCpuPerformance('Error fetching base CPU performance')\n    throw error\n  }\n\n  await pr.setCpuPerformance(\n    formatCpuPerformance({\n      baseCpuPerformances,\n      localCpuPerformances,\n    })\n  )\n}\n\nasync function computeCpuPerformance(): Promise<PerformanceMetric[]> {\n  const pr = LOCAL_BRANCH ? await fetchPR(LOCAL_BRANCH) : null\n  const commitSha = LOCAL_COMMIT_SHA || ''\n  const resultId = pr\n    ? await triggerSyntheticsTest(pr.number.toString(), commitSha)\n    : await triggerSyntheticsTest('', commitSha)\n  await waitForSyntheticsTestToFinish(resultId, RETRIES_NUMBER)\n  return fetchPerformanceMetrics(\n    'cpu',\n    TESTS.map((test) => test.property),\n    LOCAL_COMMIT_SHA || ''\n  )\n}\n\nasync function triggerSyntheticsTest(prNumber: string, commitId: string): Promise<string> {\n  const body = {\n    tests: [\n      {\n        public_id: `${TEST_PUBLIC_ID}`,\n        startUrl: `https://datadoghq.dev/browser-sdk-test-playground/performance/cpu?prNumber=${prNumber}&commitId=${commitId}`,\n      },\n    ],\n  }\n  const url = 'https://api.datadoghq.com/api/v1/synthetics/tests/trigger/ci'\n  const response = await fetchHandlingError(url, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      'DD-API-KEY': API_KEY,\n      'DD-APPLICATION-KEY': APP_KEY,\n    },\n    body: JSON.stringify(body),\n  })\n  const data = (await response.json()) as SyntheticsTestResult\n  return data.results[0].result_id\n}\n\nasync function waitForSyntheticsTestToFinish(resultId: string, retriesNumber: number): Promise<void> {\n  const url = `https://api.datadoghq.com/api/v1/synthetics/tests/${TEST_PUBLIC_ID}/results/${resultId}`\n  for (let i = 0; i < retriesNumber; i++) {\n    const response = await fetch(url, {\n      method: 'GET',\n      headers: {\n        'Content-Type': 'application/json',\n        'DD-API-KEY': API_KEY,\n        'DD-APPLICATION-KEY': APP_KEY,\n      },\n    })\n    // do not use response.ok as we can have 404 responses\n    if (response.status >= 500) {\n      throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`)\n    }\n    const data = (await response.json()) as SyntheticsTestStatus\n    if (data.length !== 0 && data.status === 0) {\n      await timeout(TIMEOUT_IN_MS) // Wait for logs ingestion\n      return\n    }\n    await timeout(TIMEOUT_IN_MS)\n  }\n  throw new Error('Synthetics test did not finish within the specified number of retries')\n}\n\nfunction formatCpuPerformance({\n  baseCpuPerformances,\n  localCpuPerformances,\n}: {\n  baseCpuPerformances: PerformanceMetric[]\n  localCpuPerformances: PerformanceMetric[]\n}) {\n  return markdownArray({\n    headers: [\n      { label: 'Action Name', align: 'left' },\n      { label: 'Base CPU Time (ms)', align: 'right' },\n      { label: 'Local CPU Time (ms)', align: 'right' },\n      { label: '𝚫%', align: 'right' },\n    ],\n    rows: localCpuPerformances.map((localCpuPerformance) => {\n      const baseCpuPerformance = baseCpuPerformances.find(\n        (baseCpuPerformance) => baseCpuPerformance.name === localCpuPerformance.name\n      )\n\n      if (!baseCpuPerformance) {\n        return [localCpuPerformance.name, 'N/A', String(localCpuPerformance.value), 'N/A']\n      }\n\n      return [\n        TESTS.find((test) => test.property === localCpuPerformance.name)!.name,\n        String(baseCpuPerformance.value),\n        String(localCpuPerformance.value),\n        formatPercentage((localCpuPerformance.value - baseCpuPerformance.value) / baseCpuPerformance.value, {\n          includeSign: true,\n        }),\n      ]\n    }),\n  })\n}\n"
  },
  {
    "path": "scripts/performance/lib/fetchPerformanceMetrics.ts",
    "content": "import { getOrg2ApiKey, getOrg2AppKey } from '../../lib/secrets.ts'\nimport { fetchHandlingError } from '../../lib/executionUtils.ts'\n\nconst ONE_DAY_IN_SECOND = 24 * 60 * 60\n\ninterface DatadogResponse {\n  series?: Array<{\n    pointlist?: Array<[number, number]>\n  }>\n}\n\nexport interface PerformanceMetric {\n  name: string\n  value: number\n}\n\nexport async function fetchPerformanceMetrics(\n  type: string,\n  names: string[],\n  commitId: string\n): Promise<PerformanceMetric[]> {\n  return (await Promise.all(names.map((name) => fetchMetric(type, name, commitId)))).filter(\n    (metric): metric is PerformanceMetric => !!metric\n  )\n}\n\nasync function fetchMetric(type: string, name: string, commitId: string): Promise<PerformanceMetric | undefined> {\n  const now = Math.floor(Date.now() / 1000)\n  const date = now - 30 * ONE_DAY_IN_SECOND\n  let query = ''\n\n  switch (type) {\n    case 'bundle':\n      query = `avg:bundle_sizes.${name}{commit:${commitId}}&from=${date}&to=${now}`\n      break\n    case 'cpu':\n      query = `avg:cpu.sdk.${name}.performance.average{commitid:${commitId}}&from=${date}&to=${now}`\n      break\n    case 'memory':\n      query = `avg:memory.sdk.${name}.performance.bytes{commit:${commitId}}&from=${date}&to=${now}`\n      break\n  }\n\n  const response = await fetchHandlingError(`https://api.datadoghq.com/api/v1/query?query=${query}`, {\n    method: 'GET',\n    headers: {\n      'Content-Type': 'application/json',\n      'DD-API-KEY': getOrg2ApiKey(),\n      'DD-APPLICATION-KEY': getOrg2AppKey(),\n    },\n  })\n  const data = (await response.json()) as DatadogResponse\n  if (data.series && data.series.length > 0 && data.series[0].pointlist && data.series[0].pointlist.length > 0) {\n    return {\n      name,\n      value: data.series[0].pointlist[0][1],\n    }\n  }\n}\n"
  },
  {
    "path": "scripts/performance/lib/memoryPerformance.ts",
    "content": "import type { Browser, CDPSession, Page, Protocol } from 'puppeteer'\nimport { launch } from 'puppeteer'\nimport { fetchPR, LOCAL_BRANCH } from '../../lib/gitUtils.ts'\nimport { formatSize, printLog } from '../../lib/executionUtils.ts'\nimport { markdownArray, type Pr } from './reportAsAPrComment.ts'\nimport type { Test } from './constants.ts'\nimport { TESTS } from './constants.ts'\nimport type { PerformanceMetric } from './fetchPerformanceMetrics.ts'\nimport { fetchPerformanceMetrics } from './fetchPerformanceMetrics.ts'\nimport { reportToDatadog } from './reportToDatadog.ts'\n\nconst NUMBER_OF_RUNS = 30 // Rule of thumb: this should be enough to get a good average\nconst BATCH_SIZE = 2\n\ninterface TestRunResult {\n  medianPercentage: number\n  medianBytes: number\n}\n\nexport async function computeAndReportMemoryPerformance(pr?: Pr) {\n  const localMemoryPerformances = await computeMemoryPerformance()\n  await reportToDatadog({\n    message: 'Browser SDK memory consumption',\n    ...Object.fromEntries(localMemoryPerformances.map(({ name, value }) => [name, { memory_bytes: value }])),\n  })\n  if (!pr) {\n    return\n  }\n  let baseMemoryPerformances: PerformanceMetric[]\n  try {\n    baseMemoryPerformances = await fetchPerformanceMetrics(\n      'memory',\n      localMemoryPerformances.map((memoryPerformance) => memoryPerformance.name),\n      pr.lastCommonCommit\n    )\n  } catch (error) {\n    await pr.setMemoryPerformance('Error fetching base memory performance')\n    throw error\n  }\n\n  await pr.setMemoryPerformance(\n    formatMemoryPerformance({\n      baseMemoryPerformances,\n      localMemoryPerformances,\n    })\n  )\n}\n\nexport async function computeMemoryPerformance(): Promise<PerformanceMetric[]> {\n  const results: PerformanceMetric[] = []\n  const pr = LOCAL_BRANCH ? await fetchPR(LOCAL_BRANCH) : null\n  const benchmarkUrl = pr\n    ? `https://datadoghq.dev/browser-sdk-test-playground/performance/memory?prNumber=${pr.number}`\n    : 'https://datadoghq.dev/browser-sdk-test-playground/performance/memory'\n\n  for (let i = 0; i < TESTS.length; i += BATCH_SIZE) {\n    await runTests(TESTS.slice(i, i + BATCH_SIZE), benchmarkUrl, (result) => results.push(result))\n  }\n\n  return results\n}\n\nasync function runTests(tests: Test[], benchmarkUrl: string, cb: (result: PerformanceMetric) => void): Promise<void> {\n  await Promise.all(\n    tests.map(async (test) => {\n      const testName = test.name\n      const testButton = test.button\n      const allBytesMeasurements: number[] = []\n      const allPercentageMeasurements: number[] = []\n      printLog(`Running test for: ${testButton}`)\n      for (let j = 0; j < NUMBER_OF_RUNS; j++) {\n        const { medianPercentage, medianBytes } = await runTest(testButton, benchmarkUrl)\n        allPercentageMeasurements.push(medianPercentage)\n        allBytesMeasurements.push(medianBytes)\n      }\n      const sdkMemoryPercentage = average(allPercentageMeasurements)\n      const sdkMemoryBytes = average(allBytesMeasurements)\n      printLog(\n        `Average percentage of memory used by SDK for ${testName} over ${NUMBER_OF_RUNS} runs: ${sdkMemoryPercentage}%  for ${sdkMemoryBytes} bytes`\n      )\n      cb({ name: test.property, value: sdkMemoryBytes })\n    })\n  )\n}\n\nasync function runTest(testButton: string, benchmarkUrl: string): Promise<TestRunResult> {\n  const browser: Browser = await launch({\n    args: ['--no-sandbox', '--disable-setuid-sandbox'],\n  })\n  const page: Page = await browser.newPage()\n  await page.goto(benchmarkUrl)\n\n  // Start the Chrome DevTools Protocol session and enable the heap profiler\n  const client: CDPSession = await page.target().createCDPSession()\n  await client.send('HeapProfiler.enable')\n\n  // Select the button to trigger the test\n  await page.waitForSelector(testButton)\n  const button = await page.$(testButton)\n  if (!button) {\n    throw new Error(`Button ${testButton} not found`)\n  }\n\n  await client.send('HeapProfiler.collectGarbage')\n\n  // Start the heap profiler sampling\n  await client.send('HeapProfiler.startSampling', {\n    samplingInterval: 50,\n  })\n\n  await button.click()\n  const { profile } = await client.send('HeapProfiler.stopSampling')\n  const measurementsPercentage: number[] = []\n  const measurementsBytes: number[] = []\n  const sizeForNodeId = new Map<number, number>()\n\n  for (const sample of profile.samples) {\n    sizeForNodeId.set(sample.nodeId, (sizeForNodeId.get(sample.nodeId) || 0) + sample.size)\n    let totalSize = 0\n    let sdkConsumption = 0\n    for (const node of children(profile.head)) {\n      const consumption = sizeForNodeId.get(node.id) || 0\n      totalSize += consumption\n      if (isSdkBundleUrl(node.callFrame.url)) {\n        sdkConsumption += consumption\n      }\n    }\n    const sdkPercentage = (sdkConsumption / totalSize) * 100\n    measurementsBytes.push(sdkConsumption)\n    measurementsPercentage.push(sdkPercentage)\n  }\n\n  const medianPercentage = median(measurementsPercentage)\n  const medianBytes = median(measurementsBytes)\n  await browser.close()\n  return { medianPercentage, medianBytes }\n}\n\nfunction* children(\n  node: Protocol.HeapProfiler.SamplingHeapProfileNode\n): Generator<Protocol.HeapProfiler.SamplingHeapProfileNode> {\n  yield node\n  for (const child of node.children || []) {\n    yield* children(child)\n  }\n}\n\nfunction isSdkBundleUrl(url: string): boolean {\n  return (\n    url.startsWith('https://www.datad0g-browser-agent.com/') ||\n    url.startsWith('https://www.datadoghq-browser-agent.com/')\n  )\n}\n\nfunction average(values: number[]): number {\n  return Number((values.reduce((a, b) => a + b, 0) / values.length).toFixed(2))\n}\n\nfunction median(values: number[]): number {\n  values.sort((a, b) => a - b)\n  return values[Math.floor(values.length / 2)]\n}\n\nfunction formatMemoryPerformance({\n  baseMemoryPerformances,\n  localMemoryPerformances,\n}: {\n  baseMemoryPerformances: PerformanceMetric[]\n  localMemoryPerformances: PerformanceMetric[]\n}) {\n  return markdownArray({\n    headers: [\n      { label: 'Action Name', align: 'left' },\n      { label: 'Base Memory Consumption', align: 'right' },\n      { label: 'Local Memory Consumption', align: 'right' },\n      { label: '𝚫', align: 'right' },\n    ],\n    rows: localMemoryPerformances.map((localMemoryPerformance) => {\n      const baseMemoryPerformance = baseMemoryPerformances.find(\n        (baseMemoryPerformance) => baseMemoryPerformance.name === localMemoryPerformance.name\n      )\n\n      if (!baseMemoryPerformance) {\n        return [localMemoryPerformance.name, 'N/A', formatSize(localMemoryPerformance.value), 'N/A']\n      }\n\n      return [\n        TESTS.find((test) => test.property === localMemoryPerformance.name)!.name,\n        formatSize(baseMemoryPerformance.value),\n        formatSize(localMemoryPerformance.value),\n        formatSize(localMemoryPerformance.value - baseMemoryPerformance.value, {\n          includeSign: true,\n        }),\n      ]\n    }),\n  })\n}\n"
  },
  {
    "path": "scripts/performance/lib/reportAsAPrComment.spec.ts",
    "content": "import assert from 'node:assert/strict'\nimport { describe, it, mock } from 'node:test'\nimport type { fetch, Response } from 'undici'\nimport { mockModule } from '../../deploy/lib/testHelpers.ts'\n\ndescribe('PrComment', () => {\n  it('should send a comment with performance results', async () => {\n    const fetchMock = mock.fn<typeof fetch>()\n    fetchMock.mock.mockImplementation(() => Promise.resolve({ ok: true } as Response))\n    await mockModule('undici', { fetch: fetchMock })\n    const { Pr } = await import('./reportAsAPrComment.ts')\n\n    const pr = new Pr(123, 'abc')\n\n    await pr.setBundleSizes('RUM: 10KB')\n\n    const [url, options] = fetchMock.mock.calls[0].arguments\n    assert.equal(url, 'https://pr-commenter.us1.ddbuild.io/internal/cit/pr-comment')\n\n    const { body } = options as RequestInit\n    const payload = JSON.parse(body as string)\n    assert.equal(payload.pr_url, 'https://github.com/DataDog/browser-sdk/pull/123')\n    assert.equal(payload.header, 'Bundles Sizes Evolution')\n    assert.equal(payload.org, 'DataDog')\n    assert.equal(payload.repo, 'browser-sdk')\n    assert.equal(\n      payload.message,\n      `\nRUM: 10KB\n\n<details>\n<summary>🚀 CPU Performance</summary>\n\nPending...\n\n</details>\n\n<details>\n<summary>🧠 Memory Performance</summary>\n\nPending...\n\n</details>\n\n🔗 [RealWorld](https://datadoghq.dev/browser-sdk-test-playground/realworld-scenario/?prNumber=123)\n`\n    )\n  })\n})\n"
  },
  {
    "path": "scripts/performance/lib/reportAsAPrComment.ts",
    "content": "import { command } from '../../lib/command.ts'\nimport { fetchHandlingError } from '../../lib/executionUtils.ts'\n\nconst PR_COMMENT_HEADER = 'Bundles Sizes Evolution'\nconst PR_COMMENTER_AUTH_TOKEN = command`authanywhere --raw`.run()\n\nexport class Pr {\n  prNumber: number\n  lastCommonCommit: string\n  bundleSizesSection: string = 'Pending...'\n  memoryPerformanceSection: string = 'Pending...'\n  cpuPerformanceSection: string = 'Pending...'\n\n  constructor(prNumber: number, lastCommonCommit: string) {\n    this.prNumber = prNumber\n    this.lastCommonCommit = lastCommonCommit\n  }\n\n  async setBundleSizes(newSection: string) {\n    this.bundleSizesSection = newSection\n    await this.updateComment()\n  }\n\n  async setMemoryPerformance(newSection: string) {\n    this.memoryPerformanceSection = newSection\n    await this.updateComment()\n  }\n\n  async setCpuPerformance(newSection: string) {\n    this.cpuPerformanceSection = newSection\n    await this.updateComment()\n  }\n\n  formatComment() {\n    return `\n${this.bundleSizesSection}\n\n<details>\n<summary>🚀 CPU Performance</summary>\n\n${this.cpuPerformanceSection}\n\n</details>\n\n<details>\n<summary>🧠 Memory Performance</summary>\n\n${this.memoryPerformanceSection}\n\n</details>\n\n🔗 [RealWorld](https://datadoghq.dev/browser-sdk-test-playground/realworld-scenario/?prNumber=${this.prNumber})\n`\n  }\n\n  async updateComment() {\n    await updatePrComment(this.prNumber, this.formatComment())\n  }\n}\n\nasync function updatePrComment(prNumber: number, message: string): Promise<void> {\n  const payload = {\n    pr_url: `https://github.com/DataDog/browser-sdk/pull/${prNumber}`,\n    message,\n    header: PR_COMMENT_HEADER,\n    org: 'DataDog',\n    repo: 'browser-sdk',\n  }\n  await fetchHandlingError('https://pr-commenter.us1.ddbuild.io/internal/cit/pr-comment', {\n    method: 'PATCH',\n    headers: {\n      Authorization: `Bearer ${PR_COMMENTER_AUTH_TOKEN}`,\n    },\n    body: JSON.stringify(payload),\n  })\n}\n\ninterface MarkdownArrayOptions {\n  headers: Array<{ label: string; align: 'left' | 'right' | 'center' }>\n  rows: string[][]\n}\n\nexport function markdownArray({ headers, rows }: MarkdownArrayOptions): string {\n  let markdown = `| ${headers.map((header) => header.label).join(' | ')} |\\n`\n  markdown += `| ${headers.map((header) => align(header.align)).join(' | ')} |\\n`\n\n  rows.forEach((row) => {\n    markdown += `| ${row.join(' | ')} |\\n`\n  })\n  return markdown\n}\n\nfunction align(align: 'left' | 'right' | 'center') {\n  if (align === 'center') {\n    return ':---:'\n  } else if (align === 'right') {\n    return '---:'\n  }\n\n  return '---'\n}\n"
  },
  {
    "path": "scripts/performance/lib/reportToDatadog.ts",
    "content": "import { fetchHandlingError } from '../../lib/executionUtils.ts'\nimport { getOrg2ApiKey } from '../../lib/secrets.ts'\nimport { browserSdkVersion } from '../../lib/browserSdkVersion.ts'\n\nexport async function reportToDatadog(\n  logData: Record<string, number | string | Record<string, number>>\n): Promise<void> {\n  await fetchHandlingError('https://http-intake.logs.datadoghq.com/api/v2/logs', {\n    method: 'POST',\n    headers: {\n      'DD-API-KEY': getOrg2ApiKey(),\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify([\n      {\n        service: 'browser-sdk',\n        ddsource: 'browser-sdk',\n        env: 'ci',\n        version: browserSdkVersion,\n        commit: process.env.CI_COMMIT_SHORT_SHA,\n        branch: process.env.CI_COMMIT_REF_NAME,\n        ...logData,\n      },\n    ]),\n  })\n}\n"
  },
  {
    "path": "scripts/release/check-release.ts",
    "content": "import { browserSdkVersion as releaseVersion } from '../lib/browserSdkVersion.ts'\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { checkPackageJsonFiles } from '../lib/checkBrowserSdkPackageJsonFiles.ts'\n\nrunMain(() => {\n  checkGitTag()\n  checkPackageJsonFiles()\n\n  printLog('Release check done.')\n})\n\nfunction checkGitTag(): void {\n  printLog('Checking release version tag is on HEAD')\n  const headRef = command`git rev-parse HEAD`.run()\n  let tagRef: string\n  try {\n    tagRef = command`git rev-list -n 1 v${releaseVersion} --`.run()\n  } catch (error) {\n    throw new Error(`Failed to find git tag reference: ${error as string}`)\n  }\n  if (tagRef !== headRef) {\n    throw new Error('Git tag not on HEAD')\n  }\n}\n"
  },
  {
    "path": "scripts/release/create-github-release.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { createGitHubRelease } from '../lib/gitUtils.ts'\nimport { printLog, runMain } from '../lib/executionUtils.ts'\n\ninterface ReleaseInfo {\n  version: string\n  body: string\n}\n\ninterface GitHubReleaseResponse {\n  html_url: string\n}\n\nrunMain(async () => {\n  const requestedVersion = process.argv[2]\n  printLog(`Creating GitHub release for ${requestedVersion ? `version ${requestedVersion}` : 'latest version'}`)\n  const versionAndBody = getReleaseVersionAndBody(requestedVersion)\n  const response = (await createGitHubRelease(versionAndBody)) as GitHubReleaseResponse\n  printLog(`GitHub release created: ${response.html_url}`)\n})\n\n/**\n * Get the version and body of the release to create.\n *\n * @param requestedVersion - The version to create a release for.\n * @return The version and body for the release\n */\nfunction getReleaseVersionAndBody(requestedVersion?: string): ReleaseInfo {\n  for (const { version, body } of iterReleases()) {\n    if (!requestedVersion || version === requestedVersion) {\n      return { version, body }\n    }\n  }\n\n  throw new Error('No releases found in CHANGELOG.md')\n}\n\n/**\n * Iterate over the releases in the CHANGELOG.md file.\n *\n * @returns An iterator of releases\n */\nfunction* iterReleases(): Iterable<ReleaseInfo> {\n  const changelog = readFileSync('CHANGELOG.md', 'utf8')\n  const titleMatches = changelog.matchAll(/^## (v\\d+\\.\\d+\\.\\d+)/gm)\n  let titleMatch = titleMatches.next().value as RegExpMatchArray | undefined\n  while (titleMatch) {\n    const nextTitleMatch = titleMatches.next().value as RegExpMatchArray | undefined\n    const version = titleMatch[1]\n    const body = changelog.slice(titleMatch.index! + titleMatch[0].length, nextTitleMatch?.index).trim()\n    yield { version, body }\n    titleMatch = nextTitleMatch\n  }\n}\n"
  },
  {
    "path": "scripts/release/generate-changelog/index.ts",
    "content": "import { command } from '../../lib/command.ts'\nimport { spawnCommand, printError, runMain } from '../../lib/executionUtils.ts'\nimport { modifyFile } from '../../lib/filesUtils.ts'\nimport { addNewChangesToChangelog } from './lib/addNewChangesToChangelog.ts'\nimport { CHANGELOG_FILE } from './lib/constants.ts'\n\nrunMain(async () => {\n  if (!process.env.EDITOR) {\n    printError('Please configure your environment variable EDITOR')\n    process.exit(1)\n  }\n\n  await modifyFile(CHANGELOG_FILE, addNewChangesToChangelog)\n\n  await spawnCommand(process.env.EDITOR, [CHANGELOG_FILE])\n\n  command`yarn run prettier --write ${CHANGELOG_FILE}`.run()\n\n  command`git add ${CHANGELOG_FILE}`.run()\n})\n"
  },
  {
    "path": "scripts/release/generate-changelog/lib/addNewChangesToChangelog.ts",
    "content": "import { readFile } from 'node:fs/promises'\nimport * as fs from 'node:fs'\nimport * as emojiNameMap from 'emoji-name-map'\n\nimport { browserSdkVersion } from '../../../lib/browserSdkVersion.ts'\nimport { command } from '../../../lib/command.ts'\nimport { getAffectedPackages } from './getAffectedPackages.ts'\nimport { CHANGELOG_FILE, CONTRIBUTING_FILE, PUBLIC_EMOJI_PRIORITY, INTERNAL_EMOJI_PRIORITY } from './constants.ts'\n\nconst FIRST_EMOJI_REGEX = /\\p{Extended_Pictographic}/u\n\n/**\n * Add new changes to the changelog.\n *\n * @param previousContent - {string}\n * @returns {Promise<string>}\n */\nexport const addNewChangesToChangelog = async (previousContent: string): Promise<string> => {\n  const emojisLegend = await getEmojisLegend()\n  const changeLists = getChangeLists()\n\n  return `\\\n# Changelog\n\n${emojisLegend}\n\n---\n\n## v${browserSdkVersion}\n\n${changeLists}\n${previousContent.slice(previousContent.indexOf('\\n##'))}`\n}\n\nasync function getEmojisLegend(): Promise<string> {\n  const contributing = await readFile(CONTRIBUTING_FILE, { encoding: 'utf-8' })\n  let collectLines = false\n\n  const lines = ['> **Legend**']\n\n  for (const line of contributing.split('\\n')) {\n    if (line.startsWith('### User-facing changes')) {\n      collectLines = true\n    } else if (collectLines) {\n      if (line.startsWith('#')) {\n        break\n      } else if (line) {\n        lines.push('>', `> ${line}`)\n      }\n    }\n  }\n\n  lines.push('>', '> See [Gitmoji](https://gitmoji.dev/) for a guide on the emojis used.')\n\n  return lines.join('\\n')\n}\n\nfunction getChangeLists(): string {\n  const lastTagName = getLastReleaseTagName()\n  const commits = command`git log ${[`${lastTagName}..HEAD`, '--pretty=format:%H %s']}`.run().split('\\n')\n\n  const internalChanges: string[] = []\n  const publicChanges: string[] = []\n\n  commits.forEach((commit) => {\n    const spaceIndex = commit.indexOf(' ')\n    const hash = commit.slice(0, spaceIndex)\n    const message = commit.slice(spaceIndex + 1)\n    if (isVersionMessage(message) || isStagingBumpMessage(message)) {\n      return\n    }\n\n    const change = formatChange(hash, message)\n    const emoji = findFirstEmoji(change)\n    if (PUBLIC_EMOJI_PRIORITY.includes(emoji || '')) {\n      publicChanges.push(change)\n    } else {\n      internalChanges.push(change)\n    }\n  })\n\n  return [\n    formatChangeList('Public Changes', publicChanges, PUBLIC_EMOJI_PRIORITY),\n    formatChangeList('Internal Changes', internalChanges, INTERNAL_EMOJI_PRIORITY),\n  ]\n    .filter(Boolean)\n    .join('\\n\\n')\n}\n\nfunction getLastReleaseTagName(): string {\n  const changelog = fs.readFileSync(CHANGELOG_FILE, { encoding: 'utf-8' })\n  const match = changelog.match(/^## (v\\d+\\.\\d+\\.\\d+.*)/m)\n  if (!match) {\n    throw new Error('Could not find the last release version in the changelog')\n  }\n  return match[1]\n}\n\nfunction sortByEmojiPriority(a: string, b: string, priorityList: string[]): number {\n  const getFirstRelevantEmojiIndex = (text: string): number => {\n    const emoji = findFirstEmoji(text)\n    return emoji && priorityList.includes(emoji) ? priorityList.indexOf(emoji) : Number.MAX_VALUE\n  }\n  return getFirstRelevantEmojiIndex(a) - getFirstRelevantEmojiIndex(b)\n}\n\nfunction formatChangeList(title: string, changes: string[], priority: string[]): string {\n  if (!changes.length) {\n    return ''\n  }\n\n  const formatedList = changes.sort((a, b) => sortByEmojiPriority(a, b, priority)).join('\\n')\n  return `**${title}:**\\n\\n${formatedList}`\n}\n\nfunction formatChange(hash: string, message: string): string {\n  let change = `- ${message}`\n\n  const affectedPackages = getAffectedPackages(hash)\n  if (affectedPackages.length > 0) {\n    const formattedPackages = affectedPackages\n      .map((packageDirectoryName) => `[${packageDirectoryName.toUpperCase()}]`)\n      .join(' ')\n    change += ` ${formattedPackages}`\n  }\n\n  return addLinksToGithubIssues(emojiNameToUnicode(change))\n}\n\nfunction emojiNameToUnicode(message: string): string {\n  return message.replace(/:[^:\\s]*(?:::[^:\\s]*)*:/g, (emoji) => emojiNameMap.get(emoji) || emoji)\n}\n\nfunction addLinksToGithubIssues(message: string): string {\n  return message.replace(/\\(#(\\d+)\\)/gm, (_, id) => `([#${id}](https://github.com/DataDog/browser-sdk/pull/${id}))`)\n}\n\nfunction findFirstEmoji(message: string): string | undefined {\n  return message.match(FIRST_EMOJI_REGEX)?.[0]\n}\n\nfunction isVersionMessage(line: string): boolean {\n  return /^v\\d+\\.\\d+\\.\\d+/.test(line)\n}\n\nfunction isStagingBumpMessage(line: string): boolean {\n  return /Bump staging to staging-\\d+/.test(line)\n}\n"
  },
  {
    "path": "scripts/release/generate-changelog/lib/constants.ts",
    "content": "export const CONTRIBUTING_FILE = 'docs/DEVELOPMENT.md'\nexport const CHANGELOG_FILE = 'CHANGELOG.md'\nexport const PUBLIC_EMOJI_PRIORITY: string[] = ['💥', '✨', '🐛', '⚡', '📝']\nexport const INTERNAL_EMOJI_PRIORITY: string[] = [\n  '👷',\n  '🔧',\n  '📦', // build conf\n  '♻️',\n  '🎨', // refactoring\n  '🧪',\n  '✅', // tests\n  '🔇',\n  '🔊', // telemetry\n  '👌',\n  '📄',\n  '⚗️', // experiment\n]\n"
  },
  {
    "path": "scripts/release/generate-changelog/lib/getAffectedPackages.ts",
    "content": "import * as fs from 'node:fs'\nimport { packagesDirectoryNames } from '../../../lib/packagesDirectoryNames.ts'\nimport { command } from '../../../lib/command.ts'\n\ninterface PackageJson {\n  dependencies?: Record<string, string>\n}\n\nconst PACKAGES_REVERSE_DEPENDENCIES = (() => {\n  const result = new Map<string, Set<string>>()\n  packagesDirectoryNames.forEach((packageDirectoryName: string) => {\n    for (const dependency of getDepenciesRecursively(packageDirectoryName)) {\n      if (!result.has(dependency)) {\n        result.set(dependency, new Set<string>())\n      }\n      result.get(dependency)!.add(packageDirectoryName)\n    }\n  })\n  return result\n})()\n\nexport const getAffectedPackages = (hash: string): string[] => {\n  const changedFiles = command`git diff-tree --no-commit-id --name-only -r ${hash}`.run().trim().split('\\n')\n  const affectedPackages = new Set<string>()\n\n  changedFiles.forEach((filePath: string) => {\n    const packageDirectoryName = getPackageDirectoryNameFromFilePath(filePath)\n    if (packageDirectoryName) {\n      if (!isToplevelPackage(packageDirectoryName)) {\n        PACKAGES_REVERSE_DEPENDENCIES.get(packageDirectoryName)?.forEach((dependentPackageDirectoryName: string) => {\n          if (isToplevelPackage(dependentPackageDirectoryName)) {\n            affectedPackages.add(dependentPackageDirectoryName)\n          }\n        })\n      } else {\n        affectedPackages.add(packageDirectoryName)\n      }\n    }\n  })\n\n  return Array.from(affectedPackages)\n}\n\nfunction getPackageDirectoryNameFromFilePath(filePath: string): string | undefined {\n  if (filePath.startsWith('packages/')) {\n    return filePath.split('/')[1]\n  }\n}\n\nfunction isToplevelPackage(packageDirectoryName: string): boolean {\n  return !PACKAGES_REVERSE_DEPENDENCIES.has(packageDirectoryName)\n}\n\nfunction getPackageDirectoryNameFromPackageName(packageName: string): string | undefined {\n  if (packageName.startsWith('@datadog/browser-')) {\n    return packageName.slice('@datadog/browser-'.length)\n  }\n}\n\nfunction getDepenciesRecursively(packageDirectoryName: string): Set<string> {\n  const packageDirectoryNameJson: PackageJson = JSON.parse(\n    fs.readFileSync(`packages/${packageDirectoryName}/package.json`, { encoding: 'utf-8' })\n  )\n  const dependencies = new Set<string>()\n  if (packageDirectoryNameJson.dependencies) {\n    for (const dependencyPackageName of Object.keys(packageDirectoryNameJson.dependencies)) {\n      const packageDirectoryName = getPackageDirectoryNameFromPackageName(dependencyPackageName)\n      if (packageDirectoryName) {\n        dependencies.add(packageDirectoryName)\n        for (const transitiveDependency of getDepenciesRecursively(packageDirectoryName)) {\n          dependencies.add(transitiveDependency)\n        }\n      }\n    }\n  }\n  return dependencies\n}\n"
  },
  {
    "path": "scripts/release/prepare-release.ts",
    "content": "import fs from 'node:fs'\nimport { parseArgs } from 'node:util'\nimport { runMain, printLog } from '../lib/executionUtils.ts'\nimport { findPackageJsonFiles } from '../lib/filesUtils.ts'\nimport { command } from '../lib/command.ts'\n\nrunMain(() => {\n  const {\n    positionals: [version],\n    values: { push },\n  } = parseArgs({\n    allowPositionals: true,\n    options: {\n      push: { type: 'boolean', default: false },\n    },\n  })\n\n  if (!isSemanticVersion(version)) {\n    throw new Error('Missing or invalid version argument. Usage: node scripts/release/prepare-release.ts <version>')\n  }\n\n  if (command`git status --porcelain`.run().trim()) {\n    throw new Error('Git working tree is not clean')\n  }\n\n  const releaseBranch = `release/v${version}`\n  const currentBranch = command`git branch --show-current`.run().trim()\n  if (currentBranch !== releaseBranch) {\n    printLog(`Checking out ${releaseBranch} branch...`)\n    command`git fetch origin`.run()\n    command`git checkout -b ${releaseBranch} origin/main`.run()\n  }\n\n  printLog(`Preparing release v${version}...`)\n\n  command`yarn`.withLogs().run() // Just in case\n\n  setVersionInPackageJsonFiles(version)\n  command`node ./scripts/release/generate-changelog/index.ts`.withLogs().run()\n  command`yarn`.run() // Update lockfile\n  command`git add -u`.run()\n  command`git commit -m v${version}`.run()\n  command`git tag -a v${version} -m v${version}`.run()\n\n  if (push) {\n    command`git push origin ${releaseBranch} v${version}`.withLogs().run()\n  }\n\n  printLog(`Release v${version} prepared successfully!`)\n  printLog('Next steps:')\n  if (!push) {\n    printLog(`  * git push origin ${releaseBranch} v${version}`)\n  }\n  printLog(`  * Open a PR from ${releaseBranch} to main`)\n  printLog('  * Ask for a review and merge the PR')\n  printLog('  * Go to the CI and trigger the deployment pipeline')\n})\n\nfunction setVersionInPackageJsonFiles(version: string) {\n  const packageJsonFiles = findPackageJsonFiles()\n\n  for (const { path: absolutePath, content } of packageJsonFiles) {\n    if (isSemanticVersion(content.version)) {\n      content.version = version\n    }\n    for (const depField of ['dependencies', 'peerDependencies', 'devDependencies'] as const) {\n      if (!content[depField]) {\n        continue\n      }\n\n      for (const [key, value] of Object.entries(content[depField])) {\n        if (key.startsWith('@datadog/browser-') && isSemanticVersion(value)) {\n          content[depField][key] = version\n        }\n      }\n    }\n\n    fs.writeFileSync(absolutePath, `${JSON.stringify(content, null, 2)}\\n`)\n  }\n}\n\nfunction isSemanticVersion(input: string | undefined): boolean {\n  return input !== undefined && /^\\d+\\.\\d+\\.\\d+$/.test(input)\n}\n"
  },
  {
    "path": "scripts/release/renew-token.ts",
    "content": "import { createInterface } from 'node:readline/promises'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { Writable } from 'node:stream'\nimport { printError, printLog, runMain } from '../lib/executionUtils.ts'\nimport { findPackageJsonFiles } from '../lib/filesUtils.ts'\nimport { command } from '../lib/command.ts'\n\nconst TOKEN_NAME = 'browser-sdk-granular'\n\nrunMain(async () => {\n  if (getLoggedInUser() !== 'datadog') {\n    printError('You must be logged in as datadog. Run `npm login` and try again.')\n    process.exit(1)\n  }\n\n  const accessToken = findAccessTokenFromNpmrc()\n  if (!accessToken) {\n    printError('Could not find NPM token in ~/.npmrc. Make sure you have logged in with `npm login`')\n    process.exit(1)\n  }\n\n  const password = await prompt({ question: 'npmjs.com password: ', showOutput: false })\n  const otp = await prompt({ question: 'npmjs.com OTP: ' })\n\n  const { objects: tokens } = await callNpmApi<{\n    objects: Array<{ name: string; key: string }>\n  }>({\n    route: 'tokens',\n    method: 'GET',\n    otp,\n    accessToken,\n  })\n\n  const existingToken = tokens.find((token) => token.name === TOKEN_NAME)\n  if (existingToken) {\n    printLog('Token already exists, removing it')\n    await callNpmApi({\n      route: `tokens/token/${existingToken.key}`,\n      method: 'DELETE',\n      otp,\n      accessToken,\n    })\n  }\n\n  const result = await callNpmApi<{ token: string }>({\n    route: 'tokens',\n    method: 'POST',\n    body: {\n      password,\n      name: TOKEN_NAME,\n      token_description: 'Token used to publish Browser SDK packages (@datadog/browser-*) from the CI.',\n      expires: 90,\n      bypass_2fa: true,\n      packages: findPublisheablePackages(),\n      packages_and_scopes_permission: 'read-write',\n    },\n    otp,\n    accessToken,\n  })\n\n  printLog('Token created')\n\n  printLog('Updating AWS SSM parameter...')\n  command`\n    aws-vault exec sso-build-stable-developer -- aws ssm put-parameter --region=us-east-1 --name=ci.browser-sdk.npm_token --value=${result.token} --type SecureString --overwrite\n  `\n    .withLogs()\n    .run()\n\n  printLog('All done!')\n})\n\nfunction getLoggedInUser() {\n  try {\n    return command`npm whoami`.run().trim()\n  } catch {\n    return undefined\n  }\n}\n\nasync function callNpmApi<T>({\n  route,\n  method,\n  body,\n  otp,\n  accessToken,\n}: {\n  route: string\n  method: string\n  body?: any\n  otp: string\n  accessToken: string\n}): Promise<T> {\n  // https://api-docs.npmjs.com/#tag/Tokens/operation/createToken\n  const response = await fetch(`https://registry.npmjs.org/-/npm/v1/${route}`, {\n    method,\n    headers: {\n      'Content-Type': 'application/json',\n      Accept: 'application/json',\n      Authorization: `Bearer ${accessToken}`,\n      'npm-otp': otp,\n    },\n    body: body && JSON.stringify(body),\n  })\n\n  const responseBody: any = await response.text().then((text) => {\n    try {\n      return JSON.parse(text) as unknown\n    } catch {\n      return text\n    }\n  })\n\n  if (!response.ok) {\n    printError('Failed to renew token.')\n    printError(`NPM API '${method} ${route}' responded with ${response.statusText}`)\n    printError(responseBody.error || responseBody)\n    process.exit(1)\n  }\n\n  return responseBody as T\n}\n\nfunction findPublisheablePackages() {\n  const files = findPackageJsonFiles()\n  return files\n    .filter(({ content }) => content.version && content.name && !content.private)\n    .map(({ content }) => content.name as string)\n}\n\nfunction findAccessTokenFromNpmrc() {\n  const npmrcPath = path.join(os.homedir(), '.npmrc')\n  try {\n    return fs.readFileSync(npmrcPath, 'utf-8').match(/_authToken=(.*)/)?.[1]\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      return undefined\n    }\n    throw error\n  }\n}\n\nasync function prompt({ question, showOutput = true }: { question: string; showOutput?: boolean }) {\n  if (!showOutput) {\n    process.stdout.write(question)\n  }\n\n  const readline = createInterface({\n    input: process.stdin,\n    output: showOutput\n      ? process.stdout\n      : new Writable({\n          write(_chunk, _encoding, callback) {\n            callback()\n          },\n        }),\n    terminal: true,\n  })\n\n  const value = await readline.question(question)\n  readline.close()\n  if (!showOutput) {\n    process.stdout.write('\\n')\n  }\n  return value\n}\n"
  },
  {
    "path": "scripts/show-bundle-size.ts",
    "content": "import { calculateBundleSizes } from './lib/computeBundleSize.ts'\nimport { formatSize, printLog, runMain } from './lib/executionUtils.ts'\n\nconst COL_WIDTH = 12\n\nrunMain(() => {\n  const bundleSizes = calculateBundleSizes()\n\n  printRow('Bundle', 'Size', 'Gzip')\n  printRow('-'.repeat(COL_WIDTH), '-'.repeat(COL_WIDTH), '-'.repeat(COL_WIDTH))\n\n  for (const [key, size] of Object.entries(bundleSizes)) {\n    printRow(key, formatSize(size.uncompressed), formatSize(size.gzipped))\n  }\n})\n\nfunction printRow(key: string, ...values: string[]): void {\n  printLog(`${key.padEnd(COL_WIDTH)} | ${values.map((value) => value.padStart(COL_WIDTH)).join(' | ')}`)\n}\n"
  },
  {
    "path": "scripts/staging-ci/check-squash-into-staging.ts",
    "content": "import { printLog, printError, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { initGitConfig } from '../lib/gitUtils.ts'\n\nconst REPOSITORY = process.env.GIT_REPOSITORY\nconst CI_COMMIT_SHA = process.env.CI_COMMIT_SHA\nconst CI_COMMIT_SHORT_SHA = process.env.CI_COMMIT_SHORT_SHA\nconst CI_COMMIT_REF_NAME = process.env.CI_COMMIT_REF_NAME\nconst MAIN_BRANCH = process.env.MAIN_BRANCH\n\nrunMain(() => {\n  if (!REPOSITORY || !CI_COMMIT_SHA || !CI_COMMIT_SHORT_SHA || !CI_COMMIT_REF_NAME || !MAIN_BRANCH) {\n    throw new Error('Missing required environment variables')\n  }\n\n  initGitConfig(REPOSITORY)\n  command`git fetch --no-tags origin ${MAIN_BRANCH}`.run()\n  const ciConfigurationFromMain = command`git show origin/${MAIN_BRANCH}:.gitlab-ci.yml`.run()\n  const currentStaging = /CURRENT_STAGING: (staging-.*)/g.exec(ciConfigurationFromMain)?.[1]\n\n  if (!currentStaging) {\n    throw new Error('Could not find CURRENT_STAGING in .gitlab-ci.yml')\n  }\n\n  command`git fetch --no-tags origin ${currentStaging}`.run()\n\n  printLog(\n    `Checking if branch '${CI_COMMIT_REF_NAME}' (${CI_COMMIT_SHORT_SHA}) can be squash merged into ${currentStaging}...`\n  )\n\n  try {\n    command`git checkout ${MAIN_BRANCH} -f`.run()\n    command`git pull`.run()\n    command`git merge --squash ${CI_COMMIT_SHA}`.run()\n  } catch (error) {\n    const diff = command`git diff`.run()\n    printError(\n      `Conflicts:\\n${diff}\\n` +\n        `You can resolve these conflicts by updating your branch with latest ${MAIN_BRANCH} changes.`\n    )\n    throw error\n  }\n\n  try {\n    command`git commit -am ${'squash test'}`.run()\n\n    command`git checkout ${currentStaging} -f`.run()\n    command`git pull`.run()\n    command`git merge ${MAIN_BRANCH}`.run()\n  } catch (error) {\n    const diff = command`git diff`.run()\n    printError(\n      `Conflicts:\\n${diff}\\n` +\n        'You can resolve these conflicts by re-running \"to-staging\" on your branch to propagate latest changes.'\n    )\n    throw error\n  }\n\n  printLog('Check done.')\n})\n"
  },
  {
    "path": "scripts/staging-ci/check-staging-merge.ts",
    "content": "import { printLog, printError, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { fetchPR, initGitConfig } from '../lib/gitUtils.ts'\n\nconst REPOSITORY = process.env.GIT_REPOSITORY\nconst CI_COMMIT_SHA = process.env.CI_COMMIT_SHA\nconst CI_COMMIT_SHORT_SHA = process.env.CI_COMMIT_SHORT_SHA\nconst CI_COMMIT_REF_NAME = process.env.CI_COMMIT_REF_NAME\nconst MAIN_BRANCH = process.env.MAIN_BRANCH\nconst NEXT_MAJOR_BRANCH = process.env.NEXT_MAJOR_BRANCH\n\nrunMain(async () => {\n  if (!REPOSITORY || !CI_COMMIT_SHA || !CI_COMMIT_SHORT_SHA || !CI_COMMIT_REF_NAME || !MAIN_BRANCH) {\n    throw new Error('Missing required environment variables')\n  }\n\n  if (NEXT_MAJOR_BRANCH) {\n    const pr = await fetchPR(CI_COMMIT_REF_NAME)\n    if (pr?.base.ref === NEXT_MAJOR_BRANCH) {\n      printLog(`PR targets ${NEXT_MAJOR_BRANCH}, skipping staging merge check.`)\n      return\n    }\n  }\n\n  initGitConfig(REPOSITORY)\n  command`git fetch --no-tags origin ${MAIN_BRANCH}`.run()\n  const ciConfigurationFromMain = command`git show origin/${MAIN_BRANCH}:.gitlab-ci.yml`.run()\n  const currentStaging = /CURRENT_STAGING: (staging-.*)/g.exec(ciConfigurationFromMain)?.[1]\n\n  if (!currentStaging) {\n    throw new Error('Could not find CURRENT_STAGING in .gitlab-ci.yml')\n  }\n\n  command`git fetch --no-tags origin ${currentStaging}`.run()\n  command`git checkout ${currentStaging} -f`.run()\n  command`git pull`.run()\n\n  printLog(\n    `Checking if branch '${CI_COMMIT_REF_NAME}' (${CI_COMMIT_SHORT_SHA}) can be merged into ${currentStaging}...`\n  )\n  try {\n    command`git merge --no-ff ${CI_COMMIT_SHA}`.run()\n  } catch (error) {\n    const diff = command`git diff`.run()\n    printError(\n      `Conflicts:\\n${diff}\\n` +\n        'You can resolve these conflicts by running \"branches-status staging fix\" in your branch' +\n        'and resolving the merge conflicts.'\n    )\n    throw error\n  }\n\n  printLog('Check done.')\n})\n"
  },
  {
    "path": "scripts/staging-ci/staging-reset.ts",
    "content": "import fs from 'node:fs'\nimport { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { CI_FILE, replaceCiFileVariable, readCiFileVariable } from '../lib/filesUtils.ts'\nimport { initGitConfig } from '../lib/gitUtils.ts'\n\nconst REPOSITORY = process.env.GIT_REPOSITORY\nconst MAIN_BRANCH = process.env.MAIN_BRANCH\n\nconst CURRENT_STAGING_BRANCH = readCiFileVariable('CURRENT_STAGING')\nconst NEW_STAGING_NUMBER = getWeekNumber().toString().padStart(2, '0')\nconst NEW_STAGING_BRANCH = `staging-${NEW_STAGING_NUMBER}`\n\nrunMain(async () => {\n  if (!REPOSITORY || !MAIN_BRANCH) {\n    throw new Error('Missing required environment variables')\n  }\n\n  if (!CURRENT_STAGING_BRANCH) {\n    throw new Error('Could not read CURRENT_STAGING from CI file')\n  }\n\n  // used to share the new staging name to the notification jobs\n  fs.appendFileSync('build.env', `NEW_STAGING=${NEW_STAGING_BRANCH}`)\n\n  initGitConfig(REPOSITORY)\n  command`git fetch --no-tags origin ${MAIN_BRANCH} ${CURRENT_STAGING_BRANCH}`.run()\n  command`git checkout ${MAIN_BRANCH} -f`.run()\n  command`git pull`.run()\n\n  const isNewBranch = CURRENT_STAGING_BRANCH !== NEW_STAGING_BRANCH\n  if (isNewBranch) {\n    printLog(`Changing staging branch in ${CI_FILE}...`)\n\n    await replaceCiFileVariable('CURRENT_STAGING', NEW_STAGING_BRANCH)\n    command`git commit ${CI_FILE} -m ${`👷 Bump staging to ${NEW_STAGING_BRANCH}`}`.run()\n    command`git push origin ${MAIN_BRANCH}`.run()\n  } else {\n    printLog(`Staging branch already up to date in ${CI_FILE}. Skipping.`)\n  }\n\n  try {\n    printLog('Deleting existing staging local branch if it exists...')\n    command`git branch -D ${NEW_STAGING_BRANCH}`.run()\n  } catch {\n    // The local branch did not exist yet, let's continue\n  }\n\n  printLog('Creating the new staging branch...')\n  command`git checkout -b ${NEW_STAGING_BRANCH}`.run()\n  command`git push origin -f ${NEW_STAGING_BRANCH}`.run()\n\n  command`git checkout ${CURRENT_STAGING_BRANCH}`.run()\n  command`git pull origin ${CURRENT_STAGING_BRANCH}`.run()\n\n  if (isNewBranch && fs.existsSync(CI_FILE)) {\n    printLog('Disabling CI on the old branch...')\n    command`git rm ${CI_FILE}`.run()\n    command`git commit ${CI_FILE} -m ${`Remove ${CI_FILE} on old branch so pushes are noop`}`.run()\n    command`git push origin ${CURRENT_STAGING_BRANCH}`.run()\n  } else {\n    printLog('CI already disabled on the old branch. Skipping.')\n  }\n\n  printLog('Reset done.')\n})\n\nfunction getWeekNumber(): number {\n  const today = new Date()\n  const yearStart = new Date(Date.UTC(today.getUTCFullYear(), 0, 1))\n  return Math.ceil(((today.getTime() - yearStart.getTime()) / 86400000 + yearStart.getUTCDay() + 1) / 7)\n}\n"
  },
  {
    "path": "scripts/test/bs-kill.ts",
    "content": "/**\n * This script stops all BrowserStack workers that are currently running.\n * Useful when troubleshooting BrowserStack issues locally.\n */\nimport { printLog, runMain, timeout } from '../lib/executionUtils.ts'\nimport { browserStackRequest } from '../lib/bsUtils.ts'\n\nconst MINIMUM_WORKER_LIFE = 30_000\n\nconst BS_WORKERS_URL = 'https://api.browserstack.com/5/workers'\nconst buildBsWorkerUrl = (workerId: string): string => `https://api.browserstack.com/5/worker/${workerId}`\n\ninterface BsWorker {\n  id: string\n  [key: string]: any\n}\n\ninterface StopResponse {\n  time?: number\n  message?: string\n}\n\nrunMain(async () => {\n  const workerIds = await getActiveWorkerIds()\n  printLog(`Stopping ${workerIds.length} workers`)\n  await Promise.all(workerIds.map((workerId) => stopWorker(workerId)))\n  process.exit(0)\n})\n\nasync function getActiveWorkerIds(): Promise<string[]> {\n  const workers = (await browserStackRequest(BS_WORKERS_URL)) as BsWorker[]\n  return workers.map((worker) => worker.id)\n}\n\nasync function stopWorker(workerId: string): Promise<void> {\n  const stopResponse = (await browserStackRequest(buildBsWorkerUrl(workerId), { method: 'DELETE' })) as StopResponse\n  // stopResponse:\n  // - when stopped: {\"time\":X.Y}\n  // - when worker not old enough: {\"message\":\"worker is running for X.Y secs, minimum life is 30 sec\"}\n  if (stopResponse.time === undefined) {\n    printLog(`Worker ${workerId} not stopped, retrying in 30s`)\n    await timeout(MINIMUM_WORKER_LIFE)\n    await stopWorker(workerId)\n  }\n}\n"
  },
  {
    "path": "scripts/test/bs-wrapper.ts",
    "content": "// This wrapper script ensures that no other test is running in BrowserStack before launching the\n// test command, to avoid overloading the service and making tests more flaky than necessary. This\n// is also handled by the CI (exclusive lock on the \"browserstack\" resource), but it is helpful when\n// launching tests outside of the CI.\n//\n// It used to re-run the test command based on its output (in particular, when the BrowserStack\n// session failed to be created), but we observed that:\n//\n// * The retry logic of karma and wdio was more efficient to retry this kind of tests (the\n// BrowserStack connection is re-created on each retry)\n//\n// * Aborting the test command via a SIGTERM signal was buggy and the command continued to run even\n// after killing it. There might be a better way of prematurely aborting the test command if we need\n// to in the future.\n\nimport { spawn, type ChildProcess } from 'node:child_process'\nimport browserStack from 'browserstack-local'\nimport { printLog, runMain, timeout, printError } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { browserStackRequest } from '../lib/bsUtils.ts'\n\nconst AVAILABILITY_CHECK_DELAY = 30_000\nconst NO_OUTPUT_TIMEOUT = 5 * 60_000\nconst BS_BUILD_URL = 'https://api.browserstack.com/automate/builds.json?status=running'\n\nconst bsLocal = new browserStack.Local()\n\nrunMain(async () => {\n  if (command`git tag --points-at HEAD`.run()) {\n    printLog('Skip bs execution on tags')\n    return\n  }\n\n  if (!process.env.BS_USERNAME || !process.env.BS_ACCESS_KEY) {\n    printError('Missing Browserstack credentials (BS_ACCESS_KEY and BS_USERNAME env variables)')\n    return\n  }\n\n  await waitForAvailability()\n  await startBsLocal()\n  const isSuccess = await runTests()\n  await stopBsLocal()\n  process.exit(isSuccess ? 0 : 1)\n})\n\nasync function waitForAvailability(): Promise<void> {\n  while (await hasRunningBuild()) {\n    printLog('Other build running, waiting...')\n    await timeout(AVAILABILITY_CHECK_DELAY)\n  }\n}\n\nasync function hasRunningBuild(): Promise<boolean> {\n  const builds = (await browserStackRequest(BS_BUILD_URL)) as any[]\n  return builds.length > 0\n}\n\nfunction startBsLocal(): Promise<void> {\n  printLog('Starting BrowserStackLocal...')\n\n  return new Promise((resolve) => {\n    bsLocal.start(\n      {\n        key: process.env.BS_ACCESS_KEY,\n        forceLocal: true,\n        forceKill: true,\n        onlyAutomate: true,\n      },\n      (error?: Error) => {\n        if (error) {\n          printError('Failed to start BrowserStackLocal:', error)\n          process.exit(1)\n        }\n        printLog('BrowserStackLocal started', bsLocal.isRunning())\n        resolve()\n      }\n    )\n  })\n}\n\nfunction stopBsLocal(): Promise<void> {\n  return new Promise((resolve) => {\n    bsLocal.stop(() => {\n      printLog('BrowserStackLocal stopped')\n      resolve()\n    })\n  })\n}\n\nfunction runTests(): Promise<boolean> {\n  return new Promise((resolve) => {\n    const [command, ...args] = process.argv.slice(2)\n\n    const child: ChildProcess = spawn(command, args, {\n      stdio: ['inherit', 'pipe', 'pipe'],\n      env: {\n        ...process.env,\n        FORCE_COLOR: 'true',\n        BROWSER_STACK: 'true',\n      },\n    })\n\n    let output = ''\n    let timeoutId: NodeJS.Timeout\n\n    child.stdout!.pipe(process.stdout)\n    child.stdout!.on('data', onOutput)\n\n    child.stderr!.pipe(process.stderr)\n    child.stderr!.on('data', onOutput)\n\n    child.on('exit', (code, signal) => {\n      resolve(!signal && code === 0)\n    })\n\n    function onOutput(data: Buffer | string): void {\n      output += data.toString()\n\n      clearTimeout(timeoutId)\n\n      if (hasUnrecoverableFailure(output)) {\n        killIt('unrecoverable failure')\n      } else {\n        timeoutId = setTimeout(() => killIt('no output timeout'), NO_OUTPUT_TIMEOUT)\n      }\n    }\n\n    function killIt(message: string): void {\n      printError(`Killing the browserstack job because of ${message}`)\n      // use 'SIGKILL' instead of 'SIGTERM' because Karma intercepts 'SIGTERM' and terminates the process with a 0 exit code,\n      // which is not what we want here (we want to indicate a failure).\n      // see https://github.com/karma-runner/karma/blob/master/lib/server.js#L391\n      child.kill('SIGKILL')\n    }\n  })\n}\n\nfunction hasUnrecoverableFailure(stdout: string): boolean {\n  return stdout.includes('is set to true but local testing through BrowserStack is not connected.')\n}\n"
  },
  {
    "path": "scripts/test/bump-chrome-version.ts",
    "content": "import fs from 'node:fs'\nimport { printLog, runMain, fetchHandlingError } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { CI_FILE, replaceCiFileVariable } from '../lib/filesUtils.ts'\nimport { initGitConfig, createPullRequest } from '../lib/gitUtils.ts'\n\nconst REPOSITORY = process.env.GIT_REPOSITORY\nconst MAIN_BRANCH = process.env.MAIN_BRANCH\nconst CURRENT_CI_IMAGE = process.env.CURRENT_CI_IMAGE\nconst CURRENT_PACKAGE_VERSION = process.env.CHROME_PACKAGE_VERSION\n\nconst CHROME_PACKAGE_URL = 'https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable'\n\nrunMain(async () => {\n  if (!REPOSITORY || !MAIN_BRANCH || !CURRENT_CI_IMAGE || !CURRENT_PACKAGE_VERSION) {\n    throw new Error('Missing required environment variables')\n  }\n\n  initGitConfig(REPOSITORY)\n  command`git fetch --no-tags origin ${MAIN_BRANCH}`.run()\n  command`git checkout ${MAIN_BRANCH} -f`.run()\n  command`git pull origin ${MAIN_BRANCH}`.run()\n\n  const packageVersion = await getPackageVersion()\n\n  if (!packageVersion) {\n    throw new Error('Could not fetch Chrome package version')\n  }\n\n  const majorPackageVersion = getMajor(packageVersion)\n\n  if (majorPackageVersion <= getMajor(CURRENT_PACKAGE_VERSION)) {\n    printLog('Chrome is up to date.')\n    return\n  }\n\n  const chromeVersionBranch = `bump-chrome-version-to-${majorPackageVersion}`\n  const commitMessage = `👷 Bump chrome to ${packageVersion}`\n\n  const isBranchAlreadyCreated = command`git ls-remote --heads ${REPOSITORY} ${chromeVersionBranch}`.run()\n  if (isBranchAlreadyCreated) {\n    printLog('Bump chrome branch already created.')\n    return\n  }\n\n  command`git checkout -b ${chromeVersionBranch}`.run()\n\n  printLog('Update versions...')\n  await replaceCiFileVariable('CHROME_PACKAGE_VERSION', packageVersion)\n  await replaceCiFileVariable('CURRENT_CI_IMAGE', String(Number(CURRENT_CI_IMAGE) + 1))\n\n  command`git add ${CI_FILE}`.run()\n  command`git commit -m ${commitMessage}`.run()\n  command`git push origin ${chromeVersionBranch}`.run()\n\n  printLog('Create PR...')\n\n  const pullRequestUrl = createPullRequest(MAIN_BRANCH)\n  printLog(`Chrome version bump PR created (from ${CURRENT_PACKAGE_VERSION} to ${packageVersion}).`)\n\n  // used to share the pull request url to the notification jobs\n  fs.appendFileSync('build.env', `BUMP_CHROME_PULL_REQUEST_URL=${pullRequestUrl}`)\n})\n\nasync function getPackageVersion(): Promise<string | null> {\n  const packagePage = await (await fetchHandlingError(CHROME_PACKAGE_URL)).text()\n  const packageMatches = /<td>([0-9.-]+)<\\/td>/.exec(packagePage)\n\n  return packageMatches ? packageMatches[1] : null\n}\n\nfunction getMajor(version: string): number {\n  const majorRegex = /^([0-9]+)./\n  const majorMatches = majorRegex.exec(version)\n  const major = majorMatches ? majorMatches[1] : null\n\n  return Number(major)\n}\n"
  },
  {
    "path": "scripts/test/ci-bs.ts",
    "content": "import { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { fetchPR, getLastCommonCommit, LOCAL_BRANCH } from '../lib/gitUtils.ts'\nimport { getBrowserStackUsername, getBrowserStackAccessKey } from '../lib/secrets.ts'\n\n// Patterns that should trigger BrowserStack tests (git pathspecs)\nconst RELEVANT_FILE_PATTERNS = [\n  'packages/*',\n  'test/*',\n  'developer-extension/*',\n  'scripts/test/*',\n  'package.json',\n  'yarn.lock',\n  'tsconfig*',\n  'webpack.base.ts',\n]\n\nrunMain(async () => {\n  const testCommand = process.argv[2]\n  if (!testCommand) {\n    throw new Error('Usage: ci-bs.ts <test:unit|test:e2e:ci>')\n  }\n\n  const pr = await fetchPR(LOCAL_BRANCH!)\n  const baseBranch = pr?.base.ref ?? 'main'\n  const baseCommit = getLastCommonCommit(baseBranch)\n\n  if (!hasRelevantChanges(baseCommit)) {\n    printLog('No code changes affecting browser behavior detected. Skipping BrowserStack tests.')\n    return\n  }\n\n  command`yarn ${testCommand}:bs`\n    .withEnvironment({\n      BS_USERNAME: getBrowserStackUsername(),\n      BS_ACCESS_KEY: getBrowserStackAccessKey(),\n    })\n    .withLogs()\n    .run()\n})\n\nfunction hasRelevantChanges(baseCommit: string): boolean {\n  const changedFiles = command`git diff --name-only ${baseCommit} HEAD -- ${RELEVANT_FILE_PATTERNS}`.run()\n\n  if (changedFiles.trim()) {\n    printLog(`Matched files:\\n${changedFiles}`)\n    return true\n  }\n\n  return false\n}\n"
  },
  {
    "path": "scripts/test/export-test-result.ts",
    "content": "import { printLog, runMain } from '../lib/executionUtils.ts'\nimport { command } from '../lib/command.ts'\nimport { getOrg2ApiKey } from '../lib/secrets.ts'\n\n/**\n * Upload test result to datadog\n * Usage:\n * node export-test-result.ts testType\n */\n\nconst testType = process.argv[2]\nconst resultFolder = `test-report/${testType}/`\nconst coverageFolder = `coverage/${testType}/`\n\nrunMain(() => {\n  command`datadog-ci junit upload --service browser-sdk --env ci --tags test.type:${testType} ${resultFolder}`\n    .withEnvironment({\n      DATADOG_API_KEY: getOrg2ApiKey(),\n    })\n    .withLogs()\n    .run()\n  command`datadog-ci coverage upload --flags service:browser-sdk --flags env:ci --flags test.type:${testType} ${coverageFolder}`\n    .withEnvironment({\n      DATADOG_API_KEY: getOrg2ApiKey(),\n    })\n    .withLogs()\n    .run()\n\n  printLog(`Export ${testType} tests done.`)\n})\n"
  },
  {
    "path": "scripts/update-branch.ts",
    "content": "import { parseArgs } from 'node:util'\nimport { printLog, printError, runMain, fetchHandlingError } from './lib/executionUtils.ts'\nimport { command } from './lib/command.ts'\n\nconst REPOSITORY = process.env.APP\nconst DEVFLOW_AUTH_TOKEN = command`authanywhere --audience sdm --raw`.run()\nconst DEVFLOW_API_URL = 'https://devflow-api.us1.ddbuild.io/internal/api/v2/devflow/execute/'\nconst FEEDBACK_LEVEL_FAILURE = 'FEEDBACK_LEVEL_FAILURE'\n\ninterface DevFlowFeedback {\n  level: string\n  title: string\n  message?: string\n  details_url?: string\n}\n\ninterface DevFlowResponse {\n  state: {\n    feedbacks: DevFlowFeedback[]\n  }\n}\n\nrunMain(async () => {\n  const args = parseArgs({ allowPositionals: true })\n  const [branch] = args.positionals\n\n  if (!branch) {\n    throw new Error('Branch name is required')\n  }\n\n  await updateBranch(branch)\n\n  // `update-branch` always skips CI, so we need to trigger it manually\n  await triggerCi(branch)\n})\n\nasync function updateBranch(branch: string): Promise<void> {\n  await devFlow('update-branch', { branch })\n}\n\nasync function triggerCi(branch: string): Promise<void> {\n  await devFlow('trigger-ci', { ref: branch })\n}\n\nasync function devFlow(action: string, options: Record<string, string>): Promise<void> {\n  const params = getDevFlowURLSearchParams(options)\n  const rawResponse = await fetchHandlingError(`${DEVFLOW_API_URL}/${action}?${params}`, {\n    headers: {\n      Authorization: `Bearer ${DEVFLOW_AUTH_TOKEN}`,\n    },\n  })\n\n  const jsonResponse = (await rawResponse.json()) as DevFlowResponse\n\n  let isSuccess = true\n  for (const feedback of jsonResponse.state.feedbacks) {\n    if (feedback.level === FEEDBACK_LEVEL_FAILURE) {\n      isSuccess = false\n    }\n    const print = feedback.level === FEEDBACK_LEVEL_FAILURE ? printError : printLog\n    print(feedback.title)\n    if (feedback.message) {\n      print(feedback.message)\n    }\n    if (feedback.details_url) {\n      print(`Details: ${feedback.details_url}`)\n    }\n  }\n\n  if (!isSuccess) {\n    throw new Error(`DevFlow action \"${action}\" failed`)\n  }\n}\n\nfunction getDevFlowURLSearchParams(options: Record<string, string>): string {\n  if (!REPOSITORY) {\n    throw new Error('APP environment variable is required')\n  }\n  const params = new URLSearchParams({\n    repository: REPOSITORY,\n    ...options,\n  })\n\n  return params.toString()\n}\n"
  },
  {
    "path": "static-analysis.datadog.yml",
    "content": "rulesets:\nignore:\n  - '**/*' # disable static analysis\n"
  },
  {
    "path": "test/apps/.gitignore",
    "content": "allowed-tracking-origin/\ninvalid-tracking-origin/\nreact-router-v7-app/\ncdn-extension/\nappendChild-extension/\n"
  },
  {
    "path": "test/apps/angular-app/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*\n"
  },
  {
    "path": "test/apps/angular-app/main.ts",
    "content": "import 'zone.js'\nimport { Component, inject } from '@angular/core'\nimport { bootstrapApplication } from '@angular/platform-browser'\nimport { provideRouter, RouterOutlet, RouterLink, ActivatedRoute, type Routes } from '@angular/router'\nimport { NgIf } from '@angular/common'\nimport { datadogRum } from '@datadog/browser-rum'\nimport { angularPlugin, provideDatadogRouter, provideDatadogErrorHandler } from '@datadog/browser-rum-angular'\n\ndeclare global {\n  interface Window {\n    RUM_CONFIGURATION?: any\n    RUM_CONTEXT?: any\n  }\n}\n\n// Initialize RUM before bootstrap\ndatadogRum.init({ ...window.RUM_CONFIGURATION, plugins: [angularPlugin({ router: true })] })\nif (window.RUM_CONTEXT) {\n  datadogRum.setGlobalContext(window.RUM_CONTEXT)\n}\n\n// Components\n\n@Component({\n  selector: 'app-initial-route',\n  standalone: true,\n  imports: [RouterLink],\n  template: `\n    <h1>Initial Route</h1>\n    <a routerLink=\"/user/42\" [queryParams]=\"{ admin: 'true' }\">Go to User 42</a><br />\n    <a routerLink=\"/guides/123\">Go to Guides 123</a><br />\n    <a routerLink=\"/error-test\">Go to Error Test</a><br />\n    <a routerLink=\"/parent/nested\">Go to Nested Route</a><br />\n    <a routerLink=\"/unknown/page\">Go to Wildcard Route</a><br />\n    <button id=\"throw-error\" (click)=\"throwError()\">Throw Error</button>\n    <button id=\"throw-error-with-context\" (click)=\"throwErrorWithContext()\">Throw Error With Context</button>\n  `,\n})\nclass InitialRouteComponent {\n  throwError() {\n    throw new Error('angular error from component')\n  }\n\n  throwErrorWithContext() {\n    const error = new Error('angular error with dd_context')\n    ;(error as any).dd_context = { component: 'InitialRoute', userId: 42 }\n    throw error\n  }\n}\n\n@Component({\n  selector: 'app-user-route',\n  standalone: true,\n  imports: [RouterLink],\n  template: `\n    <h1>User Page</h1>\n    <a routerLink=\"/\">Back to Home</a><br />\n    <a [routerLink]=\"['/user', id]\" fragment=\"section\">Go to Section</a><br />\n    <a [routerLink]=\"['/user', id]\" [queryParams]=\"{ admin: 'false' }\">Change query params</a><br />\n    <a [routerLink]=\"['/user', '999']\" [queryParams]=\"{ admin: 'true' }\">Go to User 999</a>\n  `,\n})\nclass UserRouteComponent {\n  protected id = inject(ActivatedRoute).snapshot.params['id'] as string\n}\n\n@Component({\n  selector: 'app-guides-route',\n  standalone: true,\n  imports: [RouterLink],\n  template: `\n    <h1>Guides</h1>\n    <a routerLink=\"/\">Back to Home</a>\n  `,\n})\nclass GuidesRouteComponent {}\n\n@Component({\n  selector: 'app-error-test-route',\n  standalone: true,\n  imports: [NgIf],\n  template: `\n    <h1>Error Test</h1>\n    <button data-testid=\"trigger-error\" (click)=\"triggerError()\">Trigger Error</button>\n    <div *ngIf=\"hasError\" data-testid=\"error-handled\">Error occurred</div>\n  `,\n})\nclass ErrorTestRouteComponent {\n  hasError = false\n\n  triggerError() {\n    this.hasError = true\n    throw new Error('Error triggered by button click')\n  }\n}\n\n@Component({\n  selector: 'app-nested-route',\n  standalone: true,\n  template: '<h1>Nested Route</h1>',\n})\nclass NestedRouteComponent {}\n\n@Component({\n  selector: 'app-wildcard-route',\n  standalone: true,\n  template: '<h1>Wildcard Route</h1>',\n})\nclass WildcardRouteComponent {}\n\n@Component({\n  selector: 'app-root',\n  standalone: true,\n  imports: [RouterOutlet],\n  template: '<router-outlet></router-outlet>',\n})\nclass AppComponent {}\n\n// Routes\nconst nestedRoutes: Routes = [{ path: 'nested', component: NestedRouteComponent }]\n\nconst routes: Routes = [\n  { path: '', component: InitialRouteComponent },\n  { path: 'user/:id', component: UserRouteComponent },\n  { path: 'guides/:slug', component: GuidesRouteComponent },\n  { path: 'error-test', component: ErrorTestRouteComponent },\n  { path: 'parent', loadChildren: () => Promise.resolve(nestedRoutes) },\n  { path: '**', component: WildcardRouteComponent },\n]\n\n// Bootstrap - dynamically create root element (E2E framework serves bare HTML)\nconst rootElement = document.createElement('app-root')\ndocument.body.appendChild(rootElement)\n\nvoid bootstrapApplication(AppComponent, {\n  providers: [provideRouter(routes), provideDatadogRouter(), provideDatadogErrorHandler()],\n})\n"
  },
  {
    "path": "test/apps/angular-app/package.json",
    "content": "{\n  \"name\": \"angular-app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack\"\n  },\n  \"dependencies\": {\n    \"@angular/common\": \"15.2.10\",\n    \"@angular/compiler\": \"15.2.10\",\n    \"@angular/compiler-cli\": \"15.2.10\",\n    \"@angular/core\": \"15.2.10\",\n    \"@angular/platform-browser\": \"15.2.10\",\n    \"@angular/router\": \"15.2.10\",\n    \"rxjs\": \"7.8.2\",\n    \"zone.js\": \"0.16.1\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"*\",\n    \"@datadog/browser-rum-angular\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-angular\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-rum-angular\": \"file:../../../packages/rum-angular/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"@ngtools/webpack\": \"15.2.11\",\n    \"babel-loader\": \"9.2.1\",\n    \"typescript\": \"4.9.5\",\n    \"webpack\": \"5.105.4\",\n    \"webpack-cli\": \"6.0.1\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/angular-app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/\",\n    \"strict\": true,\n    \"module\": \"es2022\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"target\": \"es2022\",\n    \"lib\": [\"ES2022\", \"DOM\"],\n    \"types\": [],\n    \"experimentalDecorators\": true,\n    \"useDefineForClassFields\": false\n  },\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictTemplates\": true\n  }\n}\n"
  },
  {
    "path": "test/apps/angular-app/webpack.config.js",
    "content": "const path = require('node:path')\n// eslint-disable-next-line import/no-unresolved\nconst { AngularWebpackPlugin } = require('@ngtools/webpack')\n\nmodule.exports = {\n  mode: 'production',\n  entry: './main.ts',\n  target: ['web', 'es2022'],\n  module: {\n    rules: [\n      { test: /\\.ts$/, use: '@ngtools/webpack' },\n      {\n        test: /\\.[cm]?js$/,\n        include: /node_modules/,\n        use: {\n          loader: 'babel-loader',\n          options: {\n            plugins: ['@angular/compiler-cli/linker/babel'],\n            compact: false,\n            cacheDirectory: true,\n          },\n        },\n      },\n    ],\n  },\n  resolve: {\n    extensions: ['.ts', '.js'],\n  },\n  plugins: [\n    new AngularWebpackPlugin({\n      tsconfig: path.resolve(__dirname, 'tsconfig.json'),\n      jitMode: false,\n    }),\n  ],\n  optimization: {\n    chunkIds: 'named',\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'angular-app.js',\n    chunkFilename: 'chunks/[name]-[contenthash]-angular-app.js',\n  },\n}\n"
  },
  {
    "path": "test/apps/base-extension/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*"
  },
  {
    "path": "test/apps/base-extension/README.md",
    "content": "Basic Manifest v3 extension used in end-to-end tests for isExtensionEnvironment.\n"
  },
  {
    "path": "test/apps/base-extension/manifest.json",
    "content": "{\n  \"name\": \"Datadog RUM Testing Extension\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Injects Datadog RUM into every page to inspect data being sent.\",\n  \"permissions\": [\"scripting\", \"activeTab\"],\n  \"host_permissions\": [\"<all_urls>\"],\n  \"content_scripts\": [\n    {\n      \"matches\": [\"<all_urls>\"],\n      \"js\": [\"dist/base.js\"],\n      \"run_at\": \"document_end\",\n      \"world\": \"MAIN\"\n    }\n  ]\n}\n"
  },
  {
    "path": "test/apps/base-extension/package.json",
    "content": "{\n  \"name\": \"rum-testing-extension\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-logs\": \"*\",\n    \"@datadog/browser-rum\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-logs\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-logs\": \"file:../../../packages/logs/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"webpack\": \"5.105.4\",\n    \"webpack-cli\": \"6.0.1\"\n  }\n}\n"
  },
  {
    "path": "test/apps/base-extension/src/appendChild.ts",
    "content": "const originalAppendChild = Node.prototype.appendChild // eslint-disable-line @typescript-eslint/unbound-method\n\nNode.prototype.appendChild = function <T extends Node>(node: T): T {\n  return originalAppendChild.call(this, node) as T\n}\n"
  },
  {
    "path": "test/apps/base-extension/src/base.ts",
    "content": "import { datadogRum } from '@datadog/browser-rum'\nimport { datadogLogs } from '@datadog/browser-logs'\nimport type { RumInitConfiguration } from '@datadog/browser-rum-core'\nimport type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport type { Context } from '@datadog/browser-core'\n\ndeclare global {\n  interface Window {\n    EXT_RUM_CONFIGURATION?: RumInitConfiguration\n    RUM_CONTEXT?: Context\n    EXT_LOGS_CONFIGURATION?: LogsInitConfiguration\n    LOGS_CONTEXT?: Context\n  }\n}\n\nif (window.EXT_RUM_CONFIGURATION) {\n  datadogRum.init(window.EXT_RUM_CONFIGURATION)\n\n  if (window.RUM_CONTEXT) {\n    datadogRum.setGlobalContext(window.RUM_CONTEXT)\n  }\n}\n\nif (window.EXT_LOGS_CONFIGURATION) {\n  datadogLogs.init(window.EXT_LOGS_CONFIGURATION)\n\n  if (window.LOGS_CONTEXT) {\n    datadogLogs.setGlobalContext(window.LOGS_CONTEXT)\n  }\n}\n"
  },
  {
    "path": "test/apps/base-extension/src/cdn.ts",
    "content": "import type { RumInitConfiguration, RumPublicApi } from '@datadog/browser-rum-core'\nimport type { LogsInitConfiguration, LogsGlobal } from '@datadog/browser-logs'\nimport type { Context } from '@datadog/browser-core'\n\ndeclare global {\n  interface Window {\n    RUM_BUNDLE_URL?: string\n    LOGS_BUNDLE_URL?: string\n    EXT_RUM_CONFIGURATION?: RumInitConfiguration\n    RUM_CONTEXT?: Context\n    EXT_LOGS_CONFIGURATION?: LogsInitConfiguration\n    LOGS_CONTEXT?: Context\n    DD_RUM?: RumPublicApi\n    DD_LOGS?: LogsGlobal\n  }\n}\n\nfunction load<T extends 'DD_RUM' | 'DD_LOGS'>(\n  sdk: T,\n  url: string,\n  initConfig: T extends 'DD_RUM' ? RumInitConfiguration : LogsInitConfiguration,\n  globalContext?: Context\n) {\n  const script = document.createElement('script')\n  script.src = url\n  script.onload = () => {\n    if (!window[sdk]) {\n      console.error(`${sdk} is not loaded`)\n      return\n    }\n\n    window[sdk].init(initConfig as any)\n    if (globalContext) {\n      window[sdk].setGlobalContext(globalContext)\n    }\n  }\n\n  document.documentElement.appendChild(script)\n}\n\nif (window.RUM_BUNDLE_URL && window.EXT_RUM_CONFIGURATION) {\n  load('DD_RUM', window.RUM_BUNDLE_URL, window.EXT_RUM_CONFIGURATION, window.RUM_CONTEXT)\n}\n\nif (window.LOGS_BUNDLE_URL && window.EXT_LOGS_CONFIGURATION) {\n  load('DD_LOGS', window.LOGS_BUNDLE_URL, window.EXT_LOGS_CONFIGURATION, window.LOGS_CONTEXT)\n}\n"
  },
  {
    "path": "test/apps/base-extension/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/\",\n    \"rootDir\": \"./src\",\n    \"strict\": true,\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"bundler\",\n    \"target\": \"es2015\",\n    \"lib\": [\"ES2015\", \"DOM\"],\n    \"types\": []\n  }\n}\n"
  },
  {
    "path": "test/apps/base-extension/webpack.config.js",
    "content": "const path = require('node:path')\n\nmodule.exports = {\n  mode: 'production',\n  target: ['web', 'es2018'],\n  entry: {\n    base: './src/base.ts',\n    cdn: './src/cdn.ts',\n    appendChild: './src/appendChild.ts',\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.ts$/,\n        use: 'ts-loader',\n        exclude: /node_modules/,\n      },\n    ],\n  },\n  output: {\n    filename: '[name].js',\n    path: path.resolve(__dirname, 'dist'),\n    publicPath: '',\n  },\n  optimization: {\n    chunkIds: 'named',\n  },\n}\n"
  },
  {
    "path": "test/apps/microfrontend/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*"
  },
  {
    "path": "test/apps/microfrontend/app1.ts",
    "content": "import { createApp } from './common'\n\ncreateApp('app1', 'App 1 (mfe-app1-service v1.0.0)', 'blue')\n"
  },
  {
    "path": "test/apps/microfrontend/app2.ts",
    "content": "import { createApp } from './common'\n\ncreateApp('app2', 'App 2 (mfe-app2-service v0.2.0)', 'green')\n"
  },
  {
    "path": "test/apps/microfrontend/bootstrap.ts",
    "content": "// @ts-ignore The dynamic import keeps shell.ts out of the entry chunk,\nvoid import('./shell')\n"
  },
  {
    "path": "test/apps/microfrontend/common.ts",
    "content": "function createContainer(id: string, title: string, borderColor: string) {\n  const container = document.createElement('div')\n  container.id = id\n  container.style.flex = '1'\n  container.style.border = `2px solid ${borderColor}`\n  container.style.padding = '10px'\n\n  const appTitle = document.createElement('h2')\n  appTitle.textContent = title\n  container.appendChild(appTitle)\n  document.body.appendChild(container)\n  return container\n}\n\nfunction createButton(container: HTMLElement, eventType: string, clickHandler: () => void) {\n  const button = document.createElement('button')\n  button.id = `${container.id}-${eventType}`\n  button.textContent = `${container.id}-${eventType}`\n  button.onclick = clickHandler\n  container.appendChild(button)\n}\n\nexport function createApp(id: string, title: string, borderColor: string) {\n  const container = createContainer(id, title, borderColor)\n\n  createButton(container, 'fetch', () => {\n    void fetch('/ok')\n  })\n\n  createButton(container, 'xhr', () => {\n    const xhr = new XMLHttpRequest()\n    xhr.open('GET', '/ok')\n    xhr.send()\n  })\n\n  createButton(container, 'error', () => {\n    window.DD_RUM.addError(new Error(`${id}-error`))\n  })\n\n  createButton(container, 'console-error', () => {\n    console.error(`${id}-console-error`)\n  })\n\n  createButton(container, 'runtime-error', () => {\n    throw new Error(`${id}-runtime-error`)\n  })\n\n  createButton(container, 'loaf', () => {\n    const end = performance.now() + 55\n    while (performance.now() < end) {\n      // block the handler for ~55ms to trigger a long task\n    }\n  })\n\n  createButton(container, 'custom-action', () => {\n    window.DD_RUM.addAction(`${id}-action`)\n  })\n\n  createButton(container, 'vital', () => {\n    const ref = window.DD_RUM.startDurationVital(`${id}-vital`)\n    window.DD_RUM.stopDurationVital(ref)\n  })\n\n  createButton(container, 'feature-operation', () => {\n    window.DD_RUM.startFeatureOperation(`${id}-feature-operation`)\n  })\n\n  createButton(container, 'view', () => {\n    window.DD_RUM.startView({ name: `${id}-view` })\n  })\n}\n"
  },
  {
    "path": "test/apps/microfrontend/package.json",
    "content": "{\n  \"name\": \"microfrontend-test-app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack --config webpack.app1.js && webpack --config webpack.app2.js && webpack --config webpack.shell.js\"\n  },\n  \"devDependencies\": {\n    \"@datadog/webpack-plugin\": \"3.1.3\",\n    \"@module-federation/enhanced\": \"2.3.1\",\n    \"ts-loader\": \"9.5.7\",\n    \"typescript\": \"5.9.3\",\n    \"webpack\": \"5.105.4\",\n    \"webpack-cli\": \"6.0.1\"\n  }\n}\n"
  },
  {
    "path": "test/apps/microfrontend/shell.ts",
    "content": "async function initShell() {\n  // @ts-ignore Module Federation remote entries\n  await Promise.all([import('app1/app1'), import('app2/app2')])\n}\n\nvoid initShell()\n"
  },
  {
    "path": "test/apps/microfrontend/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2018\",\n    \"module\": \"esnext\",\n    \"lib\": [\"ES2018\", \"DOM\"],\n    \"moduleResolution\": \"bundler\",\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"
  },
  {
    "path": "test/apps/microfrontend/types.d.ts",
    "content": "interface Window {\n  DD_RUM: {\n    addError: (error: Error) => void\n    addAction: (name: string, context?: any) => void\n    startDurationVital: (name: string) => any\n    stopDurationVital: (ref: any) => void\n    startFeatureOperation: (name: string) => void\n    startView: (options: { name: string }) => void\n  }\n}\n"
  },
  {
    "path": "test/apps/microfrontend/webpack.app1.js",
    "content": "const { datadogWebpackPlugin } = require('@datadog/webpack-plugin')\nconst { ModuleFederationPlugin } = require('@module-federation/enhanced/webpack')\nconst webpackBase = require('./webpack.base')\n\nmodule.exports = webpackBase({\n  name: 'app1',\n  plugins: [\n    new ModuleFederationPlugin({\n      name: 'app1',\n      filename: 'app1Entry.js',\n      exposes: {\n        './app1': './app1.ts',\n      },\n    }),\n    datadogWebpackPlugin({\n      rum: {\n        enable: true,\n        sourceCodeContext: {\n          service: 'mfe-app1-service',\n          version: '1.0.0',\n        },\n      },\n    }),\n  ],\n})\n"
  },
  {
    "path": "test/apps/microfrontend/webpack.app2.js",
    "content": "const { datadogWebpackPlugin } = require('@datadog/webpack-plugin')\nconst { ModuleFederationPlugin } = require('@module-federation/enhanced/webpack')\nconst webpackBase = require('./webpack.base')\n\nmodule.exports = webpackBase({\n  name: 'app2',\n  plugins: [\n    new ModuleFederationPlugin({\n      name: 'app2',\n      filename: 'app2Entry.js',\n      exposes: {\n        './app2': './app2.ts',\n      },\n    }),\n    datadogWebpackPlugin({\n      rum: {\n        enable: true,\n        sourceCodeContext: {\n          service: 'mfe-app2-service',\n          version: '0.2.0',\n        },\n      },\n    }),\n  ],\n})\n"
  },
  {
    "path": "test/apps/microfrontend/webpack.base.js",
    "content": "const path = require('node:path')\n\nmodule.exports = ({ name, plugins, entry }) => ({\n  mode: 'development',\n  ...(entry ? { entry } : {}),\n  devtool: 'source-map',\n  module: {\n    rules: [{ test: /\\.ts$/, use: 'ts-loader' }],\n  },\n  resolve: {\n    extensions: ['.ts', '.js'],\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: `${name}.js`,\n    chunkFilename: `chunks/[name]-[contenthash]-${name}.js`,\n    publicPath: 'auto',\n  },\n  plugins,\n})\n"
  },
  {
    "path": "test/apps/microfrontend/webpack.shell.js",
    "content": "const { datadogWebpackPlugin } = require('@datadog/webpack-plugin')\nconst { ModuleFederationPlugin } = require('@module-federation/enhanced/webpack')\nconst webpackBase = require('./webpack.base')\n\nmodule.exports = webpackBase({\n  name: 'shell',\n  entry: './bootstrap.ts',\n  plugins: [\n    new ModuleFederationPlugin({\n      name: 'shell',\n      remotes: {\n        app1: 'app1@/microfrontend/app1Entry.js',\n        app2: 'app2@/microfrontend/app2Entry.js',\n      },\n    }),\n    datadogWebpackPlugin({\n      rum: {\n        enable: true,\n        sourceCodeContext: {\n          service: 'mf-shell-service',\n          version: '2.0.0',\n        },\n      },\n    }),\n  ],\n})\n"
  },
  {
    "path": "test/apps/nextjs/.gitignore",
    "content": ".next\nnode_modules\n.yarn/*\nnext-env.d.ts"
  },
  {
    "path": "test/apps/nextjs/app/@sidebar/default.tsx",
    "content": "export default function SidebarDefault() {\n  return null\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/@sidebar/guides/[...slug]/page.tsx",
    "content": "export default async function SidebarGuides({ params }: { params: Promise<{ slug: string[] }> }) {\n  const { slug } = await params\n\n  return (\n    <aside\n      data-testid=\"sidebar\"\n      style={{ borderLeft: '2px solid #ddd', paddingLeft: '1rem', marginLeft: '1rem', minWidth: '150px' }}\n    >\n      <p>Sidebar: Guides {slug.join('/')}</p>\n    </aside>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/@sidebar/page.tsx",
    "content": "export default function SidebarHome() {\n  return (\n    <aside\n      data-testid=\"sidebar\"\n      style={{ borderLeft: '2px solid #ddd', paddingLeft: '1rem', marginLeft: '1rem', minWidth: '150px' }}\n    >\n      <p>Sidebar: Home</p>\n    </aside>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/@sidebar/user/[id]/page.tsx",
    "content": "export default async function SidebarUser({ params }: { params: Promise<{ id: string }> }) {\n  const { id } = await params\n\n  return (\n    <aside\n      data-testid=\"sidebar\"\n      style={{ borderLeft: '2px solid #ddd', paddingLeft: '1rem', marginLeft: '1rem', minWidth: '150px' }}\n    >\n      <p>Sidebar: User {id}</p>\n    </aside>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/error-test/error.tsx",
    "content": "// Segment-level error boundary for the error-test route (https://nextjs.org/docs/app/api-reference/file-conventions/error).\n// Calls addNextjsError to report both client errors and server errors (with digest) to RUM.\n'use client'\n\nimport { addNextjsError } from '@datadog/browser-rum-nextjs'\nimport Link from 'next/link'\nimport { useEffect, useState } from 'react'\n\nexport default function ErrorBoundary({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {\n  const [errorReported, setErrorReported] = useState(false)\n\n  useEffect(() => {\n    addNextjsError(error)\n    setErrorReported(true)\n  }, [error])\n\n  return (\n    <div data-testid=\"error-handled\" data-error-reported={errorReported || undefined}>\n      <h2>Something went wrong!</h2>\n      {error.digest && <p data-testid=\"error-digest\">Digest: {error.digest}</p>}\n      <button onClick={reset}>Try again</button>\n      <br />\n      <Link href=\"/\">Back to Home</Link>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/error-test/page.tsx",
    "content": "// Error test page. Triggers a client-side error\n// and verifies it is captured by error.tsx via addNextjsError.\n'use client'\n\nimport { useState } from 'react'\nimport Link from 'next/link'\n\nexport default function ErrorTestPage() {\n  const [shouldThrow, setShouldThrow] = useState(false)\n\n  if (shouldThrow) {\n    throw new Error('Client error from error-test')\n  }\n\n  return (\n    <div>\n      <Link href=\"/\">Back to Home</Link>\n      <h1>Error Test</h1>\n      <button data-testid=\"trigger-error\" onClick={() => setShouldThrow(true)}>\n        Trigger Error\n      </button>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/error-test/server-error/page.tsx",
    "content": "// Server component that throws when ?throw=true is present. Used to verify that server errors\n// are caught by the parent error.tsx with a digest attached to the error context.\n// The ?throw=true guard prevents Next.js from failing the build during static prerendering.\nexport default async function ServerErrorPage({ searchParams }: { searchParams: Promise<{ throw?: string }> }) {\n  const { throw: shouldThrow } = await searchParams\n\n  if (shouldThrow === 'true') {\n    throw new Error('Server error from error-test')\n  }\n\n  return (\n    <div>\n      <h1>Server Error Test</h1>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/global-error-test/page.tsx",
    "content": "// Server component that throws at root level when ?throw=true, triggering global-error.tsx.\n// Needed because global-error.tsx only activates for errors that escape the root layout.\nexport default async function GlobalErrorTestPage({ searchParams }: { searchParams: Promise<{ throw?: string }> }) {\n  const { throw: shouldThrow } = await searchParams\n  if (shouldThrow === 'true') throw new Error('Global error test')\n  return <div>Global error test page</div>\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/global-error.tsx",
    "content": "// Global error boundary — catches errors that escape the root layout (https://nextjs.org/docs/app/getting-started/error-handling#global-errors).\n// Calls addNextjsError so tests can verify RUM captures root-level errors.\n'use client'\n\nimport { addNextjsError } from '@datadog/browser-rum-nextjs'\nimport { useEffect } from 'react'\n\nexport default function GlobalError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {\n  useEffect(() => {\n    addNextjsError(error)\n  }, [error])\n\n  return (\n    <html>\n      <body>\n        <div data-testid=\"global-error-boundary\">\n          <h2>Global error!</h2>\n          {error.digest && <p data-testid=\"error-digest\">Digest: {error.digest}</p>}\n          <button onClick={reset}>Try again</button>\n          <br />\n          <a href=\"/\">Go to Home</a>\n        </div>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/guides/[...slug]/page.tsx",
    "content": "import Link from 'next/link'\n\nexport default async function GuidesPage({ params }: { params: Promise<{ slug: string[] }> }) {\n  const { slug } = await params\n\n  return (\n    <div>\n      <Link href=\"/\">Back to Home</Link>\n      <h1>Guides: {slug.join('/')}</h1>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/layout.tsx",
    "content": "import { DatadogAppRouter } from '@datadog/browser-rum-nextjs'\n\nexport default function RootLayout({ children, sidebar }: { children: React.ReactNode; sidebar: React.ReactNode }) {\n  return (\n    <html lang=\"en\">\n      <body style={{ fontFamily: 'system-ui, sans-serif', margin: 0 }}>\n        <DatadogAppRouter />\n        <nav style={{ background: '#632ca6', padding: '1rem', marginBottom: '1rem' }}>\n          <a href=\"/\" style={{ color: 'white', textDecoration: 'none' }}>\n            Home\n          </a>\n        </nav>\n        <div style={{ display: 'flex', maxWidth: '800px', margin: '0 auto', padding: '1rem' }}>\n          <main style={{ flex: 1 }}>{children}</main>\n          {sidebar}\n        </div>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/page.tsx",
    "content": "import Link from 'next/link'\n\nexport default function HomePage() {\n  return (\n    <div>\n      <h1>Home</h1>\n      <ul>\n        <li>\n          <Link href=\"/user/42?admin=true\">Go to User 42</Link>\n        </li>\n        <li>\n          <Link href=\"/guides/123\">Go to Guides 123</Link>\n        </li>\n        <li>\n          <Link href=\"/error-test\">Go to Error Test</Link>\n        </li>\n        <li>\n          <Link href=\"/error-test/server-error?throw=true\">Go to Server Error</Link>\n        </li>\n        <li>\n          <Link href=\"/global-error-test?throw=true\">Go to Global Error</Link>\n        </li>\n      </ul>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/app/user/[id]/page.tsx",
    "content": "import Link from 'next/link'\n\nexport default async function UserPage({ params }: { params: Promise<{ id: string }> }) {\n  const { id } = await params\n\n  return (\n    <div>\n      <Link href=\"/\">← Back to Home</Link>\n      <h1>User {id}</h1>\n      <div>\n        <Link href=\"/user/999?admin=true\">Go to User 999</Link>\n      </div>\n      <div>\n        <Link href={`/user/${id}?admin=false`}>Change query params</Link>\n      </div>\n      <div>\n        <Link href={`/user/${id}#section`}>Go to Section</Link>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/instrumentation-client.js",
    "content": "import { datadogRum } from '@datadog/browser-rum'\nimport { nextjsPlugin } from '@datadog/browser-rum-nextjs'\n\nconst params = new URLSearchParams(window.location.search)\nconst config = params.get('rum-config')\nconst context = params.get('rum-context')\n\nif (config && !datadogRum.getInitConfiguration()) {\n  datadogRum.init({ ...JSON.parse(config), plugins: [nextjsPlugin()] })\n  if (context) {\n    datadogRum.setGlobalContext(JSON.parse(context))\n  }\n}\n\nexport { onRouterTransitionStart } from '@datadog/browser-rum-nextjs'\n"
  },
  {
    "path": "test/apps/nextjs/next.config.js",
    "content": "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  turbopack: {\n    root: __dirname,\n  },\n}\n\nmodule.exports = nextConfig\n"
  },
  {
    "path": "test/apps/nextjs/package.json",
    "content": "{\n  \"name\": \"nextjs\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"next build\",\n    \"start\": \"next start --port 0\"\n  },\n  \"dependencies\": {\n    \"next\": \"16.1.6\",\n    \"react\": \"19.2.4\",\n    \"react-dom\": \"19.2.4\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"*\",\n    \"@datadog/browser-rum-nextjs\": \"*\",\n    \"@datadog/browser-rum-react\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-nextjs\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-react\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-rum-nextjs\": \"file:../../../packages/rum-nextjs/package.tgz\",\n    \"@datadog/browser-rum-react\": \"file:../../../packages/rum-react/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"22.19.17\",\n    \"@types/react\": \"19.2.14\",\n    \"@types/react-dom\": \"19.2.3\",\n    \"typescript\": \"5.9.3\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/nextjs/pages/_app.tsx",
    "content": "import type { AppProps } from 'next/app'\nimport Link from 'next/link'\nimport { DatadogPagesRouter } from '@datadog/browser-rum-nextjs'\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  return (\n    <>\n      <DatadogPagesRouter />\n      <nav style={{ background: '#632ca6', padding: '1rem', marginBottom: '1rem' }}>\n        <Link href=\"/pages-router\" style={{ color: 'white', textDecoration: 'none' }}>\n          Home\n        </Link>\n      </nav>\n      <main style={{ maxWidth: '800px', margin: '0 auto', padding: '1rem' }}>\n        <Component {...pageProps} />\n      </main>\n    </>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/pages/pages-router/error-test.tsx",
    "content": "import { ErrorBoundary } from '@datadog/browser-rum-nextjs'\nimport type { ErrorBoundaryFallback } from '@datadog/browser-rum-nextjs'\nimport { useState, useEffect } from 'react'\nimport Link from 'next/link'\n\nfunction ErrorThrower() {\n  const [shouldThrow, setShouldThrow] = useState(false)\n  if (shouldThrow) throw new Error('Pages Router error from NextjsErrorBoundary')\n  return (\n    <button data-testid=\"trigger-error\" onClick={() => setShouldThrow(true)}>\n      Trigger Error\n    </button>\n  )\n}\n\nconst ErrorFallback: ErrorBoundaryFallback = ({ error, resetError }) => {\n  const [errorReported, setErrorReported] = useState(false)\n\n  useEffect(() => {\n    setErrorReported(true)\n  }, [error])\n\n  return (\n    <div data-testid=\"error-handled\" data-error-reported={errorReported || undefined}>\n      <p>{error.message}</p>\n      <button data-testid=\"reset-error\" onClick={resetError}>\n        Reset\n      </button>\n    </div>\n  )\n}\n\nexport default function ErrorTestPage() {\n  return (\n    <div>\n      <Link href=\"/pages-router\">← Back to Home</Link>\n      <h1>Error Test</h1>\n      <ErrorBoundary fallback={ErrorFallback}>\n        <ErrorThrower />\n      </ErrorBoundary>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/pages/pages-router/guides/[...slug].tsx",
    "content": "import Link from 'next/link'\nimport { useRouter } from 'next/router'\n\nexport default function GuidesPage() {\n  const router = useRouter()\n  const { slug } = router.query\n  const slugParts = Array.isArray(slug) ? slug : slug ? [slug] : []\n\n  return (\n    <div>\n      <Link href=\"/pages-router\">← Back to Home</Link>\n      <h1>Guides: {slugParts.join('/')}</h1>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/pages/pages-router/index.tsx",
    "content": "import Link from 'next/link'\n\nexport default function HomePage() {\n  return (\n    <div>\n      <h1>Home</h1>\n      <ul>\n        <li>\n          <Link href=\"/pages-router/user/42?admin=true\">Go to User 42</Link>\n        </li>\n        <li>\n          <Link href=\"/pages-router/guides/123\">Go to Guides 123</Link>\n        </li>\n        <li>\n          <Link href=\"/pages-router/error-test\">Go to Error Test</Link>\n        </li>\n      </ul>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/pages/pages-router/user/[id].tsx",
    "content": "import Link from 'next/link'\nimport { useRouter } from 'next/router'\n\nexport default function UserPage() {\n  const router = useRouter()\n  const { id } = router.query\n\n  return (\n    <div>\n      <Link href=\"/pages-router\">← Back to Home</Link>\n      <h1>User {id}</h1>\n      <div>\n        <Link href=\"/pages-router/user/999?admin=true\">Go to User 999</Link>\n      </div>\n      <div>\n        <Link href={`/pages-router/user/${id}?admin=false`}>Change query params</Link>\n      </div>\n      <div>\n        <Link href={`/pages-router/user/${id}#section`}>Go to Section</Link>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/nextjs/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    },\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\", \"**/*.js\", \".next/types/**/*.ts\", \".next/dev/types/**/*.ts\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "test/apps/nuxt-app/.gitignore",
    "content": ".next\nnode_modules\n.yarn/*\nnext-env.d.ts\n.output/*\n.nuxt/*"
  },
  {
    "path": "test/apps/nuxt-app/app.vue",
    "content": "<template>\n  <NuxtPage />\n</template>\n"
  },
  {
    "path": "test/apps/nuxt-app/nuxt.config.ts",
    "content": "import { defineNuxtConfig } from 'nuxt/config'\n\nexport default defineNuxtConfig({\n  experimental: {\n    appManifest: false,\n  },\n})\n"
  },
  {
    "path": "test/apps/nuxt-app/package.json",
    "content": "{\n  \"name\": \"nuxt-app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"nuxt build\",\n    \"dev\": \"nuxt dev --port 0 --host\",\n    \"start\": \"nuxt preview --port 0 --host\"\n  },\n  \"dependencies\": {\n    \"nuxt\": \"^3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"*\",\n    \"@datadog/browser-rum-nuxt\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-nuxt\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-rum-nuxt\": \"file:../../../packages/rum-nuxt/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/nuxt-app/pages/guides/[...slug].vue",
    "content": "<template>\n  <div>\n    <h1>Guides</h1>\n    <NuxtLink to=\"/\">Back to Home</NuxtLink>\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/nuxt-app/pages/index.vue",
    "content": "<template>\n  <div>\n    <h1>Home</h1>\n    <NuxtLink to=\"/user/42?admin=true\">Go to User 42</NuxtLink><br />\n    <NuxtLink to=\"/guides/123\">Go to Guides 123</NuxtLink><br />\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/nuxt-app/pages/user/[id].vue",
    "content": "<script setup lang=\"ts\">\nconst route = useRoute()\n</script>\n\n<template>\n  <div>\n    <h1>User {{ route.params.id }}</h1>\n    <NuxtLink to=\"/\">Back to Home</NuxtLink><br />\n    <NuxtLink :to=\"`/user/${route.params.id}#section`\">Go to Section</NuxtLink><br />\n    <NuxtLink :to=\"`/user/${route.params.id}?admin=false`\">Change query params</NuxtLink><br />\n    <NuxtLink to=\"/user/999?admin=true\">Go to User 999</NuxtLink>\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/nuxt-app/plugins/datadog-rum.client.ts",
    "content": "import { datadogRum } from '@datadog/browser-rum'\nimport { nuxtRumPlugin } from '@datadog/browser-rum-nuxt'\nimport { defineNuxtPlugin, useRoute, useRouter } from 'nuxt/app'\n\nexport default defineNuxtPlugin(() => {\n  const route = useRoute()\n  const rumConfigParam = route.query['rum-config']\n\n  if (rumConfigParam) {\n    const raw = Array.isArray(rumConfigParam) ? rumConfigParam[0] : rumConfigParam\n    if (raw) {\n      const config = JSON.parse(raw)\n      datadogRum.init({ ...config, plugins: [nuxtRumPlugin({ router: useRouter() })] })\n    }\n  }\n})\n"
  },
  {
    "path": "test/apps/nuxt-app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"**/*.ts\", \"**/*.vue\"],\n  \"exclude\": [\"node_modules\", \".nuxt\", \"dist\"]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*"
  },
  {
    "path": "test/apps/react-heavy-spa/README.md",
    "content": "# React Heavy SPA - Observability App\n\nA complex, JavaScript-heavy single-page application built with React + TypeScript for performance benchmarking and profiling of Datadog Browser SDK.\n\n## Pages\n\n- 📊 **Dashboard** – Displays metrics cards, charts, and a service grid using Recharts. Triggering CLS due to multiple large dataset fetches.\n- 📝 **Logs Explorer** – Provides log search, filtering, and a virtualized table with 2,000 logs.\n- 🖥️ **Infrastructure** – Visualizes a host map and table with 3,000 hosts, where heavy DOM manipulation causes INP delays during filtering or interaction.\n- ⚙️ **Settings** – Manages user and team settings with form submissions.\n\n## Performance metrics target\n\nTarget to have Web Vitals in the “Needs improvement” score range.\n\n- **LCP**: ~3000ms\n- **CLS**: ~0.13\n- **INP**: ~300ms\n- **TBT**: ~45000ms\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 20+ (recommended)\n- Yarn (uses Yarn by default)\n\n### Installation\n\n```bash\n# Install dependencies\nyarn install\n```\n\n### Development\n\n```bash\n# Run development server (opens browser automatically)\nyarn dev\n```\n\nThe app will be available at `http://localhost:5173`\n\n### Building for Production\n\n```bash\n# Create production build (includes TypeScript compilation)\nyarn build\n\n# Preview production build\nyarn preview\n```\n"
  },
  {
    "path": "test/apps/react-heavy-spa/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/dd_icon_rgb.png\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Heavy SPA Benchmark - Datadog Web UI</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/apps/react-heavy-spa/package.json",
    "content": "{\n  \"name\": \"heavy-spa\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite --open\",\n    \"build\": \"tsc -b && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"react\": \"19.2.4\",\n    \"react-dom\": \"19.2.4\",\n    \"react-is\": \"19.2.4\",\n    \"react-router-dom\": \"7.14.0\",\n    \"react-window\": \"2.2.7\",\n    \"recharts\": \"3.8.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"25.5.2\",\n    \"@types/react\": \"19.2.14\",\n    \"@types/react-dom\": \"19.2.3\",\n    \"@vitejs/plugin-react\": \"5.2.0\",\n    \"globals\": \"17.4.0\",\n    \"typescript\": \"5.9.3\",\n    \"vite\": \"7.3.2\"\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/public/data/infrastructure.json",
    "content": "{\n  \"hosts\": [\n    {\n      \"id\": \"host-1\",\n      \"name\": \"prod-web-0001\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 89,\n      \"disk\": 18,\n      \"network\": 12,\n      \"uptime\": 9776882\n    },\n    {\n      \"id\": \"host-2\",\n      \"name\": \"prod-api-0002\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 74,\n      \"disk\": 15,\n      \"network\": 20,\n      \"uptime\": 2607085\n    },\n    {\n      \"id\": \"host-3\",\n      \"name\": \"prod-database-0003\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 76,\n      \"disk\": 55,\n      \"network\": 19,\n      \"uptime\": 3402254\n    },\n    {\n      \"id\": \"host-4\",\n      \"name\": \"prod-cache-0004\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 34,\n      \"disk\": 52,\n      \"network\": 34,\n      \"uptime\": 5493904\n    },\n    {\n      \"id\": \"host-5\",\n      \"name\": \"prod-worker-0005\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 5,\n      \"disk\": 48,\n      \"network\": 60,\n      \"uptime\": 8502888\n    },\n    {\n      \"id\": \"host-6\",\n      \"name\": \"prod-queue-0006\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 50,\n      \"disk\": 90,\n      \"network\": 41,\n      \"uptime\": 7667432\n    },\n    {\n      \"id\": \"host-7\",\n      \"name\": \"prod-web-0007\",\n      \"status\": \"healthy\",\n      \"cpu\": 25,\n      \"memory\": 1,\n      \"disk\": 20,\n      \"network\": 92,\n      \"uptime\": 5930833\n    },\n    {\n      \"id\": \"host-8\",\n      \"name\": \"prod-api-0008\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 61,\n      \"disk\": 79,\n      \"network\": 65,\n      \"uptime\": 5274908\n    },\n    {\n      \"id\": \"host-9\",\n      \"name\": \"prod-database-0009\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 44,\n      \"disk\": 67,\n      \"network\": 62,\n      \"uptime\": 2357151\n    },\n    {\n      \"id\": \"host-10\",\n      \"name\": \"prod-cache-0010\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 87,\n      \"disk\": 12,\n      \"network\": 23,\n      \"uptime\": 5449352\n    },\n    {\n      \"id\": \"host-11\",\n      \"name\": \"prod-worker-0011\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 50,\n      \"disk\": 65,\n      \"network\": 12,\n      \"uptime\": 8758949\n    },\n    {\n      \"id\": \"host-12\",\n      \"name\": \"prod-queue-0012\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 39,\n      \"disk\": 73,\n      \"network\": 62,\n      \"uptime\": 8254237\n    },\n    {\n      \"id\": \"host-13\",\n      \"name\": \"prod-web-0013\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 52,\n      \"disk\": 26,\n      \"network\": 85,\n      \"uptime\": 7782372\n    },\n    {\n      \"id\": \"host-14\",\n      \"name\": \"prod-api-0014\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 8,\n      \"disk\": 46,\n      \"network\": 9,\n      \"uptime\": 3308388\n    },\n    {\n      \"id\": \"host-15\",\n      \"name\": \"prod-database-0015\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 97,\n      \"disk\": 42,\n      \"network\": 77,\n      \"uptime\": 5914431\n    },\n    {\n      \"id\": \"host-16\",\n      \"name\": \"prod-cache-0016\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 68,\n      \"disk\": 62,\n      \"network\": 51,\n      \"uptime\": 7327003\n    },\n    {\n      \"id\": \"host-17\",\n      \"name\": \"prod-worker-0017\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 68,\n      \"disk\": 32,\n      \"network\": 82,\n      \"uptime\": 4631534\n    },\n    {\n      \"id\": \"host-18\",\n      \"name\": \"prod-queue-0018\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 42,\n      \"disk\": 2,\n      \"network\": 50,\n      \"uptime\": 2711362\n    },\n    {\n      \"id\": \"host-19\",\n      \"name\": \"prod-web-0019\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 92,\n      \"disk\": 31,\n      \"network\": 92,\n      \"uptime\": 6311807\n    },\n    {\n      \"id\": \"host-20\",\n      \"name\": \"prod-api-0020\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 67,\n      \"disk\": 37,\n      \"network\": 94,\n      \"uptime\": 3981426\n    },\n    {\n      \"id\": \"host-21\",\n      \"name\": \"prod-database-0021\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 98,\n      \"disk\": 85,\n      \"network\": 63,\n      \"uptime\": 4564554\n    },\n    {\n      \"id\": \"host-22\",\n      \"name\": \"prod-cache-0022\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 44,\n      \"disk\": 54,\n      \"network\": 16,\n      \"uptime\": 3858200\n    },\n    {\n      \"id\": \"host-23\",\n      \"name\": \"prod-worker-0023\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 29,\n      \"disk\": 19,\n      \"network\": 70,\n      \"uptime\": 6487175\n    },\n    {\n      \"id\": \"host-24\",\n      \"name\": \"prod-queue-0024\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 42,\n      \"disk\": 80,\n      \"network\": 57,\n      \"uptime\": 2921984\n    },\n    {\n      \"id\": \"host-25\",\n      \"name\": \"prod-web-0025\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 26,\n      \"disk\": 84,\n      \"network\": 61,\n      \"uptime\": 5118400\n    },\n    {\n      \"id\": \"host-26\",\n      \"name\": \"prod-api-0026\",\n      \"status\": \"healthy\",\n      \"cpu\": 77,\n      \"memory\": 73,\n      \"disk\": 39,\n      \"network\": 27,\n      \"uptime\": 8909293\n    },\n    {\n      \"id\": \"host-27\",\n      \"name\": \"prod-database-0027\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 65,\n      \"disk\": 34,\n      \"network\": 32,\n      \"uptime\": 266242\n    },\n    {\n      \"id\": \"host-28\",\n      \"name\": \"prod-cache-0028\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 24,\n      \"disk\": 25,\n      \"network\": 8,\n      \"uptime\": 8939960\n    },\n    {\n      \"id\": \"host-29\",\n      \"name\": \"prod-worker-0029\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 54,\n      \"disk\": 43,\n      \"network\": 97,\n      \"uptime\": 287481\n    },\n    {\n      \"id\": \"host-30\",\n      \"name\": \"prod-queue-0030\",\n      \"status\": \"healthy\",\n      \"cpu\": 85,\n      \"memory\": 88,\n      \"disk\": 73,\n      \"network\": 94,\n      \"uptime\": 3015730\n    },\n    {\n      \"id\": \"host-31\",\n      \"name\": \"prod-web-0031\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 15,\n      \"disk\": 9,\n      \"network\": 37,\n      \"uptime\": 1248340\n    },\n    {\n      \"id\": \"host-32\",\n      \"name\": \"prod-api-0032\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 0,\n      \"disk\": 87,\n      \"network\": 44,\n      \"uptime\": 8534846\n    },\n    {\n      \"id\": \"host-33\",\n      \"name\": \"prod-database-0033\",\n      \"status\": \"healthy\",\n      \"cpu\": 100,\n      \"memory\": 39,\n      \"disk\": 51,\n      \"network\": 17,\n      \"uptime\": 4625919\n    },\n    {\n      \"id\": \"host-34\",\n      \"name\": \"prod-cache-0034\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 16,\n      \"disk\": 14,\n      \"network\": 93,\n      \"uptime\": 1476071\n    },\n    {\n      \"id\": \"host-35\",\n      \"name\": \"prod-worker-0035\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 54,\n      \"disk\": 61,\n      \"network\": 63,\n      \"uptime\": 9192372\n    },\n    {\n      \"id\": \"host-36\",\n      \"name\": \"prod-queue-0036\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 7,\n      \"disk\": 71,\n      \"network\": 62,\n      \"uptime\": 6542166\n    },\n    {\n      \"id\": \"host-37\",\n      \"name\": \"prod-web-0037\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 3,\n      \"disk\": 12,\n      \"network\": 93,\n      \"uptime\": 1892156\n    },\n    {\n      \"id\": \"host-38\",\n      \"name\": \"prod-api-0038\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 11,\n      \"disk\": 10,\n      \"network\": 42,\n      \"uptime\": 9501549\n    },\n    {\n      \"id\": \"host-39\",\n      \"name\": \"prod-database-0039\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 3,\n      \"disk\": 41,\n      \"network\": 64,\n      \"uptime\": 49515\n    },\n    {\n      \"id\": \"host-40\",\n      \"name\": \"prod-cache-0040\",\n      \"status\": \"healthy\",\n      \"cpu\": 30,\n      \"memory\": 98,\n      \"disk\": 64,\n      \"network\": 5,\n      \"uptime\": 7939934\n    },\n    {\n      \"id\": \"host-41\",\n      \"name\": \"prod-worker-0041\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 45,\n      \"disk\": 48,\n      \"network\": 56,\n      \"uptime\": 7567696\n    },\n    {\n      \"id\": \"host-42\",\n      \"name\": \"prod-queue-0042\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 68,\n      \"disk\": 3,\n      \"network\": 52,\n      \"uptime\": 7466013\n    },\n    {\n      \"id\": \"host-43\",\n      \"name\": \"prod-web-0043\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 25,\n      \"disk\": 54,\n      \"network\": 62,\n      \"uptime\": 1883086\n    },\n    {\n      \"id\": \"host-44\",\n      \"name\": \"prod-api-0044\",\n      \"status\": \"healthy\",\n      \"cpu\": 63,\n      \"memory\": 2,\n      \"disk\": 23,\n      \"network\": 31,\n      \"uptime\": 1715943\n    },\n    {\n      \"id\": \"host-45\",\n      \"name\": \"prod-database-0045\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 93,\n      \"disk\": 0,\n      \"network\": 96,\n      \"uptime\": 7859324\n    },\n    {\n      \"id\": \"host-46\",\n      \"name\": \"prod-cache-0046\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 79,\n      \"disk\": 8,\n      \"network\": 6,\n      \"uptime\": 6605722\n    },\n    {\n      \"id\": \"host-47\",\n      \"name\": \"prod-worker-0047\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 56,\n      \"disk\": 64,\n      \"network\": 47,\n      \"uptime\": 6931268\n    },\n    {\n      \"id\": \"host-48\",\n      \"name\": \"prod-queue-0048\",\n      \"status\": \"healthy\",\n      \"cpu\": 75,\n      \"memory\": 61,\n      \"disk\": 19,\n      \"network\": 77,\n      \"uptime\": 6402813\n    },\n    {\n      \"id\": \"host-49\",\n      \"name\": \"prod-web-0049\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 91,\n      \"disk\": 77,\n      \"network\": 82,\n      \"uptime\": 3577518\n    },\n    {\n      \"id\": \"host-50\",\n      \"name\": \"prod-api-0050\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 54,\n      \"disk\": 29,\n      \"network\": 31,\n      \"uptime\": 1531268\n    },\n    {\n      \"id\": \"host-51\",\n      \"name\": \"prod-database-0051\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 25,\n      \"disk\": 25,\n      \"network\": 48,\n      \"uptime\": 3072808\n    },\n    {\n      \"id\": \"host-52\",\n      \"name\": \"prod-cache-0052\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 81,\n      \"disk\": 75,\n      \"network\": 92,\n      \"uptime\": 5935013\n    },\n    {\n      \"id\": \"host-53\",\n      \"name\": \"prod-worker-0053\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 10,\n      \"disk\": 28,\n      \"network\": 31,\n      \"uptime\": 4304609\n    },\n    {\n      \"id\": \"host-54\",\n      \"name\": \"prod-queue-0054\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 34,\n      \"disk\": 92,\n      \"network\": 14,\n      \"uptime\": 4485818\n    },\n    {\n      \"id\": \"host-55\",\n      \"name\": \"prod-web-0055\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 24,\n      \"disk\": 9,\n      \"network\": 26,\n      \"uptime\": 9063818\n    },\n    {\n      \"id\": \"host-56\",\n      \"name\": \"prod-api-0056\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 39,\n      \"disk\": 74,\n      \"network\": 96,\n      \"uptime\": 6890424\n    },\n    {\n      \"id\": \"host-57\",\n      \"name\": \"prod-database-0057\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 18,\n      \"disk\": 70,\n      \"network\": 87,\n      \"uptime\": 7831827\n    },\n    {\n      \"id\": \"host-58\",\n      \"name\": \"prod-cache-0058\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 7,\n      \"disk\": 73,\n      \"network\": 33,\n      \"uptime\": 2864899\n    },\n    {\n      \"id\": \"host-59\",\n      \"name\": \"prod-worker-0059\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 4,\n      \"disk\": 13,\n      \"network\": 100,\n      \"uptime\": 8254412\n    },\n    {\n      \"id\": \"host-60\",\n      \"name\": \"prod-queue-0060\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 91,\n      \"disk\": 58,\n      \"network\": 56,\n      \"uptime\": 2048667\n    },\n    {\n      \"id\": \"host-61\",\n      \"name\": \"prod-web-0061\",\n      \"status\": \"warning\",\n      \"cpu\": 23,\n      \"memory\": 77,\n      \"disk\": 33,\n      \"network\": 78,\n      \"uptime\": 2822472\n    },\n    {\n      \"id\": \"host-62\",\n      \"name\": \"prod-api-0062\",\n      \"status\": \"warning\",\n      \"cpu\": 91,\n      \"memory\": 83,\n      \"disk\": 23,\n      \"network\": 84,\n      \"uptime\": 7666720\n    },\n    {\n      \"id\": \"host-63\",\n      \"name\": \"prod-database-0063\",\n      \"status\": \"warning\",\n      \"cpu\": 51,\n      \"memory\": 61,\n      \"disk\": 19,\n      \"network\": 81,\n      \"uptime\": 5051741\n    },\n    {\n      \"id\": \"host-64\",\n      \"name\": \"prod-cache-0064\",\n      \"status\": \"warning\",\n      \"cpu\": 58,\n      \"memory\": 31,\n      \"disk\": 45,\n      \"network\": 24,\n      \"uptime\": 7732725\n    },\n    {\n      \"id\": \"host-65\",\n      \"name\": \"prod-worker-0065\",\n      \"status\": \"warning\",\n      \"cpu\": 29,\n      \"memory\": 44,\n      \"disk\": 99,\n      \"network\": 0,\n      \"uptime\": 7883689\n    },\n    {\n      \"id\": \"host-66\",\n      \"name\": \"prod-queue-0066\",\n      \"status\": \"warning\",\n      \"cpu\": 53,\n      \"memory\": 95,\n      \"disk\": 95,\n      \"network\": 67,\n      \"uptime\": 5587542\n    },\n    {\n      \"id\": \"host-67\",\n      \"name\": \"prod-web-0067\",\n      \"status\": \"warning\",\n      \"cpu\": 26,\n      \"memory\": 14,\n      \"disk\": 61,\n      \"network\": 62,\n      \"uptime\": 1035557\n    },\n    {\n      \"id\": \"host-68\",\n      \"name\": \"prod-api-0068\",\n      \"status\": \"warning\",\n      \"cpu\": 37,\n      \"memory\": 69,\n      \"disk\": 3,\n      \"network\": 25,\n      \"uptime\": 5188105\n    },\n    {\n      \"id\": \"host-69\",\n      \"name\": \"prod-database-0069\",\n      \"status\": \"warning\",\n      \"cpu\": 0,\n      \"memory\": 57,\n      \"disk\": 69,\n      \"network\": 57,\n      \"uptime\": 6990514\n    },\n    {\n      \"id\": \"host-70\",\n      \"name\": \"prod-cache-0070\",\n      \"status\": \"warning\",\n      \"cpu\": 0,\n      \"memory\": 56,\n      \"disk\": 14,\n      \"network\": 83,\n      \"uptime\": 3868563\n    },\n    {\n      \"id\": \"host-71\",\n      \"name\": \"prod-worker-0071\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 12,\n      \"disk\": 76,\n      \"network\": 28,\n      \"uptime\": 5264953\n    },\n    {\n      \"id\": \"host-72\",\n      \"name\": \"prod-queue-0072\",\n      \"status\": \"warning\",\n      \"cpu\": 37,\n      \"memory\": 73,\n      \"disk\": 89,\n      \"network\": 42,\n      \"uptime\": 8771063\n    },\n    {\n      \"id\": \"host-73\",\n      \"name\": \"prod-web-0073\",\n      \"status\": \"warning\",\n      \"cpu\": 28,\n      \"memory\": 75,\n      \"disk\": 36,\n      \"network\": 43,\n      \"uptime\": 8282086\n    },\n    {\n      \"id\": \"host-74\",\n      \"name\": \"prod-api-0074\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 83,\n      \"disk\": 71,\n      \"network\": 61,\n      \"uptime\": 7637065\n    },\n    {\n      \"id\": \"host-75\",\n      \"name\": \"prod-database-0075\",\n      \"status\": \"warning\",\n      \"cpu\": 86,\n      \"memory\": 80,\n      \"disk\": 52,\n      \"network\": 4,\n      \"uptime\": 4635447\n    },\n    {\n      \"id\": \"host-76\",\n      \"name\": \"prod-cache-0076\",\n      \"status\": \"warning\",\n      \"cpu\": 94,\n      \"memory\": 78,\n      \"disk\": 2,\n      \"network\": 62,\n      \"uptime\": 2305005\n    },\n    {\n      \"id\": \"host-77\",\n      \"name\": \"prod-worker-0077\",\n      \"status\": \"warning\",\n      \"cpu\": 94,\n      \"memory\": 55,\n      \"disk\": 18,\n      \"network\": 8,\n      \"uptime\": 9629549\n    },\n    {\n      \"id\": \"host-78\",\n      \"name\": \"prod-queue-0078\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 89,\n      \"disk\": 11,\n      \"network\": 19,\n      \"uptime\": 3842259\n    },\n    {\n      \"id\": \"host-79\",\n      \"name\": \"prod-web-0079\",\n      \"status\": \"warning\",\n      \"cpu\": 31,\n      \"memory\": 9,\n      \"disk\": 17,\n      \"network\": 96,\n      \"uptime\": 1072392\n    },\n    {\n      \"id\": \"host-80\",\n      \"name\": \"prod-api-0080\",\n      \"status\": \"warning\",\n      \"cpu\": 65,\n      \"memory\": 32,\n      \"disk\": 87,\n      \"network\": 20,\n      \"uptime\": 2781166\n    },\n    {\n      \"id\": \"host-81\",\n      \"name\": \"prod-database-0081\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 95,\n      \"disk\": 25,\n      \"network\": 84,\n      \"uptime\": 4308435\n    },\n    {\n      \"id\": \"host-82\",\n      \"name\": \"prod-cache-0082\",\n      \"status\": \"warning\",\n      \"cpu\": 63,\n      \"memory\": 0,\n      \"disk\": 11,\n      \"network\": 41,\n      \"uptime\": 5749750\n    },\n    {\n      \"id\": \"host-83\",\n      \"name\": \"prod-worker-0083\",\n      \"status\": \"warning\",\n      \"cpu\": 79,\n      \"memory\": 23,\n      \"disk\": 86,\n      \"network\": 20,\n      \"uptime\": 870408\n    },\n    {\n      \"id\": \"host-84\",\n      \"name\": \"prod-queue-0084\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 94,\n      \"disk\": 43,\n      \"network\": 74,\n      \"uptime\": 4211429\n    },\n    {\n      \"id\": \"host-85\",\n      \"name\": \"prod-web-0085\",\n      \"status\": \"warning\",\n      \"cpu\": 17,\n      \"memory\": 72,\n      \"disk\": 86,\n      \"network\": 33,\n      \"uptime\": 113608\n    },\n    {\n      \"id\": \"host-86\",\n      \"name\": \"prod-api-0086\",\n      \"status\": \"critical\",\n      \"cpu\": 50,\n      \"memory\": 21,\n      \"disk\": 94,\n      \"network\": 91,\n      \"uptime\": 5890630\n    },\n    {\n      \"id\": \"host-87\",\n      \"name\": \"prod-database-0087\",\n      \"status\": \"critical\",\n      \"cpu\": 17,\n      \"memory\": 68,\n      \"disk\": 86,\n      \"network\": 84,\n      \"uptime\": 4653238\n    },\n    {\n      \"id\": \"host-88\",\n      \"name\": \"prod-cache-0088\",\n      \"status\": \"critical\",\n      \"cpu\": 56,\n      \"memory\": 15,\n      \"disk\": 77,\n      \"network\": 25,\n      \"uptime\": 9602861\n    },\n    {\n      \"id\": \"host-89\",\n      \"name\": \"prod-worker-0089\",\n      \"status\": \"critical\",\n      \"cpu\": 81,\n      \"memory\": 43,\n      \"disk\": 25,\n      \"network\": 47,\n      \"uptime\": 2541798\n    },\n    {\n      \"id\": \"host-90\",\n      \"name\": \"prod-queue-0090\",\n      \"status\": \"critical\",\n      \"cpu\": 37,\n      \"memory\": 58,\n      \"disk\": 31,\n      \"network\": 76,\n      \"uptime\": 5060135\n    },\n    {\n      \"id\": \"host-91\",\n      \"name\": \"prod-web-0091\",\n      \"status\": \"critical\",\n      \"cpu\": 6,\n      \"memory\": 51,\n      \"disk\": 56,\n      \"network\": 78,\n      \"uptime\": 6530164\n    },\n    {\n      \"id\": \"host-92\",\n      \"name\": \"prod-api-0092\",\n      \"status\": \"critical\",\n      \"cpu\": 97,\n      \"memory\": 54,\n      \"disk\": 0,\n      \"network\": 42,\n      \"uptime\": 6830529\n    },\n    {\n      \"id\": \"host-93\",\n      \"name\": \"prod-database-0093\",\n      \"status\": \"critical\",\n      \"cpu\": 26,\n      \"memory\": 69,\n      \"disk\": 72,\n      \"network\": 48,\n      \"uptime\": 4042286\n    },\n    {\n      \"id\": \"host-94\",\n      \"name\": \"prod-cache-0094\",\n      \"status\": \"critical\",\n      \"cpu\": 66,\n      \"memory\": 83,\n      \"disk\": 32,\n      \"network\": 66,\n      \"uptime\": 48929\n    },\n    {\n      \"id\": \"host-95\",\n      \"name\": \"prod-worker-0095\",\n      \"status\": \"critical\",\n      \"cpu\": 40,\n      \"memory\": 28,\n      \"disk\": 38,\n      \"network\": 55,\n      \"uptime\": 5043444\n    },\n    {\n      \"id\": \"host-96\",\n      \"name\": \"prod-queue-0096\",\n      \"status\": \"critical\",\n      \"cpu\": 82,\n      \"memory\": 92,\n      \"disk\": 45,\n      \"network\": 35,\n      \"uptime\": 3800637\n    },\n    {\n      \"id\": \"host-97\",\n      \"name\": \"prod-web-0097\",\n      \"status\": \"critical\",\n      \"cpu\": 75,\n      \"memory\": 73,\n      \"disk\": 25,\n      \"network\": 70,\n      \"uptime\": 9575860\n    },\n    {\n      \"id\": \"host-98\",\n      \"name\": \"prod-api-0098\",\n      \"status\": \"critical\",\n      \"cpu\": 94,\n      \"memory\": 33,\n      \"disk\": 26,\n      \"network\": 0,\n      \"uptime\": 4248544\n    },\n    {\n      \"id\": \"host-99\",\n      \"name\": \"prod-database-0099\",\n      \"status\": \"critical\",\n      \"cpu\": 31,\n      \"memory\": 76,\n      \"disk\": 92,\n      \"network\": 98,\n      \"uptime\": 1865496\n    },\n    {\n      \"id\": \"host-100\",\n      \"name\": \"prod-cache-0100\",\n      \"status\": \"critical\",\n      \"cpu\": 14,\n      \"memory\": 36,\n      \"disk\": 61,\n      \"network\": 14,\n      \"uptime\": 5348001\n    },\n    {\n      \"id\": \"host-101\",\n      \"name\": \"prod-worker-0101\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 48,\n      \"disk\": 47,\n      \"network\": 51,\n      \"uptime\": 777018\n    },\n    {\n      \"id\": \"host-102\",\n      \"name\": \"prod-queue-0102\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 55,\n      \"disk\": 92,\n      \"network\": 4,\n      \"uptime\": 4348637\n    },\n    {\n      \"id\": \"host-103\",\n      \"name\": \"prod-web-0103\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 3,\n      \"disk\": 52,\n      \"network\": 51,\n      \"uptime\": 1673085\n    },\n    {\n      \"id\": \"host-104\",\n      \"name\": \"prod-api-0104\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 49,\n      \"disk\": 52,\n      \"network\": 76,\n      \"uptime\": 5330646\n    },\n    {\n      \"id\": \"host-105\",\n      \"name\": \"prod-database-0105\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 56,\n      \"disk\": 30,\n      \"network\": 6,\n      \"uptime\": 7465541\n    },\n    {\n      \"id\": \"host-106\",\n      \"name\": \"prod-cache-0106\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 32,\n      \"disk\": 95,\n      \"network\": 34,\n      \"uptime\": 1469388\n    },\n    {\n      \"id\": \"host-107\",\n      \"name\": \"prod-worker-0107\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 88,\n      \"disk\": 19,\n      \"network\": 86,\n      \"uptime\": 2053476\n    },\n    {\n      \"id\": \"host-108\",\n      \"name\": \"prod-queue-0108\",\n      \"status\": \"healthy\",\n      \"cpu\": 74,\n      \"memory\": 77,\n      \"disk\": 100,\n      \"network\": 92,\n      \"uptime\": 6088311\n    },\n    {\n      \"id\": \"host-109\",\n      \"name\": \"prod-web-0109\",\n      \"status\": \"healthy\",\n      \"cpu\": 3,\n      \"memory\": 50,\n      \"disk\": 76,\n      \"network\": 24,\n      \"uptime\": 3442409\n    },\n    {\n      \"id\": \"host-110\",\n      \"name\": \"prod-api-0110\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 48,\n      \"disk\": 60,\n      \"network\": 56,\n      \"uptime\": 2220762\n    },\n    {\n      \"id\": \"host-111\",\n      \"name\": \"prod-database-0111\",\n      \"status\": \"healthy\",\n      \"cpu\": 25,\n      \"memory\": 25,\n      \"disk\": 45,\n      \"network\": 82,\n      \"uptime\": 8663771\n    },\n    {\n      \"id\": \"host-112\",\n      \"name\": \"prod-cache-0112\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 49,\n      \"disk\": 44,\n      \"network\": 68,\n      \"uptime\": 3455935\n    },\n    {\n      \"id\": \"host-113\",\n      \"name\": \"prod-worker-0113\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 77,\n      \"disk\": 65,\n      \"network\": 28,\n      \"uptime\": 5880476\n    },\n    {\n      \"id\": \"host-114\",\n      \"name\": \"prod-queue-0114\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 45,\n      \"disk\": 65,\n      \"network\": 3,\n      \"uptime\": 6575579\n    },\n    {\n      \"id\": \"host-115\",\n      \"name\": \"prod-web-0115\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 30,\n      \"disk\": 1,\n      \"network\": 87,\n      \"uptime\": 4566541\n    },\n    {\n      \"id\": \"host-116\",\n      \"name\": \"prod-api-0116\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 65,\n      \"disk\": 97,\n      \"network\": 51,\n      \"uptime\": 2512073\n    },\n    {\n      \"id\": \"host-117\",\n      \"name\": \"prod-database-0117\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 3,\n      \"disk\": 68,\n      \"network\": 53,\n      \"uptime\": 3432105\n    },\n    {\n      \"id\": \"host-118\",\n      \"name\": \"prod-cache-0118\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 81,\n      \"disk\": 64,\n      \"network\": 14,\n      \"uptime\": 5103503\n    },\n    {\n      \"id\": \"host-119\",\n      \"name\": \"prod-worker-0119\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 13,\n      \"disk\": 88,\n      \"network\": 57,\n      \"uptime\": 1622259\n    },\n    {\n      \"id\": \"host-120\",\n      \"name\": \"prod-queue-0120\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 57,\n      \"disk\": 62,\n      \"network\": 16,\n      \"uptime\": 1592574\n    },\n    {\n      \"id\": \"host-121\",\n      \"name\": \"prod-web-0121\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 84,\n      \"disk\": 63,\n      \"network\": 55,\n      \"uptime\": 2881370\n    },\n    {\n      \"id\": \"host-122\",\n      \"name\": \"prod-api-0122\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 9,\n      \"disk\": 27,\n      \"network\": 56,\n      \"uptime\": 8346807\n    },\n    {\n      \"id\": \"host-123\",\n      \"name\": \"prod-database-0123\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 87,\n      \"disk\": 95,\n      \"network\": 57,\n      \"uptime\": 4774506\n    },\n    {\n      \"id\": \"host-124\",\n      \"name\": \"prod-cache-0124\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 83,\n      \"disk\": 20,\n      \"network\": 58,\n      \"uptime\": 1521911\n    },\n    {\n      \"id\": \"host-125\",\n      \"name\": \"prod-worker-0125\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 56,\n      \"disk\": 70,\n      \"network\": 36,\n      \"uptime\": 1064\n    },\n    {\n      \"id\": \"host-126\",\n      \"name\": \"prod-queue-0126\",\n      \"status\": \"healthy\",\n      \"cpu\": 77,\n      \"memory\": 75,\n      \"disk\": 41,\n      \"network\": 29,\n      \"uptime\": 4486636\n    },\n    {\n      \"id\": \"host-127\",\n      \"name\": \"prod-web-0127\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 24,\n      \"disk\": 38,\n      \"network\": 25,\n      \"uptime\": 1267096\n    },\n    {\n      \"id\": \"host-128\",\n      \"name\": \"prod-api-0128\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 61,\n      \"disk\": 96,\n      \"network\": 13,\n      \"uptime\": 1593356\n    },\n    {\n      \"id\": \"host-129\",\n      \"name\": \"prod-database-0129\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 4,\n      \"disk\": 99,\n      \"network\": 2,\n      \"uptime\": 1551316\n    },\n    {\n      \"id\": \"host-130\",\n      \"name\": \"prod-cache-0130\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 47,\n      \"disk\": 14,\n      \"network\": 86,\n      \"uptime\": 6822126\n    },\n    {\n      \"id\": \"host-131\",\n      \"name\": \"prod-worker-0131\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 78,\n      \"disk\": 57,\n      \"network\": 65,\n      \"uptime\": 6509974\n    },\n    {\n      \"id\": \"host-132\",\n      \"name\": \"prod-queue-0132\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 43,\n      \"disk\": 24,\n      \"network\": 36,\n      \"uptime\": 5014458\n    },\n    {\n      \"id\": \"host-133\",\n      \"name\": \"prod-web-0133\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 37,\n      \"disk\": 74,\n      \"network\": 57,\n      \"uptime\": 9824628\n    },\n    {\n      \"id\": \"host-134\",\n      \"name\": \"prod-api-0134\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 85,\n      \"disk\": 56,\n      \"network\": 9,\n      \"uptime\": 8740376\n    },\n    {\n      \"id\": \"host-135\",\n      \"name\": \"prod-database-0135\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 48,\n      \"disk\": 20,\n      \"network\": 44,\n      \"uptime\": 3013099\n    },\n    {\n      \"id\": \"host-136\",\n      \"name\": \"prod-cache-0136\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 66,\n      \"disk\": 57,\n      \"network\": 80,\n      \"uptime\": 8007609\n    },\n    {\n      \"id\": \"host-137\",\n      \"name\": \"prod-worker-0137\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 19,\n      \"disk\": 78,\n      \"network\": 81,\n      \"uptime\": 4316298\n    },\n    {\n      \"id\": \"host-138\",\n      \"name\": \"prod-queue-0138\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 74,\n      \"disk\": 34,\n      \"network\": 88,\n      \"uptime\": 3575355\n    },\n    {\n      \"id\": \"host-139\",\n      \"name\": \"prod-web-0139\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 45,\n      \"disk\": 85,\n      \"network\": 10,\n      \"uptime\": 4861527\n    },\n    {\n      \"id\": \"host-140\",\n      \"name\": \"prod-api-0140\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 89,\n      \"disk\": 1,\n      \"network\": 10,\n      \"uptime\": 5888645\n    },\n    {\n      \"id\": \"host-141\",\n      \"name\": \"prod-database-0141\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 68,\n      \"disk\": 61,\n      \"network\": 68,\n      \"uptime\": 8789724\n    },\n    {\n      \"id\": \"host-142\",\n      \"name\": \"prod-cache-0142\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 81,\n      \"disk\": 65,\n      \"network\": 70,\n      \"uptime\": 4981182\n    },\n    {\n      \"id\": \"host-143\",\n      \"name\": \"prod-worker-0143\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 87,\n      \"disk\": 13,\n      \"network\": 66,\n      \"uptime\": 2312579\n    },\n    {\n      \"id\": \"host-144\",\n      \"name\": \"prod-queue-0144\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 11,\n      \"disk\": 88,\n      \"network\": 54,\n      \"uptime\": 9492562\n    },\n    {\n      \"id\": \"host-145\",\n      \"name\": \"prod-web-0145\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 65,\n      \"disk\": 1,\n      \"network\": 23,\n      \"uptime\": 406652\n    },\n    {\n      \"id\": \"host-146\",\n      \"name\": \"prod-api-0146\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 68,\n      \"disk\": 96,\n      \"network\": 22,\n      \"uptime\": 6822403\n    },\n    {\n      \"id\": \"host-147\",\n      \"name\": \"prod-database-0147\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 9,\n      \"disk\": 67,\n      \"network\": 37,\n      \"uptime\": 477651\n    },\n    {\n      \"id\": \"host-148\",\n      \"name\": \"prod-cache-0148\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 87,\n      \"disk\": 68,\n      \"network\": 1,\n      \"uptime\": 4013558\n    },\n    {\n      \"id\": \"host-149\",\n      \"name\": \"prod-worker-0149\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 21,\n      \"disk\": 78,\n      \"network\": 19,\n      \"uptime\": 500837\n    },\n    {\n      \"id\": \"host-150\",\n      \"name\": \"prod-queue-0150\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 96,\n      \"disk\": 49,\n      \"network\": 10,\n      \"uptime\": 6329870\n    },\n    {\n      \"id\": \"host-151\",\n      \"name\": \"prod-web-0151\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 99,\n      \"disk\": 29,\n      \"network\": 91,\n      \"uptime\": 7662100\n    },\n    {\n      \"id\": \"host-152\",\n      \"name\": \"prod-api-0152\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 31,\n      \"disk\": 98,\n      \"network\": 54,\n      \"uptime\": 7193443\n    },\n    {\n      \"id\": \"host-153\",\n      \"name\": \"prod-database-0153\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 81,\n      \"disk\": 50,\n      \"network\": 72,\n      \"uptime\": 2127150\n    },\n    {\n      \"id\": \"host-154\",\n      \"name\": \"prod-cache-0154\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 79,\n      \"disk\": 36,\n      \"network\": 8,\n      \"uptime\": 8842165\n    },\n    {\n      \"id\": \"host-155\",\n      \"name\": \"prod-worker-0155\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 11,\n      \"disk\": 5,\n      \"network\": 81,\n      \"uptime\": 1046401\n    },\n    {\n      \"id\": \"host-156\",\n      \"name\": \"prod-queue-0156\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 1,\n      \"disk\": 98,\n      \"network\": 95,\n      \"uptime\": 7026678\n    },\n    {\n      \"id\": \"host-157\",\n      \"name\": \"prod-web-0157\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 65,\n      \"disk\": 5,\n      \"network\": 61,\n      \"uptime\": 5047398\n    },\n    {\n      \"id\": \"host-158\",\n      \"name\": \"prod-api-0158\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 75,\n      \"disk\": 99,\n      \"network\": 89,\n      \"uptime\": 9111155\n    },\n    {\n      \"id\": \"host-159\",\n      \"name\": \"prod-database-0159\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 34,\n      \"disk\": 33,\n      \"network\": 45,\n      \"uptime\": 9586303\n    },\n    {\n      \"id\": \"host-160\",\n      \"name\": \"prod-cache-0160\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 49,\n      \"disk\": 46,\n      \"network\": 96,\n      \"uptime\": 8412364\n    },\n    {\n      \"id\": \"host-161\",\n      \"name\": \"prod-worker-0161\",\n      \"status\": \"warning\",\n      \"cpu\": 46,\n      \"memory\": 41,\n      \"disk\": 79,\n      \"network\": 44,\n      \"uptime\": 1144463\n    },\n    {\n      \"id\": \"host-162\",\n      \"name\": \"prod-queue-0162\",\n      \"status\": \"warning\",\n      \"cpu\": 64,\n      \"memory\": 35,\n      \"disk\": 33,\n      \"network\": 30,\n      \"uptime\": 1863216\n    },\n    {\n      \"id\": \"host-163\",\n      \"name\": \"prod-web-0163\",\n      \"status\": \"warning\",\n      \"cpu\": 15,\n      \"memory\": 85,\n      \"disk\": 40,\n      \"network\": 36,\n      \"uptime\": 4873561\n    },\n    {\n      \"id\": \"host-164\",\n      \"name\": \"prod-api-0164\",\n      \"status\": \"warning\",\n      \"cpu\": 78,\n      \"memory\": 69,\n      \"disk\": 73,\n      \"network\": 90,\n      \"uptime\": 7089232\n    },\n    {\n      \"id\": \"host-165\",\n      \"name\": \"prod-database-0165\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 43,\n      \"disk\": 44,\n      \"network\": 94,\n      \"uptime\": 4431418\n    },\n    {\n      \"id\": \"host-166\",\n      \"name\": \"prod-cache-0166\",\n      \"status\": \"warning\",\n      \"cpu\": 14,\n      \"memory\": 91,\n      \"disk\": 57,\n      \"network\": 56,\n      \"uptime\": 4193070\n    },\n    {\n      \"id\": \"host-167\",\n      \"name\": \"prod-worker-0167\",\n      \"status\": \"warning\",\n      \"cpu\": 41,\n      \"memory\": 84,\n      \"disk\": 19,\n      \"network\": 74,\n      \"uptime\": 2716688\n    },\n    {\n      \"id\": \"host-168\",\n      \"name\": \"prod-queue-0168\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 4,\n      \"disk\": 49,\n      \"network\": 48,\n      \"uptime\": 6359540\n    },\n    {\n      \"id\": \"host-169\",\n      \"name\": \"prod-web-0169\",\n      \"status\": \"warning\",\n      \"cpu\": 98,\n      \"memory\": 95,\n      \"disk\": 70,\n      \"network\": 94,\n      \"uptime\": 4383800\n    },\n    {\n      \"id\": \"host-170\",\n      \"name\": \"prod-api-0170\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 92,\n      \"disk\": 50,\n      \"network\": 63,\n      \"uptime\": 9729172\n    },\n    {\n      \"id\": \"host-171\",\n      \"name\": \"prod-database-0171\",\n      \"status\": \"warning\",\n      \"cpu\": 48,\n      \"memory\": 47,\n      \"disk\": 24,\n      \"network\": 82,\n      \"uptime\": 4536148\n    },\n    {\n      \"id\": \"host-172\",\n      \"name\": \"prod-cache-0172\",\n      \"status\": \"warning\",\n      \"cpu\": 66,\n      \"memory\": 97,\n      \"disk\": 53,\n      \"network\": 18,\n      \"uptime\": 1235524\n    },\n    {\n      \"id\": \"host-173\",\n      \"name\": \"prod-worker-0173\",\n      \"status\": \"warning\",\n      \"cpu\": 4,\n      \"memory\": 7,\n      \"disk\": 53,\n      \"network\": 99,\n      \"uptime\": 8357444\n    },\n    {\n      \"id\": \"host-174\",\n      \"name\": \"prod-queue-0174\",\n      \"status\": \"warning\",\n      \"cpu\": 98,\n      \"memory\": 13,\n      \"disk\": 89,\n      \"network\": 13,\n      \"uptime\": 6012482\n    },\n    {\n      \"id\": \"host-175\",\n      \"name\": \"prod-web-0175\",\n      \"status\": \"warning\",\n      \"cpu\": 33,\n      \"memory\": 97,\n      \"disk\": 95,\n      \"network\": 66,\n      \"uptime\": 6519391\n    },\n    {\n      \"id\": \"host-176\",\n      \"name\": \"prod-api-0176\",\n      \"status\": \"warning\",\n      \"cpu\": 21,\n      \"memory\": 4,\n      \"disk\": 25,\n      \"network\": 96,\n      \"uptime\": 5424842\n    },\n    {\n      \"id\": \"host-177\",\n      \"name\": \"prod-database-0177\",\n      \"status\": \"warning\",\n      \"cpu\": 4,\n      \"memory\": 12,\n      \"disk\": 0,\n      \"network\": 25,\n      \"uptime\": 5032611\n    },\n    {\n      \"id\": \"host-178\",\n      \"name\": \"prod-cache-0178\",\n      \"status\": \"warning\",\n      \"cpu\": 46,\n      \"memory\": 15,\n      \"disk\": 46,\n      \"network\": 95,\n      \"uptime\": 846420\n    },\n    {\n      \"id\": \"host-179\",\n      \"name\": \"prod-worker-0179\",\n      \"status\": \"warning\",\n      \"cpu\": 3,\n      \"memory\": 23,\n      \"disk\": 3,\n      \"network\": 14,\n      \"uptime\": 3020980\n    },\n    {\n      \"id\": \"host-180\",\n      \"name\": \"prod-queue-0180\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 62,\n      \"disk\": 43,\n      \"network\": 69,\n      \"uptime\": 1083318\n    },\n    {\n      \"id\": \"host-181\",\n      \"name\": \"prod-web-0181\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 9,\n      \"disk\": 38,\n      \"network\": 23,\n      \"uptime\": 2281982\n    },\n    {\n      \"id\": \"host-182\",\n      \"name\": \"prod-api-0182\",\n      \"status\": \"warning\",\n      \"cpu\": 60,\n      \"memory\": 92,\n      \"disk\": 45,\n      \"network\": 61,\n      \"uptime\": 3916817\n    },\n    {\n      \"id\": \"host-183\",\n      \"name\": \"prod-database-0183\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 45,\n      \"disk\": 29,\n      \"network\": 23,\n      \"uptime\": 6645322\n    },\n    {\n      \"id\": \"host-184\",\n      \"name\": \"prod-cache-0184\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 43,\n      \"disk\": 9,\n      \"network\": 87,\n      \"uptime\": 3468058\n    },\n    {\n      \"id\": \"host-185\",\n      \"name\": \"prod-worker-0185\",\n      \"status\": \"warning\",\n      \"cpu\": 93,\n      \"memory\": 28,\n      \"disk\": 14,\n      \"network\": 43,\n      \"uptime\": 4187481\n    },\n    {\n      \"id\": \"host-186\",\n      \"name\": \"prod-queue-0186\",\n      \"status\": \"critical\",\n      \"cpu\": 82,\n      \"memory\": 31,\n      \"disk\": 47,\n      \"network\": 100,\n      \"uptime\": 9918326\n    },\n    {\n      \"id\": \"host-187\",\n      \"name\": \"prod-web-0187\",\n      \"status\": \"critical\",\n      \"cpu\": 75,\n      \"memory\": 54,\n      \"disk\": 64,\n      \"network\": 49,\n      \"uptime\": 1697643\n    },\n    {\n      \"id\": \"host-188\",\n      \"name\": \"prod-api-0188\",\n      \"status\": \"critical\",\n      \"cpu\": 100,\n      \"memory\": 84,\n      \"disk\": 47,\n      \"network\": 73,\n      \"uptime\": 2234969\n    },\n    {\n      \"id\": \"host-189\",\n      \"name\": \"prod-database-0189\",\n      \"status\": \"critical\",\n      \"cpu\": 28,\n      \"memory\": 61,\n      \"disk\": 18,\n      \"network\": 90,\n      \"uptime\": 4326656\n    },\n    {\n      \"id\": \"host-190\",\n      \"name\": \"prod-cache-0190\",\n      \"status\": \"critical\",\n      \"cpu\": 19,\n      \"memory\": 88,\n      \"disk\": 20,\n      \"network\": 15,\n      \"uptime\": 141704\n    },\n    {\n      \"id\": \"host-191\",\n      \"name\": \"prod-worker-0191\",\n      \"status\": \"critical\",\n      \"cpu\": 13,\n      \"memory\": 59,\n      \"disk\": 62,\n      \"network\": 35,\n      \"uptime\": 5337192\n    },\n    {\n      \"id\": \"host-192\",\n      \"name\": \"prod-queue-0192\",\n      \"status\": \"critical\",\n      \"cpu\": 60,\n      \"memory\": 74,\n      \"disk\": 98,\n      \"network\": 54,\n      \"uptime\": 5974494\n    },\n    {\n      \"id\": \"host-193\",\n      \"name\": \"prod-web-0193\",\n      \"status\": \"critical\",\n      \"cpu\": 100,\n      \"memory\": 45,\n      \"disk\": 13,\n      \"network\": 49,\n      \"uptime\": 137374\n    },\n    {\n      \"id\": \"host-194\",\n      \"name\": \"prod-api-0194\",\n      \"status\": \"critical\",\n      \"cpu\": 83,\n      \"memory\": 43,\n      \"disk\": 48,\n      \"network\": 38,\n      \"uptime\": 6996240\n    },\n    {\n      \"id\": \"host-195\",\n      \"name\": \"prod-database-0195\",\n      \"status\": \"critical\",\n      \"cpu\": 74,\n      \"memory\": 95,\n      \"disk\": 55,\n      \"network\": 6,\n      \"uptime\": 6181658\n    },\n    {\n      \"id\": \"host-196\",\n      \"name\": \"prod-cache-0196\",\n      \"status\": \"critical\",\n      \"cpu\": 71,\n      \"memory\": 43,\n      \"disk\": 97,\n      \"network\": 57,\n      \"uptime\": 9810723\n    },\n    {\n      \"id\": \"host-197\",\n      \"name\": \"prod-worker-0197\",\n      \"status\": \"critical\",\n      \"cpu\": 28,\n      \"memory\": 65,\n      \"disk\": 82,\n      \"network\": 40,\n      \"uptime\": 4193574\n    },\n    {\n      \"id\": \"host-198\",\n      \"name\": \"prod-queue-0198\",\n      \"status\": \"critical\",\n      \"cpu\": 88,\n      \"memory\": 72,\n      \"disk\": 93,\n      \"network\": 30,\n      \"uptime\": 1964834\n    },\n    {\n      \"id\": \"host-199\",\n      \"name\": \"prod-web-0199\",\n      \"status\": \"critical\",\n      \"cpu\": 6,\n      \"memory\": 97,\n      \"disk\": 15,\n      \"network\": 99,\n      \"uptime\": 4275826\n    },\n    {\n      \"id\": \"host-200\",\n      \"name\": \"prod-api-0200\",\n      \"status\": \"critical\",\n      \"cpu\": 70,\n      \"memory\": 59,\n      \"disk\": 57,\n      \"network\": 58,\n      \"uptime\": 3119993\n    },\n    {\n      \"id\": \"host-201\",\n      \"name\": \"prod-database-0201\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 74,\n      \"disk\": 66,\n      \"network\": 17,\n      \"uptime\": 6734726\n    },\n    {\n      \"id\": \"host-202\",\n      \"name\": \"prod-cache-0202\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 53,\n      \"disk\": 23,\n      \"network\": 96,\n      \"uptime\": 8537999\n    },\n    {\n      \"id\": \"host-203\",\n      \"name\": \"prod-worker-0203\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 79,\n      \"disk\": 62,\n      \"network\": 52,\n      \"uptime\": 2850607\n    },\n    {\n      \"id\": \"host-204\",\n      \"name\": \"prod-queue-0204\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 92,\n      \"disk\": 11,\n      \"network\": 90,\n      \"uptime\": 2742283\n    },\n    {\n      \"id\": \"host-205\",\n      \"name\": \"prod-web-0205\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 93,\n      \"disk\": 89,\n      \"network\": 43,\n      \"uptime\": 7697137\n    },\n    {\n      \"id\": \"host-206\",\n      \"name\": \"prod-api-0206\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 11,\n      \"disk\": 15,\n      \"network\": 31,\n      \"uptime\": 5240788\n    },\n    {\n      \"id\": \"host-207\",\n      \"name\": \"prod-database-0207\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 57,\n      \"disk\": 38,\n      \"network\": 68,\n      \"uptime\": 1786872\n    },\n    {\n      \"id\": \"host-208\",\n      \"name\": \"prod-cache-0208\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 14,\n      \"disk\": 69,\n      \"network\": 91,\n      \"uptime\": 4097652\n    },\n    {\n      \"id\": \"host-209\",\n      \"name\": \"prod-worker-0209\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 6,\n      \"disk\": 9,\n      \"network\": 60,\n      \"uptime\": 8090371\n    },\n    {\n      \"id\": \"host-210\",\n      \"name\": \"prod-queue-0210\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 32,\n      \"disk\": 49,\n      \"network\": 32,\n      \"uptime\": 6821515\n    },\n    {\n      \"id\": \"host-211\",\n      \"name\": \"prod-web-0211\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 0,\n      \"disk\": 38,\n      \"network\": 85,\n      \"uptime\": 8891183\n    },\n    {\n      \"id\": \"host-212\",\n      \"name\": \"prod-api-0212\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 91,\n      \"disk\": 94,\n      \"network\": 86,\n      \"uptime\": 1427768\n    },\n    {\n      \"id\": \"host-213\",\n      \"name\": \"prod-database-0213\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 68,\n      \"disk\": 67,\n      \"network\": 26,\n      \"uptime\": 200478\n    },\n    {\n      \"id\": \"host-214\",\n      \"name\": \"prod-cache-0214\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 51,\n      \"disk\": 15,\n      \"network\": 45,\n      \"uptime\": 2692703\n    },\n    {\n      \"id\": \"host-215\",\n      \"name\": \"prod-worker-0215\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 58,\n      \"disk\": 27,\n      \"network\": 74,\n      \"uptime\": 9795475\n    },\n    {\n      \"id\": \"host-216\",\n      \"name\": \"prod-queue-0216\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 18,\n      \"disk\": 15,\n      \"network\": 64,\n      \"uptime\": 6193562\n    },\n    {\n      \"id\": \"host-217\",\n      \"name\": \"prod-web-0217\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 36,\n      \"disk\": 28,\n      \"network\": 2,\n      \"uptime\": 9641779\n    },\n    {\n      \"id\": \"host-218\",\n      \"name\": \"prod-api-0218\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 67,\n      \"disk\": 66,\n      \"network\": 23,\n      \"uptime\": 5471414\n    },\n    {\n      \"id\": \"host-219\",\n      \"name\": \"prod-database-0219\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 17,\n      \"disk\": 8,\n      \"network\": 0,\n      \"uptime\": 6163892\n    },\n    {\n      \"id\": \"host-220\",\n      \"name\": \"prod-cache-0220\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 59,\n      \"disk\": 90,\n      \"network\": 64,\n      \"uptime\": 8802331\n    },\n    {\n      \"id\": \"host-221\",\n      \"name\": \"prod-worker-0221\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 5,\n      \"disk\": 51,\n      \"network\": 53,\n      \"uptime\": 9152828\n    },\n    {\n      \"id\": \"host-222\",\n      \"name\": \"prod-queue-0222\",\n      \"status\": \"healthy\",\n      \"cpu\": 25,\n      \"memory\": 45,\n      \"disk\": 41,\n      \"network\": 11,\n      \"uptime\": 3869833\n    },\n    {\n      \"id\": \"host-223\",\n      \"name\": \"prod-web-0223\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 30,\n      \"disk\": 99,\n      \"network\": 73,\n      \"uptime\": 6709590\n    },\n    {\n      \"id\": \"host-224\",\n      \"name\": \"prod-api-0224\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 63,\n      \"disk\": 79,\n      \"network\": 5,\n      \"uptime\": 7492311\n    },\n    {\n      \"id\": \"host-225\",\n      \"name\": \"prod-database-0225\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 45,\n      \"disk\": 64,\n      \"network\": 46,\n      \"uptime\": 4836029\n    },\n    {\n      \"id\": \"host-226\",\n      \"name\": \"prod-cache-0226\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 91,\n      \"disk\": 5,\n      \"network\": 17,\n      \"uptime\": 8826485\n    },\n    {\n      \"id\": \"host-227\",\n      \"name\": \"prod-worker-0227\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 46,\n      \"disk\": 64,\n      \"network\": 84,\n      \"uptime\": 2456591\n    },\n    {\n      \"id\": \"host-228\",\n      \"name\": \"prod-queue-0228\",\n      \"status\": \"healthy\",\n      \"cpu\": 3,\n      \"memory\": 91,\n      \"disk\": 53,\n      \"network\": 90,\n      \"uptime\": 3505804\n    },\n    {\n      \"id\": \"host-229\",\n      \"name\": \"prod-web-0229\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 44,\n      \"disk\": 0,\n      \"network\": 4,\n      \"uptime\": 6783289\n    },\n    {\n      \"id\": \"host-230\",\n      \"name\": \"prod-api-0230\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 82,\n      \"disk\": 73,\n      \"network\": 14,\n      \"uptime\": 5558502\n    },\n    {\n      \"id\": \"host-231\",\n      \"name\": \"prod-database-0231\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 50,\n      \"disk\": 39,\n      \"network\": 55,\n      \"uptime\": 3211501\n    },\n    {\n      \"id\": \"host-232\",\n      \"name\": \"prod-cache-0232\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 42,\n      \"disk\": 69,\n      \"network\": 99,\n      \"uptime\": 4320046\n    },\n    {\n      \"id\": \"host-233\",\n      \"name\": \"prod-worker-0233\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 79,\n      \"disk\": 91,\n      \"network\": 25,\n      \"uptime\": 1445556\n    },\n    {\n      \"id\": \"host-234\",\n      \"name\": \"prod-queue-0234\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 10,\n      \"disk\": 6,\n      \"network\": 100,\n      \"uptime\": 1888719\n    },\n    {\n      \"id\": \"host-235\",\n      \"name\": \"prod-web-0235\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 74,\n      \"disk\": 94,\n      \"network\": 60,\n      \"uptime\": 3499887\n    },\n    {\n      \"id\": \"host-236\",\n      \"name\": \"prod-api-0236\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 46,\n      \"disk\": 20,\n      \"network\": 53,\n      \"uptime\": 429289\n    },\n    {\n      \"id\": \"host-237\",\n      \"name\": \"prod-database-0237\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 68,\n      \"disk\": 65,\n      \"network\": 64,\n      \"uptime\": 9301342\n    },\n    {\n      \"id\": \"host-238\",\n      \"name\": \"prod-cache-0238\",\n      \"status\": \"healthy\",\n      \"cpu\": 57,\n      \"memory\": 56,\n      \"disk\": 91,\n      \"network\": 21,\n      \"uptime\": 9511938\n    },\n    {\n      \"id\": \"host-239\",\n      \"name\": \"prod-worker-0239\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 23,\n      \"disk\": 18,\n      \"network\": 17,\n      \"uptime\": 6923410\n    },\n    {\n      \"id\": \"host-240\",\n      \"name\": \"prod-queue-0240\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 99,\n      \"disk\": 32,\n      \"network\": 68,\n      \"uptime\": 9477357\n    },\n    {\n      \"id\": \"host-241\",\n      \"name\": \"prod-web-0241\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 44,\n      \"disk\": 23,\n      \"network\": 78,\n      \"uptime\": 6702343\n    },\n    {\n      \"id\": \"host-242\",\n      \"name\": \"prod-api-0242\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 67,\n      \"disk\": 83,\n      \"network\": 26,\n      \"uptime\": 477541\n    },\n    {\n      \"id\": \"host-243\",\n      \"name\": \"prod-database-0243\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 89,\n      \"disk\": 73,\n      \"network\": 22,\n      \"uptime\": 8853075\n    },\n    {\n      \"id\": \"host-244\",\n      \"name\": \"prod-cache-0244\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 32,\n      \"disk\": 83,\n      \"network\": 65,\n      \"uptime\": 3633039\n    },\n    {\n      \"id\": \"host-245\",\n      \"name\": \"prod-worker-0245\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 64,\n      \"disk\": 89,\n      \"network\": 88,\n      \"uptime\": 8671358\n    },\n    {\n      \"id\": \"host-246\",\n      \"name\": \"prod-queue-0246\",\n      \"status\": \"healthy\",\n      \"cpu\": 13,\n      \"memory\": 11,\n      \"disk\": 95,\n      \"network\": 53,\n      \"uptime\": 6538756\n    },\n    {\n      \"id\": \"host-247\",\n      \"name\": \"prod-web-0247\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 94,\n      \"disk\": 50,\n      \"network\": 93,\n      \"uptime\": 5877096\n    },\n    {\n      \"id\": \"host-248\",\n      \"name\": \"prod-api-0248\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 4,\n      \"disk\": 78,\n      \"network\": 98,\n      \"uptime\": 1400849\n    },\n    {\n      \"id\": \"host-249\",\n      \"name\": \"prod-database-0249\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 22,\n      \"disk\": 13,\n      \"network\": 9,\n      \"uptime\": 5552752\n    },\n    {\n      \"id\": \"host-250\",\n      \"name\": \"prod-cache-0250\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 73,\n      \"disk\": 77,\n      \"network\": 41,\n      \"uptime\": 4989757\n    },\n    {\n      \"id\": \"host-251\",\n      \"name\": \"prod-worker-0251\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 61,\n      \"disk\": 74,\n      \"network\": 81,\n      \"uptime\": 7928595\n    },\n    {\n      \"id\": \"host-252\",\n      \"name\": \"prod-queue-0252\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 22,\n      \"disk\": 80,\n      \"network\": 80,\n      \"uptime\": 4017550\n    },\n    {\n      \"id\": \"host-253\",\n      \"name\": \"prod-web-0253\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 43,\n      \"disk\": 13,\n      \"network\": 24,\n      \"uptime\": 2043136\n    },\n    {\n      \"id\": \"host-254\",\n      \"name\": \"prod-api-0254\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 39,\n      \"disk\": 69,\n      \"network\": 32,\n      \"uptime\": 7028263\n    },\n    {\n      \"id\": \"host-255\",\n      \"name\": \"prod-database-0255\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 61,\n      \"disk\": 64,\n      \"network\": 53,\n      \"uptime\": 2009893\n    },\n    {\n      \"id\": \"host-256\",\n      \"name\": \"prod-cache-0256\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 43,\n      \"disk\": 77,\n      \"network\": 37,\n      \"uptime\": 4074990\n    },\n    {\n      \"id\": \"host-257\",\n      \"name\": \"prod-worker-0257\",\n      \"status\": \"healthy\",\n      \"cpu\": 74,\n      \"memory\": 78,\n      \"disk\": 44,\n      \"network\": 95,\n      \"uptime\": 2466933\n    },\n    {\n      \"id\": \"host-258\",\n      \"name\": \"prod-queue-0258\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 65,\n      \"disk\": 73,\n      \"network\": 30,\n      \"uptime\": 1892303\n    },\n    {\n      \"id\": \"host-259\",\n      \"name\": \"prod-web-0259\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 6,\n      \"disk\": 55,\n      \"network\": 36,\n      \"uptime\": 9226151\n    },\n    {\n      \"id\": \"host-260\",\n      \"name\": \"prod-api-0260\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 47,\n      \"disk\": 52,\n      \"network\": 48,\n      \"uptime\": 209583\n    },\n    {\n      \"id\": \"host-261\",\n      \"name\": \"prod-database-0261\",\n      \"status\": \"warning\",\n      \"cpu\": 98,\n      \"memory\": 52,\n      \"disk\": 13,\n      \"network\": 5,\n      \"uptime\": 8807143\n    },\n    {\n      \"id\": \"host-262\",\n      \"name\": \"prod-cache-0262\",\n      \"status\": \"warning\",\n      \"cpu\": 75,\n      \"memory\": 73,\n      \"disk\": 84,\n      \"network\": 37,\n      \"uptime\": 3469489\n    },\n    {\n      \"id\": \"host-263\",\n      \"name\": \"prod-worker-0263\",\n      \"status\": \"warning\",\n      \"cpu\": 47,\n      \"memory\": 56,\n      \"disk\": 89,\n      \"network\": 32,\n      \"uptime\": 3895191\n    },\n    {\n      \"id\": \"host-264\",\n      \"name\": \"prod-queue-0264\",\n      \"status\": \"warning\",\n      \"cpu\": 79,\n      \"memory\": 19,\n      \"disk\": 26,\n      \"network\": 58,\n      \"uptime\": 8264556\n    },\n    {\n      \"id\": \"host-265\",\n      \"name\": \"prod-web-0265\",\n      \"status\": \"warning\",\n      \"cpu\": 14,\n      \"memory\": 33,\n      \"disk\": 23,\n      \"network\": 75,\n      \"uptime\": 7087476\n    },\n    {\n      \"id\": \"host-266\",\n      \"name\": \"prod-api-0266\",\n      \"status\": \"warning\",\n      \"cpu\": 25,\n      \"memory\": 72,\n      \"disk\": 56,\n      \"network\": 37,\n      \"uptime\": 8804789\n    },\n    {\n      \"id\": \"host-267\",\n      \"name\": \"prod-database-0267\",\n      \"status\": \"warning\",\n      \"cpu\": 60,\n      \"memory\": 5,\n      \"disk\": 33,\n      \"network\": 55,\n      \"uptime\": 5104054\n    },\n    {\n      \"id\": \"host-268\",\n      \"name\": \"prod-cache-0268\",\n      \"status\": \"warning\",\n      \"cpu\": 79,\n      \"memory\": 51,\n      \"disk\": 96,\n      \"network\": 43,\n      \"uptime\": 4458941\n    },\n    {\n      \"id\": \"host-269\",\n      \"name\": \"prod-worker-0269\",\n      \"status\": \"warning\",\n      \"cpu\": 59,\n      \"memory\": 68,\n      \"disk\": 31,\n      \"network\": 10,\n      \"uptime\": 1931340\n    },\n    {\n      \"id\": \"host-270\",\n      \"name\": \"prod-queue-0270\",\n      \"status\": \"warning\",\n      \"cpu\": 100,\n      \"memory\": 30,\n      \"disk\": 34,\n      \"network\": 19,\n      \"uptime\": 2069885\n    },\n    {\n      \"id\": \"host-271\",\n      \"name\": \"prod-web-0271\",\n      \"status\": \"warning\",\n      \"cpu\": 60,\n      \"memory\": 43,\n      \"disk\": 25,\n      \"network\": 72,\n      \"uptime\": 1503249\n    },\n    {\n      \"id\": \"host-272\",\n      \"name\": \"prod-api-0272\",\n      \"status\": \"warning\",\n      \"cpu\": 26,\n      \"memory\": 31,\n      \"disk\": 81,\n      \"network\": 10,\n      \"uptime\": 3200026\n    },\n    {\n      \"id\": \"host-273\",\n      \"name\": \"prod-database-0273\",\n      \"status\": \"warning\",\n      \"cpu\": 35,\n      \"memory\": 64,\n      \"disk\": 32,\n      \"network\": 100,\n      \"uptime\": 8094738\n    },\n    {\n      \"id\": \"host-274\",\n      \"name\": \"prod-cache-0274\",\n      \"status\": \"warning\",\n      \"cpu\": 59,\n      \"memory\": 22,\n      \"disk\": 61,\n      \"network\": 38,\n      \"uptime\": 5377255\n    },\n    {\n      \"id\": \"host-275\",\n      \"name\": \"prod-worker-0275\",\n      \"status\": \"warning\",\n      \"cpu\": 92,\n      \"memory\": 22,\n      \"disk\": 59,\n      \"network\": 17,\n      \"uptime\": 3103627\n    },\n    {\n      \"id\": \"host-276\",\n      \"name\": \"prod-queue-0276\",\n      \"status\": \"warning\",\n      \"cpu\": 94,\n      \"memory\": 41,\n      \"disk\": 63,\n      \"network\": 23,\n      \"uptime\": 3297214\n    },\n    {\n      \"id\": \"host-277\",\n      \"name\": \"prod-web-0277\",\n      \"status\": \"warning\",\n      \"cpu\": 97,\n      \"memory\": 94,\n      \"disk\": 74,\n      \"network\": 79,\n      \"uptime\": 8629793\n    },\n    {\n      \"id\": \"host-278\",\n      \"name\": \"prod-api-0278\",\n      \"status\": \"warning\",\n      \"cpu\": 52,\n      \"memory\": 24,\n      \"disk\": 72,\n      \"network\": 66,\n      \"uptime\": 3574677\n    },\n    {\n      \"id\": \"host-279\",\n      \"name\": \"prod-database-0279\",\n      \"status\": \"warning\",\n      \"cpu\": 3,\n      \"memory\": 43,\n      \"disk\": 8,\n      \"network\": 69,\n      \"uptime\": 8581261\n    },\n    {\n      \"id\": \"host-280\",\n      \"name\": \"prod-cache-0280\",\n      \"status\": \"warning\",\n      \"cpu\": 61,\n      \"memory\": 22,\n      \"disk\": 74,\n      \"network\": 49,\n      \"uptime\": 2646908\n    },\n    {\n      \"id\": \"host-281\",\n      \"name\": \"prod-worker-0281\",\n      \"status\": \"warning\",\n      \"cpu\": 39,\n      \"memory\": 65,\n      \"disk\": 57,\n      \"network\": 17,\n      \"uptime\": 6891955\n    },\n    {\n      \"id\": \"host-282\",\n      \"name\": \"prod-queue-0282\",\n      \"status\": \"warning\",\n      \"cpu\": 21,\n      \"memory\": 91,\n      \"disk\": 89,\n      \"network\": 38,\n      \"uptime\": 150609\n    },\n    {\n      \"id\": \"host-283\",\n      \"name\": \"prod-web-0283\",\n      \"status\": \"warning\",\n      \"cpu\": 42,\n      \"memory\": 34,\n      \"disk\": 44,\n      \"network\": 50,\n      \"uptime\": 8456025\n    },\n    {\n      \"id\": \"host-284\",\n      \"name\": \"prod-api-0284\",\n      \"status\": \"warning\",\n      \"cpu\": 9,\n      \"memory\": 27,\n      \"disk\": 39,\n      \"network\": 96,\n      \"uptime\": 7725559\n    },\n    {\n      \"id\": \"host-285\",\n      \"name\": \"prod-database-0285\",\n      \"status\": \"warning\",\n      \"cpu\": 45,\n      \"memory\": 88,\n      \"disk\": 92,\n      \"network\": 16,\n      \"uptime\": 1940191\n    },\n    {\n      \"id\": \"host-286\",\n      \"name\": \"prod-cache-0286\",\n      \"status\": \"critical\",\n      \"cpu\": 28,\n      \"memory\": 51,\n      \"disk\": 36,\n      \"network\": 76,\n      \"uptime\": 7092936\n    },\n    {\n      \"id\": \"host-287\",\n      \"name\": \"prod-worker-0287\",\n      \"status\": \"critical\",\n      \"cpu\": 44,\n      \"memory\": 87,\n      \"disk\": 58,\n      \"network\": 69,\n      \"uptime\": 283548\n    },\n    {\n      \"id\": \"host-288\",\n      \"name\": \"prod-queue-0288\",\n      \"status\": \"critical\",\n      \"cpu\": 93,\n      \"memory\": 43,\n      \"disk\": 85,\n      \"network\": 70,\n      \"uptime\": 8595456\n    },\n    {\n      \"id\": \"host-289\",\n      \"name\": \"prod-web-0289\",\n      \"status\": \"critical\",\n      \"cpu\": 46,\n      \"memory\": 61,\n      \"disk\": 83,\n      \"network\": 86,\n      \"uptime\": 9623391\n    },\n    {\n      \"id\": \"host-290\",\n      \"name\": \"prod-api-0290\",\n      \"status\": \"critical\",\n      \"cpu\": 22,\n      \"memory\": 71,\n      \"disk\": 48,\n      \"network\": 68,\n      \"uptime\": 177484\n    },\n    {\n      \"id\": \"host-291\",\n      \"name\": \"prod-database-0291\",\n      \"status\": \"critical\",\n      \"cpu\": 98,\n      \"memory\": 72,\n      \"disk\": 33,\n      \"network\": 46,\n      \"uptime\": 488196\n    },\n    {\n      \"id\": \"host-292\",\n      \"name\": \"prod-cache-0292\",\n      \"status\": \"critical\",\n      \"cpu\": 51,\n      \"memory\": 60,\n      \"disk\": 18,\n      \"network\": 52,\n      \"uptime\": 4030394\n    },\n    {\n      \"id\": \"host-293\",\n      \"name\": \"prod-worker-0293\",\n      \"status\": \"critical\",\n      \"cpu\": 44,\n      \"memory\": 59,\n      \"disk\": 21,\n      \"network\": 33,\n      \"uptime\": 5546638\n    },\n    {\n      \"id\": \"host-294\",\n      \"name\": \"prod-queue-0294\",\n      \"status\": \"critical\",\n      \"cpu\": 3,\n      \"memory\": 74,\n      \"disk\": 28,\n      \"network\": 76,\n      \"uptime\": 5910979\n    },\n    {\n      \"id\": \"host-295\",\n      \"name\": \"prod-web-0295\",\n      \"status\": \"critical\",\n      \"cpu\": 97,\n      \"memory\": 24,\n      \"disk\": 19,\n      \"network\": 73,\n      \"uptime\": 3867086\n    },\n    {\n      \"id\": \"host-296\",\n      \"name\": \"prod-api-0296\",\n      \"status\": \"critical\",\n      \"cpu\": 51,\n      \"memory\": 94,\n      \"disk\": 52,\n      \"network\": 40,\n      \"uptime\": 2766454\n    },\n    {\n      \"id\": \"host-297\",\n      \"name\": \"prod-database-0297\",\n      \"status\": \"critical\",\n      \"cpu\": 91,\n      \"memory\": 50,\n      \"disk\": 61,\n      \"network\": 68,\n      \"uptime\": 7406077\n    },\n    {\n      \"id\": \"host-298\",\n      \"name\": \"prod-cache-0298\",\n      \"status\": \"critical\",\n      \"cpu\": 61,\n      \"memory\": 2,\n      \"disk\": 48,\n      \"network\": 26,\n      \"uptime\": 7785988\n    },\n    {\n      \"id\": \"host-299\",\n      \"name\": \"prod-worker-0299\",\n      \"status\": \"critical\",\n      \"cpu\": 96,\n      \"memory\": 31,\n      \"disk\": 78,\n      \"network\": 32,\n      \"uptime\": 3517333\n    },\n    {\n      \"id\": \"host-300\",\n      \"name\": \"prod-queue-0300\",\n      \"status\": \"critical\",\n      \"cpu\": 12,\n      \"memory\": 93,\n      \"disk\": 29,\n      \"network\": 20,\n      \"uptime\": 597996\n    },\n    {\n      \"id\": \"host-301\",\n      \"name\": \"prod-web-0301\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 19,\n      \"disk\": 39,\n      \"network\": 91,\n      \"uptime\": 9396455\n    },\n    {\n      \"id\": \"host-302\",\n      \"name\": \"prod-api-0302\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 10,\n      \"disk\": 66,\n      \"network\": 66,\n      \"uptime\": 1894477\n    },\n    {\n      \"id\": \"host-303\",\n      \"name\": \"prod-database-0303\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 14,\n      \"disk\": 88,\n      \"network\": 77,\n      \"uptime\": 7739975\n    },\n    {\n      \"id\": \"host-304\",\n      \"name\": \"prod-cache-0304\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 52,\n      \"disk\": 49,\n      \"network\": 93,\n      \"uptime\": 3556464\n    },\n    {\n      \"id\": \"host-305\",\n      \"name\": \"prod-worker-0305\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 60,\n      \"disk\": 47,\n      \"network\": 58,\n      \"uptime\": 1493479\n    },\n    {\n      \"id\": \"host-306\",\n      \"name\": \"prod-queue-0306\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 44,\n      \"disk\": 67,\n      \"network\": 63,\n      \"uptime\": 1626121\n    },\n    {\n      \"id\": \"host-307\",\n      \"name\": \"prod-web-0307\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 23,\n      \"disk\": 56,\n      \"network\": 79,\n      \"uptime\": 4251220\n    },\n    {\n      \"id\": \"host-308\",\n      \"name\": \"prod-api-0308\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 91,\n      \"disk\": 64,\n      \"network\": 4,\n      \"uptime\": 909928\n    },\n    {\n      \"id\": \"host-309\",\n      \"name\": \"prod-database-0309\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 69,\n      \"disk\": 24,\n      \"network\": 7,\n      \"uptime\": 1619973\n    },\n    {\n      \"id\": \"host-310\",\n      \"name\": \"prod-cache-0310\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 14,\n      \"disk\": 59,\n      \"network\": 2,\n      \"uptime\": 3256249\n    },\n    {\n      \"id\": \"host-311\",\n      \"name\": \"prod-worker-0311\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 70,\n      \"disk\": 9,\n      \"network\": 69,\n      \"uptime\": 6529350\n    },\n    {\n      \"id\": \"host-312\",\n      \"name\": \"prod-queue-0312\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 41,\n      \"disk\": 51,\n      \"network\": 40,\n      \"uptime\": 6083100\n    },\n    {\n      \"id\": \"host-313\",\n      \"name\": \"prod-web-0313\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 89,\n      \"disk\": 4,\n      \"network\": 8,\n      \"uptime\": 4915319\n    },\n    {\n      \"id\": \"host-314\",\n      \"name\": \"prod-api-0314\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 22,\n      \"disk\": 0,\n      \"network\": 94,\n      \"uptime\": 3668404\n    },\n    {\n      \"id\": \"host-315\",\n      \"name\": \"prod-database-0315\",\n      \"status\": \"healthy\",\n      \"cpu\": 3,\n      \"memory\": 22,\n      \"disk\": 28,\n      \"network\": 95,\n      \"uptime\": 9785086\n    },\n    {\n      \"id\": \"host-316\",\n      \"name\": \"prod-cache-0316\",\n      \"status\": \"healthy\",\n      \"cpu\": 72,\n      \"memory\": 46,\n      \"disk\": 45,\n      \"network\": 39,\n      \"uptime\": 561314\n    },\n    {\n      \"id\": \"host-317\",\n      \"name\": \"prod-worker-0317\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 94,\n      \"disk\": 94,\n      \"network\": 92,\n      \"uptime\": 8715405\n    },\n    {\n      \"id\": \"host-318\",\n      \"name\": \"prod-queue-0318\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 91,\n      \"disk\": 57,\n      \"network\": 56,\n      \"uptime\": 7077179\n    },\n    {\n      \"id\": \"host-319\",\n      \"name\": \"prod-web-0319\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 51,\n      \"disk\": 33,\n      \"network\": 36,\n      \"uptime\": 2343804\n    },\n    {\n      \"id\": \"host-320\",\n      \"name\": \"prod-api-0320\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 100,\n      \"disk\": 97,\n      \"network\": 0,\n      \"uptime\": 7119598\n    },\n    {\n      \"id\": \"host-321\",\n      \"name\": \"prod-database-0321\",\n      \"status\": \"healthy\",\n      \"cpu\": 37,\n      \"memory\": 79,\n      \"disk\": 98,\n      \"network\": 34,\n      \"uptime\": 4009801\n    },\n    {\n      \"id\": \"host-322\",\n      \"name\": \"prod-cache-0322\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 36,\n      \"disk\": 57,\n      \"network\": 64,\n      \"uptime\": 8757972\n    },\n    {\n      \"id\": \"host-323\",\n      \"name\": \"prod-worker-0323\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 0,\n      \"disk\": 56,\n      \"network\": 38,\n      \"uptime\": 3601655\n    },\n    {\n      \"id\": \"host-324\",\n      \"name\": \"prod-queue-0324\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 9,\n      \"disk\": 48,\n      \"network\": 99,\n      \"uptime\": 1694146\n    },\n    {\n      \"id\": \"host-325\",\n      \"name\": \"prod-web-0325\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 30,\n      \"disk\": 68,\n      \"network\": 22,\n      \"uptime\": 893089\n    },\n    {\n      \"id\": \"host-326\",\n      \"name\": \"prod-api-0326\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 92,\n      \"disk\": 4,\n      \"network\": 89,\n      \"uptime\": 862889\n    },\n    {\n      \"id\": \"host-327\",\n      \"name\": \"prod-database-0327\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 17,\n      \"disk\": 47,\n      \"network\": 65,\n      \"uptime\": 9811534\n    },\n    {\n      \"id\": \"host-328\",\n      \"name\": \"prod-cache-0328\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 92,\n      \"disk\": 75,\n      \"network\": 98,\n      \"uptime\": 3473051\n    },\n    {\n      \"id\": \"host-329\",\n      \"name\": \"prod-worker-0329\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 13,\n      \"disk\": 51,\n      \"network\": 99,\n      \"uptime\": 9902682\n    },\n    {\n      \"id\": \"host-330\",\n      \"name\": \"prod-queue-0330\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 20,\n      \"disk\": 90,\n      \"network\": 58,\n      \"uptime\": 213810\n    },\n    {\n      \"id\": \"host-331\",\n      \"name\": \"prod-web-0331\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 62,\n      \"disk\": 7,\n      \"network\": 67,\n      \"uptime\": 3117351\n    },\n    {\n      \"id\": \"host-332\",\n      \"name\": \"prod-api-0332\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 27,\n      \"disk\": 29,\n      \"network\": 36,\n      \"uptime\": 2135583\n    },\n    {\n      \"id\": \"host-333\",\n      \"name\": \"prod-database-0333\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 13,\n      \"disk\": 86,\n      \"network\": 42,\n      \"uptime\": 5004985\n    },\n    {\n      \"id\": \"host-334\",\n      \"name\": \"prod-cache-0334\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 26,\n      \"disk\": 58,\n      \"network\": 79,\n      \"uptime\": 2679866\n    },\n    {\n      \"id\": \"host-335\",\n      \"name\": \"prod-worker-0335\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 48,\n      \"disk\": 6,\n      \"network\": 93,\n      \"uptime\": 3481334\n    },\n    {\n      \"id\": \"host-336\",\n      \"name\": \"prod-queue-0336\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 81,\n      \"disk\": 75,\n      \"network\": 51,\n      \"uptime\": 1963343\n    },\n    {\n      \"id\": \"host-337\",\n      \"name\": \"prod-web-0337\",\n      \"status\": \"healthy\",\n      \"cpu\": 7,\n      \"memory\": 55,\n      \"disk\": 72,\n      \"network\": 22,\n      \"uptime\": 5341214\n    },\n    {\n      \"id\": \"host-338\",\n      \"name\": \"prod-api-0338\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 89,\n      \"disk\": 49,\n      \"network\": 8,\n      \"uptime\": 3007817\n    },\n    {\n      \"id\": \"host-339\",\n      \"name\": \"prod-database-0339\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 39,\n      \"disk\": 23,\n      \"network\": 64,\n      \"uptime\": 6482690\n    },\n    {\n      \"id\": \"host-340\",\n      \"name\": \"prod-cache-0340\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 25,\n      \"disk\": 5,\n      \"network\": 0,\n      \"uptime\": 8846443\n    },\n    {\n      \"id\": \"host-341\",\n      \"name\": \"prod-worker-0341\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 45,\n      \"disk\": 23,\n      \"network\": 12,\n      \"uptime\": 6628838\n    },\n    {\n      \"id\": \"host-342\",\n      \"name\": \"prod-queue-0342\",\n      \"status\": \"healthy\",\n      \"cpu\": 100,\n      \"memory\": 1,\n      \"disk\": 51,\n      \"network\": 12,\n      \"uptime\": 321385\n    },\n    {\n      \"id\": \"host-343\",\n      \"name\": \"prod-web-0343\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 55,\n      \"disk\": 43,\n      \"network\": 49,\n      \"uptime\": 9934155\n    },\n    {\n      \"id\": \"host-344\",\n      \"name\": \"prod-api-0344\",\n      \"status\": \"healthy\",\n      \"cpu\": 30,\n      \"memory\": 51,\n      \"disk\": 87,\n      \"network\": 22,\n      \"uptime\": 8451769\n    },\n    {\n      \"id\": \"host-345\",\n      \"name\": \"prod-database-0345\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 2,\n      \"disk\": 31,\n      \"network\": 62,\n      \"uptime\": 1290808\n    },\n    {\n      \"id\": \"host-346\",\n      \"name\": \"prod-cache-0346\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 34,\n      \"disk\": 32,\n      \"network\": 67,\n      \"uptime\": 5099249\n    },\n    {\n      \"id\": \"host-347\",\n      \"name\": \"prod-worker-0347\",\n      \"status\": \"healthy\",\n      \"cpu\": 24,\n      \"memory\": 32,\n      \"disk\": 56,\n      \"network\": 53,\n      \"uptime\": 5507201\n    },\n    {\n      \"id\": \"host-348\",\n      \"name\": \"prod-queue-0348\",\n      \"status\": \"healthy\",\n      \"cpu\": 100,\n      \"memory\": 6,\n      \"disk\": 73,\n      \"network\": 0,\n      \"uptime\": 4984939\n    },\n    {\n      \"id\": \"host-349\",\n      \"name\": \"prod-web-0349\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 89,\n      \"disk\": 13,\n      \"network\": 92,\n      \"uptime\": 2614643\n    },\n    {\n      \"id\": \"host-350\",\n      \"name\": \"prod-api-0350\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 61,\n      \"disk\": 61,\n      \"network\": 63,\n      \"uptime\": 759046\n    },\n    {\n      \"id\": \"host-351\",\n      \"name\": \"prod-database-0351\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 69,\n      \"disk\": 60,\n      \"network\": 4,\n      \"uptime\": 2293118\n    },\n    {\n      \"id\": \"host-352\",\n      \"name\": \"prod-cache-0352\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 58,\n      \"disk\": 51,\n      \"network\": 38,\n      \"uptime\": 9424380\n    },\n    {\n      \"id\": \"host-353\",\n      \"name\": \"prod-worker-0353\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 80,\n      \"disk\": 73,\n      \"network\": 47,\n      \"uptime\": 8863539\n    },\n    {\n      \"id\": \"host-354\",\n      \"name\": \"prod-queue-0354\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 63,\n      \"disk\": 64,\n      \"network\": 73,\n      \"uptime\": 8215768\n    },\n    {\n      \"id\": \"host-355\",\n      \"name\": \"prod-web-0355\",\n      \"status\": \"healthy\",\n      \"cpu\": 74,\n      \"memory\": 87,\n      \"disk\": 87,\n      \"network\": 67,\n      \"uptime\": 2690480\n    },\n    {\n      \"id\": \"host-356\",\n      \"name\": \"prod-api-0356\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 75,\n      \"disk\": 51,\n      \"network\": 77,\n      \"uptime\": 9639234\n    },\n    {\n      \"id\": \"host-357\",\n      \"name\": \"prod-database-0357\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 7,\n      \"disk\": 54,\n      \"network\": 18,\n      \"uptime\": 6448690\n    },\n    {\n      \"id\": \"host-358\",\n      \"name\": \"prod-cache-0358\",\n      \"status\": \"healthy\",\n      \"cpu\": 24,\n      \"memory\": 23,\n      \"disk\": 67,\n      \"network\": 71,\n      \"uptime\": 905553\n    },\n    {\n      \"id\": \"host-359\",\n      \"name\": \"prod-worker-0359\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 4,\n      \"disk\": 3,\n      \"network\": 50,\n      \"uptime\": 5379000\n    },\n    {\n      \"id\": \"host-360\",\n      \"name\": \"prod-queue-0360\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 78,\n      \"disk\": 24,\n      \"network\": 57,\n      \"uptime\": 820729\n    },\n    {\n      \"id\": \"host-361\",\n      \"name\": \"prod-web-0361\",\n      \"status\": \"warning\",\n      \"cpu\": 45,\n      \"memory\": 68,\n      \"disk\": 84,\n      \"network\": 41,\n      \"uptime\": 5091310\n    },\n    {\n      \"id\": \"host-362\",\n      \"name\": \"prod-api-0362\",\n      \"status\": \"warning\",\n      \"cpu\": 70,\n      \"memory\": 80,\n      \"disk\": 88,\n      \"network\": 32,\n      \"uptime\": 8839157\n    },\n    {\n      \"id\": \"host-363\",\n      \"name\": \"prod-database-0363\",\n      \"status\": \"warning\",\n      \"cpu\": 5,\n      \"memory\": 54,\n      \"disk\": 49,\n      \"network\": 8,\n      \"uptime\": 5877154\n    },\n    {\n      \"id\": \"host-364\",\n      \"name\": \"prod-cache-0364\",\n      \"status\": \"warning\",\n      \"cpu\": 37,\n      \"memory\": 58,\n      \"disk\": 67,\n      \"network\": 18,\n      \"uptime\": 4638597\n    },\n    {\n      \"id\": \"host-365\",\n      \"name\": \"prod-worker-0365\",\n      \"status\": \"warning\",\n      \"cpu\": 54,\n      \"memory\": 45,\n      \"disk\": 79,\n      \"network\": 40,\n      \"uptime\": 5846502\n    },\n    {\n      \"id\": \"host-366\",\n      \"name\": \"prod-queue-0366\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 54,\n      \"disk\": 17,\n      \"network\": 16,\n      \"uptime\": 5653745\n    },\n    {\n      \"id\": \"host-367\",\n      \"name\": \"prod-web-0367\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 50,\n      \"disk\": 93,\n      \"network\": 14,\n      \"uptime\": 8865937\n    },\n    {\n      \"id\": \"host-368\",\n      \"name\": \"prod-api-0368\",\n      \"status\": \"warning\",\n      \"cpu\": 60,\n      \"memory\": 98,\n      \"disk\": 4,\n      \"network\": 27,\n      \"uptime\": 9281256\n    },\n    {\n      \"id\": \"host-369\",\n      \"name\": \"prod-database-0369\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 16,\n      \"disk\": 52,\n      \"network\": 79,\n      \"uptime\": 1355525\n    },\n    {\n      \"id\": \"host-370\",\n      \"name\": \"prod-cache-0370\",\n      \"status\": \"warning\",\n      \"cpu\": 100,\n      \"memory\": 62,\n      \"disk\": 4,\n      \"network\": 64,\n      \"uptime\": 3828032\n    },\n    {\n      \"id\": \"host-371\",\n      \"name\": \"prod-worker-0371\",\n      \"status\": \"warning\",\n      \"cpu\": 49,\n      \"memory\": 17,\n      \"disk\": 96,\n      \"network\": 75,\n      \"uptime\": 9437195\n    },\n    {\n      \"id\": \"host-372\",\n      \"name\": \"prod-queue-0372\",\n      \"status\": \"warning\",\n      \"cpu\": 11,\n      \"memory\": 69,\n      \"disk\": 14,\n      \"network\": 14,\n      \"uptime\": 7361131\n    },\n    {\n      \"id\": \"host-373\",\n      \"name\": \"prod-web-0373\",\n      \"status\": \"warning\",\n      \"cpu\": 3,\n      \"memory\": 44,\n      \"disk\": 30,\n      \"network\": 26,\n      \"uptime\": 2395974\n    },\n    {\n      \"id\": \"host-374\",\n      \"name\": \"prod-api-0374\",\n      \"status\": \"warning\",\n      \"cpu\": 67,\n      \"memory\": 92,\n      \"disk\": 33,\n      \"network\": 100,\n      \"uptime\": 6835527\n    },\n    {\n      \"id\": \"host-375\",\n      \"name\": \"prod-database-0375\",\n      \"status\": \"warning\",\n      \"cpu\": 10,\n      \"memory\": 15,\n      \"disk\": 79,\n      \"network\": 16,\n      \"uptime\": 2824344\n    },\n    {\n      \"id\": \"host-376\",\n      \"name\": \"prod-cache-0376\",\n      \"status\": \"warning\",\n      \"cpu\": 5,\n      \"memory\": 35,\n      \"disk\": 88,\n      \"network\": 48,\n      \"uptime\": 6794572\n    },\n    {\n      \"id\": \"host-377\",\n      \"name\": \"prod-worker-0377\",\n      \"status\": \"warning\",\n      \"cpu\": 1,\n      \"memory\": 2,\n      \"disk\": 91,\n      \"network\": 35,\n      \"uptime\": 2496751\n    },\n    {\n      \"id\": \"host-378\",\n      \"name\": \"prod-queue-0378\",\n      \"status\": \"warning\",\n      \"cpu\": 2,\n      \"memory\": 92,\n      \"disk\": 69,\n      \"network\": 25,\n      \"uptime\": 8687781\n    },\n    {\n      \"id\": \"host-379\",\n      \"name\": \"prod-web-0379\",\n      \"status\": \"warning\",\n      \"cpu\": 43,\n      \"memory\": 49,\n      \"disk\": 24,\n      \"network\": 70,\n      \"uptime\": 5230676\n    },\n    {\n      \"id\": \"host-380\",\n      \"name\": \"prod-api-0380\",\n      \"status\": \"warning\",\n      \"cpu\": 19,\n      \"memory\": 44,\n      \"disk\": 84,\n      \"network\": 64,\n      \"uptime\": 7511430\n    },\n    {\n      \"id\": \"host-381\",\n      \"name\": \"prod-database-0381\",\n      \"status\": \"warning\",\n      \"cpu\": 1,\n      \"memory\": 1,\n      \"disk\": 32,\n      \"network\": 49,\n      \"uptime\": 4775752\n    },\n    {\n      \"id\": \"host-382\",\n      \"name\": \"prod-cache-0382\",\n      \"status\": \"warning\",\n      \"cpu\": 96,\n      \"memory\": 22,\n      \"disk\": 53,\n      \"network\": 6,\n      \"uptime\": 5960217\n    },\n    {\n      \"id\": \"host-383\",\n      \"name\": \"prod-worker-0383\",\n      \"status\": \"warning\",\n      \"cpu\": 74,\n      \"memory\": 74,\n      \"disk\": 32,\n      \"network\": 61,\n      \"uptime\": 821832\n    },\n    {\n      \"id\": \"host-384\",\n      \"name\": \"prod-queue-0384\",\n      \"status\": \"warning\",\n      \"cpu\": 35,\n      \"memory\": 6,\n      \"disk\": 92,\n      \"network\": 87,\n      \"uptime\": 3833409\n    },\n    {\n      \"id\": \"host-385\",\n      \"name\": \"prod-web-0385\",\n      \"status\": \"warning\",\n      \"cpu\": 38,\n      \"memory\": 0,\n      \"disk\": 44,\n      \"network\": 26,\n      \"uptime\": 4124627\n    },\n    {\n      \"id\": \"host-386\",\n      \"name\": \"prod-api-0386\",\n      \"status\": \"critical\",\n      \"cpu\": 47,\n      \"memory\": 77,\n      \"disk\": 53,\n      \"network\": 73,\n      \"uptime\": 5400844\n    },\n    {\n      \"id\": \"host-387\",\n      \"name\": \"prod-database-0387\",\n      \"status\": \"critical\",\n      \"cpu\": 93,\n      \"memory\": 41,\n      \"disk\": 31,\n      \"network\": 88,\n      \"uptime\": 8672664\n    },\n    {\n      \"id\": \"host-388\",\n      \"name\": \"prod-cache-0388\",\n      \"status\": \"critical\",\n      \"cpu\": 77,\n      \"memory\": 33,\n      \"disk\": 71,\n      \"network\": 16,\n      \"uptime\": 8777215\n    },\n    {\n      \"id\": \"host-389\",\n      \"name\": \"prod-worker-0389\",\n      \"status\": \"critical\",\n      \"cpu\": 2,\n      \"memory\": 29,\n      \"disk\": 29,\n      \"network\": 92,\n      \"uptime\": 945020\n    },\n    {\n      \"id\": \"host-390\",\n      \"name\": \"prod-queue-0390\",\n      \"status\": \"critical\",\n      \"cpu\": 95,\n      \"memory\": 7,\n      \"disk\": 53,\n      \"network\": 16,\n      \"uptime\": 7245391\n    },\n    {\n      \"id\": \"host-391\",\n      \"name\": \"prod-web-0391\",\n      \"status\": \"critical\",\n      \"cpu\": 58,\n      \"memory\": 71,\n      \"disk\": 33,\n      \"network\": 59,\n      \"uptime\": 2519091\n    },\n    {\n      \"id\": \"host-392\",\n      \"name\": \"prod-api-0392\",\n      \"status\": \"critical\",\n      \"cpu\": 9,\n      \"memory\": 54,\n      \"disk\": 39,\n      \"network\": 73,\n      \"uptime\": 9710057\n    },\n    {\n      \"id\": \"host-393\",\n      \"name\": \"prod-database-0393\",\n      \"status\": \"critical\",\n      \"cpu\": 83,\n      \"memory\": 5,\n      \"disk\": 56,\n      \"network\": 84,\n      \"uptime\": 7980966\n    },\n    {\n      \"id\": \"host-394\",\n      \"name\": \"prod-cache-0394\",\n      \"status\": \"critical\",\n      \"cpu\": 12,\n      \"memory\": 42,\n      \"disk\": 73,\n      \"network\": 84,\n      \"uptime\": 4702371\n    },\n    {\n      \"id\": \"host-395\",\n      \"name\": \"prod-worker-0395\",\n      \"status\": \"critical\",\n      \"cpu\": 67,\n      \"memory\": 1,\n      \"disk\": 33,\n      \"network\": 11,\n      \"uptime\": 6115853\n    },\n    {\n      \"id\": \"host-396\",\n      \"name\": \"prod-queue-0396\",\n      \"status\": \"critical\",\n      \"cpu\": 90,\n      \"memory\": 84,\n      \"disk\": 22,\n      \"network\": 68,\n      \"uptime\": 3860967\n    },\n    {\n      \"id\": \"host-397\",\n      \"name\": \"prod-web-0397\",\n      \"status\": \"critical\",\n      \"cpu\": 50,\n      \"memory\": 73,\n      \"disk\": 38,\n      \"network\": 5,\n      \"uptime\": 6819123\n    },\n    {\n      \"id\": \"host-398\",\n      \"name\": \"prod-api-0398\",\n      \"status\": \"critical\",\n      \"cpu\": 77,\n      \"memory\": 31,\n      \"disk\": 7,\n      \"network\": 46,\n      \"uptime\": 880114\n    },\n    {\n      \"id\": \"host-399\",\n      \"name\": \"prod-database-0399\",\n      \"status\": \"critical\",\n      \"cpu\": 0,\n      \"memory\": 6,\n      \"disk\": 67,\n      \"network\": 3,\n      \"uptime\": 7652108\n    },\n    {\n      \"id\": \"host-400\",\n      \"name\": \"prod-cache-0400\",\n      \"status\": \"critical\",\n      \"cpu\": 73,\n      \"memory\": 75,\n      \"disk\": 83,\n      \"network\": 85,\n      \"uptime\": 9923415\n    },\n    {\n      \"id\": \"host-401\",\n      \"name\": \"prod-worker-0401\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 13,\n      \"disk\": 53,\n      \"network\": 21,\n      \"uptime\": 2160826\n    },\n    {\n      \"id\": \"host-402\",\n      \"name\": \"prod-queue-0402\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 51,\n      \"disk\": 41,\n      \"network\": 22,\n      \"uptime\": 2932930\n    },\n    {\n      \"id\": \"host-403\",\n      \"name\": \"prod-web-0403\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 88,\n      \"disk\": 75,\n      \"network\": 32,\n      \"uptime\": 9982117\n    },\n    {\n      \"id\": \"host-404\",\n      \"name\": \"prod-api-0404\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 27,\n      \"disk\": 81,\n      \"network\": 95,\n      \"uptime\": 8225491\n    },\n    {\n      \"id\": \"host-405\",\n      \"name\": \"prod-database-0405\",\n      \"status\": \"healthy\",\n      \"cpu\": 79,\n      \"memory\": 33,\n      \"disk\": 39,\n      \"network\": 74,\n      \"uptime\": 7243109\n    },\n    {\n      \"id\": \"host-406\",\n      \"name\": \"prod-cache-0406\",\n      \"status\": \"healthy\",\n      \"cpu\": 6,\n      \"memory\": 26,\n      \"disk\": 85,\n      \"network\": 45,\n      \"uptime\": 2235323\n    },\n    {\n      \"id\": \"host-407\",\n      \"name\": \"prod-worker-0407\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 60,\n      \"disk\": 30,\n      \"network\": 63,\n      \"uptime\": 1958858\n    },\n    {\n      \"id\": \"host-408\",\n      \"name\": \"prod-queue-0408\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 39,\n      \"disk\": 26,\n      \"network\": 92,\n      \"uptime\": 5385918\n    },\n    {\n      \"id\": \"host-409\",\n      \"name\": \"prod-web-0409\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 55,\n      \"disk\": 71,\n      \"network\": 63,\n      \"uptime\": 7136083\n    },\n    {\n      \"id\": \"host-410\",\n      \"name\": \"prod-api-0410\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 58,\n      \"disk\": 78,\n      \"network\": 65,\n      \"uptime\": 4689399\n    },\n    {\n      \"id\": \"host-411\",\n      \"name\": \"prod-database-0411\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 82,\n      \"disk\": 60,\n      \"network\": 14,\n      \"uptime\": 6731898\n    },\n    {\n      \"id\": \"host-412\",\n      \"name\": \"prod-cache-0412\",\n      \"status\": \"healthy\",\n      \"cpu\": 7,\n      \"memory\": 9,\n      \"disk\": 10,\n      \"network\": 43,\n      \"uptime\": 9534746\n    },\n    {\n      \"id\": \"host-413\",\n      \"name\": \"prod-worker-0413\",\n      \"status\": \"healthy\",\n      \"cpu\": 37,\n      \"memory\": 21,\n      \"disk\": 85,\n      \"network\": 99,\n      \"uptime\": 5928302\n    },\n    {\n      \"id\": \"host-414\",\n      \"name\": \"prod-queue-0414\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 55,\n      \"disk\": 58,\n      \"network\": 64,\n      \"uptime\": 9917242\n    },\n    {\n      \"id\": \"host-415\",\n      \"name\": \"prod-web-0415\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 20,\n      \"disk\": 50,\n      \"network\": 73,\n      \"uptime\": 959377\n    },\n    {\n      \"id\": \"host-416\",\n      \"name\": \"prod-api-0416\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 54,\n      \"disk\": 34,\n      \"network\": 24,\n      \"uptime\": 4788384\n    },\n    {\n      \"id\": \"host-417\",\n      \"name\": \"prod-database-0417\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 75,\n      \"disk\": 23,\n      \"network\": 75,\n      \"uptime\": 4847988\n    },\n    {\n      \"id\": \"host-418\",\n      \"name\": \"prod-cache-0418\",\n      \"status\": \"healthy\",\n      \"cpu\": 68,\n      \"memory\": 58,\n      \"disk\": 9,\n      \"network\": 26,\n      \"uptime\": 3124991\n    },\n    {\n      \"id\": \"host-419\",\n      \"name\": \"prod-worker-0419\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 47,\n      \"disk\": 77,\n      \"network\": 87,\n      \"uptime\": 3582626\n    },\n    {\n      \"id\": \"host-420\",\n      \"name\": \"prod-queue-0420\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 56,\n      \"disk\": 87,\n      \"network\": 67,\n      \"uptime\": 5844709\n    },\n    {\n      \"id\": \"host-421\",\n      \"name\": \"prod-web-0421\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 19,\n      \"disk\": 16,\n      \"network\": 1,\n      \"uptime\": 4876694\n    },\n    {\n      \"id\": \"host-422\",\n      \"name\": \"prod-api-0422\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 9,\n      \"disk\": 28,\n      \"network\": 73,\n      \"uptime\": 1211591\n    },\n    {\n      \"id\": \"host-423\",\n      \"name\": \"prod-database-0423\",\n      \"status\": \"healthy\",\n      \"cpu\": 41,\n      \"memory\": 2,\n      \"disk\": 96,\n      \"network\": 97,\n      \"uptime\": 1687473\n    },\n    {\n      \"id\": \"host-424\",\n      \"name\": \"prod-cache-0424\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 7,\n      \"disk\": 15,\n      \"network\": 81,\n      \"uptime\": 768919\n    },\n    {\n      \"id\": \"host-425\",\n      \"name\": \"prod-worker-0425\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 23,\n      \"disk\": 63,\n      \"network\": 57,\n      \"uptime\": 2125164\n    },\n    {\n      \"id\": \"host-426\",\n      \"name\": \"prod-queue-0426\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 25,\n      \"disk\": 28,\n      \"network\": 81,\n      \"uptime\": 4494151\n    },\n    {\n      \"id\": \"host-427\",\n      \"name\": \"prod-web-0427\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 34,\n      \"disk\": 0,\n      \"network\": 96,\n      \"uptime\": 5754534\n    },\n    {\n      \"id\": \"host-428\",\n      \"name\": \"prod-api-0428\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 74,\n      \"disk\": 47,\n      \"network\": 86,\n      \"uptime\": 5104093\n    },\n    {\n      \"id\": \"host-429\",\n      \"name\": \"prod-database-0429\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 74,\n      \"disk\": 84,\n      \"network\": 69,\n      \"uptime\": 4661859\n    },\n    {\n      \"id\": \"host-430\",\n      \"name\": \"prod-cache-0430\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 36,\n      \"disk\": 85,\n      \"network\": 97,\n      \"uptime\": 3312090\n    },\n    {\n      \"id\": \"host-431\",\n      \"name\": \"prod-worker-0431\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 22,\n      \"disk\": 71,\n      \"network\": 6,\n      \"uptime\": 713138\n    },\n    {\n      \"id\": \"host-432\",\n      \"name\": \"prod-queue-0432\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 45,\n      \"disk\": 93,\n      \"network\": 91,\n      \"uptime\": 5758676\n    },\n    {\n      \"id\": \"host-433\",\n      \"name\": \"prod-web-0433\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 57,\n      \"disk\": 38,\n      \"network\": 34,\n      \"uptime\": 1650295\n    },\n    {\n      \"id\": \"host-434\",\n      \"name\": \"prod-api-0434\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 68,\n      \"disk\": 28,\n      \"network\": 7,\n      \"uptime\": 8493444\n    },\n    {\n      \"id\": \"host-435\",\n      \"name\": \"prod-database-0435\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 95,\n      \"disk\": 15,\n      \"network\": 38,\n      \"uptime\": 5557655\n    },\n    {\n      \"id\": \"host-436\",\n      \"name\": \"prod-cache-0436\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 71,\n      \"disk\": 39,\n      \"network\": 23,\n      \"uptime\": 7232005\n    },\n    {\n      \"id\": \"host-437\",\n      \"name\": \"prod-worker-0437\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 52,\n      \"disk\": 97,\n      \"network\": 52,\n      \"uptime\": 1909038\n    },\n    {\n      \"id\": \"host-438\",\n      \"name\": \"prod-queue-0438\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 12,\n      \"disk\": 92,\n      \"network\": 74,\n      \"uptime\": 7665381\n    },\n    {\n      \"id\": \"host-439\",\n      \"name\": \"prod-web-0439\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 43,\n      \"disk\": 74,\n      \"network\": 79,\n      \"uptime\": 3766638\n    },\n    {\n      \"id\": \"host-440\",\n      \"name\": \"prod-api-0440\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 8,\n      \"disk\": 52,\n      \"network\": 41,\n      \"uptime\": 1924221\n    },\n    {\n      \"id\": \"host-441\",\n      \"name\": \"prod-database-0441\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 32,\n      \"disk\": 100,\n      \"network\": 92,\n      \"uptime\": 5830830\n    },\n    {\n      \"id\": \"host-442\",\n      \"name\": \"prod-cache-0442\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 51,\n      \"disk\": 76,\n      \"network\": 37,\n      \"uptime\": 618664\n    },\n    {\n      \"id\": \"host-443\",\n      \"name\": \"prod-worker-0443\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 72,\n      \"disk\": 51,\n      \"network\": 61,\n      \"uptime\": 3004965\n    },\n    {\n      \"id\": \"host-444\",\n      \"name\": \"prod-queue-0444\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 22,\n      \"disk\": 1,\n      \"network\": 15,\n      \"uptime\": 1437308\n    },\n    {\n      \"id\": \"host-445\",\n      \"name\": \"prod-web-0445\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 17,\n      \"disk\": 5,\n      \"network\": 12,\n      \"uptime\": 3170864\n    },\n    {\n      \"id\": \"host-446\",\n      \"name\": \"prod-api-0446\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 70,\n      \"disk\": 80,\n      \"network\": 56,\n      \"uptime\": 8796792\n    },\n    {\n      \"id\": \"host-447\",\n      \"name\": \"prod-database-0447\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 25,\n      \"disk\": 97,\n      \"network\": 44,\n      \"uptime\": 1356795\n    },\n    {\n      \"id\": \"host-448\",\n      \"name\": \"prod-cache-0448\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 22,\n      \"disk\": 79,\n      \"network\": 24,\n      \"uptime\": 3202552\n    },\n    {\n      \"id\": \"host-449\",\n      \"name\": \"prod-worker-0449\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 23,\n      \"disk\": 48,\n      \"network\": 99,\n      \"uptime\": 8451881\n    },\n    {\n      \"id\": \"host-450\",\n      \"name\": \"prod-queue-0450\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 86,\n      \"disk\": 71,\n      \"network\": 100,\n      \"uptime\": 2227507\n    },\n    {\n      \"id\": \"host-451\",\n      \"name\": \"prod-web-0451\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 79,\n      \"disk\": 42,\n      \"network\": 31,\n      \"uptime\": 3753887\n    },\n    {\n      \"id\": \"host-452\",\n      \"name\": \"prod-api-0452\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 75,\n      \"disk\": 89,\n      \"network\": 81,\n      \"uptime\": 6774569\n    },\n    {\n      \"id\": \"host-453\",\n      \"name\": \"prod-database-0453\",\n      \"status\": \"healthy\",\n      \"cpu\": 30,\n      \"memory\": 93,\n      \"disk\": 36,\n      \"network\": 89,\n      \"uptime\": 2294022\n    },\n    {\n      \"id\": \"host-454\",\n      \"name\": \"prod-cache-0454\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 10,\n      \"disk\": 53,\n      \"network\": 89,\n      \"uptime\": 4948452\n    },\n    {\n      \"id\": \"host-455\",\n      \"name\": \"prod-worker-0455\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 5,\n      \"disk\": 32,\n      \"network\": 31,\n      \"uptime\": 9583746\n    },\n    {\n      \"id\": \"host-456\",\n      \"name\": \"prod-queue-0456\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 96,\n      \"disk\": 32,\n      \"network\": 8,\n      \"uptime\": 7556259\n    },\n    {\n      \"id\": \"host-457\",\n      \"name\": \"prod-web-0457\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 42,\n      \"disk\": 81,\n      \"network\": 12,\n      \"uptime\": 9552643\n    },\n    {\n      \"id\": \"host-458\",\n      \"name\": \"prod-api-0458\",\n      \"status\": \"healthy\",\n      \"cpu\": 72,\n      \"memory\": 13,\n      \"disk\": 97,\n      \"network\": 51,\n      \"uptime\": 4103302\n    },\n    {\n      \"id\": \"host-459\",\n      \"name\": \"prod-database-0459\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 58,\n      \"disk\": 3,\n      \"network\": 73,\n      \"uptime\": 2070400\n    },\n    {\n      \"id\": \"host-460\",\n      \"name\": \"prod-cache-0460\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 41,\n      \"disk\": 89,\n      \"network\": 28,\n      \"uptime\": 7986730\n    },\n    {\n      \"id\": \"host-461\",\n      \"name\": \"prod-worker-0461\",\n      \"status\": \"warning\",\n      \"cpu\": 36,\n      \"memory\": 78,\n      \"disk\": 39,\n      \"network\": 74,\n      \"uptime\": 115360\n    },\n    {\n      \"id\": \"host-462\",\n      \"name\": \"prod-queue-0462\",\n      \"status\": \"warning\",\n      \"cpu\": 52,\n      \"memory\": 8,\n      \"disk\": 29,\n      \"network\": 91,\n      \"uptime\": 772972\n    },\n    {\n      \"id\": \"host-463\",\n      \"name\": \"prod-web-0463\",\n      \"status\": \"warning\",\n      \"cpu\": 15,\n      \"memory\": 68,\n      \"disk\": 23,\n      \"network\": 88,\n      \"uptime\": 8388701\n    },\n    {\n      \"id\": \"host-464\",\n      \"name\": \"prod-api-0464\",\n      \"status\": \"warning\",\n      \"cpu\": 41,\n      \"memory\": 9,\n      \"disk\": 31,\n      \"network\": 19,\n      \"uptime\": 3284305\n    },\n    {\n      \"id\": \"host-465\",\n      \"name\": \"prod-database-0465\",\n      \"status\": \"warning\",\n      \"cpu\": 12,\n      \"memory\": 22,\n      \"disk\": 63,\n      \"network\": 62,\n      \"uptime\": 6447994\n    },\n    {\n      \"id\": \"host-466\",\n      \"name\": \"prod-cache-0466\",\n      \"status\": \"warning\",\n      \"cpu\": 94,\n      \"memory\": 50,\n      \"disk\": 2,\n      \"network\": 33,\n      \"uptime\": 3805648\n    },\n    {\n      \"id\": \"host-467\",\n      \"name\": \"prod-worker-0467\",\n      \"status\": \"warning\",\n      \"cpu\": 65,\n      \"memory\": 94,\n      \"disk\": 67,\n      \"network\": 34,\n      \"uptime\": 642972\n    },\n    {\n      \"id\": \"host-468\",\n      \"name\": \"prod-queue-0468\",\n      \"status\": \"warning\",\n      \"cpu\": 24,\n      \"memory\": 15,\n      \"disk\": 82,\n      \"network\": 70,\n      \"uptime\": 6473052\n    },\n    {\n      \"id\": \"host-469\",\n      \"name\": \"prod-web-0469\",\n      \"status\": \"warning\",\n      \"cpu\": 83,\n      \"memory\": 70,\n      \"disk\": 75,\n      \"network\": 73,\n      \"uptime\": 88639\n    },\n    {\n      \"id\": \"host-470\",\n      \"name\": \"prod-api-0470\",\n      \"status\": \"warning\",\n      \"cpu\": 26,\n      \"memory\": 74,\n      \"disk\": 54,\n      \"network\": 89,\n      \"uptime\": 9189093\n    },\n    {\n      \"id\": \"host-471\",\n      \"name\": \"prod-database-0471\",\n      \"status\": \"warning\",\n      \"cpu\": 66,\n      \"memory\": 98,\n      \"disk\": 24,\n      \"network\": 31,\n      \"uptime\": 6844866\n    },\n    {\n      \"id\": \"host-472\",\n      \"name\": \"prod-cache-0472\",\n      \"status\": \"warning\",\n      \"cpu\": 10,\n      \"memory\": 19,\n      \"disk\": 68,\n      \"network\": 42,\n      \"uptime\": 8663588\n    },\n    {\n      \"id\": \"host-473\",\n      \"name\": \"prod-worker-0473\",\n      \"status\": \"warning\",\n      \"cpu\": 52,\n      \"memory\": 36,\n      \"disk\": 42,\n      \"network\": 50,\n      \"uptime\": 1583272\n    },\n    {\n      \"id\": \"host-474\",\n      \"name\": \"prod-queue-0474\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 20,\n      \"disk\": 79,\n      \"network\": 63,\n      \"uptime\": 4428489\n    },\n    {\n      \"id\": \"host-475\",\n      \"name\": \"prod-web-0475\",\n      \"status\": \"warning\",\n      \"cpu\": 2,\n      \"memory\": 2,\n      \"disk\": 88,\n      \"network\": 54,\n      \"uptime\": 935788\n    },\n    {\n      \"id\": \"host-476\",\n      \"name\": \"prod-api-0476\",\n      \"status\": \"warning\",\n      \"cpu\": 33,\n      \"memory\": 49,\n      \"disk\": 88,\n      \"network\": 64,\n      \"uptime\": 4153846\n    },\n    {\n      \"id\": \"host-477\",\n      \"name\": \"prod-database-0477\",\n      \"status\": \"warning\",\n      \"cpu\": 7,\n      \"memory\": 57,\n      \"disk\": 46,\n      \"network\": 15,\n      \"uptime\": 5995078\n    },\n    {\n      \"id\": \"host-478\",\n      \"name\": \"prod-cache-0478\",\n      \"status\": \"warning\",\n      \"cpu\": 55,\n      \"memory\": 9,\n      \"disk\": 30,\n      \"network\": 88,\n      \"uptime\": 6630053\n    },\n    {\n      \"id\": \"host-479\",\n      \"name\": \"prod-worker-0479\",\n      \"status\": \"warning\",\n      \"cpu\": 100,\n      \"memory\": 23,\n      \"disk\": 80,\n      \"network\": 16,\n      \"uptime\": 2093947\n    },\n    {\n      \"id\": \"host-480\",\n      \"name\": \"prod-queue-0480\",\n      \"status\": \"warning\",\n      \"cpu\": 87,\n      \"memory\": 62,\n      \"disk\": 45,\n      \"network\": 24,\n      \"uptime\": 9526031\n    },\n    {\n      \"id\": \"host-481\",\n      \"name\": \"prod-web-0481\",\n      \"status\": \"warning\",\n      \"cpu\": 34,\n      \"memory\": 75,\n      \"disk\": 3,\n      \"network\": 94,\n      \"uptime\": 6222084\n    },\n    {\n      \"id\": \"host-482\",\n      \"name\": \"prod-api-0482\",\n      \"status\": \"warning\",\n      \"cpu\": 92,\n      \"memory\": 55,\n      \"disk\": 86,\n      \"network\": 8,\n      \"uptime\": 4687104\n    },\n    {\n      \"id\": \"host-483\",\n      \"name\": \"prod-database-0483\",\n      \"status\": \"warning\",\n      \"cpu\": 73,\n      \"memory\": 83,\n      \"disk\": 51,\n      \"network\": 56,\n      \"uptime\": 8424083\n    },\n    {\n      \"id\": \"host-484\",\n      \"name\": \"prod-cache-0484\",\n      \"status\": \"warning\",\n      \"cpu\": 87,\n      \"memory\": 79,\n      \"disk\": 35,\n      \"network\": 65,\n      \"uptime\": 3191599\n    },\n    {\n      \"id\": \"host-485\",\n      \"name\": \"prod-worker-0485\",\n      \"status\": \"warning\",\n      \"cpu\": 84,\n      \"memory\": 23,\n      \"disk\": 13,\n      \"network\": 1,\n      \"uptime\": 7824227\n    },\n    {\n      \"id\": \"host-486\",\n      \"name\": \"prod-queue-0486\",\n      \"status\": \"critical\",\n      \"cpu\": 92,\n      \"memory\": 6,\n      \"disk\": 75,\n      \"network\": 52,\n      \"uptime\": 3341731\n    },\n    {\n      \"id\": \"host-487\",\n      \"name\": \"prod-web-0487\",\n      \"status\": \"critical\",\n      \"cpu\": 68,\n      \"memory\": 88,\n      \"disk\": 52,\n      \"network\": 25,\n      \"uptime\": 2342432\n    },\n    {\n      \"id\": \"host-488\",\n      \"name\": \"prod-api-0488\",\n      \"status\": \"critical\",\n      \"cpu\": 95,\n      \"memory\": 41,\n      \"disk\": 74,\n      \"network\": 55,\n      \"uptime\": 2901549\n    },\n    {\n      \"id\": \"host-489\",\n      \"name\": \"prod-database-0489\",\n      \"status\": \"critical\",\n      \"cpu\": 17,\n      \"memory\": 40,\n      \"disk\": 78,\n      \"network\": 24,\n      \"uptime\": 3399187\n    },\n    {\n      \"id\": \"host-490\",\n      \"name\": \"prod-cache-0490\",\n      \"status\": \"critical\",\n      \"cpu\": 49,\n      \"memory\": 60,\n      \"disk\": 66,\n      \"network\": 13,\n      \"uptime\": 3162479\n    },\n    {\n      \"id\": \"host-491\",\n      \"name\": \"prod-worker-0491\",\n      \"status\": \"critical\",\n      \"cpu\": 62,\n      \"memory\": 66,\n      \"disk\": 44,\n      \"network\": 53,\n      \"uptime\": 1897079\n    },\n    {\n      \"id\": \"host-492\",\n      \"name\": \"prod-queue-0492\",\n      \"status\": \"critical\",\n      \"cpu\": 36,\n      \"memory\": 91,\n      \"disk\": 80,\n      \"network\": 58,\n      \"uptime\": 9364532\n    },\n    {\n      \"id\": \"host-493\",\n      \"name\": \"prod-web-0493\",\n      \"status\": \"critical\",\n      \"cpu\": 87,\n      \"memory\": 34,\n      \"disk\": 39,\n      \"network\": 48,\n      \"uptime\": 5548180\n    },\n    {\n      \"id\": \"host-494\",\n      \"name\": \"prod-api-0494\",\n      \"status\": \"critical\",\n      \"cpu\": 45,\n      \"memory\": 68,\n      \"disk\": 56,\n      \"network\": 76,\n      \"uptime\": 2345866\n    },\n    {\n      \"id\": \"host-495\",\n      \"name\": \"prod-database-0495\",\n      \"status\": \"critical\",\n      \"cpu\": 99,\n      \"memory\": 22,\n      \"disk\": 17,\n      \"network\": 52,\n      \"uptime\": 7188323\n    },\n    {\n      \"id\": \"host-496\",\n      \"name\": \"prod-cache-0496\",\n      \"status\": \"critical\",\n      \"cpu\": 52,\n      \"memory\": 66,\n      \"disk\": 83,\n      \"network\": 96,\n      \"uptime\": 387048\n    },\n    {\n      \"id\": \"host-497\",\n      \"name\": \"prod-worker-0497\",\n      \"status\": \"critical\",\n      \"cpu\": 75,\n      \"memory\": 40,\n      \"disk\": 7,\n      \"network\": 81,\n      \"uptime\": 8015241\n    },\n    {\n      \"id\": \"host-498\",\n      \"name\": \"prod-queue-0498\",\n      \"status\": \"critical\",\n      \"cpu\": 38,\n      \"memory\": 87,\n      \"disk\": 26,\n      \"network\": 29,\n      \"uptime\": 8937550\n    },\n    {\n      \"id\": \"host-499\",\n      \"name\": \"prod-web-0499\",\n      \"status\": \"critical\",\n      \"cpu\": 40,\n      \"memory\": 76,\n      \"disk\": 5,\n      \"network\": 97,\n      \"uptime\": 4424527\n    },\n    {\n      \"id\": \"host-500\",\n      \"name\": \"prod-api-0500\",\n      \"status\": \"critical\",\n      \"cpu\": 48,\n      \"memory\": 48,\n      \"disk\": 46,\n      \"network\": 77,\n      \"uptime\": 3689146\n    },\n    {\n      \"id\": \"host-501\",\n      \"name\": \"prod-database-0501\",\n      \"status\": \"healthy\",\n      \"cpu\": 92,\n      \"memory\": 63,\n      \"disk\": 84,\n      \"network\": 90,\n      \"uptime\": 5012453\n    },\n    {\n      \"id\": \"host-502\",\n      \"name\": \"prod-cache-0502\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 91,\n      \"disk\": 5,\n      \"network\": 43,\n      \"uptime\": 3907394\n    },\n    {\n      \"id\": \"host-503\",\n      \"name\": \"prod-worker-0503\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 42,\n      \"disk\": 66,\n      \"network\": 10,\n      \"uptime\": 2226607\n    },\n    {\n      \"id\": \"host-504\",\n      \"name\": \"prod-queue-0504\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 4,\n      \"disk\": 88,\n      \"network\": 4,\n      \"uptime\": 7522762\n    },\n    {\n      \"id\": \"host-505\",\n      \"name\": \"prod-web-0505\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 9,\n      \"disk\": 67,\n      \"network\": 8,\n      \"uptime\": 8917534\n    },\n    {\n      \"id\": \"host-506\",\n      \"name\": \"prod-api-0506\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 74,\n      \"disk\": 74,\n      \"network\": 60,\n      \"uptime\": 2674460\n    },\n    {\n      \"id\": \"host-507\",\n      \"name\": \"prod-database-0507\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 8,\n      \"disk\": 1,\n      \"network\": 79,\n      \"uptime\": 8507951\n    },\n    {\n      \"id\": \"host-508\",\n      \"name\": \"prod-cache-0508\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 40,\n      \"disk\": 77,\n      \"network\": 96,\n      \"uptime\": 3097099\n    },\n    {\n      \"id\": \"host-509\",\n      \"name\": \"prod-worker-0509\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 42,\n      \"disk\": 70,\n      \"network\": 57,\n      \"uptime\": 8746625\n    },\n    {\n      \"id\": \"host-510\",\n      \"name\": \"prod-queue-0510\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 72,\n      \"disk\": 12,\n      \"network\": 41,\n      \"uptime\": 1215455\n    },\n    {\n      \"id\": \"host-511\",\n      \"name\": \"prod-web-0511\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 85,\n      \"disk\": 28,\n      \"network\": 49,\n      \"uptime\": 7015680\n    },\n    {\n      \"id\": \"host-512\",\n      \"name\": \"prod-api-0512\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 77,\n      \"disk\": 28,\n      \"network\": 37,\n      \"uptime\": 2516742\n    },\n    {\n      \"id\": \"host-513\",\n      \"name\": \"prod-database-0513\",\n      \"status\": \"healthy\",\n      \"cpu\": 68,\n      \"memory\": 56,\n      \"disk\": 60,\n      \"network\": 36,\n      \"uptime\": 7687585\n    },\n    {\n      \"id\": \"host-514\",\n      \"name\": \"prod-cache-0514\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 100,\n      \"disk\": 90,\n      \"network\": 28,\n      \"uptime\": 2267458\n    },\n    {\n      \"id\": \"host-515\",\n      \"name\": \"prod-worker-0515\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 96,\n      \"disk\": 78,\n      \"network\": 58,\n      \"uptime\": 3939103\n    },\n    {\n      \"id\": \"host-516\",\n      \"name\": \"prod-queue-0516\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 91,\n      \"disk\": 74,\n      \"network\": 24,\n      \"uptime\": 3352554\n    },\n    {\n      \"id\": \"host-517\",\n      \"name\": \"prod-web-0517\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 11,\n      \"disk\": 47,\n      \"network\": 97,\n      \"uptime\": 3854471\n    },\n    {\n      \"id\": \"host-518\",\n      \"name\": \"prod-api-0518\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 44,\n      \"disk\": 17,\n      \"network\": 47,\n      \"uptime\": 1365767\n    },\n    {\n      \"id\": \"host-519\",\n      \"name\": \"prod-database-0519\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 28,\n      \"disk\": 35,\n      \"network\": 57,\n      \"uptime\": 1363911\n    },\n    {\n      \"id\": \"host-520\",\n      \"name\": \"prod-cache-0520\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 66,\n      \"disk\": 100,\n      \"network\": 73,\n      \"uptime\": 1079913\n    },\n    {\n      \"id\": \"host-521\",\n      \"name\": \"prod-worker-0521\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 49,\n      \"disk\": 46,\n      \"network\": 38,\n      \"uptime\": 1981082\n    },\n    {\n      \"id\": \"host-522\",\n      \"name\": \"prod-queue-0522\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 50,\n      \"disk\": 31,\n      \"network\": 60,\n      \"uptime\": 6306834\n    },\n    {\n      \"id\": \"host-523\",\n      \"name\": \"prod-web-0523\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 70,\n      \"disk\": 20,\n      \"network\": 62,\n      \"uptime\": 1722115\n    },\n    {\n      \"id\": \"host-524\",\n      \"name\": \"prod-api-0524\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 77,\n      \"disk\": 4,\n      \"network\": 3,\n      \"uptime\": 8689095\n    },\n    {\n      \"id\": \"host-525\",\n      \"name\": \"prod-database-0525\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 52,\n      \"disk\": 15,\n      \"network\": 7,\n      \"uptime\": 7531138\n    },\n    {\n      \"id\": \"host-526\",\n      \"name\": \"prod-cache-0526\",\n      \"status\": \"healthy\",\n      \"cpu\": 79,\n      \"memory\": 57,\n      \"disk\": 80,\n      \"network\": 49,\n      \"uptime\": 5634\n    },\n    {\n      \"id\": \"host-527\",\n      \"name\": \"prod-worker-0527\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 5,\n      \"disk\": 65,\n      \"network\": 56,\n      \"uptime\": 5348285\n    },\n    {\n      \"id\": \"host-528\",\n      \"name\": \"prod-queue-0528\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 30,\n      \"disk\": 80,\n      \"network\": 24,\n      \"uptime\": 9284678\n    },\n    {\n      \"id\": \"host-529\",\n      \"name\": \"prod-web-0529\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 34,\n      \"disk\": 52,\n      \"network\": 37,\n      \"uptime\": 3812715\n    },\n    {\n      \"id\": \"host-530\",\n      \"name\": \"prod-api-0530\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 9,\n      \"disk\": 53,\n      \"network\": 31,\n      \"uptime\": 8558260\n    },\n    {\n      \"id\": \"host-531\",\n      \"name\": \"prod-database-0531\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 69,\n      \"disk\": 86,\n      \"network\": 61,\n      \"uptime\": 288029\n    },\n    {\n      \"id\": \"host-532\",\n      \"name\": \"prod-cache-0532\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 96,\n      \"disk\": 67,\n      \"network\": 52,\n      \"uptime\": 2853938\n    },\n    {\n      \"id\": \"host-533\",\n      \"name\": \"prod-worker-0533\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 36,\n      \"disk\": 68,\n      \"network\": 94,\n      \"uptime\": 217658\n    },\n    {\n      \"id\": \"host-534\",\n      \"name\": \"prod-queue-0534\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 8,\n      \"disk\": 66,\n      \"network\": 95,\n      \"uptime\": 4079225\n    },\n    {\n      \"id\": \"host-535\",\n      \"name\": \"prod-web-0535\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 34,\n      \"disk\": 59,\n      \"network\": 57,\n      \"uptime\": 3132454\n    },\n    {\n      \"id\": \"host-536\",\n      \"name\": \"prod-api-0536\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 63,\n      \"disk\": 76,\n      \"network\": 3,\n      \"uptime\": 8392642\n    },\n    {\n      \"id\": \"host-537\",\n      \"name\": \"prod-database-0537\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 50,\n      \"disk\": 86,\n      \"network\": 36,\n      \"uptime\": 6424819\n    },\n    {\n      \"id\": \"host-538\",\n      \"name\": \"prod-cache-0538\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 19,\n      \"disk\": 20,\n      \"network\": 18,\n      \"uptime\": 129614\n    },\n    {\n      \"id\": \"host-539\",\n      \"name\": \"prod-worker-0539\",\n      \"status\": \"healthy\",\n      \"cpu\": 91,\n      \"memory\": 66,\n      \"disk\": 22,\n      \"network\": 76,\n      \"uptime\": 9376063\n    },\n    {\n      \"id\": \"host-540\",\n      \"name\": \"prod-queue-0540\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 17,\n      \"disk\": 84,\n      \"network\": 48,\n      \"uptime\": 2482868\n    },\n    {\n      \"id\": \"host-541\",\n      \"name\": \"prod-web-0541\",\n      \"status\": \"healthy\",\n      \"cpu\": 72,\n      \"memory\": 93,\n      \"disk\": 28,\n      \"network\": 23,\n      \"uptime\": 3089023\n    },\n    {\n      \"id\": \"host-542\",\n      \"name\": \"prod-api-0542\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 54,\n      \"disk\": 12,\n      \"network\": 47,\n      \"uptime\": 893281\n    },\n    {\n      \"id\": \"host-543\",\n      \"name\": \"prod-database-0543\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 85,\n      \"disk\": 1,\n      \"network\": 36,\n      \"uptime\": 9755864\n    },\n    {\n      \"id\": \"host-544\",\n      \"name\": \"prod-cache-0544\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 2,\n      \"disk\": 77,\n      \"network\": 54,\n      \"uptime\": 3394999\n    },\n    {\n      \"id\": \"host-545\",\n      \"name\": \"prod-worker-0545\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 10,\n      \"disk\": 86,\n      \"network\": 46,\n      \"uptime\": 9645761\n    },\n    {\n      \"id\": \"host-546\",\n      \"name\": \"prod-queue-0546\",\n      \"status\": \"healthy\",\n      \"cpu\": 41,\n      \"memory\": 82,\n      \"disk\": 57,\n      \"network\": 54,\n      \"uptime\": 4835602\n    },\n    {\n      \"id\": \"host-547\",\n      \"name\": \"prod-web-0547\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 6,\n      \"disk\": 73,\n      \"network\": 16,\n      \"uptime\": 2336383\n    },\n    {\n      \"id\": \"host-548\",\n      \"name\": \"prod-api-0548\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 6,\n      \"disk\": 19,\n      \"network\": 51,\n      \"uptime\": 4877270\n    },\n    {\n      \"id\": \"host-549\",\n      \"name\": \"prod-database-0549\",\n      \"status\": \"healthy\",\n      \"cpu\": 72,\n      \"memory\": 72,\n      \"disk\": 70,\n      \"network\": 80,\n      \"uptime\": 4851536\n    },\n    {\n      \"id\": \"host-550\",\n      \"name\": \"prod-cache-0550\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 59,\n      \"disk\": 11,\n      \"network\": 61,\n      \"uptime\": 1304805\n    },\n    {\n      \"id\": \"host-551\",\n      \"name\": \"prod-worker-0551\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 12,\n      \"disk\": 5,\n      \"network\": 27,\n      \"uptime\": 2848987\n    },\n    {\n      \"id\": \"host-552\",\n      \"name\": \"prod-queue-0552\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 49,\n      \"disk\": 78,\n      \"network\": 62,\n      \"uptime\": 3891840\n    },\n    {\n      \"id\": \"host-553\",\n      \"name\": \"prod-web-0553\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 12,\n      \"disk\": 56,\n      \"network\": 32,\n      \"uptime\": 3280987\n    },\n    {\n      \"id\": \"host-554\",\n      \"name\": \"prod-api-0554\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 25,\n      \"disk\": 71,\n      \"network\": 82,\n      \"uptime\": 6654488\n    },\n    {\n      \"id\": \"host-555\",\n      \"name\": \"prod-database-0555\",\n      \"status\": \"healthy\",\n      \"cpu\": 74,\n      \"memory\": 0,\n      \"disk\": 73,\n      \"network\": 10,\n      \"uptime\": 5805778\n    },\n    {\n      \"id\": \"host-556\",\n      \"name\": \"prod-cache-0556\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 13,\n      \"disk\": 80,\n      \"network\": 26,\n      \"uptime\": 7479723\n    },\n    {\n      \"id\": \"host-557\",\n      \"name\": \"prod-worker-0557\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 5,\n      \"disk\": 33,\n      \"network\": 18,\n      \"uptime\": 4541907\n    },\n    {\n      \"id\": \"host-558\",\n      \"name\": \"prod-queue-0558\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 93,\n      \"disk\": 74,\n      \"network\": 44,\n      \"uptime\": 7873055\n    },\n    {\n      \"id\": \"host-559\",\n      \"name\": \"prod-web-0559\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 95,\n      \"disk\": 94,\n      \"network\": 46,\n      \"uptime\": 8547542\n    },\n    {\n      \"id\": \"host-560\",\n      \"name\": \"prod-api-0560\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 18,\n      \"disk\": 64,\n      \"network\": 11,\n      \"uptime\": 5550691\n    },\n    {\n      \"id\": \"host-561\",\n      \"name\": \"prod-database-0561\",\n      \"status\": \"warning\",\n      \"cpu\": 23,\n      \"memory\": 61,\n      \"disk\": 2,\n      \"network\": 28,\n      \"uptime\": 1978811\n    },\n    {\n      \"id\": \"host-562\",\n      \"name\": \"prod-cache-0562\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 54,\n      \"disk\": 40,\n      \"network\": 39,\n      \"uptime\": 5835780\n    },\n    {\n      \"id\": \"host-563\",\n      \"name\": \"prod-worker-0563\",\n      \"status\": \"warning\",\n      \"cpu\": 79,\n      \"memory\": 100,\n      \"disk\": 33,\n      \"network\": 12,\n      \"uptime\": 9574624\n    },\n    {\n      \"id\": \"host-564\",\n      \"name\": \"prod-queue-0564\",\n      \"status\": \"warning\",\n      \"cpu\": 28,\n      \"memory\": 21,\n      \"disk\": 92,\n      \"network\": 19,\n      \"uptime\": 3955857\n    },\n    {\n      \"id\": \"host-565\",\n      \"name\": \"prod-web-0565\",\n      \"status\": \"warning\",\n      \"cpu\": 50,\n      \"memory\": 21,\n      \"disk\": 93,\n      \"network\": 78,\n      \"uptime\": 2034782\n    },\n    {\n      \"id\": \"host-566\",\n      \"name\": \"prod-api-0566\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 76,\n      \"disk\": 37,\n      \"network\": 11,\n      \"uptime\": 8013388\n    },\n    {\n      \"id\": \"host-567\",\n      \"name\": \"prod-database-0567\",\n      \"status\": \"warning\",\n      \"cpu\": 87,\n      \"memory\": 72,\n      \"disk\": 41,\n      \"network\": 32,\n      \"uptime\": 9916438\n    },\n    {\n      \"id\": \"host-568\",\n      \"name\": \"prod-cache-0568\",\n      \"status\": \"warning\",\n      \"cpu\": 79,\n      \"memory\": 87,\n      \"disk\": 81,\n      \"network\": 11,\n      \"uptime\": 6533398\n    },\n    {\n      \"id\": \"host-569\",\n      \"name\": \"prod-worker-0569\",\n      \"status\": \"warning\",\n      \"cpu\": 96,\n      \"memory\": 96,\n      \"disk\": 50,\n      \"network\": 97,\n      \"uptime\": 4231043\n    },\n    {\n      \"id\": \"host-570\",\n      \"name\": \"prod-queue-0570\",\n      \"status\": \"warning\",\n      \"cpu\": 74,\n      \"memory\": 52,\n      \"disk\": 90,\n      \"network\": 9,\n      \"uptime\": 2922283\n    },\n    {\n      \"id\": \"host-571\",\n      \"name\": \"prod-web-0571\",\n      \"status\": \"warning\",\n      \"cpu\": 4,\n      \"memory\": 24,\n      \"disk\": 19,\n      \"network\": 69,\n      \"uptime\": 3183679\n    },\n    {\n      \"id\": \"host-572\",\n      \"name\": \"prod-api-0572\",\n      \"status\": \"warning\",\n      \"cpu\": 77,\n      \"memory\": 33,\n      \"disk\": 28,\n      \"network\": 17,\n      \"uptime\": 285835\n    },\n    {\n      \"id\": \"host-573\",\n      \"name\": \"prod-database-0573\",\n      \"status\": \"warning\",\n      \"cpu\": 9,\n      \"memory\": 76,\n      \"disk\": 26,\n      \"network\": 5,\n      \"uptime\": 8541550\n    },\n    {\n      \"id\": \"host-574\",\n      \"name\": \"prod-cache-0574\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 100,\n      \"disk\": 65,\n      \"network\": 61,\n      \"uptime\": 678860\n    },\n    {\n      \"id\": \"host-575\",\n      \"name\": \"prod-worker-0575\",\n      \"status\": \"warning\",\n      \"cpu\": 48,\n      \"memory\": 83,\n      \"disk\": 57,\n      \"network\": 48,\n      \"uptime\": 7695103\n    },\n    {\n      \"id\": \"host-576\",\n      \"name\": \"prod-queue-0576\",\n      \"status\": \"warning\",\n      \"cpu\": 34,\n      \"memory\": 71,\n      \"disk\": 12,\n      \"network\": 32,\n      \"uptime\": 1154284\n    },\n    {\n      \"id\": \"host-577\",\n      \"name\": \"prod-web-0577\",\n      \"status\": \"warning\",\n      \"cpu\": 98,\n      \"memory\": 53,\n      \"disk\": 100,\n      \"network\": 68,\n      \"uptime\": 3863579\n    },\n    {\n      \"id\": \"host-578\",\n      \"name\": \"prod-api-0578\",\n      \"status\": \"warning\",\n      \"cpu\": 28,\n      \"memory\": 93,\n      \"disk\": 97,\n      \"network\": 81,\n      \"uptime\": 3354091\n    },\n    {\n      \"id\": \"host-579\",\n      \"name\": \"prod-database-0579\",\n      \"status\": \"warning\",\n      \"cpu\": 36,\n      \"memory\": 58,\n      \"disk\": 88,\n      \"network\": 15,\n      \"uptime\": 4152710\n    },\n    {\n      \"id\": \"host-580\",\n      \"name\": \"prod-cache-0580\",\n      \"status\": \"warning\",\n      \"cpu\": 58,\n      \"memory\": 38,\n      \"disk\": 8,\n      \"network\": 39,\n      \"uptime\": 3061562\n    },\n    {\n      \"id\": \"host-581\",\n      \"name\": \"prod-worker-0581\",\n      \"status\": \"warning\",\n      \"cpu\": 87,\n      \"memory\": 21,\n      \"disk\": 85,\n      \"network\": 52,\n      \"uptime\": 2004655\n    },\n    {\n      \"id\": \"host-582\",\n      \"name\": \"prod-queue-0582\",\n      \"status\": \"warning\",\n      \"cpu\": 58,\n      \"memory\": 6,\n      \"disk\": 99,\n      \"network\": 52,\n      \"uptime\": 3077719\n    },\n    {\n      \"id\": \"host-583\",\n      \"name\": \"prod-web-0583\",\n      \"status\": \"warning\",\n      \"cpu\": 28,\n      \"memory\": 62,\n      \"disk\": 31,\n      \"network\": 6,\n      \"uptime\": 9444380\n    },\n    {\n      \"id\": \"host-584\",\n      \"name\": \"prod-api-0584\",\n      \"status\": \"warning\",\n      \"cpu\": 69,\n      \"memory\": 52,\n      \"disk\": 27,\n      \"network\": 99,\n      \"uptime\": 5413484\n    },\n    {\n      \"id\": \"host-585\",\n      \"name\": \"prod-database-0585\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 42,\n      \"disk\": 96,\n      \"network\": 60,\n      \"uptime\": 9752673\n    },\n    {\n      \"id\": \"host-586\",\n      \"name\": \"prod-cache-0586\",\n      \"status\": \"critical\",\n      \"cpu\": 0,\n      \"memory\": 17,\n      \"disk\": 51,\n      \"network\": 85,\n      \"uptime\": 7040331\n    },\n    {\n      \"id\": \"host-587\",\n      \"name\": \"prod-worker-0587\",\n      \"status\": \"critical\",\n      \"cpu\": 56,\n      \"memory\": 33,\n      \"disk\": 68,\n      \"network\": 64,\n      \"uptime\": 8724387\n    },\n    {\n      \"id\": \"host-588\",\n      \"name\": \"prod-queue-0588\",\n      \"status\": \"critical\",\n      \"cpu\": 69,\n      \"memory\": 36,\n      \"disk\": 73,\n      \"network\": 46,\n      \"uptime\": 3251532\n    },\n    {\n      \"id\": \"host-589\",\n      \"name\": \"prod-web-0589\",\n      \"status\": \"critical\",\n      \"cpu\": 13,\n      \"memory\": 62,\n      \"disk\": 78,\n      \"network\": 8,\n      \"uptime\": 7628491\n    },\n    {\n      \"id\": \"host-590\",\n      \"name\": \"prod-api-0590\",\n      \"status\": \"critical\",\n      \"cpu\": 55,\n      \"memory\": 92,\n      \"disk\": 55,\n      \"network\": 62,\n      \"uptime\": 2122046\n    },\n    {\n      \"id\": \"host-591\",\n      \"name\": \"prod-database-0591\",\n      \"status\": \"critical\",\n      \"cpu\": 76,\n      \"memory\": 90,\n      \"disk\": 80,\n      \"network\": 86,\n      \"uptime\": 6219736\n    },\n    {\n      \"id\": \"host-592\",\n      \"name\": \"prod-cache-0592\",\n      \"status\": \"critical\",\n      \"cpu\": 56,\n      \"memory\": 18,\n      \"disk\": 57,\n      \"network\": 54,\n      \"uptime\": 4448725\n    },\n    {\n      \"id\": \"host-593\",\n      \"name\": \"prod-worker-0593\",\n      \"status\": \"critical\",\n      \"cpu\": 5,\n      \"memory\": 40,\n      \"disk\": 40,\n      \"network\": 29,\n      \"uptime\": 7763435\n    },\n    {\n      \"id\": \"host-594\",\n      \"name\": \"prod-queue-0594\",\n      \"status\": \"critical\",\n      \"cpu\": 69,\n      \"memory\": 94,\n      \"disk\": 78,\n      \"network\": 59,\n      \"uptime\": 739430\n    },\n    {\n      \"id\": \"host-595\",\n      \"name\": \"prod-web-0595\",\n      \"status\": \"critical\",\n      \"cpu\": 100,\n      \"memory\": 9,\n      \"disk\": 72,\n      \"network\": 21,\n      \"uptime\": 5132933\n    },\n    {\n      \"id\": \"host-596\",\n      \"name\": \"prod-api-0596\",\n      \"status\": \"critical\",\n      \"cpu\": 95,\n      \"memory\": 26,\n      \"disk\": 42,\n      \"network\": 64,\n      \"uptime\": 1266580\n    },\n    {\n      \"id\": \"host-597\",\n      \"name\": \"prod-database-0597\",\n      \"status\": \"critical\",\n      \"cpu\": 2,\n      \"memory\": 9,\n      \"disk\": 23,\n      \"network\": 83,\n      \"uptime\": 3786985\n    },\n    {\n      \"id\": \"host-598\",\n      \"name\": \"prod-cache-0598\",\n      \"status\": \"critical\",\n      \"cpu\": 21,\n      \"memory\": 72,\n      \"disk\": 97,\n      \"network\": 32,\n      \"uptime\": 9697619\n    },\n    {\n      \"id\": \"host-599\",\n      \"name\": \"prod-worker-0599\",\n      \"status\": \"critical\",\n      \"cpu\": 67,\n      \"memory\": 4,\n      \"disk\": 60,\n      \"network\": 95,\n      \"uptime\": 2899685\n    },\n    {\n      \"id\": \"host-600\",\n      \"name\": \"prod-queue-0600\",\n      \"status\": \"critical\",\n      \"cpu\": 70,\n      \"memory\": 0,\n      \"disk\": 87,\n      \"network\": 49,\n      \"uptime\": 6315520\n    },\n    {\n      \"id\": \"host-601\",\n      \"name\": \"prod-web-0601\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 8,\n      \"disk\": 98,\n      \"network\": 11,\n      \"uptime\": 4312253\n    },\n    {\n      \"id\": \"host-602\",\n      \"name\": \"prod-api-0602\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 82,\n      \"disk\": 89,\n      \"network\": 62,\n      \"uptime\": 9426986\n    },\n    {\n      \"id\": \"host-603\",\n      \"name\": \"prod-database-0603\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 5,\n      \"disk\": 89,\n      \"network\": 29,\n      \"uptime\": 6980381\n    },\n    {\n      \"id\": \"host-604\",\n      \"name\": \"prod-cache-0604\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 38,\n      \"disk\": 50,\n      \"network\": 32,\n      \"uptime\": 3431257\n    },\n    {\n      \"id\": \"host-605\",\n      \"name\": \"prod-worker-0605\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 35,\n      \"disk\": 37,\n      \"network\": 88,\n      \"uptime\": 7508331\n    },\n    {\n      \"id\": \"host-606\",\n      \"name\": \"prod-queue-0606\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 13,\n      \"disk\": 90,\n      \"network\": 51,\n      \"uptime\": 3685971\n    },\n    {\n      \"id\": \"host-607\",\n      \"name\": \"prod-web-0607\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 53,\n      \"disk\": 40,\n      \"network\": 90,\n      \"uptime\": 3517861\n    },\n    {\n      \"id\": \"host-608\",\n      \"name\": \"prod-api-0608\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 55,\n      \"disk\": 59,\n      \"network\": 0,\n      \"uptime\": 8833274\n    },\n    {\n      \"id\": \"host-609\",\n      \"name\": \"prod-database-0609\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 77,\n      \"disk\": 20,\n      \"network\": 59,\n      \"uptime\": 3365390\n    },\n    {\n      \"id\": \"host-610\",\n      \"name\": \"prod-cache-0610\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 50,\n      \"disk\": 31,\n      \"network\": 34,\n      \"uptime\": 1258418\n    },\n    {\n      \"id\": \"host-611\",\n      \"name\": \"prod-worker-0611\",\n      \"status\": \"healthy\",\n      \"cpu\": 25,\n      \"memory\": 81,\n      \"disk\": 85,\n      \"network\": 16,\n      \"uptime\": 2025719\n    },\n    {\n      \"id\": \"host-612\",\n      \"name\": \"prod-queue-0612\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 9,\n      \"disk\": 62,\n      \"network\": 60,\n      \"uptime\": 5581816\n    },\n    {\n      \"id\": \"host-613\",\n      \"name\": \"prod-web-0613\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 82,\n      \"disk\": 77,\n      \"network\": 82,\n      \"uptime\": 8504717\n    },\n    {\n      \"id\": \"host-614\",\n      \"name\": \"prod-api-0614\",\n      \"status\": \"healthy\",\n      \"cpu\": 95,\n      \"memory\": 71,\n      \"disk\": 3,\n      \"network\": 89,\n      \"uptime\": 3841716\n    },\n    {\n      \"id\": \"host-615\",\n      \"name\": \"prod-database-0615\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 50,\n      \"disk\": 17,\n      \"network\": 8,\n      \"uptime\": 9730027\n    },\n    {\n      \"id\": \"host-616\",\n      \"name\": \"prod-cache-0616\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 87,\n      \"disk\": 54,\n      \"network\": 26,\n      \"uptime\": 1410493\n    },\n    {\n      \"id\": \"host-617\",\n      \"name\": \"prod-worker-0617\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 15,\n      \"disk\": 78,\n      \"network\": 64,\n      \"uptime\": 3956979\n    },\n    {\n      \"id\": \"host-618\",\n      \"name\": \"prod-queue-0618\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 18,\n      \"disk\": 93,\n      \"network\": 61,\n      \"uptime\": 8507411\n    },\n    {\n      \"id\": \"host-619\",\n      \"name\": \"prod-web-0619\",\n      \"status\": \"healthy\",\n      \"cpu\": 92,\n      \"memory\": 18,\n      \"disk\": 19,\n      \"network\": 5,\n      \"uptime\": 6575230\n    },\n    {\n      \"id\": \"host-620\",\n      \"name\": \"prod-api-0620\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 17,\n      \"disk\": 26,\n      \"network\": 35,\n      \"uptime\": 1309440\n    },\n    {\n      \"id\": \"host-621\",\n      \"name\": \"prod-database-0621\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 87,\n      \"disk\": 31,\n      \"network\": 19,\n      \"uptime\": 8448233\n    },\n    {\n      \"id\": \"host-622\",\n      \"name\": \"prod-cache-0622\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 9,\n      \"disk\": 82,\n      \"network\": 39,\n      \"uptime\": 8381025\n    },\n    {\n      \"id\": \"host-623\",\n      \"name\": \"prod-worker-0623\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 16,\n      \"disk\": 42,\n      \"network\": 52,\n      \"uptime\": 7382698\n    },\n    {\n      \"id\": \"host-624\",\n      \"name\": \"prod-queue-0624\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 67,\n      \"disk\": 100,\n      \"network\": 59,\n      \"uptime\": 6603404\n    },\n    {\n      \"id\": \"host-625\",\n      \"name\": \"prod-web-0625\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 15,\n      \"disk\": 40,\n      \"network\": 81,\n      \"uptime\": 9857355\n    },\n    {\n      \"id\": \"host-626\",\n      \"name\": \"prod-api-0626\",\n      \"status\": \"healthy\",\n      \"cpu\": 100,\n      \"memory\": 72,\n      \"disk\": 56,\n      \"network\": 74,\n      \"uptime\": 4774526\n    },\n    {\n      \"id\": \"host-627\",\n      \"name\": \"prod-database-0627\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 85,\n      \"disk\": 77,\n      \"network\": 97,\n      \"uptime\": 2696271\n    },\n    {\n      \"id\": \"host-628\",\n      \"name\": \"prod-cache-0628\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 70,\n      \"disk\": 51,\n      \"network\": 63,\n      \"uptime\": 3400523\n    },\n    {\n      \"id\": \"host-629\",\n      \"name\": \"prod-worker-0629\",\n      \"status\": \"healthy\",\n      \"cpu\": 68,\n      \"memory\": 36,\n      \"disk\": 50,\n      \"network\": 92,\n      \"uptime\": 3673666\n    },\n    {\n      \"id\": \"host-630\",\n      \"name\": \"prod-queue-0630\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 30,\n      \"disk\": 10,\n      \"network\": 26,\n      \"uptime\": 1956917\n    },\n    {\n      \"id\": \"host-631\",\n      \"name\": \"prod-web-0631\",\n      \"status\": \"healthy\",\n      \"cpu\": 91,\n      \"memory\": 35,\n      \"disk\": 53,\n      \"network\": 97,\n      \"uptime\": 747898\n    },\n    {\n      \"id\": \"host-632\",\n      \"name\": \"prod-api-0632\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 86,\n      \"disk\": 32,\n      \"network\": 58,\n      \"uptime\": 1592714\n    },\n    {\n      \"id\": \"host-633\",\n      \"name\": \"prod-database-0633\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 85,\n      \"disk\": 46,\n      \"network\": 12,\n      \"uptime\": 1023022\n    },\n    {\n      \"id\": \"host-634\",\n      \"name\": \"prod-cache-0634\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 97,\n      \"disk\": 1,\n      \"network\": 78,\n      \"uptime\": 4708004\n    },\n    {\n      \"id\": \"host-635\",\n      \"name\": \"prod-worker-0635\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 95,\n      \"disk\": 31,\n      \"network\": 13,\n      \"uptime\": 7913563\n    },\n    {\n      \"id\": \"host-636\",\n      \"name\": \"prod-queue-0636\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 15,\n      \"disk\": 94,\n      \"network\": 20,\n      \"uptime\": 3792595\n    },\n    {\n      \"id\": \"host-637\",\n      \"name\": \"prod-web-0637\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 56,\n      \"disk\": 53,\n      \"network\": 53,\n      \"uptime\": 8538339\n    },\n    {\n      \"id\": \"host-638\",\n      \"name\": \"prod-api-0638\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 60,\n      \"disk\": 88,\n      \"network\": 33,\n      \"uptime\": 474570\n    },\n    {\n      \"id\": \"host-639\",\n      \"name\": \"prod-database-0639\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 36,\n      \"disk\": 64,\n      \"network\": 36,\n      \"uptime\": 1759195\n    },\n    {\n      \"id\": \"host-640\",\n      \"name\": \"prod-cache-0640\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 23,\n      \"disk\": 63,\n      \"network\": 45,\n      \"uptime\": 2232535\n    },\n    {\n      \"id\": \"host-641\",\n      \"name\": \"prod-worker-0641\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 70,\n      \"disk\": 68,\n      \"network\": 49,\n      \"uptime\": 6175767\n    },\n    {\n      \"id\": \"host-642\",\n      \"name\": \"prod-queue-0642\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 9,\n      \"disk\": 17,\n      \"network\": 10,\n      \"uptime\": 3143238\n    },\n    {\n      \"id\": \"host-643\",\n      \"name\": \"prod-web-0643\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 58,\n      \"disk\": 12,\n      \"network\": 57,\n      \"uptime\": 8315093\n    },\n    {\n      \"id\": \"host-644\",\n      \"name\": \"prod-api-0644\",\n      \"status\": \"healthy\",\n      \"cpu\": 75,\n      \"memory\": 39,\n      \"disk\": 4,\n      \"network\": 40,\n      \"uptime\": 112958\n    },\n    {\n      \"id\": \"host-645\",\n      \"name\": \"prod-database-0645\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 50,\n      \"disk\": 31,\n      \"network\": 34,\n      \"uptime\": 1647945\n    },\n    {\n      \"id\": \"host-646\",\n      \"name\": \"prod-cache-0646\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 8,\n      \"disk\": 34,\n      \"network\": 28,\n      \"uptime\": 6575703\n    },\n    {\n      \"id\": \"host-647\",\n      \"name\": \"prod-worker-0647\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 87,\n      \"disk\": 84,\n      \"network\": 45,\n      \"uptime\": 2431954\n    },\n    {\n      \"id\": \"host-648\",\n      \"name\": \"prod-queue-0648\",\n      \"status\": \"healthy\",\n      \"cpu\": 85,\n      \"memory\": 24,\n      \"disk\": 85,\n      \"network\": 8,\n      \"uptime\": 5925315\n    },\n    {\n      \"id\": \"host-649\",\n      \"name\": \"prod-web-0649\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 21,\n      \"disk\": 44,\n      \"network\": 16,\n      \"uptime\": 1071528\n    },\n    {\n      \"id\": \"host-650\",\n      \"name\": \"prod-api-0650\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 71,\n      \"disk\": 69,\n      \"network\": 81,\n      \"uptime\": 3183484\n    },\n    {\n      \"id\": \"host-651\",\n      \"name\": \"prod-database-0651\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 93,\n      \"disk\": 1,\n      \"network\": 67,\n      \"uptime\": 7268902\n    },\n    {\n      \"id\": \"host-652\",\n      \"name\": \"prod-cache-0652\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 34,\n      \"disk\": 40,\n      \"network\": 8,\n      \"uptime\": 1278828\n    },\n    {\n      \"id\": \"host-653\",\n      \"name\": \"prod-worker-0653\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 98,\n      \"disk\": 90,\n      \"network\": 2,\n      \"uptime\": 2522243\n    },\n    {\n      \"id\": \"host-654\",\n      \"name\": \"prod-queue-0654\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 94,\n      \"disk\": 43,\n      \"network\": 25,\n      \"uptime\": 1027263\n    },\n    {\n      \"id\": \"host-655\",\n      \"name\": \"prod-web-0655\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 8,\n      \"disk\": 35,\n      \"network\": 3,\n      \"uptime\": 1091234\n    },\n    {\n      \"id\": \"host-656\",\n      \"name\": \"prod-api-0656\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 28,\n      \"disk\": 3,\n      \"network\": 54,\n      \"uptime\": 5984856\n    },\n    {\n      \"id\": \"host-657\",\n      \"name\": \"prod-database-0657\",\n      \"status\": \"healthy\",\n      \"cpu\": 69,\n      \"memory\": 82,\n      \"disk\": 76,\n      \"network\": 97,\n      \"uptime\": 3689166\n    },\n    {\n      \"id\": \"host-658\",\n      \"name\": \"prod-cache-0658\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 40,\n      \"disk\": 97,\n      \"network\": 4,\n      \"uptime\": 7339990\n    },\n    {\n      \"id\": \"host-659\",\n      \"name\": \"prod-worker-0659\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 52,\n      \"disk\": 15,\n      \"network\": 62,\n      \"uptime\": 3122688\n    },\n    {\n      \"id\": \"host-660\",\n      \"name\": \"prod-queue-0660\",\n      \"status\": \"healthy\",\n      \"cpu\": 85,\n      \"memory\": 3,\n      \"disk\": 96,\n      \"network\": 27,\n      \"uptime\": 8798072\n    },\n    {\n      \"id\": \"host-661\",\n      \"name\": \"prod-web-0661\",\n      \"status\": \"warning\",\n      \"cpu\": 4,\n      \"memory\": 33,\n      \"disk\": 9,\n      \"network\": 73,\n      \"uptime\": 7336247\n    },\n    {\n      \"id\": \"host-662\",\n      \"name\": \"prod-api-0662\",\n      \"status\": \"warning\",\n      \"cpu\": 50,\n      \"memory\": 77,\n      \"disk\": 6,\n      \"network\": 36,\n      \"uptime\": 9046117\n    },\n    {\n      \"id\": \"host-663\",\n      \"name\": \"prod-database-0663\",\n      \"status\": \"warning\",\n      \"cpu\": 16,\n      \"memory\": 85,\n      \"disk\": 72,\n      \"network\": 52,\n      \"uptime\": 6094244\n    },\n    {\n      \"id\": \"host-664\",\n      \"name\": \"prod-cache-0664\",\n      \"status\": \"warning\",\n      \"cpu\": 44,\n      \"memory\": 62,\n      \"disk\": 4,\n      \"network\": 66,\n      \"uptime\": 3817502\n    },\n    {\n      \"id\": \"host-665\",\n      \"name\": \"prod-worker-0665\",\n      \"status\": \"warning\",\n      \"cpu\": 23,\n      \"memory\": 3,\n      \"disk\": 74,\n      \"network\": 56,\n      \"uptime\": 206579\n    },\n    {\n      \"id\": \"host-666\",\n      \"name\": \"prod-queue-0666\",\n      \"status\": \"warning\",\n      \"cpu\": 13,\n      \"memory\": 70,\n      \"disk\": 53,\n      \"network\": 85,\n      \"uptime\": 73350\n    },\n    {\n      \"id\": \"host-667\",\n      \"name\": \"prod-web-0667\",\n      \"status\": \"warning\",\n      \"cpu\": 51,\n      \"memory\": 20,\n      \"disk\": 52,\n      \"network\": 9,\n      \"uptime\": 6628901\n    },\n    {\n      \"id\": \"host-668\",\n      \"name\": \"prod-api-0668\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 93,\n      \"disk\": 68,\n      \"network\": 57,\n      \"uptime\": 349187\n    },\n    {\n      \"id\": \"host-669\",\n      \"name\": \"prod-database-0669\",\n      \"status\": \"warning\",\n      \"cpu\": 60,\n      \"memory\": 77,\n      \"disk\": 73,\n      \"network\": 26,\n      \"uptime\": 3547388\n    },\n    {\n      \"id\": \"host-670\",\n      \"name\": \"prod-cache-0670\",\n      \"status\": \"warning\",\n      \"cpu\": 66,\n      \"memory\": 77,\n      \"disk\": 99,\n      \"network\": 17,\n      \"uptime\": 6376410\n    },\n    {\n      \"id\": \"host-671\",\n      \"name\": \"prod-worker-0671\",\n      \"status\": \"warning\",\n      \"cpu\": 66,\n      \"memory\": 57,\n      \"disk\": 51,\n      \"network\": 16,\n      \"uptime\": 2772109\n    },\n    {\n      \"id\": \"host-672\",\n      \"name\": \"prod-queue-0672\",\n      \"status\": \"warning\",\n      \"cpu\": 58,\n      \"memory\": 88,\n      \"disk\": 0,\n      \"network\": 99,\n      \"uptime\": 1792493\n    },\n    {\n      \"id\": \"host-673\",\n      \"name\": \"prod-web-0673\",\n      \"status\": \"warning\",\n      \"cpu\": 59,\n      \"memory\": 15,\n      \"disk\": 57,\n      \"network\": 54,\n      \"uptime\": 9883357\n    },\n    {\n      \"id\": \"host-674\",\n      \"name\": \"prod-api-0674\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 31,\n      \"disk\": 71,\n      \"network\": 27,\n      \"uptime\": 1180165\n    },\n    {\n      \"id\": \"host-675\",\n      \"name\": \"prod-database-0675\",\n      \"status\": \"warning\",\n      \"cpu\": 36,\n      \"memory\": 52,\n      \"disk\": 99,\n      \"network\": 83,\n      \"uptime\": 7987973\n    },\n    {\n      \"id\": \"host-676\",\n      \"name\": \"prod-cache-0676\",\n      \"status\": \"warning\",\n      \"cpu\": 33,\n      \"memory\": 87,\n      \"disk\": 57,\n      \"network\": 54,\n      \"uptime\": 7766597\n    },\n    {\n      \"id\": \"host-677\",\n      \"name\": \"prod-worker-0677\",\n      \"status\": \"warning\",\n      \"cpu\": 54,\n      \"memory\": 78,\n      \"disk\": 90,\n      \"network\": 86,\n      \"uptime\": 8681498\n    },\n    {\n      \"id\": \"host-678\",\n      \"name\": \"prod-queue-0678\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 41,\n      \"disk\": 13,\n      \"network\": 56,\n      \"uptime\": 5380114\n    },\n    {\n      \"id\": \"host-679\",\n      \"name\": \"prod-web-0679\",\n      \"status\": \"warning\",\n      \"cpu\": 13,\n      \"memory\": 18,\n      \"disk\": 4,\n      \"network\": 2,\n      \"uptime\": 9321290\n    },\n    {\n      \"id\": \"host-680\",\n      \"name\": \"prod-api-0680\",\n      \"status\": \"warning\",\n      \"cpu\": 69,\n      \"memory\": 36,\n      \"disk\": 42,\n      \"network\": 63,\n      \"uptime\": 770097\n    },\n    {\n      \"id\": \"host-681\",\n      \"name\": \"prod-database-0681\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 13,\n      \"disk\": 57,\n      \"network\": 51,\n      \"uptime\": 5034969\n    },\n    {\n      \"id\": \"host-682\",\n      \"name\": \"prod-cache-0682\",\n      \"status\": \"warning\",\n      \"cpu\": 51,\n      \"memory\": 18,\n      \"disk\": 83,\n      \"network\": 9,\n      \"uptime\": 9869644\n    },\n    {\n      \"id\": \"host-683\",\n      \"name\": \"prod-worker-0683\",\n      \"status\": \"warning\",\n      \"cpu\": 98,\n      \"memory\": 49,\n      \"disk\": 29,\n      \"network\": 57,\n      \"uptime\": 1274355\n    },\n    {\n      \"id\": \"host-684\",\n      \"name\": \"prod-queue-0684\",\n      \"status\": \"warning\",\n      \"cpu\": 75,\n      \"memory\": 5,\n      \"disk\": 21,\n      \"network\": 66,\n      \"uptime\": 6043366\n    },\n    {\n      \"id\": \"host-685\",\n      \"name\": \"prod-web-0685\",\n      \"status\": \"warning\",\n      \"cpu\": 93,\n      \"memory\": 27,\n      \"disk\": 15,\n      \"network\": 50,\n      \"uptime\": 8791599\n    },\n    {\n      \"id\": \"host-686\",\n      \"name\": \"prod-api-0686\",\n      \"status\": \"critical\",\n      \"cpu\": 65,\n      \"memory\": 97,\n      \"disk\": 82,\n      \"network\": 3,\n      \"uptime\": 7957675\n    },\n    {\n      \"id\": \"host-687\",\n      \"name\": \"prod-database-0687\",\n      \"status\": \"critical\",\n      \"cpu\": 70,\n      \"memory\": 78,\n      \"disk\": 11,\n      \"network\": 26,\n      \"uptime\": 6272291\n    },\n    {\n      \"id\": \"host-688\",\n      \"name\": \"prod-cache-0688\",\n      \"status\": \"critical\",\n      \"cpu\": 22,\n      \"memory\": 50,\n      \"disk\": 65,\n      \"network\": 99,\n      \"uptime\": 6554142\n    },\n    {\n      \"id\": \"host-689\",\n      \"name\": \"prod-worker-0689\",\n      \"status\": \"critical\",\n      \"cpu\": 67,\n      \"memory\": 19,\n      \"disk\": 53,\n      \"network\": 40,\n      \"uptime\": 2778911\n    },\n    {\n      \"id\": \"host-690\",\n      \"name\": \"prod-queue-0690\",\n      \"status\": \"critical\",\n      \"cpu\": 84,\n      \"memory\": 3,\n      \"disk\": 33,\n      \"network\": 67,\n      \"uptime\": 9489037\n    },\n    {\n      \"id\": \"host-691\",\n      \"name\": \"prod-web-0691\",\n      \"status\": \"critical\",\n      \"cpu\": 69,\n      \"memory\": 15,\n      \"disk\": 11,\n      \"network\": 68,\n      \"uptime\": 706320\n    },\n    {\n      \"id\": \"host-692\",\n      \"name\": \"prod-api-0692\",\n      \"status\": \"critical\",\n      \"cpu\": 85,\n      \"memory\": 14,\n      \"disk\": 99,\n      \"network\": 24,\n      \"uptime\": 5256851\n    },\n    {\n      \"id\": \"host-693\",\n      \"name\": \"prod-database-0693\",\n      \"status\": \"critical\",\n      \"cpu\": 66,\n      \"memory\": 29,\n      \"disk\": 52,\n      \"network\": 17,\n      \"uptime\": 437902\n    },\n    {\n      \"id\": \"host-694\",\n      \"name\": \"prod-cache-0694\",\n      \"status\": \"critical\",\n      \"cpu\": 82,\n      \"memory\": 95,\n      \"disk\": 59,\n      \"network\": 90,\n      \"uptime\": 5852604\n    },\n    {\n      \"id\": \"host-695\",\n      \"name\": \"prod-worker-0695\",\n      \"status\": \"critical\",\n      \"cpu\": 52,\n      \"memory\": 21,\n      \"disk\": 94,\n      \"network\": 41,\n      \"uptime\": 1402560\n    },\n    {\n      \"id\": \"host-696\",\n      \"name\": \"prod-queue-0696\",\n      \"status\": \"critical\",\n      \"cpu\": 79,\n      \"memory\": 16,\n      \"disk\": 21,\n      \"network\": 54,\n      \"uptime\": 6108382\n    },\n    {\n      \"id\": \"host-697\",\n      \"name\": \"prod-web-0697\",\n      \"status\": \"critical\",\n      \"cpu\": 91,\n      \"memory\": 68,\n      \"disk\": 21,\n      \"network\": 92,\n      \"uptime\": 2309892\n    },\n    {\n      \"id\": \"host-698\",\n      \"name\": \"prod-api-0698\",\n      \"status\": \"critical\",\n      \"cpu\": 87,\n      \"memory\": 57,\n      \"disk\": 83,\n      \"network\": 56,\n      \"uptime\": 8195624\n    },\n    {\n      \"id\": \"host-699\",\n      \"name\": \"prod-database-0699\",\n      \"status\": \"critical\",\n      \"cpu\": 98,\n      \"memory\": 53,\n      \"disk\": 53,\n      \"network\": 38,\n      \"uptime\": 8305850\n    },\n    {\n      \"id\": \"host-700\",\n      \"name\": \"prod-cache-0700\",\n      \"status\": \"critical\",\n      \"cpu\": 13,\n      \"memory\": 38,\n      \"disk\": 81,\n      \"network\": 26,\n      \"uptime\": 1905489\n    },\n    {\n      \"id\": \"host-701\",\n      \"name\": \"prod-worker-0701\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 56,\n      \"disk\": 99,\n      \"network\": 52,\n      \"uptime\": 5429629\n    },\n    {\n      \"id\": \"host-702\",\n      \"name\": \"prod-queue-0702\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 60,\n      \"disk\": 96,\n      \"network\": 5,\n      \"uptime\": 1203863\n    },\n    {\n      \"id\": \"host-703\",\n      \"name\": \"prod-web-0703\",\n      \"status\": \"healthy\",\n      \"cpu\": 95,\n      \"memory\": 35,\n      \"disk\": 34,\n      \"network\": 27,\n      \"uptime\": 7299877\n    },\n    {\n      \"id\": \"host-704\",\n      \"name\": \"prod-api-0704\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 16,\n      \"disk\": 92,\n      \"network\": 73,\n      \"uptime\": 8711650\n    },\n    {\n      \"id\": \"host-705\",\n      \"name\": \"prod-database-0705\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 38,\n      \"disk\": 68,\n      \"network\": 7,\n      \"uptime\": 6194820\n    },\n    {\n      \"id\": \"host-706\",\n      \"name\": \"prod-cache-0706\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 15,\n      \"disk\": 44,\n      \"network\": 44,\n      \"uptime\": 9013842\n    },\n    {\n      \"id\": \"host-707\",\n      \"name\": \"prod-worker-0707\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 23,\n      \"disk\": 7,\n      \"network\": 84,\n      \"uptime\": 1940448\n    },\n    {\n      \"id\": \"host-708\",\n      \"name\": \"prod-queue-0708\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 19,\n      \"disk\": 3,\n      \"network\": 16,\n      \"uptime\": 6125758\n    },\n    {\n      \"id\": \"host-709\",\n      \"name\": \"prod-web-0709\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 50,\n      \"disk\": 2,\n      \"network\": 87,\n      \"uptime\": 7347587\n    },\n    {\n      \"id\": \"host-710\",\n      \"name\": \"prod-api-0710\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 45,\n      \"disk\": 74,\n      \"network\": 84,\n      \"uptime\": 2458947\n    },\n    {\n      \"id\": \"host-711\",\n      \"name\": \"prod-database-0711\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 81,\n      \"disk\": 92,\n      \"network\": 67,\n      \"uptime\": 9603503\n    },\n    {\n      \"id\": \"host-712\",\n      \"name\": \"prod-cache-0712\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 26,\n      \"disk\": 35,\n      \"network\": 85,\n      \"uptime\": 8184369\n    },\n    {\n      \"id\": \"host-713\",\n      \"name\": \"prod-worker-0713\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 94,\n      \"disk\": 28,\n      \"network\": 64,\n      \"uptime\": 7793597\n    },\n    {\n      \"id\": \"host-714\",\n      \"name\": \"prod-queue-0714\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 47,\n      \"disk\": 83,\n      \"network\": 28,\n      \"uptime\": 2722923\n    },\n    {\n      \"id\": \"host-715\",\n      \"name\": \"prod-web-0715\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 71,\n      \"disk\": 93,\n      \"network\": 96,\n      \"uptime\": 6709297\n    },\n    {\n      \"id\": \"host-716\",\n      \"name\": \"prod-api-0716\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 41,\n      \"disk\": 46,\n      \"network\": 76,\n      \"uptime\": 2150580\n    },\n    {\n      \"id\": \"host-717\",\n      \"name\": \"prod-database-0717\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 68,\n      \"disk\": 22,\n      \"network\": 43,\n      \"uptime\": 1949732\n    },\n    {\n      \"id\": \"host-718\",\n      \"name\": \"prod-cache-0718\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 61,\n      \"disk\": 15,\n      \"network\": 64,\n      \"uptime\": 4987121\n    },\n    {\n      \"id\": \"host-719\",\n      \"name\": \"prod-worker-0719\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 6,\n      \"disk\": 68,\n      \"network\": 47,\n      \"uptime\": 3904002\n    },\n    {\n      \"id\": \"host-720\",\n      \"name\": \"prod-queue-0720\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 22,\n      \"disk\": 13,\n      \"network\": 18,\n      \"uptime\": 6340745\n    },\n    {\n      \"id\": \"host-721\",\n      \"name\": \"prod-web-0721\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 3,\n      \"disk\": 66,\n      \"network\": 51,\n      \"uptime\": 2066444\n    },\n    {\n      \"id\": \"host-722\",\n      \"name\": \"prod-api-0722\",\n      \"status\": \"healthy\",\n      \"cpu\": 12,\n      \"memory\": 91,\n      \"disk\": 63,\n      \"network\": 89,\n      \"uptime\": 5065496\n    },\n    {\n      \"id\": \"host-723\",\n      \"name\": \"prod-database-0723\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 92,\n      \"disk\": 24,\n      \"network\": 51,\n      \"uptime\": 2397454\n    },\n    {\n      \"id\": \"host-724\",\n      \"name\": \"prod-cache-0724\",\n      \"status\": \"healthy\",\n      \"cpu\": 91,\n      \"memory\": 95,\n      \"disk\": 22,\n      \"network\": 64,\n      \"uptime\": 4929283\n    },\n    {\n      \"id\": \"host-725\",\n      \"name\": \"prod-worker-0725\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 39,\n      \"disk\": 17,\n      \"network\": 62,\n      \"uptime\": 9625088\n    },\n    {\n      \"id\": \"host-726\",\n      \"name\": \"prod-queue-0726\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 7,\n      \"disk\": 95,\n      \"network\": 71,\n      \"uptime\": 2790912\n    },\n    {\n      \"id\": \"host-727\",\n      \"name\": \"prod-web-0727\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 57,\n      \"disk\": 4,\n      \"network\": 21,\n      \"uptime\": 853807\n    },\n    {\n      \"id\": \"host-728\",\n      \"name\": \"prod-api-0728\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 7,\n      \"disk\": 67,\n      \"network\": 69,\n      \"uptime\": 6637222\n    },\n    {\n      \"id\": \"host-729\",\n      \"name\": \"prod-database-0729\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 6,\n      \"disk\": 68,\n      \"network\": 53,\n      \"uptime\": 347600\n    },\n    {\n      \"id\": \"host-730\",\n      \"name\": \"prod-cache-0730\",\n      \"status\": \"healthy\",\n      \"cpu\": 41,\n      \"memory\": 89,\n      \"disk\": 18,\n      \"network\": 75,\n      \"uptime\": 6728284\n    },\n    {\n      \"id\": \"host-731\",\n      \"name\": \"prod-worker-0731\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 32,\n      \"disk\": 8,\n      \"network\": 46,\n      \"uptime\": 9523446\n    },\n    {\n      \"id\": \"host-732\",\n      \"name\": \"prod-queue-0732\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 78,\n      \"disk\": 52,\n      \"network\": 1,\n      \"uptime\": 9793249\n    },\n    {\n      \"id\": \"host-733\",\n      \"name\": \"prod-web-0733\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 32,\n      \"disk\": 99,\n      \"network\": 44,\n      \"uptime\": 4187267\n    },\n    {\n      \"id\": \"host-734\",\n      \"name\": \"prod-api-0734\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 95,\n      \"disk\": 97,\n      \"network\": 49,\n      \"uptime\": 1243665\n    },\n    {\n      \"id\": \"host-735\",\n      \"name\": \"prod-database-0735\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 57,\n      \"disk\": 53,\n      \"network\": 63,\n      \"uptime\": 8344488\n    },\n    {\n      \"id\": \"host-736\",\n      \"name\": \"prod-cache-0736\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 91,\n      \"disk\": 34,\n      \"network\": 64,\n      \"uptime\": 7736120\n    },\n    {\n      \"id\": \"host-737\",\n      \"name\": \"prod-worker-0737\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 39,\n      \"disk\": 76,\n      \"network\": 71,\n      \"uptime\": 4370126\n    },\n    {\n      \"id\": \"host-738\",\n      \"name\": \"prod-queue-0738\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 42,\n      \"disk\": 80,\n      \"network\": 40,\n      \"uptime\": 7612722\n    },\n    {\n      \"id\": \"host-739\",\n      \"name\": \"prod-web-0739\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 33,\n      \"disk\": 98,\n      \"network\": 1,\n      \"uptime\": 6456678\n    },\n    {\n      \"id\": \"host-740\",\n      \"name\": \"prod-api-0740\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 7,\n      \"disk\": 48,\n      \"network\": 63,\n      \"uptime\": 8354849\n    },\n    {\n      \"id\": \"host-741\",\n      \"name\": \"prod-database-0741\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 67,\n      \"disk\": 7,\n      \"network\": 20,\n      \"uptime\": 9779071\n    },\n    {\n      \"id\": \"host-742\",\n      \"name\": \"prod-cache-0742\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 89,\n      \"disk\": 79,\n      \"network\": 95,\n      \"uptime\": 4232297\n    },\n    {\n      \"id\": \"host-743\",\n      \"name\": \"prod-worker-0743\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 52,\n      \"disk\": 62,\n      \"network\": 30,\n      \"uptime\": 5960972\n    },\n    {\n      \"id\": \"host-744\",\n      \"name\": \"prod-queue-0744\",\n      \"status\": \"healthy\",\n      \"cpu\": 92,\n      \"memory\": 74,\n      \"disk\": 85,\n      \"network\": 79,\n      \"uptime\": 1228197\n    },\n    {\n      \"id\": \"host-745\",\n      \"name\": \"prod-web-0745\",\n      \"status\": \"healthy\",\n      \"cpu\": 79,\n      \"memory\": 13,\n      \"disk\": 46,\n      \"network\": 20,\n      \"uptime\": 7907033\n    },\n    {\n      \"id\": \"host-746\",\n      \"name\": \"prod-api-0746\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 58,\n      \"disk\": 29,\n      \"network\": 88,\n      \"uptime\": 335201\n    },\n    {\n      \"id\": \"host-747\",\n      \"name\": \"prod-database-0747\",\n      \"status\": \"healthy\",\n      \"cpu\": 77,\n      \"memory\": 27,\n      \"disk\": 60,\n      \"network\": 58,\n      \"uptime\": 7977459\n    },\n    {\n      \"id\": \"host-748\",\n      \"name\": \"prod-cache-0748\",\n      \"status\": \"healthy\",\n      \"cpu\": 58,\n      \"memory\": 32,\n      \"disk\": 28,\n      \"network\": 99,\n      \"uptime\": 345272\n    },\n    {\n      \"id\": \"host-749\",\n      \"name\": \"prod-worker-0749\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 53,\n      \"disk\": 6,\n      \"network\": 84,\n      \"uptime\": 3603801\n    },\n    {\n      \"id\": \"host-750\",\n      \"name\": \"prod-queue-0750\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 4,\n      \"disk\": 11,\n      \"network\": 69,\n      \"uptime\": 8150059\n    },\n    {\n      \"id\": \"host-751\",\n      \"name\": \"prod-web-0751\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 93,\n      \"disk\": 57,\n      \"network\": 22,\n      \"uptime\": 3615852\n    },\n    {\n      \"id\": \"host-752\",\n      \"name\": \"prod-api-0752\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 54,\n      \"disk\": 4,\n      \"network\": 84,\n      \"uptime\": 8323978\n    },\n    {\n      \"id\": \"host-753\",\n      \"name\": \"prod-database-0753\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 16,\n      \"disk\": 51,\n      \"network\": 29,\n      \"uptime\": 7662893\n    },\n    {\n      \"id\": \"host-754\",\n      \"name\": \"prod-cache-0754\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 30,\n      \"disk\": 45,\n      \"network\": 92,\n      \"uptime\": 1672358\n    },\n    {\n      \"id\": \"host-755\",\n      \"name\": \"prod-worker-0755\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 5,\n      \"disk\": 68,\n      \"network\": 97,\n      \"uptime\": 3439262\n    },\n    {\n      \"id\": \"host-756\",\n      \"name\": \"prod-queue-0756\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 41,\n      \"disk\": 65,\n      \"network\": 91,\n      \"uptime\": 2092135\n    },\n    {\n      \"id\": \"host-757\",\n      \"name\": \"prod-web-0757\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 68,\n      \"disk\": 33,\n      \"network\": 25,\n      \"uptime\": 6397716\n    },\n    {\n      \"id\": \"host-758\",\n      \"name\": \"prod-api-0758\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 65,\n      \"disk\": 19,\n      \"network\": 13,\n      \"uptime\": 5818389\n    },\n    {\n      \"id\": \"host-759\",\n      \"name\": \"prod-database-0759\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 39,\n      \"disk\": 75,\n      \"network\": 17,\n      \"uptime\": 4548761\n    },\n    {\n      \"id\": \"host-760\",\n      \"name\": \"prod-cache-0760\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 66,\n      \"disk\": 95,\n      \"network\": 58,\n      \"uptime\": 3715400\n    },\n    {\n      \"id\": \"host-761\",\n      \"name\": \"prod-worker-0761\",\n      \"status\": \"warning\",\n      \"cpu\": 65,\n      \"memory\": 92,\n      \"disk\": 26,\n      \"network\": 49,\n      \"uptime\": 2787102\n    },\n    {\n      \"id\": \"host-762\",\n      \"name\": \"prod-queue-0762\",\n      \"status\": \"warning\",\n      \"cpu\": 67,\n      \"memory\": 91,\n      \"disk\": 64,\n      \"network\": 30,\n      \"uptime\": 912711\n    },\n    {\n      \"id\": \"host-763\",\n      \"name\": \"prod-web-0763\",\n      \"status\": \"warning\",\n      \"cpu\": 18,\n      \"memory\": 24,\n      \"disk\": 44,\n      \"network\": 37,\n      \"uptime\": 3690239\n    },\n    {\n      \"id\": \"host-764\",\n      \"name\": \"prod-api-0764\",\n      \"status\": \"warning\",\n      \"cpu\": 49,\n      \"memory\": 75,\n      \"disk\": 74,\n      \"network\": 6,\n      \"uptime\": 8569031\n    },\n    {\n      \"id\": \"host-765\",\n      \"name\": \"prod-database-0765\",\n      \"status\": \"warning\",\n      \"cpu\": 31,\n      \"memory\": 1,\n      \"disk\": 47,\n      \"network\": 75,\n      \"uptime\": 3607448\n    },\n    {\n      \"id\": \"host-766\",\n      \"name\": \"prod-cache-0766\",\n      \"status\": \"warning\",\n      \"cpu\": 3,\n      \"memory\": 51,\n      \"disk\": 22,\n      \"network\": 97,\n      \"uptime\": 7139680\n    },\n    {\n      \"id\": \"host-767\",\n      \"name\": \"prod-worker-0767\",\n      \"status\": \"warning\",\n      \"cpu\": 9,\n      \"memory\": 99,\n      \"disk\": 25,\n      \"network\": 44,\n      \"uptime\": 3705431\n    },\n    {\n      \"id\": \"host-768\",\n      \"name\": \"prod-queue-0768\",\n      \"status\": \"warning\",\n      \"cpu\": 63,\n      \"memory\": 7,\n      \"disk\": 32,\n      \"network\": 83,\n      \"uptime\": 2462407\n    },\n    {\n      \"id\": \"host-769\",\n      \"name\": \"prod-web-0769\",\n      \"status\": \"warning\",\n      \"cpu\": 21,\n      \"memory\": 50,\n      \"disk\": 38,\n      \"network\": 29,\n      \"uptime\": 4766655\n    },\n    {\n      \"id\": \"host-770\",\n      \"name\": \"prod-api-0770\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 0,\n      \"disk\": 5,\n      \"network\": 21,\n      \"uptime\": 5936329\n    },\n    {\n      \"id\": \"host-771\",\n      \"name\": \"prod-database-0771\",\n      \"status\": \"warning\",\n      \"cpu\": 44,\n      \"memory\": 67,\n      \"disk\": 19,\n      \"network\": 42,\n      \"uptime\": 4930651\n    },\n    {\n      \"id\": \"host-772\",\n      \"name\": \"prod-cache-0772\",\n      \"status\": \"warning\",\n      \"cpu\": 43,\n      \"memory\": 63,\n      \"disk\": 70,\n      \"network\": 50,\n      \"uptime\": 7765833\n    },\n    {\n      \"id\": \"host-773\",\n      \"name\": \"prod-worker-0773\",\n      \"status\": \"warning\",\n      \"cpu\": 73,\n      \"memory\": 92,\n      \"disk\": 48,\n      \"network\": 60,\n      \"uptime\": 8365332\n    },\n    {\n      \"id\": \"host-774\",\n      \"name\": \"prod-queue-0774\",\n      \"status\": \"warning\",\n      \"cpu\": 64,\n      \"memory\": 62,\n      \"disk\": 64,\n      \"network\": 74,\n      \"uptime\": 8193416\n    },\n    {\n      \"id\": \"host-775\",\n      \"name\": \"prod-web-0775\",\n      \"status\": \"warning\",\n      \"cpu\": 67,\n      \"memory\": 60,\n      \"disk\": 27,\n      \"network\": 43,\n      \"uptime\": 2509811\n    },\n    {\n      \"id\": \"host-776\",\n      \"name\": \"prod-api-0776\",\n      \"status\": \"warning\",\n      \"cpu\": 80,\n      \"memory\": 98,\n      \"disk\": 24,\n      \"network\": 29,\n      \"uptime\": 2890823\n    },\n    {\n      \"id\": \"host-777\",\n      \"name\": \"prod-database-0777\",\n      \"status\": \"warning\",\n      \"cpu\": 99,\n      \"memory\": 81,\n      \"disk\": 53,\n      \"network\": 41,\n      \"uptime\": 6503547\n    },\n    {\n      \"id\": \"host-778\",\n      \"name\": \"prod-cache-0778\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 61,\n      \"disk\": 95,\n      \"network\": 19,\n      \"uptime\": 3607391\n    },\n    {\n      \"id\": \"host-779\",\n      \"name\": \"prod-worker-0779\",\n      \"status\": \"warning\",\n      \"cpu\": 5,\n      \"memory\": 56,\n      \"disk\": 4,\n      \"network\": 5,\n      \"uptime\": 6134742\n    },\n    {\n      \"id\": \"host-780\",\n      \"name\": \"prod-queue-0780\",\n      \"status\": \"warning\",\n      \"cpu\": 20,\n      \"memory\": 64,\n      \"disk\": 59,\n      \"network\": 74,\n      \"uptime\": 1947708\n    },\n    {\n      \"id\": \"host-781\",\n      \"name\": \"prod-web-0781\",\n      \"status\": \"warning\",\n      \"cpu\": 86,\n      \"memory\": 27,\n      \"disk\": 37,\n      \"network\": 17,\n      \"uptime\": 6616983\n    },\n    {\n      \"id\": \"host-782\",\n      \"name\": \"prod-api-0782\",\n      \"status\": \"warning\",\n      \"cpu\": 77,\n      \"memory\": 97,\n      \"disk\": 34,\n      \"network\": 16,\n      \"uptime\": 7812710\n    },\n    {\n      \"id\": \"host-783\",\n      \"name\": \"prod-database-0783\",\n      \"status\": \"warning\",\n      \"cpu\": 29,\n      \"memory\": 90,\n      \"disk\": 85,\n      \"network\": 63,\n      \"uptime\": 5185448\n    },\n    {\n      \"id\": \"host-784\",\n      \"name\": \"prod-cache-0784\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 16,\n      \"disk\": 0,\n      \"network\": 85,\n      \"uptime\": 6985791\n    },\n    {\n      \"id\": \"host-785\",\n      \"name\": \"prod-worker-0785\",\n      \"status\": \"warning\",\n      \"cpu\": 42,\n      \"memory\": 50,\n      \"disk\": 31,\n      \"network\": 9,\n      \"uptime\": 3844675\n    },\n    {\n      \"id\": \"host-786\",\n      \"name\": \"prod-queue-0786\",\n      \"status\": \"critical\",\n      \"cpu\": 29,\n      \"memory\": 92,\n      \"disk\": 63,\n      \"network\": 38,\n      \"uptime\": 8334346\n    },\n    {\n      \"id\": \"host-787\",\n      \"name\": \"prod-web-0787\",\n      \"status\": \"critical\",\n      \"cpu\": 91,\n      \"memory\": 32,\n      \"disk\": 86,\n      \"network\": 50,\n      \"uptime\": 610562\n    },\n    {\n      \"id\": \"host-788\",\n      \"name\": \"prod-api-0788\",\n      \"status\": \"critical\",\n      \"cpu\": 39,\n      \"memory\": 46,\n      \"disk\": 43,\n      \"network\": 44,\n      \"uptime\": 4417496\n    },\n    {\n      \"id\": \"host-789\",\n      \"name\": \"prod-database-0789\",\n      \"status\": \"critical\",\n      \"cpu\": 90,\n      \"memory\": 26,\n      \"disk\": 59,\n      \"network\": 24,\n      \"uptime\": 4198461\n    },\n    {\n      \"id\": \"host-790\",\n      \"name\": \"prod-cache-0790\",\n      \"status\": \"critical\",\n      \"cpu\": 13,\n      \"memory\": 19,\n      \"disk\": 95,\n      \"network\": 49,\n      \"uptime\": 2159609\n    },\n    {\n      \"id\": \"host-791\",\n      \"name\": \"prod-worker-0791\",\n      \"status\": \"critical\",\n      \"cpu\": 19,\n      \"memory\": 6,\n      \"disk\": 86,\n      \"network\": 23,\n      \"uptime\": 8529186\n    },\n    {\n      \"id\": \"host-792\",\n      \"name\": \"prod-queue-0792\",\n      \"status\": \"critical\",\n      \"cpu\": 35,\n      \"memory\": 60,\n      \"disk\": 41,\n      \"network\": 55,\n      \"uptime\": 7874706\n    },\n    {\n      \"id\": \"host-793\",\n      \"name\": \"prod-web-0793\",\n      \"status\": \"critical\",\n      \"cpu\": 64,\n      \"memory\": 8,\n      \"disk\": 34,\n      \"network\": 34,\n      \"uptime\": 633206\n    },\n    {\n      \"id\": \"host-794\",\n      \"name\": \"prod-api-0794\",\n      \"status\": \"critical\",\n      \"cpu\": 5,\n      \"memory\": 76,\n      \"disk\": 55,\n      \"network\": 45,\n      \"uptime\": 3499775\n    },\n    {\n      \"id\": \"host-795\",\n      \"name\": \"prod-database-0795\",\n      \"status\": \"critical\",\n      \"cpu\": 28,\n      \"memory\": 65,\n      \"disk\": 58,\n      \"network\": 35,\n      \"uptime\": 7747464\n    },\n    {\n      \"id\": \"host-796\",\n      \"name\": \"prod-cache-0796\",\n      \"status\": \"critical\",\n      \"cpu\": 1,\n      \"memory\": 64,\n      \"disk\": 82,\n      \"network\": 64,\n      \"uptime\": 8917142\n    },\n    {\n      \"id\": \"host-797\",\n      \"name\": \"prod-worker-0797\",\n      \"status\": \"critical\",\n      \"cpu\": 47,\n      \"memory\": 29,\n      \"disk\": 26,\n      \"network\": 97,\n      \"uptime\": 8671444\n    },\n    {\n      \"id\": \"host-798\",\n      \"name\": \"prod-queue-0798\",\n      \"status\": \"critical\",\n      \"cpu\": 29,\n      \"memory\": 90,\n      \"disk\": 57,\n      \"network\": 36,\n      \"uptime\": 6745031\n    },\n    {\n      \"id\": \"host-799\",\n      \"name\": \"prod-web-0799\",\n      \"status\": \"critical\",\n      \"cpu\": 40,\n      \"memory\": 80,\n      \"disk\": 72,\n      \"network\": 0,\n      \"uptime\": 4898537\n    },\n    {\n      \"id\": \"host-800\",\n      \"name\": \"prod-api-0800\",\n      \"status\": \"critical\",\n      \"cpu\": 4,\n      \"memory\": 93,\n      \"disk\": 9,\n      \"network\": 68,\n      \"uptime\": 6433193\n    },\n    {\n      \"id\": \"host-801\",\n      \"name\": \"prod-database-0801\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 49,\n      \"disk\": 11,\n      \"network\": 34,\n      \"uptime\": 8222309\n    },\n    {\n      \"id\": \"host-802\",\n      \"name\": \"prod-cache-0802\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 1,\n      \"disk\": 1,\n      \"network\": 64,\n      \"uptime\": 4357762\n    },\n    {\n      \"id\": \"host-803\",\n      \"name\": \"prod-worker-0803\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 62,\n      \"disk\": 30,\n      \"network\": 70,\n      \"uptime\": 7541212\n    },\n    {\n      \"id\": \"host-804\",\n      \"name\": \"prod-queue-0804\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 41,\n      \"disk\": 66,\n      \"network\": 40,\n      \"uptime\": 5713873\n    },\n    {\n      \"id\": \"host-805\",\n      \"name\": \"prod-web-0805\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 62,\n      \"disk\": 68,\n      \"network\": 36,\n      \"uptime\": 1954002\n    },\n    {\n      \"id\": \"host-806\",\n      \"name\": \"prod-api-0806\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 63,\n      \"disk\": 64,\n      \"network\": 68,\n      \"uptime\": 322275\n    },\n    {\n      \"id\": \"host-807\",\n      \"name\": \"prod-database-0807\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 97,\n      \"disk\": 69,\n      \"network\": 95,\n      \"uptime\": 2123630\n    },\n    {\n      \"id\": \"host-808\",\n      \"name\": \"prod-cache-0808\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 39,\n      \"disk\": 92,\n      \"network\": 100,\n      \"uptime\": 3738238\n    },\n    {\n      \"id\": \"host-809\",\n      \"name\": \"prod-worker-0809\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 98,\n      \"disk\": 58,\n      \"network\": 48,\n      \"uptime\": 6342891\n    },\n    {\n      \"id\": \"host-810\",\n      \"name\": \"prod-queue-0810\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 6,\n      \"disk\": 20,\n      \"network\": 21,\n      \"uptime\": 9062202\n    },\n    {\n      \"id\": \"host-811\",\n      \"name\": \"prod-web-0811\",\n      \"status\": \"healthy\",\n      \"cpu\": 92,\n      \"memory\": 30,\n      \"disk\": 63,\n      \"network\": 50,\n      \"uptime\": 6396519\n    },\n    {\n      \"id\": \"host-812\",\n      \"name\": \"prod-api-0812\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 59,\n      \"disk\": 79,\n      \"network\": 28,\n      \"uptime\": 7744798\n    },\n    {\n      \"id\": \"host-813\",\n      \"name\": \"prod-database-0813\",\n      \"status\": \"healthy\",\n      \"cpu\": 6,\n      \"memory\": 73,\n      \"disk\": 87,\n      \"network\": 95,\n      \"uptime\": 2459214\n    },\n    {\n      \"id\": \"host-814\",\n      \"name\": \"prod-cache-0814\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 97,\n      \"disk\": 55,\n      \"network\": 22,\n      \"uptime\": 7706041\n    },\n    {\n      \"id\": \"host-815\",\n      \"name\": \"prod-worker-0815\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 89,\n      \"disk\": 79,\n      \"network\": 64,\n      \"uptime\": 5676819\n    },\n    {\n      \"id\": \"host-816\",\n      \"name\": \"prod-queue-0816\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 13,\n      \"disk\": 14,\n      \"network\": 35,\n      \"uptime\": 8909662\n    },\n    {\n      \"id\": \"host-817\",\n      \"name\": \"prod-web-0817\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 82,\n      \"disk\": 90,\n      \"network\": 1,\n      \"uptime\": 6179765\n    },\n    {\n      \"id\": \"host-818\",\n      \"name\": \"prod-api-0818\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 83,\n      \"disk\": 34,\n      \"network\": 87,\n      \"uptime\": 976202\n    },\n    {\n      \"id\": \"host-819\",\n      \"name\": \"prod-database-0819\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 64,\n      \"disk\": 10,\n      \"network\": 95,\n      \"uptime\": 4410915\n    },\n    {\n      \"id\": \"host-820\",\n      \"name\": \"prod-cache-0820\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 14,\n      \"disk\": 77,\n      \"network\": 15,\n      \"uptime\": 6967876\n    },\n    {\n      \"id\": \"host-821\",\n      \"name\": \"prod-worker-0821\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 88,\n      \"disk\": 52,\n      \"network\": 12,\n      \"uptime\": 520735\n    },\n    {\n      \"id\": \"host-822\",\n      \"name\": \"prod-queue-0822\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 91,\n      \"disk\": 74,\n      \"network\": 100,\n      \"uptime\": 2815676\n    },\n    {\n      \"id\": \"host-823\",\n      \"name\": \"prod-web-0823\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 47,\n      \"disk\": 9,\n      \"network\": 17,\n      \"uptime\": 2845580\n    },\n    {\n      \"id\": \"host-824\",\n      \"name\": \"prod-api-0824\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 84,\n      \"disk\": 67,\n      \"network\": 49,\n      \"uptime\": 619534\n    },\n    {\n      \"id\": \"host-825\",\n      \"name\": \"prod-database-0825\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 81,\n      \"disk\": 0,\n      \"network\": 95,\n      \"uptime\": 322377\n    },\n    {\n      \"id\": \"host-826\",\n      \"name\": \"prod-cache-0826\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 20,\n      \"disk\": 99,\n      \"network\": 78,\n      \"uptime\": 6680473\n    },\n    {\n      \"id\": \"host-827\",\n      \"name\": \"prod-worker-0827\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 33,\n      \"disk\": 12,\n      \"network\": 44,\n      \"uptime\": 5083648\n    },\n    {\n      \"id\": \"host-828\",\n      \"name\": \"prod-queue-0828\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 91,\n      \"disk\": 21,\n      \"network\": 8,\n      \"uptime\": 1995120\n    },\n    {\n      \"id\": \"host-829\",\n      \"name\": \"prod-web-0829\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 45,\n      \"disk\": 6,\n      \"network\": 65,\n      \"uptime\": 9269688\n    },\n    {\n      \"id\": \"host-830\",\n      \"name\": \"prod-api-0830\",\n      \"status\": \"healthy\",\n      \"cpu\": 37,\n      \"memory\": 92,\n      \"disk\": 49,\n      \"network\": 17,\n      \"uptime\": 4428446\n    },\n    {\n      \"id\": \"host-831\",\n      \"name\": \"prod-database-0831\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 28,\n      \"disk\": 69,\n      \"network\": 22,\n      \"uptime\": 4722527\n    },\n    {\n      \"id\": \"host-832\",\n      \"name\": \"prod-cache-0832\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 19,\n      \"disk\": 17,\n      \"network\": 23,\n      \"uptime\": 8752787\n    },\n    {\n      \"id\": \"host-833\",\n      \"name\": \"prod-worker-0833\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 2,\n      \"disk\": 39,\n      \"network\": 57,\n      \"uptime\": 5662357\n    },\n    {\n      \"id\": \"host-834\",\n      \"name\": \"prod-queue-0834\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 24,\n      \"disk\": 80,\n      \"network\": 48,\n      \"uptime\": 3656344\n    },\n    {\n      \"id\": \"host-835\",\n      \"name\": \"prod-web-0835\",\n      \"status\": \"healthy\",\n      \"cpu\": 77,\n      \"memory\": 69,\n      \"disk\": 76,\n      \"network\": 49,\n      \"uptime\": 6957474\n    },\n    {\n      \"id\": \"host-836\",\n      \"name\": \"prod-api-0836\",\n      \"status\": \"healthy\",\n      \"cpu\": 37,\n      \"memory\": 56,\n      \"disk\": 91,\n      \"network\": 0,\n      \"uptime\": 8743095\n    },\n    {\n      \"id\": \"host-837\",\n      \"name\": \"prod-database-0837\",\n      \"status\": \"healthy\",\n      \"cpu\": 95,\n      \"memory\": 2,\n      \"disk\": 53,\n      \"network\": 53,\n      \"uptime\": 907144\n    },\n    {\n      \"id\": \"host-838\",\n      \"name\": \"prod-cache-0838\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 40,\n      \"disk\": 26,\n      \"network\": 29,\n      \"uptime\": 4110214\n    },\n    {\n      \"id\": \"host-839\",\n      \"name\": \"prod-worker-0839\",\n      \"status\": \"healthy\",\n      \"cpu\": 92,\n      \"memory\": 41,\n      \"disk\": 65,\n      \"network\": 76,\n      \"uptime\": 8488256\n    },\n    {\n      \"id\": \"host-840\",\n      \"name\": \"prod-queue-0840\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 44,\n      \"disk\": 82,\n      \"network\": 25,\n      \"uptime\": 9465360\n    },\n    {\n      \"id\": \"host-841\",\n      \"name\": \"prod-web-0841\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 57,\n      \"disk\": 77,\n      \"network\": 52,\n      \"uptime\": 5606255\n    },\n    {\n      \"id\": \"host-842\",\n      \"name\": \"prod-api-0842\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 48,\n      \"disk\": 53,\n      \"network\": 82,\n      \"uptime\": 9706547\n    },\n    {\n      \"id\": \"host-843\",\n      \"name\": \"prod-database-0843\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 37,\n      \"disk\": 6,\n      \"network\": 49,\n      \"uptime\": 1777834\n    },\n    {\n      \"id\": \"host-844\",\n      \"name\": \"prod-cache-0844\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 60,\n      \"disk\": 29,\n      \"network\": 5,\n      \"uptime\": 8143333\n    },\n    {\n      \"id\": \"host-845\",\n      \"name\": \"prod-worker-0845\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 98,\n      \"disk\": 76,\n      \"network\": 56,\n      \"uptime\": 1324022\n    },\n    {\n      \"id\": \"host-846\",\n      \"name\": \"prod-queue-0846\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 28,\n      \"disk\": 24,\n      \"network\": 46,\n      \"uptime\": 8883551\n    },\n    {\n      \"id\": \"host-847\",\n      \"name\": \"prod-web-0847\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 64,\n      \"disk\": 63,\n      \"network\": 83,\n      \"uptime\": 2596518\n    },\n    {\n      \"id\": \"host-848\",\n      \"name\": \"prod-api-0848\",\n      \"status\": \"healthy\",\n      \"cpu\": 25,\n      \"memory\": 56,\n      \"disk\": 21,\n      \"network\": 61,\n      \"uptime\": 5328648\n    },\n    {\n      \"id\": \"host-849\",\n      \"name\": \"prod-database-0849\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 19,\n      \"disk\": 10,\n      \"network\": 10,\n      \"uptime\": 288070\n    },\n    {\n      \"id\": \"host-850\",\n      \"name\": \"prod-cache-0850\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 46,\n      \"disk\": 41,\n      \"network\": 45,\n      \"uptime\": 1657687\n    },\n    {\n      \"id\": \"host-851\",\n      \"name\": \"prod-worker-0851\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 20,\n      \"disk\": 26,\n      \"network\": 38,\n      \"uptime\": 4485138\n    },\n    {\n      \"id\": \"host-852\",\n      \"name\": \"prod-queue-0852\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 88,\n      \"disk\": 85,\n      \"network\": 13,\n      \"uptime\": 9898426\n    },\n    {\n      \"id\": \"host-853\",\n      \"name\": \"prod-web-0853\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 51,\n      \"disk\": 81,\n      \"network\": 76,\n      \"uptime\": 5345904\n    },\n    {\n      \"id\": \"host-854\",\n      \"name\": \"prod-api-0854\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 96,\n      \"disk\": 84,\n      \"network\": 73,\n      \"uptime\": 502618\n    },\n    {\n      \"id\": \"host-855\",\n      \"name\": \"prod-database-0855\",\n      \"status\": \"healthy\",\n      \"cpu\": 3,\n      \"memory\": 22,\n      \"disk\": 68,\n      \"network\": 78,\n      \"uptime\": 6833852\n    },\n    {\n      \"id\": \"host-856\",\n      \"name\": \"prod-cache-0856\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 66,\n      \"disk\": 53,\n      \"network\": 92,\n      \"uptime\": 288375\n    },\n    {\n      \"id\": \"host-857\",\n      \"name\": \"prod-worker-0857\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 78,\n      \"disk\": 99,\n      \"network\": 66,\n      \"uptime\": 6984894\n    },\n    {\n      \"id\": \"host-858\",\n      \"name\": \"prod-queue-0858\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 58,\n      \"disk\": 5,\n      \"network\": 72,\n      \"uptime\": 802385\n    },\n    {\n      \"id\": \"host-859\",\n      \"name\": \"prod-web-0859\",\n      \"status\": \"healthy\",\n      \"cpu\": 74,\n      \"memory\": 87,\n      \"disk\": 89,\n      \"network\": 55,\n      \"uptime\": 3335879\n    },\n    {\n      \"id\": \"host-860\",\n      \"name\": \"prod-api-0860\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 74,\n      \"disk\": 99,\n      \"network\": 84,\n      \"uptime\": 1377865\n    },\n    {\n      \"id\": \"host-861\",\n      \"name\": \"prod-database-0861\",\n      \"status\": \"warning\",\n      \"cpu\": 17,\n      \"memory\": 90,\n      \"disk\": 66,\n      \"network\": 16,\n      \"uptime\": 6603672\n    },\n    {\n      \"id\": \"host-862\",\n      \"name\": \"prod-cache-0862\",\n      \"status\": \"warning\",\n      \"cpu\": 81,\n      \"memory\": 94,\n      \"disk\": 84,\n      \"network\": 77,\n      \"uptime\": 4464626\n    },\n    {\n      \"id\": \"host-863\",\n      \"name\": \"prod-worker-0863\",\n      \"status\": \"warning\",\n      \"cpu\": 20,\n      \"memory\": 69,\n      \"disk\": 89,\n      \"network\": 40,\n      \"uptime\": 2691661\n    },\n    {\n      \"id\": \"host-864\",\n      \"name\": \"prod-queue-0864\",\n      \"status\": \"warning\",\n      \"cpu\": 4,\n      \"memory\": 6,\n      \"disk\": 76,\n      \"network\": 33,\n      \"uptime\": 8336645\n    },\n    {\n      \"id\": \"host-865\",\n      \"name\": \"prod-web-0865\",\n      \"status\": \"warning\",\n      \"cpu\": 23,\n      \"memory\": 87,\n      \"disk\": 99,\n      \"network\": 86,\n      \"uptime\": 5082282\n    },\n    {\n      \"id\": \"host-866\",\n      \"name\": \"prod-api-0866\",\n      \"status\": \"warning\",\n      \"cpu\": 75,\n      \"memory\": 9,\n      \"disk\": 16,\n      \"network\": 70,\n      \"uptime\": 3429421\n    },\n    {\n      \"id\": \"host-867\",\n      \"name\": \"prod-database-0867\",\n      \"status\": \"warning\",\n      \"cpu\": 30,\n      \"memory\": 9,\n      \"disk\": 10,\n      \"network\": 65,\n      \"uptime\": 8098797\n    },\n    {\n      \"id\": \"host-868\",\n      \"name\": \"prod-cache-0868\",\n      \"status\": \"warning\",\n      \"cpu\": 16,\n      \"memory\": 80,\n      \"disk\": 84,\n      \"network\": 70,\n      \"uptime\": 4838936\n    },\n    {\n      \"id\": \"host-869\",\n      \"name\": \"prod-worker-0869\",\n      \"status\": \"warning\",\n      \"cpu\": 32,\n      \"memory\": 20,\n      \"disk\": 16,\n      \"network\": 85,\n      \"uptime\": 1289213\n    },\n    {\n      \"id\": \"host-870\",\n      \"name\": \"prod-queue-0870\",\n      \"status\": \"warning\",\n      \"cpu\": 90,\n      \"memory\": 93,\n      \"disk\": 2,\n      \"network\": 61,\n      \"uptime\": 9089994\n    },\n    {\n      \"id\": \"host-871\",\n      \"name\": \"prod-web-0871\",\n      \"status\": \"warning\",\n      \"cpu\": 93,\n      \"memory\": 56,\n      \"disk\": 68,\n      \"network\": 17,\n      \"uptime\": 8724557\n    },\n    {\n      \"id\": \"host-872\",\n      \"name\": \"prod-api-0872\",\n      \"status\": \"warning\",\n      \"cpu\": 49,\n      \"memory\": 83,\n      \"disk\": 90,\n      \"network\": 36,\n      \"uptime\": 8447678\n    },\n    {\n      \"id\": \"host-873\",\n      \"name\": \"prod-database-0873\",\n      \"status\": \"warning\",\n      \"cpu\": 70,\n      \"memory\": 83,\n      \"disk\": 100,\n      \"network\": 79,\n      \"uptime\": 1402746\n    },\n    {\n      \"id\": \"host-874\",\n      \"name\": \"prod-cache-0874\",\n      \"status\": \"warning\",\n      \"cpu\": 54,\n      \"memory\": 23,\n      \"disk\": 62,\n      \"network\": 19,\n      \"uptime\": 7435939\n    },\n    {\n      \"id\": \"host-875\",\n      \"name\": \"prod-worker-0875\",\n      \"status\": \"warning\",\n      \"cpu\": 63,\n      \"memory\": 43,\n      \"disk\": 6,\n      \"network\": 51,\n      \"uptime\": 7447867\n    },\n    {\n      \"id\": \"host-876\",\n      \"name\": \"prod-queue-0876\",\n      \"status\": \"warning\",\n      \"cpu\": 78,\n      \"memory\": 5,\n      \"disk\": 93,\n      \"network\": 65,\n      \"uptime\": 467007\n    },\n    {\n      \"id\": \"host-877\",\n      \"name\": \"prod-web-0877\",\n      \"status\": \"warning\",\n      \"cpu\": 4,\n      \"memory\": 18,\n      \"disk\": 57,\n      \"network\": 89,\n      \"uptime\": 3209549\n    },\n    {\n      \"id\": \"host-878\",\n      \"name\": \"prod-api-0878\",\n      \"status\": \"warning\",\n      \"cpu\": 12,\n      \"memory\": 87,\n      \"disk\": 41,\n      \"network\": 27,\n      \"uptime\": 5278091\n    },\n    {\n      \"id\": \"host-879\",\n      \"name\": \"prod-database-0879\",\n      \"status\": \"warning\",\n      \"cpu\": 45,\n      \"memory\": 38,\n      \"disk\": 78,\n      \"network\": 60,\n      \"uptime\": 9117267\n    },\n    {\n      \"id\": \"host-880\",\n      \"name\": \"prod-cache-0880\",\n      \"status\": \"warning\",\n      \"cpu\": 13,\n      \"memory\": 16,\n      \"disk\": 50,\n      \"network\": 81,\n      \"uptime\": 6433592\n    },\n    {\n      \"id\": \"host-881\",\n      \"name\": \"prod-worker-0881\",\n      \"status\": \"warning\",\n      \"cpu\": 10,\n      \"memory\": 89,\n      \"disk\": 73,\n      \"network\": 82,\n      \"uptime\": 5442761\n    },\n    {\n      \"id\": \"host-882\",\n      \"name\": \"prod-queue-0882\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 49,\n      \"disk\": 18,\n      \"network\": 94,\n      \"uptime\": 321619\n    },\n    {\n      \"id\": \"host-883\",\n      \"name\": \"prod-web-0883\",\n      \"status\": \"warning\",\n      \"cpu\": 67,\n      \"memory\": 95,\n      \"disk\": 23,\n      \"network\": 55,\n      \"uptime\": 8845270\n    },\n    {\n      \"id\": \"host-884\",\n      \"name\": \"prod-api-0884\",\n      \"status\": \"warning\",\n      \"cpu\": 68,\n      \"memory\": 98,\n      \"disk\": 2,\n      \"network\": 80,\n      \"uptime\": 7722568\n    },\n    {\n      \"id\": \"host-885\",\n      \"name\": \"prod-database-0885\",\n      \"status\": \"warning\",\n      \"cpu\": 77,\n      \"memory\": 46,\n      \"disk\": 39,\n      \"network\": 14,\n      \"uptime\": 1005561\n    },\n    {\n      \"id\": \"host-886\",\n      \"name\": \"prod-cache-0886\",\n      \"status\": \"critical\",\n      \"cpu\": 26,\n      \"memory\": 28,\n      \"disk\": 80,\n      \"network\": 78,\n      \"uptime\": 2589060\n    },\n    {\n      \"id\": \"host-887\",\n      \"name\": \"prod-worker-0887\",\n      \"status\": \"critical\",\n      \"cpu\": 72,\n      \"memory\": 75,\n      \"disk\": 62,\n      \"network\": 9,\n      \"uptime\": 6051717\n    },\n    {\n      \"id\": \"host-888\",\n      \"name\": \"prod-queue-0888\",\n      \"status\": \"critical\",\n      \"cpu\": 96,\n      \"memory\": 4,\n      \"disk\": 51,\n      \"network\": 66,\n      \"uptime\": 3376973\n    },\n    {\n      \"id\": \"host-889\",\n      \"name\": \"prod-web-0889\",\n      \"status\": \"critical\",\n      \"cpu\": 95,\n      \"memory\": 14,\n      \"disk\": 26,\n      \"network\": 2,\n      \"uptime\": 8322721\n    },\n    {\n      \"id\": \"host-890\",\n      \"name\": \"prod-api-0890\",\n      \"status\": \"critical\",\n      \"cpu\": 41,\n      \"memory\": 22,\n      \"disk\": 39,\n      \"network\": 14,\n      \"uptime\": 3964015\n    },\n    {\n      \"id\": \"host-891\",\n      \"name\": \"prod-database-0891\",\n      \"status\": \"critical\",\n      \"cpu\": 52,\n      \"memory\": 44,\n      \"disk\": 56,\n      \"network\": 2,\n      \"uptime\": 2160365\n    },\n    {\n      \"id\": \"host-892\",\n      \"name\": \"prod-cache-0892\",\n      \"status\": \"critical\",\n      \"cpu\": 9,\n      \"memory\": 16,\n      \"disk\": 6,\n      \"network\": 22,\n      \"uptime\": 1310473\n    },\n    {\n      \"id\": \"host-893\",\n      \"name\": \"prod-worker-0893\",\n      \"status\": \"critical\",\n      \"cpu\": 84,\n      \"memory\": 79,\n      \"disk\": 21,\n      \"network\": 12,\n      \"uptime\": 8820346\n    },\n    {\n      \"id\": \"host-894\",\n      \"name\": \"prod-queue-0894\",\n      \"status\": \"critical\",\n      \"cpu\": 81,\n      \"memory\": 24,\n      \"disk\": 27,\n      \"network\": 70,\n      \"uptime\": 1171354\n    },\n    {\n      \"id\": \"host-895\",\n      \"name\": \"prod-web-0895\",\n      \"status\": \"critical\",\n      \"cpu\": 17,\n      \"memory\": 23,\n      \"disk\": 27,\n      \"network\": 45,\n      \"uptime\": 216548\n    },\n    {\n      \"id\": \"host-896\",\n      \"name\": \"prod-api-0896\",\n      \"status\": \"critical\",\n      \"cpu\": 46,\n      \"memory\": 78,\n      \"disk\": 100,\n      \"network\": 25,\n      \"uptime\": 1878166\n    },\n    {\n      \"id\": \"host-897\",\n      \"name\": \"prod-database-0897\",\n      \"status\": \"critical\",\n      \"cpu\": 64,\n      \"memory\": 12,\n      \"disk\": 57,\n      \"network\": 99,\n      \"uptime\": 6310934\n    },\n    {\n      \"id\": \"host-898\",\n      \"name\": \"prod-cache-0898\",\n      \"status\": \"critical\",\n      \"cpu\": 75,\n      \"memory\": 1,\n      \"disk\": 60,\n      \"network\": 38,\n      \"uptime\": 9019998\n    },\n    {\n      \"id\": \"host-899\",\n      \"name\": \"prod-worker-0899\",\n      \"status\": \"critical\",\n      \"cpu\": 25,\n      \"memory\": 77,\n      \"disk\": 62,\n      \"network\": 68,\n      \"uptime\": 5793308\n    },\n    {\n      \"id\": \"host-900\",\n      \"name\": \"prod-queue-0900\",\n      \"status\": \"critical\",\n      \"cpu\": 81,\n      \"memory\": 22,\n      \"disk\": 91,\n      \"network\": 98,\n      \"uptime\": 1244561\n    },\n    {\n      \"id\": \"host-901\",\n      \"name\": \"prod-web-0901\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 2,\n      \"disk\": 67,\n      \"network\": 42,\n      \"uptime\": 6234343\n    },\n    {\n      \"id\": \"host-902\",\n      \"name\": \"prod-api-0902\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 56,\n      \"disk\": 70,\n      \"network\": 10,\n      \"uptime\": 1783822\n    },\n    {\n      \"id\": \"host-903\",\n      \"name\": \"prod-database-0903\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 36,\n      \"disk\": 69,\n      \"network\": 31,\n      \"uptime\": 764634\n    },\n    {\n      \"id\": \"host-904\",\n      \"name\": \"prod-cache-0904\",\n      \"status\": \"healthy\",\n      \"cpu\": 41,\n      \"memory\": 7,\n      \"disk\": 31,\n      \"network\": 7,\n      \"uptime\": 7637311\n    },\n    {\n      \"id\": \"host-905\",\n      \"name\": \"prod-worker-0905\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 21,\n      \"disk\": 92,\n      \"network\": 77,\n      \"uptime\": 9852181\n    },\n    {\n      \"id\": \"host-906\",\n      \"name\": \"prod-queue-0906\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 65,\n      \"disk\": 0,\n      \"network\": 36,\n      \"uptime\": 4137888\n    },\n    {\n      \"id\": \"host-907\",\n      \"name\": \"prod-web-0907\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 1,\n      \"disk\": 59,\n      \"network\": 61,\n      \"uptime\": 1192200\n    },\n    {\n      \"id\": \"host-908\",\n      \"name\": \"prod-api-0908\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 89,\n      \"disk\": 32,\n      \"network\": 4,\n      \"uptime\": 9872110\n    },\n    {\n      \"id\": \"host-909\",\n      \"name\": \"prod-database-0909\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 96,\n      \"disk\": 95,\n      \"network\": 92,\n      \"uptime\": 2653741\n    },\n    {\n      \"id\": \"host-910\",\n      \"name\": \"prod-cache-0910\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 86,\n      \"disk\": 5,\n      \"network\": 29,\n      \"uptime\": 8330907\n    },\n    {\n      \"id\": \"host-911\",\n      \"name\": \"prod-worker-0911\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 51,\n      \"disk\": 62,\n      \"network\": 76,\n      \"uptime\": 4247969\n    },\n    {\n      \"id\": \"host-912\",\n      \"name\": \"prod-queue-0912\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 38,\n      \"disk\": 41,\n      \"network\": 82,\n      \"uptime\": 460477\n    },\n    {\n      \"id\": \"host-913\",\n      \"name\": \"prod-web-0913\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 2,\n      \"disk\": 17,\n      \"network\": 20,\n      \"uptime\": 2423000\n    },\n    {\n      \"id\": \"host-914\",\n      \"name\": \"prod-api-0914\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 6,\n      \"disk\": 99,\n      \"network\": 93,\n      \"uptime\": 2523085\n    },\n    {\n      \"id\": \"host-915\",\n      \"name\": \"prod-database-0915\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 92,\n      \"disk\": 45,\n      \"network\": 48,\n      \"uptime\": 1858194\n    },\n    {\n      \"id\": \"host-916\",\n      \"name\": \"prod-cache-0916\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 34,\n      \"disk\": 21,\n      \"network\": 84,\n      \"uptime\": 6010927\n    },\n    {\n      \"id\": \"host-917\",\n      \"name\": \"prod-worker-0917\",\n      \"status\": \"healthy\",\n      \"cpu\": 91,\n      \"memory\": 93,\n      \"disk\": 96,\n      \"network\": 21,\n      \"uptime\": 524417\n    },\n    {\n      \"id\": \"host-918\",\n      \"name\": \"prod-queue-0918\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 36,\n      \"disk\": 25,\n      \"network\": 5,\n      \"uptime\": 2078745\n    },\n    {\n      \"id\": \"host-919\",\n      \"name\": \"prod-web-0919\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 8,\n      \"disk\": 51,\n      \"network\": 57,\n      \"uptime\": 7759054\n    },\n    {\n      \"id\": \"host-920\",\n      \"name\": \"prod-api-0920\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 0,\n      \"disk\": 8,\n      \"network\": 92,\n      \"uptime\": 7841922\n    },\n    {\n      \"id\": \"host-921\",\n      \"name\": \"prod-database-0921\",\n      \"status\": \"healthy\",\n      \"cpu\": 77,\n      \"memory\": 37,\n      \"disk\": 99,\n      \"network\": 24,\n      \"uptime\": 5140231\n    },\n    {\n      \"id\": \"host-922\",\n      \"name\": \"prod-cache-0922\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 26,\n      \"disk\": 85,\n      \"network\": 29,\n      \"uptime\": 9187850\n    },\n    {\n      \"id\": \"host-923\",\n      \"name\": \"prod-worker-0923\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 68,\n      \"disk\": 53,\n      \"network\": 40,\n      \"uptime\": 7632736\n    },\n    {\n      \"id\": \"host-924\",\n      \"name\": \"prod-queue-0924\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 58,\n      \"disk\": 78,\n      \"network\": 7,\n      \"uptime\": 7558208\n    },\n    {\n      \"id\": \"host-925\",\n      \"name\": \"prod-web-0925\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 100,\n      \"disk\": 5,\n      \"network\": 64,\n      \"uptime\": 1145542\n    },\n    {\n      \"id\": \"host-926\",\n      \"name\": \"prod-api-0926\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 97,\n      \"disk\": 38,\n      \"network\": 33,\n      \"uptime\": 5313110\n    },\n    {\n      \"id\": \"host-927\",\n      \"name\": \"prod-database-0927\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 100,\n      \"disk\": 29,\n      \"network\": 89,\n      \"uptime\": 7395343\n    },\n    {\n      \"id\": \"host-928\",\n      \"name\": \"prod-cache-0928\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 81,\n      \"disk\": 31,\n      \"network\": 59,\n      \"uptime\": 8391395\n    },\n    {\n      \"id\": \"host-929\",\n      \"name\": \"prod-worker-0929\",\n      \"status\": \"healthy\",\n      \"cpu\": 6,\n      \"memory\": 28,\n      \"disk\": 26,\n      \"network\": 1,\n      \"uptime\": 1829942\n    },\n    {\n      \"id\": \"host-930\",\n      \"name\": \"prod-queue-0930\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 82,\n      \"disk\": 69,\n      \"network\": 9,\n      \"uptime\": 1829321\n    },\n    {\n      \"id\": \"host-931\",\n      \"name\": \"prod-web-0931\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 69,\n      \"disk\": 32,\n      \"network\": 78,\n      \"uptime\": 9697555\n    },\n    {\n      \"id\": \"host-932\",\n      \"name\": \"prod-api-0932\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 94,\n      \"disk\": 55,\n      \"network\": 51,\n      \"uptime\": 2723416\n    },\n    {\n      \"id\": \"host-933\",\n      \"name\": \"prod-database-0933\",\n      \"status\": \"healthy\",\n      \"cpu\": 37,\n      \"memory\": 72,\n      \"disk\": 8,\n      \"network\": 15,\n      \"uptime\": 2637207\n    },\n    {\n      \"id\": \"host-934\",\n      \"name\": \"prod-cache-0934\",\n      \"status\": \"healthy\",\n      \"cpu\": 95,\n      \"memory\": 26,\n      \"disk\": 34,\n      \"network\": 41,\n      \"uptime\": 1311348\n    },\n    {\n      \"id\": \"host-935\",\n      \"name\": \"prod-worker-0935\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 57,\n      \"disk\": 42,\n      \"network\": 27,\n      \"uptime\": 5916644\n    },\n    {\n      \"id\": \"host-936\",\n      \"name\": \"prod-queue-0936\",\n      \"status\": \"healthy\",\n      \"cpu\": 85,\n      \"memory\": 49,\n      \"disk\": 40,\n      \"network\": 57,\n      \"uptime\": 8739732\n    },\n    {\n      \"id\": \"host-937\",\n      \"name\": \"prod-web-0937\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 60,\n      \"disk\": 89,\n      \"network\": 78,\n      \"uptime\": 4704794\n    },\n    {\n      \"id\": \"host-938\",\n      \"name\": \"prod-api-0938\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 9,\n      \"disk\": 13,\n      \"network\": 71,\n      \"uptime\": 7268616\n    },\n    {\n      \"id\": \"host-939\",\n      \"name\": \"prod-database-0939\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 60,\n      \"disk\": 52,\n      \"network\": 38,\n      \"uptime\": 760986\n    },\n    {\n      \"id\": \"host-940\",\n      \"name\": \"prod-cache-0940\",\n      \"status\": \"healthy\",\n      \"cpu\": 57,\n      \"memory\": 95,\n      \"disk\": 40,\n      \"network\": 79,\n      \"uptime\": 4388256\n    },\n    {\n      \"id\": \"host-941\",\n      \"name\": \"prod-worker-0941\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 62,\n      \"disk\": 37,\n      \"network\": 9,\n      \"uptime\": 6540447\n    },\n    {\n      \"id\": \"host-942\",\n      \"name\": \"prod-queue-0942\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 78,\n      \"disk\": 79,\n      \"network\": 48,\n      \"uptime\": 2499777\n    },\n    {\n      \"id\": \"host-943\",\n      \"name\": \"prod-web-0943\",\n      \"status\": \"healthy\",\n      \"cpu\": 37,\n      \"memory\": 25,\n      \"disk\": 83,\n      \"network\": 1,\n      \"uptime\": 8109038\n    },\n    {\n      \"id\": \"host-944\",\n      \"name\": \"prod-api-0944\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 27,\n      \"disk\": 74,\n      \"network\": 68,\n      \"uptime\": 658330\n    },\n    {\n      \"id\": \"host-945\",\n      \"name\": \"prod-database-0945\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 69,\n      \"disk\": 58,\n      \"network\": 30,\n      \"uptime\": 8664006\n    },\n    {\n      \"id\": \"host-946\",\n      \"name\": \"prod-cache-0946\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 29,\n      \"disk\": 86,\n      \"network\": 1,\n      \"uptime\": 6477293\n    },\n    {\n      \"id\": \"host-947\",\n      \"name\": \"prod-worker-0947\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 21,\n      \"disk\": 46,\n      \"network\": 12,\n      \"uptime\": 5495076\n    },\n    {\n      \"id\": \"host-948\",\n      \"name\": \"prod-queue-0948\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 67,\n      \"disk\": 57,\n      \"network\": 23,\n      \"uptime\": 1784755\n    },\n    {\n      \"id\": \"host-949\",\n      \"name\": \"prod-web-0949\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 40,\n      \"disk\": 66,\n      \"network\": 52,\n      \"uptime\": 8384878\n    },\n    {\n      \"id\": \"host-950\",\n      \"name\": \"prod-api-0950\",\n      \"status\": \"healthy\",\n      \"cpu\": 75,\n      \"memory\": 14,\n      \"disk\": 66,\n      \"network\": 30,\n      \"uptime\": 2133226\n    },\n    {\n      \"id\": \"host-951\",\n      \"name\": \"prod-database-0951\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 28,\n      \"disk\": 13,\n      \"network\": 63,\n      \"uptime\": 1493141\n    },\n    {\n      \"id\": \"host-952\",\n      \"name\": \"prod-cache-0952\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 23,\n      \"disk\": 96,\n      \"network\": 76,\n      \"uptime\": 2434204\n    },\n    {\n      \"id\": \"host-953\",\n      \"name\": \"prod-worker-0953\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 7,\n      \"disk\": 28,\n      \"network\": 66,\n      \"uptime\": 632502\n    },\n    {\n      \"id\": \"host-954\",\n      \"name\": \"prod-queue-0954\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 43,\n      \"disk\": 26,\n      \"network\": 77,\n      \"uptime\": 9573791\n    },\n    {\n      \"id\": \"host-955\",\n      \"name\": \"prod-web-0955\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 77,\n      \"disk\": 64,\n      \"network\": 88,\n      \"uptime\": 4556446\n    },\n    {\n      \"id\": \"host-956\",\n      \"name\": \"prod-api-0956\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 46,\n      \"disk\": 46,\n      \"network\": 68,\n      \"uptime\": 9421757\n    },\n    {\n      \"id\": \"host-957\",\n      \"name\": \"prod-database-0957\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 0,\n      \"disk\": 66,\n      \"network\": 76,\n      \"uptime\": 3508835\n    },\n    {\n      \"id\": \"host-958\",\n      \"name\": \"prod-cache-0958\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 43,\n      \"disk\": 4,\n      \"network\": 74,\n      \"uptime\": 790675\n    },\n    {\n      \"id\": \"host-959\",\n      \"name\": \"prod-worker-0959\",\n      \"status\": \"healthy\",\n      \"cpu\": 6,\n      \"memory\": 0,\n      \"disk\": 21,\n      \"network\": 23,\n      \"uptime\": 8187653\n    },\n    {\n      \"id\": \"host-960\",\n      \"name\": \"prod-queue-0960\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 39,\n      \"disk\": 92,\n      \"network\": 71,\n      \"uptime\": 3449631\n    },\n    {\n      \"id\": \"host-961\",\n      \"name\": \"prod-web-0961\",\n      \"status\": \"warning\",\n      \"cpu\": 25,\n      \"memory\": 99,\n      \"disk\": 95,\n      \"network\": 97,\n      \"uptime\": 6996861\n    },\n    {\n      \"id\": \"host-962\",\n      \"name\": \"prod-api-0962\",\n      \"status\": \"warning\",\n      \"cpu\": 58,\n      \"memory\": 94,\n      \"disk\": 95,\n      \"network\": 60,\n      \"uptime\": 7305398\n    },\n    {\n      \"id\": \"host-963\",\n      \"name\": \"prod-database-0963\",\n      \"status\": \"warning\",\n      \"cpu\": 36,\n      \"memory\": 78,\n      \"disk\": 19,\n      \"network\": 42,\n      \"uptime\": 97658\n    },\n    {\n      \"id\": \"host-964\",\n      \"name\": \"prod-cache-0964\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 45,\n      \"disk\": 38,\n      \"network\": 90,\n      \"uptime\": 1812232\n    },\n    {\n      \"id\": \"host-965\",\n      \"name\": \"prod-worker-0965\",\n      \"status\": \"warning\",\n      \"cpu\": 78,\n      \"memory\": 1,\n      \"disk\": 3,\n      \"network\": 56,\n      \"uptime\": 3116237\n    },\n    {\n      \"id\": \"host-966\",\n      \"name\": \"prod-queue-0966\",\n      \"status\": \"warning\",\n      \"cpu\": 68,\n      \"memory\": 68,\n      \"disk\": 84,\n      \"network\": 5,\n      \"uptime\": 5473579\n    },\n    {\n      \"id\": \"host-967\",\n      \"name\": \"prod-web-0967\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 53,\n      \"disk\": 17,\n      \"network\": 65,\n      \"uptime\": 8174480\n    },\n    {\n      \"id\": \"host-968\",\n      \"name\": \"prod-api-0968\",\n      \"status\": \"warning\",\n      \"cpu\": 64,\n      \"memory\": 58,\n      \"disk\": 72,\n      \"network\": 1,\n      \"uptime\": 5521977\n    },\n    {\n      \"id\": \"host-969\",\n      \"name\": \"prod-database-0969\",\n      \"status\": \"warning\",\n      \"cpu\": 18,\n      \"memory\": 62,\n      \"disk\": 67,\n      \"network\": 22,\n      \"uptime\": 8984550\n    },\n    {\n      \"id\": \"host-970\",\n      \"name\": \"prod-cache-0970\",\n      \"status\": \"warning\",\n      \"cpu\": 18,\n      \"memory\": 14,\n      \"disk\": 76,\n      \"network\": 26,\n      \"uptime\": 6824439\n    },\n    {\n      \"id\": \"host-971\",\n      \"name\": \"prod-worker-0971\",\n      \"status\": \"warning\",\n      \"cpu\": 12,\n      \"memory\": 28,\n      \"disk\": 18,\n      \"network\": 31,\n      \"uptime\": 651297\n    },\n    {\n      \"id\": \"host-972\",\n      \"name\": \"prod-queue-0972\",\n      \"status\": \"warning\",\n      \"cpu\": 99,\n      \"memory\": 89,\n      \"disk\": 22,\n      \"network\": 38,\n      \"uptime\": 172270\n    },\n    {\n      \"id\": \"host-973\",\n      \"name\": \"prod-web-0973\",\n      \"status\": \"warning\",\n      \"cpu\": 10,\n      \"memory\": 6,\n      \"disk\": 1,\n      \"network\": 69,\n      \"uptime\": 23820\n    },\n    {\n      \"id\": \"host-974\",\n      \"name\": \"prod-api-0974\",\n      \"status\": \"warning\",\n      \"cpu\": 36,\n      \"memory\": 8,\n      \"disk\": 61,\n      \"network\": 88,\n      \"uptime\": 6604192\n    },\n    {\n      \"id\": \"host-975\",\n      \"name\": \"prod-database-0975\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 70,\n      \"disk\": 72,\n      \"network\": 45,\n      \"uptime\": 8041169\n    },\n    {\n      \"id\": \"host-976\",\n      \"name\": \"prod-cache-0976\",\n      \"status\": \"warning\",\n      \"cpu\": 80,\n      \"memory\": 26,\n      \"disk\": 66,\n      \"network\": 75,\n      \"uptime\": 5175456\n    },\n    {\n      \"id\": \"host-977\",\n      \"name\": \"prod-worker-0977\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 26,\n      \"disk\": 34,\n      \"network\": 4,\n      \"uptime\": 8432912\n    },\n    {\n      \"id\": \"host-978\",\n      \"name\": \"prod-queue-0978\",\n      \"status\": \"warning\",\n      \"cpu\": 64,\n      \"memory\": 86,\n      \"disk\": 70,\n      \"network\": 97,\n      \"uptime\": 5496312\n    },\n    {\n      \"id\": \"host-979\",\n      \"name\": \"prod-web-0979\",\n      \"status\": \"warning\",\n      \"cpu\": 31,\n      \"memory\": 83,\n      \"disk\": 85,\n      \"network\": 23,\n      \"uptime\": 5637249\n    },\n    {\n      \"id\": \"host-980\",\n      \"name\": \"prod-api-0980\",\n      \"status\": \"warning\",\n      \"cpu\": 88,\n      \"memory\": 7,\n      \"disk\": 1,\n      \"network\": 61,\n      \"uptime\": 4553049\n    },\n    {\n      \"id\": \"host-981\",\n      \"name\": \"prod-database-0981\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 55,\n      \"disk\": 73,\n      \"network\": 88,\n      \"uptime\": 3312414\n    },\n    {\n      \"id\": \"host-982\",\n      \"name\": \"prod-cache-0982\",\n      \"status\": \"warning\",\n      \"cpu\": 65,\n      \"memory\": 77,\n      \"disk\": 40,\n      \"network\": 36,\n      \"uptime\": 7245987\n    },\n    {\n      \"id\": \"host-983\",\n      \"name\": \"prod-worker-0983\",\n      \"status\": \"warning\",\n      \"cpu\": 53,\n      \"memory\": 59,\n      \"disk\": 18,\n      \"network\": 70,\n      \"uptime\": 1237980\n    },\n    {\n      \"id\": \"host-984\",\n      \"name\": \"prod-queue-0984\",\n      \"status\": \"warning\",\n      \"cpu\": 92,\n      \"memory\": 90,\n      \"disk\": 94,\n      \"network\": 78,\n      \"uptime\": 3298180\n    },\n    {\n      \"id\": \"host-985\",\n      \"name\": \"prod-web-0985\",\n      \"status\": \"warning\",\n      \"cpu\": 83,\n      \"memory\": 56,\n      \"disk\": 40,\n      \"network\": 12,\n      \"uptime\": 2461201\n    },\n    {\n      \"id\": \"host-986\",\n      \"name\": \"prod-api-0986\",\n      \"status\": \"critical\",\n      \"cpu\": 18,\n      \"memory\": 69,\n      \"disk\": 52,\n      \"network\": 6,\n      \"uptime\": 6487243\n    },\n    {\n      \"id\": \"host-987\",\n      \"name\": \"prod-database-0987\",\n      \"status\": \"critical\",\n      \"cpu\": 46,\n      \"memory\": 32,\n      \"disk\": 85,\n      \"network\": 47,\n      \"uptime\": 8121755\n    },\n    {\n      \"id\": \"host-988\",\n      \"name\": \"prod-cache-0988\",\n      \"status\": \"critical\",\n      \"cpu\": 56,\n      \"memory\": 4,\n      \"disk\": 63,\n      \"network\": 94,\n      \"uptime\": 7853972\n    },\n    {\n      \"id\": \"host-989\",\n      \"name\": \"prod-worker-0989\",\n      \"status\": \"critical\",\n      \"cpu\": 52,\n      \"memory\": 95,\n      \"disk\": 73,\n      \"network\": 62,\n      \"uptime\": 6944792\n    },\n    {\n      \"id\": \"host-990\",\n      \"name\": \"prod-queue-0990\",\n      \"status\": \"critical\",\n      \"cpu\": 66,\n      \"memory\": 84,\n      \"disk\": 3,\n      \"network\": 89,\n      \"uptime\": 7060217\n    },\n    {\n      \"id\": \"host-991\",\n      \"name\": \"prod-web-0991\",\n      \"status\": \"critical\",\n      \"cpu\": 35,\n      \"memory\": 73,\n      \"disk\": 13,\n      \"network\": 19,\n      \"uptime\": 981626\n    },\n    {\n      \"id\": \"host-992\",\n      \"name\": \"prod-api-0992\",\n      \"status\": \"critical\",\n      \"cpu\": 82,\n      \"memory\": 14,\n      \"disk\": 24,\n      \"network\": 41,\n      \"uptime\": 3111679\n    },\n    {\n      \"id\": \"host-993\",\n      \"name\": \"prod-database-0993\",\n      \"status\": \"critical\",\n      \"cpu\": 46,\n      \"memory\": 88,\n      \"disk\": 99,\n      \"network\": 14,\n      \"uptime\": 4657931\n    },\n    {\n      \"id\": \"host-994\",\n      \"name\": \"prod-cache-0994\",\n      \"status\": \"critical\",\n      \"cpu\": 99,\n      \"memory\": 65,\n      \"disk\": 39,\n      \"network\": 79,\n      \"uptime\": 2372700\n    },\n    {\n      \"id\": \"host-995\",\n      \"name\": \"prod-worker-0995\",\n      \"status\": \"critical\",\n      \"cpu\": 50,\n      \"memory\": 80,\n      \"disk\": 40,\n      \"network\": 33,\n      \"uptime\": 6621484\n    },\n    {\n      \"id\": \"host-996\",\n      \"name\": \"prod-queue-0996\",\n      \"status\": \"critical\",\n      \"cpu\": 81,\n      \"memory\": 46,\n      \"disk\": 33,\n      \"network\": 56,\n      \"uptime\": 2296188\n    },\n    {\n      \"id\": \"host-997\",\n      \"name\": \"prod-web-0997\",\n      \"status\": \"critical\",\n      \"cpu\": 48,\n      \"memory\": 71,\n      \"disk\": 40,\n      \"network\": 24,\n      \"uptime\": 5001592\n    },\n    {\n      \"id\": \"host-998\",\n      \"name\": \"prod-api-0998\",\n      \"status\": \"critical\",\n      \"cpu\": 65,\n      \"memory\": 55,\n      \"disk\": 100,\n      \"network\": 88,\n      \"uptime\": 1207732\n    },\n    {\n      \"id\": \"host-999\",\n      \"name\": \"prod-database-0999\",\n      \"status\": \"critical\",\n      \"cpu\": 41,\n      \"memory\": 24,\n      \"disk\": 57,\n      \"network\": 87,\n      \"uptime\": 3522976\n    },\n    {\n      \"id\": \"host-1000\",\n      \"name\": \"prod-cache-1000\",\n      \"status\": \"critical\",\n      \"cpu\": 16,\n      \"memory\": 76,\n      \"disk\": 4,\n      \"network\": 61,\n      \"uptime\": 247444\n    },\n    {\n      \"id\": \"host-1001\",\n      \"name\": \"prod-worker-1001\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 33,\n      \"disk\": 33,\n      \"network\": 73,\n      \"uptime\": 8504955\n    },\n    {\n      \"id\": \"host-1002\",\n      \"name\": \"prod-queue-1002\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 47,\n      \"disk\": 49,\n      \"network\": 75,\n      \"uptime\": 1176729\n    },\n    {\n      \"id\": \"host-1003\",\n      \"name\": \"prod-web-1003\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 61,\n      \"disk\": 22,\n      \"network\": 38,\n      \"uptime\": 2260054\n    },\n    {\n      \"id\": \"host-1004\",\n      \"name\": \"prod-api-1004\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 37,\n      \"disk\": 48,\n      \"network\": 47,\n      \"uptime\": 3292082\n    },\n    {\n      \"id\": \"host-1005\",\n      \"name\": \"prod-database-1005\",\n      \"status\": \"healthy\",\n      \"cpu\": 24,\n      \"memory\": 70,\n      \"disk\": 91,\n      \"network\": 65,\n      \"uptime\": 8420453\n    },\n    {\n      \"id\": \"host-1006\",\n      \"name\": \"prod-cache-1006\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 98,\n      \"disk\": 79,\n      \"network\": 47,\n      \"uptime\": 1736784\n    },\n    {\n      \"id\": \"host-1007\",\n      \"name\": \"prod-worker-1007\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 81,\n      \"disk\": 68,\n      \"network\": 54,\n      \"uptime\": 4557327\n    },\n    {\n      \"id\": \"host-1008\",\n      \"name\": \"prod-queue-1008\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 98,\n      \"disk\": 16,\n      \"network\": 55,\n      \"uptime\": 4913020\n    },\n    {\n      \"id\": \"host-1009\",\n      \"name\": \"prod-web-1009\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 98,\n      \"disk\": 49,\n      \"network\": 3,\n      \"uptime\": 2469747\n    },\n    {\n      \"id\": \"host-1010\",\n      \"name\": \"prod-api-1010\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 47,\n      \"disk\": 80,\n      \"network\": 48,\n      \"uptime\": 1376391\n    },\n    {\n      \"id\": \"host-1011\",\n      \"name\": \"prod-database-1011\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 33,\n      \"disk\": 76,\n      \"network\": 4,\n      \"uptime\": 1577526\n    },\n    {\n      \"id\": \"host-1012\",\n      \"name\": \"prod-cache-1012\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 47,\n      \"disk\": 55,\n      \"network\": 68,\n      \"uptime\": 2648406\n    },\n    {\n      \"id\": \"host-1013\",\n      \"name\": \"prod-worker-1013\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 24,\n      \"disk\": 41,\n      \"network\": 90,\n      \"uptime\": 5827223\n    },\n    {\n      \"id\": \"host-1014\",\n      \"name\": \"prod-queue-1014\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 11,\n      \"disk\": 60,\n      \"network\": 48,\n      \"uptime\": 3235688\n    },\n    {\n      \"id\": \"host-1015\",\n      \"name\": \"prod-web-1015\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 46,\n      \"disk\": 5,\n      \"network\": 60,\n      \"uptime\": 264349\n    },\n    {\n      \"id\": \"host-1016\",\n      \"name\": \"prod-api-1016\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 3,\n      \"disk\": 3,\n      \"network\": 62,\n      \"uptime\": 8778653\n    },\n    {\n      \"id\": \"host-1017\",\n      \"name\": \"prod-database-1017\",\n      \"status\": \"healthy\",\n      \"cpu\": 69,\n      \"memory\": 82,\n      \"disk\": 45,\n      \"network\": 3,\n      \"uptime\": 3978156\n    },\n    {\n      \"id\": \"host-1018\",\n      \"name\": \"prod-cache-1018\",\n      \"status\": \"healthy\",\n      \"cpu\": 30,\n      \"memory\": 72,\n      \"disk\": 34,\n      \"network\": 61,\n      \"uptime\": 4697151\n    },\n    {\n      \"id\": \"host-1019\",\n      \"name\": \"prod-worker-1019\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 39,\n      \"disk\": 11,\n      \"network\": 13,\n      \"uptime\": 4925817\n    },\n    {\n      \"id\": \"host-1020\",\n      \"name\": \"prod-queue-1020\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 30,\n      \"disk\": 7,\n      \"network\": 78,\n      \"uptime\": 8246938\n    },\n    {\n      \"id\": \"host-1021\",\n      \"name\": \"prod-web-1021\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 71,\n      \"disk\": 43,\n      \"network\": 89,\n      \"uptime\": 3989904\n    },\n    {\n      \"id\": \"host-1022\",\n      \"name\": \"prod-api-1022\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 82,\n      \"disk\": 8,\n      \"network\": 95,\n      \"uptime\": 6794181\n    },\n    {\n      \"id\": \"host-1023\",\n      \"name\": \"prod-database-1023\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 48,\n      \"disk\": 16,\n      \"network\": 97,\n      \"uptime\": 7658013\n    },\n    {\n      \"id\": \"host-1024\",\n      \"name\": \"prod-cache-1024\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 55,\n      \"disk\": 95,\n      \"network\": 70,\n      \"uptime\": 2139288\n    },\n    {\n      \"id\": \"host-1025\",\n      \"name\": \"prod-worker-1025\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 25,\n      \"disk\": 47,\n      \"network\": 87,\n      \"uptime\": 3330035\n    },\n    {\n      \"id\": \"host-1026\",\n      \"name\": \"prod-queue-1026\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 29,\n      \"disk\": 28,\n      \"network\": 2,\n      \"uptime\": 3540252\n    },\n    {\n      \"id\": \"host-1027\",\n      \"name\": \"prod-web-1027\",\n      \"status\": \"healthy\",\n      \"cpu\": 16,\n      \"memory\": 28,\n      \"disk\": 70,\n      \"network\": 61,\n      \"uptime\": 6480293\n    },\n    {\n      \"id\": \"host-1028\",\n      \"name\": \"prod-api-1028\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 12,\n      \"disk\": 33,\n      \"network\": 8,\n      \"uptime\": 8891314\n    },\n    {\n      \"id\": \"host-1029\",\n      \"name\": \"prod-database-1029\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 49,\n      \"disk\": 58,\n      \"network\": 58,\n      \"uptime\": 7381478\n    },\n    {\n      \"id\": \"host-1030\",\n      \"name\": \"prod-cache-1030\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 93,\n      \"disk\": 15,\n      \"network\": 31,\n      \"uptime\": 4285336\n    },\n    {\n      \"id\": \"host-1031\",\n      \"name\": \"prod-worker-1031\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 81,\n      \"disk\": 78,\n      \"network\": 90,\n      \"uptime\": 1513192\n    },\n    {\n      \"id\": \"host-1032\",\n      \"name\": \"prod-queue-1032\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 7,\n      \"disk\": 93,\n      \"network\": 5,\n      \"uptime\": 7030983\n    },\n    {\n      \"id\": \"host-1033\",\n      \"name\": \"prod-web-1033\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 27,\n      \"disk\": 2,\n      \"network\": 26,\n      \"uptime\": 8941466\n    },\n    {\n      \"id\": \"host-1034\",\n      \"name\": \"prod-api-1034\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 35,\n      \"disk\": 80,\n      \"network\": 71,\n      \"uptime\": 7703377\n    },\n    {\n      \"id\": \"host-1035\",\n      \"name\": \"prod-database-1035\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 40,\n      \"disk\": 50,\n      \"network\": 96,\n      \"uptime\": 7273465\n    },\n    {\n      \"id\": \"host-1036\",\n      \"name\": \"prod-cache-1036\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 87,\n      \"disk\": 94,\n      \"network\": 31,\n      \"uptime\": 6763674\n    },\n    {\n      \"id\": \"host-1037\",\n      \"name\": \"prod-worker-1037\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 91,\n      \"disk\": 5,\n      \"network\": 90,\n      \"uptime\": 2345584\n    },\n    {\n      \"id\": \"host-1038\",\n      \"name\": \"prod-queue-1038\",\n      \"status\": \"healthy\",\n      \"cpu\": 75,\n      \"memory\": 9,\n      \"disk\": 30,\n      \"network\": 94,\n      \"uptime\": 7214172\n    },\n    {\n      \"id\": \"host-1039\",\n      \"name\": \"prod-web-1039\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 67,\n      \"disk\": 30,\n      \"network\": 86,\n      \"uptime\": 6215728\n    },\n    {\n      \"id\": \"host-1040\",\n      \"name\": \"prod-api-1040\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 99,\n      \"disk\": 21,\n      \"network\": 50,\n      \"uptime\": 6023488\n    },\n    {\n      \"id\": \"host-1041\",\n      \"name\": \"prod-database-1041\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 60,\n      \"disk\": 32,\n      \"network\": 52,\n      \"uptime\": 725558\n    },\n    {\n      \"id\": \"host-1042\",\n      \"name\": \"prod-cache-1042\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 69,\n      \"disk\": 83,\n      \"network\": 98,\n      \"uptime\": 3628638\n    },\n    {\n      \"id\": \"host-1043\",\n      \"name\": \"prod-worker-1043\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 87,\n      \"disk\": 100,\n      \"network\": 51,\n      \"uptime\": 9236222\n    },\n    {\n      \"id\": \"host-1044\",\n      \"name\": \"prod-queue-1044\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 33,\n      \"disk\": 7,\n      \"network\": 62,\n      \"uptime\": 4178202\n    },\n    {\n      \"id\": \"host-1045\",\n      \"name\": \"prod-web-1045\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 54,\n      \"disk\": 74,\n      \"network\": 40,\n      \"uptime\": 9354828\n    },\n    {\n      \"id\": \"host-1046\",\n      \"name\": \"prod-api-1046\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 48,\n      \"disk\": 87,\n      \"network\": 10,\n      \"uptime\": 8522119\n    },\n    {\n      \"id\": \"host-1047\",\n      \"name\": \"prod-database-1047\",\n      \"status\": \"healthy\",\n      \"cpu\": 13,\n      \"memory\": 43,\n      \"disk\": 92,\n      \"network\": 19,\n      \"uptime\": 830131\n    },\n    {\n      \"id\": \"host-1048\",\n      \"name\": \"prod-cache-1048\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 28,\n      \"disk\": 63,\n      \"network\": 24,\n      \"uptime\": 2435699\n    },\n    {\n      \"id\": \"host-1049\",\n      \"name\": \"prod-worker-1049\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 80,\n      \"disk\": 92,\n      \"network\": 34,\n      \"uptime\": 8171728\n    },\n    {\n      \"id\": \"host-1050\",\n      \"name\": \"prod-queue-1050\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 33,\n      \"disk\": 22,\n      \"network\": 87,\n      \"uptime\": 908633\n    },\n    {\n      \"id\": \"host-1051\",\n      \"name\": \"prod-web-1051\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 92,\n      \"disk\": 64,\n      \"network\": 61,\n      \"uptime\": 3226216\n    },\n    {\n      \"id\": \"host-1052\",\n      \"name\": \"prod-api-1052\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 33,\n      \"disk\": 46,\n      \"network\": 46,\n      \"uptime\": 4741553\n    },\n    {\n      \"id\": \"host-1053\",\n      \"name\": \"prod-database-1053\",\n      \"status\": \"healthy\",\n      \"cpu\": 13,\n      \"memory\": 25,\n      \"disk\": 86,\n      \"network\": 65,\n      \"uptime\": 1446822\n    },\n    {\n      \"id\": \"host-1054\",\n      \"name\": \"prod-cache-1054\",\n      \"status\": \"healthy\",\n      \"cpu\": 95,\n      \"memory\": 27,\n      \"disk\": 76,\n      \"network\": 91,\n      \"uptime\": 5884107\n    },\n    {\n      \"id\": \"host-1055\",\n      \"name\": \"prod-worker-1055\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 87,\n      \"disk\": 98,\n      \"network\": 48,\n      \"uptime\": 584317\n    },\n    {\n      \"id\": \"host-1056\",\n      \"name\": \"prod-queue-1056\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 46,\n      \"disk\": 68,\n      \"network\": 60,\n      \"uptime\": 1377764\n    },\n    {\n      \"id\": \"host-1057\",\n      \"name\": \"prod-web-1057\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 60,\n      \"disk\": 12,\n      \"network\": 82,\n      \"uptime\": 1180044\n    },\n    {\n      \"id\": \"host-1058\",\n      \"name\": \"prod-api-1058\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 80,\n      \"disk\": 6,\n      \"network\": 16,\n      \"uptime\": 2291536\n    },\n    {\n      \"id\": \"host-1059\",\n      \"name\": \"prod-database-1059\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 58,\n      \"disk\": 3,\n      \"network\": 76,\n      \"uptime\": 2462991\n    },\n    {\n      \"id\": \"host-1060\",\n      \"name\": \"prod-cache-1060\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 7,\n      \"disk\": 45,\n      \"network\": 58,\n      \"uptime\": 8667441\n    },\n    {\n      \"id\": \"host-1061\",\n      \"name\": \"prod-worker-1061\",\n      \"status\": \"warning\",\n      \"cpu\": 45,\n      \"memory\": 91,\n      \"disk\": 30,\n      \"network\": 20,\n      \"uptime\": 555242\n    },\n    {\n      \"id\": \"host-1062\",\n      \"name\": \"prod-queue-1062\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 88,\n      \"disk\": 37,\n      \"network\": 36,\n      \"uptime\": 3294807\n    },\n    {\n      \"id\": \"host-1063\",\n      \"name\": \"prod-web-1063\",\n      \"status\": \"warning\",\n      \"cpu\": 99,\n      \"memory\": 44,\n      \"disk\": 18,\n      \"network\": 94,\n      \"uptime\": 1945963\n    },\n    {\n      \"id\": \"host-1064\",\n      \"name\": \"prod-api-1064\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 74,\n      \"disk\": 27,\n      \"network\": 50,\n      \"uptime\": 996776\n    },\n    {\n      \"id\": \"host-1065\",\n      \"name\": \"prod-database-1065\",\n      \"status\": \"warning\",\n      \"cpu\": 30,\n      \"memory\": 22,\n      \"disk\": 6,\n      \"network\": 99,\n      \"uptime\": 5730930\n    },\n    {\n      \"id\": \"host-1066\",\n      \"name\": \"prod-cache-1066\",\n      \"status\": \"warning\",\n      \"cpu\": 21,\n      \"memory\": 86,\n      \"disk\": 100,\n      \"network\": 97,\n      \"uptime\": 3542207\n    },\n    {\n      \"id\": \"host-1067\",\n      \"name\": \"prod-worker-1067\",\n      \"status\": \"warning\",\n      \"cpu\": 44,\n      \"memory\": 5,\n      \"disk\": 64,\n      \"network\": 65,\n      \"uptime\": 2931539\n    },\n    {\n      \"id\": \"host-1068\",\n      \"name\": \"prod-queue-1068\",\n      \"status\": \"warning\",\n      \"cpu\": 96,\n      \"memory\": 3,\n      \"disk\": 75,\n      \"network\": 4,\n      \"uptime\": 6269090\n    },\n    {\n      \"id\": \"host-1069\",\n      \"name\": \"prod-web-1069\",\n      \"status\": \"warning\",\n      \"cpu\": 90,\n      \"memory\": 0,\n      \"disk\": 68,\n      \"network\": 5,\n      \"uptime\": 7305296\n    },\n    {\n      \"id\": \"host-1070\",\n      \"name\": \"prod-api-1070\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 41,\n      \"disk\": 38,\n      \"network\": 70,\n      \"uptime\": 4874523\n    },\n    {\n      \"id\": \"host-1071\",\n      \"name\": \"prod-database-1071\",\n      \"status\": \"warning\",\n      \"cpu\": 52,\n      \"memory\": 23,\n      \"disk\": 50,\n      \"network\": 74,\n      \"uptime\": 7311395\n    },\n    {\n      \"id\": \"host-1072\",\n      \"name\": \"prod-cache-1072\",\n      \"status\": \"warning\",\n      \"cpu\": 96,\n      \"memory\": 61,\n      \"disk\": 60,\n      \"network\": 25,\n      \"uptime\": 197745\n    },\n    {\n      \"id\": \"host-1073\",\n      \"name\": \"prod-worker-1073\",\n      \"status\": \"warning\",\n      \"cpu\": 72,\n      \"memory\": 47,\n      \"disk\": 5,\n      \"network\": 43,\n      \"uptime\": 4501594\n    },\n    {\n      \"id\": \"host-1074\",\n      \"name\": \"prod-queue-1074\",\n      \"status\": \"warning\",\n      \"cpu\": 37,\n      \"memory\": 3,\n      \"disk\": 5,\n      \"network\": 66,\n      \"uptime\": 8384680\n    },\n    {\n      \"id\": \"host-1075\",\n      \"name\": \"prod-web-1075\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 33,\n      \"disk\": 27,\n      \"network\": 27,\n      \"uptime\": 1277062\n    },\n    {\n      \"id\": \"host-1076\",\n      \"name\": \"prod-api-1076\",\n      \"status\": \"warning\",\n      \"cpu\": 88,\n      \"memory\": 69,\n      \"disk\": 56,\n      \"network\": 29,\n      \"uptime\": 6789936\n    },\n    {\n      \"id\": \"host-1077\",\n      \"name\": \"prod-database-1077\",\n      \"status\": \"warning\",\n      \"cpu\": 100,\n      \"memory\": 21,\n      \"disk\": 0,\n      \"network\": 98,\n      \"uptime\": 8029847\n    },\n    {\n      \"id\": \"host-1078\",\n      \"name\": \"prod-cache-1078\",\n      \"status\": \"warning\",\n      \"cpu\": 43,\n      \"memory\": 55,\n      \"disk\": 2,\n      \"network\": 47,\n      \"uptime\": 7167421\n    },\n    {\n      \"id\": \"host-1079\",\n      \"name\": \"prod-worker-1079\",\n      \"status\": \"warning\",\n      \"cpu\": 38,\n      \"memory\": 52,\n      \"disk\": 13,\n      \"network\": 78,\n      \"uptime\": 8274028\n    },\n    {\n      \"id\": \"host-1080\",\n      \"name\": \"prod-queue-1080\",\n      \"status\": \"warning\",\n      \"cpu\": 20,\n      \"memory\": 19,\n      \"disk\": 33,\n      \"network\": 48,\n      \"uptime\": 3339953\n    },\n    {\n      \"id\": \"host-1081\",\n      \"name\": \"prod-web-1081\",\n      \"status\": \"warning\",\n      \"cpu\": 46,\n      \"memory\": 55,\n      \"disk\": 33,\n      \"network\": 13,\n      \"uptime\": 1662348\n    },\n    {\n      \"id\": \"host-1082\",\n      \"name\": \"prod-api-1082\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 34,\n      \"disk\": 4,\n      \"network\": 45,\n      \"uptime\": 1440295\n    },\n    {\n      \"id\": \"host-1083\",\n      \"name\": \"prod-database-1083\",\n      \"status\": \"warning\",\n      \"cpu\": 52,\n      \"memory\": 99,\n      \"disk\": 97,\n      \"network\": 34,\n      \"uptime\": 9625346\n    },\n    {\n      \"id\": \"host-1084\",\n      \"name\": \"prod-cache-1084\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 73,\n      \"disk\": 18,\n      \"network\": 78,\n      \"uptime\": 9935984\n    },\n    {\n      \"id\": \"host-1085\",\n      \"name\": \"prod-worker-1085\",\n      \"status\": \"warning\",\n      \"cpu\": 3,\n      \"memory\": 62,\n      \"disk\": 72,\n      \"network\": 50,\n      \"uptime\": 3701873\n    },\n    {\n      \"id\": \"host-1086\",\n      \"name\": \"prod-queue-1086\",\n      \"status\": \"critical\",\n      \"cpu\": 85,\n      \"memory\": 68,\n      \"disk\": 38,\n      \"network\": 65,\n      \"uptime\": 1295923\n    },\n    {\n      \"id\": \"host-1087\",\n      \"name\": \"prod-web-1087\",\n      \"status\": \"critical\",\n      \"cpu\": 67,\n      \"memory\": 58,\n      \"disk\": 45,\n      \"network\": 54,\n      \"uptime\": 9459348\n    },\n    {\n      \"id\": \"host-1088\",\n      \"name\": \"prod-api-1088\",\n      \"status\": \"critical\",\n      \"cpu\": 73,\n      \"memory\": 8,\n      \"disk\": 74,\n      \"network\": 60,\n      \"uptime\": 5347759\n    },\n    {\n      \"id\": \"host-1089\",\n      \"name\": \"prod-database-1089\",\n      \"status\": \"critical\",\n      \"cpu\": 88,\n      \"memory\": 34,\n      \"disk\": 95,\n      \"network\": 100,\n      \"uptime\": 8429470\n    },\n    {\n      \"id\": \"host-1090\",\n      \"name\": \"prod-cache-1090\",\n      \"status\": \"critical\",\n      \"cpu\": 23,\n      \"memory\": 52,\n      \"disk\": 86,\n      \"network\": 16,\n      \"uptime\": 2803411\n    },\n    {\n      \"id\": \"host-1091\",\n      \"name\": \"prod-worker-1091\",\n      \"status\": \"critical\",\n      \"cpu\": 81,\n      \"memory\": 10,\n      \"disk\": 25,\n      \"network\": 98,\n      \"uptime\": 136055\n    },\n    {\n      \"id\": \"host-1092\",\n      \"name\": \"prod-queue-1092\",\n      \"status\": \"critical\",\n      \"cpu\": 29,\n      \"memory\": 31,\n      \"disk\": 18,\n      \"network\": 52,\n      \"uptime\": 2844668\n    },\n    {\n      \"id\": \"host-1093\",\n      \"name\": \"prod-web-1093\",\n      \"status\": \"critical\",\n      \"cpu\": 52,\n      \"memory\": 35,\n      \"disk\": 18,\n      \"network\": 74,\n      \"uptime\": 9244115\n    },\n    {\n      \"id\": \"host-1094\",\n      \"name\": \"prod-api-1094\",\n      \"status\": \"critical\",\n      \"cpu\": 43,\n      \"memory\": 28,\n      \"disk\": 16,\n      \"network\": 94,\n      \"uptime\": 2863542\n    },\n    {\n      \"id\": \"host-1095\",\n      \"name\": \"prod-database-1095\",\n      \"status\": \"critical\",\n      \"cpu\": 21,\n      \"memory\": 61,\n      \"disk\": 73,\n      \"network\": 12,\n      \"uptime\": 7723960\n    },\n    {\n      \"id\": \"host-1096\",\n      \"name\": \"prod-cache-1096\",\n      \"status\": \"critical\",\n      \"cpu\": 60,\n      \"memory\": 11,\n      \"disk\": 62,\n      \"network\": 65,\n      \"uptime\": 6846412\n    },\n    {\n      \"id\": \"host-1097\",\n      \"name\": \"prod-worker-1097\",\n      \"status\": \"critical\",\n      \"cpu\": 58,\n      \"memory\": 59,\n      \"disk\": 4,\n      \"network\": 26,\n      \"uptime\": 2464006\n    },\n    {\n      \"id\": \"host-1098\",\n      \"name\": \"prod-queue-1098\",\n      \"status\": \"critical\",\n      \"cpu\": 2,\n      \"memory\": 97,\n      \"disk\": 19,\n      \"network\": 81,\n      \"uptime\": 9286427\n    },\n    {\n      \"id\": \"host-1099\",\n      \"name\": \"prod-web-1099\",\n      \"status\": \"critical\",\n      \"cpu\": 86,\n      \"memory\": 55,\n      \"disk\": 24,\n      \"network\": 30,\n      \"uptime\": 7339566\n    },\n    {\n      \"id\": \"host-1100\",\n      \"name\": \"prod-api-1100\",\n      \"status\": \"critical\",\n      \"cpu\": 57,\n      \"memory\": 38,\n      \"disk\": 12,\n      \"network\": 36,\n      \"uptime\": 6313988\n    },\n    {\n      \"id\": \"host-1101\",\n      \"name\": \"prod-database-1101\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 96,\n      \"disk\": 13,\n      \"network\": 74,\n      \"uptime\": 1185833\n    },\n    {\n      \"id\": \"host-1102\",\n      \"name\": \"prod-cache-1102\",\n      \"status\": \"healthy\",\n      \"cpu\": 74,\n      \"memory\": 40,\n      \"disk\": 0,\n      \"network\": 78,\n      \"uptime\": 3286405\n    },\n    {\n      \"id\": \"host-1103\",\n      \"name\": \"prod-worker-1103\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 89,\n      \"disk\": 72,\n      \"network\": 3,\n      \"uptime\": 9129617\n    },\n    {\n      \"id\": \"host-1104\",\n      \"name\": \"prod-queue-1104\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 91,\n      \"disk\": 85,\n      \"network\": 9,\n      \"uptime\": 8695740\n    },\n    {\n      \"id\": \"host-1105\",\n      \"name\": \"prod-web-1105\",\n      \"status\": \"healthy\",\n      \"cpu\": 79,\n      \"memory\": 60,\n      \"disk\": 78,\n      \"network\": 83,\n      \"uptime\": 4738937\n    },\n    {\n      \"id\": \"host-1106\",\n      \"name\": \"prod-api-1106\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 42,\n      \"disk\": 82,\n      \"network\": 71,\n      \"uptime\": 4462189\n    },\n    {\n      \"id\": \"host-1107\",\n      \"name\": \"prod-database-1107\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 95,\n      \"disk\": 70,\n      \"network\": 29,\n      \"uptime\": 9381692\n    },\n    {\n      \"id\": \"host-1108\",\n      \"name\": \"prod-cache-1108\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 21,\n      \"disk\": 78,\n      \"network\": 75,\n      \"uptime\": 1699976\n    },\n    {\n      \"id\": \"host-1109\",\n      \"name\": \"prod-worker-1109\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 51,\n      \"disk\": 46,\n      \"network\": 37,\n      \"uptime\": 7424513\n    },\n    {\n      \"id\": \"host-1110\",\n      \"name\": \"prod-queue-1110\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 44,\n      \"disk\": 39,\n      \"network\": 2,\n      \"uptime\": 77721\n    },\n    {\n      \"id\": \"host-1111\",\n      \"name\": \"prod-web-1111\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 55,\n      \"disk\": 58,\n      \"network\": 70,\n      \"uptime\": 147746\n    },\n    {\n      \"id\": \"host-1112\",\n      \"name\": \"prod-api-1112\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 91,\n      \"disk\": 93,\n      \"network\": 14,\n      \"uptime\": 1029646\n    },\n    {\n      \"id\": \"host-1113\",\n      \"name\": \"prod-database-1113\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 34,\n      \"disk\": 99,\n      \"network\": 37,\n      \"uptime\": 9911423\n    },\n    {\n      \"id\": \"host-1114\",\n      \"name\": \"prod-cache-1114\",\n      \"status\": \"healthy\",\n      \"cpu\": 44,\n      \"memory\": 4,\n      \"disk\": 80,\n      \"network\": 89,\n      \"uptime\": 2359625\n    },\n    {\n      \"id\": \"host-1115\",\n      \"name\": \"prod-worker-1115\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 13,\n      \"disk\": 11,\n      \"network\": 78,\n      \"uptime\": 8421582\n    },\n    {\n      \"id\": \"host-1116\",\n      \"name\": \"prod-queue-1116\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 31,\n      \"disk\": 51,\n      \"network\": 17,\n      \"uptime\": 4934947\n    },\n    {\n      \"id\": \"host-1117\",\n      \"name\": \"prod-web-1117\",\n      \"status\": \"healthy\",\n      \"cpu\": 91,\n      \"memory\": 55,\n      \"disk\": 84,\n      \"network\": 32,\n      \"uptime\": 1721149\n    },\n    {\n      \"id\": \"host-1118\",\n      \"name\": \"prod-api-1118\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 64,\n      \"disk\": 92,\n      \"network\": 44,\n      \"uptime\": 9856992\n    },\n    {\n      \"id\": \"host-1119\",\n      \"name\": \"prod-database-1119\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 99,\n      \"disk\": 97,\n      \"network\": 79,\n      \"uptime\": 797227\n    },\n    {\n      \"id\": \"host-1120\",\n      \"name\": \"prod-cache-1120\",\n      \"status\": \"healthy\",\n      \"cpu\": 7,\n      \"memory\": 22,\n      \"disk\": 87,\n      \"network\": 26,\n      \"uptime\": 8836138\n    },\n    {\n      \"id\": \"host-1121\",\n      \"name\": \"prod-worker-1121\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 58,\n      \"disk\": 12,\n      \"network\": 87,\n      \"uptime\": 8137089\n    },\n    {\n      \"id\": \"host-1122\",\n      \"name\": \"prod-queue-1122\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 70,\n      \"disk\": 95,\n      \"network\": 91,\n      \"uptime\": 6989823\n    },\n    {\n      \"id\": \"host-1123\",\n      \"name\": \"prod-web-1123\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 75,\n      \"disk\": 40,\n      \"network\": 1,\n      \"uptime\": 6921266\n    },\n    {\n      \"id\": \"host-1124\",\n      \"name\": \"prod-api-1124\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 64,\n      \"disk\": 91,\n      \"network\": 15,\n      \"uptime\": 7762017\n    },\n    {\n      \"id\": \"host-1125\",\n      \"name\": \"prod-database-1125\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 88,\n      \"disk\": 57,\n      \"network\": 62,\n      \"uptime\": 2734692\n    },\n    {\n      \"id\": \"host-1126\",\n      \"name\": \"prod-cache-1126\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 15,\n      \"disk\": 18,\n      \"network\": 21,\n      \"uptime\": 7335778\n    },\n    {\n      \"id\": \"host-1127\",\n      \"name\": \"prod-worker-1127\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 25,\n      \"disk\": 27,\n      \"network\": 12,\n      \"uptime\": 6526145\n    },\n    {\n      \"id\": \"host-1128\",\n      \"name\": \"prod-queue-1128\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 85,\n      \"disk\": 68,\n      \"network\": 78,\n      \"uptime\": 8798347\n    },\n    {\n      \"id\": \"host-1129\",\n      \"name\": \"prod-web-1129\",\n      \"status\": \"healthy\",\n      \"cpu\": 29,\n      \"memory\": 57,\n      \"disk\": 62,\n      \"network\": 98,\n      \"uptime\": 6898703\n    },\n    {\n      \"id\": \"host-1130\",\n      \"name\": \"prod-api-1130\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 68,\n      \"disk\": 80,\n      \"network\": 49,\n      \"uptime\": 9365566\n    },\n    {\n      \"id\": \"host-1131\",\n      \"name\": \"prod-database-1131\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 41,\n      \"disk\": 11,\n      \"network\": 19,\n      \"uptime\": 168943\n    },\n    {\n      \"id\": \"host-1132\",\n      \"name\": \"prod-cache-1132\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 46,\n      \"disk\": 64,\n      \"network\": 80,\n      \"uptime\": 2934335\n    },\n    {\n      \"id\": \"host-1133\",\n      \"name\": \"prod-worker-1133\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 58,\n      \"disk\": 29,\n      \"network\": 7,\n      \"uptime\": 7177484\n    },\n    {\n      \"id\": \"host-1134\",\n      \"name\": \"prod-queue-1134\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 89,\n      \"disk\": 22,\n      \"network\": 55,\n      \"uptime\": 809616\n    },\n    {\n      \"id\": \"host-1135\",\n      \"name\": \"prod-web-1135\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 87,\n      \"disk\": 43,\n      \"network\": 59,\n      \"uptime\": 9569323\n    },\n    {\n      \"id\": \"host-1136\",\n      \"name\": \"prod-api-1136\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 52,\n      \"disk\": 85,\n      \"network\": 83,\n      \"uptime\": 4667178\n    },\n    {\n      \"id\": \"host-1137\",\n      \"name\": \"prod-database-1137\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 93,\n      \"disk\": 43,\n      \"network\": 49,\n      \"uptime\": 5149328\n    },\n    {\n      \"id\": \"host-1138\",\n      \"name\": \"prod-cache-1138\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 87,\n      \"disk\": 88,\n      \"network\": 19,\n      \"uptime\": 1603138\n    },\n    {\n      \"id\": \"host-1139\",\n      \"name\": \"prod-worker-1139\",\n      \"status\": \"healthy\",\n      \"cpu\": 77,\n      \"memory\": 70,\n      \"disk\": 58,\n      \"network\": 59,\n      \"uptime\": 1936102\n    },\n    {\n      \"id\": \"host-1140\",\n      \"name\": \"prod-queue-1140\",\n      \"status\": \"healthy\",\n      \"cpu\": 50,\n      \"memory\": 0,\n      \"disk\": 52,\n      \"network\": 83,\n      \"uptime\": 4999321\n    },\n    {\n      \"id\": \"host-1141\",\n      \"name\": \"prod-web-1141\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 59,\n      \"disk\": 29,\n      \"network\": 19,\n      \"uptime\": 5719788\n    },\n    {\n      \"id\": \"host-1142\",\n      \"name\": \"prod-api-1142\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 68,\n      \"disk\": 18,\n      \"network\": 84,\n      \"uptime\": 8340058\n    },\n    {\n      \"id\": \"host-1143\",\n      \"name\": \"prod-database-1143\",\n      \"status\": \"healthy\",\n      \"cpu\": 57,\n      \"memory\": 93,\n      \"disk\": 44,\n      \"network\": 36,\n      \"uptime\": 5923349\n    },\n    {\n      \"id\": \"host-1144\",\n      \"name\": \"prod-cache-1144\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 58,\n      \"disk\": 1,\n      \"network\": 95,\n      \"uptime\": 9902963\n    },\n    {\n      \"id\": \"host-1145\",\n      \"name\": \"prod-worker-1145\",\n      \"status\": \"healthy\",\n      \"cpu\": 6,\n      \"memory\": 24,\n      \"disk\": 18,\n      \"network\": 36,\n      \"uptime\": 6689778\n    },\n    {\n      \"id\": \"host-1146\",\n      \"name\": \"prod-queue-1146\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 36,\n      \"disk\": 68,\n      \"network\": 17,\n      \"uptime\": 5101820\n    },\n    {\n      \"id\": \"host-1147\",\n      \"name\": \"prod-web-1147\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 90,\n      \"disk\": 0,\n      \"network\": 31,\n      \"uptime\": 1231088\n    },\n    {\n      \"id\": \"host-1148\",\n      \"name\": \"prod-api-1148\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 43,\n      \"disk\": 1,\n      \"network\": 89,\n      \"uptime\": 3950602\n    },\n    {\n      \"id\": \"host-1149\",\n      \"name\": \"prod-database-1149\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 94,\n      \"disk\": 10,\n      \"network\": 89,\n      \"uptime\": 4996506\n    },\n    {\n      \"id\": \"host-1150\",\n      \"name\": \"prod-cache-1150\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 42,\n      \"disk\": 31,\n      \"network\": 87,\n      \"uptime\": 3863167\n    },\n    {\n      \"id\": \"host-1151\",\n      \"name\": \"prod-worker-1151\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 9,\n      \"disk\": 100,\n      \"network\": 56,\n      \"uptime\": 1522316\n    },\n    {\n      \"id\": \"host-1152\",\n      \"name\": \"prod-queue-1152\",\n      \"status\": \"healthy\",\n      \"cpu\": 84,\n      \"memory\": 47,\n      \"disk\": 0,\n      \"network\": 50,\n      \"uptime\": 1415462\n    },\n    {\n      \"id\": \"host-1153\",\n      \"name\": \"prod-web-1153\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 77,\n      \"disk\": 40,\n      \"network\": 26,\n      \"uptime\": 3846814\n    },\n    {\n      \"id\": \"host-1154\",\n      \"name\": \"prod-api-1154\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 78,\n      \"disk\": 87,\n      \"network\": 11,\n      \"uptime\": 8460340\n    },\n    {\n      \"id\": \"host-1155\",\n      \"name\": \"prod-database-1155\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 18,\n      \"disk\": 96,\n      \"network\": 80,\n      \"uptime\": 8714873\n    },\n    {\n      \"id\": \"host-1156\",\n      \"name\": \"prod-cache-1156\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 46,\n      \"disk\": 80,\n      \"network\": 49,\n      \"uptime\": 9333299\n    },\n    {\n      \"id\": \"host-1157\",\n      \"name\": \"prod-worker-1157\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 10,\n      \"disk\": 89,\n      \"network\": 78,\n      \"uptime\": 9983461\n    },\n    {\n      \"id\": \"host-1158\",\n      \"name\": \"prod-queue-1158\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 24,\n      \"disk\": 30,\n      \"network\": 23,\n      \"uptime\": 3938023\n    },\n    {\n      \"id\": \"host-1159\",\n      \"name\": \"prod-web-1159\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 42,\n      \"disk\": 83,\n      \"network\": 34,\n      \"uptime\": 5592893\n    },\n    {\n      \"id\": \"host-1160\",\n      \"name\": \"prod-api-1160\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 24,\n      \"disk\": 43,\n      \"network\": 39,\n      \"uptime\": 7295253\n    },\n    {\n      \"id\": \"host-1161\",\n      \"name\": \"prod-database-1161\",\n      \"status\": \"warning\",\n      \"cpu\": 27,\n      \"memory\": 73,\n      \"disk\": 61,\n      \"network\": 64,\n      \"uptime\": 7535644\n    },\n    {\n      \"id\": \"host-1162\",\n      \"name\": \"prod-cache-1162\",\n      \"status\": \"warning\",\n      \"cpu\": 32,\n      \"memory\": 32,\n      \"disk\": 85,\n      \"network\": 39,\n      \"uptime\": 2001035\n    },\n    {\n      \"id\": \"host-1163\",\n      \"name\": \"prod-worker-1163\",\n      \"status\": \"warning\",\n      \"cpu\": 11,\n      \"memory\": 63,\n      \"disk\": 32,\n      \"network\": 70,\n      \"uptime\": 4085699\n    },\n    {\n      \"id\": \"host-1164\",\n      \"name\": \"prod-queue-1164\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 79,\n      \"disk\": 69,\n      \"network\": 67,\n      \"uptime\": 4859045\n    },\n    {\n      \"id\": \"host-1165\",\n      \"name\": \"prod-web-1165\",\n      \"status\": \"warning\",\n      \"cpu\": 51,\n      \"memory\": 100,\n      \"disk\": 97,\n      \"network\": 25,\n      \"uptime\": 2238839\n    },\n    {\n      \"id\": \"host-1166\",\n      \"name\": \"prod-api-1166\",\n      \"status\": \"warning\",\n      \"cpu\": 32,\n      \"memory\": 27,\n      \"disk\": 8,\n      \"network\": 27,\n      \"uptime\": 4082259\n    },\n    {\n      \"id\": \"host-1167\",\n      \"name\": \"prod-database-1167\",\n      \"status\": \"warning\",\n      \"cpu\": 12,\n      \"memory\": 42,\n      \"disk\": 13,\n      \"network\": 16,\n      \"uptime\": 5800918\n    },\n    {\n      \"id\": \"host-1168\",\n      \"name\": \"prod-cache-1168\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 20,\n      \"disk\": 1,\n      \"network\": 73,\n      \"uptime\": 9555425\n    },\n    {\n      \"id\": \"host-1169\",\n      \"name\": \"prod-worker-1169\",\n      \"status\": \"warning\",\n      \"cpu\": 3,\n      \"memory\": 90,\n      \"disk\": 2,\n      \"network\": 49,\n      \"uptime\": 3174859\n    },\n    {\n      \"id\": \"host-1170\",\n      \"name\": \"prod-queue-1170\",\n      \"status\": \"warning\",\n      \"cpu\": 73,\n      \"memory\": 28,\n      \"disk\": 1,\n      \"network\": 97,\n      \"uptime\": 2764718\n    },\n    {\n      \"id\": \"host-1171\",\n      \"name\": \"prod-web-1171\",\n      \"status\": \"warning\",\n      \"cpu\": 18,\n      \"memory\": 21,\n      \"disk\": 11,\n      \"network\": 61,\n      \"uptime\": 8035797\n    },\n    {\n      \"id\": \"host-1172\",\n      \"name\": \"prod-api-1172\",\n      \"status\": \"warning\",\n      \"cpu\": 67,\n      \"memory\": 15,\n      \"disk\": 38,\n      \"network\": 42,\n      \"uptime\": 2756479\n    },\n    {\n      \"id\": \"host-1173\",\n      \"name\": \"prod-database-1173\",\n      \"status\": \"warning\",\n      \"cpu\": 66,\n      \"memory\": 61,\n      \"disk\": 71,\n      \"network\": 4,\n      \"uptime\": 5847901\n    },\n    {\n      \"id\": \"host-1174\",\n      \"name\": \"prod-cache-1174\",\n      \"status\": \"warning\",\n      \"cpu\": 60,\n      \"memory\": 85,\n      \"disk\": 89,\n      \"network\": 33,\n      \"uptime\": 2124874\n    },\n    {\n      \"id\": \"host-1175\",\n      \"name\": \"prod-worker-1175\",\n      \"status\": \"warning\",\n      \"cpu\": 7,\n      \"memory\": 91,\n      \"disk\": 73,\n      \"network\": 66,\n      \"uptime\": 8054372\n    },\n    {\n      \"id\": \"host-1176\",\n      \"name\": \"prod-queue-1176\",\n      \"status\": \"warning\",\n      \"cpu\": 9,\n      \"memory\": 20,\n      \"disk\": 21,\n      \"network\": 71,\n      \"uptime\": 725233\n    },\n    {\n      \"id\": \"host-1177\",\n      \"name\": \"prod-web-1177\",\n      \"status\": \"warning\",\n      \"cpu\": 71,\n      \"memory\": 88,\n      \"disk\": 8,\n      \"network\": 34,\n      \"uptime\": 6356657\n    },\n    {\n      \"id\": \"host-1178\",\n      \"name\": \"prod-api-1178\",\n      \"status\": \"warning\",\n      \"cpu\": 1,\n      \"memory\": 78,\n      \"disk\": 27,\n      \"network\": 19,\n      \"uptime\": 6403104\n    },\n    {\n      \"id\": \"host-1179\",\n      \"name\": \"prod-database-1179\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 0,\n      \"disk\": 50,\n      \"network\": 69,\n      \"uptime\": 9866084\n    },\n    {\n      \"id\": \"host-1180\",\n      \"name\": \"prod-cache-1180\",\n      \"status\": \"warning\",\n      \"cpu\": 64,\n      \"memory\": 40,\n      \"disk\": 80,\n      \"network\": 97,\n      \"uptime\": 2521581\n    },\n    {\n      \"id\": \"host-1181\",\n      \"name\": \"prod-worker-1181\",\n      \"status\": \"warning\",\n      \"cpu\": 22,\n      \"memory\": 77,\n      \"disk\": 70,\n      \"network\": 71,\n      \"uptime\": 6536105\n    },\n    {\n      \"id\": \"host-1182\",\n      \"name\": \"prod-queue-1182\",\n      \"status\": \"warning\",\n      \"cpu\": 42,\n      \"memory\": 28,\n      \"disk\": 94,\n      \"network\": 19,\n      \"uptime\": 8701343\n    },\n    {\n      \"id\": \"host-1183\",\n      \"name\": \"prod-web-1183\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 64,\n      \"disk\": 35,\n      \"network\": 1,\n      \"uptime\": 8807893\n    },\n    {\n      \"id\": \"host-1184\",\n      \"name\": \"prod-api-1184\",\n      \"status\": \"warning\",\n      \"cpu\": 26,\n      \"memory\": 4,\n      \"disk\": 26,\n      \"network\": 66,\n      \"uptime\": 171675\n    },\n    {\n      \"id\": \"host-1185\",\n      \"name\": \"prod-database-1185\",\n      \"status\": \"warning\",\n      \"cpu\": 96,\n      \"memory\": 27,\n      \"disk\": 100,\n      \"network\": 52,\n      \"uptime\": 7696655\n    },\n    {\n      \"id\": \"host-1186\",\n      \"name\": \"prod-cache-1186\",\n      \"status\": \"critical\",\n      \"cpu\": 24,\n      \"memory\": 87,\n      \"disk\": 6,\n      \"network\": 33,\n      \"uptime\": 9668900\n    },\n    {\n      \"id\": \"host-1187\",\n      \"name\": \"prod-worker-1187\",\n      \"status\": \"critical\",\n      \"cpu\": 36,\n      \"memory\": 19,\n      \"disk\": 21,\n      \"network\": 33,\n      \"uptime\": 8630110\n    },\n    {\n      \"id\": \"host-1188\",\n      \"name\": \"prod-queue-1188\",\n      \"status\": \"critical\",\n      \"cpu\": 57,\n      \"memory\": 97,\n      \"disk\": 43,\n      \"network\": 24,\n      \"uptime\": 460850\n    },\n    {\n      \"id\": \"host-1189\",\n      \"name\": \"prod-web-1189\",\n      \"status\": \"critical\",\n      \"cpu\": 63,\n      \"memory\": 27,\n      \"disk\": 100,\n      \"network\": 15,\n      \"uptime\": 9702039\n    },\n    {\n      \"id\": \"host-1190\",\n      \"name\": \"prod-api-1190\",\n      \"status\": \"critical\",\n      \"cpu\": 81,\n      \"memory\": 20,\n      \"disk\": 97,\n      \"network\": 21,\n      \"uptime\": 1380177\n    },\n    {\n      \"id\": \"host-1191\",\n      \"name\": \"prod-database-1191\",\n      \"status\": \"critical\",\n      \"cpu\": 76,\n      \"memory\": 92,\n      \"disk\": 60,\n      \"network\": 99,\n      \"uptime\": 9090344\n    },\n    {\n      \"id\": \"host-1192\",\n      \"name\": \"prod-cache-1192\",\n      \"status\": \"critical\",\n      \"cpu\": 42,\n      \"memory\": 3,\n      \"disk\": 89,\n      \"network\": 10,\n      \"uptime\": 211863\n    },\n    {\n      \"id\": \"host-1193\",\n      \"name\": \"prod-worker-1193\",\n      \"status\": \"critical\",\n      \"cpu\": 44,\n      \"memory\": 76,\n      \"disk\": 6,\n      \"network\": 37,\n      \"uptime\": 9835593\n    },\n    {\n      \"id\": \"host-1194\",\n      \"name\": \"prod-queue-1194\",\n      \"status\": \"critical\",\n      \"cpu\": 27,\n      \"memory\": 17,\n      \"disk\": 85,\n      \"network\": 39,\n      \"uptime\": 6369106\n    },\n    {\n      \"id\": \"host-1195\",\n      \"name\": \"prod-web-1195\",\n      \"status\": \"critical\",\n      \"cpu\": 50,\n      \"memory\": 92,\n      \"disk\": 16,\n      \"network\": 3,\n      \"uptime\": 8030323\n    },\n    {\n      \"id\": \"host-1196\",\n      \"name\": \"prod-api-1196\",\n      \"status\": \"critical\",\n      \"cpu\": 28,\n      \"memory\": 11,\n      \"disk\": 5,\n      \"network\": 59,\n      \"uptime\": 9212861\n    },\n    {\n      \"id\": \"host-1197\",\n      \"name\": \"prod-database-1197\",\n      \"status\": \"critical\",\n      \"cpu\": 83,\n      \"memory\": 75,\n      \"disk\": 18,\n      \"network\": 68,\n      \"uptime\": 2008921\n    },\n    {\n      \"id\": \"host-1198\",\n      \"name\": \"prod-cache-1198\",\n      \"status\": \"critical\",\n      \"cpu\": 2,\n      \"memory\": 77,\n      \"disk\": 82,\n      \"network\": 89,\n      \"uptime\": 3391691\n    },\n    {\n      \"id\": \"host-1199\",\n      \"name\": \"prod-worker-1199\",\n      \"status\": \"critical\",\n      \"cpu\": 28,\n      \"memory\": 17,\n      \"disk\": 6,\n      \"network\": 22,\n      \"uptime\": 1294940\n    },\n    {\n      \"id\": \"host-1200\",\n      \"name\": \"prod-queue-1200\",\n      \"status\": \"critical\",\n      \"cpu\": 7,\n      \"memory\": 44,\n      \"disk\": 70,\n      \"network\": 29,\n      \"uptime\": 6684613\n    },\n    {\n      \"id\": \"host-1201\",\n      \"name\": \"prod-web-1201\",\n      \"status\": \"healthy\",\n      \"cpu\": 55,\n      \"memory\": 47,\n      \"disk\": 96,\n      \"network\": 99,\n      \"uptime\": 7193338\n    },\n    {\n      \"id\": \"host-1202\",\n      \"name\": \"prod-api-1202\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 39,\n      \"disk\": 72,\n      \"network\": 13,\n      \"uptime\": 1629842\n    },\n    {\n      \"id\": \"host-1203\",\n      \"name\": \"prod-database-1203\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 23,\n      \"disk\": 21,\n      \"network\": 23,\n      \"uptime\": 1537188\n    },\n    {\n      \"id\": \"host-1204\",\n      \"name\": \"prod-cache-1204\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 36,\n      \"disk\": 73,\n      \"network\": 17,\n      \"uptime\": 3583989\n    },\n    {\n      \"id\": \"host-1205\",\n      \"name\": \"prod-worker-1205\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 4,\n      \"disk\": 65,\n      \"network\": 84,\n      \"uptime\": 2211243\n    },\n    {\n      \"id\": \"host-1206\",\n      \"name\": \"prod-queue-1206\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 94,\n      \"disk\": 95,\n      \"network\": 82,\n      \"uptime\": 3357394\n    },\n    {\n      \"id\": \"host-1207\",\n      \"name\": \"prod-web-1207\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 32,\n      \"disk\": 10,\n      \"network\": 52,\n      \"uptime\": 7375534\n    },\n    {\n      \"id\": \"host-1208\",\n      \"name\": \"prod-api-1208\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 56,\n      \"disk\": 37,\n      \"network\": 5,\n      \"uptime\": 2176256\n    },\n    {\n      \"id\": \"host-1209\",\n      \"name\": \"prod-database-1209\",\n      \"status\": \"healthy\",\n      \"cpu\": 76,\n      \"memory\": 62,\n      \"disk\": 86,\n      \"network\": 86,\n      \"uptime\": 218778\n    },\n    {\n      \"id\": \"host-1210\",\n      \"name\": \"prod-cache-1210\",\n      \"status\": \"healthy\",\n      \"cpu\": 7,\n      \"memory\": 73,\n      \"disk\": 25,\n      \"network\": 47,\n      \"uptime\": 3327082\n    },\n    {\n      \"id\": \"host-1211\",\n      \"name\": \"prod-worker-1211\",\n      \"status\": \"healthy\",\n      \"cpu\": 57,\n      \"memory\": 14,\n      \"disk\": 11,\n      \"network\": 91,\n      \"uptime\": 8821471\n    },\n    {\n      \"id\": \"host-1212\",\n      \"name\": \"prod-queue-1212\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 4,\n      \"disk\": 82,\n      \"network\": 15,\n      \"uptime\": 5992272\n    },\n    {\n      \"id\": \"host-1213\",\n      \"name\": \"prod-web-1213\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 26,\n      \"disk\": 47,\n      \"network\": 33,\n      \"uptime\": 5116393\n    },\n    {\n      \"id\": \"host-1214\",\n      \"name\": \"prod-api-1214\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 82,\n      \"disk\": 89,\n      \"network\": 94,\n      \"uptime\": 211050\n    },\n    {\n      \"id\": \"host-1215\",\n      \"name\": \"prod-database-1215\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 99,\n      \"disk\": 13,\n      \"network\": 62,\n      \"uptime\": 1014685\n    },\n    {\n      \"id\": \"host-1216\",\n      \"name\": \"prod-cache-1216\",\n      \"status\": \"healthy\",\n      \"cpu\": 28,\n      \"memory\": 49,\n      \"disk\": 32,\n      \"network\": 63,\n      \"uptime\": 757477\n    },\n    {\n      \"id\": \"host-1217\",\n      \"name\": \"prod-worker-1217\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 40,\n      \"disk\": 57,\n      \"network\": 16,\n      \"uptime\": 8625546\n    },\n    {\n      \"id\": \"host-1218\",\n      \"name\": \"prod-queue-1218\",\n      \"status\": \"healthy\",\n      \"cpu\": 97,\n      \"memory\": 62,\n      \"disk\": 46,\n      \"network\": 53,\n      \"uptime\": 2865546\n    },\n    {\n      \"id\": \"host-1219\",\n      \"name\": \"prod-web-1219\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 24,\n      \"disk\": 11,\n      \"network\": 20,\n      \"uptime\": 8033260\n    },\n    {\n      \"id\": \"host-1220\",\n      \"name\": \"prod-api-1220\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 68,\n      \"disk\": 46,\n      \"network\": 15,\n      \"uptime\": 5135123\n    },\n    {\n      \"id\": \"host-1221\",\n      \"name\": \"prod-database-1221\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 42,\n      \"disk\": 89,\n      \"network\": 7,\n      \"uptime\": 5643311\n    },\n    {\n      \"id\": \"host-1222\",\n      \"name\": \"prod-cache-1222\",\n      \"status\": \"healthy\",\n      \"cpu\": 49,\n      \"memory\": 47,\n      \"disk\": 34,\n      \"network\": 70,\n      \"uptime\": 839197\n    },\n    {\n      \"id\": \"host-1223\",\n      \"name\": \"prod-worker-1223\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 14,\n      \"disk\": 53,\n      \"network\": 86,\n      \"uptime\": 9240770\n    },\n    {\n      \"id\": \"host-1224\",\n      \"name\": \"prod-queue-1224\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 19,\n      \"disk\": 62,\n      \"network\": 69,\n      \"uptime\": 7259723\n    },\n    {\n      \"id\": \"host-1225\",\n      \"name\": \"prod-web-1225\",\n      \"status\": \"healthy\",\n      \"cpu\": 40,\n      \"memory\": 48,\n      \"disk\": 95,\n      \"network\": 28,\n      \"uptime\": 1708038\n    },\n    {\n      \"id\": \"host-1226\",\n      \"name\": \"prod-api-1226\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 1,\n      \"disk\": 76,\n      \"network\": 46,\n      \"uptime\": 1071075\n    },\n    {\n      \"id\": \"host-1227\",\n      \"name\": \"prod-database-1227\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 3,\n      \"disk\": 33,\n      \"network\": 84,\n      \"uptime\": 1035448\n    },\n    {\n      \"id\": \"host-1228\",\n      \"name\": \"prod-cache-1228\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 39,\n      \"disk\": 74,\n      \"network\": 0,\n      \"uptime\": 5700532\n    },\n    {\n      \"id\": \"host-1229\",\n      \"name\": \"prod-worker-1229\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 32,\n      \"disk\": 67,\n      \"network\": 49,\n      \"uptime\": 3787727\n    },\n    {\n      \"id\": \"host-1230\",\n      \"name\": \"prod-queue-1230\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 63,\n      \"disk\": 26,\n      \"network\": 16,\n      \"uptime\": 8865179\n    },\n    {\n      \"id\": \"host-1231\",\n      \"name\": \"prod-web-1231\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 69,\n      \"disk\": 17,\n      \"network\": 62,\n      \"uptime\": 1725330\n    },\n    {\n      \"id\": \"host-1232\",\n      \"name\": \"prod-api-1232\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 93,\n      \"disk\": 22,\n      \"network\": 80,\n      \"uptime\": 5359123\n    },\n    {\n      \"id\": \"host-1233\",\n      \"name\": \"prod-database-1233\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 6,\n      \"disk\": 1,\n      \"network\": 40,\n      \"uptime\": 9036738\n    },\n    {\n      \"id\": \"host-1234\",\n      \"name\": \"prod-cache-1234\",\n      \"status\": \"healthy\",\n      \"cpu\": 26,\n      \"memory\": 90,\n      \"disk\": 93,\n      \"network\": 38,\n      \"uptime\": 8611933\n    },\n    {\n      \"id\": \"host-1235\",\n      \"name\": \"prod-worker-1235\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 35,\n      \"disk\": 66,\n      \"network\": 2,\n      \"uptime\": 3735032\n    },\n    {\n      \"id\": \"host-1236\",\n      \"name\": \"prod-queue-1236\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 76,\n      \"disk\": 22,\n      \"network\": 82,\n      \"uptime\": 4071920\n    },\n    {\n      \"id\": \"host-1237\",\n      \"name\": \"prod-web-1237\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 54,\n      \"disk\": 36,\n      \"network\": 0,\n      \"uptime\": 964192\n    },\n    {\n      \"id\": \"host-1238\",\n      \"name\": \"prod-api-1238\",\n      \"status\": \"healthy\",\n      \"cpu\": 38,\n      \"memory\": 28,\n      \"disk\": 15,\n      \"network\": 79,\n      \"uptime\": 8226280\n    },\n    {\n      \"id\": \"host-1239\",\n      \"name\": \"prod-database-1239\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 73,\n      \"disk\": 29,\n      \"network\": 83,\n      \"uptime\": 7509676\n    },\n    {\n      \"id\": \"host-1240\",\n      \"name\": \"prod-cache-1240\",\n      \"status\": \"healthy\",\n      \"cpu\": 69,\n      \"memory\": 29,\n      \"disk\": 17,\n      \"network\": 32,\n      \"uptime\": 5670449\n    },\n    {\n      \"id\": \"host-1241\",\n      \"name\": \"prod-worker-1241\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 100,\n      \"disk\": 100,\n      \"network\": 74,\n      \"uptime\": 9438721\n    },\n    {\n      \"id\": \"host-1242\",\n      \"name\": \"prod-queue-1242\",\n      \"status\": \"healthy\",\n      \"cpu\": 90,\n      \"memory\": 21,\n      \"disk\": 46,\n      \"network\": 8,\n      \"uptime\": 4768150\n    },\n    {\n      \"id\": \"host-1243\",\n      \"name\": \"prod-web-1243\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 73,\n      \"disk\": 40,\n      \"network\": 22,\n      \"uptime\": 8313714\n    },\n    {\n      \"id\": \"host-1244\",\n      \"name\": \"prod-api-1244\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 44,\n      \"disk\": 75,\n      \"network\": 7,\n      \"uptime\": 2897723\n    },\n    {\n      \"id\": \"host-1245\",\n      \"name\": \"prod-database-1245\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 58,\n      \"disk\": 7,\n      \"network\": 62,\n      \"uptime\": 2157375\n    },\n    {\n      \"id\": \"host-1246\",\n      \"name\": \"prod-cache-1246\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 58,\n      \"disk\": 16,\n      \"network\": 9,\n      \"uptime\": 3615794\n    },\n    {\n      \"id\": \"host-1247\",\n      \"name\": \"prod-worker-1247\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 50,\n      \"disk\": 65,\n      \"network\": 92,\n      \"uptime\": 3581136\n    },\n    {\n      \"id\": \"host-1248\",\n      \"name\": \"prod-queue-1248\",\n      \"status\": \"healthy\",\n      \"cpu\": 67,\n      \"memory\": 64,\n      \"disk\": 80,\n      \"network\": 49,\n      \"uptime\": 3787848\n    },\n    {\n      \"id\": \"host-1249\",\n      \"name\": \"prod-web-1249\",\n      \"status\": \"healthy\",\n      \"cpu\": 87,\n      \"memory\": 46,\n      \"disk\": 57,\n      \"network\": 90,\n      \"uptime\": 7632978\n    },\n    {\n      \"id\": \"host-1250\",\n      \"name\": \"prod-api-1250\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 66,\n      \"disk\": 45,\n      \"network\": 90,\n      \"uptime\": 7798729\n    },\n    {\n      \"id\": \"host-1251\",\n      \"name\": \"prod-database-1251\",\n      \"status\": \"healthy\",\n      \"cpu\": 99,\n      \"memory\": 81,\n      \"disk\": 47,\n      \"network\": 67,\n      \"uptime\": 5921458\n    },\n    {\n      \"id\": \"host-1252\",\n      \"name\": \"prod-cache-1252\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 10,\n      \"disk\": 93,\n      \"network\": 37,\n      \"uptime\": 8572255\n    },\n    {\n      \"id\": \"host-1253\",\n      \"name\": \"prod-worker-1253\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 76,\n      \"disk\": 4,\n      \"network\": 9,\n      \"uptime\": 5771557\n    },\n    {\n      \"id\": \"host-1254\",\n      \"name\": \"prod-queue-1254\",\n      \"status\": \"healthy\",\n      \"cpu\": 14,\n      \"memory\": 28,\n      \"disk\": 66,\n      \"network\": 66,\n      \"uptime\": 3683261\n    },\n    {\n      \"id\": \"host-1255\",\n      \"name\": \"prod-web-1255\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 98,\n      \"disk\": 94,\n      \"network\": 0,\n      \"uptime\": 9405388\n    },\n    {\n      \"id\": \"host-1256\",\n      \"name\": \"prod-api-1256\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 39,\n      \"disk\": 94,\n      \"network\": 24,\n      \"uptime\": 1794505\n    },\n    {\n      \"id\": \"host-1257\",\n      \"name\": \"prod-database-1257\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 30,\n      \"disk\": 43,\n      \"network\": 31,\n      \"uptime\": 6404807\n    },\n    {\n      \"id\": \"host-1258\",\n      \"name\": \"prod-cache-1258\",\n      \"status\": \"healthy\",\n      \"cpu\": 58,\n      \"memory\": 11,\n      \"disk\": 19,\n      \"network\": 29,\n      \"uptime\": 6325879\n    },\n    {\n      \"id\": \"host-1259\",\n      \"name\": \"prod-worker-1259\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 97,\n      \"disk\": 58,\n      \"network\": 37,\n      \"uptime\": 968424\n    },\n    {\n      \"id\": \"host-1260\",\n      \"name\": \"prod-queue-1260\",\n      \"status\": \"healthy\",\n      \"cpu\": 7,\n      \"memory\": 90,\n      \"disk\": 17,\n      \"network\": 49,\n      \"uptime\": 396128\n    },\n    {\n      \"id\": \"host-1261\",\n      \"name\": \"prod-web-1261\",\n      \"status\": \"warning\",\n      \"cpu\": 21,\n      \"memory\": 42,\n      \"disk\": 72,\n      \"network\": 73,\n      \"uptime\": 4618090\n    },\n    {\n      \"id\": \"host-1262\",\n      \"name\": \"prod-api-1262\",\n      \"status\": \"warning\",\n      \"cpu\": 54,\n      \"memory\": 47,\n      \"disk\": 69,\n      \"network\": 11,\n      \"uptime\": 1753279\n    },\n    {\n      \"id\": \"host-1263\",\n      \"name\": \"prod-database-1263\",\n      \"status\": \"warning\",\n      \"cpu\": 62,\n      \"memory\": 84,\n      \"disk\": 2,\n      \"network\": 48,\n      \"uptime\": 2753667\n    },\n    {\n      \"id\": \"host-1264\",\n      \"name\": \"prod-cache-1264\",\n      \"status\": \"warning\",\n      \"cpu\": 90,\n      \"memory\": 65,\n      \"disk\": 63,\n      \"network\": 84,\n      \"uptime\": 9767431\n    },\n    {\n      \"id\": \"host-1265\",\n      \"name\": \"prod-worker-1265\",\n      \"status\": \"warning\",\n      \"cpu\": 40,\n      \"memory\": 74,\n      \"disk\": 96,\n      \"network\": 61,\n      \"uptime\": 320913\n    },\n    {\n      \"id\": \"host-1266\",\n      \"name\": \"prod-queue-1266\",\n      \"status\": \"warning\",\n      \"cpu\": 91,\n      \"memory\": 54,\n      \"disk\": 54,\n      \"network\": 51,\n      \"uptime\": 5755984\n    },\n    {\n      \"id\": \"host-1267\",\n      \"name\": \"prod-web-1267\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 4,\n      \"disk\": 87,\n      \"network\": 30,\n      \"uptime\": 1887186\n    },\n    {\n      \"id\": \"host-1268\",\n      \"name\": \"prod-api-1268\",\n      \"status\": \"warning\",\n      \"cpu\": 90,\n      \"memory\": 84,\n      \"disk\": 61,\n      \"network\": 47,\n      \"uptime\": 9851927\n    },\n    {\n      \"id\": \"host-1269\",\n      \"name\": \"prod-database-1269\",\n      \"status\": \"warning\",\n      \"cpu\": 48,\n      \"memory\": 24,\n      \"disk\": 34,\n      \"network\": 36,\n      \"uptime\": 8698409\n    },\n    {\n      \"id\": \"host-1270\",\n      \"name\": \"prod-cache-1270\",\n      \"status\": \"warning\",\n      \"cpu\": 17,\n      \"memory\": 38,\n      \"disk\": 57,\n      \"network\": 2,\n      \"uptime\": 1366140\n    },\n    {\n      \"id\": \"host-1271\",\n      \"name\": \"prod-worker-1271\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 60,\n      \"disk\": 23,\n      \"network\": 39,\n      \"uptime\": 1234858\n    },\n    {\n      \"id\": \"host-1272\",\n      \"name\": \"prod-queue-1272\",\n      \"status\": \"warning\",\n      \"cpu\": 87,\n      \"memory\": 59,\n      \"disk\": 17,\n      \"network\": 17,\n      \"uptime\": 5828720\n    },\n    {\n      \"id\": \"host-1273\",\n      \"name\": \"prod-web-1273\",\n      \"status\": \"warning\",\n      \"cpu\": 92,\n      \"memory\": 63,\n      \"disk\": 71,\n      \"network\": 32,\n      \"uptime\": 3597072\n    },\n    {\n      \"id\": \"host-1274\",\n      \"name\": \"prod-api-1274\",\n      \"status\": \"warning\",\n      \"cpu\": 74,\n      \"memory\": 44,\n      \"disk\": 37,\n      \"network\": 87,\n      \"uptime\": 9640620\n    },\n    {\n      \"id\": \"host-1275\",\n      \"name\": \"prod-database-1275\",\n      \"status\": \"warning\",\n      \"cpu\": 1,\n      \"memory\": 21,\n      \"disk\": 92,\n      \"network\": 88,\n      \"uptime\": 9706068\n    },\n    {\n      \"id\": \"host-1276\",\n      \"name\": \"prod-cache-1276\",\n      \"status\": \"warning\",\n      \"cpu\": 65,\n      \"memory\": 43,\n      \"disk\": 0,\n      \"network\": 20,\n      \"uptime\": 1287192\n    },\n    {\n      \"id\": \"host-1277\",\n      \"name\": \"prod-worker-1277\",\n      \"status\": \"warning\",\n      \"cpu\": 62,\n      \"memory\": 1,\n      \"disk\": 34,\n      \"network\": 62,\n      \"uptime\": 7989243\n    },\n    {\n      \"id\": \"host-1278\",\n      \"name\": \"prod-queue-1278\",\n      \"status\": \"warning\",\n      \"cpu\": 5,\n      \"memory\": 70,\n      \"disk\": 67,\n      \"network\": 97,\n      \"uptime\": 4992204\n    },\n    {\n      \"id\": \"host-1279\",\n      \"name\": \"prod-web-1279\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 85,\n      \"disk\": 31,\n      \"network\": 77,\n      \"uptime\": 5333329\n    },\n    {\n      \"id\": \"host-1280\",\n      \"name\": \"prod-api-1280\",\n      \"status\": \"warning\",\n      \"cpu\": 98,\n      \"memory\": 90,\n      \"disk\": 50,\n      \"network\": 0,\n      \"uptime\": 6056776\n    },\n    {\n      \"id\": \"host-1281\",\n      \"name\": \"prod-database-1281\",\n      \"status\": \"warning\",\n      \"cpu\": 89,\n      \"memory\": 17,\n      \"disk\": 50,\n      \"network\": 42,\n      \"uptime\": 4017020\n    },\n    {\n      \"id\": \"host-1282\",\n      \"name\": \"prod-cache-1282\",\n      \"status\": \"warning\",\n      \"cpu\": 10,\n      \"memory\": 36,\n      \"disk\": 96,\n      \"network\": 5,\n      \"uptime\": 7567626\n    },\n    {\n      \"id\": \"host-1283\",\n      \"name\": \"prod-worker-1283\",\n      \"status\": \"warning\",\n      \"cpu\": 23,\n      \"memory\": 69,\n      \"disk\": 5,\n      \"network\": 5,\n      \"uptime\": 4389952\n    },\n    {\n      \"id\": \"host-1284\",\n      \"name\": \"prod-queue-1284\",\n      \"status\": \"warning\",\n      \"cpu\": 32,\n      \"memory\": 6,\n      \"disk\": 21,\n      \"network\": 23,\n      \"uptime\": 5214465\n    },\n    {\n      \"id\": \"host-1285\",\n      \"name\": \"prod-web-1285\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 39,\n      \"disk\": 80,\n      \"network\": 3,\n      \"uptime\": 7600478\n    },\n    {\n      \"id\": \"host-1286\",\n      \"name\": \"prod-api-1286\",\n      \"status\": \"critical\",\n      \"cpu\": 24,\n      \"memory\": 95,\n      \"disk\": 100,\n      \"network\": 22,\n      \"uptime\": 4167221\n    },\n    {\n      \"id\": \"host-1287\",\n      \"name\": \"prod-database-1287\",\n      \"status\": \"critical\",\n      \"cpu\": 7,\n      \"memory\": 77,\n      \"disk\": 55,\n      \"network\": 39,\n      \"uptime\": 7801459\n    },\n    {\n      \"id\": \"host-1288\",\n      \"name\": \"prod-cache-1288\",\n      \"status\": \"critical\",\n      \"cpu\": 41,\n      \"memory\": 24,\n      \"disk\": 37,\n      \"network\": 43,\n      \"uptime\": 4810589\n    },\n    {\n      \"id\": \"host-1289\",\n      \"name\": \"prod-worker-1289\",\n      \"status\": \"critical\",\n      \"cpu\": 57,\n      \"memory\": 100,\n      \"disk\": 100,\n      \"network\": 6,\n      \"uptime\": 6812127\n    },\n    {\n      \"id\": \"host-1290\",\n      \"name\": \"prod-queue-1290\",\n      \"status\": \"critical\",\n      \"cpu\": 21,\n      \"memory\": 52,\n      \"disk\": 10,\n      \"network\": 60,\n      \"uptime\": 6869786\n    },\n    {\n      \"id\": \"host-1291\",\n      \"name\": \"prod-web-1291\",\n      \"status\": \"critical\",\n      \"cpu\": 55,\n      \"memory\": 96,\n      \"disk\": 43,\n      \"network\": 3,\n      \"uptime\": 7542702\n    },\n    {\n      \"id\": \"host-1292\",\n      \"name\": \"prod-api-1292\",\n      \"status\": \"critical\",\n      \"cpu\": 62,\n      \"memory\": 93,\n      \"disk\": 50,\n      \"network\": 37,\n      \"uptime\": 4018379\n    },\n    {\n      \"id\": \"host-1293\",\n      \"name\": \"prod-database-1293\",\n      \"status\": \"critical\",\n      \"cpu\": 32,\n      \"memory\": 85,\n      \"disk\": 13,\n      \"network\": 4,\n      \"uptime\": 9606287\n    },\n    {\n      \"id\": \"host-1294\",\n      \"name\": \"prod-cache-1294\",\n      \"status\": \"critical\",\n      \"cpu\": 38,\n      \"memory\": 53,\n      \"disk\": 26,\n      \"network\": 52,\n      \"uptime\": 7110248\n    },\n    {\n      \"id\": \"host-1295\",\n      \"name\": \"prod-worker-1295\",\n      \"status\": \"critical\",\n      \"cpu\": 70,\n      \"memory\": 89,\n      \"disk\": 33,\n      \"network\": 64,\n      \"uptime\": 2570619\n    },\n    {\n      \"id\": \"host-1296\",\n      \"name\": \"prod-queue-1296\",\n      \"status\": \"critical\",\n      \"cpu\": 53,\n      \"memory\": 75,\n      \"disk\": 24,\n      \"network\": 100,\n      \"uptime\": 4676202\n    },\n    {\n      \"id\": \"host-1297\",\n      \"name\": \"prod-web-1297\",\n      \"status\": \"critical\",\n      \"cpu\": 8,\n      \"memory\": 32,\n      \"disk\": 31,\n      \"network\": 6,\n      \"uptime\": 6880867\n    },\n    {\n      \"id\": \"host-1298\",\n      \"name\": \"prod-api-1298\",\n      \"status\": \"critical\",\n      \"cpu\": 33,\n      \"memory\": 93,\n      \"disk\": 47,\n      \"network\": 61,\n      \"uptime\": 3715064\n    },\n    {\n      \"id\": \"host-1299\",\n      \"name\": \"prod-database-1299\",\n      \"status\": \"critical\",\n      \"cpu\": 60,\n      \"memory\": 97,\n      \"disk\": 70,\n      \"network\": 38,\n      \"uptime\": 9735657\n    },\n    {\n      \"id\": \"host-1300\",\n      \"name\": \"prod-cache-1300\",\n      \"status\": \"critical\",\n      \"cpu\": 35,\n      \"memory\": 14,\n      \"disk\": 63,\n      \"network\": 61,\n      \"uptime\": 4115866\n    },\n    {\n      \"id\": \"host-1301\",\n      \"name\": \"prod-worker-1301\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 86,\n      \"disk\": 19,\n      \"network\": 37,\n      \"uptime\": 4628504\n    },\n    {\n      \"id\": \"host-1302\",\n      \"name\": \"prod-queue-1302\",\n      \"status\": \"healthy\",\n      \"cpu\": 18,\n      \"memory\": 48,\n      \"disk\": 5,\n      \"network\": 98,\n      \"uptime\": 3635116\n    },\n    {\n      \"id\": \"host-1303\",\n      \"name\": \"prod-web-1303\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 85,\n      \"disk\": 23,\n      \"network\": 61,\n      \"uptime\": 6381297\n    },\n    {\n      \"id\": \"host-1304\",\n      \"name\": \"prod-api-1304\",\n      \"status\": \"healthy\",\n      \"cpu\": 58,\n      \"memory\": 77,\n      \"disk\": 57,\n      \"network\": 81,\n      \"uptime\": 5912750\n    },\n    {\n      \"id\": \"host-1305\",\n      \"name\": \"prod-database-1305\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 83,\n      \"disk\": 91,\n      \"network\": 30,\n      \"uptime\": 6851066\n    },\n    {\n      \"id\": \"host-1306\",\n      \"name\": \"prod-cache-1306\",\n      \"status\": \"healthy\",\n      \"cpu\": 25,\n      \"memory\": 86,\n      \"disk\": 22,\n      \"network\": 67,\n      \"uptime\": 1077232\n    },\n    {\n      \"id\": \"host-1307\",\n      \"name\": \"prod-worker-1307\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 89,\n      \"disk\": 52,\n      \"network\": 73,\n      \"uptime\": 6101362\n    },\n    {\n      \"id\": \"host-1308\",\n      \"name\": \"prod-queue-1308\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 39,\n      \"disk\": 3,\n      \"network\": 25,\n      \"uptime\": 6755755\n    },\n    {\n      \"id\": \"host-1309\",\n      \"name\": \"prod-web-1309\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 31,\n      \"disk\": 76,\n      \"network\": 58,\n      \"uptime\": 341512\n    },\n    {\n      \"id\": \"host-1310\",\n      \"name\": \"prod-api-1310\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 47,\n      \"disk\": 97,\n      \"network\": 90,\n      \"uptime\": 499974\n    },\n    {\n      \"id\": \"host-1311\",\n      \"name\": \"prod-database-1311\",\n      \"status\": \"healthy\",\n      \"cpu\": 21,\n      \"memory\": 67,\n      \"disk\": 83,\n      \"network\": 75,\n      \"uptime\": 1891759\n    },\n    {\n      \"id\": \"host-1312\",\n      \"name\": \"prod-cache-1312\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 95,\n      \"disk\": 33,\n      \"network\": 84,\n      \"uptime\": 5853690\n    },\n    {\n      \"id\": \"host-1313\",\n      \"name\": \"prod-worker-1313\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 48,\n      \"disk\": 5,\n      \"network\": 47,\n      \"uptime\": 2546649\n    },\n    {\n      \"id\": \"host-1314\",\n      \"name\": \"prod-queue-1314\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 36,\n      \"disk\": 34,\n      \"network\": 84,\n      \"uptime\": 5405440\n    },\n    {\n      \"id\": \"host-1315\",\n      \"name\": \"prod-web-1315\",\n      \"status\": \"healthy\",\n      \"cpu\": 80,\n      \"memory\": 97,\n      \"disk\": 41,\n      \"network\": 56,\n      \"uptime\": 538969\n    },\n    {\n      \"id\": \"host-1316\",\n      \"name\": \"prod-api-1316\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 95,\n      \"disk\": 17,\n      \"network\": 28,\n      \"uptime\": 2594340\n    },\n    {\n      \"id\": \"host-1317\",\n      \"name\": \"prod-database-1317\",\n      \"status\": \"healthy\",\n      \"cpu\": 52,\n      \"memory\": 49,\n      \"disk\": 97,\n      \"network\": 69,\n      \"uptime\": 5460105\n    },\n    {\n      \"id\": \"host-1318\",\n      \"name\": \"prod-cache-1318\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 19,\n      \"disk\": 37,\n      \"network\": 0,\n      \"uptime\": 320096\n    },\n    {\n      \"id\": \"host-1319\",\n      \"name\": \"prod-worker-1319\",\n      \"status\": \"healthy\",\n      \"cpu\": 10,\n      \"memory\": 13,\n      \"disk\": 3,\n      \"network\": 84,\n      \"uptime\": 9737297\n    },\n    {\n      \"id\": \"host-1320\",\n      \"name\": \"prod-queue-1320\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 19,\n      \"disk\": 41,\n      \"network\": 8,\n      \"uptime\": 383331\n    },\n    {\n      \"id\": \"host-1321\",\n      \"name\": \"prod-web-1321\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 95,\n      \"disk\": 28,\n      \"network\": 26,\n      \"uptime\": 2255454\n    },\n    {\n      \"id\": \"host-1322\",\n      \"name\": \"prod-api-1322\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 15,\n      \"disk\": 87,\n      \"network\": 7,\n      \"uptime\": 587005\n    },\n    {\n      \"id\": \"host-1323\",\n      \"name\": \"prod-database-1323\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 40,\n      \"disk\": 59,\n      \"network\": 57,\n      \"uptime\": 118844\n    },\n    {\n      \"id\": \"host-1324\",\n      \"name\": \"prod-cache-1324\",\n      \"status\": \"healthy\",\n      \"cpu\": 88,\n      \"memory\": 50,\n      \"disk\": 80,\n      \"network\": 28,\n      \"uptime\": 5601068\n    },\n    {\n      \"id\": \"host-1325\",\n      \"name\": \"prod-worker-1325\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 60,\n      \"disk\": 94,\n      \"network\": 51,\n      \"uptime\": 9597643\n    },\n    {\n      \"id\": \"host-1326\",\n      \"name\": \"prod-queue-1326\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 4,\n      \"disk\": 87,\n      \"network\": 62,\n      \"uptime\": 7031046\n    },\n    {\n      \"id\": \"host-1327\",\n      \"name\": \"prod-web-1327\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 79,\n      \"disk\": 86,\n      \"network\": 16,\n      \"uptime\": 456650\n    },\n    {\n      \"id\": \"host-1328\",\n      \"name\": \"prod-api-1328\",\n      \"status\": \"healthy\",\n      \"cpu\": 7,\n      \"memory\": 15,\n      \"disk\": 75,\n      \"network\": 95,\n      \"uptime\": 3695797\n    },\n    {\n      \"id\": \"host-1329\",\n      \"name\": \"prod-database-1329\",\n      \"status\": \"healthy\",\n      \"cpu\": 36,\n      \"memory\": 83,\n      \"disk\": 82,\n      \"network\": 91,\n      \"uptime\": 7406382\n    },\n    {\n      \"id\": \"host-1330\",\n      \"name\": \"prod-cache-1330\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 87,\n      \"disk\": 94,\n      \"network\": 66,\n      \"uptime\": 8312470\n    },\n    {\n      \"id\": \"host-1331\",\n      \"name\": \"prod-worker-1331\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 98,\n      \"disk\": 61,\n      \"network\": 78,\n      \"uptime\": 8193484\n    },\n    {\n      \"id\": \"host-1332\",\n      \"name\": \"prod-queue-1332\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 68,\n      \"disk\": 92,\n      \"network\": 84,\n      \"uptime\": 2683051\n    },\n    {\n      \"id\": \"host-1333\",\n      \"name\": \"prod-web-1333\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 44,\n      \"disk\": 26,\n      \"network\": 83,\n      \"uptime\": 5790495\n    },\n    {\n      \"id\": \"host-1334\",\n      \"name\": \"prod-api-1334\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 3,\n      \"disk\": 44,\n      \"network\": 11,\n      \"uptime\": 8206866\n    },\n    {\n      \"id\": \"host-1335\",\n      \"name\": \"prod-database-1335\",\n      \"status\": \"healthy\",\n      \"cpu\": 83,\n      \"memory\": 23,\n      \"disk\": 7,\n      \"network\": 19,\n      \"uptime\": 2408579\n    },\n    {\n      \"id\": \"host-1336\",\n      \"name\": \"prod-cache-1336\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 39,\n      \"disk\": 50,\n      \"network\": 70,\n      \"uptime\": 1123833\n    },\n    {\n      \"id\": \"host-1337\",\n      \"name\": \"prod-worker-1337\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 13,\n      \"disk\": 47,\n      \"network\": 9,\n      \"uptime\": 5595263\n    },\n    {\n      \"id\": \"host-1338\",\n      \"name\": \"prod-queue-1338\",\n      \"status\": \"healthy\",\n      \"cpu\": 96,\n      \"memory\": 65,\n      \"disk\": 94,\n      \"network\": 10,\n      \"uptime\": 4385039\n    },\n    {\n      \"id\": \"host-1339\",\n      \"name\": \"prod-web-1339\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 82,\n      \"disk\": 26,\n      \"network\": 78,\n      \"uptime\": 5939107\n    },\n    {\n      \"id\": \"host-1340\",\n      \"name\": \"prod-api-1340\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 38,\n      \"disk\": 85,\n      \"network\": 12,\n      \"uptime\": 2968632\n    },\n    {\n      \"id\": \"host-1341\",\n      \"name\": \"prod-database-1341\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 89,\n      \"disk\": 96,\n      \"network\": 24,\n      \"uptime\": 9508389\n    },\n    {\n      \"id\": \"host-1342\",\n      \"name\": \"prod-cache-1342\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 4,\n      \"disk\": 91,\n      \"network\": 5,\n      \"uptime\": 472667\n    },\n    {\n      \"id\": \"host-1343\",\n      \"name\": \"prod-worker-1343\",\n      \"status\": \"healthy\",\n      \"cpu\": 46,\n      \"memory\": 63,\n      \"disk\": 19,\n      \"network\": 11,\n      \"uptime\": 6715676\n    },\n    {\n      \"id\": \"host-1344\",\n      \"name\": \"prod-queue-1344\",\n      \"status\": \"healthy\",\n      \"cpu\": 66,\n      \"memory\": 75,\n      \"disk\": 82,\n      \"network\": 69,\n      \"uptime\": 7808430\n    },\n    {\n      \"id\": \"host-1345\",\n      \"name\": \"prod-web-1345\",\n      \"status\": \"healthy\",\n      \"cpu\": 9,\n      \"memory\": 45,\n      \"disk\": 100,\n      \"network\": 56,\n      \"uptime\": 2957835\n    },\n    {\n      \"id\": \"host-1346\",\n      \"name\": \"prod-api-1346\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 94,\n      \"disk\": 56,\n      \"network\": 62,\n      \"uptime\": 2111220\n    },\n    {\n      \"id\": \"host-1347\",\n      \"name\": \"prod-database-1347\",\n      \"status\": \"healthy\",\n      \"cpu\": 93,\n      \"memory\": 64,\n      \"disk\": 26,\n      \"network\": 45,\n      \"uptime\": 9773864\n    },\n    {\n      \"id\": \"host-1348\",\n      \"name\": \"prod-cache-1348\",\n      \"status\": \"healthy\",\n      \"cpu\": 13,\n      \"memory\": 68,\n      \"disk\": 73,\n      \"network\": 82,\n      \"uptime\": 8710210\n    },\n    {\n      \"id\": \"host-1349\",\n      \"name\": \"prod-worker-1349\",\n      \"status\": \"healthy\",\n      \"cpu\": 3,\n      \"memory\": 5,\n      \"disk\": 41,\n      \"network\": 84,\n      \"uptime\": 4765652\n    },\n    {\n      \"id\": \"host-1350\",\n      \"name\": \"prod-queue-1350\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 98,\n      \"disk\": 4,\n      \"network\": 77,\n      \"uptime\": 5237908\n    },\n    {\n      \"id\": \"host-1351\",\n      \"name\": \"prod-web-1351\",\n      \"status\": \"healthy\",\n      \"cpu\": 61,\n      \"memory\": 31,\n      \"disk\": 70,\n      \"network\": 87,\n      \"uptime\": 9738096\n    },\n    {\n      \"id\": \"host-1352\",\n      \"name\": \"prod-api-1352\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 32,\n      \"disk\": 9,\n      \"network\": 16,\n      \"uptime\": 5787340\n    },\n    {\n      \"id\": \"host-1353\",\n      \"name\": \"prod-database-1353\",\n      \"status\": \"healthy\",\n      \"cpu\": 82,\n      \"memory\": 69,\n      \"disk\": 90,\n      \"network\": 0,\n      \"uptime\": 7753254\n    },\n    {\n      \"id\": \"host-1354\",\n      \"name\": \"prod-cache-1354\",\n      \"status\": \"healthy\",\n      \"cpu\": 79,\n      \"memory\": 41,\n      \"disk\": 33,\n      \"network\": 23,\n      \"uptime\": 5728085\n    },\n    {\n      \"id\": \"host-1355\",\n      \"name\": \"prod-worker-1355\",\n      \"status\": \"healthy\",\n      \"cpu\": 35,\n      \"memory\": 95,\n      \"disk\": 30,\n      \"network\": 25,\n      \"uptime\": 5522050\n    },\n    {\n      \"id\": \"host-1356\",\n      \"name\": \"prod-queue-1356\",\n      \"status\": \"healthy\",\n      \"cpu\": 3,\n      \"memory\": 0,\n      \"disk\": 31,\n      \"network\": 48,\n      \"uptime\": 5226195\n    },\n    {\n      \"id\": \"host-1357\",\n      \"name\": \"prod-web-1357\",\n      \"status\": \"healthy\",\n      \"cpu\": 24,\n      \"memory\": 11,\n      \"disk\": 88,\n      \"network\": 56,\n      \"uptime\": 8276248\n    },\n    {\n      \"id\": \"host-1358\",\n      \"name\": \"prod-api-1358\",\n      \"status\": \"healthy\",\n      \"cpu\": 8,\n      \"memory\": 56,\n      \"disk\": 44,\n      \"network\": 52,\n      \"uptime\": 113694\n    },\n    {\n      \"id\": \"host-1359\",\n      \"name\": \"prod-database-1359\",\n      \"status\": \"healthy\",\n      \"cpu\": 41,\n      \"memory\": 37,\n      \"disk\": 35,\n      \"network\": 81,\n      \"uptime\": 3225289\n    },\n    {\n      \"id\": \"host-1360\",\n      \"name\": \"prod-cache-1360\",\n      \"status\": \"healthy\",\n      \"cpu\": 15,\n      \"memory\": 43,\n      \"disk\": 38,\n      \"network\": 9,\n      \"uptime\": 6231217\n    },\n    {\n      \"id\": \"host-1361\",\n      \"name\": \"prod-worker-1361\",\n      \"status\": \"warning\",\n      \"cpu\": 38,\n      \"memory\": 78,\n      \"disk\": 36,\n      \"network\": 10,\n      \"uptime\": 7865675\n    },\n    {\n      \"id\": \"host-1362\",\n      \"name\": \"prod-queue-1362\",\n      \"status\": \"warning\",\n      \"cpu\": 30,\n      \"memory\": 13,\n      \"disk\": 82,\n      \"network\": 97,\n      \"uptime\": 6314697\n    },\n    {\n      \"id\": \"host-1363\",\n      \"name\": \"prod-web-1363\",\n      \"status\": \"warning\",\n      \"cpu\": 57,\n      \"memory\": 70,\n      \"disk\": 99,\n      \"network\": 5,\n      \"uptime\": 8878967\n    },\n    {\n      \"id\": \"host-1364\",\n      \"name\": \"prod-api-1364\",\n      \"status\": \"warning\",\n      \"cpu\": 35,\n      \"memory\": 24,\n      \"disk\": 61,\n      \"network\": 95,\n      \"uptime\": 4967532\n    },\n    {\n      \"id\": \"host-1365\",\n      \"name\": \"prod-database-1365\",\n      \"status\": \"warning\",\n      \"cpu\": 2,\n      \"memory\": 20,\n      \"disk\": 10,\n      \"network\": 58,\n      \"uptime\": 824201\n    },\n    {\n      \"id\": \"host-1366\",\n      \"name\": \"prod-cache-1366\",\n      \"status\": \"warning\",\n      \"cpu\": 80,\n      \"memory\": 36,\n      \"disk\": 4,\n      \"network\": 31,\n      \"uptime\": 526919\n    },\n    {\n      \"id\": \"host-1367\",\n      \"name\": \"prod-worker-1367\",\n      \"status\": \"warning\",\n      \"cpu\": 74,\n      \"memory\": 22,\n      \"disk\": 87,\n      \"network\": 1,\n      \"uptime\": 9628840\n    },\n    {\n      \"id\": \"host-1368\",\n      \"name\": \"prod-queue-1368\",\n      \"status\": \"warning\",\n      \"cpu\": 66,\n      \"memory\": 58,\n      \"disk\": 3,\n      \"network\": 30,\n      \"uptime\": 6537098\n    },\n    {\n      \"id\": \"host-1369\",\n      \"name\": \"prod-web-1369\",\n      \"status\": \"warning\",\n      \"cpu\": 81,\n      \"memory\": 42,\n      \"disk\": 18,\n      \"network\": 94,\n      \"uptime\": 697825\n    },\n    {\n      \"id\": \"host-1370\",\n      \"name\": \"prod-api-1370\",\n      \"status\": \"warning\",\n      \"cpu\": 24,\n      \"memory\": 12,\n      \"disk\": 14,\n      \"network\": 5,\n      \"uptime\": 2633736\n    },\n    {\n      \"id\": \"host-1371\",\n      \"name\": \"prod-database-1371\",\n      \"status\": \"warning\",\n      \"cpu\": 21,\n      \"memory\": 14,\n      \"disk\": 29,\n      \"network\": 71,\n      \"uptime\": 5411866\n    },\n    {\n      \"id\": \"host-1372\",\n      \"name\": \"prod-cache-1372\",\n      \"status\": \"warning\",\n      \"cpu\": 25,\n      \"memory\": 70,\n      \"disk\": 48,\n      \"network\": 25,\n      \"uptime\": 5498653\n    },\n    {\n      \"id\": \"host-1373\",\n      \"name\": \"prod-worker-1373\",\n      \"status\": \"warning\",\n      \"cpu\": 97,\n      \"memory\": 18,\n      \"disk\": 32,\n      \"network\": 99,\n      \"uptime\": 9407590\n    },\n    {\n      \"id\": \"host-1374\",\n      \"name\": \"prod-queue-1374\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 80,\n      \"disk\": 65,\n      \"network\": 45,\n      \"uptime\": 146928\n    },\n    {\n      \"id\": \"host-1375\",\n      \"name\": \"prod-web-1375\",\n      \"status\": \"warning\",\n      \"cpu\": 31,\n      \"memory\": 36,\n      \"disk\": 78,\n      \"network\": 48,\n      \"uptime\": 1940687\n    },\n    {\n      \"id\": \"host-1376\",\n      \"name\": \"prod-api-1376\",\n      \"status\": \"warning\",\n      \"cpu\": 76,\n      \"memory\": 40,\n      \"disk\": 33,\n      \"network\": 81,\n      \"uptime\": 210335\n    },\n    {\n      \"id\": \"host-1377\",\n      \"name\": \"prod-database-1377\",\n      \"status\": \"warning\",\n      \"cpu\": 86,\n      \"memory\": 28,\n      \"disk\": 13,\n      \"network\": 77,\n      \"uptime\": 5486392\n    },\n    {\n      \"id\": \"host-1378\",\n      \"name\": \"prod-cache-1378\",\n      \"status\": \"warning\",\n      \"cpu\": 42,\n      \"memory\": 41,\n      \"disk\": 8,\n      \"network\": 53,\n      \"uptime\": 389751\n    },\n    {\n      \"id\": \"host-1379\",\n      \"name\": \"prod-worker-1379\",\n      \"status\": \"warning\",\n      \"cpu\": 47,\n      \"memory\": 59,\n      \"disk\": 63,\n      \"network\": 62,\n      \"uptime\": 3421776\n    },\n    {\n      \"id\": \"host-1380\",\n      \"name\": \"prod-queue-1380\",\n      \"status\": \"warning\",\n      \"cpu\": 42,\n      \"memory\": 86,\n      \"disk\": 11,\n      \"network\": 94,\n      \"uptime\": 4157063\n    },\n    {\n      \"id\": \"host-1381\",\n      \"name\": \"prod-web-1381\",\n      \"status\": \"warning\",\n      \"cpu\": 50,\n      \"memory\": 34,\n      \"disk\": 13,\n      \"network\": 58,\n      \"uptime\": 5142924\n    },\n    {\n      \"id\": \"host-1382\",\n      \"name\": \"prod-api-1382\",\n      \"status\": \"warning\",\n      \"cpu\": 95,\n      \"memory\": 57,\n      \"disk\": 39,\n      \"network\": 61,\n      \"uptime\": 2831536\n    },\n    {\n      \"id\": \"host-1383\",\n      \"name\": \"prod-database-1383\",\n      \"status\": \"warning\",\n      \"cpu\": 29,\n      \"memory\": 49,\n      \"disk\": 95,\n      \"network\": 8,\n      \"uptime\": 6067038\n    },\n    {\n      \"id\": \"host-1384\",\n      \"name\": \"prod-cache-1384\",\n      \"status\": \"warning\",\n      \"cpu\": 63,\n      \"memory\": 22,\n      \"disk\": 44,\n      \"network\": 66,\n      \"uptime\": 9601958\n    },\n    {\n      \"id\": \"host-1385\",\n      \"name\": \"prod-worker-1385\",\n      \"status\": \"warning\",\n      \"cpu\": 69,\n      \"memory\": 30,\n      \"disk\": 28,\n      \"network\": 66,\n      \"uptime\": 9328699\n    },\n    {\n      \"id\": \"host-1386\",\n      \"name\": \"prod-queue-1386\",\n      \"status\": \"critical\",\n      \"cpu\": 5,\n      \"memory\": 92,\n      \"disk\": 31,\n      \"network\": 43,\n      \"uptime\": 7627315\n    },\n    {\n      \"id\": \"host-1387\",\n      \"name\": \"prod-web-1387\",\n      \"status\": \"critical\",\n      \"cpu\": 18,\n      \"memory\": 48,\n      \"disk\": 83,\n      \"network\": 57,\n      \"uptime\": 4560052\n    },\n    {\n      \"id\": \"host-1388\",\n      \"name\": \"prod-api-1388\",\n      \"status\": \"critical\",\n      \"cpu\": 48,\n      \"memory\": 72,\n      \"disk\": 45,\n      \"network\": 24,\n      \"uptime\": 5257268\n    },\n    {\n      \"id\": \"host-1389\",\n      \"name\": \"prod-database-1389\",\n      \"status\": \"critical\",\n      \"cpu\": 78,\n      \"memory\": 20,\n      \"disk\": 46,\n      \"network\": 80,\n      \"uptime\": 2191369\n    },\n    {\n      \"id\": \"host-1390\",\n      \"name\": \"prod-cache-1390\",\n      \"status\": \"critical\",\n      \"cpu\": 43,\n      \"memory\": 76,\n      \"disk\": 54,\n      \"network\": 86,\n      \"uptime\": 3105295\n    },\n    {\n      \"id\": \"host-1391\",\n      \"name\": \"prod-worker-1391\",\n      \"status\": \"critical\",\n      \"cpu\": 83,\n      \"memory\": 69,\n      \"disk\": 94,\n      \"network\": 35,\n      \"uptime\": 2361575\n    },\n    {\n      \"id\": \"host-1392\",\n      \"name\": \"prod-queue-1392\",\n      \"status\": \"critical\",\n      \"cpu\": 17,\n      \"memory\": 45,\n      \"disk\": 74,\n      \"network\": 37,\n      \"uptime\": 5315631\n    },\n    {\n      \"id\": \"host-1393\",\n      \"name\": \"prod-web-1393\",\n      \"status\": \"critical\",\n      \"cpu\": 50,\n      \"memory\": 20,\n      \"disk\": 99,\n      \"network\": 99,\n      \"uptime\": 2867357\n    },\n    {\n      \"id\": \"host-1394\",\n      \"name\": \"prod-api-1394\",\n      \"status\": \"critical\",\n      \"cpu\": 10,\n      \"memory\": 6,\n      \"disk\": 28,\n      \"network\": 3,\n      \"uptime\": 6362860\n    },\n    {\n      \"id\": \"host-1395\",\n      \"name\": \"prod-database-1395\",\n      \"status\": \"critical\",\n      \"cpu\": 68,\n      \"memory\": 4,\n      \"disk\": 67,\n      \"network\": 79,\n      \"uptime\": 1836056\n    },\n    {\n      \"id\": \"host-1396\",\n      \"name\": \"prod-cache-1396\",\n      \"status\": \"critical\",\n      \"cpu\": 78,\n      \"memory\": 69,\n      \"disk\": 79,\n      \"network\": 49,\n      \"uptime\": 287319\n    },\n    {\n      \"id\": \"host-1397\",\n      \"name\": \"prod-worker-1397\",\n      \"status\": \"critical\",\n      \"cpu\": 69,\n      \"memory\": 38,\n      \"disk\": 52,\n      \"network\": 22,\n      \"uptime\": 4138418\n    },\n    {\n      \"id\": \"host-1398\",\n      \"name\": \"prod-queue-1398\",\n      \"status\": \"critical\",\n      \"cpu\": 85,\n      \"memory\": 26,\n      \"disk\": 44,\n      \"network\": 84,\n      \"uptime\": 1936541\n    },\n    {\n      \"id\": \"host-1399\",\n      \"name\": \"prod-web-1399\",\n      \"status\": \"critical\",\n      \"cpu\": 67,\n      \"memory\": 58,\n      \"disk\": 23,\n      \"network\": 41,\n      \"uptime\": 1871815\n    },\n    {\n      \"id\": \"host-1400\",\n      \"name\": \"prod-api-1400\",\n      \"status\": \"critical\",\n      \"cpu\": 87,\n      \"memory\": 74,\n      \"disk\": 74,\n      \"network\": 36,\n      \"uptime\": 6654672\n    },\n    {\n      \"id\": \"host-1401\",\n      \"name\": \"prod-database-1401\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 50,\n      \"disk\": 45,\n      \"network\": 2,\n      \"uptime\": 6826743\n    },\n    {\n      \"id\": \"host-1402\",\n      \"name\": \"prod-cache-1402\",\n      \"status\": \"healthy\",\n      \"cpu\": 39,\n      \"memory\": 96,\n      \"disk\": 7,\n      \"network\": 16,\n      \"uptime\": 1296438\n    },\n    {\n      \"id\": \"host-1403\",\n      \"name\": \"prod-worker-1403\",\n      \"status\": \"healthy\",\n      \"cpu\": 73,\n      \"memory\": 37,\n      \"disk\": 58,\n      \"network\": 83,\n      \"uptime\": 2530637\n    },\n    {\n      \"id\": \"host-1404\",\n      \"name\": \"prod-queue-1404\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 39,\n      \"disk\": 27,\n      \"network\": 16,\n      \"uptime\": 8725670\n    },\n    {\n      \"id\": \"host-1405\",\n      \"name\": \"prod-web-1405\",\n      \"status\": \"healthy\",\n      \"cpu\": 27,\n      \"memory\": 99,\n      \"disk\": 39,\n      \"network\": 0,\n      \"uptime\": 5535335\n    },\n    {\n      \"id\": \"host-1406\",\n      \"name\": \"prod-api-1406\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 36,\n      \"disk\": 8,\n      \"network\": 33,\n      \"uptime\": 6170255\n    },\n    {\n      \"id\": \"host-1407\",\n      \"name\": \"prod-database-1407\",\n      \"status\": \"healthy\",\n      \"cpu\": 86,\n      \"memory\": 33,\n      \"disk\": 94,\n      \"network\": 85,\n      \"uptime\": 4282078\n    },\n    {\n      \"id\": \"host-1408\",\n      \"name\": \"prod-cache-1408\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 99,\n      \"disk\": 38,\n      \"network\": 1,\n      \"uptime\": 3461412\n    },\n    {\n      \"id\": \"host-1409\",\n      \"name\": \"prod-worker-1409\",\n      \"status\": \"healthy\",\n      \"cpu\": 2,\n      \"memory\": 41,\n      \"disk\": 32,\n      \"network\": 83,\n      \"uptime\": 5921800\n    },\n    {\n      \"id\": \"host-1410\",\n      \"name\": \"prod-queue-1410\",\n      \"status\": \"healthy\",\n      \"cpu\": 60,\n      \"memory\": 34,\n      \"disk\": 50,\n      \"network\": 12,\n      \"uptime\": 2506652\n    },\n    {\n      \"id\": \"host-1411\",\n      \"name\": \"prod-web-1411\",\n      \"status\": \"healthy\",\n      \"cpu\": 95,\n      \"memory\": 86,\n      \"disk\": 91,\n      \"network\": 48,\n      \"uptime\": 2027325\n    },\n    {\n      \"id\": \"host-1412\",\n      \"name\": \"prod-api-1412\",\n      \"status\": \"healthy\",\n      \"cpu\": 34,\n      \"memory\": 45,\n      \"disk\": 86,\n      \"network\": 42,\n      \"uptime\": 7475628\n    },\n    {\n      \"id\": \"host-1413\",\n      \"name\": \"prod-database-1413\",\n      \"status\": \"healthy\",\n      \"cpu\": 65,\n      \"memory\": 28,\n      \"disk\": 23,\n      \"network\": 71,\n      \"uptime\": 2654601\n    },\n    {\n      \"id\": \"host-1414\",\n      \"name\": \"prod-cache-1414\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 72,\n      \"disk\": 42,\n      \"network\": 84,\n      \"uptime\": 6407552\n    },\n    {\n      \"id\": \"host-1415\",\n      \"name\": \"prod-worker-1415\",\n      \"status\": \"healthy\",\n      \"cpu\": 33,\n      \"memory\": 65,\n      \"disk\": 93,\n      \"network\": 14,\n      \"uptime\": 9339003\n    },\n    {\n      \"id\": \"host-1416\",\n      \"name\": \"prod-queue-1416\",\n      \"status\": \"healthy\",\n      \"cpu\": 70,\n      \"memory\": 94,\n      \"disk\": 20,\n      \"network\": 55,\n      \"uptime\": 2388022\n    },\n    {\n      \"id\": \"host-1417\",\n      \"name\": \"prod-web-1417\",\n      \"status\": \"healthy\",\n      \"cpu\": 53,\n      \"memory\": 49,\n      \"disk\": 66,\n      \"network\": 73,\n      \"uptime\": 1886147\n    },\n    {\n      \"id\": \"host-1418\",\n      \"name\": \"prod-api-1418\",\n      \"status\": \"healthy\",\n      \"cpu\": 17,\n      \"memory\": 53,\n      \"disk\": 91,\n      \"network\": 32,\n      \"uptime\": 628091\n    },\n    {\n      \"id\": \"host-1419\",\n      \"name\": \"prod-database-1419\",\n      \"status\": \"healthy\",\n      \"cpu\": 71,\n      \"memory\": 59,\n      \"disk\": 0,\n      \"network\": 70,\n      \"uptime\": 4593374\n    },\n    {\n      \"id\": \"host-1420\",\n      \"name\": \"prod-cache-1420\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 28,\n      \"disk\": 16,\n      \"network\": 61,\n      \"uptime\": 5546573\n    },\n    {\n      \"id\": \"host-1421\",\n      \"name\": \"prod-worker-1421\",\n      \"status\": \"healthy\",\n      \"cpu\": 30,\n      \"memory\": 83,\n      \"disk\": 91,\n      \"network\": 94,\n      \"uptime\": 7424577\n    },\n    {\n      \"id\": \"host-1422\",\n      \"name\": \"prod-queue-1422\",\n      \"status\": \"healthy\",\n      \"cpu\": 42,\n      \"memory\": 67,\n      \"disk\": 87,\n      \"network\": 93,\n      \"uptime\": 4860411\n    },\n    {\n      \"id\": \"host-1423\",\n      \"name\": \"prod-web-1423\",\n      \"status\": \"healthy\",\n      \"cpu\": 75,\n      \"memory\": 90,\n      \"disk\": 8,\n      \"network\": 99,\n      \"uptime\": 7734896\n    },\n    {\n      \"id\": \"host-1424\",\n      \"name\": \"prod-api-1424\",\n      \"status\": \"healthy\",\n      \"cpu\": 54,\n      \"memory\": 36,\n      \"disk\": 71,\n      \"network\": 20,\n      \"uptime\": 8210109\n    },\n    {\n      \"id\": \"host-1425\",\n      \"name\": \"prod-database-1425\",\n      \"status\": \"healthy\",\n      \"cpu\": 98,\n      \"memory\": 14,\n      \"disk\": 97,\n      \"network\": 29,\n      \"uptime\": 3866778\n    },\n    {\n      \"id\": \"host-1426\",\n      \"name\": \"prod-cache-1426\",\n      \"status\": \"healthy\",\n      \"cpu\": 64,\n      \"memory\": 4,\n      \"disk\": 9,\n      \"network\": 92,\n      \"uptime\": 8121978\n    },\n    {\n      \"id\": \"host-1427\",\n      \"name\": \"prod-worker-1427\",\n      \"status\": \"healthy\",\n      \"cpu\": 100,\n      \"memory\": 60,\n      \"disk\": 44,\n      \"network\": 20,\n      \"uptime\": 2579694\n    },\n    {\n      \"id\": \"host-1428\",\n      \"name\": \"prod-queue-1428\",\n      \"status\": \"healthy\",\n      \"cpu\": 0,\n      \"memory\": 0,\n      \"disk\": 24,\n      \"network\": 1,\n      \"uptime\": 3842645\n    },\n    {\n      \"id\": \"host-1429\",\n      \"name\": \"prod-web-1429\",\n      \"status\": \"healthy\",\n      \"cpu\": 31,\n      \"memory\": 96,\n      \"disk\": 87,\n      \"network\": 100,\n      \"uptime\": 5732568\n    },\n    {\n      \"id\": \"host-1430\",\n      \"name\": \"prod-api-1430\",\n      \"status\": \"healthy\",\n      \"cpu\": 11,\n      \"memory\": 98,\n      \"disk\": 18,\n      \"network\": 62,\n      \"uptime\": 9856203\n    },\n    {\n      \"id\": \"host-1431\",\n      \"name\": \"prod-database-1431\",\n      \"status\": \"healthy\",\n      \"cpu\": 43,\n      \"memory\": 75,\n      \"disk\": 92,\n      \"network\": 68,\n      \"uptime\": 1836795\n    },\n    {\n      \"id\": \"host-1432\",\n      \"name\": \"prod-cache-1432\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 82,\n      \"disk\": 85,\n      \"network\": 12,\n      \"uptime\": 4337863\n    },\n    {\n      \"id\": \"host-1433\",\n      \"name\": \"prod-worker-1433\",\n      \"status\": \"healthy\",\n      \"cpu\": 68,\n      \"memory\": 72,\n      \"disk\": 79,\n      \"network\": 53,\n      \"uptime\": 2041173\n    },\n    {\n      \"id\": \"host-1434\",\n      \"name\": \"prod-queue-1434\",\n      \"status\": \"healthy\",\n      \"cpu\": 62,\n      \"memory\": 80,\n      \"disk\": 52,\n      \"network\": 95,\n      \"uptime\": 9119383\n    },\n    {\n      \"id\": \"host-1435\",\n      \"name\": \"prod-web-1435\",\n      \"status\": \"healthy\",\n      \"cpu\": 81,\n      \"memory\": 87,\n      \"disk\": 37,\n      \"network\": 43,\n      \"uptime\": 8500337\n    },\n    {\n      \"id\": \"host-1436\",\n      \"name\": \"prod-api-1436\",\n      \"status\": \"healthy\",\n      \"cpu\": 22,\n      \"memory\": 93,\n      \"disk\": 34,\n      \"network\": 23,\n      \"uptime\": 5396536\n    },\n    {\n      \"id\": \"host-1437\",\n      \"name\": \"prod-database-1437\",\n      \"status\": \"healthy\",\n      \"cpu\": 51,\n      \"memory\": 36,\n      \"disk\": 65,\n      \"network\": 53,\n      \"uptime\": 415103\n    },\n    {\n      \"id\": \"host-1438\",\n      \"name\": \"prod-cache-1438\",\n      \"status\": \"healthy\",\n      \"cpu\": 47,\n      \"memory\": 81,\n      \"disk\": 77,\n      \"network\": 44,\n      \"uptime\": 7505697\n    },\n    {\n      \"id\": \"host-1439\",\n      \"name\": \"prod-worker-1439\",\n      \"status\": \"healthy\",\n      \"cpu\": 41,\n      \"memory\": 44,\n      \"disk\": 62,\n      \"network\": 50,\n      \"uptime\": 5562159\n    },\n    {\n      \"id\": \"host-1440\",\n      \"name\": \"prod-queue-1440\",\n      \"status\": \"healthy\",\n      \"cpu\": 89,\n      \"memory\": 32,\n      \"disk\": 5,\n      \"network\": 67,\n      \"uptime\": 3519200\n    },\n    {\n      \"id\": \"host-1441\",\n      \"name\": \"prod-web-1441\",\n      \"status\": \"healthy\",\n      \"cpu\": 78,\n      \"memory\": 78,\n      \"disk\": 40,\n      \"network\": 50,\n      \"uptime\": 9191731\n    },\n    {\n      \"id\": \"host-1442\",\n      \"name\": \"prod-api-1442\",\n      \"status\": \"healthy\",\n      \"cpu\": 92,\n      \"memory\": 83,\n      \"disk\": 49,\n      \"network\": 17,\n      \"uptime\": 9526120\n    },\n    {\n      \"id\": \"host-1443\",\n      \"name\": \"prod-database-1443\",\n      \"status\": \"healthy\",\n      \"cpu\": 45,\n      \"memory\": 38,\n      \"disk\": 15,\n      \"network\": 35,\n      \"uptime\": 3315147\n    },\n    {\n      \"id\": \"host-1444\",\n      \"name\": \"prod-cache-1444\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 93,\n      \"disk\": 62,\n      \"network\": 62,\n      \"uptime\": 1140418\n    },\n    {\n      \"id\": \"host-1445\",\n      \"name\": \"prod-worker-1445\",\n      \"status\": \"healthy\",\n      \"cpu\": 19,\n      \"memory\": 68,\n      \"disk\": 30,\n      \"network\": 63,\n      \"uptime\": 8755174\n    },\n    {\n      \"id\": \"host-1446\",\n      \"name\": \"prod-queue-1446\",\n      \"status\": \"healthy\",\n      \"cpu\": 4,\n      \"memory\": 58,\n      \"disk\": 99,\n      \"network\": 4,\n      \"uptime\": 4149359\n    },\n    {\n      \"id\": \"host-1447\",\n      \"name\": \"prod-web-1447\",\n      \"status\": \"healthy\",\n      \"cpu\": 59,\n      \"memory\": 18,\n      \"disk\": 21,\n      \"network\": 34,\n      \"uptime\": 3642855\n    },\n    {\n      \"id\": \"host-1448\",\n      \"name\": \"prod-api-1448\",\n      \"status\": \"healthy\",\n      \"cpu\": 20,\n      \"memory\": 48,\n      \"disk\": 87,\n      \"network\": 41,\n      \"uptime\": 3900910\n    },\n    {\n      \"id\": \"host-1449\",\n      \"name\": \"prod-database-1449\",\n      \"status\": \"healthy\",\n      \"cpu\": 79,\n      \"memory\": 74,\n      \"disk\": 84,\n      \"network\": 51,\n      \"uptime\": 5918487\n    },\n    {\n      \"id\": \"host-1450\",\n      \"name\": \"prod-cache-1450\",\n      \"status\": \"healthy\",\n      \"cpu\": 48,\n      \"memory\": 18,\n      \"disk\": 69,\n      \"network\": 9,\n      \"uptime\": 1809292\n    },\n    {\n      \"id\": \"host-1451\",\n      \"name\": \"prod-worker-1451\",\n      \"status\": \"healthy\",\n      \"cpu\": 24,\n      \"memory\": 50,\n      \"disk\": 21,\n      \"network\": 20,\n      \"uptime\": 8081792\n    },\n    {\n      \"id\": \"host-1452\",\n      \"name\": \"prod-queue-1452\",\n      \"status\": \"healthy\",\n      \"cpu\": 32,\n      \"memory\": 17,\n      \"disk\": 53,\n      \"network\": 93,\n      \"uptime\": 582042\n    },\n    {\n      \"id\": \"host-1453\",\n      \"name\": \"prod-web-1453\",\n      \"status\": \"healthy\",\n      \"cpu\": 23,\n      \"memory\": 47,\n      \"disk\": 38,\n      \"network\": 99,\n      \"uptime\": 796367\n    },\n    {\n      \"id\": \"host-1454\",\n      \"name\": \"prod-api-1454\",\n      \"status\": \"healthy\",\n      \"cpu\": 56,\n      \"memory\": 69,\n      \"disk\": 13,\n      \"network\": 20,\n      \"uptime\": 9030824\n    },\n    {\n      \"id\": \"host-1455\",\n      \"name\": \"prod-database-1455\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 49,\n      \"disk\": 10,\n      \"network\": 59,\n      \"uptime\": 2113723\n    },\n    {\n      \"id\": \"host-1456\",\n      \"name\": \"prod-cache-1456\",\n      \"status\": \"healthy\",\n      \"cpu\": 68,\n      \"memory\": 66,\n      \"disk\": 63,\n      \"network\": 28,\n      \"uptime\": 6734501\n    },\n    {\n      \"id\": \"host-1457\",\n      \"name\": \"prod-worker-1457\",\n      \"status\": \"healthy\",\n      \"cpu\": 5,\n      \"memory\": 88,\n      \"disk\": 46,\n      \"network\": 28,\n      \"uptime\": 3107305\n    },\n    {\n      \"id\": \"host-1458\",\n      \"name\": \"prod-queue-1458\",\n      \"status\": \"healthy\",\n      \"cpu\": 75,\n      \"memory\": 13,\n      \"disk\": 90,\n      \"network\": 76,\n      \"uptime\": 7051902\n    },\n    {\n      \"id\": \"host-1459\",\n      \"name\": \"prod-web-1459\",\n      \"status\": \"healthy\",\n      \"cpu\": 94,\n      \"memory\": 65,\n      \"disk\": 98,\n      \"network\": 22,\n      \"uptime\": 5938218\n    },\n    {\n      \"id\": \"host-1460\",\n      \"name\": \"prod-api-1460\",\n      \"status\": \"healthy\",\n      \"cpu\": 1,\n      \"memory\": 69,\n      \"disk\": 74,\n      \"network\": 100,\n      \"uptime\": 1271589\n    },\n    {\n      \"id\": \"host-1461\",\n      \"name\": \"prod-database-1461\",\n      \"status\": \"warning\",\n      \"cpu\": 84,\n      \"memory\": 47,\n      \"disk\": 24,\n      \"network\": 95,\n      \"uptime\": 8621181\n    },\n    {\n      \"id\": \"host-1462\",\n      \"name\": \"prod-cache-1462\",\n      \"status\": \"warning\",\n      \"cpu\": 85,\n      \"memory\": 93,\n      \"disk\": 81,\n      \"network\": 98,\n      \"uptime\": 3570340\n    },\n    {\n      \"id\": \"host-1463\",\n      \"name\": \"prod-worker-1463\",\n      \"status\": \"warning\",\n      \"cpu\": 63,\n      \"memory\": 81,\n      \"disk\": 80,\n      \"network\": 57,\n      \"uptime\": 3420976\n    },\n    {\n      \"id\": \"host-1464\",\n      \"name\": \"prod-queue-1464\",\n      \"status\": \"warning\",\n      \"cpu\": 86,\n      \"memory\": 83,\n      \"disk\": 66,\n      \"network\": 49,\n      \"uptime\": 5508669\n    },\n    {\n      \"id\": \"host-1465\",\n      \"name\": \"prod-web-1465\",\n      \"status\": \"warning\",\n      \"cpu\": 8,\n      \"memory\": 67,\n      \"disk\": 45,\n      \"network\": 84,\n      \"uptime\": 5329633\n    },\n    {\n      \"id\": \"host-1466\",\n      \"name\": \"prod-api-1466\",\n      \"status\": \"warning\",\n      \"cpu\": 50,\n      \"memory\": 28,\n      \"disk\": 68,\n      \"network\": 42,\n      \"uptime\": 4498820\n    },\n    {\n      \"id\": \"host-1467\",\n      \"name\": \"prod-database-1467\",\n      \"status\": \"warning\",\n      \"cpu\": 97,\n      \"memory\": 98,\n      \"disk\": 59,\n      \"network\": 26,\n      \"uptime\": 7045060\n    },\n    {\n      \"id\": \"host-1468\",\n      \"name\": \"prod-cache-1468\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 32,\n      \"disk\": 68,\n      \"network\": 51,\n      \"uptime\": 4802266\n    },\n    {\n      \"id\": \"host-1469\",\n      \"name\": \"prod-worker-1469\",\n      \"status\": \"warning\",\n      \"cpu\": 39,\n      \"memory\": 71,\n      \"disk\": 46,\n      \"network\": 64,\n      \"uptime\": 8277083\n    },\n    {\n      \"id\": \"host-1470\",\n      \"name\": \"prod-queue-1470\",\n      \"status\": \"warning\",\n      \"cpu\": 96,\n      \"memory\": 68,\n      \"disk\": 35,\n      \"network\": 63,\n      \"uptime\": 9019960\n    },\n    {\n      \"id\": \"host-1471\",\n      \"name\": \"prod-web-1471\",\n      \"status\": \"warning\",\n      \"cpu\": 54,\n      \"memory\": 36,\n      \"disk\": 92,\n      \"network\": 7,\n      \"uptime\": 4952726\n    },\n    {\n      \"id\": \"host-1472\",\n      \"name\": \"prod-api-1472\",\n      \"status\": \"warning\",\n      \"cpu\": 35,\n      \"memory\": 84,\n      \"disk\": 8,\n      \"network\": 32,\n      \"uptime\": 8242548\n    },\n    {\n      \"id\": \"host-1473\",\n      \"name\": \"prod-database-1473\",\n      \"status\": \"warning\",\n      \"cpu\": 51,\n      \"memory\": 10,\n      \"disk\": 2,\n      \"network\": 63,\n      \"uptime\": 374908\n    },\n    {\n      \"id\": \"host-1474\",\n      \"name\": \"prod-cache-1474\",\n      \"status\": \"warning\",\n      \"cpu\": 70,\n      \"memory\": 100,\n      \"disk\": 82,\n      \"network\": 51,\n      \"uptime\": 5166155\n    },\n    {\n      \"id\": \"host-1475\",\n      \"name\": \"prod-worker-1475\",\n      \"status\": \"warning\",\n      \"cpu\": 23,\n      \"memory\": 24,\n      \"disk\": 89,\n      \"network\": 2,\n      \"uptime\": 1973751\n    },\n    {\n      \"id\": \"host-1476\",\n      \"name\": \"prod-queue-1476\",\n      \"status\": \"warning\",\n      \"cpu\": 27,\n      \"memory\": 22,\n      \"disk\": 40,\n      \"network\": 25,\n      \"uptime\": 8189751\n    },\n    {\n      \"id\": \"host-1477\",\n      \"name\": \"prod-web-1477\",\n      \"status\": \"warning\",\n      \"cpu\": 90,\n      \"memory\": 26,\n      \"disk\": 65,\n      \"network\": 45,\n      \"uptime\": 683902\n    },\n    {\n      \"id\": \"host-1478\",\n      \"name\": \"prod-api-1478\",\n      \"status\": \"warning\",\n      \"cpu\": 28,\n      \"memory\": 73,\n      \"disk\": 9,\n      \"network\": 50,\n      \"uptime\": 6995304\n    },\n    {\n      \"id\": \"host-1479\",\n      \"name\": \"prod-database-1479\",\n      \"status\": \"warning\",\n      \"cpu\": 82,\n      \"memory\": 85,\n      \"disk\": 18,\n      \"network\": 9,\n      \"uptime\": 1035630\n    },\n    {\n      \"id\": \"host-1480\",\n      \"name\": \"prod-cache-1480\",\n      \"status\": \"warning\",\n      \"cpu\": 83,\n      \"memory\": 0,\n      \"disk\": 38,\n      \"network\": 45,\n      \"uptime\": 5885925\n    },\n    {\n      \"id\": \"host-1481\",\n      \"name\": \"prod-worker-1481\",\n      \"status\": \"warning\",\n      \"cpu\": 97,\n      \"memory\": 26,\n      \"disk\": 6,\n      \"network\": 68,\n      \"uptime\": 4821848\n    },\n    {\n      \"id\": \"host-1482\",\n      \"name\": \"prod-queue-1482\",\n      \"status\": \"warning\",\n      \"cpu\": 6,\n      \"memory\": 16,\n      \"disk\": 72,\n      \"network\": 59,\n      \"uptime\": 2031824\n    },\n    {\n      \"id\": \"host-1483\",\n      \"name\": \"prod-web-1483\",\n      \"status\": \"warning\",\n      \"cpu\": 12,\n      \"memory\": 68,\n      \"disk\": 95,\n      \"network\": 76,\n      \"uptime\": 5209949\n    },\n    {\n      \"id\": \"host-1484\",\n      \"name\": \"prod-api-1484\",\n      \"status\": \"warning\",\n      \"cpu\": 11,\n      \"memory\": 83,\n      \"disk\": 88,\n      \"network\": 1,\n      \"uptime\": 7122844\n    },\n    {\n      \"id\": \"host-1485\",\n      \"name\": \"prod-database-1485\",\n      \"status\": \"warning\",\n      \"cpu\": 82,\n      \"memory\": 27,\n      \"disk\": 20,\n      \"network\": 75,\n      \"uptime\": 4228740\n    },\n    {\n      \"id\": \"host-1486\",\n      \"name\": \"prod-cache-1486\",\n      \"status\": \"critical\",\n      \"cpu\": 91,\n      \"memory\": 12,\n      \"disk\": 91,\n      \"network\": 82,\n      \"uptime\": 4117576\n    },\n    {\n      \"id\": \"host-1487\",\n      \"name\": \"prod-worker-1487\",\n      \"status\": \"critical\",\n      \"cpu\": 37,\n      \"memory\": 1,\n      \"disk\": 74,\n      \"network\": 76,\n      \"uptime\": 5593151\n    },\n    {\n      \"id\": \"host-1488\",\n      \"name\": \"prod-queue-1488\",\n      \"status\": \"critical\",\n      \"cpu\": 86,\n      \"memory\": 42,\n      \"disk\": 75,\n      \"network\": 55,\n      \"uptime\": 4764829\n    },\n    {\n      \"id\": \"host-1489\",\n      \"name\": \"prod-web-1489\",\n      \"status\": \"critical\",\n      \"cpu\": 63,\n      \"memory\": 48,\n      \"disk\": 3,\n      \"network\": 3,\n      \"uptime\": 2882771\n    },\n    {\n      \"id\": \"host-1490\",\n      \"name\": \"prod-api-1490\",\n      \"status\": \"critical\",\n      \"cpu\": 46,\n      \"memory\": 64,\n      \"disk\": 2,\n      \"network\": 42,\n      \"uptime\": 9449351\n    },\n    {\n      \"id\": \"host-1491\",\n      \"name\": \"prod-database-1491\",\n      \"status\": \"critical\",\n      \"cpu\": 27,\n      \"memory\": 96,\n      \"disk\": 48,\n      \"network\": 4,\n      \"uptime\": 4320590\n    },\n    {\n      \"id\": \"host-1492\",\n      \"name\": \"prod-cache-1492\",\n      \"status\": \"critical\",\n      \"cpu\": 88,\n      \"memory\": 7,\n      \"disk\": 38,\n      \"network\": 52,\n      \"uptime\": 6575720\n    },\n    {\n      \"id\": \"host-1493\",\n      \"name\": \"prod-worker-1493\",\n      \"status\": \"critical\",\n      \"cpu\": 67,\n      \"memory\": 47,\n      \"disk\": 61,\n      \"network\": 14,\n      \"uptime\": 1043095\n    },\n    {\n      \"id\": \"host-1494\",\n      \"name\": \"prod-queue-1494\",\n      \"status\": \"critical\",\n      \"cpu\": 84,\n      \"memory\": 14,\n      \"disk\": 4,\n      \"network\": 41,\n      \"uptime\": 1796219\n    },\n    {\n      \"id\": \"host-1495\",\n      \"name\": \"prod-web-1495\",\n      \"status\": \"critical\",\n      \"cpu\": 9,\n      \"memory\": 74,\n      \"disk\": 73,\n      \"network\": 86,\n      \"uptime\": 9012401\n    },\n    {\n      \"id\": \"host-1496\",\n      \"name\": \"prod-api-1496\",\n      \"status\": \"critical\",\n      \"cpu\": 99,\n      \"memory\": 28,\n      \"disk\": 53,\n      \"network\": 19,\n      \"uptime\": 9720309\n    },\n    {\n      \"id\": \"host-1497\",\n      \"name\": \"prod-database-1497\",\n      \"status\": \"critical\",\n      \"cpu\": 95,\n      \"memory\": 38,\n      \"disk\": 47,\n      \"network\": 5,\n      \"uptime\": 1124651\n    },\n    {\n      \"id\": \"host-1498\",\n      \"name\": \"prod-cache-1498\",\n      \"status\": \"critical\",\n      \"cpu\": 57,\n      \"memory\": 63,\n      \"disk\": 72,\n      \"network\": 53,\n      \"uptime\": 3407150\n    },\n    {\n      \"id\": \"host-1499\",\n      \"name\": \"prod-worker-1499\",\n      \"status\": \"critical\",\n      \"cpu\": 66,\n      \"memory\": 44,\n      \"disk\": 11,\n      \"network\": 11,\n      \"uptime\": 8251534\n    },\n    {\n      \"id\": \"host-1500\",\n      \"name\": \"prod-queue-1500\",\n      \"status\": \"critical\",\n      \"cpu\": 36,\n      \"memory\": 0,\n      \"disk\": 42,\n      \"network\": 56,\n      \"uptime\": 9960551\n    }\n  ]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/public/data/logs.json",
    "content": "{\n  \"logs\": [\n    {\n      \"id\": \"log-1680\",\n      \"timestamp\": 1761145169689,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache miss for key: user:3298\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-914\",\n      \"timestamp\": 1761145037302,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"File uploaded: yh3ykt.pdf\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1268\",\n      \"timestamp\": 1761144943551,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1408\",\n      \"timestamp\": 1761144572773,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1940\",\n      \"timestamp\": 1761144378218,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1418\",\n      \"timestamp\": 1761144355063,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Retry attempt 4 for failed request\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1367\",\n      \"timestamp\": 1761144009914,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Queue size approaching limit: 8843\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1375\",\n      \"timestamp\": 1761143707420,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-689\",\n      \"timestamp\": 1761143648668,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-851\",\n      \"timestamp\": 1761143179974,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1093\",\n      \"timestamp\": 1761143066359,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Lock released: resource-28\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-190\",\n      \"timestamp\": 1761142386601,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-632\",\n      \"timestamp\": 1761142337832,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-130\",\n      \"timestamp\": 1761141822322,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-550\",\n      \"timestamp\": 1761141616721,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"File uploaded: vz1m8.pdf\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:main\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-229\",\n      \"timestamp\": 1761140706926,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Stock updated for product SKU-86795\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1354\",\n      \"timestamp\": 1761140499979,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-723\",\n      \"timestamp\": 1761139536504,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1730\",\n      \"timestamp\": 1761139376778,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-111\",\n      \"timestamp\": 1761137875639,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1932\",\n      \"timestamp\": 1761137544585,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1090\",\n      \"timestamp\": 1761137343759,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Request processed successfully in 467ms\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-857\",\n      \"timestamp\": 1761137146767,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-834\",\n      \"timestamp\": 1761136744727,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-268\",\n      \"timestamp\": 1761136389824,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1917\",\n      \"timestamp\": 1761136250534,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1732\",\n      \"timestamp\": 1761136118215,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-788\",\n      \"timestamp\": 1761136031176,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Lock released: resource-36\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-531\",\n      \"timestamp\": 1761136001391,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1248\",\n      \"timestamp\": 1761135585492,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Rate limit approaching for client 192.168.165.52\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-340\",\n      \"timestamp\": 1761135516678,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1293\",\n      \"timestamp\": 1761135471911,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Stock updated for product SKU-39914\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-587\",\n      \"timestamp\": 1761135406099,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Stock updated for product SKU-96265\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1633\",\n      \"timestamp\": 1761135315564,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Request processed successfully in 318ms\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-925\",\n      \"timestamp\": 1761135252844,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Slow query detected: SELECT * FROM transactions...\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1919\",\n      \"timestamp\": 1761135120123,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Request processed successfully in 274ms\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-7\",\n      \"timestamp\": 1761135087764,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-869\",\n      \"timestamp\": 1761134621514,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1134\",\n      \"timestamp\": 1761133571520,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-621\",\n      \"timestamp\": 1761133274521,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-315\",\n      \"timestamp\": 1761132963846,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database pool almost full: 92/100\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-564\",\n      \"timestamp\": 1761132876032,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-143\",\n      \"timestamp\": 1761132854159,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-291\",\n      \"timestamp\": 1761132823538,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1441\",\n      \"timestamp\": 1761132808790,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1774\",\n      \"timestamp\": 1761132754628,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Order ORD-894567 completed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1289\",\n      \"timestamp\": 1761132711346,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-845\",\n      \"timestamp\": 1761132096809,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-234\",\n      \"timestamp\": 1761132049371,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1257\",\n      \"timestamp\": 1761131458423,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Authentication failed for user169@example.com: invalid credentials\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1733\",\n      \"timestamp\": 1761130993949,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Queue size approaching limit: 9747\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-314\",\n      \"timestamp\": 1761130886435,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-18\",\n      \"timestamp\": 1761130614066,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-698\",\n      \"timestamp\": 1761130561390,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Database pool almost full: 97/100\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-702\",\n      \"timestamp\": 1761130521265,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1449\",\n      \"timestamp\": 1761130313321,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"HTTP request: DELETE /uploads/8yl3yw.jpg\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-324\",\n      \"timestamp\": 1761129918707,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1073\",\n      \"timestamp\": 1761129677106,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-924\",\n      \"timestamp\": 1761128819164,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-838\",\n      \"timestamp\": 1761127774170,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Cache hit for key: user:5275\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1447\",\n      \"timestamp\": 1761127068470,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Stock updated for product SKU-89869\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1463\",\n      \"timestamp\": 1761126600583,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1990\",\n      \"timestamp\": 1761126425393,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1382\",\n      \"timestamp\": 1761126415732,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-169\",\n      \"timestamp\": 1761125923932,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-860\",\n      \"timestamp\": 1761125507870,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Lock acquired: resource-55\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-805\",\n      \"timestamp\": 1761125081866,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"High memory usage: 88%\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1145\",\n      \"timestamp\": 1761124659272,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1737\",\n      \"timestamp\": 1761124044899,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1047\",\n      \"timestamp\": 1761123857037,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-996\",\n      \"timestamp\": 1761123832108,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache invalidated: user:4602\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1087\",\n      \"timestamp\": 1761123374032,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Personalized recommendations generated for user 22943\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-536\",\n      \"timestamp\": 1761122944268,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1767\",\n      \"timestamp\": 1761122846312,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"New user registered: user475@example.com\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-558\",\n      \"timestamp\": 1761122064556,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1116\",\n      \"timestamp\": 1761121567694,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-973\",\n      \"timestamp\": 1761121447935,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock acquired: resource-36\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1326\",\n      \"timestamp\": 1761121218855,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-549\",\n      \"timestamp\": 1761121202829,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Lock acquired: resource-22\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-434\",\n      \"timestamp\": 1761120840672,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-352\",\n      \"timestamp\": 1761120542271,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"New user registered: user343@example.com\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-446\",\n      \"timestamp\": 1761120322934,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1849\",\n      \"timestamp\": 1761120077698,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1661\",\n      \"timestamp\": 1761119714053,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1280\",\n      \"timestamp\": 1761119443799,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1497\",\n      \"timestamp\": 1761119412643,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-971\",\n      \"timestamp\": 1761118822995,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"High memory usage: 77%\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-46\",\n      \"timestamp\": 1761118532336,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1172\",\n      \"timestamp\": 1761118305945,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Lock released: resource-67\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-391\",\n      \"timestamp\": 1761116868903,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-837\",\n      \"timestamp\": 1761115742576,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-12\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-454\",\n      \"timestamp\": 1761115194207,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-220\",\n      \"timestamp\": 1761114573710,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1524\",\n      \"timestamp\": 1761114294211,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-161\",\n      \"timestamp\": 1761113886452,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1635\",\n      \"timestamp\": 1761113788312,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1389\",\n      \"timestamp\": 1761112966052,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1972\",\n      \"timestamp\": 1761112728792,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-898\",\n      \"timestamp\": 1761112068160,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1476\",\n      \"timestamp\": 1761111860106,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-200\",\n      \"timestamp\": 1761111531230,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-422\",\n      \"timestamp\": 1761111209207,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-308\",\n      \"timestamp\": 1761110615761,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache miss for key: user:2727\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-479\",\n      \"timestamp\": 1761110577873,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1982\",\n      \"timestamp\": 1761110430041,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"HTTP request: PUT /uploads/4b3hx.jpg\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-727\",\n      \"timestamp\": 1761110273194,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1199\",\n      \"timestamp\": 1761110094887,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1690\",\n      \"timestamp\": 1761110087418,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1961\",\n      \"timestamp\": 1761109825917,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache hit for key: user:4453\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-347\",\n      \"timestamp\": 1761109824641,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-9\",\n      \"timestamp\": 1761109751115,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Request processed successfully in 448ms\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-848\",\n      \"timestamp\": 1761109648337,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1965\",\n      \"timestamp\": 1761109327235,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"File not found: /uploads/ny6uhv.jpg\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-820\",\n      \"timestamp\": 1761108785279,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-415\",\n      \"timestamp\": 1761107059833,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"High memory usage: 94%\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1685\",\n      \"timestamp\": 1761106980080,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-639\",\n      \"timestamp\": 1761106865841,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-742\",\n      \"timestamp\": 1761106682568,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Lock released: resource-22\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-746\",\n      \"timestamp\": 1761106574087,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Request processed successfully in 149ms\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-816\",\n      \"timestamp\": 1761106274279,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache invalidated: user:3802\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1335\",\n      \"timestamp\": 1761105681192,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Queue size approaching limit: 9194\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1789\",\n      \"timestamp\": 1761105473420,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1814\",\n      \"timestamp\": 1761104954981,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Connection pool stats: active=6/max=50\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-783\",\n      \"timestamp\": 1761104869571,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Request processed successfully in 279ms\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1120\",\n      \"timestamp\": 1761104821254,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-211\",\n      \"timestamp\": 1761104729190,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1966\",\n      \"timestamp\": 1761104667759,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Rate limit approaching for client 192.168.90.121\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1169\",\n      \"timestamp\": 1761104651991,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1271\",\n      \"timestamp\": 1761104304249,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache invalidated: user:5007\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-124\",\n      \"timestamp\": 1761104235302,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1197\",\n      \"timestamp\": 1761103666522,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Stock updated for product SKU-25084\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-652\",\n      \"timestamp\": 1761103377633,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-56\",\n      \"timestamp\": 1761103309731,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-812\",\n      \"timestamp\": 1761102759799,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-72\",\n      \"timestamp\": 1761101923481,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1766\",\n      \"timestamp\": 1761100853826,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1979\",\n      \"timestamp\": 1761100642803,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-575\",\n      \"timestamp\": 1761100562621,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-377\",\n      \"timestamp\": 1761100486860,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache hit for key: user:6131\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1405\",\n      \"timestamp\": 1761099826241,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-782\",\n      \"timestamp\": 1761099676085,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1434\",\n      \"timestamp\": 1761099624495,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-282\",\n      \"timestamp\": 1761099566527,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1213\",\n      \"timestamp\": 1761099565065,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-491\",\n      \"timestamp\": 1761099359711,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-359\",\n      \"timestamp\": 1761099347600,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1889\",\n      \"timestamp\": 1761099109133,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1010\",\n      \"timestamp\": 1761098941959,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1930\",\n      \"timestamp\": 1761098865814,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Personalized recommendations generated for user 65980\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1159\",\n      \"timestamp\": 1761098119008,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1499\",\n      \"timestamp\": 1761098116624,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1686\",\n      \"timestamp\": 1761098068566,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1150\",\n      \"timestamp\": 1761097654403,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache invalidated: user:6698\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1860\",\n      \"timestamp\": 1761097500592,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-676\",\n      \"timestamp\": 1761097402053,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-631\",\n      \"timestamp\": 1761097273792,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Retry attempt 4 for failed request\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-193\",\n      \"timestamp\": 1761097265311,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1140\",\n      \"timestamp\": 1761097063943,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Cache miss for key: user:6894\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1857\",\n      \"timestamp\": 1761097033562,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Authentication failed for user865@example.com: invalid credentials\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-283\",\n      \"timestamp\": 1761096840740,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-603\",\n      \"timestamp\": 1761096317540,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1137\",\n      \"timestamp\": 1761095962073,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-221\",\n      \"timestamp\": 1761095707000,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1976\",\n      \"timestamp\": 1761094706522,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-977\",\n      \"timestamp\": 1761094596944,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1504\",\n      \"timestamp\": 1761094314805,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache miss for key: user:6014\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-115\",\n      \"timestamp\": 1761094297868,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-448\",\n      \"timestamp\": 1761094141019,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1882\",\n      \"timestamp\": 1761093479024,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache miss for key: user:5735\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1787\",\n      \"timestamp\": 1761093446488,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"File uploaded: gohe4.pdf\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-515\",\n      \"timestamp\": 1761093220093,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Lock released: resource-60\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-945\",\n      \"timestamp\": 1761092966997,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-310\",\n      \"timestamp\": 1761092882778,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\", \"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1604\",\n      \"timestamp\": 1761092842719,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1888\",\n      \"timestamp\": 1761092782113,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache miss for key: user:8370\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1398\",\n      \"timestamp\": 1761092745426,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Order ORD-669017 completed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1800\",\n      \"timestamp\": 1761092323185,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"SSL certificate expires in 16 days\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-798\",\n      \"timestamp\": 1761091589428,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Lock released: resource-1\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1196\",\n      \"timestamp\": 1761091204644,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"HTTP request: GET /uploads/amzrj.jpg\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1409\",\n      \"timestamp\": 1761091079323,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-372\",\n      \"timestamp\": 1761091004281,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1743\",\n      \"timestamp\": 1761090105446,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-757\",\n      \"timestamp\": 1761088289355,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-33\",\n      \"timestamp\": 1761087942913,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-146\",\n      \"timestamp\": 1761086708786,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Lock released: resource-93\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-413\",\n      \"timestamp\": 1761086670179,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-936\",\n      \"timestamp\": 1761086055491,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"New user registered: user199@example.com\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1695\",\n      \"timestamp\": 1761085814961,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-47\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1109\",\n      \"timestamp\": 1761085671438,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Personalized recommendations generated for user 29265\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1100\",\n      \"timestamp\": 1761085577584,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1987\",\n      \"timestamp\": 1761085550030,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"New user registered: user744@example.com\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-516\",\n      \"timestamp\": 1761084693464,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"High memory usage: 79%\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1454\",\n      \"timestamp\": 1761084497861,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Authentication failed for user251@example.com: invalid credentials\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1630\",\n      \"timestamp\": 1761084140032,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1208\",\n      \"timestamp\": 1761083911332,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1103\",\n      \"timestamp\": 1761083760115,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Queue size approaching limit: 9099\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-351\",\n      \"timestamp\": 1761083284650,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Queue size approaching limit: 9261\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1528\",\n      \"timestamp\": 1761083238763,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Request processed successfully in 42ms\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-468\",\n      \"timestamp\": 1761083182530,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Lock released: resource-41\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-154\",\n      \"timestamp\": 1761083181423,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1696\",\n      \"timestamp\": 1761082482645,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-722\",\n      \"timestamp\": 1761082363154,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Entering function: calculateTotal\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-119\",\n      \"timestamp\": 1761081592788,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1240\",\n      \"timestamp\": 1761081523136,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-949\",\n      \"timestamp\": 1761080943432,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-532\",\n      \"timestamp\": 1761080744351,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-262\",\n      \"timestamp\": 1761080692403,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"SSL certificate expires in 13 days\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1305\",\n      \"timestamp\": 1761080512676,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"New user registered: user998@example.com\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1256\",\n      \"timestamp\": 1761080351095,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Order ORD-896185 completed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1832\",\n      \"timestamp\": 1761080178407,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1585\",\n      \"timestamp\": 1761080148468,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Cache invalidated: user:795\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-481\",\n      \"timestamp\": 1761080138473,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-179\",\n      \"timestamp\": 1761079985436,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Connection pool stats: active=35/max=50\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-378\",\n      \"timestamp\": 1761079852655,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-175\",\n      \"timestamp\": 1761079728073,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-334\",\n      \"timestamp\": 1761078913284,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-280\",\n      \"timestamp\": 1761078310749,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"SSL certificate expires in 27 days\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1192\",\n      \"timestamp\": 1761078287765,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1650\",\n      \"timestamp\": 1761078253457,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-346\",\n      \"timestamp\": 1761077919362,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-445\",\n      \"timestamp\": 1761077287881,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1069\",\n      \"timestamp\": 1761077191863,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1114\",\n      \"timestamp\": 1761076791115,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-870\",\n      \"timestamp\": 1761076616627,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-350\",\n      \"timestamp\": 1761076321664,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-864\",\n      \"timestamp\": 1761076106496,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-83\",\n      \"timestamp\": 1761075821947,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Database pool almost full: 81/100\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1007\",\n      \"timestamp\": 1761075575683,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Lock acquired: resource-10\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\", \"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1655\",\n      \"timestamp\": 1761075430121,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-795\",\n      \"timestamp\": 1761075181278,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database pool almost full: 92/100\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-552\",\n      \"timestamp\": 1761075136820,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-641\",\n      \"timestamp\": 1761075122311,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-642\",\n      \"timestamp\": 1761074658425,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-595\",\n      \"timestamp\": 1761074554802,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock acquired: resource-94\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-625\",\n      \"timestamp\": 1761073929490,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1572\",\n      \"timestamp\": 1761073663986,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"SSL certificate expires in 9 days\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1121\",\n      \"timestamp\": 1761073357308,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-147\",\n      \"timestamp\": 1761073053911,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Order ORD-704960 completed\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-159\",\n      \"timestamp\": 1761073049745,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-125\",\n      \"timestamp\": 1761072974931,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1044\",\n      \"timestamp\": 1761072777342,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"File not found: /uploads/ssocvs.jpg\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1029\",\n      \"timestamp\": 1761072513180,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1956\",\n      \"timestamp\": 1761071380208,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-323\",\n      \"timestamp\": 1761071068575,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"HTTP request: POST /uploads/wg0fw9.jpg\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1728\",\n      \"timestamp\": 1761070588182,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"High memory usage: 91%\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1355\",\n      \"timestamp\": 1761070503316,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-955\",\n      \"timestamp\": 1761070130280,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Order ORD-895669 completed\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-135\",\n      \"timestamp\": 1761068943480,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-368\",\n      \"timestamp\": 1761068654751,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1269\",\n      \"timestamp\": 1761068142932,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-341\",\n      \"timestamp\": 1761067534072,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1927\",\n      \"timestamp\": 1761066749771,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-57\",\n      \"timestamp\": 1761066729676,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-561\",\n      \"timestamp\": 1761066400247,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Personalized recommendations generated for user 94088\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1719\",\n      \"timestamp\": 1761066214980,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Slow query detected: SELECT * FROM orders...\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1510\",\n      \"timestamp\": 1761066146744,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-122\",\n      \"timestamp\": 1761066109906,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-541\",\n      \"timestamp\": 1761065949230,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1041\",\n      \"timestamp\": 1761065683143,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-196\",\n      \"timestamp\": 1761064884702,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Order ORD-547717 completed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1421\",\n      \"timestamp\": 1761064721938,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Queue size approaching limit: 9799\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1771\",\n      \"timestamp\": 1761064688149,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database pool almost full: 94/100\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-968\",\n      \"timestamp\": 1761063985015,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1138\",\n      \"timestamp\": 1761063910525,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-530\",\n      \"timestamp\": 1761063506718,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-687\",\n      \"timestamp\": 1761063460410,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database pool almost full: 87/100\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1721\",\n      \"timestamp\": 1761063420040,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1851\",\n      \"timestamp\": 1761062786705,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1278\",\n      \"timestamp\": 1761062220833,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-806\",\n      \"timestamp\": 1761061449523,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-852\",\n      \"timestamp\": 1761061302068,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Order ORD-750427 completed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-20\",\n      \"timestamp\": 1761060410424,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1724\",\n      \"timestamp\": 1761060158306,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-40\",\n      \"timestamp\": 1761059810485,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-997\",\n      \"timestamp\": 1761059522986,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"SSL certificate expires in 5 days\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1580\",\n      \"timestamp\": 1761059309697,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-380\",\n      \"timestamp\": 1761059106696,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-97\",\n      \"timestamp\": 1761058710522,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Cache invalidated: user:7368\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-361\",\n      \"timestamp\": 1761058571324,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-117\",\n      \"timestamp\": 1761058503646,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1808\",\n      \"timestamp\": 1761058482302,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-709\",\n      \"timestamp\": 1761058414424,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Scheduled job completed: report-generation\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-867\",\n      \"timestamp\": 1761058148758,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-235\",\n      \"timestamp\": 1761057960513,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1755\",\n      \"timestamp\": 1761057777785,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Authentication failed for user857@example.com: invalid credentials\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1665\",\n      \"timestamp\": 1761057742392,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Authentication failed for user73@example.com: invalid credentials\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1119\",\n      \"timestamp\": 1761057661627,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database pool almost full: 81/100\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-116\",\n      \"timestamp\": 1761057661479,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-988\",\n      \"timestamp\": 1761057378839,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"File uploaded: k3q8s4.pdf\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"cluster:backup\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-233\",\n      \"timestamp\": 1761057311992,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1705\",\n      \"timestamp\": 1761056922416,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"SSL certificate expires in 11 days\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-108\",\n      \"timestamp\": 1761056906247,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1612\",\n      \"timestamp\": 1761056658874,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-131\",\n      \"timestamp\": 1761056611532,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1812\",\n      \"timestamp\": 1761056572050,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Slow query detected: SELECT * FROM orders...\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1020\",\n      \"timestamp\": 1761056480249,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1374\",\n      \"timestamp\": 1761055893965,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-272\",\n      \"timestamp\": 1761055629814,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-467\",\n      \"timestamp\": 1761055446513,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1016\",\n      \"timestamp\": 1761055422403,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1401\",\n      \"timestamp\": 1761054782820,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-150\",\n      \"timestamp\": 1761054422780,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1122\",\n      \"timestamp\": 1761054177946,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1320\",\n      \"timestamp\": 1761053975892,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Lock acquired: resource-22\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-285\",\n      \"timestamp\": 1761053579785,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1893\",\n      \"timestamp\": 1761053572629,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Order ORD-254415 completed\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1937\",\n      \"timestamp\": 1761053351891,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-402\",\n      \"timestamp\": 1761053027375,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1239\",\n      \"timestamp\": 1761052313517,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1534\",\n      \"timestamp\": 1761052274136,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-266\",\n      \"timestamp\": 1761052170399,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1957\",\n      \"timestamp\": 1761051975230,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1260\",\n      \"timestamp\": 1761051624828,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1773\",\n      \"timestamp\": 1761051593929,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Stock updated for product SKU-88517\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1547\",\n      \"timestamp\": 1761050938669,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"HTTP response: 200\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-41\",\n      \"timestamp\": 1761050606821,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-615\",\n      \"timestamp\": 1761050458864,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1327\",\n      \"timestamp\": 1761050292193,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1455\",\n      \"timestamp\": 1761050157622,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Connection pool stats: active=3/max=50\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1472\",\n      \"timestamp\": 1761049011095,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-362\",\n      \"timestamp\": 1761048942081,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1806\",\n      \"timestamp\": 1761048905750,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-774\",\n      \"timestamp\": 1761048491293,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-186\",\n      \"timestamp\": 1761048402101,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Request processed successfully in 370ms\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-214\",\n      \"timestamp\": 1761048011156,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:3.0.1\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1084\",\n      \"timestamp\": 1761047872700,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1960\",\n      \"timestamp\": 1761047850048,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-177\",\n      \"timestamp\": 1761047276427,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-488\",\n      \"timestamp\": 1761046919376,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Connection pool stats: active=44/max=50\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-671\",\n      \"timestamp\": 1761046770833,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1237\",\n      \"timestamp\": 1761046625915,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1797\",\n      \"timestamp\": 1761045707275,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"File not found: /uploads/9enhpl.jpg\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1287\",\n      \"timestamp\": 1761045158571,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-831\",\n      \"timestamp\": 1761045154158,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-596\",\n      \"timestamp\": 1761044827403,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Database pool almost full: 93/100\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1222\",\n      \"timestamp\": 1761044143932,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1645\",\n      \"timestamp\": 1761043673871,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"region:eu-west-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-23\",\n      \"timestamp\": 1761042640531,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-293\",\n      \"timestamp\": 1761042566921,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1484\",\n      \"timestamp\": 1761041754355,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Authentication failed for user275@example.com: invalid credentials\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1609\",\n      \"timestamp\": 1761041469234,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Order ORD-169095 completed\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1164\",\n      \"timestamp\": 1761040594709,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1457\",\n      \"timestamp\": 1761040546996,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-53\",\n      \"timestamp\": 1761040276377,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Retry attempt 5 for failed request\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1687\",\n      \"timestamp\": 1761039841142,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Slow query detected: SELECT * FROM transactions...\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-747\",\n      \"timestamp\": 1761039103983,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-499\",\n      \"timestamp\": 1761038890172,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1482\",\n      \"timestamp\": 1761038632797,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Stock updated for product SKU-18413\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-809\",\n      \"timestamp\": 1761038022227,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1214\",\n      \"timestamp\": 1761037912559,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1908\",\n      \"timestamp\": 1761037804560,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1968\",\n      \"timestamp\": 1761037511727,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"SSL certificate expires in 16 days\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-950\",\n      \"timestamp\": 1761037396342,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"HTTP response: 200\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-223\",\n      \"timestamp\": 1761037078027,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1292\",\n      \"timestamp\": 1761036930344,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1360\",\n      \"timestamp\": 1761036914245,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-701\",\n      \"timestamp\": 1761036744095,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1906\",\n      \"timestamp\": 1761035359508,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-602\",\n      \"timestamp\": 1761035033830,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-10\",\n      \"timestamp\": 1761034250962,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1419\",\n      \"timestamp\": 1761033982130,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-349\",\n      \"timestamp\": 1761033414556,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1852\",\n      \"timestamp\": 1761032770521,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"File uploaded: 0ijfb9.pdf\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-139\",\n      \"timestamp\": 1761032574173,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1130\",\n      \"timestamp\": 1761032332302,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock acquired: resource-72\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-725\",\n      \"timestamp\": 1761032232267,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1377\",\n      \"timestamp\": 1761031654051,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1363\",\n      \"timestamp\": 1761031329866,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"SSL certificate expires in 28 days\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1507\",\n      \"timestamp\": 1761031327091,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database pool almost full: 85/100\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1828\",\n      \"timestamp\": 1761030595676,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-134\",\n      \"timestamp\": 1761030024727,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-374\",\n      \"timestamp\": 1761029966703,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-431\",\n      \"timestamp\": 1761029376111,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1708\",\n      \"timestamp\": 1761029021326,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-328\",\n      \"timestamp\": 1761028678573,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock acquired: resource-28\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-162\",\n      \"timestamp\": 1761028664879,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1855\",\n      \"timestamp\": 1761028612789,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1369\",\n      \"timestamp\": 1761028408497,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Database pool almost full: 98/100\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-475\",\n      \"timestamp\": 1761028022234,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-643\",\n      \"timestamp\": 1761027902050,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-510\",\n      \"timestamp\": 1761027896411,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache miss for key: user:4844\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1745\",\n      \"timestamp\": 1761027770172,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"High memory usage: 86%\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1587\",\n      \"timestamp\": 1761027517964,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"HTTP response: 204\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-899\",\n      \"timestamp\": 1761027425395,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Rate limit approaching for client 192.168.6.146\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1112\",\n      \"timestamp\": 1761027344755,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-439\",\n      \"timestamp\": 1761027310987,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-265\",\n      \"timestamp\": 1761026875296,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-244\",\n      \"timestamp\": 1761026250367,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1160\",\n      \"timestamp\": 1761025766482,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1274\",\n      \"timestamp\": 1761025508751,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-39\",\n      \"timestamp\": 1761025298821,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-230\",\n      \"timestamp\": 1761025131911,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"High memory usage: 77%\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-305\",\n      \"timestamp\": 1761024317792,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1626\",\n      \"timestamp\": 1761024164589,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1786\",\n      \"timestamp\": 1761023826673,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Request processed successfully in 334ms\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-381\",\n      \"timestamp\": 1761023561962,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Lock released: resource-60\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-674\",\n      \"timestamp\": 1761023423081,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-565\",\n      \"timestamp\": 1761023263697,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Lock released: resource-97\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1311\",\n      \"timestamp\": 1761023238400,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1829\",\n      \"timestamp\": 1761023080543,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1912\",\n      \"timestamp\": 1761022883401,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Request processed successfully in 139ms\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1028\",\n      \"timestamp\": 1761022547991,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Personalized recommendations generated for user 98914\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1249\",\n      \"timestamp\": 1761022236668,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1935\",\n      \"timestamp\": 1761021765395,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1544\",\n      \"timestamp\": 1761021524633,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-343\",\n      \"timestamp\": 1761020752062,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-734\",\n      \"timestamp\": 1761020674188,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Authentication failed for user814@example.com: invalid credentials\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1378\",\n      \"timestamp\": 1761020604799,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Authentication failed for user159@example.com: invalid credentials\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1247\",\n      \"timestamp\": 1761020464033,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"SSL certificate expires in 13 days\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1555\",\n      \"timestamp\": 1761020052658,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1301\",\n      \"timestamp\": 1761019645486,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock released: resource-34\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-89\",\n      \"timestamp\": 1761019222850,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-604\",\n      \"timestamp\": 1761018969179,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1738\",\n      \"timestamp\": 1761018594394,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Order ORD-980016 completed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-464\",\n      \"timestamp\": 1761018487463,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"File uploaded: pmphhf.pdf\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1306\",\n      \"timestamp\": 1761018121278,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-318\",\n      \"timestamp\": 1761017930215,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1558\",\n      \"timestamp\": 1761017450967,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock acquired: resource-84\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1465\",\n      \"timestamp\": 1761017051066,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"File uploaded: js64qq.pdf\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1254\",\n      \"timestamp\": 1761016705720,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-588\",\n      \"timestamp\": 1761016499892,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1520\",\n      \"timestamp\": 1761016280813,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-713\",\n      \"timestamp\": 1761015461770,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Rate limit approaching for client 192.168.72.163\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-504\",\n      \"timestamp\": 1761015280696,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1262\",\n      \"timestamp\": 1761014901086,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Personalized recommendations generated for user 91825\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-717\",\n      \"timestamp\": 1761014785595,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"File not found: /uploads/cnggdu.jpg\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1489\",\n      \"timestamp\": 1761014746185,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1753\",\n      \"timestamp\": 1761014664564,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1790\",\n      \"timestamp\": 1761014562028,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"SSL certificate expires in 15 days\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1765\",\n      \"timestamp\": 1761014204904,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"New user registered: user725@example.com\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1494\",\n      \"timestamp\": 1761012956215,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Personalized recommendations generated for user 60702\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1723\",\n      \"timestamp\": 1761012923189,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1601\",\n      \"timestamp\": 1761012408893,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database pool almost full: 93/100\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-843\",\n      \"timestamp\": 1761012356051,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"HTTP request: POST /uploads/ldqi7g.jpg\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-259\",\n      \"timestamp\": 1761012031229,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-157\",\n      \"timestamp\": 1761011788364,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1666\",\n      \"timestamp\": 1761011690527,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"High memory usage: 82%\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-880\",\n      \"timestamp\": 1761011397460,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-818\",\n      \"timestamp\": 1761011204643,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1295\",\n      \"timestamp\": 1761011141564,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"New user registered: user335@example.com\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-778\",\n      \"timestamp\": 1761010651219,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-121\",\n      \"timestamp\": 1761010635860,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Authentication failed for user455@example.com: invalid credentials\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-79\",\n      \"timestamp\": 1761010294196,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Stock updated for product SKU-88341\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1750\",\n      \"timestamp\": 1761010194009,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Rate limit approaching for client 192.168.6.254\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1672\",\n      \"timestamp\": 1761009420748,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1531\",\n      \"timestamp\": 1761009279466,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-574\",\n      \"timestamp\": 1761009141124,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Request processed successfully in 403ms\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1620\",\n      \"timestamp\": 1761008440865,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-993\",\n      \"timestamp\": 1761008190447,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-383\",\n      \"timestamp\": 1761008097054,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1291\",\n      \"timestamp\": 1761008011867,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1241\",\n      \"timestamp\": 1761007359326,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Lock released: resource-25\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1567\",\n      \"timestamp\": 1761006950897,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-195\",\n      \"timestamp\": 1761006807408,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP request: PUT /uploads/9rcyd.jpg\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1741\",\n      \"timestamp\": 1761006443677,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1483\",\n      \"timestamp\": 1761005863909,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-99\",\n      \"timestamp\": 1761005312100,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"File uploaded: c5h0fh.pdf\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-487\",\n      \"timestamp\": 1761005096921,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Lock released: resource-2\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-148\",\n      \"timestamp\": 1761004605679,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-482\",\n      \"timestamp\": 1761004452869,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Personalized recommendations generated for user 18520\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-81\",\n      \"timestamp\": 1761004376003,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"File uploaded: w35zwo.pdf\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1397\",\n      \"timestamp\": 1761003354900,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"High memory usage: 76%\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-472\",\n      \"timestamp\": 1761002939734,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-810\",\n      \"timestamp\": 1761002677093,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1485\",\n      \"timestamp\": 1761002507419,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-966\",\n      \"timestamp\": 1761002495684,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Lock acquired: resource-88\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1638\",\n      \"timestamp\": 1761002396044,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1546\",\n      \"timestamp\": 1761001777472,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1780\",\n      \"timestamp\": 1761001680199,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Request processed successfully in 231ms\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-67\",\n      \"timestamp\": 1761001670768,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"HTTP request: PUT /uploads/cz1tu.jpg\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1611\",\n      \"timestamp\": 1761001459619,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1323\",\n      \"timestamp\": 1761000816120,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-802\",\n      \"timestamp\": 1761000652925,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1480\",\n      \"timestamp\": 1761000299241,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Order ORD-993222 completed\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1052\",\n      \"timestamp\": 1761000287386,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache hit for key: user:1827\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-456\",\n      \"timestamp\": 1761000096868,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1296\",\n      \"timestamp\": 1760999606422,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1366\",\n      \"timestamp\": 1760999496564,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Lock acquired: resource-88\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-503\",\n      \"timestamp\": 1760999341429,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Retry attempt 5 for failed request\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-398\",\n      \"timestamp\": 1760999240831,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1688\",\n      \"timestamp\": 1760999074296,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Stock updated for product SKU-73062\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-78\",\n      \"timestamp\": 1760998275768,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-297\",\n      \"timestamp\": 1760998095093,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"HTTP response: 200\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1275\",\n      \"timestamp\": 1760998068766,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Personalized recommendations generated for user 57086\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1900\",\n      \"timestamp\": 1760997933169,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-452\",\n      \"timestamp\": 1760997769305,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-553\",\n      \"timestamp\": 1760997175530,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1588\",\n      \"timestamp\": 1760997154582,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-675\",\n      \"timestamp\": 1760996876366,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"High memory usage: 80%\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-96\",\n      \"timestamp\": 1760996045474,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-332\",\n      \"timestamp\": 1760996019389,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache miss for key: user:7257\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1021\",\n      \"timestamp\": 1760995924518,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"HTTP response: 404\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1403\",\n      \"timestamp\": 1760995012520,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1527\",\n      \"timestamp\": 1760994680229,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-35\",\n      \"timestamp\": 1760994276035,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"File uploaded: 54n0l.pdf\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1153\",\n      \"timestamp\": 1760993808807,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1061\",\n      \"timestamp\": 1760993584936,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-100\",\n      \"timestamp\": 1760993324065,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-243\",\n      \"timestamp\": 1760992690048,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-444\",\n      \"timestamp\": 1760992588735,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1769\",\n      \"timestamp\": 1760992478440,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"New user registered: user694@example.com\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-544\",\n      \"timestamp\": 1760992099328,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-863\",\n      \"timestamp\": 1760991863168,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1632\",\n      \"timestamp\": 1760991544623,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1477\",\n      \"timestamp\": 1760991242373,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Database pool almost full: 86/100\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-325\",\n      \"timestamp\": 1760991061003,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1359\",\n      \"timestamp\": 1760991040794,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1820\",\n      \"timestamp\": 1760990859431,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"HTTP response: 404\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1065\",\n      \"timestamp\": 1760990384612,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-661\",\n      \"timestamp\": 1760990281598,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1221\",\n      \"timestamp\": 1760990082736,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-858\",\n      \"timestamp\": 1760989619370,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1155\",\n      \"timestamp\": 1760989162620,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1697\",\n      \"timestamp\": 1760988271883,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Stock updated for product SKU-22955\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1001\",\n      \"timestamp\": 1760987861327,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1994\",\n      \"timestamp\": 1760987717592,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Lock released: resource-42\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:3.0.1\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1290\",\n      \"timestamp\": 1760987123935,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1303\",\n      \"timestamp\": 1760987072805,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1664\",\n      \"timestamp\": 1760987021219,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1201\",\n      \"timestamp\": 1760986984700,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock released: resource-75\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1794\",\n      \"timestamp\": 1760986981890,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"File uploaded: nuvv0d.pdf\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1763\",\n      \"timestamp\": 1760986633451,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"New user registered: user12@example.com\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-720\",\n      \"timestamp\": 1760986521667,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1811\",\n      \"timestamp\": 1760986295105,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-554\",\n      \"timestamp\": 1760986073500,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-791\",\n      \"timestamp\": 1760984112407,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"High memory usage: 94%\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-483\",\n      \"timestamp\": 1760983668960,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-152\",\n      \"timestamp\": 1760983593481,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"File uploaded: j5ymc.pdf\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-218\",\n      \"timestamp\": 1760983187796,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Entering function: calculateTotal\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-55\",\n      \"timestamp\": 1760983133011,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"SSL certificate expires in 20 days\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-974\",\n      \"timestamp\": 1760982924537,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"SSL certificate expires in 18 days\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1105\",\n      \"timestamp\": 1760982643040,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-560\",\n      \"timestamp\": 1760982559640,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-155\",\n      \"timestamp\": 1760982519829,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1376\",\n      \"timestamp\": 1760982364794,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"File uploaded: 8wvm75i.pdf\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-570\",\n      \"timestamp\": 1760982095052,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Rate limit approaching for client 192.168.224.168\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-930\",\n      \"timestamp\": 1760981918495,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1691\",\n      \"timestamp\": 1760981809673,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-493\",\n      \"timestamp\": 1760981591663,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-192\",\n      \"timestamp\": 1760979629659,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Rate limit approaching for client 192.168.252.110\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-630\",\n      \"timestamp\": 1760979166764,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1799\",\n      \"timestamp\": 1760979111626,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1744\",\n      \"timestamp\": 1760978864241,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"SSL certificate expires in 2 days\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1332\",\n      \"timestamp\": 1760978858467,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1653\",\n      \"timestamp\": 1760978797498,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-608\",\n      \"timestamp\": 1760978748983,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Request processed successfully in 453ms\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"region:eu-west-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1991\",\n      \"timestamp\": 1760978440899,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1846\",\n      \"timestamp\": 1760977836436,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1776\",\n      \"timestamp\": 1760977092325,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-36\",\n      \"timestamp\": 1760977043340,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-534\",\n      \"timestamp\": 1760976857306,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache invalidated: user:360\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1317\",\n      \"timestamp\": 1760976553949,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"New user registered: user726@example.com\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1648\",\n      \"timestamp\": 1760975769184,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1598\",\n      \"timestamp\": 1760975744673,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1322\",\n      \"timestamp\": 1760975164098,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1345\",\n      \"timestamp\": 1760974929480,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Authentication failed for user743@example.com: invalid credentials\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-680\",\n      \"timestamp\": 1760974924841,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1636\",\n      \"timestamp\": 1760974787120,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1284\",\n      \"timestamp\": 1760974539656,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Connection pool stats: active=12/max=50\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-537\",\n      \"timestamp\": 1760974439980,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1710\",\n      \"timestamp\": 1760974417966,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"New user registered: user939@example.com\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1819\",\n      \"timestamp\": 1760974160408,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1156\",\n      \"timestamp\": 1760973589492,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-789\",\n      \"timestamp\": 1760973249370,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-785\",\n      \"timestamp\": 1760972717973,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-947\",\n      \"timestamp\": 1760972228432,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1552\",\n      \"timestamp\": 1760971958135,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1139\",\n      \"timestamp\": 1760971255401,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1045\",\n      \"timestamp\": 1760970896414,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1223\",\n      \"timestamp\": 1760970447468,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1509\",\n      \"timestamp\": 1760970320666,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-461\",\n      \"timestamp\": 1760970218962,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1171\",\n      \"timestamp\": 1760969794787,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"File uploaded: 9gc1to.pdf\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-137\",\n      \"timestamp\": 1760969578249,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-750\",\n      \"timestamp\": 1760969117193,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1146\",\n      \"timestamp\": 1760968575545,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Connection pool stats: active=19/max=50\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1641\",\n      \"timestamp\": 1760968078288,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"HTTP response: 200\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-273\",\n      \"timestamp\": 1760967975599,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Database pool almost full: 96/100\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1995\",\n      \"timestamp\": 1760967873562,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1111\",\n      \"timestamp\": 1760967682984,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Retry attempt 4 for failed request\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-921\",\n      \"timestamp\": 1760967165635,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1729\",\n      \"timestamp\": 1760966806799,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-735\",\n      \"timestamp\": 1760966393775,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-302\",\n      \"timestamp\": 1760965842980,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1095\",\n      \"timestamp\": 1760965812313,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-170\",\n      \"timestamp\": 1760964860158,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1805\",\n      \"timestamp\": 1760964577295,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-929\",\n      \"timestamp\": 1760963755946,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-754\",\n      \"timestamp\": 1760962923795,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1136\",\n      \"timestamp\": 1760962893394,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1803\",\n      \"timestamp\": 1760962815886,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache invalidated: user:3713\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-529\",\n      \"timestamp\": 1760962311478,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-198\",\n      \"timestamp\": 1760962001782,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1056\",\n      \"timestamp\": 1760961453400,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-994\",\n      \"timestamp\": 1760960738906,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-894\",\n      \"timestamp\": 1760960407729,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-719\",\n      \"timestamp\": 1760960271453,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-251\",\n      \"timestamp\": 1760959752353,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Order ORD-294601 completed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-626\",\n      \"timestamp\": 1760959524927,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"SSL certificate expires in 21 days\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1574\",\n      \"timestamp\": 1760959440643,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-866\",\n      \"timestamp\": 1760959008120,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-197\",\n      \"timestamp\": 1760958881483,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-476\",\n      \"timestamp\": 1760958834046,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-394\",\n      \"timestamp\": 1760958549077,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1083\",\n      \"timestamp\": 1760958414396,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-721\",\n      \"timestamp\": 1760958291113,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"SSL certificate expires in 10 days\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1144\",\n      \"timestamp\": 1760958140319,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1154\",\n      \"timestamp\": 1760957576843,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache miss for key: user:2115\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1535\",\n      \"timestamp\": 1760956975232,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1\",\n      \"timestamp\": 1760956915033,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache invalidated: user:4032\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-580\",\n      \"timestamp\": 1760956815018,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1887\",\n      \"timestamp\": 1760956680388,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-371\",\n      \"timestamp\": 1760956383403,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"HTTP request: POST /uploads/pgnqwp.jpg\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1251\",\n      \"timestamp\": 1760956210436,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Request processed successfully in 275ms\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1717\",\n      \"timestamp\": 1760956020658,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1807\",\n      \"timestamp\": 1760955878421,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1228\",\n      \"timestamp\": 1760955006140,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1163\",\n      \"timestamp\": 1760953869678,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-551\",\n      \"timestamp\": 1760953749017,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache invalidated: user:1437\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1525\",\n      \"timestamp\": 1760953730271,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-741\",\n      \"timestamp\": 1760953070321,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1071\",\n      \"timestamp\": 1760952307751,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-354\",\n      \"timestamp\": 1760952302093,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1495\",\n      \"timestamp\": 1760952215373,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-90\",\n      \"timestamp\": 1760952173144,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-826\",\n      \"timestamp\": 1760952114931,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Personalized recommendations generated for user 94417\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1086\",\n      \"timestamp\": 1760952077855,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Lock released: resource-70\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-114\",\n      \"timestamp\": 1760951333833,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"High memory usage: 78%\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-174\",\n      \"timestamp\": 1760951067048,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-216\",\n      \"timestamp\": 1760951029096,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1538\",\n      \"timestamp\": 1760950974001,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-160\",\n      \"timestamp\": 1760950879776,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1619\",\n      \"timestamp\": 1760950651486,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Rate limit approaching for client 192.168.153.110\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1835\",\n      \"timestamp\": 1760950480235,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1897\",\n      \"timestamp\": 1760950471389,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1212\",\n      \"timestamp\": 1760950214052,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Order ORD-155239 completed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1336\",\n      \"timestamp\": 1760949683512,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1884\",\n      \"timestamp\": 1760949224027,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-207\",\n      \"timestamp\": 1760949068780,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1349\",\n      \"timestamp\": 1760948571474,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-990\",\n      \"timestamp\": 1760948276548,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-287\",\n      \"timestamp\": 1760947983530,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1232\",\n      \"timestamp\": 1760947651449,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-992\",\n      \"timestamp\": 1760947419330,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1694\",\n      \"timestamp\": 1760947022055,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1573\",\n      \"timestamp\": 1760945936781,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-999\",\n      \"timestamp\": 1760945756813,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"File not found: /uploads/6eamn.jpg\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-256\",\n      \"timestamp\": 1760945026390,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Connection pool stats: active=38/max=50\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1370\",\n      \"timestamp\": 1760944699969,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-882\",\n      \"timestamp\": 1760943969600,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1381\",\n      \"timestamp\": 1760943520410,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1823\",\n      \"timestamp\": 1760943187841,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1181\",\n      \"timestamp\": 1760943183820,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Database pool almost full: 94/100\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1971\",\n      \"timestamp\": 1760943160979,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-406\",\n      \"timestamp\": 1760942441388,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-901\",\n      \"timestamp\": 1760942020498,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1840\",\n      \"timestamp\": 1760941971099,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1361\",\n      \"timestamp\": 1760941711425,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-149\",\n      \"timestamp\": 1760941396212,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-724\",\n      \"timestamp\": 1760940981765,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1394\",\n      \"timestamp\": 1760940789993,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Cache invalidated: user:171\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1539\",\n      \"timestamp\": 1760940620308,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-648\",\n      \"timestamp\": 1760940591813,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-519\",\n      \"timestamp\": 1760940333021,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database pool almost full: 83/100\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-187\",\n      \"timestamp\": 1760940238551,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache invalidated: user:1939\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1341\",\n      \"timestamp\": 1760940133568,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1276\",\n      \"timestamp\": 1760939854350,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Queue size approaching limit: 8024\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-61\",\n      \"timestamp\": 1760939394223,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-212\",\n      \"timestamp\": 1760939385068,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1039\",\n      \"timestamp\": 1760939274201,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1346\",\n      \"timestamp\": 1760939161075,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1605\",\n      \"timestamp\": 1760938824371,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"File uploaded: f5n81.pdf\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1227\",\n      \"timestamp\": 1760938657170,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-204\",\n      \"timestamp\": 1760938608375,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-399\",\n      \"timestamp\": 1760938482641,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-390\",\n      \"timestamp\": 1760938444011,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-991\",\n      \"timestamp\": 1760937990464,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Request processed successfully in 212ms\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-540\",\n      \"timestamp\": 1760937218825,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-271\",\n      \"timestamp\": 1760936861210,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-983\",\n      \"timestamp\": 1760936583515,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1161\",\n      \"timestamp\": 1760936368222,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1329\",\n      \"timestamp\": 1760936296363,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1947\",\n      \"timestamp\": 1760936123942,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1064\",\n      \"timestamp\": 1760936061207,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Rate limit approaching for client 192.168.51.40\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-786\",\n      \"timestamp\": 1760935692379,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"File not found: /uploads/o0gqw.jpg\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1234\",\n      \"timestamp\": 1760935557871,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1720\",\n      \"timestamp\": 1760935557165,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-52\",\n      \"timestamp\": 1760935152092,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1920\",\n      \"timestamp\": 1760935062289,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1999\",\n      \"timestamp\": 1760934855423,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"SSL certificate expires in 3 days\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1702\",\n      \"timestamp\": 1760934660587,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-760\",\n      \"timestamp\": 1760934569182,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-213\",\n      \"timestamp\": 1760934103380,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1701\",\n      \"timestamp\": 1760934091201,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-480\",\n      \"timestamp\": 1760933918178,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1435\",\n      \"timestamp\": 1760933812639,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1559\",\n      \"timestamp\": 1760933470575,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Request processed successfully in 39ms\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1175\",\n      \"timestamp\": 1760933436633,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Entering function: calculateTotal\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1712\",\n      \"timestamp\": 1760933127123,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Personalized recommendations generated for user 88998\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1225\",\n      \"timestamp\": 1760932982231,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Lock acquired: resource-62\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1266\",\n      \"timestamp\": 1760932759933,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Request processed successfully in 441ms\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-731\",\n      \"timestamp\": 1760932463144,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1331\",\n      \"timestamp\": 1760932087437,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-979\",\n      \"timestamp\": 1760931895580,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1085\",\n      \"timestamp\": 1760931739275,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"High memory usage: 90%\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-975\",\n      \"timestamp\": 1760931262614,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Connection pool stats: active=10/max=50\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-684\",\n      \"timestamp\": 1760930978059,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache hit for key: user:1659\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-267\",\n      \"timestamp\": 1760930741434,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"File not found: /uploads/xj3wkb.jpg\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-908\",\n      \"timestamp\": 1760930698114,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-592\",\n      \"timestamp\": 1760930574471,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1640\",\n      \"timestamp\": 1760930379755,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Queue size approaching limit: 8461\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-868\",\n      \"timestamp\": 1760930248110,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-828\",\n      \"timestamp\": 1760929939816,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-577\",\n      \"timestamp\": 1760929748987,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache invalidated: user:8863\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-27\",\n      \"timestamp\": 1760929592449,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"SSL certificate expires in 21 days\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1583\",\n      \"timestamp\": 1760928828424,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1006\",\n      \"timestamp\": 1760928828187,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Cache miss for key: user:7121\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1242\",\n      \"timestamp\": 1760928784511,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-403\",\n      \"timestamp\": 1760928240351,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Authentication failed for user512@example.com: invalid credentials\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1182\",\n      \"timestamp\": 1760927546990,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-129\",\n      \"timestamp\": 1760927506634,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1055\",\n      \"timestamp\": 1760927342340,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1026\",\n      \"timestamp\": 1760927273791,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Stock updated for product SKU-99451\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-911\",\n      \"timestamp\": 1760927220118,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-699\",\n      \"timestamp\": 1760927103975,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-629\",\n      \"timestamp\": 1760926045916,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1673\",\n      \"timestamp\": 1760925728535,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Retry attempt 2 for failed request\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-242\",\n      \"timestamp\": 1760924890870,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1022\",\n      \"timestamp\": 1760924836116,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-194\",\n      \"timestamp\": 1760924598020,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1593\",\n      \"timestamp\": 1760923777548,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock released: resource-88\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1277\",\n      \"timestamp\": 1760922235893,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache hit for key: user:8722\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-937\",\n      \"timestamp\": 1760921955778,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-330\",\n      \"timestamp\": 1760921657633,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-753\",\n      \"timestamp\": 1760921514535,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1748\",\n      \"timestamp\": 1760921181131,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-704\",\n      \"timestamp\": 1760921162012,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-19\",\n      \"timestamp\": 1760920914018,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Personalized recommendations generated for user 68861\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-42\",\n      \"timestamp\": 1760920626187,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"File not found: /uploads/v8fyp6.jpg\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1302\",\n      \"timestamp\": 1760919871515,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1177\",\n      \"timestamp\": 1760919245714,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1216\",\n      \"timestamp\": 1760919181946,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database pool almost full: 96/100\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-21\",\n      \"timestamp\": 1760917886345,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-777\",\n      \"timestamp\": 1760917181341,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-694\",\n      \"timestamp\": 1760915998131,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"File not found: /uploads/nmox66.jpg\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-142\",\n      \"timestamp\": 1760915820819,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-523\",\n      \"timestamp\": 1760915761594,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1107\",\n      \"timestamp\": 1760915237634,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"High memory usage: 90%\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-80\",\n      \"timestamp\": 1760915068565,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-41\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-258\",\n      \"timestamp\": 1760914705389,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Lock released: resource-45\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1816\",\n      \"timestamp\": 1760914651960,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1517\",\n      \"timestamp\": 1760914548223,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-249\",\n      \"timestamp\": 1760914004591,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-964\",\n      \"timestamp\": 1760913632745,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Connection pool stats: active=26/max=50\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-62\",\n      \"timestamp\": 1760912925472,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1958\",\n      \"timestamp\": 1760912645400,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-941\",\n      \"timestamp\": 1760912270039,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-138\",\n      \"timestamp\": 1760912030036,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-881\",\n      \"timestamp\": 1760911778870,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1693\",\n      \"timestamp\": 1760911651206,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-255\",\n      \"timestamp\": 1760911487508,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-329\",\n      \"timestamp\": 1760911468849,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Connection pool stats: active=49/max=50\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-171\",\n      \"timestamp\": 1760911327731,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Authentication failed for user349@example.com: invalid credentials\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-92\",\n      \"timestamp\": 1760910967242,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Stock updated for product SKU-79513\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1125\",\n      \"timestamp\": 1760910547001,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-841\",\n      \"timestamp\": 1760910493320,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Lock acquired: resource-25\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1581\",\n      \"timestamp\": 1760910348284,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-635\",\n      \"timestamp\": 1760909978045,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-228\",\n      \"timestamp\": 1760909004979,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Personalized recommendations generated for user 93494\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-716\",\n      \"timestamp\": 1760908957755,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-429\",\n      \"timestamp\": 1760908624049,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"SSL certificate expires in 21 days\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1402\",\n      \"timestamp\": 1760907912168,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-263\",\n      \"timestamp\": 1760907777544,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1412\",\n      \"timestamp\": 1760907740710,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-548\",\n      \"timestamp\": 1760907281961,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1406\",\n      \"timestamp\": 1760907279222,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Request processed successfully in 60ms\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1854\",\n      \"timestamp\": 1760907123864,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-524\",\n      \"timestamp\": 1760906915524,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-460\",\n      \"timestamp\": 1760906452682,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"New user registered: user775@example.com\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-960\",\n      \"timestamp\": 1760906180986,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-512\",\n      \"timestamp\": 1760905894826,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1973\",\n      \"timestamp\": 1760905490325,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1217\",\n      \"timestamp\": 1760905122111,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Entering function: calculateTotal\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-892\",\n      \"timestamp\": 1760904989271,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1431\",\n      \"timestamp\": 1760904955930,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"File uploaded: xflm8l.pdf\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-5\",\n      \"timestamp\": 1760904731621,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1578\",\n      \"timestamp\": 1760904524464,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1353\",\n      \"timestamp\": 1760904195960,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1934\",\n      \"timestamp\": 1760903931633,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1200\",\n      \"timestamp\": 1760903842712,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP request: POST /uploads/c7jox.jpg\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-296\",\n      \"timestamp\": 1760903482457,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-478\",\n      \"timestamp\": 1760902849641,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Stock updated for product SKU-43678\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1118\",\n      \"timestamp\": 1760902655129,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1831\",\n      \"timestamp\": 1760902584745,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache invalidated: user:2445\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-813\",\n      \"timestamp\": 1760902490405,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Authentication failed for user747@example.com: invalid credentials\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-972\",\n      \"timestamp\": 1760901244966,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Order ORD-738053 completed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-546\",\n      \"timestamp\": 1760900965163,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock released: resource-70\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1067\",\n      \"timestamp\": 1760900946780,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"File uploaded: 6a66o.pdf\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-489\",\n      \"timestamp\": 1760900692834,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache miss for key: user:994\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-659\",\n      \"timestamp\": 1760900154135,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1211\",\n      \"timestamp\": 1760900027192,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-311\",\n      \"timestamp\": 1760899892698,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Slow query detected: SELECT * FROM orders...\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-740\",\n      \"timestamp\": 1760898543785,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-980\",\n      \"timestamp\": 1760898002244,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1910\",\n      \"timestamp\": 1760897702952,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"High memory usage: 91%\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1417\",\n      \"timestamp\": 1760897527976,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-989\",\n      \"timestamp\": 1760897089909,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-404\",\n      \"timestamp\": 1760896576623,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"SSL certificate expires in 13 days\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1943\",\n      \"timestamp\": 1760896249858,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1334\",\n      \"timestamp\": 1760896211190,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1173\",\n      \"timestamp\": 1760895311113,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database pool almost full: 80/100\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-366\",\n      \"timestamp\": 1760895100368,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-238\",\n      \"timestamp\": 1760894874387,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Personalized recommendations generated for user 51042\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1890\",\n      \"timestamp\": 1760894715435,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-946\",\n      \"timestamp\": 1760894343902,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1049\",\n      \"timestamp\": 1760893967465,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-533\",\n      \"timestamp\": 1760893531778,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"HTTP response: 404\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-17\",\n      \"timestamp\": 1760893486894,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-104\",\n      \"timestamp\": 1760893424860,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"High memory usage: 90%\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-151\",\n      \"timestamp\": 1760893021697,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1881\",\n      \"timestamp\": 1760892357156,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1102\",\n      \"timestamp\": 1760892334192,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-543\",\n      \"timestamp\": 1760891869248,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1532\",\n      \"timestamp\": 1760891336319,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1070\",\n      \"timestamp\": 1760890926355,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-770\",\n      \"timestamp\": 1760890074110,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-64\",\n      \"timestamp\": 1760889821542,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Database pool almost full: 91/100\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1157\",\n      \"timestamp\": 1760889228476,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1488\",\n      \"timestamp\": 1760888685232,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1681\",\n      \"timestamp\": 1760887906242,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Rate limit approaching for client 192.168.39.182\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1031\",\n      \"timestamp\": 1760887892804,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1886\",\n      \"timestamp\": 1760887741695,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"HTTP request: PUT /uploads/1uykc.jpg\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-917\",\n      \"timestamp\": 1760887238747,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1692\",\n      \"timestamp\": 1760886429352,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1473\",\n      \"timestamp\": 1760885689241,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"File uploaded: aw0igw.pdf\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-37\",\n      \"timestamp\": 1760885626595,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-756\",\n      \"timestamp\": 1760885402142,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-284\",\n      \"timestamp\": 1760884713888,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Scheduled job completed: report-generation\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-245\",\n      \"timestamp\": 1760884696680,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"New user registered: user470@example.com\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1751\",\n      \"timestamp\": 1760884177595,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-538\",\n      \"timestamp\": 1760884048134,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-579\",\n      \"timestamp\": 1760883977543,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Connection pool stats: active=25/max=50\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1351\",\n      \"timestamp\": 1760883756278,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Cache hit for key: user:3345\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1627\",\n      \"timestamp\": 1760883323762,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-94\",\n      \"timestamp\": 1760882375488,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-961\",\n      \"timestamp\": 1760882084934,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"File not found: /uploads/xs21jv.jpg\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1590\",\n      \"timestamp\": 1760881583330,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1898\",\n      \"timestamp\": 1760881368711,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache hit for key: user:444\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-956\",\n      \"timestamp\": 1760881286645,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-71\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1936\",\n      \"timestamp\": 1760881244414,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-498\",\n      \"timestamp\": 1760880992967,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1142\",\n      \"timestamp\": 1760880882108,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Cache hit for key: user:1102\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-739\",\n      \"timestamp\": 1760880016443,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Request processed successfully in 164ms\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-765\",\n      \"timestamp\": 1760879897146,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1817\",\n      \"timestamp\": 1760879067562,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1446\",\n      \"timestamp\": 1760878411749,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-891\",\n      \"timestamp\": 1760878049323,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-567\",\n      \"timestamp\": 1760878020620,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-803\",\n      \"timestamp\": 1760877916370,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-141\",\n      \"timestamp\": 1760877860501,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"HTTP request: PUT /uploads/gqc7yg.jpg\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1191\",\n      \"timestamp\": 1760877857251,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-521\",\n      \"timestamp\": 1760877749980,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Personalized recommendations generated for user 98228\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1383\",\n      \"timestamp\": 1760877549604,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-252\",\n      \"timestamp\": 1760877467212,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1796\",\n      \"timestamp\": 1760877431454,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1215\",\n      \"timestamp\": 1760877243179,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"HTTP request: POST /uploads/lw9tmf.jpg\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1734\",\n      \"timestamp\": 1760877144269,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1035\",\n      \"timestamp\": 1760877034867,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Personalized recommendations generated for user 26954\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-658\",\n      \"timestamp\": 1760876329213,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-241\",\n      \"timestamp\": 1760876192910,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1978\",\n      \"timestamp\": 1760875762128,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"HTTP request: DELETE /uploads/0ehogb.jpg\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1713\",\n      \"timestamp\": 1760875457618,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"SSL certificate expires in 14 days\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-339\",\n      \"timestamp\": 1760875226189,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-931\",\n      \"timestamp\": 1760874846390,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Authentication failed for user959@example.com: invalid credentials\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1810\",\n      \"timestamp\": 1760874275321,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1304\",\n      \"timestamp\": 1760874083135,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1097\",\n      \"timestamp\": 1760873691516,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1899\",\n      \"timestamp\": 1760873647259,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"File uploaded: jjqtw.pdf\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-427\",\n      \"timestamp\": 1760873457045,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1516\",\n      \"timestamp\": 1760873443889,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1526\",\n      \"timestamp\": 1760873144025,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"SSL certificate expires in 8 days\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-437\",\n      \"timestamp\": 1760871139776,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-188\",\n      \"timestamp\": 1760871115012,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"File uploaded: nyi7h.pdf\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-590\",\n      \"timestamp\": 1760870691720,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-225\",\n      \"timestamp\": 1760870564957,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache invalidated: user:3144\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1923\",\n      \"timestamp\": 1760868843065,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-288\",\n      \"timestamp\": 1760868235824,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-292\",\n      \"timestamp\": 1760867539239,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-982\",\n      \"timestamp\": 1760867487272,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1440\",\n      \"timestamp\": 1760866315078,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-518\",\n      \"timestamp\": 1760866260173,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"High memory usage: 88%\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-85\",\n      \"timestamp\": 1760866217848,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-471\",\n      \"timestamp\": 1760865698808,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Cache hit for key: user:7225\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1659\",\n      \"timestamp\": 1760865326353,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-703\",\n      \"timestamp\": 1760865007206,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-591\",\n      \"timestamp\": 1760864689863,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Personalized recommendations generated for user 52677\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-637\",\n      \"timestamp\": 1760864211287,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1429\",\n      \"timestamp\": 1760863963937,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1461\",\n      \"timestamp\": 1760863464835,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-189\",\n      \"timestamp\": 1760863290536,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1267\",\n      \"timestamp\": 1760862634746,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Lock released: resource-35\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-408\",\n      \"timestamp\": 1760862602700,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Personalized recommendations generated for user 63162\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-666\",\n      \"timestamp\": 1760862536712,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1474\",\n      \"timestamp\": 1760861958459,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1088\",\n      \"timestamp\": 1760860883611,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-274\",\n      \"timestamp\": 1760860864376,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-768\",\n      \"timestamp\": 1760860664227,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-290\",\n      \"timestamp\": 1760860279563,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-935\",\n      \"timestamp\": 1760860211907,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Rate limit approaching for client 192.168.223.193\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-181\",\n      \"timestamp\": 1760860205618,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Authentication failed for user263@example.com: invalid credentials\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1596\",\n      \"timestamp\": 1760860011234,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Queue size approaching limit: 8009\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1700\",\n      \"timestamp\": 1760859947614,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"File uploaded: 9c9pe5.pdf\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-286\",\n      \"timestamp\": 1760859658111,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-128\",\n      \"timestamp\": 1760859612371,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1853\",\n      \"timestamp\": 1760859414514,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-418\",\n      \"timestamp\": 1760859337828,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"HTTP request: DELETE /uploads/l5anu.jpg\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-373\",\n      \"timestamp\": 1760859279933,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Connection pool stats: active=28/max=50\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1089\",\n      \"timestamp\": 1760859166238,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"HTTP request: DELETE /uploads/i3rhx7.jpg\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-375\",\n      \"timestamp\": 1760858498653,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-438\",\n      \"timestamp\": 1760858458319,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-986\",\n      \"timestamp\": 1760857963528,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-133\",\n      \"timestamp\": 1760857793038,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Slow query detected: SELECT * FROM orders...\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1781\",\n      \"timestamp\": 1760857435200,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1396\",\n      \"timestamp\": 1760857427707,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-686\",\n      \"timestamp\": 1760856987289,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Personalized recommendations generated for user 78890\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"region:eu-west-1\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1503\",\n      \"timestamp\": 1760856871654,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-850\",\n      \"timestamp\": 1760854902691,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Authentication failed for user548@example.com: invalid credentials\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-862\",\n      \"timestamp\": 1760854827231,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-176\",\n      \"timestamp\": 1760854722135,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-66\",\n      \"timestamp\": 1760854341521,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1671\",\n      \"timestamp\": 1760854104195,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache miss for key: user:8457\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-397\",\n      \"timestamp\": 1760854036712,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1258\",\n      \"timestamp\": 1760853991412,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1642\",\n      \"timestamp\": 1760853806330,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-370\",\n      \"timestamp\": 1760853774912,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-522\",\n      \"timestamp\": 1760853745957,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1272\",\n      \"timestamp\": 1760853657774,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Retry attempt 5 for failed request\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-502\",\n      \"timestamp\": 1760853151553,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1614\",\n      \"timestamp\": 1760852763883,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-835\",\n      \"timestamp\": 1760852614322,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1479\",\n      \"timestamp\": 1760852473873,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1176\",\n      \"timestamp\": 1760851925504,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1180\",\n      \"timestamp\": 1760851759439,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"SSL certificate expires in 2 days\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-145\",\n      \"timestamp\": 1760851726276,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1904\",\n      \"timestamp\": 1760851188862,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1885\",\n      \"timestamp\": 1760851072599,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Authentication failed for user919@example.com: invalid credentials\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-817\",\n      \"timestamp\": 1760850121064,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1683\",\n      \"timestamp\": 1760849515757,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Rate limit approaching for client 192.168.61.37\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1428\",\n      \"timestamp\": 1760849381237,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-797\",\n      \"timestamp\": 1760849095247,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"File not found: /uploads/0ip4kn.jpg\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1458\",\n      \"timestamp\": 1760848555453,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Personalized recommendations generated for user 61986\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-906\",\n      \"timestamp\": 1760848432041,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1921\",\n      \"timestamp\": 1760848409729,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-586\",\n      \"timestamp\": 1760847926530,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1656\",\n      \"timestamp\": 1760847678457,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"SSL certificate expires in 25 days\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-4\",\n      \"timestamp\": 1760847252593,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Retry attempt 4 for failed request\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-319\",\n      \"timestamp\": 1760847126905,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1453\",\n      \"timestamp\": 1760846843051,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:3.0.1\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1037\",\n      \"timestamp\": 1760846761600,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1878\",\n      \"timestamp\": 1760846547165,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1606\",\n      \"timestamp\": 1760846439061,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1018\",\n      \"timestamp\": 1760846096705,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Queue size approaching limit: 9548\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1668\",\n      \"timestamp\": 1760845729010,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-201\",\n      \"timestamp\": 1760845202280,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock released: resource-95\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-963\",\n      \"timestamp\": 1760844931418,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database pool almost full: 91/100\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1048\",\n      \"timestamp\": 1760844785061,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-421\",\n      \"timestamp\": 1760844621058,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-712\",\n      \"timestamp\": 1760844433222,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1079\",\n      \"timestamp\": 1760844410315,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1126\",\n      \"timestamp\": 1760843733302,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-298\",\n      \"timestamp\": 1760843619779,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1541\",\n      \"timestamp\": 1760843288710,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-486\",\n      \"timestamp\": 1760842713936,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1983\",\n      \"timestamp\": 1760841175857,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-449\",\n      \"timestamp\": 1760841113381,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-13\",\n      \"timestamp\": 1760840769240,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Connection pool stats: active=47/max=50\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-928\",\n      \"timestamp\": 1760840732176,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"File uploaded: sdue7.pdf\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1903\",\n      \"timestamp\": 1760840345214,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Personalized recommendations generated for user 79798\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1203\",\n      \"timestamp\": 1760840023120,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-428\",\n      \"timestamp\": 1760839489152,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"High memory usage: 86%\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-473\",\n      \"timestamp\": 1760839111105,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-871\",\n      \"timestamp\": 1760838944640,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-804\",\n      \"timestamp\": 1760838925971,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"File not found: /uploads/q8j03q.jpg\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1595\",\n      \"timestamp\": 1760838868732,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1607\",\n      \"timestamp\": 1760838570285,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-508\",\n      \"timestamp\": 1760838421241,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1229\",\n      \"timestamp\": 1760838284075,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1540\",\n      \"timestamp\": 1760838280235,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Authentication failed for user740@example.com: invalid credentials\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\", \"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1218\",\n      \"timestamp\": 1760837175597,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-607\",\n      \"timestamp\": 1760836937936,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1407\",\n      \"timestamp\": 1760836885601,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Order ORD-687982 completed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-998\",\n      \"timestamp\": 1760836784130,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock released: resource-82\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1922\",\n      \"timestamp\": 1760836419899,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-43\",\n      \"timestamp\": 1760836176835,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Rate limit approaching for client 192.168.138.14\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-246\",\n      \"timestamp\": 1760836057909,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"File not found: /uploads/58cfu.jpg\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1584\",\n      \"timestamp\": 1760835935833,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1622\",\n      \"timestamp\": 1760835721884,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-7\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1460\",\n      \"timestamp\": 1760835632300,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"SSL certificate expires in 21 days\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1785\",\n      \"timestamp\": 1760834895867,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache invalidated: user:7311\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1400\",\n      \"timestamp\": 1760833918131,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache invalidated: user:3916\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1970\",\n      \"timestamp\": 1760833760241,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Personalized recommendations generated for user 88598\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-737\",\n      \"timestamp\": 1760833475144,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-136\",\n      \"timestamp\": 1760833469396,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Stock updated for product SKU-29570\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1424\",\n      \"timestamp\": 1760832538091,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-178\",\n      \"timestamp\": 1760832184359,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Authentication failed for user146@example.com: invalid credentials\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1872\",\n      \"timestamp\": 1760831803370,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-907\",\n      \"timestamp\": 1760830809339,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1562\",\n      \"timestamp\": 1760830528583,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-110\",\n      \"timestamp\": 1760830374490,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-987\",\n      \"timestamp\": 1760830335258,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-490\",\n      \"timestamp\": 1760829903101,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache miss for key: user:610\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-76\",\n      \"timestamp\": 1760829723510,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1862\",\n      \"timestamp\": 1760829450194,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1321\",\n      \"timestamp\": 1760829401205,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-855\",\n      \"timestamp\": 1760829205475,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1000\",\n      \"timestamp\": 1760829164079,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1068\",\n      \"timestamp\": 1760829015846,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-913\",\n      \"timestamp\": 1760828868978,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1782\",\n      \"timestamp\": 1760828858291,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Lock released: resource-51\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1793\",\n      \"timestamp\": 1760828764591,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-710\",\n      \"timestamp\": 1760828396440,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Personalized recommendations generated for user 27062\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1151\",\n      \"timestamp\": 1760827603294,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Cache hit for key: user:7901\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1929\",\n      \"timestamp\": 1760827387812,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-24\",\n      \"timestamp\": 1760826408043,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Queue size approaching limit: 9169\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1511\",\n      \"timestamp\": 1760826199909,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-790\",\n      \"timestamp\": 1760826131574,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Queue size approaching limit: 9560\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-696\",\n      \"timestamp\": 1760825752651,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Lock released: resource-45\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1735\",\n      \"timestamp\": 1760825740221,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1131\",\n      \"timestamp\": 1760825236251,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-647\",\n      \"timestamp\": 1760824346244,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-678\",\n      \"timestamp\": 1760824232107,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Authentication failed for user836@example.com: invalid credentials\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-761\",\n      \"timestamp\": 1760824218518,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-633\",\n      \"timestamp\": 1760824194162,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1847\",\n      \"timestamp\": 1760824031903,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Queue size approaching limit: 9642\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1244\",\n      \"timestamp\": 1760823114382,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache miss for key: user:8092\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1505\",\n      \"timestamp\": 1760821951890,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"File not found: /uploads/y24u5p.jpg\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-679\",\n      \"timestamp\": 1760821920195,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Stock updated for product SKU-95764\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1916\",\n      \"timestamp\": 1760821407840,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Cache miss for key: user:1540\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1989\",\n      \"timestamp\": 1760820877941,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1802\",\n      \"timestamp\": 1760820127828,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1496\",\n      \"timestamp\": 1760819897534,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache miss for key: user:8628\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1768\",\n      \"timestamp\": 1760819547210,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Personalized recommendations generated for user 60281\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1996\",\n      \"timestamp\": 1760819154921,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1617\",\n      \"timestamp\": 1760819010515,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"High memory usage: 80%\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1036\",\n      \"timestamp\": 1760818587387,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1907\",\n      \"timestamp\": 1760818214939,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"HTTP request: POST /uploads/fnatgm.jpg\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1195\",\n      \"timestamp\": 1760818147892,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1548\",\n      \"timestamp\": 1760817792605,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-939\",\n      \"timestamp\": 1760817718518,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1300\",\n      \"timestamp\": 1760817440534,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1205\",\n      \"timestamp\": 1760817223870,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1094\",\n      \"timestamp\": 1760817080836,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-300\",\n      \"timestamp\": 1760816325645,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"File uploaded: y97xda.pdf\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"region:eu-west-1\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1152\",\n      \"timestamp\": 1760815959845,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-2\",\n      \"timestamp\": 1760815210623,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-98\",\n      \"timestamp\": 1760814548219,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-410\",\n      \"timestamp\": 1760814533156,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Database pool almost full: 82/100\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-743\",\n      \"timestamp\": 1760814414625,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1491\",\n      \"timestamp\": 1760814287515,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-688\",\n      \"timestamp\": 1760814088125,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Lock acquired: resource-3\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-165\",\n      \"timestamp\": 1760813988754,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1149\",\n      \"timestamp\": 1760813455990,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache invalidated: user:6420\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1924\",\n      \"timestamp\": 1760813351754,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Stock updated for product SKU-95856\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-11\",\n      \"timestamp\": 1760813345665,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1082\",\n      \"timestamp\": 1760812979960,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-507\",\n      \"timestamp\": 1760812940877,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Authentication failed for user762@example.com: invalid credentials\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-563\",\n      \"timestamp\": 1760812674413,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-45\",\n      \"timestamp\": 1760812573843,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1714\",\n      \"timestamp\": 1760812403449,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-450\",\n      \"timestamp\": 1760812144071,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1676\",\n      \"timestamp\": 1760811791148,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Database pool almost full: 85/100\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-904\",\n      \"timestamp\": 1760811637799,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1684\",\n      \"timestamp\": 1760811288591,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-313\",\n      \"timestamp\": 1760811110853,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1410\",\n      \"timestamp\": 1760810744120,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock released: resource-14\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-927\",\n      \"timestamp\": 1760809858080,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Queue size approaching limit: 9067\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1518\",\n      \"timestamp\": 1760809747427,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-462\",\n      \"timestamp\": 1760809710107,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-545\",\n      \"timestamp\": 1760809708631,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-827\",\n      \"timestamp\": 1760809484387,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-578\",\n      \"timestamp\": 1760809364975,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1250\",\n      \"timestamp\": 1760809183698,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"New user registered: user356@example.com\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-705\",\n      \"timestamp\": 1760808781298,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1662\",\n      \"timestamp\": 1760808303657,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"File uploaded: 1kiz5h.pdf\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1158\",\n      \"timestamp\": 1760807969546,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-707\",\n      \"timestamp\": 1760807862773,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Order ORD-119997 completed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1246\",\n      \"timestamp\": 1760807789239,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Authentication failed for user936@example.com: invalid credentials\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-599\",\n      \"timestamp\": 1760807469571,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-585\",\n      \"timestamp\": 1760807441247,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1469\",\n      \"timestamp\": 1760807249421,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-948\",\n      \"timestamp\": 1760807124435,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-559\",\n      \"timestamp\": 1760807010670,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Stock updated for product SKU-78897\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1742\",\n      \"timestamp\": 1760806940325,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-469\",\n      \"timestamp\": 1760806797980,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Retry attempt 4 for failed request\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-105\",\n      \"timestamp\": 1760806606373,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-470\",\n      \"timestamp\": 1760806457742,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Connection pool stats: active=13/max=50\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-773\",\n      \"timestamp\": 1760806045748,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Personalized recommendations generated for user 57353\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-224\",\n      \"timestamp\": 1760805973750,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"HTTP request: PUT /uploads/2724u5m.jpg\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-2000\",\n      \"timestamp\": 1760805960361,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache miss for key: user:4605\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1869\",\n      \"timestamp\": 1760805936775,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-87\",\n      \"timestamp\": 1760805823165,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Personalized recommendations generated for user 58952\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1772\",\n      \"timestamp\": 1760805803095,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1529\",\n      \"timestamp\": 1760805582333,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Queue size approaching limit: 9216\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-829\",\n      \"timestamp\": 1760804924060,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"High memory usage: 75%\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1631\",\n      \"timestamp\": 1760804731825,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1563\",\n      \"timestamp\": 1760803782059,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1698\",\n      \"timestamp\": 1760803711063,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Queue size approaching limit: 8992\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-606\",\n      \"timestamp\": 1760803628472,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-70\",\n      \"timestamp\": 1760803215721,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-367\",\n      \"timestamp\": 1760802901423,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Lock released: resource-39\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1358\",\n      \"timestamp\": 1760802770388,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"File not found: /uploads/pitqqk.jpg\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-88\",\n      \"timestamp\": 1760802379162,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1143\",\n      \"timestamp\": 1760802341332,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-976\",\n      \"timestamp\": 1760801965671,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-365\",\n      \"timestamp\": 1760801744929,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-184\",\n      \"timestamp\": 1760801641294,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"High memory usage: 83%\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-853\",\n      \"timestamp\": 1760801443529,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Authentication failed for user28@example.com: invalid credentials\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-571\",\n      \"timestamp\": 1760800576663,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-875\",\n      \"timestamp\": 1760800270459,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1788\",\n      \"timestamp\": 1760799763167,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock released: resource-14\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1963\",\n      \"timestamp\": 1760799657814,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-102\",\n      \"timestamp\": 1760799250049,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Rate limit approaching for client 192.168.143.237\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-958\",\n      \"timestamp\": 1760798621481,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-589\",\n      \"timestamp\": 1760798544939,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"SSL certificate expires in 23 days\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-573\",\n      \"timestamp\": 1760798321112,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-744\",\n      \"timestamp\": 1760797912952,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1647\",\n      \"timestamp\": 1760797684084,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1931\",\n      \"timestamp\": 1760797199187,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-912\",\n      \"timestamp\": 1760796780806,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"HTTP request: POST /uploads/qzlk2e.jpg\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1183\",\n      \"timestamp\": 1760796772528,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-697\",\n      \"timestamp\": 1760796646046,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1848\",\n      \"timestamp\": 1760796641614,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Lock released: resource-82\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1190\",\n      \"timestamp\": 1760796589274,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1895\",\n      \"timestamp\": 1760796553635,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1948\",\n      \"timestamp\": 1760796519964,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-883\",\n      \"timestamp\": 1760796439138,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1433\",\n      \"timestamp\": 1760796275209,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Connection pool stats: active=35/max=50\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1616\",\n      \"timestamp\": 1760796125838,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1959\",\n      \"timestamp\": 1760795441002,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-663\",\n      \"timestamp\": 1760795297097,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1967\",\n      \"timestamp\": 1760795196657,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1894\",\n      \"timestamp\": 1760795019470,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Order ORD-383272 completed\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1760\",\n      \"timestamp\": 1760794672050,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1602\",\n      \"timestamp\": 1760794599521,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-832\",\n      \"timestamp\": 1760794403461,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1615\",\n      \"timestamp\": 1760794350610,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Personalized recommendations generated for user 23972\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1864\",\n      \"timestamp\": 1760794297282,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"File not found: /uploads/p3i0ye.jpg\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1005\",\n      \"timestamp\": 1760794219076,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Connection pool stats: active=14/max=50\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-409\",\n      \"timestamp\": 1760793549467,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"New user registered: user300@example.com\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-405\",\n      \"timestamp\": 1760793526451,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"HTTP response: 200\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1313\",\n      \"timestamp\": 1760793518515,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-758\",\n      \"timestamp\": 1760793308833,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1646\",\n      \"timestamp\": 1760793216607,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Stock updated for product SKU-38129\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1657\",\n      \"timestamp\": 1760793142136,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1072\",\n      \"timestamp\": 1760791603608,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"File uploaded: 7kmih.pdf\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1414\",\n      \"timestamp\": 1760791534869,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1565\",\n      \"timestamp\": 1760791099211,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"New user registered: user420@example.com\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1060\",\n      \"timestamp\": 1760790654234,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Stock updated for product SKU-50806\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1185\",\n      \"timestamp\": 1760790570392,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1391\",\n      \"timestamp\": 1760790437294,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Authentication failed for user521@example.com: invalid credentials\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1629\",\n      \"timestamp\": 1760790236885,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-847\",\n      \"timestamp\": 1760789938260,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1826\",\n      \"timestamp\": 1760789881150,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Authentication failed for user2@example.com: invalid credentials\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1368\",\n      \"timestamp\": 1760789116595,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1905\",\n      \"timestamp\": 1760788989283,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1678\",\n      \"timestamp\": 1760788527019,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"SSL certificate expires in 17 days\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1711\",\n      \"timestamp\": 1760788395902,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1492\",\n      \"timestamp\": 1760788295337,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-31\",\n      \"timestamp\": 1760788292513,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1815\",\n      \"timestamp\": 1760788244438,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Order ORD-373904 completed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1571\",\n      \"timestamp\": 1760786840774,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-199\",\n      \"timestamp\": 1760786745761,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1210\",\n      \"timestamp\": 1760786517916,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-384\",\n      \"timestamp\": 1760786206772,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"File uploaded: 8cl26v.pdf\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-594\",\n      \"timestamp\": 1760785912541,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1952\",\n      \"timestamp\": 1760784713504,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1836\",\n      \"timestamp\": 1760784003566,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1462\",\n      \"timestamp\": 1760783843109,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1265\",\n      \"timestamp\": 1760783681365,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-16\",\n      \"timestamp\": 1760783600049,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock released: resource-54\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-598\",\n      \"timestamp\": 1760783433355,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:staging\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-353\",\n      \"timestamp\": 1760783182464,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Rate limit approaching for client 192.168.174.64\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1390\",\n      \"timestamp\": 1760783000986,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1392\",\n      \"timestamp\": 1760782999072,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Order ORD-460204 completed\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1486\",\n      \"timestamp\": 1760782793947,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-748\",\n      \"timestamp\": 1760782757146,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-970\",\n      \"timestamp\": 1760782682350,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Cache hit for key: user:5272\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-217\",\n      \"timestamp\": 1760782295134,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1992\",\n      \"timestamp\": 1760782252082,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-959\",\n      \"timestamp\": 1760782099831,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-123\",\n      \"timestamp\": 1760782002602,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1915\",\n      \"timestamp\": 1760781981119,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-294\",\n      \"timestamp\": 1760781946773,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1502\",\n      \"timestamp\": 1760781914683,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1078\",\n      \"timestamp\": 1760781908628,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-500\",\n      \"timestamp\": 1760781262333,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-926\",\n      \"timestamp\": 1760781164225,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1791\",\n      \"timestamp\": 1760780760108,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-474\",\n      \"timestamp\": 1760780699968,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock acquired: resource-67\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1758\",\n      \"timestamp\": 1760779468618,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Stock updated for product SKU-10260\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-732\",\n      \"timestamp\": 1760778965740,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1422\",\n      \"timestamp\": 1760778820931,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Cache invalidated: user:4253\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1450\",\n      \"timestamp\": 1760778751468,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-940\",\n      \"timestamp\": 1760778676250,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-107\",\n      \"timestamp\": 1760778670096,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-335\",\n      \"timestamp\": 1760778244964,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1003\",\n      \"timestamp\": 1760777619186,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Stock updated for product SKU-32296\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1997\",\n      \"timestamp\": 1760777428349,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-581\",\n      \"timestamp\": 1760777231270,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-965\",\n      \"timestamp\": 1760776843131,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-206\",\n      \"timestamp\": 1760776603727,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\", \"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-962\",\n      \"timestamp\": 1760776360850,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-257\",\n      \"timestamp\": 1760776298878,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1863\",\n      \"timestamp\": 1760775567154,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1892\",\n      \"timestamp\": 1760775556708,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-71\",\n      \"timestamp\": 1760775303654,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1603\",\n      \"timestamp\": 1760775244000,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-672\",\n      \"timestamp\": 1760775052480,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-496\",\n      \"timestamp\": 1760774620006,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock released: resource-79\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-47\",\n      \"timestamp\": 1760773633356,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-619\",\n      \"timestamp\": 1760773547318,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1667\",\n      \"timestamp\": 1760773485824,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1379\",\n      \"timestamp\": 1760773059294,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-714\",\n      \"timestamp\": 1760772267049,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-172\",\n      \"timestamp\": 1760772044491,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Request processed successfully in 321ms\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1004\",\n      \"timestamp\": 1760771671465,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-646\",\n      \"timestamp\": 1760771606031,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"HTTP response: 400\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-877\",\n      \"timestamp\": 1760771576875,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache miss for key: user:60\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-822\",\n      \"timestamp\": 1760771391303,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-231\",\n      \"timestamp\": 1760771058337,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1135\",\n      \"timestamp\": 1760771025607,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-68\",\n      \"timestamp\": 1760770985319,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-276\",\n      \"timestamp\": 1760770933037,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-275\",\n      \"timestamp\": 1760770899478,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1459\",\n      \"timestamp\": 1760770878440,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Slow query detected: SELECT * FROM transactions...\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1775\",\n      \"timestamp\": 1760770412586,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1757\",\n      \"timestamp\": 1760770381197,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-934\",\n      \"timestamp\": 1760770074700,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1597\",\n      \"timestamp\": 1760770067617,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1373\",\n      \"timestamp\": 1760769870567,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-358\",\n      \"timestamp\": 1760769200274,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Stock updated for product SKU-44810\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1873\",\n      \"timestamp\": 1760768605150,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Personalized recommendations generated for user 40191\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1759\",\n      \"timestamp\": 1760768067336,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP request: GET /uploads/zseyb.jpg\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1610\",\n      \"timestamp\": 1760767686822,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Authentication failed for user596@example.com: invalid credentials\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1077\",\n      \"timestamp\": 1760767658038,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1682\",\n      \"timestamp\": 1760767604473,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-433\",\n      \"timestamp\": 1760766682292,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1594\",\n      \"timestamp\": 1760766541070,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1715\",\n      \"timestamp\": 1760766531773,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1821\",\n      \"timestamp\": 1760766301819,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-312\",\n      \"timestamp\": 1760766182271,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Rate limit approaching for client 192.168.222.88\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1108\",\n      \"timestamp\": 1760766034522,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-535\",\n      \"timestamp\": 1760765855300,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Database pool almost full: 97/100\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-442\",\n      \"timestamp\": 1760764484819,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1675\",\n      \"timestamp\": 1760764428928,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-144\",\n      \"timestamp\": 1760764139696,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-25\",\n      \"timestamp\": 1760764085499,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1273\",\n      \"timestamp\": 1760764061060,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1722\",\n      \"timestamp\": 1760763301834,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1533\",\n      \"timestamp\": 1760763223236,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache miss for key: user:4452\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1942\",\n      \"timestamp\": 1760762664606,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-706\",\n      \"timestamp\": 1760762088549,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Lock released: resource-34\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1568\",\n      \"timestamp\": 1760761375861,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-237\",\n      \"timestamp\": 1760761115461,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-513\",\n      \"timestamp\": 1760760645988,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1825\",\n      \"timestamp\": 1760760545310,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-86\",\n      \"timestamp\": 1760760504873,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-889\",\n      \"timestamp\": 1760760492189,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Personalized recommendations generated for user 65808\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1027\",\n      \"timestamp\": 1760760149199,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1307\",\n      \"timestamp\": 1760758823612,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1777\",\n      \"timestamp\": 1760758553688,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Lock released: resource-39\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-933\",\n      \"timestamp\": 1760757353900,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Cache miss for key: user:9126\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1352\",\n      \"timestamp\": 1760757313920,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1404\",\n      \"timestamp\": 1760756949739,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1557\",\n      \"timestamp\": 1760756803413,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Stock updated for product SKU-33221\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-733\",\n      \"timestamp\": 1760756675788,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Request processed successfully in 168ms\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-84\",\n      \"timestamp\": 1760755805826,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1703\",\n      \"timestamp\": 1760755768610,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-333\",\n      \"timestamp\": 1760755655362,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"File uploaded: et1jok.pdf\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-779\",\n      \"timestamp\": 1760755252479,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"New user registered: user135@example.com\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1928\",\n      \"timestamp\": 1760755081553,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-985\",\n      \"timestamp\": 1760754978639,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"HTTP request: PUT /uploads/kdf7dc.jpg\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-582\",\n      \"timestamp\": 1760754903530,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Scheduled job completed: report-generation\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1198\",\n      \"timestamp\": 1760754856607,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-91\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1981\",\n      \"timestamp\": 1760754683896,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1062\",\n      \"timestamp\": 1760754177655,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1362\",\n      \"timestamp\": 1760754022475,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1865\",\n      \"timestamp\": 1760753948655,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Rate limit approaching for client 192.168.126.239\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1891\",\n      \"timestamp\": 1760753813486,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"File uploaded: kzdyvn.pdf\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1117\",\n      \"timestamp\": 1760753401342,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Lock released: resource-90\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1679\",\n      \"timestamp\": 1760753332642,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1033\",\n      \"timestamp\": 1760753085050,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-22\",\n      \"timestamp\": 1760753058148,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"New user registered: user916@example.com\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1298\",\n      \"timestamp\": 1760752659164,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-436\",\n      \"timestamp\": 1760751565493,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1194\",\n      \"timestamp\": 1760750927962,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1582\",\n      \"timestamp\": 1760750881575,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Cache hit for key: user:6555\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-846\",\n      \"timestamp\": 1760750514222,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Order ORD-949496 completed\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1761\",\n      \"timestamp\": 1760750380236,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-501\",\n      \"timestamp\": 1760750299493,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1939\",\n      \"timestamp\": 1760750146333,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-494\",\n      \"timestamp\": 1760749714973,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1113\",\n      \"timestamp\": 1760749627945,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1913\",\n      \"timestamp\": 1760749529555,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1425\",\n      \"timestamp\": 1760749291797,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"HTTP request: PUT /uploads/nsnldi.jpg\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-656\",\n      \"timestamp\": 1760748890479,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Database pool almost full: 94/100\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1674\",\n      \"timestamp\": 1760748863520,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Order ORD-379493 completed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-967\",\n      \"timestamp\": 1760748521151,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Personalized recommendations generated for user 36113\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1340\",\n      \"timestamp\": 1760748222036,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Connection pool stats: active=14/max=50\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"region:us-east-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1949\",\n      \"timestamp\": 1760748190590,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Order ORD-275585 completed\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-780\",\n      \"timestamp\": 1760747941590,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1220\",\n      \"timestamp\": 1760747863707,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Retry attempt 2 for failed request\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1762\",\n      \"timestamp\": 1760747337869,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1050\",\n      \"timestamp\": 1760747315639,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-250\",\n      \"timestamp\": 1760746891312,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1677\",\n      \"timestamp\": 1760746710168,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Order ORD-769390 completed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-295\",\n      \"timestamp\": 1760746602929,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Lock acquired: resource-50\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-609\",\n      \"timestamp\": 1760745773163,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-392\",\n      \"timestamp\": 1760745637271,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1506\",\n      \"timestamp\": 1760745453858,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-247\",\n      \"timestamp\": 1760744790001,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Rate limit approaching for client 192.168.254.247\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-344\",\n      \"timestamp\": 1760744597560,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Connection pool stats: active=44/max=50\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-158\",\n      \"timestamp\": 1760744318982,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-800\",\n      \"timestamp\": 1760744107649,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-618\",\n      \"timestamp\": 1760744090290,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database pool almost full: 92/100\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1464\",\n      \"timestamp\": 1760744033632,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"SSL certificate expires in 20 days\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1818\",\n      \"timestamp\": 1760743960718,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache invalidated: user:2373\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-65\",\n      \"timestamp\": 1760743816823,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"HTTP request: GET /uploads/sbsups.jpg\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-910\",\n      \"timestamp\": 1760743387366,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1046\",\n      \"timestamp\": 1760743381336,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1926\",\n      \"timestamp\": 1760743321111,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Authentication failed for user479@example.com: invalid credentials\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-264\",\n      \"timestamp\": 1760743232007,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-3\",\n      \"timestamp\": 1760742942847,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1384\",\n      \"timestamp\": 1760742389478,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Cache miss for key: user:8019\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1746\",\n      \"timestamp\": 1760741875364,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-379\",\n      \"timestamp\": 1760741692914,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1731\",\n      \"timestamp\": 1760741201102,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Connection pool stats: active=13/max=50\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1207\",\n      \"timestamp\": 1760740918443,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"File uploaded: t22nv.pdf\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1561\",\n      \"timestamp\": 1760740734593,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1034\",\n      \"timestamp\": 1760739719000,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Connection pool stats: active=9/max=50\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1165\",\n      \"timestamp\": 1760739616249,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1901\",\n      \"timestamp\": 1760739588153,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-260\",\n      \"timestamp\": 1760739287058,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Lock acquired: resource-8\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-839\",\n      \"timestamp\": 1760739029958,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-60\",\n      \"timestamp\": 1760738913332,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"HTTP request: GET /uploads/s6jb2i.jpg\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1591\",\n      \"timestamp\": 1760738774736,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-412\",\n      \"timestamp\": 1760738737405,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database pool almost full: 92/100\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1501\",\n      \"timestamp\": 1760738211418,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-389\",\n      \"timestamp\": 1760737706196,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1174\",\n      \"timestamp\": 1760737249656,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-915\",\n      \"timestamp\": 1760736806834,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-887\",\n      \"timestamp\": 1760736252224,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Slow query detected: SELECT * FROM orders...\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-623\",\n      \"timestamp\": 1760735953914,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"New user registered: user472@example.com\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-799\",\n      \"timestamp\": 1760735647807,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1468\",\n      \"timestamp\": 1760735535466,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"High memory usage: 77%\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1011\",\n      \"timestamp\": 1760734755885,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Request processed successfully in 308ms\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-815\",\n      \"timestamp\": 1760734492383,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-34\",\n      \"timestamp\": 1760734425367,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1589\",\n      \"timestamp\": 1760734416223,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-50\",\n      \"timestamp\": 1760734016811,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1452\",\n      \"timestamp\": 1760733850662,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-557\",\n      \"timestamp\": 1760733786228,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1230\",\n      \"timestamp\": 1760733749940,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-708\",\n      \"timestamp\": 1760733670389,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"New user registered: user526@example.com\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"region:eu-west-1\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-738\",\n      \"timestamp\": 1760732467589,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1013\",\n      \"timestamp\": 1760732378161,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Retry attempt 5 for failed request\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1613\",\n      \"timestamp\": 1760731545885,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-514\",\n      \"timestamp\": 1760731339263,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1490\",\n      \"timestamp\": 1760731246426,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-91\",\n      \"timestamp\": 1760731144255,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache miss for key: user:7685\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1830\",\n      \"timestamp\": 1760730737278,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-419\",\n      \"timestamp\": 1760730683711,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-775\",\n      \"timestamp\": 1760730624048,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"New user registered: user503@example.com\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-236\",\n      \"timestamp\": 1760730272996,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock acquired: resource-74\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1393\",\n      \"timestamp\": 1760730221652,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-873\",\n      \"timestamp\": 1760730204591,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Scheduled job completed: cleanup\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-922\",\n      \"timestamp\": 1760729819225,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Personalized recommendations generated for user 48159\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1962\",\n      \"timestamp\": 1760729547984,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Stock updated for product SKU-41463\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1628\",\n      \"timestamp\": 1760729279609,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-902\",\n      \"timestamp\": 1760728989010,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache hit for key: user:3716\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"region:eu-west-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-348\",\n      \"timestamp\": 1760728733549,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-465\",\n      \"timestamp\": 1760728674625,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-556\",\n      \"timestamp\": 1760728060792,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Stock updated for product SKU-35035\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-593\",\n      \"timestamp\": 1760727905727,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1075\",\n      \"timestamp\": 1760727715960,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-682\",\n      \"timestamp\": 1760727686724,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache invalidated: user:7442\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1779\",\n      \"timestamp\": 1760727387178,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-627\",\n      \"timestamp\": 1760727167045,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1969\",\n      \"timestamp\": 1760726921071,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-191\",\n      \"timestamp\": 1760726509784,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock released: resource-11\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-103\",\n      \"timestamp\": 1760726422792,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Authentication failed for user814@example.com: invalid credentials\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-156\",\n      \"timestamp\": 1760726394489,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1245\",\n      \"timestamp\": 1760726380401,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1993\",\n      \"timestamp\": 1760725633379,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Connection pool stats: active=18/max=50\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1002\",\n      \"timestamp\": 1760725316090,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache invalidated: user:6041\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-336\",\n      \"timestamp\": 1760725313252,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1235\",\n      \"timestamp\": 1760725058317,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"SSL certificate expires in 30 days\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1487\",\n      \"timestamp\": 1760724669487,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Authentication failed for user788@example.com: invalid credentials\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-718\",\n      \"timestamp\": 1760724628866,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1259\",\n      \"timestamp\": 1760724162069,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Connection pool stats: active=15/max=50\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-667\",\n      \"timestamp\": 1760724060658,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-48\",\n      \"timestamp\": 1760723869661,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1985\",\n      \"timestamp\": 1760723771457,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1380\",\n      \"timestamp\": 1760723626029,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Request processed successfully in 329ms\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-562\",\n      \"timestamp\": 1760723529599,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-628\",\n      \"timestamp\": 1760723384946,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1038\",\n      \"timestamp\": 1760722609838,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1709\",\n      \"timestamp\": 1760722595748,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1718\",\n      \"timestamp\": 1760722334505,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-984\",\n      \"timestamp\": 1760722266421,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-751\",\n      \"timestamp\": 1760722152635,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-240\",\n      \"timestamp\": 1760721960888,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1124\",\n      \"timestamp\": 1760721761185,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1621\",\n      \"timestamp\": 1760721458995,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"HTTP request: GET /uploads/c7a357.jpg\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-393\",\n      \"timestamp\": 1760720906534,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1778\",\n      \"timestamp\": 1760720295379,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"High memory usage: 86%\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1575\",\n      \"timestamp\": 1760719277515,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-219\",\n      \"timestamp\": 1760719214853,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-872\",\n      \"timestamp\": 1760719147362,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache hit for key: user:4501\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1255\",\n      \"timestamp\": 1760718964732,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"File uploaded: s0vp28.pdf\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1874\",\n      \"timestamp\": 1760718716128,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1170\",\n      \"timestamp\": 1760718689033,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Rate limit approaching for client 192.168.54.201\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-821\",\n      \"timestamp\": 1760718678368,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-938\",\n      \"timestamp\": 1760718564842,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Lock released: resource-97\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-729\",\n      \"timestamp\": 1760717934110,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Authentication failed for user127@example.com: invalid credentials\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-30\",\n      \"timestamp\": 1760717564917,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Retry attempt 4 for failed request\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-485\",\n      \"timestamp\": 1760716871206,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-414\",\n      \"timestamp\": 1760716709188,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"New user registered: user531@example.com\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-896\",\n      \"timestamp\": 1760716200743,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1530\",\n      \"timestamp\": 1760716198836,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-14\",\n      \"timestamp\": 1760715886004,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1834\",\n      \"timestamp\": 1760715160470,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Lock released: resource-63\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1550\",\n      \"timestamp\": 1760714749309,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1988\",\n      \"timestamp\": 1760714575070,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Order ORD-106788 completed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1324\",\n      \"timestamp\": 1760714570131,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1023\",\n      \"timestamp\": 1760714356755,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"High memory usage: 79%\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1238\",\n      \"timestamp\": 1760713747142,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1554\",\n      \"timestamp\": 1760713636188,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-900\",\n      \"timestamp\": 1760713000399,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1522\",\n      \"timestamp\": 1760712966986,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Connection pool stats: active=42/max=50\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-432\",\n      \"timestamp\": 1760712759149,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Lock acquired: resource-56\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1954\",\n      \"timestamp\": 1760712510700,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1879\",\n      \"timestamp\": 1760711939363,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1689\",\n      \"timestamp\": 1760711770011,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Request processed successfully in 349ms\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-859\",\n      \"timestamp\": 1760710979914,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1432\",\n      \"timestamp\": 1760710842166,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Connection pool stats: active=25/max=50\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1670\",\n      \"timestamp\": 1760709244084,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-576\",\n      \"timestamp\": 1760709141486,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1436\",\n      \"timestamp\": 1760708942569,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"HTTP response: 500\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1051\",\n      \"timestamp\": 1760708556067,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1371\",\n      \"timestamp\": 1760707968038,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Rate limit approaching for client 192.168.75.220\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-506\",\n      \"timestamp\": 1760707615291,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1801\",\n      \"timestamp\": 1760707610063,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Request processed successfully in 310ms\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-692\",\n      \"timestamp\": 1760707510272,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-784\",\n      \"timestamp\": 1760707397591,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-670\",\n      \"timestamp\": 1760706697529,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1261\",\n      \"timestamp\": 1760706521799,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-455\",\n      \"timestamp\": 1760706167800,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Entering function: calculateTotal\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-865\",\n      \"timestamp\": 1760706061135,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1941\",\n      \"timestamp\": 1760705779528,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1024\",\n      \"timestamp\": 1760705297670,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1110\",\n      \"timestamp\": 1760705011089,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-270\",\n      \"timestamp\": 1760704268312,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-612\",\n      \"timestamp\": 1760704227235,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Lock released: resource-96\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-909\",\n      \"timestamp\": 1760703713846,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1749\",\n      \"timestamp\": 1760703677042,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-303\",\n      \"timestamp\": 1760703102493,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-77\",\n      \"timestamp\": 1760703064734,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1128\",\n      \"timestamp\": 1760702856361,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Connection pool stats: active=38/max=50\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1456\",\n      \"timestamp\": 1760702586138,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Connection pool stats: active=5/max=50\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1875\",\n      \"timestamp\": 1760702425077,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1294\",\n      \"timestamp\": 1760701960311,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1493\",\n      \"timestamp\": 1760700669069,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"File not found: /uploads/o77srp.jpg\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-919\",\n      \"timestamp\": 1760700585565,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Stock updated for product SKU-49713\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-278\",\n      \"timestamp\": 1760700184951,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1845\",\n      \"timestamp\": 1760699979056,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1415\",\n      \"timestamp\": 1760699928595,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1442\",\n      \"timestamp\": 1760699762257,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1599\",\n      \"timestamp\": 1760699668583,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"High memory usage: 79%\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1364\",\n      \"timestamp\": 1760699593044,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-106\",\n      \"timestamp\": 1760699276560,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Retry attempt 2 for failed request\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-203\",\n      \"timestamp\": 1760698897634,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-205\",\n      \"timestamp\": 1760698228312,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1297\",\n      \"timestamp\": 1760698143751,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"File uploaded: wjb8sm.pdf\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-814\",\n      \"timestamp\": 1760697859690,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1896\",\n      \"timestamp\": 1760696545095,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Cache hit for key: user:7532\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-210\",\n      \"timestamp\": 1760696489544,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-416\",\n      \"timestamp\": 1760695782671,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-673\",\n      \"timestamp\": 1760695647881,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP response: 200\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1019\",\n      \"timestamp\": 1760695524849,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-360\",\n      \"timestamp\": 1760694483750,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Cache invalidated: user:6033\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1427\",\n      \"timestamp\": 1760694380908,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1243\",\n      \"timestamp\": 1760694239241,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1523\",\n      \"timestamp\": 1760694133594,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1842\",\n      \"timestamp\": 1760693427459,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-923\",\n      \"timestamp\": 1760693400244,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1795\",\n      \"timestamp\": 1760693045686,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-669\",\n      \"timestamp\": 1760692785399,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Request processed successfully in 134ms\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1861\",\n      \"timestamp\": 1760692157032,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1844\",\n      \"timestamp\": 1760692111642,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1395\",\n      \"timestamp\": 1760692033382,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-617\",\n      \"timestamp\": 1760690558233,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Rate limit approaching for client 192.168.204.88\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-118\",\n      \"timestamp\": 1760690461031,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1577\",\n      \"timestamp\": 1760690329351,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Personalized recommendations generated for user 12775\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-772\",\n      \"timestamp\": 1760690328135,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Cache hit for key: user:3295\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1030\",\n      \"timestamp\": 1760690196344,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-495\",\n      \"timestamp\": 1760689734004,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1344\",\n      \"timestamp\": 1760689412370,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-435\",\n      \"timestamp\": 1760688979635,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Order ORD-175300 completed\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1747\",\n      \"timestamp\": 1760688726871,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1707\",\n      \"timestamp\": 1760688711367,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database pool almost full: 84/100\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-451\",\n      \"timestamp\": 1760688683933,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Cache invalidated: user:6892\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-952\",\n      \"timestamp\": 1760688645124,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Retry attempt 5 for failed request\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-520\",\n      \"timestamp\": 1760688588963,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-388\",\n      \"timestamp\": 1760688484410,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1870\",\n      \"timestamp\": 1760688088855,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-441\",\n      \"timestamp\": 1760687672888,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-369\",\n      \"timestamp\": 1760687372725,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1337\",\n      \"timestamp\": 1760687279410,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Lock released: resource-18\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1167\",\n      \"timestamp\": 1760686944307,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-555\",\n      \"timestamp\": 1760686795794,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-407\",\n      \"timestamp\": 1760686679560,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Connection pool stats: active=35/max=50\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1339\",\n      \"timestamp\": 1760686524505,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Connection pool stats: active=25/max=50\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1413\",\n      \"timestamp\": 1760686292193,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Request processed successfully in 136ms\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-316\",\n      \"timestamp\": 1760685264868,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1974\",\n      \"timestamp\": 1760685235853,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1536\",\n      \"timestamp\": 1760685184121,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-878\",\n      \"timestamp\": 1760684993087,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database pool almost full: 85/100\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1918\",\n      \"timestamp\": 1760684929332,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-819\",\n      \"timestamp\": 1760684888978,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1437\",\n      \"timestamp\": 1760684114669,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-126\",\n      \"timestamp\": 1760683739953,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Request processed successfully in 280ms\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1475\",\n      \"timestamp\": 1760683506630,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-215\",\n      \"timestamp\": 1760683440264,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-322\",\n      \"timestamp\": 1760682542467,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-239\",\n      \"timestamp\": 1760681973373,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"HTTP request: DELETE /uploads/nxxw3.jpg\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-766\",\n      \"timestamp\": 1760681717343,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1365\",\n      \"timestamp\": 1760681311540,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1545\",\n      \"timestamp\": 1760681130307,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-153\",\n      \"timestamp\": 1760680743056,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-767\",\n      \"timestamp\": 1760680681794,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-167\",\n      \"timestamp\": 1760680525437,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1074\",\n      \"timestamp\": 1760680375066,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database pool almost full: 89/100\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1951\",\n      \"timestamp\": 1760680319467,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-222\",\n      \"timestamp\": 1760679882746,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Database pool almost full: 81/100\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1634\",\n      \"timestamp\": 1760679569485,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1310\",\n      \"timestamp\": 1760679443847,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-874\",\n      \"timestamp\": 1760679151070,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"File not found: /uploads/ejm461.jpg\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1204\",\n      \"timestamp\": 1760678652312,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-49\",\n      \"timestamp\": 1760678452666,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-6\",\n      \"timestamp\": 1760678300023,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1333\",\n      \"timestamp\": 1760677936034,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1556\",\n      \"timestamp\": 1760677646977,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1925\",\n      \"timestamp\": 1760677442798,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1318\",\n      \"timestamp\": 1760677317028,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-614\",\n      \"timestamp\": 1760677229912,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-75\",\n      \"timestamp\": 1760677077900,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1824\",\n      \"timestamp\": 1760677064213,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1133\",\n      \"timestamp\": 1760676833119,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/products\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1299\",\n      \"timestamp\": 1760676508398,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Personalized recommendations generated for user 74277\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-762\",\n      \"timestamp\": 1760675914361,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1438\",\n      \"timestamp\": 1760675172875,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Lock released: resource-75\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1500\",\n      \"timestamp\": 1760675126232,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1739\",\n      \"timestamp\": 1760675111141,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1129\",\n      \"timestamp\": 1760675035560,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1586\",\n      \"timestamp\": 1760674546447,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-634\",\n      \"timestamp\": 1760674167621,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"SSL certificate expires in 17 days\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1025\",\n      \"timestamp\": 1760673685874,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-566\",\n      \"timestamp\": 1760673419794,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1569\",\n      \"timestamp\": 1760673050229,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1451\",\n      \"timestamp\": 1760672418060,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1467\",\n      \"timestamp\": 1760671944320,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1443\",\n      \"timestamp\": 1760671752428,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1104\",\n      \"timestamp\": 1760671635109,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1549\",\n      \"timestamp\": 1760671324540,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Connection pool stats: active=0/max=50\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1841\",\n      \"timestamp\": 1760671230329,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1498\",\n      \"timestamp\": 1760671184916,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-525\",\n      \"timestamp\": 1760671027331,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1059\",\n      \"timestamp\": 1760670885193,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Request processed successfully in 86ms\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-120\",\n      \"timestamp\": 1760670784960,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1252\",\n      \"timestamp\": 1760670775532,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-903\",\n      \"timestamp\": 1760670630422,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"New user registered: user103@example.com\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-640\",\n      \"timestamp\": 1760670565308,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1231\",\n      \"timestamp\": 1760670279730,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Lock acquired: resource-39\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-655\",\n      \"timestamp\": 1760670190282,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1014\",\n      \"timestamp\": 1760670123464,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1066\",\n      \"timestamp\": 1760670069121,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-166\",\n      \"timestamp\": 1760669815595,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-528\",\n      \"timestamp\": 1760669400156,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-796\",\n      \"timestamp\": 1760669233870,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1091\",\n      \"timestamp\": 1760669216409,\n      \"level\": \"ERROR\",\n      \"service\": \"notification-service\",\n      \"message\": \"Authentication failed for user470@example.com: invalid credentials\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1343\",\n      \"timestamp\": 1760668546537,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1285\",\n      \"timestamp\": 1760668537857,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1270\",\n      \"timestamp\": 1760668423655,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-424\",\n      \"timestamp\": 1760667901437,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Cache invalidated: user:1738\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1076\",\n      \"timestamp\": 1760667780347,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1312\",\n      \"timestamp\": 1760667607959,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1998\",\n      \"timestamp\": 1760667381291,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-879\",\n      \"timestamp\": 1760667310455,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1519\",\n      \"timestamp\": 1760667032506,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1570\",\n      \"timestamp\": 1760666978809,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-916\",\n      \"timestamp\": 1760666965304,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Service started on port 3000\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1057\",\n      \"timestamp\": 1760666882295,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1448\",\n      \"timestamp\": 1760666457197,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"File not found: /uploads/bgfer.jpg\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-127\",\n      \"timestamp\": 1760666311404,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-681\",\n      \"timestamp\": 1760666287179,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1236\",\n      \"timestamp\": 1760666220203,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Rate limit approaching for client 192.168.223.171\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1975\",\n      \"timestamp\": 1760665760183,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-825\",\n      \"timestamp\": 1760665722281,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Cache miss for key: user:5594\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1127\",\n      \"timestamp\": 1760665333766,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Variable state: status=completed\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-651\",\n      \"timestamp\": 1760665010346,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Order ORD-189995 completed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-180\",\n      \"timestamp\": 1760664963322,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-15\",\n      \"timestamp\": 1760664867335,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-208\",\n      \"timestamp\": 1760664797504,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1283\",\n      \"timestamp\": 1760664768842,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-307\",\n      \"timestamp\": 1760664412774,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Order ORD-971565 completed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-601\",\n      \"timestamp\": 1760664107587,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Order ORD-977482 completed\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1416\",\n      \"timestamp\": 1760663290042,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1281\",\n      \"timestamp\": 1760663179566,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-168\",\n      \"timestamp\": 1760663111183,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"SSL certificate expires in 13 days\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1471\",\n      \"timestamp\": 1760662196918,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-492\",\n      \"timestamp\": 1760661404751,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Personalized recommendations generated for user 90613\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1564\",\n      \"timestamp\": 1760660973050,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-781\",\n      \"timestamp\": 1760660663876,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:main\", \"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-425\",\n      \"timestamp\": 1760660406850,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"File not found: /uploads/6xihai.jpg\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-261\",\n      \"timestamp\": 1760660298880,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-466\",\n      \"timestamp\": 1760660275839,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"HTTP response: 500\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1008\",\n      \"timestamp\": 1760658533477,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-726\",\n      \"timestamp\": 1760658324094,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database pool almost full: 93/100\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-140\",\n      \"timestamp\": 1760658203443,\n      \"level\": \"DEBUG\",\n      \"service\": \"report-service\",\n      \"message\": \"Cache hit for key: user:4525\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-59\",\n      \"timestamp\": 1760657680475,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-763\",\n      \"timestamp\": 1760656543842,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-943\",\n      \"timestamp\": 1760655628908,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Cache miss for key: user:4310\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-895\",\n      \"timestamp\": 1760655569953,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database pool almost full: 99/100\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1253\",\n      \"timestamp\": 1760655436349,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"SSL certificate expires in 4 days\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1809\",\n      \"timestamp\": 1760655196642,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-306\",\n      \"timestamp\": 1760655095839,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1784\",\n      \"timestamp\": 1760654955350,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache invalidated: user:5174\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-417\",\n      \"timestamp\": 1760654869023,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Order ORD-298817 completed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-317\",\n      \"timestamp\": 1760654856322,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-823\",\n      \"timestamp\": 1760654686878,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1342\",\n      \"timestamp\": 1760654193831,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-457\",\n      \"timestamp\": 1760653398772,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Authentication failed for user328@example.com: invalid credentials\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1411\",\n      \"timestamp\": 1760652564646,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Request processed successfully in 164ms\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-443\",\n      \"timestamp\": 1760652234678,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-185\",\n      \"timestamp\": 1760652158981,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-693\",\n      \"timestamp\": 1760652106194,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-645\",\n      \"timestamp\": 1760651074310,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-542\",\n      \"timestamp\": 1760651039510,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Personalized recommendations generated for user 30257\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1938\",\n      \"timestamp\": 1760650800563,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-769\",\n      \"timestamp\": 1760650341585,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:backup\", \"region:eu-west-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-109\",\n      \"timestamp\": 1760650083265,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1551\",\n      \"timestamp\": 1760649790087,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-801\",\n      \"timestamp\": 1760649391228,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Connection pool stats: active=45/max=50\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1859\",\n      \"timestamp\": 1760649088277,\n      \"level\": \"INFO\",\n      \"service\": \"email-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-649\",\n      \"timestamp\": 1760647599093,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1651\",\n      \"timestamp\": 1760647549783,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-668\",\n      \"timestamp\": 1760647048117,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache miss for key: user:327\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-953\",\n      \"timestamp\": 1760646397688,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1871\",\n      \"timestamp\": 1760646010670,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Request processed successfully in 128ms\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1704\",\n      \"timestamp\": 1760646010114,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Connection pool stats: active=24/max=50\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1911\",\n      \"timestamp\": 1760645998366,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1804\",\n      \"timestamp\": 1760645883643,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"version:3.0.1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1420\",\n      \"timestamp\": 1760645786745,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1660\",\n      \"timestamp\": 1760645685303,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP response: 201\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-833\",\n      \"timestamp\": 1760645043774,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1106\",\n      \"timestamp\": 1760644767322,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-711\",\n      \"timestamp\": 1760644330406,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Request processed successfully in 289ms\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:staging\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-320\",\n      \"timestamp\": 1760643564557,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-269\",\n      \"timestamp\": 1760642888513,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache miss for key: user:7922\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-584\",\n      \"timestamp\": 1760642806639,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"High memory usage: 89%\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1141\",\n      \"timestamp\": 1760642758195,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1658\",\n      \"timestamp\": 1760642493278,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1357\",\n      \"timestamp\": 1760642362190,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Stock updated for product SKU-29361\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1168\",\n      \"timestamp\": 1760642149724,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1699\",\n      \"timestamp\": 1760641639648,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-182\",\n      \"timestamp\": 1760641399148,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Stock updated for product SKU-18907\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-248\",\n      \"timestamp\": 1760641117555,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-113\",\n      \"timestamp\": 1760640829135,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Stock updated for product SKU-36425\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-331\",\n      \"timestamp\": 1760640735911,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1877\",\n      \"timestamp\": 1760640241572,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-458\",\n      \"timestamp\": 1760639759462,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1282\",\n      \"timestamp\": 1760639203073,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1202\",\n      \"timestamp\": 1760638853203,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Slow query detected: SELECT * FROM orders...\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-82\",\n      \"timestamp\": 1760638254957,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Entering function: calculateTotal\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1579\",\n      \"timestamp\": 1760638075906,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-304\",\n      \"timestamp\": 1760638045780,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Lock acquired: resource-66\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-74\",\n      \"timestamp\": 1760637355024,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Entering function: validateUser\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1319\",\n      \"timestamp\": 1760637078098,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-854\",\n      \"timestamp\": 1760636320269,\n      \"level\": \"INFO\",\n      \"service\": \"auth-service\",\n      \"message\": \"Stock updated for product SKU-94688\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-836\",\n      \"timestamp\": 1760635437430,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1286\",\n      \"timestamp\": 1760634426329,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-395\",\n      \"timestamp\": 1760633743671,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:main\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1843\",\n      \"timestamp\": 1760633401889,\n      \"level\": \"WARN\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1543\",\n      \"timestamp\": 1760633238663,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Authentication failed for user231@example.com: invalid credentials\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-610\",\n      \"timestamp\": 1760633184907,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1288\",\n      \"timestamp\": 1760632892936,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-423\",\n      \"timestamp\": 1760632597669,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"Stock updated for product SKU-86280\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1115\",\n      \"timestamp\": 1760631873262,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-569\",\n      \"timestamp\": 1760631549404,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"File uploaded: 9gne84.pdf\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-824\",\n      \"timestamp\": 1760631182751,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Authentication failed for user888@example.com: invalid credentials\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-954\",\n      \"timestamp\": 1760631025801,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-715\",\n      \"timestamp\": 1760631006871,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache miss for key: user:5447\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-226\",\n      \"timestamp\": 1760630874735,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Stock updated for product SKU-32176\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1764\",\n      \"timestamp\": 1760630628679,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Request processed successfully in 486ms\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1325\",\n      \"timestamp\": 1760630401270,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1902\",\n      \"timestamp\": 1760630184165,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"SSL certificate expires in 29 days\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-918\",\n      \"timestamp\": 1760630002532,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Lock released: resource-96\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1986\",\n      \"timestamp\": 1760629864311,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Lock acquired: resource-57\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-749\",\n      \"timestamp\": 1760629849446,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1953\",\n      \"timestamp\": 1760629625425,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Request processed successfully in 302ms\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1043\",\n      \"timestamp\": 1760629593751,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Rate limit approaching for client 192.168.92.53\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\", \"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-202\",\n      \"timestamp\": 1760629572252,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1308\",\n      \"timestamp\": 1760629507542,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1347\",\n      \"timestamp\": 1760629360954,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-745\",\n      \"timestamp\": 1760628962634,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1132\",\n      \"timestamp\": 1760628740400,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache miss for key: user:4614\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1798\",\n      \"timestamp\": 1760628157237,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1193\",\n      \"timestamp\": 1760627651758,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"New user registered: user161@example.com\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:1.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-51\",\n      \"timestamp\": 1760627237531,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP response: 404\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1553\",\n      \"timestamp\": 1760627006793,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache miss for key: user:2880\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-345\",\n      \"timestamp\": 1760626883935,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"SSL certificate expires in 19 days\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1356\",\n      \"timestamp\": 1760626409292,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1600\",\n      \"timestamp\": 1760625158578,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-662\",\n      \"timestamp\": 1760624846354,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Personalized recommendations generated for user 27511\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1513\",\n      \"timestamp\": 1760624549166,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1040\",\n      \"timestamp\": 1760624313689,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-227\",\n      \"timestamp\": 1760624181621,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Queue size approaching limit: 9656\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-93\",\n      \"timestamp\": 1760623438514,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-32\",\n      \"timestamp\": 1760623358345,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-792\",\n      \"timestamp\": 1760623154277,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache invalidated: user:7872\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"environment:production\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-844\",\n      \"timestamp\": 1760623132121,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-654\",\n      \"timestamp\": 1760623116138,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-787\",\n      \"timestamp\": 1760622989869,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Slow query detected: SELECT * FROM products...\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1833\",\n      \"timestamp\": 1760622968063,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"SSL certificate expires in 21 days\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"version:2.1.5\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-101\",\n      \"timestamp\": 1760622900392,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-376\",\n      \"timestamp\": 1760622798513,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"File uploaded: rl0r3n.pdf\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-396\",\n      \"timestamp\": 1760622178178,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"HTTP request: POST /uploads/w1dvda.jpg\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-793\",\n      \"timestamp\": 1760621897640,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1264\",\n      \"timestamp\": 1760621430339,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"New user registered: user979@example.com\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-547\",\n      \"timestamp\": 1760621338236,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1608\",\n      \"timestamp\": 1760621188758,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Service started on port 8080\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-636\",\n      \"timestamp\": 1760620076911,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"High memory usage: 91%\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-327\",\n      \"timestamp\": 1760619950709,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock released: resource-0\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-830\",\n      \"timestamp\": 1760619945040,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Lock acquired: resource-81\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-664\",\n      \"timestamp\": 1760619808618,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Connection pool stats: active=24/max=50\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-337\",\n      \"timestamp\": 1760619562058,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-683\",\n      \"timestamp\": 1760619521101,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1727\",\n      \"timestamp\": 1760619195255,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"File uploaded: ioo7yr.pdf\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-981\",\n      \"timestamp\": 1760619052279,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"File uploaded: f1fm7.pdf\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1726\",\n      \"timestamp\": 1760618958086,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1639\",\n      \"timestamp\": 1760618638823,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache invalidated: user:8749\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-364\",\n      \"timestamp\": 1760618493056,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-605\",\n      \"timestamp\": 1760618444325,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database pool almost full: 87/100\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1042\",\n      \"timestamp\": 1760618389919,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1770\",\n      \"timestamp\": 1760618299434,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-299\",\n      \"timestamp\": 1760618061066,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-54\",\n      \"timestamp\": 1760617754027,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-622\",\n      \"timestamp\": 1760616848247,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-517\",\n      \"timestamp\": 1760616764585,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Personalized recommendations generated for user 22545\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-477\",\n      \"timestamp\": 1760616602587,\n      \"level\": \"ERROR\",\n      \"service\": \"logging-service\",\n      \"message\": \"Authentication failed for user398@example.com: invalid credentials\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1186\",\n      \"timestamp\": 1760615565120,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-132\",\n      \"timestamp\": 1760614982534,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-942\",\n      \"timestamp\": 1760614820450,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:main\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-527\",\n      \"timestamp\": 1760614443057,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"File not found: /uploads/8otcd.jpg\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1080\",\n      \"timestamp\": 1760613989032,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1184\",\n      \"timestamp\": 1760613686741,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-463\",\n      \"timestamp\": 1760613558482,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache hit for key: user:2473\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1515\",\n      \"timestamp\": 1760613113576,\n      \"level\": \"DEBUG\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache invalidated: user:8590\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-969\",\n      \"timestamp\": 1760612973163,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-890\",\n      \"timestamp\": 1760612948155,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-511\",\n      \"timestamp\": 1760612836862,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Request processed successfully in 484ms\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-849\",\n      \"timestamp\": 1760612189956,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"High memory usage: 89%\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"version:3.0.1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-44\",\n      \"timestamp\": 1760611868648,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1880\",\n      \"timestamp\": 1760611515301,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-776\",\n      \"timestamp\": 1760611387321,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1950\",\n      \"timestamp\": 1760611266939,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"File not found: /uploads/5f34xc.jpg\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1977\",\n      \"timestamp\": 1760611258353,\n      \"level\": \"ERROR\",\n      \"service\": \"report-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-730\",\n      \"timestamp\": 1760611043144,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Event consumed: user.created\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-597\",\n      \"timestamp\": 1760610783598,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1669\",\n      \"timestamp\": 1760610756441,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1652\",\n      \"timestamp\": 1760609945170,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-856\",\n      \"timestamp\": 1760609215129,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Personalized recommendations generated for user 40356\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1387\",\n      \"timestamp\": 1760609165501,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1101\",\n      \"timestamp\": 1760608903458,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1644\",\n      \"timestamp\": 1760608460724,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-382\",\n      \"timestamp\": 1760608198213,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Personalized recommendations generated for user 15806\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1856\",\n      \"timestamp\": 1760607379563,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1445\",\n      \"timestamp\": 1760607287479,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\", \"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-951\",\n      \"timestamp\": 1760605938241,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Personalized recommendations generated for user 28711\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1592\",\n      \"timestamp\": 1760605531352,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1388\",\n      \"timestamp\": 1760605378666,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1316\",\n      \"timestamp\": 1760605027120,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-281\",\n      \"timestamp\": 1760605014019,\n      \"level\": \"INFO\",\n      \"service\": \"trace-service\",\n      \"message\": \"File uploaded: q75keo.pdf\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1189\",\n      \"timestamp\": 1760604922542,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1315\",\n      \"timestamp\": 1760604922139,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Rate limit approaching for client 192.168.39.129\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-509\",\n      \"timestamp\": 1760604531173,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-279\",\n      \"timestamp\": 1760603859657,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/users\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1179\",\n      \"timestamp\": 1760603429167,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Retry attempt 2 for failed request\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-657\",\n      \"timestamp\": 1760603281569,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"High memory usage: 88%\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1858\",\n      \"timestamp\": 1760602832111,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Authentication failed for user653@example.com: invalid credentials\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-808\",\n      \"timestamp\": 1760602814699,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Null pointer exception in UserModule\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1123\",\n      \"timestamp\": 1760601823884,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-583\",\n      \"timestamp\": 1760601457969,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Lock released: resource-6\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:eu-west-1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-660\",\n      \"timestamp\": 1760600385708,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\", \"cluster:main\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-677\",\n      \"timestamp\": 1760600317048,\n      \"level\": \"DEBUG\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-728\",\n      \"timestamp\": 1760600079511,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Personalized recommendations generated for user 37889\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-east-1\", \"region:eu-west-1\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-811\",\n      \"timestamp\": 1760599950219,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1054\",\n      \"timestamp\": 1760599769979,\n      \"level\": \"WARN\",\n      \"service\": \"auth-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-700\",\n      \"timestamp\": 1760599714680,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Stock updated for product SKU-56733\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:eu-west-1\", \"environment:production\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1663\",\n      \"timestamp\": 1760599646543,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1984\",\n      \"timestamp\": 1760599310297,\n      \"level\": \"WARN\",\n      \"service\": \"user-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1637\",\n      \"timestamp\": 1760599198433,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1430\",\n      \"timestamp\": 1760598867290,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1876\",\n      \"timestamp\": 1760598862596,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Connection pool stats: active=33/max=50\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1385\",\n      \"timestamp\": 1760598555740,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1838\",\n      \"timestamp\": 1760598467546,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Rate limit approaching for client 192.168.59.225\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"environment:production\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-539\",\n      \"timestamp\": 1760598413281,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Service started on port 5000\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1209\",\n      \"timestamp\": 1760597837063,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"Database connection timeout\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-411\",\n      \"timestamp\": 1760597379591,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1783\",\n      \"timestamp\": 1760597211924,\n      \"level\": \"INFO\",\n      \"service\": \"cache-service\",\n      \"message\": \"Service started on port 8000\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-58\",\n      \"timestamp\": 1760597169159,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"Event consumed: payment.processed\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1263\",\n      \"timestamp\": 1760596840267,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Lock released: resource-70\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-426\",\n      \"timestamp\": 1760596582762,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1058\",\n      \"timestamp\": 1760596540129,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Slow query detected: SELECT * FROM products...\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1226\",\n      \"timestamp\": 1760596409967,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Database query executed: SELECT * FROM orders\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-447\",\n      \"timestamp\": 1760596223915,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Variable state: status=active\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.1.5\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-842\",\n      \"timestamp\": 1760595935579,\n      \"level\": \"INFO\",\n      \"service\": \"payment-service\",\n      \"message\": \"Order ORD-445247 completed\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1012\",\n      \"timestamp\": 1760595628632,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1350\",\n      \"timestamp\": 1760595478685,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-386\",\n      \"timestamp\": 1760595165949,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-876\",\n      \"timestamp\": 1760593098730,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-163\",\n      \"timestamp\": 1760593087728,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"File uploaded: 3fwkrk.pdf\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-484\",\n      \"timestamp\": 1760592295331,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1624\",\n      \"timestamp\": 1760591655972,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1162\",\n      \"timestamp\": 1760591526160,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"File uploaded: idy12.pdf\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1206\",\n      \"timestamp\": 1760591294569,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-995\",\n      \"timestamp\": 1760591177468,\n      \"level\": \"DEBUG\",\n      \"service\": \"db-service\",\n      \"message\": \"Event published: payment.processed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.0.0\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1508\",\n      \"timestamp\": 1760591055584,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-112\",\n      \"timestamp\": 1760590867382,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:1.0.0\", \"version:3.0.1\", \"version:2.1.5\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-653\",\n      \"timestamp\": 1760590674433,\n      \"level\": \"ERROR\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1178\",\n      \"timestamp\": 1760590142004,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Entering function: processOrder\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-771\",\n      \"timestamp\": 1760590106902,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"High memory usage: 92%\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1909\",\n      \"timestamp\": 1760589957600,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"cluster:main\", \"version:2.1.5\", \"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1944\",\n      \"timestamp\": 1760589865934,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-886\",\n      \"timestamp\": 1760589558812,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-807\",\n      \"timestamp\": 1760588935072,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"File uploaded: 4td0yg.pdf\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1839\",\n      \"timestamp\": 1760588862703,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1914\",\n      \"timestamp\": 1760588568214,\n      \"level\": \"INFO\",\n      \"service\": \"logging-service\",\n      \"message\": \"New user registered: user511@example.com\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-69\",\n      \"timestamp\": 1760588566510,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1625\",\n      \"timestamp\": 1760588201841,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-920\",\n      \"timestamp\": 1760587303261,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1147\",\n      \"timestamp\": 1760587093705,\n      \"level\": \"ERROR\",\n      \"service\": \"storage-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1883\",\n      \"timestamp\": 1760586915016,\n      \"level\": \"WARN\",\n      \"service\": \"sms-service\",\n      \"message\": \"Rate limit approaching for client 192.168.28.149\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"version:2.1.5\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1566\",\n      \"timestamp\": 1760586880807,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Span recorded: login-flow\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-73\",\n      \"timestamp\": 1760586662020,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Retry attempt 3 for failed request\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-685\",\n      \"timestamp\": 1760586413271,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Request processed successfully in 50ms\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"cluster:main\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1736\",\n      \"timestamp\": 1760586364473,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Cache hit for key: user:4801\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"version:2.0.0\", \"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-888\",\n      \"timestamp\": 1760585336348,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-12\",\n      \"timestamp\": 1760584933840,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-385\",\n      \"timestamp\": 1760583527894,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"New user registered: user525@example.com\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"region:eu-west-1\", \"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-253\",\n      \"timestamp\": 1760582581014,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"HTTP request: GET /uploads/w846j.jpg\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1725\",\n      \"timestamp\": 1760582574336,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1148\",\n      \"timestamp\": 1760582109403,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Search index rebuilt successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-884\",\n      \"timestamp\": 1760581980318,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Retry attempt 5 for failed request\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:1.0.0\", \"region:us-east-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1187\",\n      \"timestamp\": 1760581329596,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Database pool almost full: 92/100\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1792\",\n      \"timestamp\": 1760580653860,\n      \"level\": \"ERROR\",\n      \"service\": \"sms-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1372\",\n      \"timestamp\": 1760579663606,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\", \"region:us-west-2\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1099\",\n      \"timestamp\": 1760579545547,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database pool almost full: 83/100\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.0.0\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1754\",\n      \"timestamp\": 1760579362033,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Cache invalidated: user:3242\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1081\",\n      \"timestamp\": 1760579314885,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1716\",\n      \"timestamp\": 1760579201350,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1623\",\n      \"timestamp\": 1760578758749,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1512\",\n      \"timestamp\": 1760578531749,\n      \"level\": \"DEBUG\",\n      \"service\": \"auth-service\",\n      \"message\": \"Database query executed: SELECT * FROM users\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-38\",\n      \"timestamp\": 1760577727275,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Lock acquired: resource-84\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1740\",\n      \"timestamp\": 1760577701973,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Personalized recommendations generated for user 10599\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-932\",\n      \"timestamp\": 1760577494723,\n      \"level\": \"INFO\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1188\",\n      \"timestamp\": 1760576834202,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Lock released: resource-49\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1706\",\n      \"timestamp\": 1760576525866,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1813\",\n      \"timestamp\": 1760576443188,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Cache invalidated: user:8234\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:production\", \"cluster:main\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1964\",\n      \"timestamp\": 1760575914399,\n      \"level\": \"DEBUG\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"Event consumed: order.placed\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-957\",\n      \"timestamp\": 1760575650794,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-342\",\n      \"timestamp\": 1760575611808,\n      \"level\": \"ERROR\",\n      \"service\": \"shipping-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:3.0.1\", \"region:eu-west-1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-95\",\n      \"timestamp\": 1760575084713,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Rate limit approaching for client 192.168.116.32\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-232\",\n      \"timestamp\": 1760575078866,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Cache miss for key: user:9628\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1098\",\n      \"timestamp\": 1760574202974,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-752\",\n      \"timestamp\": 1760573837202,\n      \"level\": \"ERROR\",\n      \"service\": \"search-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1514\",\n      \"timestamp\": 1760573514703,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Request processed successfully in 478ms\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-759\",\n      \"timestamp\": 1760573078390,\n      \"level\": \"DEBUG\",\n      \"service\": \"logging-service\",\n      \"message\": \"HTTP request: GET /uploads/8d2u6h.jpg\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-944\",\n      \"timestamp\": 1760572737285,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Span recorded: checkout-flow\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-650\",\n      \"timestamp\": 1760572643821,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Variable state: status=pending\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1481\",\n      \"timestamp\": 1760572264353,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Cache hit for key: user:7984\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1866\",\n      \"timestamp\": 1760571868841,\n      \"level\": \"INFO\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-east-1\", \"region:eu-west-1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-26\",\n      \"timestamp\": 1760571785884,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-web-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1822\",\n      \"timestamp\": 1760571629467,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-620\",\n      \"timestamp\": 1760570585287,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:staging\", \"version:2.1.5\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-301\",\n      \"timestamp\": 1760570478201,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Database pool almost full: 88/100\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1850\",\n      \"timestamp\": 1760570453507,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-638\",\n      \"timestamp\": 1760570270683,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\", \"environment:staging\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1348\",\n      \"timestamp\": 1760569801372,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Exiting function: validateUser\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"version:2.1.5\", \"cluster:backup\", \"region:us-east-1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1092\",\n      \"timestamp\": 1760569696523,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Deprecated API endpoint called: /api/v1/orders\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1868\",\n      \"timestamp\": 1760569344559,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"S3 bucket access denied\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-357\",\n      \"timestamp\": 1760568580275,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1309\",\n      \"timestamp\": 1760567730740,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Metrics flushed to backend\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1279\",\n      \"timestamp\": 1760566751220,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-616\",\n      \"timestamp\": 1760566690987,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Cache hit for key: user:8179\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:staging\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-978\",\n      \"timestamp\": 1760566602703,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Request processed successfully in 412ms\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-440\",\n      \"timestamp\": 1760566436876,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:staging\", \"region:us-east-1\", \"cluster:backup\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1338\",\n      \"timestamp\": 1760566091119,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:backup\", \"cluster:main\", \"region:eu-west-1\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1330\",\n      \"timestamp\": 1760565689264,\n      \"level\": \"DEBUG\",\n      \"service\": \"trace-service\",\n      \"message\": \"Lock acquired: resource-37\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:eu-west-1\", \"version:2.0.0\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-289\",\n      \"timestamp\": 1760565684204,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-885\",\n      \"timestamp\": 1760565539847,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-356\",\n      \"timestamp\": 1760565455013,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-505\",\n      \"timestamp\": 1760565321134,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Out of memory error\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1399\",\n      \"timestamp\": 1760565073876,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"SSL certificate expires in 9 days\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1219\",\n      \"timestamp\": 1760565055905,\n      \"level\": \"WARN\",\n      \"service\": \"inventory-service\",\n      \"message\": \"SSL certificate expires in 29 days\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"version:2.0.0\", \"environment:staging\", \"cluster:backup\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1618\",\n      \"timestamp\": 1760564919198,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Personalized recommendations generated for user 39785\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1643\",\n      \"timestamp\": 1760564482624,\n      \"level\": \"ERROR\",\n      \"service\": \"trace-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-897\",\n      \"timestamp\": 1760564381729,\n      \"level\": \"ERROR\",\n      \"service\": \"db-service\",\n      \"message\": \"Authentication failed for user462@example.com: invalid credentials\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-183\",\n      \"timestamp\": 1760563915579,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Queue size approaching limit: 9705\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1009\",\n      \"timestamp\": 1760563642558,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Connection pool stats: active=31/max=50\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"cluster:main\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-387\",\n      \"timestamp\": 1760563300354,\n      \"level\": \"DEBUG\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Lock released: resource-93\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1017\",\n      \"timestamp\": 1760562768354,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Null pointer exception in PaymentModule\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"region:us-west-2\", \"cluster:main\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-1233\",\n      \"timestamp\": 1760562738214,\n      \"level\": \"INFO\",\n      \"service\": \"report-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-cache-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-840\",\n      \"timestamp\": 1760562332007,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Span recorded: search-flow\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-453\",\n      \"timestamp\": 1760562201426,\n      \"level\": \"WARN\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"SSL certificate expires in 3 days\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1166\",\n      \"timestamp\": 1760561857634,\n      \"level\": \"ERROR\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1478\",\n      \"timestamp\": 1760561744482,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1328\",\n      \"timestamp\": 1760561297280,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Null pointer exception in OrderModule\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\", \"cluster:main\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1015\",\n      \"timestamp\": 1760561209048,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Backup completed successfully\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"region:us-east-1\", \"version:3.0.1\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1837\",\n      \"timestamp\": 1760560715369,\n      \"level\": \"DEBUG\",\n      \"service\": \"search-service\",\n      \"message\": \"Lock released: resource-14\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"cluster:main\", \"environment:production\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-338\",\n      \"timestamp\": 1760560471394,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Session expired, refreshing token\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1752\",\n      \"timestamp\": 1760560441394,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"HTTP request: DELETE /uploads/642pj.jpg\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-613\",\n      \"timestamp\": 1760560345471,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Invalid JSON payload received\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1980\",\n      \"timestamp\": 1760559536497,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-321\",\n      \"timestamp\": 1760559439097,\n      \"level\": \"DEBUG\",\n      \"service\": \"payment-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"region:us-east-1\", \"version:2.0.0\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-309\",\n      \"timestamp\": 1760559203108,\n      \"level\": \"INFO\",\n      \"service\": \"search-service\",\n      \"message\": \"New user registered: user424@example.com\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1224\",\n      \"timestamp\": 1760559072294,\n      \"level\": \"WARN\",\n      \"service\": \"email-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"environment:production\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1426\",\n      \"timestamp\": 1760558704141,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"environment:production\", \"version:1.0.0\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1867\",\n      \"timestamp\": 1760558404808,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Lock released: resource-69\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-691\",\n      \"timestamp\": 1760558268773,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Database pool almost full: 96/100\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-401\",\n      \"timestamp\": 1760557930025,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"SSL certificate expires in 10 days\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:backup\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1827\",\n      \"timestamp\": 1760557534463,\n      \"level\": \"ERROR\",\n      \"service\": \"payment-service\",\n      \"message\": \"JWT token validation failed: token expired\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-794\",\n      \"timestamp\": 1760557523742,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"User profile updated successfully\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1945\",\n      \"timestamp\": 1760557024703,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"version:1.0.0\", \"environment:staging\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-8\",\n      \"timestamp\": 1760556627381,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:backup\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-209\",\n      \"timestamp\": 1760556552796,\n      \"level\": \"ERROR\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-572\",\n      \"timestamp\": 1760555557500,\n      \"level\": \"ERROR\",\n      \"service\": \"user-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-326\",\n      \"timestamp\": 1760555330995,\n      \"level\": \"INFO\",\n      \"service\": \"storage-service\",\n      \"message\": \"Scheduled job completed: backup\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"environment:staging\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-29\",\n      \"timestamp\": 1760554668312,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Exiting function: calculateTotal\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"cluster:main\", \"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-497\",\n      \"timestamp\": 1760554361952,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Scheduled job completed: index-rebuild\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-420\",\n      \"timestamp\": 1760554282652,\n      \"level\": \"WARN\",\n      \"service\": \"storage-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"region:eu-west-1\", \"region:us-west-2\", \"environment:staging\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-526\",\n      \"timestamp\": 1760554033717,\n      \"level\": \"DEBUG\",\n      \"service\": \"sms-service\",\n      \"message\": \"Lock acquired: resource-17\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"version:3.0.1\", \"region:us-west-2\", \"version:2.1.5\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-893\",\n      \"timestamp\": 1760553722980,\n      \"level\": \"DEBUG\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1542\",\n      \"timestamp\": 1760553215515,\n      \"level\": \"WARN\",\n      \"service\": \"report-service\",\n      \"message\": \"Cache miss for key: user:5553\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-355\",\n      \"timestamp\": 1760553094107,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Failed to write file: disk quota exceeded\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"cluster:backup\", \"version:1.0.0\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1439\",\n      \"timestamp\": 1760552186394,\n      \"level\": \"WARN\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1537\",\n      \"timestamp\": 1760552150496,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"File uploaded: zna3bc.pdf\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:3.0.1\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-736\",\n      \"timestamp\": 1760552148698,\n      \"level\": \"WARN\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-644\",\n      \"timestamp\": 1760551965152,\n      \"level\": \"INFO\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Stock updated for product SKU-60033\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"version:1.0.0\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1063\",\n      \"timestamp\": 1760551753129,\n      \"level\": \"WARN\",\n      \"service\": \"payment-service\",\n      \"message\": \"Retry attempt 1 for failed request\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-164\",\n      \"timestamp\": 1760551688186,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-notify-01\",\n      \"tags\": [\"cluster:main\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1423\",\n      \"timestamp\": 1760551322960,\n      \"level\": \"ERROR\",\n      \"service\": \"monitoring-service\",\n      \"message\": \"HTTP 500 Internal Server Error\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-363\",\n      \"timestamp\": 1760551039032,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1933\",\n      \"timestamp\": 1760550862250,\n      \"level\": \"WARN\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.1.5\", \"version:3.0.1\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-1649\",\n      \"timestamp\": 1760550780760,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Lock released: resource-91\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"cluster:backup\", \"version:2.0.0\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-905\",\n      \"timestamp\": 1760550766869,\n      \"level\": \"DEBUG\",\n      \"service\": \"notification-service\",\n      \"message\": \"Event published: order.placed\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"region:us-east-1\", \"region:us-west-2\", \"version:3.0.1\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1386\",\n      \"timestamp\": 1760550648041,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Queue size approaching limit: 8355\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"version:2.0.0\", \"environment:production\", \"cluster:main\", \"version:3.0.1\"]\n    },\n    {\n      \"id\": \"log-1946\",\n      \"timestamp\": 1760550444649,\n      \"level\": \"DEBUG\",\n      \"service\": \"storage-service\",\n      \"message\": \"Event published: user.created\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"version:2.1.5\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-254\",\n      \"timestamp\": 1760550368653,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Failed to send email: SMTP connection refused\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"version:1.0.0\"]\n    },\n    {\n      \"id\": \"log-1576\",\n      \"timestamp\": 1760549995275,\n      \"level\": \"WARN\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Fallback to backup service\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"version:2.1.5\", \"region:us-west-2\", \"cluster:backup\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-624\",\n      \"timestamp\": 1760549079384,\n      \"level\": \"ERROR\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Credit card validation failed: invalid CVV\",\n      \"host\": \"prod-auth-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"region:eu-west-1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-28\",\n      \"timestamp\": 1760548911470,\n      \"level\": \"DEBUG\",\n      \"service\": \"cache-service\",\n      \"message\": \"Lock acquired: resource-52\",\n      \"host\": \"prod-db-01\",\n      \"tags\": [\"version:2.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1756\",\n      \"timestamp\": 1760548723160,\n      \"level\": \"ERROR\",\n      \"service\": \"auth-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-api-02\",\n      \"tags\": [\"cluster:backup\", \"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-1560\",\n      \"timestamp\": 1760548534848,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Rate limit approaching for client 192.168.231.36\",\n      \"host\": \"prod-auth-02\",\n      \"tags\": [\"version:1.0.0\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-277\",\n      \"timestamp\": 1760548513038,\n      \"level\": \"INFO\",\n      \"service\": \"notification-service\",\n      \"message\": \"Configuration reloaded\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1955\",\n      \"timestamp\": 1760548139543,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Response time degradation detected\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:1.0.0\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-400\",\n      \"timestamp\": 1760547823851,\n      \"level\": \"DEBUG\",\n      \"service\": \"email-service\",\n      \"message\": \"Lock acquired: resource-42\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"version:1.0.0\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-63\",\n      \"timestamp\": 1760547744266,\n      \"level\": \"WARN\",\n      \"service\": \"cache-service\",\n      \"message\": \"Carrier API response time exceeded 5s\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"environment:production\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1096\",\n      \"timestamp\": 1760547679645,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1444\",\n      \"timestamp\": 1760547563907,\n      \"level\": \"INFO\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Scheduled job completed: report-generation\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"version:2.1.5\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1521\",\n      \"timestamp\": 1760547469913,\n      \"level\": \"WARN\",\n      \"service\": \"search-service\",\n      \"message\": \"Circuit breaker half-open\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:1.0.0\", \"version:2.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-695\",\n      \"timestamp\": 1760546920643,\n      \"level\": \"INFO\",\n      \"service\": \"sms-service\",\n      \"message\": \"Request processed successfully in 487ms\",\n      \"host\": \"prod-analytics-01\",\n      \"tags\": [\"cluster:backup\", \"version:3.0.1\", \"environment:staging\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-568\",\n      \"timestamp\": 1760546545133,\n      \"level\": \"DEBUG\",\n      \"service\": \"user-service\",\n      \"message\": \"Lock released: resource-50\",\n      \"host\": \"prod-shipping-01\",\n      \"tags\": [\"environment:production\", \"cluster:backup\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-764\",\n      \"timestamp\": 1760546498080,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"SSL certificate expires in 27 days\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:3.0.1\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-1314\",\n      \"timestamp\": 1760545509628,\n      \"level\": \"INFO\",\n      \"service\": \"inventory-service\",\n      \"message\": \"Daily report generated successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-1053\",\n      \"timestamp\": 1760544923690,\n      \"level\": \"DEBUG\",\n      \"service\": \"metrics-service\",\n      \"message\": \"Cache hit for key: user:9469\",\n      \"host\": \"prod-search-01\",\n      \"tags\": [\"version:2.1.5\", \"region:eu-west-1\", \"environment:production\"]\n    },\n    {\n      \"id\": \"log-1654\",\n      \"timestamp\": 1760544922621,\n      \"level\": \"ERROR\",\n      \"service\": \"email-service\",\n      \"message\": \"Failed to connect to Redis\",\n      \"host\": \"prod-metrics-01\",\n      \"tags\": [\"region:us-west-2\", \"region:eu-west-1\", \"region:us-east-1\"]\n    },\n    {\n      \"id\": \"log-1032\",\n      \"timestamp\": 1760544811046,\n      \"level\": \"WARN\",\n      \"service\": \"logging-service\",\n      \"message\": \"SSL certificate expires in 12 days\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"region:us-west-2\", \"region:us-east-1\", \"region:eu-west-1\"]\n    },\n    {\n      \"id\": \"log-611\",\n      \"timestamp\": 1760544413495,\n      \"level\": \"WARN\",\n      \"service\": \"db-service\",\n      \"message\": \"Slow query detected: SELECT * FROM users...\",\n      \"host\": \"prod-storage-02\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-173\",\n      \"timestamp\": 1760544268998,\n      \"level\": \"ERROR\",\n      \"service\": \"cache-service\",\n      \"message\": \"API rate limit exceeded\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"version:2.1.5\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-1466\",\n      \"timestamp\": 1760544231407,\n      \"level\": \"INFO\",\n      \"service\": \"recommendation-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-recommend-01\",\n      \"tags\": [\"cluster:backup\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-459\",\n      \"timestamp\": 1760543805542,\n      \"level\": \"ERROR\",\n      \"service\": \"analytics-service\",\n      \"message\": \"Transaction rollback: constraint violation\",\n      \"host\": \"prod-inventory-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-430\",\n      \"timestamp\": 1760543068606,\n      \"level\": \"WARN\",\n      \"service\": \"notification-service\",\n      \"message\": \"Payment gateway timeout, retrying\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"environment:staging\", \"region:us-west-2\"]\n    },\n    {\n      \"id\": \"log-1470\",\n      \"timestamp\": 1760543025796,\n      \"level\": \"INFO\",\n      \"service\": \"user-service\",\n      \"message\": \"Request processed successfully in 69ms\",\n      \"host\": \"prod-storage-01\",\n      \"tags\": [\"region:us-east-1\", \"environment:production\", \"environment:staging\"]\n    },\n    {\n      \"id\": \"log-600\",\n      \"timestamp\": 1760542676206,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Exiting function: processOrder\",\n      \"host\": \"prod-api-01\",\n      \"tags\": [\"region:us-west-2\", \"environment:production\", \"cluster:backup\"]\n    },\n    {\n      \"id\": \"log-665\",\n      \"timestamp\": 1760542369483,\n      \"level\": \"WARN\",\n      \"service\": \"trace-service\",\n      \"message\": \"Rate limit approaching for client 192.168.223.150\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-west-2\", \"version:2.1.5\"]\n    },\n    {\n      \"id\": \"log-690\",\n      \"timestamp\": 1760542321017,\n      \"level\": \"INFO\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Health check passed\",\n      \"host\": \"prod-web-02\",\n      \"tags\": [\"version:1.0.0\", \"cluster:main\"]\n    },\n    {\n      \"id\": \"log-755\",\n      \"timestamp\": 1760541957379,\n      \"level\": \"INFO\",\n      \"service\": \"db-service\",\n      \"message\": \"Cache warmed up successfully\",\n      \"host\": \"prod-api-03\",\n      \"tags\": [\"environment:production\", \"environment:staging\", \"cluster:main\", \"version:2.0.0\"]\n    },\n    {\n      \"id\": \"log-861\",\n      \"timestamp\": 1760541318236,\n      \"level\": \"DEBUG\",\n      \"service\": \"shipping-service\",\n      \"message\": \"HTTP request: PUT /uploads/swe0fn.jpg\",\n      \"host\": \"prod-trace-01\",\n      \"tags\": [\"region:us-east-1\", \"cluster:main\"]\n    }\n  ],\n  \"facets\": {\n    \"services\": [\n      \"api-gateway\",\n      \"auth-service\",\n      \"user-service\",\n      \"payment-service\",\n      \"notification-service\",\n      \"search-service\",\n      \"analytics-service\",\n      \"db-service\",\n      \"cache-service\",\n      \"storage-service\",\n      \"email-service\",\n      \"sms-service\",\n      \"recommendation-service\",\n      \"inventory-service\",\n      \"shipping-service\",\n      \"report-service\",\n      \"monitoring-service\",\n      \"logging-service\",\n      \"metrics-service\",\n      \"trace-service\"\n    ],\n    \"levels\": [\"ERROR\", \"WARN\", \"INFO\", \"DEBUG\"],\n    \"hosts\": [\n      \"prod-web-01\",\n      \"prod-web-02\",\n      \"prod-api-01\",\n      \"prod-api-02\",\n      \"prod-api-03\",\n      \"prod-auth-01\",\n      \"prod-auth-02\",\n      \"prod-db-01\",\n      \"prod-cache-01\",\n      \"prod-storage-01\",\n      \"prod-storage-02\",\n      \"prod-notify-01\",\n      \"prod-search-01\",\n      \"prod-analytics-01\",\n      \"prod-trace-01\",\n      \"prod-inventory-01\",\n      \"prod-shipping-01\",\n      \"prod-recommend-01\",\n      \"prod-metrics-01\"\n    ],\n    \"environments\": [\"production\", \"staging\", \"development\"]\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/public/data/metrics.json",
    "content": "{\n  \"summary\": {\n    \"apm_requests\": 1234567,\n    \"logs_count\": 9876543,\n    \"infrastructure_hosts\": 456,\n    \"errors_count\": 123,\n    \"avg_response_time\": 245,\n    \"p95_response_time\": 890\n  },\n  \"timeseries\": [\n    { \"timestamp\": 1697500000000, \"requests\": 150, \"errors\": 2, \"latency\": 230 },\n    { \"timestamp\": 1697500060000, \"requests\": 180, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697500120000, \"requests\": 165, \"errors\": 3, \"latency\": 220 },\n    { \"timestamp\": 1697500180000, \"requests\": 195, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697500240000, \"requests\": 210, \"errors\": 1, \"latency\": 255 },\n    { \"timestamp\": 1697500300000, \"requests\": 190, \"errors\": 4, \"latency\": 275 },\n    { \"timestamp\": 1697500360000, \"requests\": 175, \"errors\": 2, \"latency\": 240 },\n    { \"timestamp\": 1697500420000, \"requests\": 185, \"errors\": 3, \"latency\": 265 },\n    { \"timestamp\": 1697500480000, \"requests\": 200, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697500540000, \"requests\": 220, \"errors\": 2, \"latency\": 280 },\n    { \"timestamp\": 1697500600000, \"requests\": 195, \"errors\": 5, \"latency\": 290 },\n    { \"timestamp\": 1697500660000, \"requests\": 205, \"errors\": 3, \"latency\": 250 },\n    { \"timestamp\": 1697500720000, \"requests\": 180, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697500780000, \"requests\": 170, \"errors\": 2, \"latency\": 230 },\n    { \"timestamp\": 1697500840000, \"requests\": 190, \"errors\": 4, \"latency\": 270 },\n    { \"timestamp\": 1697500900000, \"requests\": 215, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697500960000, \"requests\": 200, \"errors\": 3, \"latency\": 265 },\n    { \"timestamp\": 1697501020000, \"requests\": 185, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697501080000, \"requests\": 195, \"errors\": 2, \"latency\": 250 },\n    { \"timestamp\": 1697501140000, \"requests\": 210, \"errors\": 3, \"latency\": 275 },\n    { \"timestamp\": 1697501200000, \"requests\": 225, \"errors\": 2, \"latency\": 265 },\n    { \"timestamp\": 1697501260000, \"requests\": 198, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697501320000, \"requests\": 205, \"errors\": 4, \"latency\": 285 },\n    { \"timestamp\": 1697501380000, \"requests\": 188, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697501440000, \"requests\": 215, \"errors\": 3, \"latency\": 270 },\n    { \"timestamp\": 1697501500000, \"requests\": 230, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697501560000, \"requests\": 192, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697501620000, \"requests\": 208, \"errors\": 5, \"latency\": 295 },\n    { \"timestamp\": 1697501680000, \"requests\": 175, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697501740000, \"requests\": 220, \"errors\": 3, \"latency\": 280 },\n    { \"timestamp\": 1697501800000, \"requests\": 195, \"errors\": 2, \"latency\": 250 },\n    { \"timestamp\": 1697501860000, \"requests\": 210, \"errors\": 4, \"latency\": 275 },\n    { \"timestamp\": 1697501920000, \"requests\": 185, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697501980000, \"requests\": 200, \"errors\": 2, \"latency\": 265 },\n    { \"timestamp\": 1697502040000, \"requests\": 225, \"errors\": 3, \"latency\": 270 },\n    { \"timestamp\": 1697502100000, \"requests\": 190, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697502160000, \"requests\": 215, \"errors\": 4, \"latency\": 290 },\n    { \"timestamp\": 1697502220000, \"requests\": 205, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697502280000, \"requests\": 178, \"errors\": 3, \"latency\": 280 },\n    { \"timestamp\": 1697502340000, \"requests\": 195, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697502400000, \"requests\": 220, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697502460000, \"requests\": 188, \"errors\": 5, \"latency\": 300 },\n    { \"timestamp\": 1697502520000, \"requests\": 210, \"errors\": 3, \"latency\": 270 },\n    { \"timestamp\": 1697502580000, \"requests\": 198, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697502640000, \"requests\": 225, \"errors\": 2, \"latency\": 265 },\n    { \"timestamp\": 1697502700000, \"requests\": 192, \"errors\": 4, \"latency\": 285 },\n    { \"timestamp\": 1697502760000, \"requests\": 205, \"errors\": 2, \"latency\": 250 },\n    { \"timestamp\": 1697502820000, \"requests\": 215, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697502880000, \"requests\": 180, \"errors\": 3, \"latency\": 275 },\n    { \"timestamp\": 1697502940000, \"requests\": 200, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697503000000, \"requests\": 230, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697503060000, \"requests\": 195, \"errors\": 4, \"latency\": 295 },\n    { \"timestamp\": 1697503120000, \"requests\": 210, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697503180000, \"requests\": 185, \"errors\": 3, \"latency\": 280 },\n    { \"timestamp\": 1697503240000, \"requests\": 220, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697503300000, \"requests\": 205, \"errors\": 2, \"latency\": 270 },\n    { \"timestamp\": 1697503360000, \"requests\": 198, \"errors\": 5, \"latency\": 305 },\n    { \"timestamp\": 1697503420000, \"requests\": 215, \"errors\": 3, \"latency\": 265 },\n    { \"timestamp\": 1697503480000, \"requests\": 188, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697503540000, \"requests\": 225, \"errors\": 2, \"latency\": 275 },\n    { \"timestamp\": 1697503600000, \"requests\": 192, \"errors\": 4, \"latency\": 290 },\n    { \"timestamp\": 1697503660000, \"requests\": 210, \"errors\": 2, \"latency\": 250 },\n    { \"timestamp\": 1697503720000, \"requests\": 178, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697503780000, \"requests\": 205, \"errors\": 3, \"latency\": 280 },\n    { \"timestamp\": 1697503840000, \"requests\": 220, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697503900000, \"requests\": 195, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697503960000, \"requests\": 215, \"errors\": 4, \"latency\": 295 },\n    { \"timestamp\": 1697504020000, \"requests\": 200, \"errors\": 3, \"latency\": 270 },\n    { \"timestamp\": 1697504080000, \"requests\": 230, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697504140000, \"requests\": 188, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697504200000, \"requests\": 210, \"errors\": 2, \"latency\": 265 },\n    { \"timestamp\": 1697504260000, \"requests\": 198, \"errors\": 5, \"latency\": 300 },\n    { \"timestamp\": 1697504320000, \"requests\": 225, \"errors\": 3, \"latency\": 275 },\n    { \"timestamp\": 1697504380000, \"requests\": 192, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697504440000, \"requests\": 205, \"errors\": 2, \"latency\": 280 },\n    { \"timestamp\": 1697504500000, \"requests\": 215, \"errors\": 4, \"latency\": 290 },\n    { \"timestamp\": 1697504560000, \"requests\": 185, \"errors\": 2, \"latency\": 250 },\n    { \"timestamp\": 1697504620000, \"requests\": 220, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697504680000, \"requests\": 195, \"errors\": 3, \"latency\": 270 },\n    { \"timestamp\": 1697504740000, \"requests\": 210, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697504800000, \"requests\": 200, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697504860000, \"requests\": 230, \"errors\": 4, \"latency\": 285 },\n    { \"timestamp\": 1697504920000, \"requests\": 188, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697504980000, \"requests\": 215, \"errors\": 3, \"latency\": 275 },\n    { \"timestamp\": 1697505040000, \"requests\": 205, \"errors\": 1, \"latency\": 240 },\n    { \"timestamp\": 1697505100000, \"requests\": 198, \"errors\": 2, \"latency\": 265 },\n    { \"timestamp\": 1697505160000, \"requests\": 225, \"errors\": 5, \"latency\": 295 },\n    { \"timestamp\": 1697505220000, \"requests\": 192, \"errors\": 3, \"latency\": 280 },\n    { \"timestamp\": 1697505280000, \"requests\": 210, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697505340000, \"requests\": 185, \"errors\": 2, \"latency\": 270 },\n    { \"timestamp\": 1697505400000, \"requests\": 220, \"errors\": 4, \"latency\": 290 },\n    { \"timestamp\": 1697505460000, \"requests\": 195, \"errors\": 2, \"latency\": 250 },\n    { \"timestamp\": 1697505520000, \"requests\": 215, \"errors\": 1, \"latency\": 235 },\n    { \"timestamp\": 1697505580000, \"requests\": 200, \"errors\": 3, \"latency\": 275 },\n    { \"timestamp\": 1697505640000, \"requests\": 230, \"errors\": 2, \"latency\": 260 },\n    { \"timestamp\": 1697505700000, \"requests\": 188, \"errors\": 1, \"latency\": 245 },\n    { \"timestamp\": 1697505760000, \"requests\": 205, \"errors\": 4, \"latency\": 300 },\n    { \"timestamp\": 1697505820000, \"requests\": 210, \"errors\": 3, \"latency\": 270 },\n    { \"timestamp\": 1697505880000, \"requests\": 198, \"errors\": 2, \"latency\": 255 },\n    { \"timestamp\": 1697505940000, \"requests\": 225, \"errors\": 1, \"latency\": 240 }\n  ],\n  \"services\": [\n    { \"name\": \"api-gateway\", \"status\": \"healthy\", \"requests\": 50000, \"errors\": 45, \"avgLatency\": 120 },\n    { \"name\": \"auth-service\", \"status\": \"healthy\", \"requests\": 35000, \"errors\": 12, \"avgLatency\": 95 },\n    { \"name\": \"user-service\", \"status\": \"healthy\", \"requests\": 42000, \"errors\": 23, \"avgLatency\": 150 },\n    { \"name\": \"payment-service\", \"status\": \"warning\", \"requests\": 28000, \"errors\": 156, \"avgLatency\": 320 },\n    { \"name\": \"notification-service\", \"status\": \"healthy\", \"requests\": 15000, \"errors\": 8, \"avgLatency\": 85 },\n    { \"name\": \"search-service\", \"status\": \"healthy\", \"requests\": 38000, \"errors\": 34, \"avgLatency\": 210 },\n    { \"name\": \"analytics-service\", \"status\": \"healthy\", \"requests\": 22000, \"errors\": 15, \"avgLatency\": 180 },\n    { \"name\": \"db-service\", \"status\": \"healthy\", \"requests\": 65000, \"errors\": 45, \"avgLatency\": 75 },\n    { \"name\": \"cache-service\", \"status\": \"healthy\", \"requests\": 98000, \"errors\": 12, \"avgLatency\": 25 },\n    { \"name\": \"storage-service\", \"status\": \"critical\", \"requests\": 18000, \"errors\": 890, \"avgLatency\": 550 },\n    { \"name\": \"email-service\", \"status\": \"healthy\", \"requests\": 12000, \"errors\": 5, \"avgLatency\": 140 },\n    { \"name\": \"sms-service\", \"status\": \"healthy\", \"requests\": 8000, \"errors\": 3, \"avgLatency\": 160 },\n    { \"name\": \"recommendation-service\", \"status\": \"healthy\", \"requests\": 25000, \"errors\": 18, \"avgLatency\": 280 },\n    { \"name\": \"inventory-service\", \"status\": \"healthy\", \"requests\": 32000, \"errors\": 28, \"avgLatency\": 195 },\n    { \"name\": \"shipping-service\", \"status\": \"warning\", \"requests\": 14000, \"errors\": 67, \"avgLatency\": 380 },\n    { \"name\": \"report-service\", \"status\": \"healthy\", \"requests\": 9000, \"errors\": 7, \"avgLatency\": 420 },\n    { \"name\": \"monitoring-service\", \"status\": \"healthy\", \"requests\": 45000, \"errors\": 23, \"avgLatency\": 65 },\n    { \"name\": \"logging-service\", \"status\": \"healthy\", \"requests\": 78000, \"errors\": 34, \"avgLatency\": 45 },\n    { \"name\": \"metrics-service\", \"status\": \"healthy\", \"requests\": 52000, \"errors\": 29, \"avgLatency\": 55 },\n    { \"name\": \"trace-service\", \"status\": \"healthy\", \"requests\": 48000, \"errors\": 31, \"avgLatency\": 70 }\n  ],\n  \"activity\": [\n    {\n      \"id\": 1,\n      \"type\": \"alert\",\n      \"severity\": \"critical\",\n      \"service\": \"storage-service\",\n      \"message\": \"High error rate detected\",\n      \"timestamp\": 1697501140000\n    },\n    {\n      \"id\": 2,\n      \"type\": \"deployment\",\n      \"severity\": \"info\",\n      \"service\": \"api-gateway\",\n      \"message\": \"Version 2.3.1 deployed\",\n      \"timestamp\": 1697501080000\n    },\n    {\n      \"id\": 3,\n      \"type\": \"alert\",\n      \"severity\": \"warning\",\n      \"service\": \"payment-service\",\n      \"message\": \"Increased latency detected\",\n      \"timestamp\": 1697501020000\n    },\n    {\n      \"id\": 4,\n      \"type\": \"incident\",\n      \"severity\": \"info\",\n      \"service\": \"user-service\",\n      \"message\": \"Incident #4521 resolved\",\n      \"timestamp\": 1697500960000\n    },\n    {\n      \"id\": 5,\n      \"type\": \"alert\",\n      \"severity\": \"warning\",\n      \"service\": \"shipping-service\",\n      \"message\": \"Error rate above threshold\",\n      \"timestamp\": 1697500900000\n    },\n    {\n      \"id\": 6,\n      \"type\": \"deployment\",\n      \"severity\": \"info\",\n      \"service\": \"auth-service\",\n      \"message\": \"Rollback to version 1.8.2\",\n      \"timestamp\": 1697500840000\n    },\n    {\n      \"id\": 7,\n      \"type\": \"alert\",\n      \"severity\": \"info\",\n      \"service\": \"cache-service\",\n      \"message\": \"Memory usage normalized\",\n      \"timestamp\": 1697500780000\n    },\n    {\n      \"id\": 8,\n      \"type\": \"deployment\",\n      \"severity\": \"info\",\n      \"service\": \"search-service\",\n      \"message\": \"Version 3.1.0 deployed\",\n      \"timestamp\": 1697500720000\n    }\n  ]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/public/data/traces.json",
    "content": "{\n  \"traces\": [\n    {\n      \"id\": \"trace-1\",\n      \"traceId\": \"abc123def456\",\n      \"service\": \"api-gateway\",\n      \"operation\": \"POST /api/checkout\",\n      \"duration\": 1245,\n      \"timestamp\": 1697501140000,\n      \"status\": \"ok\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-1\",\n          \"operation\": \"http.request\",\n          \"duration\": 1245,\n          \"service\": \"api-gateway\",\n          \"resource\": \"POST /api/checkout\"\n        },\n        {\n          \"spanId\": \"span-2\",\n          \"operation\": \"validate.user\",\n          \"duration\": 45,\n          \"service\": \"auth-service\",\n          \"resource\": \"validate_token\"\n        },\n        {\n          \"spanId\": \"span-3\",\n          \"operation\": \"db.query\",\n          \"duration\": 120,\n          \"service\": \"user-service\",\n          \"resource\": \"SELECT FROM users\"\n        },\n        {\n          \"spanId\": \"span-4\",\n          \"operation\": \"payment.process\",\n          \"duration\": 850,\n          \"service\": \"payment-service\",\n          \"resource\": \"charge_card\"\n        },\n        {\n          \"spanId\": \"span-5\",\n          \"operation\": \"inventory.check\",\n          \"duration\": 95,\n          \"service\": \"inventory-service\",\n          \"resource\": \"check_stock\"\n        },\n        {\n          \"spanId\": \"span-6\",\n          \"operation\": \"email.send\",\n          \"duration\": 135,\n          \"service\": \"notification-service\",\n          \"resource\": \"send_confirmation\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-2\",\n      \"traceId\": \"xyz789ghi012\",\n      \"service\": \"search-service\",\n      \"operation\": \"GET /api/search\",\n      \"duration\": 345,\n      \"timestamp\": 1697501135000,\n      \"status\": \"ok\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-7\",\n          \"operation\": \"http.request\",\n          \"duration\": 345,\n          \"service\": \"search-service\",\n          \"resource\": \"GET /api/search\"\n        },\n        {\n          \"spanId\": \"span-8\",\n          \"operation\": \"cache.get\",\n          \"duration\": 15,\n          \"service\": \"cache-service\",\n          \"resource\": \"GET search:query:123\"\n        },\n        {\n          \"spanId\": \"span-9\",\n          \"operation\": \"elasticsearch.query\",\n          \"duration\": 280,\n          \"service\": \"search-service\",\n          \"resource\": \"search_products\"\n        },\n        {\n          \"spanId\": \"span-10\",\n          \"operation\": \"cache.set\",\n          \"duration\": 25,\n          \"service\": \"cache-service\",\n          \"resource\": \"SET search:query:123\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-3\",\n      \"traceId\": \"mno345pqr678\",\n      \"service\": \"user-service\",\n      \"operation\": \"PUT /api/users/profile\",\n      \"duration\": 285,\n      \"timestamp\": 1697501130000,\n      \"status\": \"ok\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-11\",\n          \"operation\": \"http.request\",\n          \"duration\": 285,\n          \"service\": \"user-service\",\n          \"resource\": \"PUT /api/users/profile\"\n        },\n        {\n          \"spanId\": \"span-12\",\n          \"operation\": \"validate.input\",\n          \"duration\": 25,\n          \"service\": \"user-service\",\n          \"resource\": \"validate_profile_data\"\n        },\n        {\n          \"spanId\": \"span-13\",\n          \"operation\": \"db.update\",\n          \"duration\": 180,\n          \"service\": \"db-service\",\n          \"resource\": \"UPDATE users\"\n        },\n        {\n          \"spanId\": \"span-14\",\n          \"operation\": \"cache.invalidate\",\n          \"duration\": 35,\n          \"service\": \"cache-service\",\n          \"resource\": \"DEL user:12345\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-4\",\n      \"traceId\": \"stu901vwx234\",\n      \"service\": \"storage-service\",\n      \"operation\": \"POST /api/upload\",\n      \"duration\": 2450,\n      \"timestamp\": 1697501125000,\n      \"status\": \"error\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-15\",\n          \"operation\": \"http.request\",\n          \"duration\": 2450,\n          \"service\": \"storage-service\",\n          \"resource\": \"POST /api/upload\"\n        },\n        {\n          \"spanId\": \"span-16\",\n          \"operation\": \"validate.file\",\n          \"duration\": 55,\n          \"service\": \"storage-service\",\n          \"resource\": \"check_file_type\"\n        },\n        {\n          \"spanId\": \"span-17\",\n          \"operation\": \"s3.upload\",\n          \"duration\": 2350,\n          \"service\": \"storage-service\",\n          \"resource\": \"PUT object\",\n          \"error\": \"AccessDenied\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-5\",\n      \"traceId\": \"yza567bcd890\",\n      \"service\": \"analytics-service\",\n      \"operation\": \"POST /api/events\",\n      \"duration\": 125,\n      \"timestamp\": 1697501120000,\n      \"status\": \"ok\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-18\",\n          \"operation\": \"http.request\",\n          \"duration\": 125,\n          \"service\": \"analytics-service\",\n          \"resource\": \"POST /api/events\"\n        },\n        {\n          \"spanId\": \"span-19\",\n          \"operation\": \"kafka.produce\",\n          \"duration\": 85,\n          \"service\": \"analytics-service\",\n          \"resource\": \"send_event\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-6\",\n      \"traceId\": \"efg123hij456\",\n      \"service\": \"recommendation-service\",\n      \"operation\": \"GET /api/recommendations\",\n      \"duration\": 520,\n      \"timestamp\": 1697501115000,\n      \"status\": \"ok\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-20\",\n          \"operation\": \"http.request\",\n          \"duration\": 520,\n          \"service\": \"recommendation-service\",\n          \"resource\": \"GET /api/recommendations\"\n        },\n        {\n          \"spanId\": \"span-21\",\n          \"operation\": \"ml.inference\",\n          \"duration\": 420,\n          \"service\": \"recommendation-service\",\n          \"resource\": \"generate_recommendations\"\n        },\n        {\n          \"spanId\": \"span-22\",\n          \"operation\": \"db.query\",\n          \"duration\": 75,\n          \"service\": \"db-service\",\n          \"resource\": \"SELECT FROM products\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-7\",\n      \"traceId\": \"klm789nop012\",\n      \"service\": \"shipping-service\",\n      \"operation\": \"POST /api/shipping/calculate\",\n      \"duration\": 1850,\n      \"timestamp\": 1697501110000,\n      \"status\": \"warning\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-23\",\n          \"operation\": \"http.request\",\n          \"duration\": 1850,\n          \"service\": \"shipping-service\",\n          \"resource\": \"POST /api/shipping/calculate\"\n        },\n        {\n          \"spanId\": \"span-24\",\n          \"operation\": \"external.api\",\n          \"duration\": 1720,\n          \"service\": \"shipping-service\",\n          \"resource\": \"fedex_api_call\",\n          \"warning\": \"slow_response\"\n        },\n        {\n          \"spanId\": \"span-25\",\n          \"operation\": \"db.insert\",\n          \"duration\": 95,\n          \"service\": \"db-service\",\n          \"resource\": \"INSERT INTO shipping_quotes\"\n        }\n      ]\n    },\n    {\n      \"id\": \"trace-8\",\n      \"traceId\": \"qrs345tuv678\",\n      \"service\": \"auth-service\",\n      \"operation\": \"POST /api/auth/login\",\n      \"duration\": 195,\n      \"timestamp\": 1697501105000,\n      \"status\": \"ok\",\n      \"spans\": [\n        {\n          \"spanId\": \"span-26\",\n          \"operation\": \"http.request\",\n          \"duration\": 195,\n          \"service\": \"auth-service\",\n          \"resource\": \"POST /api/auth/login\"\n        },\n        {\n          \"spanId\": \"span-27\",\n          \"operation\": \"db.query\",\n          \"duration\": 85,\n          \"service\": \"db-service\",\n          \"resource\": \"SELECT FROM users\"\n        },\n        {\n          \"spanId\": \"span-28\",\n          \"operation\": \"crypto.hash\",\n          \"duration\": 65,\n          \"service\": \"auth-service\",\n          \"resource\": \"bcrypt_compare\"\n        },\n        {\n          \"spanId\": \"span-29\",\n          \"operation\": \"jwt.sign\",\n          \"duration\": 25,\n          \"service\": \"auth-service\",\n          \"resource\": \"generate_token\"\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/App.css",
    "content": ".logo {\n  height: 6em;\n  padding: 1.5em;\n  will-change: filter;\n  transition: filter 300ms;\n}\n.logo:hover {\n  filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n  filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n  from {\n    transform: rotate(0deg);\n  }\n  to {\n    transform: rotate(360deg);\n  }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n  a:nth-of-type(2) .logo {\n    animation: logo-spin infinite 20s linear;\n  }\n}\n\n.card {\n  padding: 2em;\n}\n\n.read-the-docs {\n  color: #888;\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/App.tsx",
    "content": "import { BrowserRouter, Routes, Route } from 'react-router-dom'\nimport MainLayout from './components/Layout/MainLayout'\nimport Dashboard from './components/Dashboard/Dashboard'\nimport LogsExplorer from './components/Logs/LogsExplorer'\nimport Infrastructure from './components/Infrastructure/Infrastructure'\nimport Settings from './components/Settings/Settings'\nimport { ROUTES } from './utils/constants'\nimport './App.css'\n\nfunction App() {\n  return (\n    <BrowserRouter>\n      <MainLayout>\n        <Routes>\n          <Route path={ROUTES.DASHBOARD} element={<Dashboard />} />\n          <Route path={ROUTES.LOGS} element={<LogsExplorer />} />\n          <Route path={ROUTES.INFRASTRUCTURE} element={<Infrastructure />} />\n          <Route path={ROUTES.SETTINGS} element={<Settings />} />\n        </Routes>\n      </MainLayout>\n    </BrowserRouter>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/ActivityFeed.css",
    "content": ".activity-feed {\n  background: var(--color-surface, #2a2a2a);\n  border-radius: 8px;\n  padding: 24px;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n.feed-title {\n  font-size: 18px;\n  font-weight: 600;\n  color: var(--color-text, #e0e0e0);\n  margin: 0 0 20px 0;\n}\n\n.activity-list {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n}\n\n.activity-item {\n  display: flex;\n  gap: 12px;\n  padding: 12px;\n  border-radius: 6px;\n  border-left: 3px solid transparent;\n  background: var(--color-bg, #1e1e1e);\n  transition: background-color 0.2s ease;\n}\n\n.activity-item:hover {\n  background: #252525;\n}\n\n.activity-severity-critical {\n  border-left-color: var(--color-error, #ff5252);\n}\n\n.activity-severity-warning {\n  border-left-color: var(--color-warning, #ffa726);\n}\n\n.activity-severity-info {\n  border-left-color: var(--color-primary, #632ca6);\n}\n\n.activity-icon {\n  font-size: 20px;\n  flex-shrink: 0;\n}\n\n.activity-content {\n  flex: 1;\n  min-width: 0;\n}\n\n.activity-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 4px;\n}\n\n.activity-service {\n  font-size: 13px;\n  font-weight: 600;\n  color: var(--color-text, #e0e0e0);\n}\n\n.activity-time {\n  font-size: 12px;\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.activity-message {\n  font-size: 13px;\n  color: var(--color-text-secondary, #b0b0b0);\n  margin: 0;\n  line-height: 1.4;\n}\n\n.feed-loading {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  min-height: 400px;\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.feed-loading p {\n  margin-top: 16px;\n  font-size: 14px;\n}\n\n.feed-loading .loading-spinner {\n  width: 40px;\n  height: 40px;\n  border: 4px solid rgba(255, 255, 255, 0.1);\n  border-top-color: #632ca6;\n  border-radius: 50%;\n  animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/ActivityFeed.tsx",
    "content": "import { Trace } from '../../types/data'\nimport './ActivityFeed.css'\n\ninterface ActivityFeedProps {\n  traces: Trace[]\n  loading?: boolean\n}\n\nexport default function ActivityFeed({ traces, loading = false }: ActivityFeedProps) {\n  const getStatusClass = (status: string) => {\n    return `activity-severity-${status === 'ok' ? 'info' : status === 'error' ? 'critical' : 'warning'}`\n  }\n\n  const getStatusIcon = (status: string) => {\n    switch (status) {\n      case 'ok':\n        return '✓'\n      case 'error':\n        return '✗'\n      case 'warning':\n        return '⚠'\n      default:\n        return '📋'\n    }\n  }\n\n  const formatTimestamp = (timestamp: number) => {\n    const now = Date.now()\n    const diff = now - timestamp\n    const minutes = Math.floor(diff / 60000)\n    const hours = Math.floor(diff / 3600000)\n    const days = Math.floor(diff / 86400000)\n\n    if (minutes < 1) return 'Just now'\n    if (minutes < 60) return `${minutes}m ago`\n    if (hours < 24) return `${hours}h ago`\n    return `${days}d ago`\n  }\n\n  const formatDuration = (duration: number) => {\n    if (duration < 1000) return `${duration}ms`\n    return `${(duration / 1000).toFixed(2)}s`\n  }\n\n  return (\n    <div className=\"activity-feed\">\n      <h3 className=\"feed-title\">Recent Traces</h3>\n      {loading ? (\n        <div className=\"feed-loading\">\n          <div className=\"loading-spinner\"></div>\n          <p>Loading traces...</p>\n        </div>\n      ) : (\n        <div className=\"activity-list\">\n          {traces.map((trace) => (\n            <div key={trace.id} className={`activity-item ${getStatusClass(trace.status)}`}>\n              <div className=\"activity-icon\">{getStatusIcon(trace.status)}</div>\n              <div className=\"activity-content\">\n                <div className=\"activity-header\">\n                  <span className=\"activity-service\">{trace.service}</span>\n                  <span className=\"activity-time\">{formatTimestamp(trace.timestamp)}</span>\n                </div>\n                <p className=\"activity-message\">\n                  {trace.operation} - {formatDuration(trace.duration)} ({trace.spans.length} spans)\n                </p>\n              </div>\n            </div>\n          ))}\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/Dashboard.css",
    "content": ".dashboard {\n  padding: 24px;\n  max-width: 1400px;\n  margin: 0 auto;\n}\n\n.dashboard-title {\n  font-size: 28px;\n  font-weight: 700;\n  color: var(--color-text, #e0e0e0);\n  margin: 0 0 24px 0;\n}\n\n.metrics-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n  gap: 20px;\n  margin-bottom: 24px;\n}\n\n.metrics-grid-loading {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  min-height: 120px;\n  margin-bottom: 24px;\n  background: rgba(255, 255, 255, 0.05);\n  border-radius: 8px;\n  gap: 12px;\n}\n\n.metrics-grid-loading .loading-spinner {\n  width: 24px;\n  height: 24px;\n  border: 3px solid rgba(255, 255, 255, 0.1);\n  border-top-color: #42a5f5;\n  border-radius: 50%;\n  animation: spin 0.8s linear infinite;\n}\n\n.metrics-grid-loading p {\n  color: var(--color-text-secondary, #b0b0b0);\n  margin: 0;\n  font-size: 14px;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n\n.charts-section {\n  display: grid;\n  grid-template-columns: 2fr 1fr;\n  gap: 20px;\n  margin-bottom: 24px;\n}\n\n@media (max-width: 1024px) {\n  .charts-section {\n    grid-template-columns: 1fr;\n  }\n}\n\n.content-grid {\n  display: grid;\n  grid-template-columns: 2fr 1fr;\n  gap: 20px;\n}\n\n@media (max-width: 1024px) {\n  .content-grid {\n    grid-template-columns: 1fr;\n  }\n}\n\n.loading-state,\n.error-state {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  min-height: 400px;\n  font-size: 18px;\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.error-state {\n  color: var(--color-error, #ff5252);\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/Dashboard.tsx",
    "content": "import { useMemo } from 'react'\nimport { useData } from '../../hooks/useData'\nimport MetricCard from './MetricCard'\nimport TimeSeriesChart from './TimeSeriesChart'\nimport ServiceStatusPieChart from './ServiceStatusPieChart'\nimport ServiceGrid from './ServiceGrid'\nimport ActivityFeed from './ActivityFeed'\nimport { LogsData, TracesData } from '../../types/data'\nimport './Dashboard.css'\nimport { heavyComputation } from '../../utils/performanceThrottle'\n\ninterface MetricsData {\n  summary: {\n    apm_requests: number\n    logs_count: number\n    infrastructure_hosts: number\n    errors_count: number\n    avg_response_time: number\n    p95_response_time: number\n  }\n  timeseries: Array<{\n    timestamp: number\n    requests: number\n    errors: number\n    latency: number\n  }>\n  services: Array<{\n    name: string\n    status: 'healthy' | 'warning' | 'critical'\n    requests: number\n    errors: number\n    avgLatency: number\n  }>\n  activity: Array<{\n    id: number\n    type: 'alert' | 'deployment' | 'incident'\n    severity: 'critical' | 'warning' | 'info'\n    service: string\n    message: string\n    timestamp: number\n  }>\n}\n\nexport default function Dashboard() {\n  const { data: metricsData, loading: timeseriesLoading } = useData<MetricsData>('/data/metrics.json', 10)\n  const { data: logsData, loading: pieChartLoading } = useData<LogsData>('/data/logs.json', 20)\n  const { data: metricsData2, loading: servicesLoading } = useData<MetricsData>('/data/metrics.json', 50)\n  const { data: tracesData, loading: activityLoading } = useData<TracesData>('/data/traces.json', 25)\n\n  // Extract timeseries data from the first fetch\n  const timeseriesData = metricsData?.timeseries || []\n\n  // Extract logs data for pie chart from the second fetch\n  const logs = logsData?.logs || []\n\n  // Extract services data from the third fetch\n  const servicesData = metricsData2?.services || []\n\n  // Extract traces data from the fourth fetch\n  const traces = tracesData?.traces || []\n\n  // Heavy computation on data processing (simulates expensive data transformations)\n  const processedTimeseries = useMemo(() => {\n    if (!timeseriesData || timeseriesData.length === 0) return []\n    console.log('[Performance] Processing timeseries data with heavy computation')\n    return timeseriesData\n  }, [timeseriesData])\n\n  // Compute metrics from services data\n  const computedMetrics = useMemo(() => {\n    if (!servicesData || servicesData.length === 0 || !timeseriesData || timeseriesData.length === 0) return null\n\n    // Calculate total requests and errors from services\n    const totalRequests = servicesData.reduce((sum, service) => sum + service.requests, 0)\n    const totalErrors = servicesData.reduce((sum, service) => sum + service.errors, 0)\n\n    // Calculate average latency weighted by request count\n    const totalWeightedLatency = servicesData.reduce((sum, service) => sum + service.avgLatency * service.requests, 0)\n    const avgResponseTime = Math.round(totalWeightedLatency / totalRequests)\n\n    // Calculate p95 latency (approximate from highest service latencies)\n    const sortedLatencies = servicesData.map((s) => s.avgLatency).sort((a, b) => b - a)\n    const p95Index = Math.ceil(sortedLatencies.length * 0.05)\n    const p95ResponseTime = sortedLatencies[p95Index] || sortedLatencies[0]\n\n    // Count number of hosts (services in this case)\n    const infrastructureHosts = servicesData.length\n\n    heavyComputation([totalRequests], 200)\n    return {\n      apm_requests: totalRequests,\n      logs_count: logs.length,\n      infrastructure_hosts: infrastructureHosts,\n      errors_count: totalErrors,\n      avg_response_time: avgResponseTime,\n      p95_response_time: p95ResponseTime,\n    }\n  }, [servicesData, timeseriesData, logs])\n\n  // Compute log level distribution for pie chart\n  const logLevelData = useMemo(() => {\n    if (!logs || logs.length === 0) return []\n\n    const levelCounts = logs.reduce(\n      (acc, log) => {\n        acc[log.level] = (acc[log.level] || 0) + 1\n        return acc\n      },\n      {} as Record<string, number>\n    )\n\n    const colors = {\n      ERROR: '#FF5252',\n      WARN: '#FFA726',\n      INFO: '#42A5F5',\n      DEBUG: '#66BB6A',\n    }\n\n    return Object.entries(levelCounts).map(([level, count]) => ({\n      name: level,\n      value: count,\n      color: colors[level as keyof typeof colors] || '#999',\n    }))\n  }, [logs])\n\n  return (\n    <div className=\"dashboard\">\n      <h1 className=\"dashboard-title\">Dashboard</h1>\n\n      {/* Metrics appear after chart, responsible for CLS */}\n      {computedMetrics && (\n        <div className=\"metrics-grid\">\n          <MetricCard title=\"APM Requests\" value={computedMetrics.apm_requests} trend=\"up\" />\n          <MetricCard title=\"Logs Count\" value={computedMetrics.logs_count} trend=\"up\" />\n          <MetricCard title=\"Infrastructure Hosts\" value={computedMetrics.infrastructure_hosts} />\n          <MetricCard title=\"Errors\" value={computedMetrics.errors_count} trend=\"down\" />\n          <MetricCard title=\"Avg Response Time\" value={computedMetrics.avg_response_time} unit=\"ms\" />\n          <MetricCard title=\"P95 Response Time\" value={computedMetrics.p95_response_time} unit=\"ms\" />\n        </div>\n      )}\n\n      <div className=\"charts-section\">\n        <TimeSeriesChart data={processedTimeseries} loading={timeseriesLoading} />\n        <ServiceStatusPieChart data={logLevelData} loading={pieChartLoading} />\n      </div>\n\n      <div className=\"content-grid\">\n        <ServiceGrid services={servicesData} loading={servicesLoading} />\n        <ActivityFeed traces={traces} loading={activityLoading} />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/MetricCard.css",
    "content": ".metric-card {\n  background: var(--color-surface, #2a2a2a);\n  border-radius: 8px;\n  padding: 24px;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n  transition:\n    transform 0.2s ease,\n    box-shadow 0.2s ease;\n}\n\n.metric-card:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);\n}\n\n.metric-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 16px;\n}\n\n.metric-title {\n  font-size: 14px;\n  font-weight: 500;\n  color: var(--color-text-secondary, #b0b0b0);\n  margin: 0;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.metric-value {\n  font-size: 32px;\n  font-weight: 700;\n  color: var(--color-text, #e0e0e0);\n  line-height: 1.2;\n}\n\n.metric-unit {\n  font-size: 18px;\n  font-weight: 400;\n  color: var(--color-text-secondary, #b0b0b0);\n  margin-left: 8px;\n}\n\n.metric-trend {\n  font-size: 20px;\n  font-weight: bold;\n}\n\n.metric-trend-up {\n  color: var(--color-success, #3ebf62);\n}\n\n.metric-trend-down {\n  color: var(--color-error, #ff5252);\n}\n\n.metric-trend-neutral {\n  color: var(--color-warning, #ffa726);\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/MetricCard.tsx",
    "content": "import './MetricCard.css'\n\ninterface MetricCardProps {\n  title: string\n  value: number | string\n  unit?: string\n  trend?: 'up' | 'down' | 'neutral'\n}\n\nexport default function MetricCard({ title, value, unit, trend }: MetricCardProps) {\n  const formatValue = (val: number | string) => {\n    if (typeof val === 'number') {\n      if (val >= 1000000) {\n        return `${(val / 1000000).toFixed(2)}M`\n      }\n      if (val >= 1000) {\n        return `${(val / 1000).toFixed(1)}K`\n      }\n      return val.toLocaleString()\n    }\n    return val\n  }\n\n  return (\n    <div className=\"metric-card\">\n      <div className=\"metric-header\">\n        <h3 className=\"metric-title\">{title}</h3>\n        {trend && (\n          <span className={`metric-trend metric-trend-${trend}`}>\n            {trend === 'up' ? '↑' : trend === 'down' ? '↓' : '→'}\n          </span>\n        )}\n      </div>\n      <div className=\"metric-value\">\n        {formatValue(value)}\n        {unit && <span className=\"metric-unit\">{unit}</span>}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/ServiceGrid.css",
    "content": ".service-grid {\n  background: var(--color-surface, #2a2a2a);\n  border-radius: 8px;\n  padding: 24px;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n.grid-title {\n  font-size: 18px;\n  font-weight: 600;\n  color: var(--color-text, #e0e0e0);\n  margin: 0 0 20px 0;\n}\n\n.grid-container {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n  gap: 16px;\n}\n\n.service-card {\n  background: var(--color-bg, #1e1e1e);\n  border: 1px solid #444;\n  border-radius: 6px;\n  padding: 16px;\n  transition: border-color 0.2s ease;\n}\n\n.service-card:hover {\n  border-color: var(--color-primary, #632ca6);\n}\n\n.service-header {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 12px;\n}\n\n.service-status-dot {\n  width: 10px;\n  height: 10px;\n  border-radius: 50%;\n  flex-shrink: 0;\n}\n\n.service-name {\n  font-size: 14px;\n  font-weight: 600;\n  color: var(--color-text, #e0e0e0);\n  margin: 0;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.service-metrics {\n  display: flex;\n  flex-direction: column;\n  gap: 6px;\n}\n\n.service-metric {\n  display: flex;\n  justify-content: space-between;\n  font-size: 12px;\n}\n\n.metric-label {\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.metric-val {\n  color: var(--color-text, #e0e0e0);\n  font-weight: 500;\n}\n\n.grid-loading {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  min-height: 400px;\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.grid-loading p {\n  margin-top: 16px;\n  font-size: 14px;\n}\n\n.grid-loading .loading-spinner {\n  width: 40px;\n  height: 40px;\n  border: 4px solid rgba(255, 255, 255, 0.1);\n  border-top-color: #3ebf62;\n  border-radius: 50%;\n  animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/ServiceGrid.tsx",
    "content": "import './ServiceGrid.css'\n\ninterface Service {\n  name: string\n  status: 'healthy' | 'warning' | 'critical'\n  requests: number\n  errors: number\n  avgLatency: number\n}\n\ninterface ServiceGridProps {\n  services: Service[]\n  loading?: boolean\n}\n\nexport default function ServiceGrid({ services, loading = false }: ServiceGridProps) {\n  const getStatusColor = (status: string) => {\n    switch (status) {\n      case 'healthy':\n        return 'var(--color-success, #3EBF62)'\n      case 'warning':\n        return 'var(--color-warning, #FFA726)'\n      case 'critical':\n        return 'var(--color-error, #FF5252)'\n      default:\n        return 'var(--color-text-secondary, #B0B0B0)'\n    }\n  }\n\n  const formatNumber = (num: number) => {\n    if (num >= 1000) {\n      return `${(num / 1000).toFixed(1)}K`\n    }\n    return num.toString()\n  }\n\n  return (\n    <div className=\"service-grid\">\n      <h3 className=\"grid-title\">Service Health</h3>\n      {loading ? (\n        <div className=\"grid-loading\">\n          <div className=\"loading-spinner\"></div>\n          <p>Loading services...</p>\n        </div>\n      ) : (\n        <div className=\"grid-container\">\n          {services.map((service) => (\n            <div key={service.name} className=\"service-card\">\n              <div className=\"service-header\">\n                <span className=\"service-status-dot\" style={{ backgroundColor: getStatusColor(service.status) }} />\n                <h4 className=\"service-name\">{service.name}</h4>\n              </div>\n              <div className=\"service-metrics\">\n                <div className=\"service-metric\">\n                  <span className=\"metric-label\">Requests:</span>\n                  <span className=\"metric-val\">{formatNumber(service.requests)}</span>\n                </div>\n                <div className=\"service-metric\">\n                  <span className=\"metric-label\">Errors:</span>\n                  <span className=\"metric-val\">{service.errors}</span>\n                </div>\n                <div className=\"service-metric\">\n                  <span className=\"metric-label\">Latency:</span>\n                  <span className=\"metric-val\">{service.avgLatency}ms</span>\n                </div>\n              </div>\n            </div>\n          ))}\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/ServiceStatusPieChart.css",
    "content": ".service-status-pie-chart {\n  background-color: #1e1e1e;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.service-status-pie-chart .chart-title {\n  margin: 0 0 20px 0;\n  font-size: 16px;\n  font-weight: 600;\n  color: #e0e0e0;\n}\n\n.service-status-pie-chart .chart-loading {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  height: 300px;\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.service-status-pie-chart .chart-loading p {\n  margin-top: 16px;\n  font-size: 14px;\n}\n\n.service-status-pie-chart .loading-spinner {\n  width: 40px;\n  height: 40px;\n  border: 4px solid rgba(255, 255, 255, 0.1);\n  border-top-color: #ffa726;\n  border-radius: 50%;\n  animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/ServiceStatusPieChart.tsx",
    "content": "import { PieChart, Pie, Cell, ResponsiveContainer, Legend, Tooltip } from 'recharts'\nimport './ServiceStatusPieChart.css'\n\ninterface LogLevelData {\n  name: string\n  value: number\n  color: string\n  [key: string]: unknown\n}\n\ninterface ServiceStatusPieChartProps {\n  data: LogLevelData[]\n  loading?: boolean\n}\n\nexport default function ServiceStatusPieChart({ data, loading = false }: ServiceStatusPieChartProps) {\n  return (\n    <div className=\"service-status-pie-chart\">\n      <h3 className=\"chart-title\">Log Level Distribution</h3>\n      {loading ? (\n        <div className=\"chart-loading\">\n          <div className=\"loading-spinner\"></div>\n          <p>Loading status data...</p>\n        </div>\n      ) : (\n        <ResponsiveContainer width=\"100%\" height={300}>\n          <PieChart>\n            <Pie\n              data={data}\n              cx=\"50%\"\n              cy=\"50%\"\n              labelLine={false}\n              label={({ name, percent }) => `${name}: ${((percent ?? 0) * 100).toFixed(0)}%`}\n              outerRadius={80}\n              fill=\"#8884d8\"\n              dataKey=\"value\"\n            >\n              {data.map((entry, index) => (\n                <Cell key={`cell-${index}`} fill={entry.color} />\n              ))}\n            </Pie>\n            <Tooltip\n              contentStyle={{\n                backgroundColor: '#2A2A2A',\n                border: '1px solid #444',\n                borderRadius: '4px',\n                color: '#E0E0E0',\n              }}\n            />\n            <Legend wrapperStyle={{ color: '#E0E0E0' }} />\n          </PieChart>\n        </ResponsiveContainer>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/TimeSeriesChart.css",
    "content": ".timeseries-chart {\n  background: var(--color-surface, #2a2a2a);\n  border-radius: 8px;\n  padding: 24px;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n.chart-title {\n  font-size: 18px;\n  font-weight: 600;\n  color: var(--color-text, #e0e0e0);\n  margin: 0 0 20px 0;\n}\n\n.chart-loading {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  height: 300px;\n  color: var(--color-text-secondary, #b0b0b0);\n}\n\n.chart-loading p {\n  margin-top: 16px;\n  font-size: 14px;\n}\n\n.loading-spinner {\n  width: 40px;\n  height: 40px;\n  border: 4px solid rgba(255, 255, 255, 0.1);\n  border-top-color: #632ca6;\n  border-radius: 50%;\n  animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Dashboard/TimeSeriesChart.tsx",
    "content": "import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'\nimport './TimeSeriesChart.css'\n\ninterface TimeSeriesData {\n  timestamp: number\n  requests: number\n  errors: number\n  latency: number\n}\n\ninterface TimeSeriesChartProps {\n  data: TimeSeriesData[]\n  loading?: boolean\n}\n\nexport default function TimeSeriesChart({ data, loading = false }: TimeSeriesChartProps) {\n  const formatTimestamp = (label: React.ReactNode): string => {\n    if (typeof label !== 'number') throw new Error('Unexpected label')\n\n    // Convert label to number (it will be the timestamp value from data)\n    const timestamp = Number(label)\n    const date = new Date(timestamp)\n    return date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })\n  }\n\n  return (\n    <div className=\"timeseries-chart\">\n      <h3 className=\"chart-title\">Request Metrics Over Time</h3>\n      {loading ? (\n        <div className=\"chart-loading\">\n          <div className=\"loading-spinner\"></div>\n          <p>Loading chart data...</p>\n        </div>\n      ) : (\n        <ResponsiveContainer width=\"100%\" height={300}>\n          <LineChart data={data} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>\n            <CartesianGrid strokeDasharray=\"3 3\" stroke=\"#444\" />\n            <XAxis dataKey=\"timestamp\" tickFormatter={formatTimestamp} stroke=\"#B0B0B0\" style={{ fontSize: '12px' }} />\n            <YAxis stroke=\"#B0B0B0\" style={{ fontSize: '12px' }} />\n            <Tooltip\n              contentStyle={{\n                backgroundColor: '#2A2A2A',\n                border: '1px solid #444',\n                borderRadius: '4px',\n                color: '#E0E0E0',\n              }}\n              labelFormatter={formatTimestamp}\n            />\n            <Legend wrapperStyle={{ color: '#E0E0E0' }} />\n            <Line type=\"monotone\" dataKey=\"requests\" stroke=\"#632CA6\" strokeWidth={2} dot={false} name=\"Requests\" />\n            <Line type=\"monotone\" dataKey=\"errors\" stroke=\"#FF5252\" strokeWidth={2} dot={false} name=\"Errors\" />\n            <Line type=\"monotone\" dataKey=\"latency\" stroke=\"#3EBF62\" strokeWidth={2} dot={false} name=\"Latency (ms)\" />\n          </LineChart>\n        </ResponsiveContainer>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/HostDetails.css",
    "content": ".host-details {\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  display: flex;\n  flex-direction: column;\n  overflow: hidden;\n  height: 100%;\n}\n\n.host-details-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: var(--spacing-lg);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.host-details-title {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-md);\n}\n\n.host-details-title h3 {\n  margin: 0;\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  color: var(--color-text);\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n}\n\n.close-btn {\n  background: none;\n  border: none;\n  color: var(--color-text-secondary);\n  cursor: pointer;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  transition: all 0.2s ease;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.close-btn:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n.close-btn svg {\n  width: 20px;\n  height: 20px;\n}\n\n.host-details-summary {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n  gap: var(--spacing-md);\n  padding: var(--spacing-lg);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.summary-item {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-xs);\n}\n\n.summary-label {\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n  font-weight: 600;\n}\n\n.summary-value {\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n}\n\n.summary-value.cpu {\n  color: #42a5f5;\n}\n\n.summary-value.memory {\n  color: #ffa726;\n}\n\n.summary-value.disk {\n  color: #66bb6a;\n}\n\n.summary-value.network {\n  color: #ab47bc;\n}\n\n.summary-value.uptime {\n  color: var(--color-text);\n}\n\n.host-details-charts {\n  flex: 1;\n  padding: var(--spacing-lg);\n  overflow-y: auto;\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n  gap: var(--spacing-lg);\n}\n\n.chart-container {\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-md);\n  min-height: 250px;\n}\n\n.chart-container h4 {\n  margin: 0 0 var(--spacing-md) 0;\n  font-size: var(--font-size-md);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.chart-wrapper {\n  height: 200px;\n  position: relative;\n}\n\n.status-badge {\n  display: inline-block;\n  padding: 4px 12px;\n  border-radius: 4px;\n  font-size: var(--font-size-xs);\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.status-badge.healthy {\n  background: rgba(62, 191, 98, 0.2);\n  color: #3ebf62;\n}\n\n.status-badge.warning {\n  background: rgba(255, 167, 38, 0.2);\n  color: #ffa726;\n}\n\n.status-badge.critical {\n  background: rgba(255, 82, 82, 0.2);\n  color: #ff5252;\n}\n\n@media (max-width: 1024px) {\n  .host-details-charts {\n    grid-template-columns: 1fr;\n  }\n}\n\n@media (max-width: 768px) {\n  .host-details-header {\n    padding: var(--spacing-md);\n  }\n\n  .host-details-summary {\n    grid-template-columns: repeat(2, 1fr);\n    padding: var(--spacing-md);\n  }\n\n  .host-details-charts {\n    padding: var(--spacing-md);\n    gap: var(--spacing-md);\n  }\n\n  .chart-container {\n    min-height: 200px;\n  }\n\n  .chart-wrapper {\n    height: 150px;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/HostDetails.tsx",
    "content": "import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'\nimport { Host, HostMetricsTimeSeries } from '../../types/data'\nimport './HostDetails.css'\n\ninterface HostDetailsProps {\n  host: Host\n  metrics: HostMetricsTimeSeries\n  onClose: () => void\n}\n\nfunction formatUptime(seconds: number): string {\n  const days = Math.floor(seconds / 86400)\n  const hours = Math.floor((seconds % 86400) / 3600)\n  const minutes = Math.floor((seconds % 3600) / 60)\n\n  const parts = []\n  if (days > 0) parts.push(`${days}d`)\n  if (hours > 0) parts.push(`${hours}h`)\n  if (minutes > 0 || parts.length === 0) parts.push(`${minutes}m`)\n\n  return parts.join(' ')\n}\n\nfunction formatTimestamp(timestamp: number): string {\n  const date = new Date(timestamp)\n  return date.toLocaleTimeString('en-US', {\n    hour: '2-digit',\n    minute: '2-digit',\n    hour12: false,\n  })\n}\n\nexport default function HostDetails({ host, metrics, onClose }: HostDetailsProps) {\n  const cpuData = metrics.cpu.map((point) => ({\n    time: formatTimestamp(point.timestamp),\n    value: point.value,\n  }))\n\n  const memoryData = metrics.memory.map((point) => ({\n    time: formatTimestamp(point.timestamp),\n    value: point.value,\n  }))\n\n  const diskData = metrics.disk?.map((point) => ({\n    time: formatTimestamp(point.timestamp),\n    value: point.value,\n  }))\n\n  const networkData = metrics.network?.map((point) => ({\n    time: formatTimestamp(point.timestamp),\n    value: point.value,\n  }))\n\n  return (\n    <div className=\"host-details\">\n      <div className=\"host-details-header\">\n        <div className=\"host-details-title\">\n          <h3>{host.name}</h3>\n          <span className={`status-badge ${host.status}`}>{host.status}</span>\n        </div>\n        <button className=\"close-btn\" onClick={onClose} aria-label=\"Close details\">\n          <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n            <path\n              fillRule=\"evenodd\"\n              d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n              clipRule=\"evenodd\"\n            />\n          </svg>\n        </button>\n      </div>\n\n      <div className=\"host-details-summary\">\n        <div className=\"summary-item\">\n          <span className=\"summary-label\">CPU</span>\n          <span className=\"summary-value cpu\">{host.cpu}%</span>\n        </div>\n        <div className=\"summary-item\">\n          <span className=\"summary-label\">Memory</span>\n          <span className=\"summary-value memory\">{host.memory}%</span>\n        </div>\n        <div className=\"summary-item\">\n          <span className=\"summary-label\">Disk</span>\n          <span className=\"summary-value disk\">{host.disk}%</span>\n        </div>\n        <div className=\"summary-item\">\n          <span className=\"summary-label\">Network</span>\n          <span className=\"summary-value network\">{host.network} Mbps</span>\n        </div>\n        <div className=\"summary-item\">\n          <span className=\"summary-label\">Uptime</span>\n          <span className=\"summary-value uptime\">{formatUptime(host.uptime)}</span>\n        </div>\n      </div>\n\n      <div className=\"host-details-charts\">\n        <div className=\"chart-container\">\n          <h4>CPU Usage</h4>\n          <div className=\"chart-wrapper\">\n            <ResponsiveContainer width=\"100%\" height=\"100%\">\n              <LineChart data={cpuData}>\n                <CartesianGrid strokeDasharray=\"3 3\" stroke=\"rgba(255, 255, 255, 0.05)\" />\n                <XAxis dataKey=\"time\" stroke=\"#888888\" tick={{ fontSize: 10 }} interval=\"preserveStartEnd\" />\n                <YAxis\n                  stroke=\"#888888\"\n                  tick={{ fontSize: 10 }}\n                  domain={[0, 100]}\n                  tickFormatter={(value) => `${value}%`}\n                />\n                <Tooltip\n                  contentStyle={{\n                    backgroundColor: 'rgba(42, 42, 42, 0.95)',\n                    border: '1px solid #3A3A3A',\n                    borderRadius: '4px',\n                    color: '#E0E0E0',\n                  }}\n                  formatter={(value) => `${value ?? 0}%`}\n                />\n                <Line\n                  type=\"monotone\"\n                  dataKey=\"value\"\n                  stroke=\"#42a5f5\"\n                  strokeWidth={2}\n                  dot={false}\n                  activeDot={{ r: 4 }}\n                />\n              </LineChart>\n            </ResponsiveContainer>\n          </div>\n        </div>\n\n        <div className=\"chart-container\">\n          <h4>Memory Usage</h4>\n          <div className=\"chart-wrapper\">\n            <ResponsiveContainer width=\"100%\" height=\"100%\">\n              <LineChart data={memoryData}>\n                <CartesianGrid strokeDasharray=\"3 3\" stroke=\"rgba(255, 255, 255, 0.05)\" />\n                <XAxis dataKey=\"time\" stroke=\"#888888\" tick={{ fontSize: 10 }} interval=\"preserveStartEnd\" />\n                <YAxis\n                  stroke=\"#888888\"\n                  tick={{ fontSize: 10 }}\n                  domain={[0, 100]}\n                  tickFormatter={(value) => `${value}%`}\n                />\n                <Tooltip\n                  contentStyle={{\n                    backgroundColor: 'rgba(42, 42, 42, 0.95)',\n                    border: '1px solid #3A3A3A',\n                    borderRadius: '4px',\n                    color: '#E0E0E0',\n                  }}\n                  formatter={(value) => `${value ?? 0}%`}\n                />\n                <Line\n                  type=\"monotone\"\n                  dataKey=\"value\"\n                  stroke=\"#ffa726\"\n                  strokeWidth={2}\n                  dot={false}\n                  activeDot={{ r: 4 }}\n                />\n              </LineChart>\n            </ResponsiveContainer>\n          </div>\n        </div>\n\n        {diskData && (\n          <div className=\"chart-container\">\n            <h4>Disk Usage</h4>\n            <div className=\"chart-wrapper\">\n              <ResponsiveContainer width=\"100%\" height=\"100%\">\n                <LineChart data={diskData}>\n                  <CartesianGrid strokeDasharray=\"3 3\" stroke=\"rgba(255, 255, 255, 0.05)\" />\n                  <XAxis dataKey=\"time\" stroke=\"#888888\" tick={{ fontSize: 10 }} interval=\"preserveStartEnd\" />\n                  <YAxis\n                    stroke=\"#888888\"\n                    tick={{ fontSize: 10 }}\n                    domain={[0, 100]}\n                    tickFormatter={(value) => `${value}%`}\n                  />\n                  <Tooltip\n                    contentStyle={{\n                      backgroundColor: 'rgba(42, 42, 42, 0.95)',\n                      border: '1px solid #3A3A3A',\n                      borderRadius: '4px',\n                      color: '#E0E0E0',\n                    }}\n                    formatter={(value) => `${value ?? 0}%`}\n                  />\n                  <Line\n                    type=\"monotone\"\n                    dataKey=\"value\"\n                    stroke=\"#66bb6a\"\n                    strokeWidth={2}\n                    dot={false}\n                    activeDot={{ r: 4 }}\n                  />\n                </LineChart>\n              </ResponsiveContainer>\n            </div>\n          </div>\n        )}\n\n        {networkData && (\n          <div className=\"chart-container\">\n            <h4>Network Traffic</h4>\n            <div className=\"chart-wrapper\">\n              <ResponsiveContainer width=\"100%\" height=\"100%\">\n                <LineChart data={networkData}>\n                  <CartesianGrid strokeDasharray=\"3 3\" stroke=\"rgba(255, 255, 255, 0.05)\" />\n                  <XAxis dataKey=\"time\" stroke=\"#888888\" tick={{ fontSize: 10 }} interval=\"preserveStartEnd\" />\n                  <YAxis stroke=\"#888888\" tick={{ fontSize: 10 }} tickFormatter={(value) => `${value}`} />\n                  <Tooltip\n                    contentStyle={{\n                      backgroundColor: 'rgba(42, 42, 42, 0.95)',\n                      border: '1px solid #3A3A3A',\n                      borderRadius: '4px',\n                      color: '#E0E0E0',\n                    }}\n                    formatter={(value) => `${value ?? 0} Mbps`}\n                  />\n                  <Line\n                    type=\"monotone\"\n                    dataKey=\"value\"\n                    stroke=\"#ab47bc\"\n                    strokeWidth={2}\n                    dot={false}\n                    activeDot={{ r: 4 }}\n                  />\n                </LineChart>\n              </ResponsiveContainer>\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/HostList.css",
    "content": ".host-list {\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  display: flex;\n  flex-direction: column;\n  overflow: hidden;\n}\n\n.host-list-header {\n  padding: var(--spacing-lg);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.host-list-header h3 {\n  margin: 0 0 var(--spacing-md) 0;\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.host-list-controls {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-md);\n}\n\n.host-search {\n  width: 100%;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  color: var(--color-text);\n  font-size: var(--font-size-md);\n  font-family: var(--font-family);\n}\n\n.host-search:focus {\n  outline: none;\n  border-color: var(--color-primary);\n  box-shadow: 0 0 0 3px rgba(99, 44, 166, 0.1);\n}\n\n.status-filters {\n  display: flex;\n  gap: var(--spacing-sm);\n  flex-wrap: wrap;\n}\n\n.filter-btn {\n  padding: var(--spacing-xs) var(--spacing-sm);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text-secondary);\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.filter-btn:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n.filter-btn.active {\n  background: var(--color-primary);\n  border-color: var(--color-primary);\n  color: white;\n}\n\n.filter-btn.healthy.active {\n  background: #3ebf62;\n  border-color: #3ebf62;\n}\n\n.filter-btn.warning.active {\n  background: #ffa726;\n  border-color: #ffa726;\n}\n\n.filter-btn.critical.active {\n  background: #ff5252;\n  border-color: #ff5252;\n}\n\n.host-table-container {\n  flex: 1;\n  overflow-y: auto;\n  max-height: 600px;\n}\n\n.host-table {\n  width: 100%;\n  border-collapse: collapse;\n}\n\n.host-table thead {\n  position: sticky;\n  top: 0;\n  background: var(--color-surface-elevated);\n  z-index: 10;\n}\n\n.host-table th {\n  padding: var(--spacing-sm) var(--spacing-md);\n  text-align: left;\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n  color: var(--color-text-secondary);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n  border-bottom: 1px solid var(--color-border);\n  cursor: pointer;\n  user-select: none;\n}\n\n.host-table th:hover {\n  background: var(--color-surface-hover);\n}\n\n.th-content {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n}\n\n.sort-icon {\n  width: 16px;\n  height: 16px;\n  flex-shrink: 0;\n}\n\n.sort-icon.inactive {\n  opacity: 0.3;\n}\n\n.sort-icon.active {\n  opacity: 1;\n  color: var(--color-primary);\n}\n\n.host-table tbody tr {\n  border-bottom: 1px solid var(--color-border-light);\n  cursor: pointer;\n  transition: background 0.2s ease;\n}\n\n.host-table tbody tr:hover {\n  background: var(--color-surface-hover);\n}\n\n.host-table tbody tr.selected {\n  background: var(--color-primary-light);\n  border-left: 3px solid var(--color-primary);\n}\n\n.host-table td {\n  padding: var(--spacing-sm) var(--spacing-md);\n  font-size: var(--font-size-sm);\n  color: var(--color-text);\n}\n\n.host-name {\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  font-weight: 500;\n}\n\n.status-badge {\n  display: inline-block;\n  padding: 2px 8px;\n  border-radius: 3px;\n  font-size: var(--font-size-xs);\n  font-weight: 600;\n  text-transform: uppercase;\n}\n\n.status-badge.healthy {\n  background: rgba(62, 191, 98, 0.2);\n  color: #3ebf62;\n}\n\n.status-badge.warning {\n  background: rgba(255, 167, 38, 0.2);\n  color: #ffa726;\n}\n\n.status-badge.critical {\n  background: rgba(255, 82, 82, 0.2);\n  color: #ff5252;\n}\n\n.metric-cell {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n}\n\n.metric-bar {\n  flex: 1;\n  height: 6px;\n  background: var(--color-surface-elevated);\n  border-radius: 3px;\n  overflow: hidden;\n}\n\n.metric-fill {\n  height: 100%;\n  border-radius: 3px;\n  transition: width 0.3s ease;\n}\n\n.metric-fill.cpu {\n  background: #42a5f5;\n}\n\n.metric-fill.memory {\n  background: #ffa726;\n}\n\n.metric-fill.disk {\n  background: #66bb6a;\n}\n\n.metric-value {\n  min-width: 40px;\n  text-align: right;\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  font-size: var(--font-size-xs);\n}\n\n.network-cell,\n.uptime-cell {\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n}\n\n.host-list-footer {\n  padding: var(--spacing-sm) var(--spacing-lg);\n  background: var(--color-surface-elevated);\n  border-top: 1px solid var(--color-border);\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n@media (max-width: 1024px) {\n  .host-table {\n    font-size: var(--font-size-xs);\n  }\n\n  .host-table th,\n  .host-table td {\n    padding: var(--spacing-xs) var(--spacing-sm);\n  }\n}\n\n@media (max-width: 768px) {\n  .host-list-header {\n    padding: var(--spacing-md);\n  }\n\n  .status-filters {\n    gap: var(--spacing-xs);\n  }\n\n  .filter-btn {\n    font-size: var(--font-size-xs);\n    padding: 4px 8px;\n  }\n\n  .host-table-container {\n    max-height: 400px;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/HostList.tsx",
    "content": "import { useState, useMemo, useCallback, memo, Dispatch, SetStateAction } from 'react'\nimport { List, RowComponentProps } from 'react-window'\nimport { Host, HostStatus } from '../../types/data'\nimport './HostList.css'\n\ninterface HostListProps {\n  hosts: Host[]\n  filteredHosts: Host[]\n  selectedHost: Host | null\n  onHostSelect: (host: Host) => void\n  statusFilter: HostStatus | 'all'\n  setStatusFilter: Dispatch<SetStateAction<HostStatus | 'all'>>\n  searchQuery: string\n  setSearchQuery: Dispatch<SetStateAction<string>>\n}\n\ntype SortField = 'name' | 'status' | 'cpu' | 'memory' | 'disk' | 'network' | 'uptime'\ntype SortDirection = 'asc' | 'desc'\n\nfunction formatUptime(seconds: number): string {\n  const days = Math.floor(seconds / 86400)\n  const hours = Math.floor((seconds % 86400) / 3600)\n\n  if (days > 0) {\n    return `${days}d ${hours}h`\n  }\n  return `${hours}h`\n}\n\nfunction getStatusOrder(status: HostStatus): number {\n  const order = { critical: 0, warning: 1, healthy: 2 }\n  return order[status]\n}\n\n// Extract SortIcon as a separate memoized component\nconst SortIcon = memo(\n  ({ field, sortField, sortDirection }: { field: SortField; sortField: SortField; sortDirection: SortDirection }) => {\n    if (sortField !== field) {\n      return (\n        <svg className=\"sort-icon inactive\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n          <path d=\"M5 12a1 1 0 102 0V6.414l1.293 1.293a1 1 0 001.414-1.414l-3-3a1 1 0 00-1.414 0l-3 3a1 1 0 001.414 1.414L5 6.414V12zM15 8a1 1 0 10-2 0v5.586l-1.293-1.293a1 1 0 00-1.414 1.414l3 3a1 1 0 001.414 0l3-3a1 1 0 00-1.414-1.414L15 13.586V8z\" />\n        </svg>\n      )\n    }\n\n    return sortDirection === 'asc' ? (\n      <svg className=\"sort-icon active\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n        <path d=\"M3 3a1 1 0 000 2h11a1 1 0 100-2H3zM3 7a1 1 0 000 2h7a1 1 0 100-2H3zM3 11a1 1 0 100 2h4a1 1 0 100-2H3zM15 8a1 1 0 10-2 0v5.586l-1.293-1.293a1 1 0 00-1.414 1.414l3 3a1 1 0 001.414 0l3-3a1 1 0 00-1.414-1.414L15 13.586V8z\" />\n      </svg>\n    ) : (\n      <svg className=\"sort-icon active\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n        <path d=\"M3 3a1 1 0 000 2h11a1 1 0 100-2H3zM3 7a1 1 0 000 2h5a1 1 0 000-2H3zM3 11a1 1 0 100 2h4a1 1 0 100-2H3zM13 16a1 1 0 102 0v-5.586l1.293 1.293a1 1 0 001.414-1.414l-3-3a1 1 0 00-1.414 0l-3 3a1 1 0 101.414 1.414L13 10.414V16z\" />\n      </svg>\n    )\n  }\n)\n\ntype HostRowExtraProps = {\n  filteredAndSortedHosts: Host[]\n  selectedHost: Host | null\n  onHostSelect: (host: Host) => void\n}\n\nfunction HostRow({\n  filteredAndSortedHosts,\n  index,\n  style,\n  selectedHost,\n  onHostSelect,\n}: RowComponentProps<HostRowExtraProps>) {\n  const host = filteredAndSortedHosts[index]\n  const isSelected = selectedHost?.id === host.id\n  return (\n    <div style={style}>\n      <table className=\"host-table\" style={{ tableLayout: 'fixed', width: '100%' }}>\n        <tbody>\n          <tr className={`host-row ${isSelected ? 'selected' : ''}`} onClick={() => onHostSelect(host)}>\n            <td className=\"host-name\">{host.name}</td>\n            <td>\n              <span className={`status-badge ${host.status}`}>{host.status}</span>\n            </td>\n            <td>\n              <div className=\"metric-cell\">\n                <div className=\"metric-bar\">\n                  <div className=\"metric-fill cpu\" style={{ width: `${host.cpu}%` }} />\n                </div>\n                <span className=\"metric-value\">{host.cpu}%</span>\n              </div>\n            </td>\n            <td>\n              <div className=\"metric-cell\">\n                <div className=\"metric-bar\">\n                  <div className=\"metric-fill memory\" style={{ width: `${host.memory}%` }} />\n                </div>\n                <span className=\"metric-value\">{host.memory}%</span>\n              </div>\n            </td>\n            <td>\n              <div className=\"metric-cell\">\n                <div className=\"metric-bar\">\n                  <div className=\"metric-fill disk\" style={{ width: `${host.disk}%` }} />\n                </div>\n                <span className=\"metric-value\">{host.disk}%</span>\n              </div>\n            </td>\n            <td className=\"network-cell\">{host.network} Mbps</td>\n            <td className=\"uptime-cell\">{formatUptime(host.uptime)}</td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n  )\n}\n\nconst HostList = memo(function HostList({\n  hosts,\n  filteredHosts,\n  selectedHost,\n  onHostSelect,\n  statusFilter,\n  setStatusFilter,\n  searchQuery,\n  setSearchQuery,\n}: HostListProps) {\n  const [sortField, setSortField] = useState<SortField>('name')\n  const [sortDirection, setSortDirection] = useState<SortDirection>('asc')\n\n  const handleSort = useCallback(\n    (field: SortField) => {\n      if (sortField === field) {\n        setSortDirection((prev) => (prev === 'asc' ? 'desc' : 'asc'))\n      } else {\n        setSortField(field)\n        setSortDirection('asc')\n      }\n    },\n    [sortField]\n  )\n\n  const filteredAndSortedHosts = useMemo(() => {\n    console.log('[Performance] Sorting hosts with heavy computation (HostList)')\n\n    // Apply sorting to already-filtered hosts\n    const sorted = [...filteredHosts].sort((a, b) => {\n      let comparison = 0\n\n      switch (sortField) {\n        case 'name':\n          comparison = a.name.localeCompare(b.name)\n          break\n        case 'status':\n          comparison = getStatusOrder(a.status) - getStatusOrder(b.status)\n          break\n        case 'cpu':\n          comparison = a.cpu - b.cpu\n          break\n        case 'memory':\n          comparison = a.memory - b.memory\n          break\n        case 'disk':\n          comparison = a.disk - b.disk\n          break\n        case 'network':\n          comparison = a.network - b.network\n          break\n        case 'uptime':\n          comparison = a.uptime - b.uptime\n          break\n      }\n\n      return sortDirection === 'asc' ? comparison : -comparison\n    })\n\n    return sorted\n  }, [filteredHosts, sortField, sortDirection])\n\n  const statusCounts = useMemo(() => {\n    return {\n      all: hosts.length,\n      healthy: hosts.filter((h) => h.status === 'healthy').length,\n      warning: hosts.filter((h) => h.status === 'warning').length,\n      critical: hosts.filter((h) => h.status === 'critical').length,\n    }\n  }, [hosts])\n\n  return (\n    <div className=\"host-list\">\n      <div className=\"host-list-header\">\n        <h3>Host List</h3>\n        <div className=\"host-list-controls\">\n          <input\n            type=\"text\"\n            className=\"host-search\"\n            placeholder=\"Search hosts...\"\n            value={searchQuery}\n            onChange={(e) => setSearchQuery(e.target.value)}\n          />\n          <div className=\"status-filters\">\n            <button\n              className={`filter-btn ${statusFilter === 'all' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('all')}\n            >\n              All ({statusCounts.all})\n            </button>\n            <button\n              className={`filter-btn healthy ${statusFilter === 'healthy' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('healthy')}\n            >\n              Healthy ({statusCounts.healthy})\n            </button>\n            <button\n              className={`filter-btn warning ${statusFilter === 'warning' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('warning')}\n            >\n              Warning ({statusCounts.warning})\n            </button>\n            <button\n              className={`filter-btn critical ${statusFilter === 'critical' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('critical')}\n            >\n              Critical ({statusCounts.critical})\n            </button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"host-table-container\">\n        <table className=\"host-table\">\n          <thead>\n            <tr>\n              <th onClick={() => handleSort('name')}>\n                <div className=\"th-content\">\n                  Name <SortIcon field=\"name\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n              <th onClick={() => handleSort('status')}>\n                <div className=\"th-content\">\n                  Status <SortIcon field=\"status\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n              <th onClick={() => handleSort('cpu')}>\n                <div className=\"th-content\">\n                  CPU <SortIcon field=\"cpu\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n              <th onClick={() => handleSort('memory')}>\n                <div className=\"th-content\">\n                  Memory <SortIcon field=\"memory\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n              <th onClick={() => handleSort('disk')}>\n                <div className=\"th-content\">\n                  Disk <SortIcon field=\"disk\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n              <th onClick={() => handleSort('network')}>\n                <div className=\"th-content\">\n                  Network <SortIcon field=\"network\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n              <th onClick={() => handleSort('uptime')}>\n                <div className=\"th-content\">\n                  Uptime <SortIcon field=\"uptime\" sortField={sortField} sortDirection={sortDirection} />\n                </div>\n              </th>\n            </tr>\n          </thead>\n        </table>\n        <div style={{ height: 'calc(100vh - 350px)', overflow: 'auto' }}>\n          <List<HostRowExtraProps>\n            rowCount={filteredAndSortedHosts.length}\n            rowComponent={HostRow}\n            rowHeight={45}\n            overscanCount={5}\n            rowProps={{\n              filteredAndSortedHosts,\n              selectedHost,\n              onHostSelect,\n            }}\n          />\n        </div>\n      </div>\n\n      <div className=\"host-list-footer\">\n        Showing {filteredAndSortedHosts.length} of {hosts.length} hosts\n      </div>\n    </div>\n  )\n})\n\nexport default HostList\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/HostMap.css",
    "content": ".host-map {\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-lg);\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  overflow: hidden;\n}\n\n.host-map-header {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-md);\n  margin-bottom: var(--spacing-lg);\n}\n\n.host-map-header h3 {\n  margin: 0;\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.host-list-controls {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-md);\n}\n\n.host-search {\n  width: 100%;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  color: var(--color-text);\n  font-size: var(--font-size-md);\n  font-family: var(--font-family);\n}\n\n.host-search:focus {\n  outline: none;\n  border-color: var(--color-primary);\n  box-shadow: 0 0 0 3px rgba(99, 44, 166, 0.1);\n}\n\n.status-filters {\n  display: flex;\n  gap: var(--spacing-sm);\n  flex-wrap: wrap;\n}\n\n.filter-btn {\n  padding: var(--spacing-xs) var(--spacing-sm);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text-secondary);\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.filter-btn:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n.filter-btn.active {\n  background: var(--color-primary);\n  border-color: var(--color-primary);\n  color: white;\n}\n\n.filter-btn.healthy.active {\n  background: #3ebf62;\n  border-color: #3ebf62;\n}\n\n.filter-btn.warning.active {\n  background: #ffa726;\n  border-color: #ffa726;\n}\n\n.filter-btn.critical.active {\n  background: #ff5252;\n  border-color: #ff5252;\n}\n\n.host-map-legend {\n  display: flex;\n  gap: var(--spacing-md);\n}\n\n.legend-item {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n.legend-dot {\n  width: 12px;\n  height: 12px;\n  border-radius: 2px;\n}\n\n.legend-dot.healthy {\n  background-color: #3ebf62;\n}\n\n.legend-dot.warning {\n  background-color: #ffa726;\n}\n\n.legend-dot.critical {\n  background-color: #ff5252;\n}\n\n.host-map-grid {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-lg);\n  overflow-y: auto;\n  flex: 1;\n}\n\n.host-map-footer {\n  margin-top: var(--spacing-md);\n  padding-top: var(--spacing-md);\n  border-top: 1px solid var(--color-border);\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n.host-category {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-sm);\n  margin-bottom: var(--spacing-md);\n}\n\n.category-wrapper {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: var(--spacing-xs) var(--spacing-sm);\n  background: var(--color-surface-elevated);\n  border-radius: 4px;\n}\n\n.category-label-container {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-md);\n}\n\n.category-label {\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n  color: var(--color-text);\n  text-transform: uppercase;\n  min-width: 80px;\n}\n\n.category-stats {\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n  display: flex;\n  gap: var(--spacing-md);\n}\n\n.category-stat {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n}\n\n.category-hosts-wrapper {\n  flex: 1;\n}\n\n.category-hosts {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, 12px);\n  gap: 3px;\n  padding: var(--spacing-xs) 0;\n}\n\n.host-cell-wrapper {\n  display: contents;\n}\n\n.host-cell-container {\n  display: contents;\n}\n\n.host-cell {\n  position: relative;\n  width: 12px;\n  height: 12px;\n  border-radius: 2px;\n  cursor: pointer;\n  outline: none;\n  border: none;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  overflow: visible;\n}\n\n.host-cell::before {\n  content: '';\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 12px;\n  height: 12px;\n  border-radius: 2px;\n  background: inherit;\n  animation: inherit;\n  transition: all 0.2s ease;\n}\n\n.host-cell:hover::before {\n  width: 120px;\n  height: 90px;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  z-index: 100;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);\n  border-radius: 6px;\n}\n\n.host-cell:focus::before {\n  width: 120px;\n  height: 90px;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  z-index: 100;\n  box-shadow: 0 0 0 2px rgba(99, 44, 166, 0.5);\n  border-radius: 6px;\n}\n\n.host-cell.healthy {\n  background-color: #3ebf62;\n}\n\n.host-cell.warning {\n  background-color: #ffa726;\n}\n\n.host-cell.critical {\n  background-color: #ff5252;\n  animation: pulse-critical-dot 2s ease-in-out infinite;\n}\n\n.host-cell.selected {\n  outline: 2px solid var(--color-primary);\n  outline-offset: 1px;\n  transform: scale(1.3);\n  z-index: 11;\n}\n\n.host-cell:hover .host-cell-content,\n.host-cell:focus .host-cell-content {\n  display: flex;\n  flex-direction: column;\n  padding: var(--spacing-xs);\n  width: 120px;\n  height: 90px;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  background: linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.5) 100%);\n  justify-content: space-between;\n  z-index: 101;\n  border-radius: 6px;\n}\n\n.host-cell-content {\n  display: none;\n}\n\n.host-cell-header {\n  width: 100%;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 2px;\n}\n\n.host-cell-label-wrapper {\n  display: flex;\n  align-items: center;\n}\n\n.host-cell-label {\n  font-size: 10px;\n  font-weight: 700;\n  color: white;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.host-cell-body {\n  width: 100%;\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n}\n\n.host-cell-status {\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  gap: 3px;\n}\n\n.status-bar-wrapper {\n  width: 100%;\n  display: flex;\n  align-items: center;\n  gap: 4px;\n}\n\n.status-bar-label {\n  font-size: 8px;\n  font-weight: 600;\n  color: rgba(255, 255, 255, 0.9);\n  text-transform: uppercase;\n  min-width: 18px;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n.status-bar {\n  height: 8px;\n  flex: 1;\n  border-radius: 4px;\n  background: rgba(0, 0, 0, 0.4);\n  position: relative;\n  overflow: hidden;\n}\n\n.status-bar-inner {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  height: 100%;\n  border-radius: 4px;\n  transition: width 0.3s ease;\n}\n\n.status-bar.cpu .status-bar-inner {\n  background: rgba(66, 165, 245, 0.9);\n}\n\n.status-bar.memory .status-bar-inner {\n  background: rgba(255, 167, 38, 0.9);\n}\n\n.status-bar.disk .status-bar-inner {\n  background: rgba(102, 187, 106, 0.9);\n}\n\n.status-bar-value {\n  font-size: 8px;\n  font-weight: 700;\n  color: white;\n  min-width: 24px;\n  text-align: right;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n@keyframes pulse-critical {\n  0%,\n  100% {\n    box-shadow: 0 0 0 0 rgba(255, 82, 82, 0.4);\n  }\n  50% {\n    box-shadow: 0 0 0 8px rgba(255, 82, 82, 0);\n  }\n}\n\n@keyframes pulse-critical-dot {\n  0%,\n  100% {\n    box-shadow: 0 0 0 0 rgba(255, 82, 82, 0.7);\n  }\n  50% {\n    box-shadow: 0 0 0 4px rgba(255, 82, 82, 0);\n  }\n}\n\n@media (max-width: 1024px) {\n  .host-category {\n    flex-direction: column;\n  }\n\n  .category-label {\n    min-width: auto;\n  }\n}\n\n@media (max-width: 768px) {\n  .host-map-header {\n    flex-direction: column;\n    align-items: flex-start;\n    gap: var(--spacing-sm);\n  }\n\n  .host-cell {\n    width: 60px;\n    height: 60px;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/HostMap.tsx",
    "content": "import React, { Dispatch, SetStateAction } from 'react'\nimport { Host, HostStatus } from '../../types/data'\nimport './HostMap.css'\n\ninterface HostMapProps {\n  hosts: Host[]\n  filteredHosts: Host[]\n  selectedHost: Host | null\n  onHostSelect: (host: Host) => void\n  statusFilter: HostStatus | 'all'\n  setStatusFilter: Dispatch<SetStateAction<HostStatus | 'all'>>\n  searchQuery: string\n  setSearchQuery: Dispatch<SetStateAction<string>>\n}\n\nfunction getHostCategory(name: string): string {\n  // Extract the middle part (e.g., \"prod-web-01\" -> \"web\")\n  const parts = name.split('-')\n  return parts.slice(1, -1).join('-')\n}\n\nfunction formatHostName(name: string): string {\n  // Extract the last part after the last hyphen (e.g., \"prod-web-01\" -> \"01\")\n  const parts = name.split('-')\n  return parts[parts.length - 1]\n}\n\n// Memoized host cell component for better performance\nconst HostCell = React.memo(\n  ({ host, isSelected, onSelect }: { host: Host; isSelected: boolean; onSelect: (host: Host) => void }) => (\n    <div\n      className={`host-cell ${host.status} ${isSelected ? 'selected' : ''}`}\n      onClick={() => onSelect(host)}\n      role=\"button\"\n      tabIndex={0}\n      onKeyDown={(e) => {\n        if (e.key === 'Enter' || e.key === ' ') {\n          e.preventDefault()\n          onSelect(host)\n        }\n      }}\n    >\n      <div className=\"host-cell-content\">\n        <div className=\"host-cell-header\">\n          <div className=\"host-cell-label-wrapper\">\n            <span className=\"host-cell-label\">{formatHostName(host.name)}</span>\n          </div>\n        </div>\n        <div className=\"host-cell-body\">\n          <div className=\"host-cell-status\">\n            <div className=\"status-bar-wrapper\">\n              <span className=\"status-bar-label\">CPU</span>\n              <div className=\"status-bar cpu\">\n                <div className=\"status-bar-inner\" style={{ width: `${host.cpu}%` }} />\n              </div>\n              <span className=\"status-bar-value\">{host.cpu}%</span>\n            </div>\n            <div className=\"status-bar-wrapper\">\n              <span className=\"status-bar-label\">MEM</span>\n              <div className=\"status-bar memory\">\n                <div className=\"status-bar-inner\" style={{ width: `${host.memory}%` }} />\n              </div>\n              <span className=\"status-bar-value\">{host.memory}%</span>\n            </div>\n            <div className=\"status-bar-wrapper\">\n              <span className=\"status-bar-label\">DSK</span>\n              <div className=\"status-bar disk\">\n                <div className=\"status-bar-inner\" style={{ width: `${host.disk}%` }} />\n              </div>\n              <span className=\"status-bar-value\">{host.disk}%</span>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n)\n\nconst HostMap = React.memo(function HostMap({\n  hosts,\n  filteredHosts,\n  selectedHost,\n  onHostSelect,\n  statusFilter,\n  setStatusFilter,\n  searchQuery,\n  setSearchQuery,\n}: HostMapProps) {\n  // Group filtered hosts by category\n  const hostsByCategory = React.useMemo(() => {\n    const grouped: Record<string, Host[]> = {}\n    filteredHosts.forEach((host) => {\n      const category = getHostCategory(host.name)\n      if (!grouped[category]) {\n        grouped[category] = []\n      }\n      grouped[category].push(host)\n    })\n    return grouped\n  }, [filteredHosts])\n\n  const categories = Object.keys(hostsByCategory).sort()\n\n  // Calculate stats for each category\n  const getCategoryStats = (categoryHosts: Host[]) => {\n    return {\n      total: categoryHosts.length,\n      healthy: categoryHosts.filter((h) => h.status === 'healthy').length,\n      warning: categoryHosts.filter((h) => h.status === 'warning').length,\n      critical: categoryHosts.filter((h) => h.status === 'critical').length,\n    }\n  }\n\n  const statusCounts = React.useMemo(() => {\n    return {\n      all: hosts.length,\n      healthy: hosts.filter((h) => h.status === 'healthy').length,\n      warning: hosts.filter((h) => h.status === 'warning').length,\n      critical: hosts.filter((h) => h.status === 'critical').length,\n    }\n  }, [hosts])\n\n  return (\n    <div className=\"host-map\">\n      <div className=\"host-map-header\">\n        <h3>Host Map</h3>\n        <div className=\"host-list-controls\">\n          <input\n            type=\"text\"\n            className=\"host-search\"\n            placeholder=\"Search hosts...\"\n            value={searchQuery}\n            onChange={(e) => setSearchQuery(e.target.value)}\n          />\n          <div className=\"status-filters\">\n            <button\n              className={`filter-btn ${statusFilter === 'all' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('all')}\n            >\n              All ({statusCounts.all})\n            </button>\n            <button\n              className={`filter-btn healthy ${statusFilter === 'healthy' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('healthy')}\n            >\n              Healthy ({statusCounts.healthy})\n            </button>\n            <button\n              className={`filter-btn warning ${statusFilter === 'warning' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('warning')}\n            >\n              Warning ({statusCounts.warning})\n            </button>\n            <button\n              className={`filter-btn critical ${statusFilter === 'critical' ? 'active' : ''}`}\n              onClick={() => setStatusFilter('critical')}\n            >\n              Critical ({statusCounts.critical})\n            </button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"host-map-grid\">\n        {categories.map((category) => {\n          const categoryHosts = hostsByCategory[category]\n          const stats = getCategoryStats(categoryHosts)\n\n          return (\n            <div key={category} className=\"host-category\">\n              <div className=\"category-wrapper\">\n                <div className=\"category-label-container\">\n                  <div className=\"category-label\">{category}</div>\n                  <div className=\"category-stats\">\n                    <span className=\"category-stat\">\n                      <span style={{ color: '#3ebf62' }}>●</span> {stats.healthy}\n                    </span>\n                    <span className=\"category-stat\">\n                      <span style={{ color: '#ffa726' }}>●</span> {stats.warning}\n                    </span>\n                    <span className=\"category-stat\">\n                      <span style={{ color: '#ff5252' }}>●</span> {stats.critical}\n                    </span>\n                    <span className=\"category-stat\">Total: {stats.total}</span>\n                  </div>\n                </div>\n              </div>\n              <div className=\"category-hosts-wrapper\">\n                <div className=\"category-hosts\">\n                  {categoryHosts.map((host) => (\n                    <HostCell\n                      key={host.id}\n                      host={host}\n                      isSelected={selectedHost?.id === host.id}\n                      onSelect={onHostSelect}\n                    />\n                  ))}\n                </div>\n              </div>\n            </div>\n          )\n        })}\n      </div>\n\n      <div className=\"host-map-footer\">\n        Showing {filteredHosts.length} of {hosts.length} hosts\n      </div>\n    </div>\n  )\n})\n\nexport default HostMap\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/Infrastructure.css",
    "content": ".infrastructure {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  background: var(--color-bg);\n  color: var(--color-text);\n  padding: var(--spacing-lg);\n  gap: var(--spacing-lg);\n}\n\n.infrastructure-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  gap: var(--spacing-lg);\n}\n\n.infrastructure-title h1 {\n  margin: 0 0 var(--spacing-md) 0;\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.infrastructure-summary {\n  display: flex;\n  gap: var(--spacing-lg);\n}\n\n.summary-stat {\n  display: flex;\n  flex-direction: column;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  min-width: 100px;\n}\n\n.summary-stat.healthy {\n  border-left: 3px solid #3ebf62;\n}\n\n.summary-stat.warning {\n  border-left: 3px solid #ffa726;\n}\n\n.summary-stat.critical {\n  border-left: 3px solid #ff5252;\n}\n\n.stat-value {\n  font-size: var(--font-size-xl);\n  font-weight: 700;\n  color: var(--color-text);\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n}\n\n.stat-label {\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n  margin-top: 2px;\n}\n\n.view-toggle {\n  display: flex;\n  gap: var(--spacing-xs);\n  background: var(--color-surface);\n  padding: 4px;\n  border-radius: 6px;\n  border: 1px solid var(--color-border);\n}\n\n.toggle-btn {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n  padding: var(--spacing-xs) var(--spacing-md);\n  background: transparent;\n  border: none;\n  border-radius: 4px;\n  color: var(--color-text-secondary);\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.toggle-btn svg {\n  width: 16px;\n  height: 16px;\n}\n\n.toggle-btn:hover {\n  color: var(--color-text);\n  background: var(--color-surface-hover);\n}\n\n.toggle-btn.active {\n  background: var(--color-primary);\n  color: white;\n}\n\n.infrastructure-content {\n  display: flex;\n  flex: 1;\n  gap: var(--spacing-lg);\n  min-height: 0;\n}\n\n.infrastructure-main {\n  flex: 1;\n  min-width: 0;\n  overflow: hidden;\n  position: relative;\n  /* Performance optimization: create a new stacking context */\n  transform: translateZ(0);\n  will-change: contents;\n}\n\n.infrastructure-sidebar {\n  width: 500px;\n  min-width: 0;\n  overflow: hidden;\n}\n\n.loading-state,\n.error-state {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 200px;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  color: var(--color-text-muted);\n  font-size: var(--font-size-md);\n}\n\n.error-state {\n  color: var(--color-error);\n}\n\n.host-details-placeholder {\n  height: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-lg);\n}\n\n.placeholder-content {\n  text-align: center;\n  max-width: 400px;\n}\n\n.placeholder-content h3 {\n  margin: 0 0 var(--spacing-md) 0;\n  font-size: var(--font-size-lg);\n  color: var(--color-text);\n}\n\n.placeholder-content p {\n  margin: 0 0 var(--spacing-lg) 0;\n  color: var(--color-text-secondary);\n  font-size: var(--font-size-md);\n}\n\n.placeholder-content .close-btn {\n  padding: var(--spacing-sm) var(--spacing-lg);\n  background: var(--color-primary);\n  border: none;\n  border-radius: 6px;\n  color: white;\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.placeholder-content .close-btn:hover {\n  background: var(--color-primary-dark);\n}\n\n@media (max-width: 1440px) {\n  .infrastructure-sidebar {\n    width: 400px;\n  }\n}\n\n@media (max-width: 1024px) {\n  .infrastructure-header {\n    flex-direction: column;\n  }\n\n  .infrastructure-summary {\n    flex-wrap: wrap;\n    gap: var(--spacing-sm);\n  }\n\n  .summary-stat {\n    min-width: 80px;\n  }\n\n  .infrastructure-content {\n    flex-direction: column;\n  }\n\n  .infrastructure-sidebar {\n    width: 100%;\n    max-height: 600px;\n  }\n}\n\n@media (max-width: 768px) {\n  .infrastructure {\n    padding: var(--spacing-md);\n  }\n\n  .infrastructure-header {\n    gap: var(--spacing-md);\n  }\n\n  .infrastructure-summary {\n    grid-template-columns: repeat(2, 1fr);\n  }\n\n  .toggle-btn {\n    padding: var(--spacing-xs);\n  }\n\n  .toggle-btn span {\n    display: none;\n  }\n\n  .infrastructure-content {\n    gap: var(--spacing-md);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Infrastructure/Infrastructure.tsx",
    "content": "import { useState, useMemo } from 'react'\nimport { useData } from '../../hooks/useData'\nimport { InfrastructureData, Host, HostStatus } from '../../types/data'\nimport HostMap from './HostMap'\nimport HostList from './HostList'\nimport HostDetails from './HostDetails'\nimport { generateHostMetrics } from '../../utils/generateMetrics'\nimport './Infrastructure.css'\n\nexport default function Infrastructure() {\n  const { data, loading, error } = useData<InfrastructureData>('/data/infrastructure.json')\n  const [selectedHost, setSelectedHost] = useState<Host | null>(null)\n  const [viewMode, setViewMode] = useState<'map' | 'list'>('map')\n  const [statusFilter, setStatusFilter] = useState<HostStatus | 'all'>('all')\n  const [searchQuery, setSearchQuery] = useState('')\n\n  const handleHostSelect = (host: Host) => {\n    setSelectedHost(host)\n  }\n\n  const handleHostDeselect = () => {\n    setSelectedHost(null)\n  }\n\n  const selectedHostMetrics = useMemo(() => {\n    if (!selectedHost) return null\n\n    // Generate metrics dynamically for the selected host\n    return generateHostMetrics(selectedHost.id, 50)\n  }, [selectedHost, data?.metrics])\n\n  const filteredHosts = useMemo(() => {\n    if (!data?.hosts) return []\n\n    let filtered = data.hosts\n\n    // Apply status filter\n    if (statusFilter !== 'all') {\n      filtered = filtered.filter((host) => host.status === statusFilter)\n    }\n\n    // Apply search filter\n    if (searchQuery) {\n      filtered = filtered.filter((host) => host.name.toLowerCase().includes(searchQuery.toLowerCase()))\n    }\n\n    return filtered\n  }, [data?.hosts, statusFilter, searchQuery])\n\n  const statusSummary = useMemo(() => {\n    if (!data?.hosts) return { total: 0, healthy: 0, warning: 0, critical: 0 }\n\n    return {\n      total: data.hosts.length,\n      healthy: data.hosts.filter((h) => h.status === 'healthy').length,\n      warning: data.hosts.filter((h) => h.status === 'warning').length,\n      critical: data.hosts.filter((h) => h.status === 'critical').length,\n    }\n  }, [data?.hosts])\n\n  if (loading) {\n    return (\n      <div className=\"infrastructure\">\n        <div className=\"loading-state\">Loading infrastructure...</div>\n      </div>\n    )\n  }\n\n  if (error) {\n    return (\n      <div className=\"infrastructure\">\n        <div className=\"error-state\">Error loading infrastructure: {error.message}</div>\n      </div>\n    )\n  }\n\n  if (!data?.hosts) {\n    return (\n      <div className=\"infrastructure\">\n        <div className=\"error-state\">No infrastructure data available</div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"infrastructure\">\n      <div className=\"infrastructure-header\">\n        <div className=\"infrastructure-title\">\n          <h1>Infrastructure</h1>\n          <div className=\"infrastructure-summary\">\n            <div className=\"summary-stat\">\n              <span className=\"stat-value\">{statusSummary.total}</span>\n              <span className=\"stat-label\">Total Hosts</span>\n            </div>\n            <div className=\"summary-stat healthy\">\n              <span className=\"stat-value\">{statusSummary.healthy}</span>\n              <span className=\"stat-label\">Healthy</span>\n            </div>\n            <div className=\"summary-stat warning\">\n              <span className=\"stat-value\">{statusSummary.warning}</span>\n              <span className=\"stat-label\">Warning</span>\n            </div>\n            <div className=\"summary-stat critical\">\n              <span className=\"stat-value\">{statusSummary.critical}</span>\n              <span className=\"stat-label\">Critical</span>\n            </div>\n          </div>\n        </div>\n\n        <div className=\"view-toggle\">\n          <button className={`toggle-btn ${viewMode === 'map' ? 'active' : ''}`} onClick={() => setViewMode('map')}>\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path d=\"M5 3a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2V5a2 2 0 00-2-2H5zM5 11a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2v-2a2 2 0 00-2-2H5zM11 5a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V5zM11 13a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\" />\n            </svg>\n            Map\n          </button>\n          <button className={`toggle-btn ${viewMode === 'list' ? 'active' : ''}`} onClick={() => setViewMode('list')}>\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path\n                fillRule=\"evenodd\"\n                d=\"M3 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z\"\n                clipRule=\"evenodd\"\n              />\n            </svg>\n            List\n          </button>\n        </div>\n      </div>\n\n      <div className=\"infrastructure-content\">\n        <div className=\"infrastructure-main\">\n          {viewMode === 'map' ? (\n            <HostMap\n              hosts={data.hosts}\n              filteredHosts={filteredHosts}\n              selectedHost={selectedHost}\n              onHostSelect={handleHostSelect}\n              statusFilter={statusFilter}\n              setStatusFilter={setStatusFilter}\n              searchQuery={searchQuery}\n              setSearchQuery={setSearchQuery}\n            />\n          ) : (\n            <HostList\n              hosts={data.hosts}\n              filteredHosts={filteredHosts}\n              selectedHost={selectedHost}\n              onHostSelect={handleHostSelect}\n              statusFilter={statusFilter}\n              setStatusFilter={setStatusFilter}\n              searchQuery={searchQuery}\n              setSearchQuery={setSearchQuery}\n            />\n          )}\n        </div>\n\n        {selectedHost && (\n          <div className=\"infrastructure-sidebar\">\n            {selectedHostMetrics ? (\n              <HostDetails host={selectedHost} metrics={selectedHostMetrics} onClose={handleHostDeselect} />\n            ) : (\n              <div className=\"host-details-placeholder\">\n                <div className=\"placeholder-content\">\n                  <h3>{selectedHost.name}</h3>\n                  <p>Detailed metrics not available for this host.</p>\n                  <button className=\"close-btn\" onClick={handleHostDeselect}>\n                    Close\n                  </button>\n                </div>\n              </div>\n            )}\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Layout/MainLayout.css",
    "content": ".main-layout {\n  width: 100%;\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  background-color: var(--color-bg);\n  color: var(--color-text);\n  overflow: hidden;\n}\n\n.layout-container {\n  display: flex;\n  flex: 1;\n  overflow: hidden;\n}\n\n.main-content {\n  flex: 1;\n  overflow-y: auto;\n  min-width: 0;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n  .main-layout {\n    height: 100dvh;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Layout/MainLayout.tsx",
    "content": "import { ReactNode } from 'react'\nimport TopBar from './TopBar'\nimport Sidebar from './Sidebar'\nimport './MainLayout.css'\n\ninterface MainLayoutProps {\n  children: ReactNode\n}\n\nexport default function MainLayout({ children }: MainLayoutProps) {\n  return (\n    <div className=\"main-layout\">\n      <TopBar />\n      <div className=\"layout-container\">\n        <Sidebar />\n        <main className=\"main-content\">{children}</main>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Layout/Sidebar.css",
    "content": ".sidebar {\n  width: 240px;\n  background-color: var(--color-surface);\n  border-right: 1px solid var(--color-border);\n  padding: var(--spacing-md) 0;\n  overflow-y: auto;\n}\n\n.nav-list {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n}\n\n.nav-link {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-md);\n  padding: var(--spacing-md) var(--spacing-lg);\n  color: var(--color-text);\n  text-decoration: none;\n  transition:\n    background-color 0.2s,\n    color 0.2s;\n  font-size: 14px;\n}\n\n.nav-link:hover {\n  background-color: var(--color-bg);\n}\n\n.nav-link-active {\n  background-color: var(--color-primary-light);\n  color: var(--color-primary);\n  border-right: 3px solid var(--color-primary);\n}\n\n.nav-icon {\n  font-size: 20px;\n  width: 24px;\n  text-align: center;\n}\n\n.nav-label {\n  font-weight: 500;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n  .sidebar {\n    width: 60px;\n    padding: var(--spacing-sm) 0;\n  }\n\n  .nav-label {\n    display: none;\n  }\n\n  .nav-icon {\n    font-size: 20px;\n  }\n\n  .nav-link {\n    justify-content: center;\n    padding: var(--spacing-md) var(--spacing-sm);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Layout/Sidebar.tsx",
    "content": "import { NavLink, useSearchParams } from 'react-router-dom'\nimport { ROUTES } from '../../utils/constants'\nimport './Sidebar.css'\n\ninterface NavItem {\n  path: string\n  label: string\n  icon: string\n}\n\nconst NAV_ITEMS: NavItem[] = [\n  { path: ROUTES.DASHBOARD, label: 'Dashboard', icon: '📊' },\n  { path: ROUTES.LOGS, label: 'Logs', icon: '📝' },\n  { path: ROUTES.INFRASTRUCTURE, label: 'Infrastructure', icon: '🖥️' },\n  { path: ROUTES.SETTINGS, label: 'Settings', icon: '⚙️' },\n]\n\nexport default function Sidebar() {\n  const [searchParams] = useSearchParams()\n  const queryString = searchParams.toString()\n\n  return (\n    <nav className=\"sidebar\">\n      <ul className=\"nav-list\">\n        {NAV_ITEMS.map((item) => {\n          const pathWithParams = queryString ? `${item.path}?${queryString}` : item.path\n\n          return (\n            <li key={item.path}>\n              <NavLink\n                to={pathWithParams}\n                className={({ isActive }) => (isActive ? 'nav-link nav-link-active' : 'nav-link')}\n              >\n                <span className=\"nav-icon\">{item.icon}</span>\n                <span className=\"nav-label\">{item.label}</span>\n              </NavLink>\n            </li>\n          )\n        })}\n      </ul>\n    </nav>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Layout/TopBar.css",
    "content": ".topbar {\n  height: 64px;\n  background-color: var(--color-surface);\n  border-bottom: 1px solid var(--color-border);\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 0 var(--spacing-lg);\n  gap: var(--spacing-lg);\n}\n\n.topbar-left {\n  display: flex;\n  align-items: center;\n  min-width: 240px;\n}\n\n.logo {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  font-size: 18px;\n  font-weight: 600;\n  color: var(--color-text);\n  text-decoration: none;\n  cursor: pointer;\n  transition: opacity 0.2s;\n}\n\n.logo:hover {\n  opacity: 0.8;\n}\n\n.logo-icon {\n  font-size: 24px;\n}\n\n.topbar-center {\n  flex: 1;\n  max-width: 600px;\n}\n\n.search-bar {\n  width: 100%;\n}\n\n.search-input {\n  width: 100%;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background-color: var(--color-bg);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text);\n  font-size: 14px;\n}\n\n.search-input:focus {\n  outline: none;\n  border-color: var(--color-primary);\n}\n\n.topbar-right {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-md);\n}\n\n.sdk-indicator {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  font-size: 12px;\n}\n\n.sdk-label {\n  color: var(--color-text-secondary);\n}\n\n.sdk-badge {\n  padding: 4px 8px;\n  border-radius: 12px;\n  font-weight: 600;\n  font-size: 11px;\n  text-transform: uppercase;\n}\n\n.sdk-badge-none {\n  background-color: var(--color-border);\n  color: var(--color-text-secondary);\n}\n\n.sdk-badge-rum {\n  background-color: var(--color-primary);\n  color: white;\n}\n\n.sdk-badge-rum-replay {\n  background-color: var(--color-warning);\n  color: white;\n}\n\n.sdk-badge-rum-profiling {\n  background-color: var(--color-success);\n  color: white;\n}\n\n.icon-button {\n  width: 36px;\n  height: 36px;\n  border-radius: 50%;\n  border: none;\n  background-color: var(--color-bg);\n  color: var(--color-text);\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 18px;\n  transition: background-color 0.2s;\n}\n\n.icon-button:hover {\n  background-color: var(--color-border);\n}\n\n.notification-wrapper {\n  position: relative;\n}\n\n.notification-button {\n  position: relative;\n}\n\n.notification-badge {\n  position: absolute;\n  top: -2px;\n  right: -2px;\n  background-color: var(--color-error, #ef4444);\n  color: white;\n  border-radius: 10px;\n  padding: 2px 6px;\n  font-size: 10px;\n  font-weight: 600;\n  min-width: 18px;\n  height: 18px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.notification-panel {\n  position: absolute;\n  top: calc(100% + 8px);\n  right: 0;\n  width: 320px;\n  background-color: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 8px;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n  z-index: 1000;\n  overflow: hidden;\n}\n\n.notification-header {\n  padding: var(--spacing-md);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.notification-header h3 {\n  margin: 0;\n  font-size: 16px;\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.notification-list {\n  max-height: 400px;\n  overflow-y: auto;\n}\n\n.notification-item {\n  display: flex;\n  align-items: start;\n  gap: var(--spacing-md);\n  padding: var(--spacing-md);\n  border-bottom: 1px solid var(--color-border);\n  cursor: pointer;\n  transition: background-color 0.2s;\n}\n\n.notification-item:last-child {\n  border-bottom: none;\n}\n\n.notification-item:hover {\n  background-color: var(--color-bg);\n}\n\n.notification-icon {\n  font-size: 24px;\n  flex-shrink: 0;\n}\n\n.notification-content {\n  flex: 1;\n  min-width: 0;\n}\n\n.notification-title {\n  font-size: 14px;\n  font-weight: 500;\n  color: var(--color-text);\n  margin-bottom: 4px;\n}\n\n.notification-time {\n  font-size: 12px;\n  color: var(--color-text-secondary);\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n  .topbar {\n    padding: 0 var(--spacing-md);\n  }\n\n  .topbar-left {\n    min-width: auto;\n  }\n\n  .logo-text {\n    display: none;\n  }\n\n  .topbar-center {\n    max-width: 300px;\n  }\n\n  .search-input {\n    font-size: 13px;\n    padding: var(--spacing-xs) var(--spacing-sm);\n  }\n}\n\n@media (max-width: 480px) {\n  .topbar-center {\n    display: none;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Layout/TopBar.tsx",
    "content": "import { useState } from 'react'\nimport { Link, useSearchParams } from 'react-router-dom'\nimport { ROUTES } from '../../utils/constants'\nimport './TopBar.css'\nimport { heavyComputation } from '../../utils/performanceThrottle'\n\nexport default function TopBar() {\n  const [showNotifications, setShowNotifications] = useState(false)\n  const [notificationCount, setNotificationCount] = useState(3)\n\n  const [searchParams] = useSearchParams()\n  const queryString = searchParams.toString()\n\n  const homeLink = queryString ? `${ROUTES.DASHBOARD}?${queryString}` : ROUTES.DASHBOARD\n\n  const handleNotificationClick = () => {\n    // Emulate heavy work that causes poor INP\n    heavyComputation([queryString], 300)\n\n    // Toggle notifications panel\n    setShowNotifications(!showNotifications)\n\n    // Clear notification count when opening\n    if (!showNotifications) {\n      setNotificationCount(0)\n    }\n  }\n\n  return (\n    <header className=\"topbar\">\n      <div className=\"topbar-left\">\n        <Link to={homeLink} className=\"logo\">\n          <span className=\"logo-icon\">📊</span>\n          <span className=\"logo-text\">Heavy SPA Benchmark</span>\n        </Link>\n      </div>\n\n      <div className=\"topbar-center\">\n        <div className=\"search-bar\">\n          <input type=\"text\" placeholder=\"Search...\" className=\"search-input\" />\n        </div>\n      </div>\n\n      <div className=\"topbar-right\">\n        <div className=\"sdk-indicator\"></div>\n        <div className=\"notification-wrapper\">\n          <button className=\"icon-button notification-button\" onClick={handleNotificationClick}>\n            🔔\n            {notificationCount > 0 && <span className=\"notification-badge\">{notificationCount}</span>}\n          </button>\n          {showNotifications && (\n            <div className=\"notification-panel\">\n              <div className=\"notification-header\">\n                <h3>Notifications</h3>\n              </div>\n              <div className=\"notification-list\">\n                <div className=\"notification-item\">\n                  <div className=\"notification-icon\">📊</div>\n                  <div className=\"notification-content\">\n                    <div className=\"notification-title\">New dashboard available</div>\n                    <div className=\"notification-time\">2 minutes ago</div>\n                  </div>\n                </div>\n                <div className=\"notification-item\">\n                  <div className=\"notification-icon\">⚠️</div>\n                  <div className=\"notification-content\">\n                    <div className=\"notification-title\">High memory usage detected</div>\n                    <div className=\"notification-time\">15 minutes ago</div>\n                  </div>\n                </div>\n                <div className=\"notification-item\">\n                  <div className=\"notification-icon\">✅</div>\n                  <div className=\"notification-content\">\n                    <div className=\"notification-title\">Performance test completed</div>\n                    <div className=\"notification-time\">1 hour ago</div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          )}\n        </div>\n        <button className=\"icon-button user-button\">👤</button>\n      </div>\n    </header>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/FilterSidebar.css",
    "content": ".filter-sidebar {\n  width: 280px;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  height: fit-content;\n  max-height: 80vh;\n  overflow-y: auto;\n  flex-shrink: 0;\n}\n\n.filter-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: var(--spacing-md);\n  border-bottom: 1px solid var(--color-border);\n  background: var(--color-surface-elevated);\n  border-radius: 6px 6px 0 0;\n}\n\n.filter-header h3 {\n  margin: 0;\n  font-size: var(--font-size-md);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.clear-filters-btn {\n  background: none;\n  border: none;\n  color: var(--color-primary);\n  font-size: var(--font-size-sm);\n  cursor: pointer;\n  padding: var(--spacing-xs) var(--spacing-sm);\n  border-radius: 4px;\n  transition: all 0.2s ease;\n}\n\n.clear-filters-btn:hover {\n  background: var(--color-primary-hover);\n  color: white;\n}\n\n.filter-loading {\n  padding: var(--spacing-lg);\n  text-align: center;\n  color: var(--color-text-muted);\n  font-size: var(--font-size-sm);\n}\n\n/* Filter Section */\n.filter-section {\n  border-bottom: 1px solid var(--color-border);\n}\n\n.filter-section:last-child {\n  border-bottom: none;\n}\n\n.filter-section-header {\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: var(--spacing-md);\n  background: none;\n  border: none;\n  color: var(--color-text);\n  font-size: var(--font-size-md);\n  font-weight: 500;\n  cursor: pointer;\n  transition: background-color 0.2s ease;\n}\n\n.filter-section-header:hover {\n  background: var(--color-surface-hover);\n}\n\n.filter-section-title {\n  text-align: left;\n}\n\n.filter-section-chevron {\n  width: 16px;\n  height: 16px;\n  color: var(--color-text-muted);\n  transition: transform 0.2s ease;\n}\n\n.filter-section-chevron.collapsed {\n  transform: rotate(-90deg);\n}\n\n.filter-section-content {\n  padding: 0 var(--spacing-md) var(--spacing-md);\n}\n\n/* Level Filters */\n.level-filters {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-xs);\n}\n\n.level-checkbox-item {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  cursor: pointer;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  transition: background-color 0.2s ease;\n}\n\n.level-checkbox-item:hover {\n  background: var(--color-surface-hover);\n}\n\n.level-checkbox-item input[type='checkbox'] {\n  margin: 0;\n}\n\n.level-indicator {\n  width: 12px;\n  height: 12px;\n  border-radius: 2px;\n  flex-shrink: 0;\n}\n\n.level-label {\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n}\n\n/* Checkbox List */\n.checkbox-list {\n  max-height: 300px;\n  overflow-y: auto;\n}\n\n.checkbox-list-header {\n  margin-bottom: var(--spacing-xs);\n}\n\n.select-all-btn {\n  background: none;\n  border: none;\n  color: var(--color-primary);\n  font-size: var(--font-size-sm);\n  cursor: pointer;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  transition: all 0.2s ease;\n}\n\n.select-all-btn:hover {\n  background: var(--color-primary-hover);\n  color: white;\n}\n\n.checkbox-items {\n  display: flex;\n  flex-direction: column;\n  gap: 2px;\n  margin-bottom: var(--spacing-sm);\n}\n\n.checkbox-item {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  cursor: pointer;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  transition: background-color 0.2s ease;\n}\n\n.checkbox-item:hover {\n  background: var(--color-surface-hover);\n}\n\n.checkbox-item input[type='checkbox'] {\n  margin: 0;\n  flex-shrink: 0;\n}\n\n.checkbox-label {\n  font-size: var(--font-size-sm);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.show-more-btn {\n  background: none;\n  border: none;\n  color: var(--color-text-muted);\n  font-size: var(--font-size-sm);\n  cursor: pointer;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  transition: all 0.2s ease;\n  width: 100%;\n  text-align: left;\n}\n\n.show-more-btn:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n@media (max-width: 768px) {\n  .filter-sidebar {\n    width: 100%;\n    max-height: 400px;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/FilterSidebar.tsx",
    "content": "import React, { useState, useCallback } from 'react'\nimport { LogFacets, LogLevel } from '../../types/data'\nimport { LogFilters } from './LogsExplorer'\nimport './FilterSidebar.css'\n\ninterface FilterSidebarProps {\n  facets?: LogFacets\n  filters: LogFilters\n  onFilterChange: (filters: Partial<LogFilters>) => void\n}\n\ninterface FilterSectionProps {\n  title: string\n  isCollapsed: boolean\n  onToggle: () => void\n  children: React.ReactNode\n}\n\nfunction FilterSection({ title, isCollapsed, onToggle, children }: FilterSectionProps) {\n  return (\n    <div className=\"filter-section\">\n      <button className=\"filter-section-header\" onClick={onToggle}>\n        <span className=\"filter-section-title\">{title}</span>\n        <svg\n          className={`filter-section-chevron ${isCollapsed ? 'collapsed' : ''}`}\n          viewBox=\"0 0 20 20\"\n          fill=\"currentColor\"\n        >\n          <path\n            fillRule=\"evenodd\"\n            d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\"\n            clipRule=\"evenodd\"\n          />\n        </svg>\n      </button>\n      {!isCollapsed && <div className=\"filter-section-content\">{children}</div>}\n    </div>\n  )\n}\n\ninterface CheckboxListProps {\n  items: string[]\n  selectedItems: string[]\n  onSelectionChange: (selected: string[]) => void\n  maxVisible?: number\n}\n\nfunction CheckboxList({ items, selectedItems, onSelectionChange, maxVisible = 10 }: CheckboxListProps) {\n  const [showAll, setShowAll] = useState(false)\n  const displayItems = showAll ? items : items.slice(0, maxVisible)\n  const hasMore = items.length > maxVisible\n\n  const handleToggle = useCallback(\n    (item: string) => {\n      const isSelected = selectedItems.includes(item)\n      if (isSelected) {\n        onSelectionChange(selectedItems.filter((i) => i !== item))\n      } else {\n        onSelectionChange([...selectedItems, item])\n      }\n    },\n    [selectedItems, onSelectionChange]\n  )\n\n  const handleSelectAll = useCallback(() => {\n    if (selectedItems.length === items.length) {\n      onSelectionChange([])\n    } else {\n      onSelectionChange([...items])\n    }\n  }, [items, selectedItems, onSelectionChange])\n\n  return (\n    <div className=\"checkbox-list\">\n      <div className=\"checkbox-list-header\">\n        <button className=\"select-all-btn\" onClick={handleSelectAll}>\n          {selectedItems.length === items.length ? 'Deselect All' : 'Select All'}\n        </button>\n      </div>\n\n      <div className=\"checkbox-items\">\n        {displayItems.map((item) => (\n          <label key={item} className=\"checkbox-item\">\n            <input type=\"checkbox\" checked={selectedItems.includes(item)} onChange={() => handleToggle(item)} />\n            <span className=\"checkbox-label\">{item}</span>\n          </label>\n        ))}\n      </div>\n\n      {hasMore && (\n        <button className=\"show-more-btn\" onClick={() => setShowAll(!showAll)}>\n          {showAll ? `Show Less` : `Show ${items.length - maxVisible} More`}\n        </button>\n      )}\n    </div>\n  )\n}\n\nconst LOG_LEVEL_COLORS: Record<LogLevel, string> = {\n  ERROR: '#ff5252',\n  WARN: '#ffa726',\n  INFO: '#42a5f5',\n  DEBUG: '#66bb6a',\n}\n\nexport default function FilterSidebar({ facets, filters, onFilterChange }: FilterSidebarProps) {\n  const [collapsedSections, setCollapsedSections] = useState<Record<string, boolean>>({\n    levels: false,\n    services: false,\n    hosts: true,\n  })\n\n  const toggleSection = useCallback((section: string) => {\n    setCollapsedSections((prev) => ({\n      ...prev,\n      [section]: !prev[section],\n    }))\n  }, [])\n\n  const handleLevelsChange = useCallback(\n    (levels: string[]) => {\n      onFilterChange({ levels: levels as LogLevel[] })\n    },\n    [onFilterChange]\n  )\n\n  const handleServicesChange = useCallback(\n    (services: string[]) => {\n      onFilterChange({ services })\n    },\n    [onFilterChange]\n  )\n\n  const handleHostsChange = useCallback(\n    (hosts: string[]) => {\n      onFilterChange({ hosts })\n    },\n    [onFilterChange]\n  )\n\n  const clearAllFilters = useCallback(() => {\n    onFilterChange({\n      levels: [],\n      services: [],\n      hosts: [],\n      search: '',\n    })\n  }, [onFilterChange])\n\n  const hasActiveFilters =\n    filters.levels.length > 0 ||\n    filters.services.length > 0 ||\n    filters.hosts.length > 0 ||\n    (filters.search && filters.search.length > 0)\n\n  if (!facets) {\n    return (\n      <div className=\"filter-sidebar\">\n        <div className=\"filter-loading\">Loading filters...</div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"filter-sidebar\">\n      <div className=\"filter-header\">\n        <h3>Filters</h3>\n        {hasActiveFilters && (\n          <button className=\"clear-filters-btn\" onClick={clearAllFilters}>\n            Clear All\n          </button>\n        )}\n      </div>\n\n      <FilterSection title=\"Log Levels\" isCollapsed={collapsedSections.levels} onToggle={() => toggleSection('levels')}>\n        <div className=\"level-filters\">\n          {facets.levels.map((level) => (\n            <label key={level} className=\"level-checkbox-item\">\n              <input\n                type=\"checkbox\"\n                checked={filters.levels.includes(level)}\n                onChange={() => {\n                  const isSelected = filters.levels.includes(level)\n                  if (isSelected) {\n                    handleLevelsChange(filters.levels.filter((l) => l !== level))\n                  } else {\n                    handleLevelsChange([...filters.levels, level])\n                  }\n                }}\n              />\n              <span className=\"level-indicator\" style={{ backgroundColor: LOG_LEVEL_COLORS[level] }} />\n              <span className=\"level-label\">{level}</span>\n            </label>\n          ))}\n        </div>\n      </FilterSection>\n\n      <FilterSection\n        title=\"Services\"\n        isCollapsed={collapsedSections.services}\n        onToggle={() => toggleSection('services')}\n      >\n        <CheckboxList\n          items={facets.services}\n          selectedItems={filters.services}\n          onSelectionChange={handleServicesChange}\n          maxVisible={8}\n        />\n      </FilterSection>\n\n      <FilterSection title=\"Hosts\" isCollapsed={collapsedSections.hosts} onToggle={() => toggleSection('hosts')}>\n        <CheckboxList\n          items={facets.hosts}\n          selectedItems={filters.hosts}\n          onSelectionChange={handleHostsChange}\n          maxVisible={8}\n        />\n      </FilterSection>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/LogDetails.css",
    "content": ".log-details {\n  width: 400px;\n  max-width: 100%;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  display: flex;\n  flex-direction: column;\n  max-height: 80vh;\n  overflow: hidden;\n  flex-shrink: 0;\n}\n\n.log-details-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.log-details-title {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n}\n\n.log-level-indicator {\n  width: 12px;\n  height: 12px;\n  border-radius: 2px;\n  flex-shrink: 0;\n}\n\n.log-level-indicator.small {\n  width: 8px;\n  height: 8px;\n}\n\n.log-level-text {\n  font-size: var(--font-size-md);\n  font-weight: 600;\n}\n\n.log-id {\n  font-size: var(--font-size-sm);\n  color: var(--color-text-muted);\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n}\n\n.log-details-actions {\n  display: flex;\n  gap: var(--spacing-sm);\n}\n\n.copy-btn {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n  background: var(--color-primary);\n  color: white;\n  border: none;\n  padding: var(--spacing-xs) var(--spacing-sm);\n  border-radius: 4px;\n  font-size: var(--font-size-sm);\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.copy-btn:hover {\n  background: var(--color-primary-hover);\n}\n\n.copy-btn.copied {\n  background: var(--color-success);\n}\n\n.copy-btn svg {\n  width: 16px;\n  height: 16px;\n}\n\n.close-btn {\n  background: none;\n  border: none;\n  color: var(--color-text-muted);\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  cursor: pointer;\n  transition: all 0.2s ease;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.close-btn:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n.close-btn svg {\n  width: 20px;\n  height: 20px;\n}\n\n/* Tabs */\n.log-details-tabs {\n  display: flex;\n  background: var(--color-surface-elevated);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.tab-button {\n  flex: 1;\n  background: none;\n  border: none;\n  padding: var(--spacing-sm) var(--spacing-md);\n  color: var(--color-text-muted);\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.2s ease;\n  border-bottom: 2px solid transparent;\n}\n\n.tab-button:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n.tab-button.active {\n  color: var(--color-primary);\n  border-bottom-color: var(--color-primary);\n  background: var(--color-surface);\n}\n\n/* Content */\n.log-details-content {\n  flex: 1;\n  overflow-y: auto;\n  padding: var(--spacing-md);\n}\n\n/* Details View */\n.log-details-view {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-lg);\n}\n\n.detail-section {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-xs);\n}\n\n.detail-section h4 {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n  color: var(--color-text-muted);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.detail-value {\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  padding: var(--spacing-sm);\n  font-size: var(--font-size-sm);\n  line-height: 1.4;\n  word-break: break-word;\n}\n\n.timestamp-value {\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  font-size: var(--font-size-xs);\n  color: var(--color-text-muted);\n}\n\n.level-value {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  font-weight: 600;\n}\n\n.service-value,\n.host-value,\n.id-value {\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  font-size: var(--font-size-sm);\n}\n\n.message-value {\n  line-height: 1.5;\n  white-space: pre-wrap;\n}\n\n.tags-value {\n  display: flex;\n  flex-wrap: wrap;\n  gap: var(--spacing-xs);\n  padding: var(--spacing-sm);\n}\n\n.tag-item {\n  background: var(--color-primary);\n  color: white;\n  font-size: var(--font-size-xs);\n  padding: 4px 8px;\n  border-radius: 3px;\n  white-space: nowrap;\n}\n\n/* Raw View */\n.log-raw-view {\n  height: 100%;\n}\n\n.log-raw-content {\n  margin: 0;\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  font-size: var(--font-size-xs);\n  line-height: 1.4;\n  color: var(--color-text);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  padding: var(--spacing-md);\n  overflow-x: auto;\n  white-space: pre;\n}\n\n@media (max-width: 768px) {\n  .log-details {\n    width: 100%;\n    max-height: 60vh;\n  }\n\n  .log-details-header {\n    flex-direction: column;\n    align-items: flex-start;\n    gap: var(--spacing-sm);\n  }\n\n  .log-details-actions {\n    align-self: flex-end;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/LogDetails.tsx",
    "content": "import React, { useState, useCallback } from 'react'\nimport { LogEntry, LogLevel } from '../../types/data'\nimport './LogDetails.css'\n\ninterface LogDetailsProps {\n  log: LogEntry\n  onClose: () => void\n}\n\nconst LOG_LEVEL_COLORS: Record<LogLevel, string> = {\n  ERROR: '#ff5252',\n  WARN: '#ffa726',\n  INFO: '#42a5f5',\n  DEBUG: '#66bb6a',\n}\n\nfunction formatTimestamp(timestamp: number): string {\n  const date = new Date(timestamp)\n  return date.toLocaleString('en-US', {\n    weekday: 'short',\n    year: 'numeric',\n    month: 'short',\n    day: '2-digit',\n    hour: '2-digit',\n    minute: '2-digit',\n    second: '2-digit',\n    timeZoneName: 'short',\n    hour12: false,\n  })\n}\n\nfunction copyToClipboard(text: string): void {\n  navigator.clipboard\n    .writeText(text)\n    .then(() => {\n      // Could show a toast notification here\n    })\n    .catch((err) => {\n      console.error('Failed to copy text:', err)\n    })\n}\n\nexport default function LogDetails({ log, onClose }: LogDetailsProps) {\n  const [activeTab, setActiveTab] = useState<'details' | 'raw'>('details')\n  const [copied, setCopied] = useState(false)\n\n  const handleCopy = useCallback(() => {\n    const logText = `[${formatTimestamp(log.timestamp)}] ${log.level} ${log.service}@${log.host}: ${log.message}`\n    copyToClipboard(logText)\n    setCopied(true)\n    setTimeout(() => setCopied(false), 2000)\n  }, [log])\n\n  const handleCopyRaw = useCallback(() => {\n    const rawLog = JSON.stringify(log, null, 2)\n    copyToClipboard(rawLog)\n    setCopied(true)\n    setTimeout(() => setCopied(false), 2000)\n  }, [log])\n\n  const handleKeyDown = useCallback(\n    (e: React.KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        onClose()\n      }\n    },\n    [onClose]\n  )\n\n  return (\n    <div className=\"log-details\" onKeyDown={handleKeyDown} tabIndex={0}>\n      <div className=\"log-details-header\">\n        <div className=\"log-details-title\">\n          <span className=\"log-level-indicator\" style={{ backgroundColor: LOG_LEVEL_COLORS[log.level] }} />\n          <span className=\"log-level-text\">{log.level}</span>\n          <span className=\"log-id\">({log.id})</span>\n        </div>\n\n        <div className=\"log-details-actions\">\n          <button\n            className={`copy-btn ${copied ? 'copied' : ''}`}\n            onClick={activeTab === 'details' ? handleCopy : handleCopyRaw}\n            title=\"Copy to clipboard\"\n          >\n            {copied ? (\n              <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n                <path\n                  fillRule=\"evenodd\"\n                  d=\"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z\"\n                  clipRule=\"evenodd\"\n                />\n              </svg>\n            ) : (\n              <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n                <path d=\"M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z\" />\n                <path d=\"M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z\" />\n              </svg>\n            )}\n            {copied ? 'Copied!' : 'Copy'}\n          </button>\n\n          <button className=\"close-btn\" onClick={onClose} aria-label=\"Close details\">\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path\n                fillRule=\"evenodd\"\n                d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n                clipRule=\"evenodd\"\n              />\n            </svg>\n          </button>\n        </div>\n      </div>\n\n      <div className=\"log-details-tabs\">\n        <button\n          className={`tab-button ${activeTab === 'details' ? 'active' : ''}`}\n          onClick={() => setActiveTab('details')}\n        >\n          Details\n        </button>\n        <button className={`tab-button ${activeTab === 'raw' ? 'active' : ''}`} onClick={() => setActiveTab('raw')}>\n          Raw\n        </button>\n      </div>\n\n      <div className=\"log-details-content\">\n        {activeTab === 'details' ? (\n          <div className=\"log-details-view\">\n            <div className=\"detail-section\">\n              <h4>Timestamp</h4>\n              <div className=\"detail-value timestamp-value\">{formatTimestamp(log.timestamp)}</div>\n            </div>\n\n            <div className=\"detail-section\">\n              <h4>Level</h4>\n              <div className=\"detail-value level-value\">\n                <span className=\"log-level-indicator small\" style={{ backgroundColor: LOG_LEVEL_COLORS[log.level] }} />\n                {log.level}\n              </div>\n            </div>\n\n            <div className=\"detail-section\">\n              <h4>Service</h4>\n              <div className=\"detail-value service-value\">{log.service}</div>\n            </div>\n\n            <div className=\"detail-section\">\n              <h4>Host</h4>\n              <div className=\"detail-value host-value\">{log.host}</div>\n            </div>\n\n            <div className=\"detail-section\">\n              <h4>Message</h4>\n              <div className=\"detail-value message-value\">{log.message}</div>\n            </div>\n\n            {log.tags.length > 0 && (\n              <div className=\"detail-section\">\n                <h4>Tags</h4>\n                <div className=\"detail-value tags-value\">\n                  {log.tags.map((tag, index) => (\n                    <span key={index} className=\"tag-item\">\n                      {tag}\n                    </span>\n                  ))}\n                </div>\n              </div>\n            )}\n\n            <div className=\"detail-section\">\n              <h4>Log ID</h4>\n              <div className=\"detail-value id-value\">{log.id}</div>\n            </div>\n          </div>\n        ) : (\n          <div className=\"log-raw-view\">\n            <pre className=\"log-raw-content\">{JSON.stringify(log, null, 2)}</pre>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/LogTable.css",
    "content": ".log-table-container {\n  display: flex;\n  flex-direction: column;\n  flex: 1;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  overflow: hidden;\n  min-height: 0;\n}\n\n.log-table-header {\n  display: grid;\n  grid-template-columns: 180px 80px 140px 140px 1fr 120px;\n  background: var(--color-surface-elevated);\n  border-bottom: 1px solid var(--color-border);\n  font-weight: 600;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-muted);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.log-header-cell {\n  padding: var(--spacing-sm) var(--spacing-md);\n  border-right: 1px solid var(--color-border);\n  display: flex;\n  align-items: center;\n}\n\n.log-header-cell:last-child {\n  border-right: none;\n}\n\n.log-table-body {\n  flex: 1;\n  min-height: 0;\n}\n\n.log-table-footer {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border-top: 1px solid var(--color-border);\n  font-size: var(--font-size-sm);\n  color: var(--color-text-muted);\n}\n\n/* Log Rows */\n.log-row {\n  position: relative;\n  border-bottom: 1px solid var(--color-border-light);\n  cursor: pointer;\n  transition: all 0.2s ease;\n  outline: none;\n}\n\n.log-row:hover {\n  background: var(--color-surface-hover);\n}\n\n.log-row:focus {\n  background: var(--color-surface-hover);\n  box-shadow: inset 3px 0 0 var(--color-primary);\n}\n\n.log-row.selected {\n  background: rgba(99, 44, 166, 0.1);\n  border-left: 3px solid var(--color-primary);\n}\n\n.log-row.error {\n  border-left: 3px solid #ff5252;\n}\n\n.log-row.warn {\n  border-left: 3px solid #ffa726;\n}\n\n.log-row.info {\n  border-left: 3px solid #42a5f5;\n}\n\n.log-row.debug {\n  border-left: 3px solid #66bb6a;\n}\n\n.log-row-content {\n  display: grid;\n  grid-template-columns: 180px 80px 140px 140px 1fr 120px;\n  align-items: center;\n  padding: var(--spacing-sm) 0;\n  min-height: 80px;\n}\n\n.log-row-content > div {\n  padding: 0 var(--spacing-md);\n  overflow: hidden;\n  display: flex;\n  align-items: center;\n}\n\n.log-timestamp {\n  flex-direction: column;\n  align-items: flex-start !important;\n  gap: 2px;\n}\n\n.log-time {\n  font-size: var(--font-size-sm);\n  color: var(--color-text);\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n}\n\n.log-relative-time {\n  font-size: var(--font-size-xs);\n  color: var(--color-text-muted);\n}\n\n.log-level {\n  gap: var(--spacing-xs);\n}\n\n.log-level-indicator {\n  width: 12px;\n  height: 12px;\n  border-radius: 2px;\n  flex-shrink: 0;\n}\n\n.log-level-text {\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n}\n\n.log-service,\n.log-host {\n  font-size: var(--font-size-sm);\n  color: var(--color-text);\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.log-message {\n  font-size: var(--font-size-sm);\n  color: var(--color-text);\n  line-height: 1.4;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.log-tags {\n  display: flex;\n  gap: var(--spacing-xs);\n  flex-wrap: wrap;\n  align-items: flex-start !important;\n}\n\n.log-tag {\n  background: var(--color-surface-elevated);\n  color: var(--color-text-muted);\n  font-size: var(--font-size-xs);\n  padding: 2px 6px;\n  border-radius: 3px;\n  border: 1px solid var(--color-border);\n  white-space: nowrap;\n}\n\n.log-tag-more {\n  background: var(--color-primary);\n  color: white;\n  font-size: var(--font-size-xs);\n  padding: 2px 6px;\n  border-radius: 3px;\n  white-space: nowrap;\n}\n\n.log-row-selected-indicator {\n  position: absolute;\n  right: var(--spacing-md);\n  top: 50%;\n  transform: translateY(-50%);\n  width: 8px;\n  height: 8px;\n  background: var(--color-primary);\n  border-radius: 50%;\n}\n\n/* Empty State */\n.log-table-empty {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 400px;\n  background: var(--color-surface);\n}\n\n.empty-state {\n  text-align: center;\n  color: var(--color-text-muted);\n}\n\n.empty-icon {\n  width: 64px;\n  height: 64px;\n  color: var(--color-text-muted);\n  opacity: 0.5;\n  margin-bottom: var(--spacing-md);\n}\n\n.empty-state h3 {\n  margin: 0 0 var(--spacing-sm);\n  font-size: var(--font-size-lg);\n  color: var(--color-text);\n}\n\n.empty-state p {\n  margin: 0;\n  font-size: var(--font-size-sm);\n}\n\n@media (max-width: 1200px) {\n  .log-table-header,\n  .log-row-content {\n    grid-template-columns: 160px 70px 120px 120px 1fr 100px;\n  }\n}\n\n@media (max-width: 768px) {\n  .log-table-header,\n  .log-row-content {\n    grid-template-columns: 1fr;\n  }\n\n  .log-row-content {\n    flex-direction: column;\n    align-items: flex-start !important;\n    padding: var(--spacing-md);\n    gap: var(--spacing-sm);\n  }\n\n  .log-row-content > div {\n    padding: 0;\n    width: 100%;\n  }\n\n  .log-timestamp {\n    flex-direction: row !important;\n    gap: var(--spacing-sm);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/LogTable.tsx",
    "content": "import { useMemo, useCallback } from 'react'\nimport { List, RowComponentProps } from 'react-window'\nimport { LogEntry, LogLevel } from '../../types/data'\nimport './LogTable.css'\n\ninterface LogTableProps {\n  logs: LogEntry[]\n  selectedLog: LogEntry | null\n  onLogSelect: (log: LogEntry) => void\n}\n\ninterface LogRowExtraProps {\n  logs: LogEntry[]\n  selectedLog: LogEntry | null\n  onLogSelect: (log: LogEntry) => void\n}\n\nconst LOG_LEVEL_COLORS: Record<LogLevel, string> = {\n  ERROR: '#ff5252',\n  WARN: '#ffa726',\n  INFO: '#42a5f5',\n  DEBUG: '#66bb6a',\n}\n\nfunction formatTimestamp(timestamp: number): string {\n  const date = new Date(timestamp)\n  return date.toLocaleString('en-US', {\n    month: 'short',\n    day: '2-digit',\n    hour: '2-digit',\n    minute: '2-digit',\n    second: '2-digit',\n    hour12: false,\n  })\n}\n\nfunction formatRelativeTime(timestamp: number): string {\n  const now = Date.now()\n  const diff = now - timestamp\n\n  if (diff < 60000) {\n    // Less than 1 minute\n    return 'just now'\n  } else if (diff < 3600000) {\n    // Less than 1 hour\n    const minutes = Math.floor(diff / 60000)\n    return `${minutes}m ago`\n  } else if (diff < 86400000) {\n    // Less than 1 day\n    const hours = Math.floor(diff / 3600000)\n    return `${hours}h ago`\n  } else {\n    const days = Math.floor(diff / 86400000)\n    return `${days}d ago`\n  }\n}\n\nfunction truncateMessage(message: string, maxLength: number = 120): string {\n  if (message.length <= maxLength) return message\n  return message.substring(0, maxLength) + '...'\n}\n\nfunction LogRow({ index, style, logs, selectedLog, onLogSelect }: RowComponentProps<LogRowExtraProps>) {\n  const log = logs[index]\n\n  const isSelected = selectedLog?.id === log.id\n\n  const handleClick = useCallback(() => {\n    onLogSelect(log)\n  }, [log, onLogSelect])\n\n  const handleKeyDown = useCallback(\n    (e: React.KeyboardEvent) => {\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault()\n        onLogSelect(log)\n      }\n    },\n    [log, onLogSelect]\n  )\n\n  return (\n    <div style={style}>\n      <div\n        className={`log-row ${isSelected ? 'selected' : ''} ${log.level.toLowerCase()}`}\n        onClick={handleClick}\n        onKeyDown={handleKeyDown}\n        tabIndex={0}\n        role=\"row\"\n        aria-selected={isSelected}\n        data-test-id={`log-row-${log.id}`}\n      >\n        <div className=\"log-row-content\">\n          <div className=\"log-timestamp\">\n            <span className=\"log-time\">{formatTimestamp(log.timestamp)}</span>\n            <span className=\"log-relative-time\">{formatRelativeTime(log.timestamp)}</span>\n          </div>\n\n          <div className=\"log-level\">\n            <span className=\"log-level-indicator\" style={{ backgroundColor: LOG_LEVEL_COLORS[log.level] }} />\n            <span className=\"log-level-text\">{log.level}</span>\n          </div>\n\n          <div className=\"log-service\">{log.service}</div>\n\n          <div className=\"log-host\">{log.host}</div>\n\n          <div className=\"log-message\">{truncateMessage(log.message)}</div>\n\n          {log.tags.length > 0 && (\n            <div className=\"log-tags\">\n              {log.tags.slice(0, 2).map((tag, idx) => (\n                <span key={idx} className=\"log-tag\">\n                  {tag}\n                </span>\n              ))}\n              {log.tags.length > 2 && <span className=\"log-tag-more\">+{log.tags.length - 2}</span>}\n            </div>\n          )}\n        </div>\n\n        {isSelected && <div className=\"log-row-selected-indicator\" />}\n      </div>\n    </div>\n  )\n}\n\nexport default function LogTable({ logs, selectedLog, onLogSelect }: LogTableProps) {\n  const itemData = useMemo(\n    () => ({\n      logs,\n      selectedLog,\n      onLogSelect,\n    }),\n    [logs, selectedLog, onLogSelect]\n  )\n\n  if (logs.length === 0) {\n    return (\n      <div className=\"log-table-container\">\n        <div className=\"log-table-header\">\n          <div className=\"log-header-cell timestamp\">Timestamp</div>\n          <div className=\"log-header-cell level\">Level</div>\n          <div className=\"log-header-cell service\">Service</div>\n          <div className=\"log-header-cell host\">Host</div>\n          <div className=\"log-header-cell message\">Message</div>\n          <div className=\"log-header-cell tags\">Tags</div>\n        </div>\n        <div className=\"log-table-empty\">\n          <div className=\"empty-state\">\n            <svg viewBox=\"0 0 24 24\" className=\"empty-icon\">\n              <path\n                fill=\"currentColor\"\n                d=\"M9,5V9H21V7.5L12,2L3,7.5V9H5V19H3V21H21V19H19V5H9M11,7H17V19H11V7M4,9V19H2V21H6V9H4M6,11H4V13H6V11M6,15H4V17H6V15M13,9V11H15V9H13M13,13V15H15V13H13Z\"\n              />\n            </svg>\n            <h3>No logs found</h3>\n            <p>Try adjusting your search criteria or filters</p>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"log-table-container\">\n      <div className=\"log-table-header\">\n        <div className=\"log-header-cell timestamp\">Timestamp</div>\n        <div className=\"log-header-cell level\">Level</div>\n        <div className=\"log-header-cell service\">Service</div>\n        <div className=\"log-header-cell host\">Host</div>\n        <div className=\"log-header-cell message\">Message</div>\n        <div className=\"log-header-cell tags\">Tags</div>\n      </div>\n\n      <div className=\"log-table-body\">\n        <List<LogRowExtraProps>\n          rowCount={logs.length}\n          rowHeight={80}\n          rowProps={itemData}\n          rowComponent={LogRow}\n          overscanCount={5}\n        />\n      </div>\n\n      <div className=\"log-table-footer\">\n        <span className=\"log-count\">{logs.length} logs displayed</span>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/LogsExplorer.css",
    "content": ".logs-explorer {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  background: var(--color-bg);\n  color: var(--color-text);\n  padding: var(--spacing-lg);\n  gap: var(--spacing-md);\n}\n\n.logs-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  margin-bottom: var(--spacing-md);\n}\n\n.logs-header h1 {\n  margin: 0;\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.logs-stats {\n  font-size: var(--font-size-sm);\n  color: var(--color-text-muted);\n  background: var(--color-surface);\n  padding: var(--spacing-xs) var(--spacing-sm);\n  border-radius: 4px;\n  border: 1px solid var(--color-border);\n}\n\n.logs-content {\n  display: flex;\n  flex: 1;\n  gap: var(--spacing-lg);\n  min-height: 0;\n}\n\n.logs-main {\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-md);\n  min-width: 0;\n}\n\n.loading-state,\n.error-state {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 200px;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  color: var(--color-text-muted);\n  font-size: var(--font-size-md);\n}\n\n.error-state {\n  color: var(--color-error);\n}\n\n@media (max-width: 768px) {\n  .logs-explorer {\n    padding: var(--spacing-md);\n  }\n\n  .logs-content {\n    flex-direction: column;\n  }\n\n  .logs-header {\n    flex-direction: column;\n    align-items: flex-start;\n    gap: var(--spacing-sm);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/LogsExplorer.tsx",
    "content": "import { useState, useMemo } from 'react'\nimport { useData } from '../../hooks/useData'\nimport { LogEntry, LogsData, LogLevel } from '../../types/data'\nimport { heavyComputation } from '../../utils/performanceThrottle'\nimport SearchBar from './SearchBar'\nimport FilterSidebar from './FilterSidebar'\nimport LogTable from './LogTable'\nimport LogDetails from './LogDetails'\nimport './LogsExplorer.css'\n\nexport interface LogFilters {\n  levels: LogLevel[]\n  services: string[]\n  hosts: string[]\n  search: string\n}\n\nexport default function LogsExplorer() {\n  const { data, loading, error } = useData<LogsData>('/data/logs.json')\n  const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null)\n  const [filters, setFilters] = useState<LogFilters>({\n    levels: [],\n    services: [],\n    hosts: [],\n    search: '',\n  })\n\n  // Filter logs based on current filters\n  const filteredLogs = useMemo(() => {\n    if (!data?.logs) return []\n\n    const results = data.logs.filter((log) => {\n      // Level filter\n      if (filters.levels.length > 0 && !filters.levels.includes(log.level)) {\n        return false\n      }\n\n      // Service filter\n      if (filters.services.length > 0 && !filters.services.includes(log.service)) {\n        return false\n      }\n\n      // Host filter\n      if (filters.hosts.length > 0 && !filters.hosts.includes(log.host)) {\n        return false\n      }\n\n      // Search filter\n      if (filters.search && !log.message.toLowerCase().includes(filters.search.toLowerCase())) {\n        return false\n      }\n\n      return true\n    })\n\n    return heavyComputation(results, 100)\n  }, [data?.logs, filters])\n\n  const handleFilterChange = (newFilters: Partial<LogFilters>) => {\n    setFilters((prev) => ({ ...prev, ...newFilters }))\n  }\n\n  const handleLogSelect = (log: LogEntry) => {\n    setSelectedLog(log)\n  }\n\n  const handleLogDeselect = () => {\n    setSelectedLog(null)\n  }\n\n  if (loading) {\n    return (\n      <div className=\"logs-explorer\">\n        <div className=\"loading-state\">Loading logs...</div>\n      </div>\n    )\n  }\n\n  if (error) {\n    return (\n      <div className=\"logs-explorer\">\n        <div className=\"error-state\">Error loading logs: {error.message}</div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"logs-explorer\">\n      <div className=\"logs-header\">\n        <h1>Logs Explorer</h1>\n        <div className=\"logs-stats\">\n          {filteredLogs.length} of {data?.logs?.length || 0} logs\n        </div>\n      </div>\n\n      <SearchBar\n        value={filters.search}\n        onChange={(search) => handleFilterChange({ search })}\n        placeholder=\"Search log messages...\"\n      />\n\n      <div className=\"logs-content\">\n        <FilterSidebar facets={data?.facets} filters={filters} onFilterChange={handleFilterChange} />\n\n        <div className=\"logs-main\">\n          <LogTable logs={filteredLogs} selectedLog={selectedLog} onLogSelect={handleLogSelect} />\n\n          {selectedLog && <LogDetails log={selectedLog} onClose={handleLogDeselect} />}\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/SearchBar.css",
    "content": ".search-bar {\n  margin-bottom: var(--spacing-md);\n}\n\n.search-input-container {\n  position: relative;\n  display: flex;\n  align-items: center;\n  max-width: 600px;\n}\n\n.search-input {\n  width: 100%;\n  padding: var(--spacing-sm) var(--spacing-md);\n  padding-left: 40px;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  color: var(--color-text);\n  font-size: var(--font-size-md);\n  font-family: var(--font-family);\n  transition: all 0.2s ease;\n}\n\n.search-input:focus {\n  outline: none;\n  border-color: var(--color-primary);\n  box-shadow: 0 0 0 3px rgba(99, 44, 166, 0.1);\n}\n\n.search-input::placeholder {\n  color: var(--color-text-muted);\n}\n\n.search-icon {\n  position: absolute;\n  left: var(--spacing-sm);\n  width: 20px;\n  height: 20px;\n  color: var(--color-text-muted);\n  pointer-events: none;\n  z-index: 1;\n}\n\n.search-clear {\n  position: absolute;\n  right: var(--spacing-sm);\n  background: none;\n  border: none;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  color: var(--color-text-muted);\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  transition: all 0.2s ease;\n}\n\n.search-clear:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n}\n\n.search-clear svg {\n  width: 16px;\n  height: 16px;\n}\n\n@media (max-width: 768px) {\n  .search-input-container {\n    max-width: 100%;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Logs/SearchBar.tsx",
    "content": "import React, { useState, useCallback, useEffect } from 'react'\nimport { useDebounce } from '../../hooks/useDebounce'\nimport './SearchBar.css'\n\ninterface SearchBarProps {\n  value: string\n  onChange: (value: string) => void\n  placeholder?: string\n}\n\nexport default function SearchBar({ value, onChange, placeholder = 'Search...' }: SearchBarProps) {\n  const [localValue, setLocalValue] = useState(value)\n\n  const debouncedValue = useDebounce(localValue, 300)\n\n  useEffect(() => {\n    if (debouncedValue !== value) {\n      onChange(debouncedValue)\n    }\n  }, [debouncedValue, onChange, value])\n\n  const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n    const newValue = e.target.value\n    setLocalValue(newValue)\n  }, [])\n\n  const handleClear = useCallback(() => {\n    setLocalValue('')\n    onChange('')\n  }, [onChange])\n\n  const handleKeyDown = useCallback(\n    (e: React.KeyboardEvent<HTMLInputElement>) => {\n      if (e.key === 'Escape') {\n        handleClear()\n      }\n    },\n    [handleClear]\n  )\n\n  return (\n    <div className=\"search-bar\">\n      <div className=\"search-input-container\">\n        <svg className=\"search-icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n          <path\n            fillRule=\"evenodd\"\n            d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\"\n            clipRule=\"evenodd\"\n          />\n        </svg>\n\n        <input\n          type=\"text\"\n          className=\"search-input\"\n          value={localValue}\n          onChange={handleInputChange}\n          onKeyDown={handleKeyDown}\n          placeholder={placeholder}\n          autoComplete=\"off\"\n          spellCheck={false}\n        />\n\n        {localValue && (\n          <button className=\"search-clear\" onClick={handleClear} type=\"button\" aria-label=\"Clear search\">\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path\n                fillRule=\"evenodd\"\n                d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n                clipRule=\"evenodd\"\n              />\n            </svg>\n          </button>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/Integrations.css",
    "content": ".integrations {\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-lg);\n}\n\n.integrations-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  margin-bottom: var(--spacing-xl);\n  gap: var(--spacing-md);\n}\n\n.integrations-header h2 {\n  margin: 0 0 var(--spacing-xs) 0;\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.integrations-header p {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n.integrations-stats {\n  display: flex;\n  flex-direction: column;\n  align-items: flex-end;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n}\n\n.integrations-stats .stat-value {\n  font-size: var(--font-size-xl);\n  font-weight: 700;\n  color: var(--color-text);\n  font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;\n}\n\n.integrations-stats .stat-label {\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n}\n\n.integrations-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n  gap: var(--spacing-lg);\n}\n\n.integration-card {\n  background: var(--color-surface-elevated);\n  border: 2px solid var(--color-border);\n  border-radius: 8px;\n  padding: var(--spacing-lg);\n  transition: all 0.3s ease;\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-md);\n}\n\n.integration-card:hover {\n  transform: translateY(-2px);\n  box-shadow: var(--shadow-md);\n}\n\n.integration-card.enabled {\n  border-color: var(--color-success);\n  background: linear-gradient(135deg, var(--color-surface-elevated) 0%, rgba(62, 191, 98, 0.05) 100%);\n}\n\n.integration-card.toggling {\n  opacity: 0.6;\n  pointer-events: none;\n}\n\n.integration-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n}\n\n.integration-icon {\n  width: 48px;\n  height: 48px;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 8px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 24px;\n}\n\n.integration-status {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n}\n\n.status-dot {\n  width: 8px;\n  height: 8px;\n  border-radius: 50%;\n  background: var(--color-text-muted);\n  transition: all 0.3s ease;\n}\n\n.status-dot.active {\n  background: var(--color-success);\n  box-shadow: 0 0 8px rgba(62, 191, 98, 0.5);\n}\n\n.status-text {\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.integration-body {\n  flex: 1;\n}\n\n.integration-body h3 {\n  margin: 0 0 var(--spacing-xs) 0;\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.integration-type {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n  text-transform: capitalize;\n}\n\n.integration-footer {\n  display: flex;\n  gap: var(--spacing-sm);\n}\n\n.toggle-btn {\n  flex: 1;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: var(--spacing-xs);\n  padding: var(--spacing-sm) var(--spacing-md);\n  border: none;\n  border-radius: 4px;\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n  font-family: var(--font-family);\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.toggle-btn svg {\n  width: 16px;\n  height: 16px;\n}\n\n.toggle-btn.connect {\n  background: var(--color-primary);\n  color: white;\n}\n\n.toggle-btn.connect:hover:not(:disabled) {\n  background: var(--color-primary-hover);\n}\n\n.toggle-btn.disconnect {\n  background: var(--color-surface);\n  color: var(--color-text);\n  border: 1px solid var(--color-border);\n}\n\n.toggle-btn.disconnect:hover:not(:disabled) {\n  background: rgba(255, 82, 82, 0.1);\n  border-color: var(--color-error);\n  color: var(--color-error);\n}\n\n.toggle-btn:disabled {\n  opacity: 0.6;\n  cursor: not-allowed;\n}\n\n.spinner {\n  width: 14px;\n  height: 14px;\n  border: 2px solid currentColor;\n  border-top-color: transparent;\n  border-radius: 50%;\n  animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n\n.settings-btn {\n  width: 40px;\n  height: 40px;\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text-secondary);\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  transition: all 0.2s ease;\n}\n\n.settings-btn svg {\n  width: 18px;\n  height: 18px;\n}\n\n.settings-btn:hover {\n  background: var(--color-surface-hover);\n  color: var(--color-text);\n  border-color: var(--color-primary);\n}\n\n@media (max-width: 1024px) {\n  .integrations-grid {\n    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n  }\n}\n\n@media (max-width: 768px) {\n  .integrations {\n    padding: var(--spacing-md);\n  }\n\n  .integrations-header {\n    flex-direction: column;\n  }\n\n  .integrations-stats {\n    width: 100%;\n    flex-direction: row;\n    justify-content: space-between;\n    align-items: center;\n  }\n\n  .integrations-grid {\n    grid-template-columns: 1fr;\n  }\n\n  .toggle-btn {\n    font-size: var(--font-size-xs);\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/Integrations.tsx",
    "content": "import { useState, useCallback } from 'react'\nimport { Integration } from '../../types/data'\nimport './Integrations.css'\n\ninterface IntegrationsProps {\n  initialIntegrations: Integration[]\n  onUpdate: (integrations: Integration[]) => void\n}\n\nconst INTEGRATION_ICONS: Record<string, string> = {\n  slack: '💬',\n  github: '🐙',\n  jira: '📋',\n  pagerduty: '🚨',\n  datadog: '🐶',\n  aws: '☁️',\n  gcp: '🌩️',\n  azure: '🔷',\n  stripe: '💳',\n  sendgrid: '📧',\n  twilio: '📱',\n  postgres: '🐘',\n}\n\nexport default function Integrations({ initialIntegrations, onUpdate }: IntegrationsProps) {\n  const [integrations, setIntegrations] = useState<Integration[]>(initialIntegrations)\n  const [togglingId, setTogglingId] = useState<string | null>(null)\n\n  const handleToggle = useCallback(\n    async (id: string) => {\n      setTogglingId(id)\n\n      // Simulate API call\n      await new Promise((resolve) => setTimeout(resolve, 500))\n\n      const updatedIntegrations = integrations.map((integration) =>\n        integration.id === id ? { ...integration, enabled: !integration.enabled } : integration\n      )\n\n      setIntegrations(updatedIntegrations)\n      onUpdate(updatedIntegrations)\n      setTogglingId(null)\n    },\n    [integrations, onUpdate]\n  )\n\n  const enabledCount = integrations.filter((i) => i.enabled).length\n\n  return (\n    <div className=\"integrations\">\n      <div className=\"integrations-header\">\n        <div>\n          <h2>Integrations</h2>\n          <p>Connect and manage third-party services</p>\n        </div>\n        <div className=\"integrations-stats\">\n          <span className=\"stat-value\">{enabledCount}</span>\n          <span className=\"stat-label\">of {integrations.length} enabled</span>\n        </div>\n      </div>\n\n      <div className=\"integrations-grid\">\n        {integrations.map((integration) => (\n          <div\n            key={integration.id}\n            className={`integration-card ${integration.enabled ? 'enabled' : 'disabled'} ${\n              togglingId === integration.id ? 'toggling' : ''\n            }`}\n          >\n            <div className=\"integration-header\">\n              <div className=\"integration-icon\">{INTEGRATION_ICONS[integration.id] || '🔌'}</div>\n              <div className=\"integration-status\">\n                <span className={`status-dot ${integration.enabled ? 'active' : ''}`} />\n                <span className=\"status-text\">{integration.enabled ? 'Connected' : 'Disconnected'}</span>\n              </div>\n            </div>\n\n            <div className=\"integration-body\">\n              <h3>{integration.name}</h3>\n              <p className=\"integration-type\">{integration.type}</p>\n            </div>\n\n            <div className=\"integration-footer\">\n              <button\n                className={`toggle-btn ${integration.enabled ? 'disconnect' : 'connect'}`}\n                onClick={() => handleToggle(integration.id)}\n                disabled={togglingId === integration.id}\n              >\n                {togglingId === integration.id ? (\n                  <>\n                    <span className=\"spinner\" />\n                    {integration.enabled ? 'Disconnecting...' : 'Connecting...'}\n                  </>\n                ) : (\n                  <>\n                    {integration.enabled ? (\n                      <>\n                        <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n                          <path\n                            fillRule=\"evenodd\"\n                            d=\"M13.477 14.89A6 6 0 015.11 6.524l8.367 8.368zm1.414-1.414L6.524 5.11a6 6 0 018.367 8.367zM18 10a8 8 0 11-16 0 8 8 0 0116 0z\"\n                            clipRule=\"evenodd\"\n                          />\n                        </svg>\n                        Disconnect\n                      </>\n                    ) : (\n                      <>\n                        <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n                          <path\n                            fillRule=\"evenodd\"\n                            d=\"M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z\"\n                            clipRule=\"evenodd\"\n                          />\n                        </svg>\n                        Connect\n                      </>\n                    )}\n                  </>\n                )}\n              </button>\n\n              {integration.enabled && (\n                <button className=\"settings-btn\" title=\"Configure integration\" aria-label=\"Configure integration\">\n                  <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n                    <path\n                      fillRule=\"evenodd\"\n                      d=\"M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z\"\n                      clipRule=\"evenodd\"\n                    />\n                  </svg>\n                </button>\n              )}\n            </div>\n          </div>\n        ))}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/Settings.css",
    "content": ".settings {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  background: var(--color-bg);\n  color: var(--color-text);\n  padding: var(--spacing-lg);\n  gap: var(--spacing-lg);\n}\n\n.settings-header {\n  margin-bottom: var(--spacing-md);\n}\n\n.settings-header h1 {\n  margin: 0 0 var(--spacing-xs) 0;\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.settings-header p {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n.settings-tabs {\n  display: flex;\n  gap: var(--spacing-xs);\n  background: var(--color-surface);\n  padding: 4px;\n  border-radius: 8px;\n  border: 1px solid var(--color-border);\n  overflow-x: auto;\n}\n\n.tab-button {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-xs);\n  padding: var(--spacing-sm) var(--spacing-lg);\n  background: transparent;\n  border: none;\n  border-radius: 6px;\n  color: var(--color-text-secondary);\n  font-size: var(--font-size-md);\n  font-weight: 500;\n  font-family: var(--font-family);\n  cursor: pointer;\n  transition: all 0.2s ease;\n  white-space: nowrap;\n}\n\n.tab-button svg {\n  width: 18px;\n  height: 18px;\n  flex-shrink: 0;\n}\n\n.tab-button:hover {\n  color: var(--color-text);\n  background: var(--color-surface-hover);\n}\n\n.tab-button.active {\n  background: var(--color-primary);\n  color: white;\n}\n\n.tab-badge {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  min-width: 20px;\n  height: 20px;\n  padding: 0 6px;\n  background: rgba(255, 255, 255, 0.2);\n  border-radius: 10px;\n  font-size: var(--font-size-xs);\n  font-weight: 600;\n}\n\n.tab-button.active .tab-badge {\n  background: rgba(255, 255, 255, 0.3);\n}\n\n.settings-content {\n  flex: 1;\n  overflow-y: auto;\n  min-height: 0;\n}\n\n/* Shared form styles from UserSettings.css are imported */\n.form-group {\n  margin-bottom: var(--spacing-lg);\n}\n\n.form-label {\n  display: block;\n  margin-bottom: var(--spacing-xs);\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.required {\n  color: var(--color-error);\n}\n\n.form-input,\n.form-select {\n  width: 100%;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text);\n  font-size: var(--font-size-md);\n  font-family: var(--font-family);\n  transition: all 0.2s ease;\n}\n\n.form-input:focus,\n.form-select:focus {\n  outline: none;\n  border-color: var(--color-primary);\n  box-shadow: 0 0 0 3px rgba(99, 44, 166, 0.1);\n}\n\n.form-input.error,\n.form-select.error {\n  border-color: var(--color-error);\n}\n\n.form-input.error:focus,\n.form-select.error:focus {\n  box-shadow: 0 0 0 3px rgba(255, 82, 82, 0.1);\n}\n\n.error-message {\n  display: block;\n  margin-top: var(--spacing-xs);\n  font-size: var(--font-size-xs);\n  color: var(--color-error);\n}\n\n.form-actions {\n  display: flex;\n  gap: var(--spacing-md);\n  margin-top: var(--spacing-xl);\n}\n\n.btn {\n  padding: var(--spacing-sm) var(--spacing-lg);\n  border: none;\n  border-radius: 4px;\n  font-size: var(--font-size-md);\n  font-weight: 600;\n  font-family: var(--font-family);\n  cursor: pointer;\n  transition: all 0.2s ease;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  min-width: 120px;\n}\n\n.btn:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n}\n\n.btn-primary {\n  background: var(--color-primary);\n  color: white;\n}\n\n.btn-primary:hover:not(:disabled) {\n  background: var(--color-primary-hover);\n}\n\n.btn-secondary {\n  background: var(--color-surface-elevated);\n  color: var(--color-text);\n  border: 1px solid var(--color-border);\n}\n\n.btn-secondary:hover:not(:disabled) {\n  background: var(--color-surface-hover);\n}\n\n@media (max-width: 1024px) {\n  .settings-tabs {\n    padding: 2px;\n  }\n\n  .tab-button {\n    padding: var(--spacing-sm) var(--spacing-md);\n    font-size: var(--font-size-sm);\n  }\n}\n\n@media (max-width: 768px) {\n  .settings {\n    padding: var(--spacing-md);\n  }\n\n  .settings-header {\n    margin-bottom: var(--spacing-sm);\n  }\n\n  .settings-tabs {\n    overflow-x: auto;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .settings-tabs::-webkit-scrollbar {\n    display: none;\n  }\n\n  .tab-button {\n    font-size: var(--font-size-xs);\n  }\n\n  .tab-badge {\n    font-size: 10px;\n    min-width: 16px;\n    height: 16px;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/Settings.tsx",
    "content": "import { useState, useCallback } from 'react'\nimport { UserSettings as UserSettingsType, TeamMember, Integration } from '../../types/data'\nimport UserSettings from './UserSettings'\nimport TeamManagement from './TeamManagement'\nimport Integrations from './Integrations'\nimport './Settings.css'\n\n// Mock initial data\nconst INITIAL_USER_SETTINGS: UserSettingsType = {\n  name: 'John Doe',\n  email: 'john.doe@example.com',\n  role: 'Admin',\n  notifications: true,\n  timezone: 'America/New_York',\n}\n\nconst INITIAL_TEAM: TeamMember[] = [\n  {\n    id: 'member-1',\n    name: 'Alice Johnson',\n    email: 'alice.johnson@example.com',\n    role: 'Developer',\n  },\n  {\n    id: 'member-2',\n    name: 'Bob Smith',\n    email: 'bob.smith@example.com',\n    role: 'Developer',\n  },\n  {\n    id: 'member-3',\n    name: 'Carol Williams',\n    email: 'carol.williams@example.com',\n    role: 'Manager',\n  },\n  {\n    id: 'member-4',\n    name: 'David Brown',\n    email: 'david.brown@example.com',\n    role: 'Viewer',\n  },\n]\n\nconst INITIAL_INTEGRATIONS: Integration[] = [\n  { id: 'slack', name: 'Slack', enabled: true, type: 'communication' },\n  { id: 'github', name: 'GitHub', enabled: true, type: 'version control' },\n  { id: 'jira', name: 'Jira', enabled: true, type: 'project management' },\n  { id: 'pagerduty', name: 'PagerDuty', enabled: false, type: 'incident management' },\n  { id: 'datadog', name: 'Datadog', enabled: true, type: 'monitoring' },\n  { id: 'aws', name: 'Amazon Web Services', enabled: true, type: 'cloud provider' },\n  { id: 'gcp', name: 'Google Cloud Platform', enabled: false, type: 'cloud provider' },\n  { id: 'azure', name: 'Microsoft Azure', enabled: false, type: 'cloud provider' },\n  { id: 'stripe', name: 'Stripe', enabled: true, type: 'payment' },\n  { id: 'sendgrid', name: 'SendGrid', enabled: true, type: 'email' },\n  { id: 'twilio', name: 'Twilio', enabled: false, type: 'sms' },\n  { id: 'postgres', name: 'PostgreSQL', enabled: true, type: 'database' },\n]\n\ntype TabType = 'user' | 'team' | 'integrations'\n\nexport default function Settings() {\n  const [activeTab, setActiveTab] = useState<TabType>('user')\n  const [userSettings, setUserSettings] = useState<UserSettingsType>(INITIAL_USER_SETTINGS)\n  const [team, setTeam] = useState<TeamMember[]>(INITIAL_TEAM)\n  const [integrations, setIntegrations] = useState<Integration[]>(INITIAL_INTEGRATIONS)\n\n  const handleUserSettingsSave = useCallback((settings: UserSettingsType) => {\n    setUserSettings(settings)\n    console.log('User settings saved:', settings)\n  }, [])\n\n  const handleTeamUpdate = useCallback((updatedTeam: TeamMember[]) => {\n    setTeam(updatedTeam)\n    console.log('Team updated:', updatedTeam)\n  }, [])\n\n  const handleIntegrationsUpdate = useCallback((updatedIntegrations: Integration[]) => {\n    setIntegrations(updatedIntegrations)\n    console.log('Integrations updated:', updatedIntegrations)\n  }, [])\n\n  return (\n    <div className=\"settings\">\n      <div className=\"settings-header\">\n        <h1>Settings</h1>\n        <p>Manage your account, team, and integrations</p>\n      </div>\n\n      <div className=\"settings-tabs\">\n        <button className={`tab-button ${activeTab === 'user' ? 'active' : ''}`} onClick={() => setActiveTab('user')}>\n          <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n            <path fillRule=\"evenodd\" d=\"M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z\" clipRule=\"evenodd\" />\n          </svg>\n          User Settings\n        </button>\n        <button className={`tab-button ${activeTab === 'team' ? 'active' : ''}`} onClick={() => setActiveTab('team')}>\n          <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n            <path d=\"M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z\" />\n          </svg>\n          Team\n          <span className=\"tab-badge\">{team.length}</span>\n        </button>\n        <button\n          className={`tab-button ${activeTab === 'integrations' ? 'active' : ''}`}\n          onClick={() => setActiveTab('integrations')}\n        >\n          <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n            <path\n              fillRule=\"evenodd\"\n              d=\"M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z\"\n              clipRule=\"evenodd\"\n            />\n          </svg>\n          Integrations\n          <span className=\"tab-badge\">{integrations.filter((i) => i.enabled).length}</span>\n        </button>\n      </div>\n\n      <div className=\"settings-content\">\n        {activeTab === 'user' && <UserSettings initialSettings={userSettings} onSave={handleUserSettingsSave} />}\n        {activeTab === 'team' && <TeamManagement initialTeam={team} onUpdate={handleTeamUpdate} />}\n        {activeTab === 'integrations' && (\n          <Integrations initialIntegrations={integrations} onUpdate={handleIntegrationsUpdate} />\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/TeamManagement.css",
    "content": ".team-management {\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-lg);\n}\n\n.team-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  margin-bottom: var(--spacing-xl);\n  gap: var(--spacing-md);\n}\n\n.team-header h2 {\n  margin: 0 0 var(--spacing-xs) 0;\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.team-header p {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n.team-header .btn svg {\n  width: 16px;\n  height: 16px;\n  margin-right: var(--spacing-xs);\n}\n\n.add-member-form {\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-lg);\n  margin-bottom: var(--spacing-xl);\n}\n\n.add-member-form h3 {\n  margin: 0 0 var(--spacing-md) 0;\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.form-row {\n  display: grid;\n  grid-template-columns: 1fr 1fr 180px;\n  gap: var(--spacing-md);\n  margin-bottom: var(--spacing-md);\n}\n\n.team-list {\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  overflow: hidden;\n}\n\n.team-list-header {\n  padding: var(--spacing-md) var(--spacing-lg);\n  background: var(--color-surface);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.team-count {\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.team-members {\n  display: flex;\n  flex-direction: column;\n}\n\n.team-member {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-md);\n  padding: var(--spacing-lg);\n  border-bottom: 1px solid var(--color-border);\n  transition: all 0.3s ease;\n}\n\n.team-member:last-child {\n  border-bottom: none;\n}\n\n.team-member:hover {\n  background: var(--color-surface-hover);\n}\n\n.team-member.removing {\n  opacity: 0;\n  transform: translateX(-20px);\n}\n\n.member-avatar {\n  width: 48px;\n  height: 48px;\n  border-radius: 50%;\n  background: var(--color-primary);\n  color: white;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  flex-shrink: 0;\n}\n\n.member-info {\n  flex: 1;\n  min-width: 0;\n}\n\n.member-info h4 {\n  margin: 0 0 2px 0;\n  font-size: var(--font-size-md);\n  font-weight: 600;\n  color: var(--color-text);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.member-info p {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.member-role {\n  min-width: 150px;\n}\n\n.role-select {\n  width: 100%;\n  padding: var(--spacing-xs) var(--spacing-sm);\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text);\n  font-size: var(--font-size-sm);\n  font-family: var(--font-family);\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.role-select:hover {\n  border-color: var(--color-primary);\n}\n\n.role-select:focus {\n  outline: none;\n  border-color: var(--color-primary);\n  box-shadow: 0 0 0 3px rgba(99, 44, 166, 0.1);\n}\n\n.remove-btn {\n  background: none;\n  border: none;\n  color: var(--color-text-secondary);\n  cursor: pointer;\n  padding: var(--spacing-xs);\n  border-radius: 4px;\n  transition: all 0.2s ease;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-shrink: 0;\n}\n\n.remove-btn svg {\n  width: 20px;\n  height: 20px;\n}\n\n.remove-btn:hover {\n  background: rgba(255, 82, 82, 0.1);\n  color: var(--color-error);\n}\n\n.empty-state {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  padding: var(--spacing-2xl);\n  text-align: center;\n}\n\n.empty-state svg {\n  width: 64px;\n  height: 64px;\n  color: var(--color-text-muted);\n  opacity: 0.5;\n  margin-bottom: var(--spacing-md);\n}\n\n.empty-state p {\n  margin: 0 0 var(--spacing-lg) 0;\n  font-size: var(--font-size-md);\n  color: var(--color-text-secondary);\n}\n\n@media (max-width: 1024px) {\n  .form-row {\n    grid-template-columns: 1fr;\n  }\n\n  .member-role {\n    min-width: 120px;\n  }\n}\n\n@media (max-width: 768px) {\n  .team-management {\n    padding: var(--spacing-md);\n  }\n\n  .team-header {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n\n  .team-header .btn {\n    width: 100%;\n  }\n\n  .add-member-form {\n    padding: var(--spacing-md);\n  }\n\n  .team-member {\n    flex-wrap: wrap;\n    padding: var(--spacing-md);\n  }\n\n  .member-role {\n    width: 100%;\n    order: 3;\n  }\n\n  .remove-btn {\n    order: 2;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/TeamManagement.tsx",
    "content": "import { useState, useCallback } from 'react'\nimport { TeamMember } from '../../types/data'\nimport './TeamManagement.css'\n\ninterface TeamManagementProps {\n  initialTeam: TeamMember[]\n  onUpdate: (team: TeamMember[]) => void\n}\n\ninterface NewMemberForm {\n  name: string\n  email: string\n  role: string\n}\n\ninterface FormErrors {\n  name?: string\n  email?: string\n}\n\nconst ROLES = ['Admin', 'Developer', 'Viewer', 'Manager']\n\nexport default function TeamManagement({ initialTeam, onUpdate }: TeamManagementProps) {\n  const [team, setTeam] = useState<TeamMember[]>(initialTeam)\n  const [isAddingMember, setIsAddingMember] = useState(false)\n  const [newMember, setNewMember] = useState<NewMemberForm>({\n    name: '',\n    email: '',\n    role: 'Developer',\n  })\n  const [formErrors, setFormErrors] = useState<FormErrors>({})\n  const [removingId, setRemovingId] = useState<string | null>(null)\n\n  const validateNewMember = useCallback((): boolean => {\n    const errors: FormErrors = {}\n\n    if (!newMember.name.trim()) {\n      errors.name = 'Name is required'\n    } else if (newMember.name.trim().length < 2) {\n      errors.name = 'Name must be at least 2 characters'\n    }\n\n    const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n    if (!newMember.email.trim()) {\n      errors.email = 'Email is required'\n    } else if (!emailRegex.test(newMember.email)) {\n      errors.email = 'Invalid email format'\n    } else if (team.some((member) => member.email.toLowerCase() === newMember.email.toLowerCase())) {\n      errors.email = 'This email is already in the team'\n    }\n\n    setFormErrors(errors)\n    return Object.keys(errors).length === 0\n  }, [newMember, team])\n\n  const handleAddMember = useCallback(() => {\n    if (!validateNewMember()) {\n      return\n    }\n\n    const member: TeamMember = {\n      id: `member-${Date.now()}`,\n      name: newMember.name.trim(),\n      email: newMember.email.trim().toLowerCase(),\n      role: newMember.role,\n    }\n\n    const updatedTeam = [...team, member]\n    setTeam(updatedTeam)\n    onUpdate(updatedTeam)\n\n    // Reset form\n    setNewMember({ name: '', email: '', role: 'Developer' })\n    setFormErrors({})\n    setIsAddingMember(false)\n  }, [newMember, team, onUpdate, validateNewMember])\n\n  const handleRemoveMember = useCallback(\n    (id: string) => {\n      setRemovingId(id)\n\n      // Animate removal\n      setTimeout(() => {\n        const updatedTeam = team.filter((member) => member.id !== id)\n        setTeam(updatedTeam)\n        onUpdate(updatedTeam)\n        setRemovingId(null)\n      }, 300)\n    },\n    [team, onUpdate]\n  )\n\n  const handleUpdateRole = useCallback(\n    (id: string, newRole: string) => {\n      const updatedTeam = team.map((member) => (member.id === id ? { ...member, role: newRole } : member))\n      setTeam(updatedTeam)\n      onUpdate(updatedTeam)\n    },\n    [team, onUpdate]\n  )\n\n  const handleCancelAdd = useCallback(() => {\n    setIsAddingMember(false)\n    setNewMember({ name: '', email: '', role: 'Developer' })\n    setFormErrors({})\n  }, [])\n\n  const handleInputChange = useCallback(\n    (field: keyof NewMemberForm, value: string) => {\n      setNewMember((prev) => ({ ...prev, [field]: value }))\n      if (formErrors[field as keyof FormErrors]) {\n        setFormErrors((prev) => ({ ...prev, [field]: undefined }))\n      }\n    },\n    [formErrors]\n  )\n\n  return (\n    <div className=\"team-management\">\n      <div className=\"team-header\">\n        <div>\n          <h2>Team Management</h2>\n          <p>Manage team members and their roles</p>\n        </div>\n        {!isAddingMember && (\n          <button className=\"btn btn-primary\" onClick={() => setIsAddingMember(true)}>\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path d=\"M8 9a3 3 0 100-6 3 3 0 000 6zM8 11a6 6 0 016 6H2a6 6 0 016-6zM16 7a1 1 0 10-2 0v1h-1a1 1 0 100 2h1v1a1 1 0 102 0v-1h1a1 1 0 100-2h-1V7z\" />\n            </svg>\n            Add Member\n          </button>\n        )}\n      </div>\n\n      {isAddingMember && (\n        <div className=\"add-member-form\">\n          <h3>Add New Team Member</h3>\n          <div className=\"form-row\">\n            <div className=\"form-group\">\n              <label htmlFor=\"member-name\" className=\"form-label\">\n                Name <span className=\"required\">*</span>\n              </label>\n              <input\n                id=\"member-name\"\n                type=\"text\"\n                className={`form-input ${formErrors.name ? 'error' : ''}`}\n                value={newMember.name}\n                onChange={(e) => handleInputChange('name', e.target.value)}\n                placeholder=\"John Doe\"\n              />\n              {formErrors.name && <span className=\"error-message\">{formErrors.name}</span>}\n            </div>\n\n            <div className=\"form-group\">\n              <label htmlFor=\"member-email\" className=\"form-label\">\n                Email <span className=\"required\">*</span>\n              </label>\n              <input\n                id=\"member-email\"\n                type=\"email\"\n                className={`form-input ${formErrors.email ? 'error' : ''}`}\n                value={newMember.email}\n                onChange={(e) => handleInputChange('email', e.target.value)}\n                placeholder=\"john.doe@example.com\"\n              />\n              {formErrors.email && <span className=\"error-message\">{formErrors.email}</span>}\n            </div>\n\n            <div className=\"form-group\">\n              <label htmlFor=\"member-role\" className=\"form-label\">\n                Role\n              </label>\n              <select\n                id=\"member-role\"\n                className=\"form-select\"\n                value={newMember.role}\n                onChange={(e) => handleInputChange('role', e.target.value)}\n              >\n                {ROLES.map((role) => (\n                  <option key={role} value={role}>\n                    {role}\n                  </option>\n                ))}\n              </select>\n            </div>\n          </div>\n\n          <div className=\"form-actions\">\n            <button className=\"btn btn-secondary\" onClick={handleCancelAdd}>\n              Cancel\n            </button>\n            <button className=\"btn btn-primary\" onClick={handleAddMember}>\n              Add Member\n            </button>\n          </div>\n        </div>\n      )}\n\n      <div className=\"team-list\">\n        <div className=\"team-list-header\">\n          <span className=\"team-count\">{team.length} team members</span>\n        </div>\n\n        {team.length === 0 ? (\n          <div className=\"empty-state\">\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path d=\"M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z\" />\n            </svg>\n            <p>No team members yet</p>\n            <button className=\"btn btn-primary\" onClick={() => setIsAddingMember(true)}>\n              Add Your First Member\n            </button>\n          </div>\n        ) : (\n          <div className=\"team-members\">\n            {team.map((member) => (\n              <div key={member.id} className={`team-member ${removingId === member.id ? 'removing' : ''}`}>\n                <div className=\"member-avatar\">{member.name.charAt(0).toUpperCase()}</div>\n                <div className=\"member-info\">\n                  <h4>{member.name}</h4>\n                  <p>{member.email}</p>\n                </div>\n                <div className=\"member-role\">\n                  <select\n                    className=\"role-select\"\n                    value={member.role}\n                    onChange={(e) => handleUpdateRole(member.id, e.target.value)}\n                  >\n                    {ROLES.map((role) => (\n                      <option key={role} value={role}>\n                        {role}\n                      </option>\n                    ))}\n                  </select>\n                </div>\n                <button\n                  className=\"remove-btn\"\n                  onClick={() => handleRemoveMember(member.id)}\n                  aria-label={`Remove ${member.name}`}\n                  title=\"Remove member\"\n                >\n                  <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n                    <path\n                      fillRule=\"evenodd\"\n                      d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n                      clipRule=\"evenodd\"\n                    />\n                  </svg>\n                </button>\n              </div>\n            ))}\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/UserSettings.css",
    "content": ".user-settings {\n  background: var(--color-surface);\n  border: 1px solid var(--color-border);\n  border-radius: 6px;\n  padding: var(--spacing-lg);\n}\n\n.user-settings-header {\n  margin-bottom: var(--spacing-xl);\n}\n\n.user-settings-header h2 {\n  margin: 0 0 var(--spacing-xs) 0;\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.user-settings-header p {\n  margin: 0;\n  font-size: var(--font-size-sm);\n  color: var(--color-text-secondary);\n}\n\n.user-settings-form {\n  max-width: 600px;\n}\n\n.form-group {\n  margin-bottom: var(--spacing-lg);\n}\n\n.form-label {\n  display: block;\n  margin-bottom: var(--spacing-xs);\n  font-size: var(--font-size-sm);\n  font-weight: 600;\n  color: var(--color-text);\n}\n\n.required {\n  color: var(--color-error);\n}\n\n.form-input,\n.form-select {\n  width: 100%;\n  padding: var(--spacing-sm) var(--spacing-md);\n  background: var(--color-surface-elevated);\n  border: 1px solid var(--color-border);\n  border-radius: 4px;\n  color: var(--color-text);\n  font-size: var(--font-size-md);\n  font-family: var(--font-family);\n  transition: all 0.2s ease;\n}\n\n.form-input:focus,\n.form-select:focus {\n  outline: none;\n  border-color: var(--color-primary);\n  box-shadow: 0 0 0 3px rgba(99, 44, 166, 0.1);\n}\n\n.form-input.error,\n.form-select.error {\n  border-color: var(--color-error);\n}\n\n.form-input.error:focus,\n.form-select.error:focus {\n  box-shadow: 0 0 0 3px rgba(255, 82, 82, 0.1);\n}\n\n.form-select {\n  cursor: pointer;\n  appearance: none;\n  background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%23888888' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");\n  background-position: right 0.5rem center;\n  background-repeat: no-repeat;\n  background-size: 1.5em 1.5em;\n  padding-right: 2.5rem;\n}\n\n.error-message {\n  display: block;\n  margin-top: var(--spacing-xs);\n  font-size: var(--font-size-xs);\n  color: var(--color-error);\n}\n\n.checkbox-group {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-xs);\n}\n\n.checkbox-label {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  cursor: pointer;\n  font-size: var(--font-size-md);\n  color: var(--color-text);\n}\n\n.form-checkbox {\n  width: 18px;\n  height: 18px;\n  cursor: pointer;\n  accent-color: var(--color-primary);\n}\n\n.checkbox-description {\n  margin: 0;\n  padding-left: 26px;\n  font-size: var(--font-size-xs);\n  color: var(--color-text-secondary);\n}\n\n.form-actions {\n  display: flex;\n  gap: var(--spacing-md);\n  margin-top: var(--spacing-xl);\n}\n\n.btn {\n  padding: var(--spacing-sm) var(--spacing-lg);\n  border: none;\n  border-radius: 4px;\n  font-size: var(--font-size-md);\n  font-weight: 600;\n  font-family: var(--font-family);\n  cursor: pointer;\n  transition: all 0.2s ease;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  min-width: 120px;\n}\n\n.btn:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n}\n\n.btn-primary {\n  background: var(--color-primary);\n  color: white;\n}\n\n.btn-primary:hover:not(:disabled) {\n  background: var(--color-primary-hover);\n}\n\n.btn-secondary {\n  background: var(--color-surface-elevated);\n  color: var(--color-text);\n  border: 1px solid var(--color-border);\n}\n\n.btn-secondary:hover:not(:disabled) {\n  background: var(--color-surface-hover);\n}\n\n.save-success {\n  display: flex;\n  align-items: center;\n  gap: var(--spacing-sm);\n  margin-top: var(--spacing-md);\n  padding: var(--spacing-md);\n  background: rgba(62, 191, 98, 0.1);\n  border: 1px solid var(--color-success);\n  border-radius: 4px;\n  color: var(--color-success);\n  font-size: var(--font-size-sm);\n  font-weight: 500;\n  animation: slideIn 0.3s ease;\n}\n\n.save-success svg {\n  width: 20px;\n  height: 20px;\n  flex-shrink: 0;\n}\n\n@keyframes slideIn {\n  from {\n    opacity: 0;\n    transform: translateY(-10px);\n  }\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n@media (max-width: 768px) {\n  .user-settings {\n    padding: var(--spacing-md);\n  }\n\n  .user-settings-form {\n    max-width: 100%;\n  }\n\n  .form-actions {\n    flex-direction: column;\n  }\n\n  .btn {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/components/Settings/UserSettings.tsx",
    "content": "import { useState, useCallback } from 'react'\nimport { UserSettings as UserSettingsType } from '../../types/data'\nimport './UserSettings.css'\n\ninterface UserSettingsProps {\n  initialSettings: UserSettingsType\n  onSave: (settings: UserSettingsType) => void\n}\n\ninterface ValidationErrors {\n  name?: string\n  email?: string\n  timezone?: string\n}\n\nconst TIMEZONES = [\n  'UTC',\n  'America/New_York',\n  'America/Chicago',\n  'America/Denver',\n  'America/Los_Angeles',\n  'Europe/London',\n  'Europe/Paris',\n  'Europe/Berlin',\n  'Asia/Tokyo',\n  'Asia/Shanghai',\n  'Asia/Dubai',\n  'Australia/Sydney',\n]\n\nconst ROLES = ['Admin', 'Developer', 'Viewer', 'Manager']\n\nexport default function UserSettings({ initialSettings, onSave }: UserSettingsProps) {\n  const [settings, setSettings] = useState<UserSettingsType>(initialSettings)\n  const [errors, setErrors] = useState<ValidationErrors>({})\n  const [isDirty, setIsDirty] = useState(false)\n  const [isSaving, setIsSaving] = useState(false)\n  const [saveSuccess, setSaveSuccess] = useState(false)\n\n  const validateForm = useCallback((): boolean => {\n    const newErrors: ValidationErrors = {}\n\n    // Name validation\n    if (!settings.name.trim()) {\n      newErrors.name = 'Name is required'\n    } else if (settings.name.trim().length < 2) {\n      newErrors.name = 'Name must be at least 2 characters'\n    }\n\n    // Email validation\n    const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n    if (!settings.email.trim()) {\n      newErrors.email = 'Email is required'\n    } else if (!emailRegex.test(settings.email)) {\n      newErrors.email = 'Invalid email format'\n    }\n\n    // Timezone validation\n    if (!settings.timezone) {\n      newErrors.timezone = 'Timezone is required'\n    }\n\n    setErrors(newErrors)\n    return Object.keys(newErrors).length === 0\n  }, [settings])\n\n  const handleInputChange = useCallback(\n    (field: keyof UserSettingsType, value: string | boolean) => {\n      setSettings((prev) => ({ ...prev, [field]: value }))\n      setIsDirty(true)\n      setSaveSuccess(false)\n\n      // Clear error for this field when user starts typing\n      if (errors[field as keyof ValidationErrors]) {\n        setErrors((prev) => ({ ...prev, [field]: undefined }))\n      }\n    },\n    [errors]\n  )\n\n  const handleSubmit = useCallback(\n    async (e: React.FormEvent) => {\n      e.preventDefault()\n\n      if (!validateForm()) {\n        return\n      }\n\n      setIsSaving(true)\n\n      // Simulate API call\n      await new Promise((resolve) => setTimeout(resolve, 800))\n\n      onSave(settings)\n      setIsSaving(false)\n      setIsDirty(false)\n      setSaveSuccess(true)\n\n      // Hide success message after 3 seconds\n      setTimeout(() => setSaveSuccess(false), 3000)\n    },\n    [settings, validateForm, onSave]\n  )\n\n  const handleReset = useCallback(() => {\n    setSettings(initialSettings)\n    setErrors({})\n    setIsDirty(false)\n    setSaveSuccess(false)\n  }, [initialSettings])\n\n  return (\n    <div className=\"user-settings\">\n      <div className=\"user-settings-header\">\n        <h2>User Settings</h2>\n        <p>Manage your account settings and preferences</p>\n      </div>\n\n      <form className=\"user-settings-form\" onSubmit={handleSubmit}>\n        <div className=\"form-group\">\n          <label htmlFor=\"name\" className=\"form-label\">\n            Full Name <span className=\"required\">*</span>\n          </label>\n          <input\n            id=\"name\"\n            type=\"text\"\n            className={`form-input ${errors.name ? 'error' : ''}`}\n            value={settings.name}\n            onChange={(e) => handleInputChange('name', e.target.value)}\n            placeholder=\"Enter your full name\"\n          />\n          {errors.name && <span className=\"error-message\">{errors.name}</span>}\n        </div>\n\n        <div className=\"form-group\">\n          <label htmlFor=\"email\" className=\"form-label\">\n            Email Address <span className=\"required\">*</span>\n          </label>\n          <input\n            id=\"email\"\n            type=\"email\"\n            className={`form-input ${errors.email ? 'error' : ''}`}\n            value={settings.email}\n            onChange={(e) => handleInputChange('email', e.target.value)}\n            placeholder=\"your.email@example.com\"\n          />\n          {errors.email && <span className=\"error-message\">{errors.email}</span>}\n        </div>\n\n        <div className=\"form-group\">\n          <label htmlFor=\"role\" className=\"form-label\">\n            Role\n          </label>\n          <select\n            id=\"role\"\n            className=\"form-select\"\n            value={settings.role}\n            onChange={(e) => handleInputChange('role', e.target.value)}\n          >\n            {ROLES.map((role) => (\n              <option key={role} value={role}>\n                {role}\n              </option>\n            ))}\n          </select>\n        </div>\n\n        <div className=\"form-group\">\n          <label htmlFor=\"timezone\" className=\"form-label\">\n            Timezone <span className=\"required\">*</span>\n          </label>\n          <select\n            id=\"timezone\"\n            className={`form-select ${errors.timezone ? 'error' : ''}`}\n            value={settings.timezone}\n            onChange={(e) => handleInputChange('timezone', e.target.value)}\n          >\n            <option value=\"\">Select a timezone</option>\n            {TIMEZONES.map((tz) => (\n              <option key={tz} value={tz}>\n                {tz}\n              </option>\n            ))}\n          </select>\n          {errors.timezone && <span className=\"error-message\">{errors.timezone}</span>}\n        </div>\n\n        <div className=\"form-group checkbox-group\">\n          <label className=\"checkbox-label\">\n            <input\n              type=\"checkbox\"\n              className=\"form-checkbox\"\n              checked={settings.notifications}\n              onChange={(e) => handleInputChange('notifications', e.target.checked)}\n            />\n            <span>Enable email notifications</span>\n          </label>\n          <p className=\"checkbox-description\">\n            Receive email notifications for system alerts, reports, and team updates\n          </p>\n        </div>\n\n        <div className=\"form-actions\">\n          <button type=\"button\" className=\"btn btn-secondary\" onClick={handleReset} disabled={!isDirty || isSaving}>\n            Reset\n          </button>\n          <button type=\"submit\" className=\"btn btn-primary\" disabled={!isDirty || isSaving}>\n            {isSaving ? 'Saving...' : 'Save Changes'}\n          </button>\n        </div>\n\n        {saveSuccess && (\n          <div className=\"save-success\">\n            <svg viewBox=\"0 0 20 20\" fill=\"currentColor\">\n              <path\n                fillRule=\"evenodd\"\n                d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\"\n                clipRule=\"evenodd\"\n              />\n            </svg>\n            Settings saved successfully!\n          </div>\n        )}\n      </form>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/hooks/useData.ts",
    "content": "import { useState, useEffect } from 'react'\nimport { fetchDataWithDelay } from '../utils/api'\n\ninterface UseDataResult<T> {\n  data: T | null\n  loading: boolean\n  error: Error | null\n}\n\n/**\n * Custom hook to fetch data from JSON files\n */\nexport function useData<T>(url: string, delayMs: number = 300): UseDataResult<T> {\n  const [data, setData] = useState<T | null>(null)\n  const [loading, setLoading] = useState(true)\n  const [error, setError] = useState<Error | null>(null)\n\n  useEffect(() => {\n    let mounted = true\n\n    const fetchData = async () => {\n      try {\n        setLoading(true)\n        const result = await fetchDataWithDelay<T>(url, delayMs)\n        if (mounted) {\n          setData(result)\n          setError(null)\n        }\n      } catch (err) {\n        if (mounted) {\n          setError(err instanceof Error ? err : new Error('Unknown error'))\n          setData(null)\n        }\n      } finally {\n        if (mounted) {\n          setLoading(false)\n        }\n      }\n    }\n\n    fetchData()\n\n    return () => {\n      mounted = false\n    }\n  }, [url, delayMs])\n\n  return { data, loading, error }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/hooks/useDebounce.ts",
    "content": "import { useState, useEffect } from 'react'\n\n/**\n * Debounce hook to delay updating a value\n */\nexport function useDebounce<T>(value: T, delay: number = 300): T {\n  const [debouncedValue, setDebouncedValue] = useState<T>(value)\n\n  useEffect(() => {\n    const handler = setTimeout(() => {\n      setDebouncedValue(value)\n    }, delay)\n\n    return () => {\n      clearTimeout(handler)\n    }\n  }, [value, delay])\n\n  return debouncedValue\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/index.css",
    "content": "/* CSS Variables - Design System */\n:root {\n  /* Colors */\n  --color-primary: #632ca6;\n  --color-primary-light: rgba(99, 44, 166, 0.1);\n  --color-primary-hover: #7d3cbf;\n  --color-success: #3ebf62;\n  --color-error: #ff5252;\n  --color-warning: #ffa726;\n  --color-bg: #1e1e1e;\n  --color-surface: #2a2a2a;\n  --color-surface-elevated: #333333;\n  --color-surface-hover: rgba(255, 255, 255, 0.05);\n  --color-border: #3a3a3a;\n  --color-border-light: rgba(255, 255, 255, 0.1);\n  --color-text: #e0e0e0;\n  --color-text-secondary: #a0a0a0;\n  --color-text-muted: #888888;\n\n  /* Spacing */\n  --spacing-xs: 4px;\n  --spacing-sm: 8px;\n  --spacing-md: 16px;\n  --spacing-lg: 24px;\n  --spacing-xl: 32px;\n  --spacing-2xl: 48px;\n\n  /* Typography */\n  --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n  --font-size-xs: 11px;\n  --font-size-sm: 12px;\n  --font-size-md: 14px;\n  --font-size-lg: 16px;\n  --font-size-xl: 20px;\n  --font-size-2xl: 24px;\n\n  /* Shadows */\n  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);\n  --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.3);\n  --shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.4);\n}\n\n/* Reset & Base Styles */\n* {\n  box-sizing: border-box;\n}\n\nhtml,\nbody {\n  margin: 0;\n  padding: 0;\n  width: 100%;\n  height: 100%;\n}\n\nbody {\n  font-family: var(--font-family);\n  font-size: var(--font-size-md);\n  line-height: 1.5;\n  color: var(--color-text);\n  background-color: var(--color-bg);\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n#root {\n  width: 100%;\n  height: 100%;\n}\n\n/* Typography */\nh1 {\n  font-size: var(--font-size-2xl);\n  font-weight: 600;\n  margin: 0 0 var(--spacing-lg) 0;\n  color: var(--color-text);\n}\n\nh2 {\n  font-size: var(--font-size-xl);\n  font-weight: 600;\n  margin: 0 0 var(--spacing-md) 0;\n  color: var(--color-text);\n}\n\nh3 {\n  font-size: var(--font-size-lg);\n  font-weight: 600;\n  margin: 0 0 var(--spacing-sm) 0;\n  color: var(--color-text);\n}\n\np {\n  margin: 0 0 var(--spacing-md) 0;\n  color: var(--color-text-secondary);\n}\n\n/* Links */\na {\n  color: var(--color-primary);\n  text-decoration: none;\n}\n\na:hover {\n  text-decoration: underline;\n}\n\n/* Buttons */\nbutton {\n  font-family: var(--font-family);\n  font-size: var(--font-size-md);\n  cursor: pointer;\n  border: none;\n  background: none;\n  padding: 0;\n}\n\n/* Form Elements */\ninput,\ntextarea,\nselect {\n  font-family: var(--font-family);\n  font-size: var(--font-size-md);\n}\n\ninput::placeholder,\ntextarea::placeholder {\n  color: var(--color-text-secondary);\n}\n\n/* Scrollbar Styling */\n::-webkit-scrollbar {\n  width: 8px;\n  height: 8px;\n}\n\n::-webkit-scrollbar-track {\n  background: var(--color-bg);\n}\n\n::-webkit-scrollbar-thumb {\n  background: var(--color-border);\n  border-radius: 4px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n  background: var(--color-text-secondary);\n}\n\n/* Utility Classes */\n.loading {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  padding: var(--spacing-2xl);\n  color: var(--color-text-secondary);\n}\n\n.error {\n  padding: var(--spacing-md);\n  background-color: rgba(255, 82, 82, 0.1);\n  border: 1px solid var(--color-error);\n  border-radius: 4px;\n  color: var(--color-error);\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/main.tsx",
    "content": "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport './index.css'\nimport App from './App.tsx'\n\ncreateRoot(document.getElementById('root')!).render(\n  <StrictMode>\n    <App />\n  </StrictMode>\n)\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/types/data.ts",
    "content": "// Common types\nexport interface TimeSeriesDataPoint {\n  timestamp: number\n  value: number\n}\n\n// Dashboard types\nexport interface MetricSummary {\n  apm_requests: number\n  logs_count: number\n  infrastructure_hosts: number\n  errors_count: number\n}\n\nexport interface ServiceStatus {\n  name: string\n  status: 'healthy' | 'degraded' | 'critical'\n  requests: number\n  errorRate?: number\n  latency?: number\n}\n\nexport interface DashboardData {\n  summary: MetricSummary\n  timeseries: TimeSeriesDataPoint[]\n  services: ServiceStatus[]\n}\n\n// Logs types\nexport type LogLevel = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG'\n\nexport interface LogEntry {\n  id: string\n  timestamp: number\n  level: LogLevel\n  service: string\n  message: string\n  host: string\n  tags: string[]\n}\n\nexport interface LogFacets {\n  services: string[]\n  levels: LogLevel[]\n  hosts: string[]\n}\n\nexport interface LogsData {\n  logs: LogEntry[]\n  facets: LogFacets\n}\n\n// APM/Traces types\nexport interface Span {\n  spanId: string\n  operation: string\n  service: string\n  resource: string\n  duration: number\n  error?: string\n  warning?: string\n}\n\nexport interface Trace {\n  id: string\n  traceId: string\n  service: string\n  operation: string\n  duration: number\n  timestamp: number\n  status: 'ok' | 'error' | 'warning'\n  spans: Span[]\n}\n\nexport interface TracesData {\n  traces: Trace[]\n}\n\n// Infrastructure types\nexport type HostStatus = 'healthy' | 'warning' | 'critical'\n\nexport interface Host {\n  id: string\n  name: string\n  status: HostStatus\n  cpu: number\n  memory: number\n  disk: number\n  network: number\n  uptime: number\n  region?: string\n  tags?: string[]\n}\n\nexport interface HostMetricsTimeSeries {\n  cpu: TimeSeriesDataPoint[]\n  memory: TimeSeriesDataPoint[]\n  disk?: TimeSeriesDataPoint[]\n  network?: TimeSeriesDataPoint[]\n}\n\nexport interface InfrastructureData {\n  hosts: Host[]\n  metrics: Record<string, HostMetricsTimeSeries>\n}\n\n// Settings types\nexport interface UserSettings {\n  name: string\n  email: string\n  role: string\n  notifications: boolean\n  timezone: string\n}\n\nexport interface TeamMember {\n  id: string\n  name: string\n  email: string\n  role: string\n}\n\nexport interface Integration {\n  id: string\n  name: string\n  enabled: boolean\n  type: string\n  icon?: string\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/utils/api.ts",
    "content": "/**\n * Fetch data from static JSON files\n */\nexport async function fetchData<T>(path: string): Promise<T> {\n  const response = await fetch(path)\n  if (!response.ok) {\n    throw new Error(`Failed to fetch ${path}: ${response.statusText}`)\n  }\n  return response.json()\n}\n\n/**\n * Simulate API delay for more realistic behavior\n */\nexport function delay(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Fetch data with simulated delay\n */\nexport async function fetchDataWithDelay<T>(path: string, delayMs: number = 300): Promise<T> {\n  await delay(delayMs)\n  return fetchData<T>(path)\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/utils/constants.ts",
    "content": "// Data file paths\nexport const DATA_PATHS = {\n  DASHBOARD: '/data/metrics.json',\n  LOGS: '/data/logs.json',\n  TRACES: '/data/traces.json',\n  INFRASTRUCTURE: '/data/infrastructure.json',\n} as const\n\n// Route paths\nexport const ROUTES = {\n  DASHBOARD: '/',\n  LOGS: '/logs',\n  APM_TRACES: '/apm/traces',\n  INFRASTRUCTURE: '/infrastructure',\n  SETTINGS: '/settings',\n  TEST: '/test',\n} as const\n\n// UI Constants\nexport const SIDEBAR_WIDTH = 240\nexport const TOPBAR_HEIGHT = 64\nexport const LOG_TABLE_ROW_HEIGHT = 48\nexport const ITEMS_PER_PAGE = 50\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/utils/generateMetrics.ts",
    "content": "import { HostMetricsTimeSeries } from '../types/data'\n\n// Simple seeded random number generator for consistent metrics per host\nfunction seededRandom(seed: number): () => number {\n  let state = seed\n  return () => {\n    state = (state * 1664525 + 1013904223) % 2147483648\n    return state / 2147483648\n  }\n}\n\nexport function generateHostMetrics(hostId: string, dataPoints: number = 50): HostMetricsTimeSeries {\n  // Use host ID as seed for consistent metrics per host\n  const seed = hostId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)\n  const random = seededRandom(seed)\n\n  const baseTimestamp = Date.now() - dataPoints * 60000 // Start from 'dataPoints' minutes ago\n\n  // Generate metrics with some variation but consistent per host\n  const generateMetricData = (baseValue: number, variance: number) => {\n    const points = []\n    let currentValue = baseValue\n\n    for (let i = 0; i < dataPoints; i++) {\n      // Add some random walk behavior\n      const change = (random() - 0.5) * variance\n      currentValue = Math.max(0, Math.min(100, currentValue + change))\n\n      points.push({\n        timestamp: baseTimestamp + i * 60000, // 1 minute intervals\n        value: Math.round(currentValue),\n      })\n    }\n\n    return points\n  }\n\n  // Generate different patterns for different metrics\n  const cpuBase = 30 + random() * 40 // 30-70% base\n  const memoryBase = 40 + random() * 40 // 40-80% base\n  const diskBase = 20 + random() * 50 // 20-70% base\n  const networkBase = 10 + random() * 60 // 10-70 Mbps base\n\n  return {\n    cpu: generateMetricData(cpuBase, 10),\n    memory: generateMetricData(memoryBase, 8),\n    disk: generateMetricData(diskBase, 5),\n    network: generateMetricData(networkBase, 15),\n  }\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/utils/performanceThrottle.ts",
    "content": "/**\n * Heavy computation that can be used in useMemo/useEffect\n * Returns a large array to simulate real data processing\n */\nexport function heavyComputation<T>(data: T[], processingTimeMs: number = 1000): T[] {\n  const start = performance.now()\n  let result = [...data]\n\n  while (performance.now() - start < processingTimeMs) {\n    // Simulate data processing\n    result = result.map((item) => item)\n    result.sort(() => Math.random() - 0.5)\n\n    // Some computation\n    result.reduce((acc) => acc + Math.random(), 0)\n  }\n\n  return result\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "test/apps/react-heavy-spa/tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [{ \"path\": \"./tsconfig.app.json\" }, { \"path\": \"./tsconfig.node.json\" }]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2022\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "test/apps/react-heavy-spa/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [react()],\n  build: {\n    minify: false,\n  },\n})\n"
  },
  {
    "path": "test/apps/react-router-v6-app/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*"
  },
  {
    "path": "test/apps/react-router-v6-app/app.tsx",
    "content": "import { createBrowserRouter } from '@datadog/browser-rum-react/react-router-v6'\nimport { RouterProvider, Link, useParams, Outlet } from 'react-router-dom'\nimport React, { useState } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { datadogRum } from '@datadog/browser-rum'\nimport {\n  reactPlugin,\n  UNSTABLE_ReactComponentTracker as ReactComponentTracker,\n  ErrorBoundary,\n} from '@datadog/browser-rum-react'\n\ndeclare global {\n  interface Window {\n    RUM_CONFIGURATION?: any\n    RUM_CONTEXT?: any\n  }\n}\n\ndatadogRum.init({ ...window.RUM_CONFIGURATION, plugins: [reactPlugin({ router: true })] })\nif (window.RUM_CONTEXT) {\n  datadogRum.setGlobalContext(window.RUM_CONTEXT)\n}\n\nfunction HomePage() {\n  return (\n    <div>\n      <h1>Home</h1>\n      <Link to=\"/user/42?admin=true\">Go to User 42</Link>\n      <br />\n      <Link to=\"/guides/123\">Go to Guides 123</Link>\n      <br />\n      <Link to=\"/wildcard/foo/bar\">Go to Wildcard</Link>\n      <br />\n      <Link to=\"/error-test\">Go to Error Test</Link>\n      <br />\n      <Link to=\"/tracked\">Go to Tracked</Link>\n    </div>\n  )\n}\n\nfunction UserPage() {\n  const { id } = useParams()\n  return (\n    <div>\n      <h1>User {id}</h1>\n      <Link to=\"/\">Back to Home</Link>\n      <br />\n      <Link to={`/user/${id}#section`}>Go to Section</Link>\n      <br />\n      <Link to={`/user/${id}?admin=false`}>Change query params</Link>\n      <br />\n      <Link to=\"/user/999?admin=true\">Go to User 999</Link>\n    </div>\n  )\n}\n\nfunction GuidesPage() {\n  return (\n    <div>\n      <h1>Guides</h1>\n      <Link to=\"/\">Back to Home</Link>\n    </div>\n  )\n}\n\nfunction WildcardPage() {\n  const splatPath = useParams()['*']\n  return (\n    <div>\n      <h1>Wildcard: {splatPath}</h1>\n      <Link to=\"/\">Back to Home</Link>\n    </div>\n  )\n}\n\nfunction Layout() {\n  return (\n    <div>\n      <nav>\n        <Link to=\"/\">Home</Link>\n      </nav>\n      <Outlet />\n    </div>\n  )\n}\n\nfunction TrackedPage() {\n  return (\n    <ReactComponentTracker name=\"TrackedPage\">\n      <h1>Component Tracker</h1>\n    </ReactComponentTracker>\n  )\n}\n\nfunction ComponentWithErrorButton() {\n  const [shouldError, setShouldError] = useState(false)\n\n  if (shouldError) {\n    throw new Error('Error triggered by button click')\n  }\n\n  return (\n    <div>\n      <h1>Component with Error Button</h1>\n      <button data-testid=\"trigger-error\" onClick={() => setShouldError(true)}>\n        Trigger Error\n      </button>\n    </div>\n  )\n}\n\nfunction ErrorPage() {\n  return (\n    <div>\n      <h1>Error Page</h1>\n      <ErrorBoundary\n        fallback={({ error, resetError }) => (\n          <div data-testid=\"error-handled\">\n            <h2>Something went wrong</h2>\n            <p>{error.message}</p>\n            <button onClick={resetError}>Try again</button>\n          </div>\n        )}\n      >\n        <ComponentWithErrorButton />\n      </ErrorBoundary>\n    </div>\n  )\n}\n\nconst router = createBrowserRouter([\n  {\n    path: '/',\n    Component: Layout,\n    children: [\n      {\n        index: true,\n        Component: HomePage,\n      },\n      {\n        path: 'user/:id',\n        Component: UserPage,\n      },\n      {\n        path: 'guides/:slug',\n        Component: GuidesPage,\n      },\n      {\n        path: 'wildcard/*',\n        Component: WildcardPage,\n      },\n      {\n        path: 'tracked',\n        Component: TrackedPage,\n      },\n      {\n        path: 'error-test',\n        Component: ErrorPage,\n      },\n    ],\n  },\n])\n\nconst rootElement = document.createElement('div')\ndocument.body.appendChild(rootElement)\nconst root = ReactDOM.createRoot(rootElement)\nroot.render(\n  <React.StrictMode>\n    <RouterProvider router={router as any} />\n  </React.StrictMode>\n)\n"
  },
  {
    "path": "test/apps/react-router-v6-app/package.json",
    "content": "{\n  \"name\": \"react-router-v6-app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack\"\n  },\n  \"dependencies\": {\n    \"react\": \"19.2.4\",\n    \"react-dom\": \"19.2.4\",\n    \"react-router-dom\": \"6.30.0\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"*\",\n    \"@datadog/browser-rum-react\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-react\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-rum-react\": \"file:../../../packages/rum-react/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"ts-loader\": \"9.5.7\",\n    \"typescript\": \"5.9.3\",\n    \"webpack\": \"5.105.4\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/react-router-v6-app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/\",\n    \"strict\": true,\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"jsx\": \"react\",\n    \"target\": \"es5\",\n    \"lib\": [\"ES2015\", \"DOM\"],\n    \"types\": []\n  }\n}\n"
  },
  {
    "path": "test/apps/react-router-v6-app/webpack.config.js",
    "content": "const path = require('node:path')\n\nmodule.exports = {\n  mode: 'production',\n  entry: './app.tsx',\n  target: ['web', 'es2018'],\n  module: {\n    rules: [\n      {\n        test: /\\.(ts|tsx)$/,\n        use: 'ts-loader',\n      },\n    ],\n  },\n  resolve: {\n    extensions: ['.ts', '.tsx', '.js', '.jsx'],\n  },\n  optimization: {\n    chunkIds: 'named',\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'react-router-v6-app.js',\n    chunkFilename: 'chunks/[name]-[contenthash]-react-router-v6-app.js',\n  },\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*"
  },
  {
    "path": "test/apps/react-shopist-like/README.md",
    "content": "# React Shopist - Lightweight E-Commerce App\n\nA lightweight React-based e-commerce application for performance benchmarking and profiling of Datadog Browser SDK.\n\n## Pages\n\n- 🛍️ **Product Listing** – Displays product grid with category filtering and search functionality.\n- 📦 **Product Detail** – Shows detailed product information with add-to-cart interactions.\n- 🛒 **Shopping Cart** – Manages cart items with quantity updates and checkout flow.\n\n## Performance metrics target\n\nTarget to have Web Vitals in the \"Good\" score range.\n\n- **LCP**: ~1000ms\n- **CLS**: ~0.05ms\n- **INP**: ~60ms\n- **TBT**: ~0ms\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 20+ (recommended)\n- Yarn (uses Yarn by default)\n\n### Installation\n\n```bash\n# Install dependencies\nyarn install\n```\n\n### Development\n\n```bash\n# Run development server (opens browser automatically)\nyarn dev\n```\n\nThe app will be available at `http://localhost:3002`\n\n### Building for Production\n\n```bash\n# Create production build (includes TypeScript compilation)\nyarn build\n\n# Preview production build\nyarn preview\n```\n"
  },
  {
    "path": "test/apps/react-shopist-like/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/vite.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Shopist - Modern E-Commerce</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/apps/react-shopist-like/package.json",
    "content": "{\n  \"name\": \"react-shopist\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite --open\",\n    \"build\": \"tsc -b && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"react\": \"19.2.4\",\n    \"react-dom\": \"19.2.4\",\n    \"react-router-dom\": \"7.14.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"19.2.14\",\n    \"@types/react-dom\": \"19.2.3\",\n    \"@vitejs/plugin-react\": \"5.2.0\",\n    \"globals\": \"17.4.0\",\n    \"typescript\": \"5.9.3\",\n    \"vite\": \"7.3.2\"\n  }\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/public/products.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"name\": \"Wicker Chair\",\n    \"category\": \"Chairs\",\n    \"price\": 250.0,\n    \"image\": \"https://images.unsplash.com/photo-1506439773649-6e0eb8cfb237?w=400\",\n    \"description\": \"Natural wicker chair with comfortable cushioning\",\n    \"inStock\": true,\n    \"rating\": 4.5\n  },\n  {\n    \"id\": 2,\n    \"name\": \"Black Shell Chair\",\n    \"category\": \"Chairs\",\n    \"price\": 320.0,\n    \"image\": \"https://images.unsplash.com/photo-1503602642458-232111445657?w=400\",\n    \"description\": \"Modern black shell chair with metal legs\",\n    \"inStock\": true,\n    \"rating\": 4.8\n  },\n  {\n    \"id\": 3,\n    \"name\": \"Wooden Stools\",\n    \"category\": \"Chairs\",\n    \"price\": 210.0,\n    \"image\": \"https://images.unsplash.com/photo-1519947486511-46149fa0a254?w=400\",\n    \"description\": \"Set of 2 handcrafted wooden stools\",\n    \"inStock\": true,\n    \"rating\": 4.3\n  },\n  {\n    \"id\": 4,\n    \"name\": \"Upholstered White Chair\",\n    \"category\": \"Chairs\",\n    \"price\": 210.0,\n    \"image\": \"https://images.unsplash.com/photo-1567538096630-e0c55bd6374c?w=400\",\n    \"description\": \"Elegant tufted white upholstered chair\",\n    \"inStock\": false,\n    \"rating\": 4.7\n  },\n  {\n    \"id\": 5,\n    \"name\": \"Grey Tufted Couch\",\n    \"category\": \"Sofas\",\n    \"price\": 850.0,\n    \"image\": \"https://images.unsplash.com/photo-1555041469-a586c61ea9bc?w=400\",\n    \"description\": \"Comfortable grey tufted sofa for your living room\",\n    \"inStock\": true,\n    \"rating\": 4.6\n  },\n  {\n    \"id\": 6,\n    \"name\": \"Modern Sectional Sofa\",\n    \"category\": \"Sofas\",\n    \"price\": 1200.0,\n    \"image\": \"https://images.unsplash.com/photo-1493663284031-b7e3aefcae8e?w=400\",\n    \"description\": \"Large sectional sofa with chaise lounge\",\n    \"inStock\": true,\n    \"rating\": 4.4\n  },\n  {\n    \"id\": 7,\n    \"name\": \"Velvet Blue Sofa\",\n    \"category\": \"Sofas\",\n    \"price\": 950.0,\n    \"image\": \"https://images.unsplash.com/photo-1550254478-ead40cc54513?w=400\",\n    \"description\": \"Luxurious velvet sofa in deep blue\",\n    \"inStock\": true,\n    \"rating\": 4.8\n  },\n  {\n    \"id\": 8,\n    \"name\": \"White Linen Duvet Set\",\n    \"category\": \"Bedding\",\n    \"price\": 180.0,\n    \"image\": \"https://images.unsplash.com/photo-1522771739844-6a9f6d5f14af?w=400\",\n    \"description\": \"Premium white linen duvet cover set\",\n    \"inStock\": true,\n    \"rating\": 4.5\n  },\n  {\n    \"id\": 9,\n    \"name\": \"Cotton Quilt Set\",\n    \"category\": \"Bedding\",\n    \"price\": 140.0,\n    \"image\": \"https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=400\",\n    \"description\": \"Soft cotton quilt with matching pillowcases\",\n    \"inStock\": true,\n    \"rating\": 4.6\n  },\n  {\n    \"id\": 10,\n    \"name\": \"Silk Pillowcase Set\",\n    \"category\": \"Bedding\",\n    \"price\": 89.0,\n    \"image\": \"https://images.unsplash.com/photo-1584100936595-c0654b55a2e2?w=400\",\n    \"description\": \"Luxurious mulberry silk pillowcases\",\n    \"inStock\": true,\n    \"rating\": 4.8\n  },\n  {\n    \"id\": 11,\n    \"name\": \"Modern Floor Lamp\",\n    \"category\": \"Lighting\",\n    \"price\": 180.0,\n    \"image\": \"https://images.unsplash.com/photo-1507473885765-e6ed057f782c?w=400\",\n    \"description\": \"Contemporary floor lamp with adjustable head\",\n    \"inStock\": true,\n    \"rating\": 4.4\n  },\n  {\n    \"id\": 12,\n    \"name\": \"Pendant Light Set\",\n    \"category\": \"Lighting\",\n    \"price\": 220.0,\n    \"image\": \"https://images.unsplash.com/photo-1513506003901-1e6a229e2d15?w=400\",\n    \"description\": \"Set of 3 modern pendant lights\",\n    \"inStock\": true,\n    \"rating\": 4.7\n  }\n]\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/App.css",
    "content": "* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\n\nbody {\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',\n    'Helvetica Neue', sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  background-color: #ffffff;\n}\n\n/* Header */\n.header {\n  background-color: #ffffff;\n  color: #000000;\n  padding: 2rem 3rem 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.header-wrapper {\n  max-width: 1400px;\n  margin: 0 auto;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n}\n\n.logo {\n  font-size: 3rem;\n  font-weight: 900;\n  color: #000000;\n  text-decoration: none;\n  letter-spacing: 0.02em;\n  text-transform: uppercase;\n  margin-bottom: 2rem;\n}\n\n.header-content {\n  width: 100%;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 0 3rem;\n}\n\n.header-nav {\n  display: flex;\n  gap: 3rem;\n  align-items: center;\n}\n\n.header-actions {\n  display: flex;\n  gap: 3rem;\n  align-items: center;\n  white-space: nowrap;\n}\n\n.nav-link {\n  color: #000000;\n  text-decoration: none;\n  font-size: 0.85rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  transition: opacity 0.2s;\n  position: relative;\n  padding-bottom: 1.5rem;\n}\n\n.nav-link:hover {\n  opacity: 0.6;\n}\n\n.nav-link.active {\n  opacity: 1;\n}\n\n.nav-link.active::after {\n  content: '';\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  height: 2px;\n  background-color: #000000;\n}\n\n/* Main Content */\n.main-content {\n  max-width: 1400px;\n  margin: 3rem auto;\n  padding: 0 3rem;\n  min-height: 600px;\n}\n\n/* Promo Banner */\n.promo-banner {\n  background: linear-gradient(135deg, #000000 0%, #333333 100%);\n  color: white;\n  padding: 1rem 3rem;\n  margin-bottom: 2rem;\n  border-radius: 0;\n}\n\n.promo-content {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 2rem;\n  flex-wrap: wrap;\n}\n\n.promo-badge {\n  background-color: #ff4444;\n  color: white;\n  padding: 0.5rem 1rem;\n  font-weight: 700;\n  font-size: 0.9rem;\n  letter-spacing: 0.1em;\n  text-transform: uppercase;\n}\n\n.promo-text {\n  font-size: 1.2rem;\n  font-weight: 500;\n  margin: 0;\n  letter-spacing: 0.02em;\n}\n\n.promo-button {\n  background-color: white;\n  color: #000000;\n  border: none;\n  padding: 0.75rem 2rem;\n  font-size: 0.85rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  cursor: pointer;\n  transition: all 0.2s;\n  border-radius: 0;\n}\n\n.promo-button:hover {\n  background-color: #f0f0f0;\n  transform: translateY(-2px);\n}\n\n/* Category Filter */\n.category-filter {\n  display: flex;\n  gap: 0;\n  margin-bottom: 3rem;\n  flex-wrap: wrap;\n  border-bottom: 2px solid #e5e5e5;\n}\n\n.category-button {\n  padding: 1rem 2rem;\n  border: none;\n  background-color: transparent;\n  color: #666666;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.95rem;\n  font-weight: 500;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  transition: all 0.2s;\n  border-bottom: 3px solid transparent;\n  margin-bottom: -2px;\n}\n\n.category-button.active {\n  background-color: transparent;\n  color: #000000;\n  font-weight: 700;\n  border-bottom-color: #000000;\n}\n\n.category-button:hover {\n  background-color: transparent;\n  color: #000000;\n}\n\n/* Product Grid */\n.product-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n  gap: 2.5rem;\n  margin-bottom: 3rem;\n}\n\n/* Skeleton Loader */\n.skeleton-card {\n  background-color: #ffffff;\n  border-radius: 0;\n  overflow: hidden;\n  animation: skeleton-pulse 1.5s ease-in-out infinite;\n}\n\n.skeleton-image {\n  width: 100%;\n  height: 400px;\n  background-color: #f0f0f0;\n}\n\n.skeleton-info {\n  padding: 1.5rem 0;\n}\n\n.skeleton-title {\n  height: 1.3rem;\n  background-color: #f0f0f0;\n  margin-bottom: 0.75rem;\n  width: 70%;\n}\n\n.skeleton-price {\n  height: 1rem;\n  background-color: #f0f0f0;\n  width: 30%;\n}\n\n@keyframes skeleton-pulse {\n  0%,\n  100% {\n    opacity: 1;\n  }\n  50% {\n    opacity: 0.6;\n  }\n}\n\n.product-card {\n  background-color: #ffffff;\n  border-radius: 0;\n  overflow: hidden;\n  border: none;\n  transition: transform 0.2s;\n  cursor: pointer;\n  text-decoration: none;\n  color: inherit;\n  display: block;\n}\n\n.product-card:hover {\n  transform: translateY(-4px);\n}\n\n.product-image-container {\n  position: relative;\n  overflow: hidden;\n}\n\n.product-image {\n  width: 100%;\n  height: 400px;\n  aspect-ratio: 1 / 1.43;\n  object-fit: cover;\n  background-color: #f8f8f8;\n  display: block;\n}\n\n.product-stock-badge {\n  position: absolute;\n  top: 1rem;\n  right: 1rem;\n  background-color: rgba(200, 200, 200, 0.9);\n  color: #000000;\n  padding: 0.5rem 1rem;\n  font-size: 0.75rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n}\n\n.product-info {\n  padding: 1.5rem 0;\n}\n\n.product-name {\n  font-size: 1.1rem;\n  font-weight: 400;\n  margin-bottom: 0.5rem;\n  color: #000000;\n  line-height: 1.4;\n}\n\n.product-price {\n  font-size: 1rem;\n  font-weight: 600;\n  color: #000000;\n}\n\n/* Product Detail */\n.product-detail {\n  background-color: white;\n  border-radius: 8px;\n  padding: 2rem;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.product-detail-content {\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 2rem;\n  margin-bottom: 2rem;\n}\n\n.product-detail-image {\n  width: 100%;\n  border-radius: 8px;\n}\n\n.product-detail-info h1 {\n  font-size: 2rem;\n  margin-bottom: 1rem;\n  color: #2c3e50;\n}\n\n.product-detail-info .product-price {\n  font-size: 2rem;\n  margin-bottom: 1rem;\n}\n\n.product-description {\n  font-size: 1rem;\n  color: #7f8c8d;\n  line-height: 1.6;\n  margin-bottom: 1rem;\n}\n\n.back-button {\n  padding: 0.75rem 1.5rem;\n  background-color: #95a5a6;\n  color: white;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n  font-size: 1rem;\n  transition: background-color 0.2s;\n}\n\n.back-button:hover {\n  background-color: #7f8c8d;\n}\n\n/* Cart */\n.cart-page {\n  background-color: #ffffff;\n  border-radius: 0;\n  padding: 0;\n}\n\n.cart-layout {\n  display: grid;\n  grid-template-columns: 1fr 400px;\n  gap: 3rem;\n}\n\n.cart-items-section h1 {\n  margin-bottom: 2rem;\n  color: #000000;\n  font-size: 1.3rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n.cart-summary-section h2 {\n  margin-bottom: 2rem;\n  color: #000000;\n  font-size: 1.3rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n.cart-items {\n  margin-bottom: 2rem;\n}\n\n.cart-item {\n  display: grid;\n  grid-template-columns: 120px 1fr auto auto;\n  gap: 1.5rem;\n  padding: 1.5rem 0;\n  border-bottom: 1px solid #e5e5e5;\n  align-items: center;\n  background-color: white;\n}\n\n.cart-item-image {\n  width: 120px;\n  height: 120px;\n  object-fit: cover;\n  border-radius: 0;\n  background-color: #f8f8f8;\n}\n\n.cart-item-info {\n  flex: 1;\n}\n\n.cart-item-name {\n  font-weight: 600;\n  margin-bottom: 0.5rem;\n  color: #000000;\n  font-size: 0.95rem;\n}\n\n.cart-item-price {\n  color: #000000;\n  font-weight: 700;\n  font-size: 1.1rem;\n  text-align: right;\n}\n\n.cart-item-actions {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n}\n\n.quantity-button {\n  width: 35px;\n  height: 35px;\n  border: 2px solid #000000;\n  background-color: white;\n  color: #000000;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 1rem;\n  font-weight: 700;\n  transition: all 0.2s;\n}\n\n.quantity-button:hover {\n  background-color: #000000;\n  color: white;\n}\n\n.remove-button {\n  background-color: transparent;\n  color: #000000;\n  border: 2px solid #000000;\n  padding: 0.5rem 1rem;\n  border-radius: 0;\n  cursor: pointer;\n  margin-left: 1rem;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  font-weight: 600;\n  font-size: 0.85rem;\n  transition: all 0.2s;\n}\n\n.remove-button:hover {\n  background-color: #000000;\n  color: white;\n}\n\n.cart-summary {\n  background-color: #f8f8f8;\n  padding: 2rem;\n  border: 1px solid #e5e5e5;\n}\n\n.summary-row {\n  display: flex;\n  justify-content: space-between;\n  padding: 0.75rem 0;\n  font-size: 0.95rem;\n}\n\n.summary-row span:first-child {\n  color: #666666;\n}\n\n.summary-row span:last-child {\n  font-weight: 600;\n  color: #000000;\n}\n\n.summary-total {\n  border-top: 2px solid #e5e5e5;\n  margin-top: 1rem;\n  padding-top: 1.5rem;\n  font-size: 1.1rem;\n  font-weight: 700;\n}\n\n.discount-code {\n  display: flex;\n  gap: 0.5rem;\n  margin: 1.5rem 0;\n}\n\n.discount-input {\n  flex: 1;\n  padding: 0.75rem 1rem;\n  border: 1px solid #e5e5e5;\n  border-radius: 0;\n  font-size: 0.9rem;\n  background-color: white;\n}\n\n.apply-button {\n  padding: 0.75rem 1.5rem;\n  background-color: transparent;\n  color: #000000;\n  border: 2px solid #000000;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.85rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  transition: all 0.2s;\n}\n\n.apply-button:hover {\n  background-color: #000000;\n  color: white;\n}\n\n.checkout-button {\n  width: 100%;\n  padding: 1rem;\n  background-color: #000000;\n  color: white;\n  border: none;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.95rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  transition: background-color 0.2s;\n}\n\n.checkout-button:hover {\n  background-color: #333333;\n}\n\n.empty-cart {\n  text-align: center;\n  padding: 3rem;\n  color: #666666;\n}\n\n/* Profile Page */\n.profile-page {\n  max-width: 800px;\n  margin: 0 auto;\n  padding: 3rem 0;\n}\n\n.profile-header {\n  display: flex;\n  align-items: center;\n  gap: 2rem;\n  padding-bottom: 3rem;\n  border-bottom: 1px solid #e5e5e5;\n  margin-bottom: 3rem;\n}\n\n.profile-avatar {\n  width: 100px;\n  height: 100px;\n  border-radius: 50%;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.avatar-placeholder {\n  width: 100%;\n  height: 100%;\n}\n\n.profile-name h1 {\n  font-size: 2rem;\n  font-weight: 600;\n  color: #000000;\n  margin: 0;\n}\n\n.profile-section {\n  display: grid;\n  grid-template-columns: 200px 1fr;\n  gap: 3rem;\n  padding: 2rem 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.profile-section-label {\n  font-size: 1rem;\n  color: #666666;\n  font-weight: 400;\n}\n\n.profile-section-content {\n  font-size: 1rem;\n  color: #000000;\n  font-weight: 400;\n  line-height: 1.6;\n}\n\n.edit-profile-button {\n  margin-top: 3rem;\n  padding: 0.75rem 2rem;\n  background-color: transparent;\n  color: #000000;\n  border: 2px solid #000000;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.85rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  transition: all 0.2s;\n}\n\n.edit-profile-button:hover {\n  background-color: #000000;\n  color: white;\n}\n\n/* Edit Profile Page */\n.edit-profile-page {\n  max-width: 680px;\n  margin: 0 auto;\n  padding: 3rem 0;\n}\n\n.edit-profile-page h1 {\n  font-size: 2rem;\n  font-weight: 600;\n  color: #000000;\n  margin-bottom: 3rem;\n}\n\n.form-section {\n  margin-bottom: 2rem;\n}\n\n.form-label {\n  display: block;\n  font-size: 0.9rem;\n  color: #666666;\n  margin-bottom: 0.75rem;\n  font-weight: 400;\n}\n\n.profile-picture-upload {\n  display: flex;\n  align-items: center;\n  gap: 2rem;\n}\n\n.profile-avatar-large {\n  width: 80px;\n  height: 80px;\n  border-radius: 50%;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  flex-shrink: 0;\n}\n\n.upload-photo-button {\n  padding: 0.75rem 1.5rem;\n  background-color: transparent;\n  color: #000000;\n  border: 2px solid #000000;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.85rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  transition: all 0.2s;\n}\n\n.upload-photo-button:hover {\n  background-color: #000000;\n  color: white;\n}\n\n.form-row {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n  gap: 1.5rem;\n  margin-bottom: 1.5rem;\n}\n\n.form-group {\n  margin-bottom: 1.5rem;\n}\n\n.form-input,\n.form-select {\n  width: 100%;\n  padding: 0.875rem 1rem;\n  border: 1px solid #e5e5e5;\n  border-radius: 0;\n  font-size: 1rem;\n  color: #000000;\n  background-color: white;\n  font-family: inherit;\n  transition: border-color 0.2s;\n}\n\n.form-input:focus,\n.form-select:focus {\n  outline: none;\n  border-color: #000000;\n}\n\n.form-select {\n  cursor: pointer;\n  appearance: none;\n  background-image: url(\"data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%23000000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\");\n  background-repeat: no-repeat;\n  background-position: right 1rem center;\n  padding-right: 3rem;\n}\n\n.form-actions {\n  display: flex;\n  justify-content: flex-end;\n  gap: 1rem;\n  margin-top: 3rem;\n  padding-top: 2rem;\n  border-top: 1px solid #e5e5e5;\n}\n\n.cancel-button {\n  padding: 0.875rem 2rem;\n  background-color: transparent;\n  color: #000000;\n  border: 2px solid #000000;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.85rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  transition: all 0.2s;\n}\n\n.cancel-button:hover {\n  background-color: #f5f5f5;\n}\n\n.save-button {\n  padding: 0.875rem 2rem;\n  background-color: #000000;\n  color: white;\n  border: 2px solid #000000;\n  border-radius: 0;\n  cursor: pointer;\n  font-size: 0.85rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  transition: all 0.2s;\n}\n\n.save-button:hover {\n  background-color: #333333;\n  border-color: #333333;\n}\n\n/* Footer */\n.footer {\n  background-color: #2b2b2b;\n  color: white;\n  margin-top: 5rem;\n}\n\n.footer-content {\n  max-width: 1400px;\n  margin: 0 auto;\n  padding: 4rem 3rem;\n  display: grid;\n  grid-template-columns: repeat(4, 1fr);\n  gap: 2rem;\n}\n\n.footer-section {\n  display: flex;\n  flex-direction: column;\n}\n\n.footer-heading {\n  font-size: 0.95rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  margin-bottom: 1rem;\n  color: white;\n}\n\n.footer-cta {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.footer-button {\n  background-color: transparent;\n  color: white;\n  border: 2px solid white;\n  padding: 0.75rem 1.5rem;\n  font-size: 0.85rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  cursor: pointer;\n  transition: all 0.2s;\n  border-radius: 0;\n}\n\n.footer-button:hover {\n  background-color: white;\n  color: #2b2b2b;\n}\n\n.footer-branding {\n  background-color: #1a1a1a;\n  padding: 2rem 3rem;\n}\n\n.footer-logo {\n  max-width: 1400px;\n  margin: 0 auto;\n  display: flex;\n  align-items: center;\n  gap: 1rem;\n}\n\n.brand-main {\n  font-size: 1.5rem;\n  font-weight: 900;\n  letter-spacing: 0.1em;\n  text-transform: uppercase;\n}\n\n.brand-sub {\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: #999999;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n@media (max-width: 1024px) {\n  .cart-layout {\n    grid-template-columns: 1fr;\n  }\n\n  .cart-item {\n    grid-template-columns: 100px 1fr;\n    gap: 1rem;\n  }\n\n  .cart-item-actions {\n    grid-column: 1 / -1;\n    justify-content: flex-start;\n    margin-top: 1rem;\n  }\n\n  .cart-item-price {\n    grid-column: 1 / -1;\n    text-align: left;\n    margin-top: 0.5rem;\n  }\n}\n\n@media (max-width: 768px) {\n  .product-detail-content {\n    grid-template-columns: 1fr;\n  }\n\n  .header {\n    padding: 1.5rem 1.5rem 0;\n  }\n\n  .logo {\n    font-size: 2rem;\n    margin-bottom: 1.5rem;\n  }\n\n  .header-content {\n    flex-direction: column;\n    gap: 0;\n  }\n\n  .header-nav,\n  .header-actions {\n    flex-wrap: wrap;\n    justify-content: center;\n    gap: 1.5rem;\n  }\n\n  .header-nav {\n    margin-bottom: 1rem;\n  }\n\n  .nav-link {\n    padding-bottom: 1rem;\n  }\n\n  .footer-content {\n    grid-template-columns: 1fr;\n  }\n\n  .footer-logo {\n    flex-direction: column;\n    text-align: center;\n  }\n\n  .main-content {\n    padding: 0 1.5rem;\n  }\n\n  .profile-header {\n    flex-direction: column;\n    text-align: center;\n  }\n\n  .profile-section {\n    grid-template-columns: 1fr;\n    gap: 1rem;\n  }\n\n  .profile-section-label {\n    font-weight: 600;\n  }\n\n  .edit-profile-page {\n    padding: 2rem 0;\n  }\n\n  .edit-profile-page h1 {\n    font-size: 1.5rem;\n  }\n\n  .form-row {\n    grid-template-columns: 1fr;\n  }\n\n  .profile-picture-upload {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n\n  .form-actions {\n    flex-direction: column;\n  }\n\n  .cancel-button,\n  .save-button {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/App.tsx",
    "content": "import { useState } from 'react'\nimport { BrowserRouter as Router, Routes, Route } from 'react-router-dom'\nimport { Header } from './components/Header'\nimport { Footer } from './components/Footer'\nimport { Home } from './pages/Home'\nimport { ProductDetail } from './pages/ProductDetail'\nimport type { CartItem } from './pages/Cart'\nimport { Cart } from './pages/Cart'\nimport { Profile } from './pages/Profile'\nimport { EditProfile } from './pages/EditProfile'\nimport type { Product } from './data/products'\nimport './App.css'\n\nfunction App() {\n  const [cartItems, setCartItems] = useState<CartItem[]>([])\n  const [searchQuery, setSearchQuery] = useState('')\n\n  const handleAddToCart = (product: Product) => {\n    setCartItems((prev) => {\n      const existingItem = prev.find((item) => item.product.id === product.id)\n      if (existingItem) {\n        return prev.map((item) => (item.product.id === product.id ? { ...item, quantity: item.quantity + 1 } : item))\n      }\n      return [...prev, { product, quantity: 1 }]\n    })\n  }\n\n  const handleUpdateQuantity = (productId: number, quantity: number) => {\n    setCartItems((prev) =>\n      prev.map((item) => (item.product.id === productId ? { ...item, quantity: Math.max(1, quantity) } : item))\n    )\n  }\n\n  const handleRemoveItem = (productId: number) => {\n    setCartItems((prev) => prev.filter((item) => item.product.id !== productId))\n  }\n\n  const cartItemCount = cartItems.reduce((sum, item) => sum + item.quantity, 0)\n\n  return (\n    <Router>\n      <Header cartItemCount={cartItemCount} searchQuery={searchQuery} onSearchChange={setSearchQuery} />\n      <Routes>\n        <Route path=\"/\" element={<Home onAddToCart={handleAddToCart} searchQuery={searchQuery} />} />\n        <Route path=\"/:category\" element={<Home onAddToCart={handleAddToCart} searchQuery={searchQuery} />} />\n        <Route path=\"/product/:id\" element={<ProductDetail onAddToCart={handleAddToCart} />} />\n        <Route\n          path=\"/cart\"\n          element={\n            <Cart cartItems={cartItems} onUpdateQuantity={handleUpdateQuantity} onRemoveItem={handleRemoveItem} />\n          }\n        />\n        <Route path=\"/profile\" element={<Profile />} />\n        <Route path=\"/profile/edit\" element={<EditProfile />} />\n      </Routes>\n      <Footer />\n    </Router>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/components/Footer.tsx",
    "content": "export function Footer() {\n  return (\n    <footer className=\"footer\">\n      <div className=\"footer-content\">\n        <div className=\"footer-section\">\n          <h3 className=\"footer-heading\">CHAIRS</h3>\n        </div>\n        <div className=\"footer-section\">\n          <h3 className=\"footer-heading\">SOFAS</h3>\n        </div>\n        <div className=\"footer-section\">\n          <h3 className=\"footer-heading\">BEDDING</h3>\n        </div>\n        <div className=\"footer-section footer-cta\">\n          <button className=\"footer-button\">SIGN UP FOR SHOP.IST</button>\n        </div>\n      </div>\n      <div className=\"footer-branding\">\n        <div className=\"footer-logo\">\n          <span className=\"brand-main\">COUCH CACHE</span>\n          <span className=\"brand-sub\">HOSTED BY SHOP.IST</span>\n        </div>\n      </div>\n    </footer>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/components/Header.tsx",
    "content": "import { Link, useLocation } from 'react-router-dom'\n\ninterface HeaderProps {\n  cartItemCount: number\n  searchQuery: string\n  onSearchChange: (query: string) => void\n}\n\nexport function Header({ cartItemCount }: HeaderProps) {\n  const location = useLocation()\n  const currentCategory = location.pathname.slice(1).toLowerCase()\n\n  return (\n    <header className=\"header\">\n      <div className=\"header-wrapper\">\n        <Link to=\"/\" className=\"logo\">\n          COUCH CACHE\n        </Link>\n        <div className=\"header-content\">\n          <div className=\"header-nav\">\n            <Link to=\"/chairs\" className={`nav-link ${currentCategory === 'chairs' ? 'active' : ''}`}>\n              CHAIRS\n            </Link>\n            <Link to=\"/sofas\" className={`nav-link ${currentCategory === 'sofas' ? 'active' : ''}`}>\n              SOFAS\n            </Link>\n            <Link to=\"/bedding\" className={`nav-link ${currentCategory === 'bedding' ? 'active' : ''}`}>\n              BEDDING\n            </Link>\n            <Link to=\"/lighting\" className={`nav-link ${currentCategory === 'lighting' ? 'active' : ''}`}>\n              LIGHTING\n            </Link>\n          </div>\n          <div className=\"header-actions\">\n            <Link to=\"/profile\" className=\"nav-link\">\n              MY PROFILE\n            </Link>\n            <Link to=\"/cart\" className=\"nav-link\">\n              CART ({cartItemCount})\n            </Link>\n          </div>\n        </div>\n      </div>\n    </header>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/components/ProductCard.tsx",
    "content": "import { Link } from 'react-router-dom'\nimport { Product } from '../data/products'\n\ninterface ProductCardProps {\n  product: Product\n  onAddToCart: (product: Product) => void\n}\n\nexport function ProductCard({ product }: ProductCardProps) {\n  return (\n    <Link to={`/product/${product.id}`} className=\"product-card\">\n      <div className=\"product-image-container\">\n        <img src={product.image} alt={product.name} className=\"product-image\" />\n        {product.inStock && <div className=\"product-stock-badge\">IN STOCK</div>}\n      </div>\n      <div className=\"product-info\">\n        <h3 className=\"product-name\">{product.name}</h3>\n        <div className=\"product-price\">${product.price.toFixed(2)}</div>\n      </div>\n    </Link>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/components/PromoBanner.tsx",
    "content": "import { useState, useEffect } from 'react'\n\nexport function PromoBanner() {\n  const [show, setShow] = useState(false)\n\n  useEffect(() => {\n    // Delay banner appearance to cause CLS\n    const timer = setTimeout(() => {\n      setShow(true)\n    }, 200)\n\n    return () => clearTimeout(timer)\n  }, [])\n\n  if (!show) return null\n\n  return (\n    <div className=\"promo-banner\">\n      <div className=\"promo-content\">\n        <span className=\"promo-badge\">SALE</span>\n        <p className=\"promo-text\">Summer Collection - Up to 50% Off on Selected Items</p>\n        <button className=\"promo-button\">Shop Now</button>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/data/products.ts",
    "content": "export interface Product {\n  id: number\n  name: string\n  category: string\n  price: number\n  image: string\n  description: string\n  inStock: boolean\n  rating: number\n}\n\nexport const categories = ['Chairs', 'Sofas', 'Bedding', 'Lighting']\n\nexport async function fetchProducts(): Promise<Product[]> {\n  const response = await fetch('/products.json')\n  if (!response.ok) {\n    throw new Error('Failed to fetch products')\n  }\n  return response.json()\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/main.tsx",
    "content": "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport App from './App.tsx'\n\ncreateRoot(document.getElementById('root')!).render(\n  <StrictMode>\n    <App />\n  </StrictMode>\n)\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/pages/Cart.tsx",
    "content": "import { useNavigate } from 'react-router-dom'\nimport type { Product } from '../data/products'\n\nexport interface CartItem {\n  product: Product\n  quantity: number\n}\n\ninterface CartProps {\n  cartItems: CartItem[]\n  onUpdateQuantity: (productId: number, quantity: number) => void\n  onRemoveItem: (productId: number) => void\n}\n\nexport function Cart({ cartItems, onUpdateQuantity, onRemoveItem }: CartProps) {\n  const navigate = useNavigate()\n\n  const total = cartItems.reduce((sum, item) => sum + item.product.price * item.quantity, 0)\n\n  if (cartItems.length === 0) {\n    return (\n      <div className=\"main-content\">\n        <div className=\"cart-page\">\n          <div className=\"empty-cart\">\n            <h2>Your cart is empty</h2>\n            <p>Add some products to get started!</p>\n            <button onClick={() => navigate('/')} className=\"back-button\">\n              Continue Shopping\n            </button>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  const subtotal = total\n  const tax = total * 0.08\n  const shipping = 61.0\n  const processingFees = 0.0\n  const grandTotal = subtotal + tax + shipping + processingFees\n\n  return (\n    <div className=\"main-content\">\n      <div className=\"cart-page\">\n        <div className=\"cart-layout\">\n          <div className=\"cart-items-section\">\n            <h1>Your Items</h1>\n            <div className=\"cart-items\">\n              {cartItems.map((item) => (\n                <div key={item.product.id} className=\"cart-item\">\n                  <img src={item.product.image} alt={item.product.name} className=\"cart-item-image\" />\n                  <div className=\"cart-item-info\">\n                    <div className=\"cart-item-name\">\n                      {item.product.name} (${item.product.price.toFixed(2)})\n                    </div>\n                  </div>\n                  <div className=\"cart-item-actions\">\n                    <button\n                      className=\"quantity-button\"\n                      onClick={() => onUpdateQuantity(item.product.id, item.quantity - 1)}\n                      disabled={item.quantity <= 1}\n                    >\n                      -\n                    </button>\n                    <span style={{ padding: '0 1rem', fontWeight: 600 }}>{item.quantity}</span>\n                    <button\n                      className=\"quantity-button\"\n                      onClick={() => onUpdateQuantity(item.product.id, item.quantity + 1)}\n                    >\n                      +\n                    </button>\n                    <button className=\"remove-button\" onClick={() => onRemoveItem(item.product.id)}>\n                      Remove\n                    </button>\n                  </div>\n                  <div className=\"cart-item-price\">${(item.product.price * item.quantity).toFixed(2)}</div>\n                </div>\n              ))}\n            </div>\n          </div>\n          <div className=\"cart-summary-section\">\n            <h2>Summary</h2>\n            <div className=\"cart-summary\">\n              <div className=\"summary-row\">\n                <span>Order value</span>\n                <span>${subtotal.toFixed(2)}</span>\n              </div>\n              <div className=\"summary-row\">\n                <span>Tax</span>\n                <span>{tax.toFixed(2)}</span>\n              </div>\n              <div className=\"summary-row\">\n                <span>Shipping</span>\n                <span>{shipping.toFixed(2)}</span>\n              </div>\n              <div className=\"summary-row\">\n                <span>Processing Fees</span>\n                <span>{processingFees.toFixed(2)}</span>\n              </div>\n              <div className=\"summary-row summary-total\">\n                <span>Total</span>\n                <span>${grandTotal.toFixed(2)}</span>\n              </div>\n              <div className=\"discount-code\">\n                <input type=\"text\" placeholder=\"Discount code\" className=\"discount-input\" />\n                <button className=\"apply-button\">APPLY</button>\n              </div>\n              <button className=\"checkout-button\">CHECKOUT</button>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/pages/EditProfile.tsx",
    "content": "import { useState } from 'react'\nimport { useNavigate } from 'react-router-dom'\n\nexport function EditProfile() {\n  const navigate = useNavigate()\n  const [formData, setFormData] = useState({\n    firstName: 'Doe',\n    lastName: 'John',\n    address: '4321 40th street',\n    address2: '#2F',\n    city: 'New York',\n    state: 'NY',\n    zipcode: '11101',\n    phone: '601-494-9501',\n  })\n\n  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n    setFormData({\n      ...formData,\n      [e.target.name]: e.target.value,\n    })\n  }\n\n  const handleSubmit = (e: React.FormEvent) => {\n    e.preventDefault()\n    // Here you would typically save the data\n    navigate('/profile')\n  }\n\n  const handleCancel = () => {\n    navigate('/profile')\n  }\n\n  return (\n    <div className=\"main-content\">\n      <div className=\"edit-profile-page\">\n        <h1>Edit your profile</h1>\n\n        <form onSubmit={handleSubmit}>\n          <div className=\"form-section\">\n            <label className=\"form-label\">Profile picture</label>\n            <div className=\"profile-picture-upload\">\n              <div className=\"profile-avatar-large\">\n                <svg viewBox=\"0 0 100 100\" className=\"avatar-placeholder\">\n                  <circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"#cccccc\" />\n                  <circle cx=\"50\" cy=\"40\" r=\"15\" fill=\"#999999\" />\n                  <path d=\"M 20 80 Q 20 60 50 60 Q 80 60 80 80\" fill=\"#999999\" />\n                </svg>\n              </div>\n              <button type=\"button\" className=\"upload-photo-button\">\n                UPLOAD PHOTO\n              </button>\n            </div>\n          </div>\n\n          <div className=\"form-row\">\n            <div className=\"form-group\">\n              <label className=\"form-label\" htmlFor=\"firstName\">\n                Firstname\n              </label>\n              <input\n                type=\"text\"\n                id=\"firstName\"\n                name=\"firstName\"\n                className=\"form-input\"\n                value={formData.firstName}\n                onChange={handleChange}\n              />\n            </div>\n            <div className=\"form-group\">\n              <label className=\"form-label\" htmlFor=\"lastName\">\n                Lastname\n              </label>\n              <input\n                type=\"text\"\n                id=\"lastName\"\n                name=\"lastName\"\n                className=\"form-input\"\n                value={formData.lastName}\n                onChange={handleChange}\n              />\n            </div>\n          </div>\n\n          <div className=\"form-group\">\n            <label className=\"form-label\" htmlFor=\"address\">\n              Address\n            </label>\n            <input\n              type=\"text\"\n              id=\"address\"\n              name=\"address\"\n              className=\"form-input\"\n              value={formData.address}\n              onChange={handleChange}\n            />\n          </div>\n\n          <div className=\"form-group\">\n            <label className=\"form-label\" htmlFor=\"address2\">\n              Address 2\n            </label>\n            <input\n              type=\"text\"\n              id=\"address2\"\n              name=\"address2\"\n              className=\"form-input\"\n              value={formData.address2}\n              onChange={handleChange}\n            />\n          </div>\n\n          <div className=\"form-row\">\n            <div className=\"form-group\">\n              <label className=\"form-label\" htmlFor=\"city\">\n                City\n              </label>\n              <input\n                type=\"text\"\n                id=\"city\"\n                name=\"city\"\n                className=\"form-input\"\n                value={formData.city}\n                onChange={handleChange}\n              />\n            </div>\n            <div className=\"form-group\">\n              <label className=\"form-label\" htmlFor=\"state\">\n                State\n              </label>\n              <select id=\"state\" name=\"state\" className=\"form-select\" value={formData.state} onChange={handleChange}>\n                <option value=\"NY\">NY</option>\n                <option value=\"CA\">CA</option>\n                <option value=\"TX\">TX</option>\n                <option value=\"FL\">FL</option>\n              </select>\n            </div>\n            <div className=\"form-group\">\n              <label className=\"form-label\" htmlFor=\"zipcode\">\n                Zipcode\n              </label>\n              <input\n                type=\"text\"\n                id=\"zipcode\"\n                name=\"zipcode\"\n                className=\"form-input\"\n                value={formData.zipcode}\n                onChange={handleChange}\n              />\n            </div>\n          </div>\n\n          <div className=\"form-group\">\n            <label className=\"form-label\" htmlFor=\"phone\">\n              Mobile phone number\n            </label>\n            <input\n              type=\"tel\"\n              id=\"phone\"\n              name=\"phone\"\n              className=\"form-input\"\n              value={formData.phone}\n              onChange={handleChange}\n            />\n          </div>\n\n          <div className=\"form-actions\">\n            <button type=\"button\" className=\"cancel-button\" onClick={handleCancel}>\n              CANCEL\n            </button>\n            <button type=\"submit\" className=\"save-button\">\n              SAVE PROFILE\n            </button>\n          </div>\n        </form>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/pages/Home.tsx",
    "content": "import { useState, useEffect, useMemo } from 'react'\nimport { useParams } from 'react-router-dom'\nimport type { Product } from '../data/products'\nimport { fetchProducts } from '../data/products'\nimport { ProductCard } from '../components/ProductCard'\nimport { PromoBanner } from '../components/PromoBanner'\n\ninterface HomeProps {\n  onAddToCart: (product: Product) => void\n  searchQuery: string\n}\n\nexport function Home({ onAddToCart, searchQuery }: HomeProps) {\n  const { category } = useParams<{ category?: string }>()\n  const [products, setProducts] = useState<Product[]>([])\n  const [loading, setLoading] = useState(true)\n  const [error, setError] = useState<string | null>(null)\n\n  useEffect(() => {\n    fetchProducts()\n      .then((data) => {\n        setProducts(data)\n        setLoading(false)\n      })\n      .catch((err) => {\n        setError(err.message)\n        setLoading(false)\n      })\n  }, [])\n\n  const filteredProducts = useMemo(\n    () =>\n      products.filter((product) => {\n        // Normalize category from URL (e.g., \"chairs\" -> \"Chairs\")\n        const normalizedCategory = category ? category.charAt(0).toUpperCase() + category.slice(1).toLowerCase() : ''\n\n        const matchesCategory = !normalizedCategory || product.category === normalizedCategory\n        const matchesSearch =\n          product.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n          product.description.toLowerCase().includes(searchQuery.toLowerCase())\n        return matchesCategory && matchesSearch\n      }),\n    [products, searchQuery, category]\n  )\n\n  if (loading) {\n    return (\n      <div className=\"main-content\">\n        <div className=\"product-grid\">\n          {Array.from({ length: 8 }).map((_, index) => (\n            <div key={index} className=\"skeleton-card\">\n              <div className=\"skeleton-image\"></div>\n              <div className=\"skeleton-info\">\n                <div className=\"skeleton-title\"></div>\n                <div className=\"skeleton-price\"></div>\n              </div>\n            </div>\n          ))}\n        </div>\n      </div>\n    )\n  }\n\n  if (error) {\n    return (\n      <div className=\"main-content\">\n        <div className=\"empty-cart\">\n          <h2>Error loading products</h2>\n          <p>{error}</p>\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"main-content\">\n      {filteredProducts.length !== 0 && (\n        <>\n          <PromoBanner />\n          <div className=\"product-grid\">\n            {filteredProducts.map((product) => (\n              <ProductCard key={product.id} product={product} onAddToCart={onAddToCart} />\n            ))}\n          </div>\n        </>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/pages/ProductDetail.tsx",
    "content": "import { useState, useEffect } from 'react'\nimport { useParams, useNavigate } from 'react-router-dom'\nimport type { Product } from '../data/products'\nimport { fetchProducts } from '../data/products'\n\ninterface ProductDetailProps {\n  onAddToCart: (product: Product) => void\n}\n\nexport function ProductDetail({ onAddToCart }: ProductDetailProps) {\n  const { id } = useParams<{ id: string }>()\n  const navigate = useNavigate()\n  const [product, setProduct] = useState<Product | null>(null)\n  const [loading, setLoading] = useState(true)\n  const [error, setError] = useState<string | null>(null)\n\n  useEffect(() => {\n    fetchProducts()\n      .then((products) => {\n        const found = products.find((p) => p.id === Number(id))\n        setProduct(found || null)\n        setLoading(false)\n      })\n      .catch((err) => {\n        setError(err.message)\n        setLoading(false)\n      })\n  }, [id])\n\n  if (loading) {\n    return (\n      <div className=\"main-content\">\n        <div className=\"empty-cart\">\n          <h2>Loading product...</h2>\n        </div>\n      </div>\n    )\n  }\n\n  if (error) {\n    return (\n      <div className=\"main-content\">\n        <div className=\"empty-cart\">\n          <h2>Error loading product</h2>\n          <p>{error}</p>\n          <button onClick={() => navigate('/')} className=\"back-button\">\n            Back to Home\n          </button>\n        </div>\n      </div>\n    )\n  }\n\n  if (!product) {\n    return (\n      <div className=\"main-content\">\n        <div className=\"empty-cart\">\n          <h2>Product not found</h2>\n          <button onClick={() => navigate('/')} className=\"back-button\">\n            Back to Home\n          </button>\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"main-content\">\n      <div className=\"product-detail\">\n        <div className=\"product-detail-content\">\n          <img src={product.image} alt={product.name} className=\"product-detail-image\" />\n          <div className=\"product-detail-info\">\n            <div className=\"product-category\">{product.category}</div>\n            <h1>{product.name}</h1>\n            <div className=\"product-rating\">\n              {'★'.repeat(Math.floor(product.rating))}\n              {'☆'.repeat(5 - Math.floor(product.rating))} {product.rating} / 5\n            </div>\n            <div className=\"product-price\">${product.price.toFixed(2)}</div>\n            <div className={`product-stock ${product.inStock ? 'in-stock' : ''}`}>\n              {product.inStock ? 'In Stock' : 'Out of Stock'}\n            </div>\n            <p className=\"product-description\">{product.description}</p>\n            <button\n              className=\"add-to-cart-button\"\n              onClick={() => onAddToCart(product)}\n              disabled={!product.inStock}\n              style={{ marginBottom: '1rem' }}\n            >\n              Add to Cart\n            </button>\n          </div>\n        </div>\n        <button onClick={() => navigate('/')} className=\"back-button\">\n          ← Back to Products\n        </button>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/pages/Profile.tsx",
    "content": "import { useNavigate } from 'react-router-dom'\n\nexport function Profile() {\n  const navigate = useNavigate()\n\n  return (\n    <div className=\"main-content\">\n      <div className=\"profile-page\">\n        <div className=\"profile-header\">\n          <div className=\"profile-avatar\">\n            <svg viewBox=\"0 0 100 100\" className=\"avatar-placeholder\">\n              <circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"#cccccc\" />\n              <circle cx=\"50\" cy=\"40\" r=\"15\" fill=\"#999999\" />\n              <path d=\"M 20 80 Q 20 60 50 60 Q 80 60 80 80\" fill=\"#999999\" />\n            </svg>\n          </div>\n          <div className=\"profile-name\">\n            <h1>Doe John</h1>\n          </div>\n        </div>\n\n        <div className=\"profile-section\">\n          <div className=\"profile-section-label\">Shipping address</div>\n          <div className=\"profile-section-content\">\n            <div>4321 40th street</div>\n            <div>#2F</div>\n            <div>New York, NY, 11101</div>\n          </div>\n        </div>\n\n        <div className=\"profile-section\">\n          <div className=\"profile-section-label\">Phone</div>\n          <div className=\"profile-section-content\">\n            <div>601-494-9501</div>\n          </div>\n        </div>\n\n        <button className=\"edit-profile-button\" onClick={() => navigate('/profile/edit')}>\n          EDIT PROFILE\n        </button>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "test/apps/react-shopist-like/tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "test/apps/react-shopist-like/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n  server: {\n    port: 3002,\n  },\n})\n"
  },
  {
    "path": "test/apps/tanstack-router-app/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*\n"
  },
  {
    "path": "test/apps/tanstack-router-app/app.tsx",
    "content": "import ReactDOM from 'react-dom/client'\nimport { RouterProvider, Link, Outlet, useParams, createRootRoute, createRoute, redirect } from '@tanstack/react-router'\nimport { datadogRum } from '@datadog/browser-rum'\nimport { reactPlugin } from '@datadog/browser-rum-react'\nimport { createRouter } from '@datadog/browser-rum-react/tanstack-router'\n\ndeclare global {\n  interface Window {\n    RUM_CONFIGURATION?: any\n    RUM_CONTEXT?: any\n  }\n}\n\ndatadogRum.init({ ...window.RUM_CONFIGURATION, plugins: [reactPlugin({ router: true })] })\nif (window.RUM_CONTEXT) {\n  datadogRum.setGlobalContext(window.RUM_CONTEXT)\n}\n\n// Routes\n\nconst rootRoute = createRootRoute({\n  component: () => (\n    <div>\n      <nav>\n        <Link to=\"/\">Home</Link>\n        {' | '}\n        <Link to=\"/posts\">Posts</Link>\n        {' | '}\n        <Link to=\"/posts/$postId\" params={{ postId: '42' }}>\n          Post 42\n        </Link>\n        {' | '}\n        <Link to=\"/\" search={{ tab: 'settings' } as Record<string, string>}>\n          Query Param\n        </Link>\n        {' | '}\n        <Link to=\"/files/$\" params={{ _splat: 'path/to/file' }}>\n          Splat\n        </Link>\n        {' | '}\n        <Link to=\"/old-posts\">Redirect</Link>\n      </nav>\n      <hr />\n      <Outlet />\n    </div>\n  ),\n})\n\nconst indexRoute = createRoute({\n  getParentRoute: () => rootRoute,\n  path: '/',\n  component: () => <h1>Home</h1>,\n})\n\nconst postsRoute = createRoute({\n  getParentRoute: () => rootRoute,\n  path: '/posts',\n  component: () => (\n    <div>\n      <h1>Posts</h1>\n      <Outlet />\n    </div>\n  ),\n})\n\nconst postsIndexRoute = createRoute({\n  getParentRoute: () => postsRoute,\n  path: '/',\n  component: () => <p>Select a post</p>,\n})\n\nfunction PostDetail() {\n  const { postId } = useParams({ strict: false })\n  return <h1>Post {postId}</h1>\n}\n\nconst postRoute = createRoute({\n  getParentRoute: () => postsRoute,\n  path: '/$postId',\n  component: PostDetail,\n})\n\nconst filesRoute = createRoute({\n  getParentRoute: () => rootRoute,\n  path: '/files/$',\n  component: () => {\n    const { _splat } = useParams({ strict: false })\n    return <h1>File: {_splat}</h1>\n  },\n})\n\nconst oldPostsRoute = createRoute({\n  getParentRoute: () => rootRoute,\n  path: '/old-posts',\n  beforeLoad: () => {\n    // eslint-disable-next-line @typescript-eslint/only-throw-error\n    throw redirect({ to: '/posts' })\n  },\n})\n\nconst routeTree = rootRoute.addChildren([\n  indexRoute,\n  postsRoute.addChildren([postsIndexRoute, postRoute]),\n  filesRoute,\n  oldPostsRoute,\n])\n\n// Cast needed because local .tgz packaging creates separate type declarations.\n// End users installing from npm won't need this — same pattern as react-router-v6-app.\nconst router = createRouter({ routeTree } as any)\n\nconst rootElement = document.createElement('div')\ndocument.body.appendChild(rootElement)\nconst root = ReactDOM.createRoot(rootElement)\nroot.render(<RouterProvider router={router as any} />)\n"
  },
  {
    "path": "test/apps/tanstack-router-app/package.json",
    "content": "{\n  \"name\": \"tanstack-router-app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack\"\n  },\n  \"dependencies\": {\n    \"@tanstack/react-router\": \"1.168.10\",\n    \"react\": \"19.2.4\",\n    \"react-dom\": \"19.2.4\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"*\",\n    \"@datadog/browser-rum-react\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-react\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-rum-react\": \"file:../../../packages/rum-react/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"@datadog/browser-rum\": \"6.32.0\",\n    \"@datadog/browser-rum-react\": \"6.32.0\",\n    \"ts-loader\": \"9.5.7\",\n    \"typescript\": \"5.9.3\",\n    \"webpack\": \"5.105.4\",\n    \"webpack-cli\": \"6.0.1\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/tanstack-router-app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/\",\n    \"strict\": true,\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"jsx\": \"react-jsx\",\n    \"target\": \"ES2018\",\n    \"lib\": [\"ES2018\", \"DOM\"],\n    \"types\": []\n  }\n}\n"
  },
  {
    "path": "test/apps/tanstack-router-app/webpack.config.js",
    "content": "const path = require('node:path')\n\nmodule.exports = {\n  mode: 'production',\n  entry: './app.tsx',\n  target: ['web', 'es2018'],\n  module: {\n    rules: [\n      {\n        test: /\\.(ts|tsx)$/,\n        use: 'ts-loader',\n      },\n    ],\n  },\n  resolve: {\n    extensions: ['.ts', '.tsx', '.js', '.jsx'],\n  },\n  optimization: {\n    chunkIds: 'named',\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'tanstack-router-app.js',\n    chunkFilename: 'chunks/[name]-[contenthash]-tanstack-router-app.js',\n  },\n}\n"
  },
  {
    "path": "test/apps/vanilla/.gitignore",
    "content": "dist\nnode_modules\n\n# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored\n.pnp.*\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n"
  },
  {
    "path": "test/apps/vanilla/app.ts",
    "content": "import { datadogLogs } from '@datadog/browser-logs'\nimport { datadogRum } from '@datadog/browser-rum'\n\ndeclare global {\n  interface Window {\n    LOGS_INIT?: () => void\n    RUM_INIT?: () => void\n  }\n}\n\nif (typeof window !== 'undefined') {\n  if (window.LOGS_INIT) {\n    window.LOGS_INIT()\n  }\n\n  if (window.RUM_INIT) {\n    window.RUM_INIT()\n  }\n} else {\n  // compat test\n  datadogLogs.init({ clientToken: 'xxx', beforeSend: undefined })\n  datadogRum.init({ clientToken: 'xxx', applicationId: 'xxx', beforeSend: undefined })\n  datadogRum.setUser({ id: undefined })\n}\n"
  },
  {
    "path": "test/apps/vanilla/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"webpack --config ./webpack.web.js\",\n    \"compat:tsc\": \"tsc -p tsconfig.json\",\n    \"compat:ssr\": \"webpack --config ./webpack.ssr.js && node dist/app.js\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-logs\": \"*\",\n    \"@datadog/browser-rum\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-logs\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-logs\": \"file:../../../packages/logs/package.tgz\",\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-rum-react\": \"file:../../../packages/rum-react/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"ts-loader\": \"9.5.7\",\n    \"typescript\": \"6.0.2\",\n    \"webpack\": \"5.105.4\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/vanilla/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/\",\n    \"strict\": true,\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"bundler\",\n    \"target\": \"es2015\",\n    \"lib\": [\"ES2015\", \"DOM\"],\n    \"types\": []\n  }\n}\n"
  },
  {
    "path": "test/apps/vanilla/webpack.base.js",
    "content": "const path = require('node:path')\n\nconst filename = 'app.js'\nmodule.exports = ({ target, optimization, mode }) => ({\n  mode,\n  entry: './app.ts',\n  target,\n  module: {\n    rules: [\n      {\n        test: /\\.ts$/,\n        use: 'ts-loader',\n      },\n    ],\n  },\n  resolve: {\n    extensions: ['.ts', '.js'],\n  },\n  optimization,\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename,\n    chunkFilename: `chunks/[name]-[contenthash]-${filename}`,\n  },\n})\n"
  },
  {
    "path": "test/apps/vanilla/webpack.ssr.js",
    "content": "const webpackBase = require('./webpack.base')\n\nmodule.exports = () =>\n  webpackBase({\n    mode: 'development',\n    target: ['node', 'es2018'],\n    optimization: {\n      minimize: true,\n    },\n  })\n"
  },
  {
    "path": "test/apps/vanilla/webpack.web.js",
    "content": "const webpackBase = require('./webpack.base')\n\nmodule.exports = () =>\n  webpackBase({\n    mode: 'production',\n    target: ['web', 'es2018'],\n    optimization: { chunkIds: 'named' },\n  })\n"
  },
  {
    "path": "test/apps/vue-router-app/.gitignore",
    "content": "dist\nnode_modules\n.yarn/*\n"
  },
  {
    "path": "test/apps/vue-router-app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"data:,\" />\n    <title>Vue RUM App</title>\n    <script>\n      window.RUM_CONFIGURATION = {\n        applicationId: 'xxx',\n        clientToken: 'xxx',\n        site: 'datadoghq.com',\n        trackUserInteractions: true,\n      }\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/apps/vue-router-app/package.json",
    "content": "{\n  \"name\": \"vue-router-app\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"dev\": \"vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"3.5.32\",\n    \"vue-router\": \"4.6.4\"\n  },\n  \"peerDependencies\": {\n    \"@datadog/browser-rum\": \"*\",\n    \"@datadog/browser-rum-vue\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@datadog/browser-rum\": {\n      \"optional\": true\n    },\n    \"@datadog/browser-rum-vue\": {\n      \"optional\": true\n    }\n  },\n  \"resolutions\": {\n    \"@datadog/browser-rum-core\": \"file:../../../packages/rum-core/package.tgz\",\n    \"@datadog/browser-core\": \"file:../../../packages/core/package.tgz\",\n    \"@datadog/browser-rum\": \"file:../../../packages/rum/package.tgz\",\n    \"@datadog/browser-rum-vue\": \"file:../../../packages/rum-vue/package.tgz\",\n    \"@datadog/browser-rum-slim\": \"file:../../../packages/rum-slim/package.tgz\",\n    \"@datadog/browser-worker\": \"file:../../../packages/worker/package.tgz\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"5.x\",\n    \"typescript\": \"5.x\",\n    \"vite\": \"7.x\"\n  },\n  \"volta\": {\n    \"extends\": \"../../../package.json\"\n  }\n}\n"
  },
  {
    "path": "test/apps/vue-router-app/src/App.vue",
    "content": "<template>\n  <RouterView />\n</template>\n"
  },
  {
    "path": "test/apps/vue-router-app/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport { createWebHistory } from 'vue-router'\nimport { createRouter } from '@datadog/browser-rum-vue/vue-router-v4'\nimport { datadogRum } from '@datadog/browser-rum'\nimport { vuePlugin, addVueError } from '@datadog/browser-rum-vue'\nimport App from './App.vue'\n\ndeclare global {\n  interface Window {\n    RUM_CONFIGURATION?: any\n    RUM_CONTEXT?: any\n  }\n}\n\nconst router = createRouter({\n  history: createWebHistory(),\n  routes: [\n    { path: '/', component: () => import('./pages/HomePage.vue') },\n    { path: '/user/:id', component: () => import('./pages/UserPage.vue') },\n    { path: '/guides/:catchAll(.*)*', component: () => import('./pages/GuidesPage.vue') },\n    { path: '/error-test', component: () => import('./pages/ErrorPage.vue') },\n  ],\n})\n\nconst params = new URLSearchParams(window.location.search)\nconst rumConfig = params.get('rum-config')\nconst rumContext = params.get('rum-context')\n\nconst config = rumConfig ? JSON.parse(rumConfig) : window.RUM_CONFIGURATION\nconst context = rumContext ? JSON.parse(rumContext) : window.RUM_CONTEXT\n\ndatadogRum.init({ ...config, plugins: [vuePlugin({ router: true })] })\n\nif (context) {\n  datadogRum.setGlobalContext(context)\n}\n\nconst app = createApp(App)\napp.config.errorHandler = addVueError\napp.use(router).mount('#app')\n"
  },
  {
    "path": "test/apps/vue-router-app/src/pages/ErrorPage.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nconst hasError = ref(false)\nfunction triggerError() {\n  hasError.value = true\n  throw new Error('Error triggered by button click')\n}\n</script>\n<template>\n  <div>\n    <h1>Error Page</h1>\n    <button data-testid=\"trigger-error\" @click=\"triggerError\">Trigger Error</button>\n    <div v-if=\"hasError\" data-testid=\"error-handled\">Error occurred</div>\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/vue-router-app/src/pages/GuidesPage.vue",
    "content": "<template>\n  <div>\n    <h1>Guides</h1>\n    <router-link to=\"/\">Back to Home</router-link>\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/vue-router-app/src/pages/HomePage.vue",
    "content": "<template>\n  <div>\n    <h1>Home</h1>\n    <router-link to=\"/user/42?admin=true\">Go to User 42</router-link><br />\n    <router-link to=\"/guides/123\">Go to Guides 123</router-link><br />\n    <router-link to=\"/error-test\">Go to Error Test</router-link>\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/vue-router-app/src/pages/UserPage.vue",
    "content": "<script setup lang=\"ts\">\nimport { useRoute } from 'vue-router'\nconst route = useRoute()\n</script>\n<template>\n  <div>\n    <h1>User {{ route.params.id }}</h1>\n    <router-link to=\"/\">Back to Home</router-link><br />\n    <router-link :to=\"`/user/${route.params.id}#section`\">Go to Section</router-link><br />\n    <router-link :to=\"`/user/${route.params.id}?admin=false`\">Change query params</router-link><br />\n    <router-link to=\"/user/999?admin=true\">Go to User 999</router-link>\n  </div>\n</template>\n"
  },
  {
    "path": "test/apps/vue-router-app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"target\": \"ES2017\"\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.vue\", \"vite.config.ts\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  },
  {
    "path": "test/apps/vue-router-app/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n  build: {\n    outDir: 'dist',\n  },\n  preview: {\n    host: true,\n  },\n  server: {\n    host: true,\n  },\n})\n"
  },
  {
    "path": "test/browsers.conf.d.ts",
    "content": "export interface BrowserConfiguration {\n  sessionName: string\n  name: string\n  version?: string\n  os: string\n  osVersion: string\n  device?: string\n}\n"
  },
  {
    "path": "test/e2e/AGENTS.md",
    "content": "# End-to-End Testing\n\nE2E tests use Playwright to test the SDK in real browser environments.\n\n## Running E2E Tests\n\n```bash\n# First time setup (builds packages, apps, installs or updates Playwright browsers)\nyarn test:e2e:init\n\n# Run E2E tests locally\nyarn test:e2e\n\n# Run tests matching specific pattern\nyarn test:e2e -g \"unhandled rejections\"\n```\n\n**Important**: `yarn test:e2e` does not build the SDK automatically. Run `yarn build:apps` to rebuild the SDK and test apps if you have made changes to the source code.\n\nTo rebuild only specific apps (faster during development):\n\n```bash\n# List available apps\nyarn build:apps --help\n\n# Build a single app\nyarn build:apps --app vanilla\n\n# Build multiple apps\nyarn build:apps --app vanilla --app react-heavy-spa\n```\n\n## Test Apps\n\nLocated in `test/apps/`:\n\n### E2E Test Apps\n\n```\ntest/apps/\n├── vanilla/              # Plain JavaScript app for basic E2E tests\n├── react-router-v6-app/  # React Router v6 integration tests\n└── base-extension/       # Browser extension testing\n```\n\n### Generated Test Apps\n\nRunning `yarn build:apps` generates additional test apps from the source apps:\n\n```\ntest/apps/ (generated)\n├── react-router-v7-app/   # Generated from react-router-v6-app with RR v7\n├── cdn-extension/         # Generated from base-extension (CDN variant)\n└── appendChild-extension/ # Generated from base-extension (appendChild variant)\n```\n\n**Note**: Generated apps are not checked into Git.\n\nE2E test apps are served by the dev server and loaded in Playwright tests.\n\n## Test Organization\n\n### File Naming Convention\n\nAll E2E test files follow this pattern:\n\n- Located in `test/e2e/scenario/` directory (or subdirectories)\n- Named with `.scenario.ts` suffix\n- Examples:\n  - `test/e2e/scenario/logs.scenario.ts`\n  - `test/e2e/scenario/rum/errors.scenario.ts`\n  - `test/e2e/scenario/recorder/shadowDom.scenario.ts`\n\n### Configuration Files\n\n- `playwright.local.config.ts` - Local development\n- `playwright.bs.config.ts` - BrowserStack cloud testing\n- `playwright.base.config.ts` - Base configuration\n\n## Writing E2E Tests\n\n### Test Structure\n\nE2E tests use a custom `createTest()` builder pattern instead of raw Playwright:\n\n```typescript\nimport { test, expect } from '@playwright/test'\nimport { createTest } from '../lib/framework'\n\ntest.describe('feature name', () => {\n  createTest('should track user interactions')\n    .withRum() // Initialize RUM SDK\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      // Interact with page\n      await page.click('button')\n\n      // Wait for SDK to flush events\n      await flushEvents()\n\n      // Assert on captured events\n      expect(intakeRegistry.rumEvents).toHaveLength(1)\n      expect(intakeRegistry.rumEvents[0].type).toBe('action')\n    })\n})\n```\n\n### Key `createTest()` Methods\n\n**SDK Configuration:**\n\n- `.withRum(config?)` - Initialize RUM SDK with optional config\n- `.withLogs(config?)` - Initialize Logs SDK with optional config\n- `.withRumSlim()` - Also test with rum-slim variant\n- `.withWorker(worker)` - Test with Service Worker (pass a `createWorker()` builder)\n\n**Custom Initialization:**\n\n- `.withRumInit(fn)` - Custom RUM initialization logic\n- `.withLogsInit(fn)` - Custom Logs initialization logic\n\n**Page Customization:**\n\n- `.withHead(html)` - Add content to `<head>`\n- `.withBody(html)` - Add content to `<body>`\n- `.withReactApp(name)` - Use a React test app\n- `.withExtension(ext)` - Test with browser extension\n\n**Configuration:**\n\n- `.withRemoteConfiguration(config)` - Simulate remote config\n- `.withEventBridge()` - Enable event bridge (for mobile/React Native)\n- `.withBasePath(path)` - Change base URL path\n\n### Test Setups\n\nBy default, each test runs with multiple SDK integration setups:\n\n- **CDN** - SDK loaded via `<script>` tag (CDN bundle)\n- **npm** - SDK imported as ES module (npm package)\n\nThis ensures the SDK works correctly in both integration methods. Tests appear as multiple test cases in the Playwright UI.\n\nTo use only one setup (not recommended):\n\n```typescript\ncreateTest('should work with custom setup')\n  .withRum()\n  .withSetup(cdnSetup) // Only test CDN setup\n  .run(async ({ intakeRegistry, flushEvents }) => {\n    // Test code\n  })\n```\n\n### Test Context\n\nThe `.run()` callback receives a `TestContext` object:\n\n```typescript\n{\n  // Event capture\n  intakeRegistry: IntakeRegistry  // Captured SDK events\n  flushEvents: () => Promise<void>  // Wait for SDK to flush\n\n  // Playwright objects\n  page: Page\n  browserContext: BrowserContext\n  browserName: 'chromium' | 'firefox' | 'webkit' | 'msedge'\n\n  // Test servers\n  servers: Servers\n  baseUrl: string\n\n  // Browser logs\n  withBrowserLogs: (cb) => void  // Access browser console logs\n  flushBrowserLogs: () => void   // Clear browser logs\n\n  // Utilities\n  deleteAllCookies: () => Promise<void>\n  sendXhr: (url, headers?) => Promise<string>\n  evaluateInWorker: (fn) => Promise<void>  // Execute code inside the service worker\n  getExtensionId: () => Promise<string>\n}\n```\n\n### Common Patterns\n\n#### Checking Captured Events\n\n```typescript\ncreateTest('should send logs')\n  .withLogs()\n  .run(async ({ intakeRegistry, flushEvents, page }) => {\n    await page.evaluate(() => {\n      window.DD_LOGS!.logger.log('hello')\n    })\n\n    await flushEvents()\n\n    // Check captured events\n    expect(intakeRegistry.logsEvents).toHaveLength(1)\n    expect(intakeRegistry.logsEvents[0].message).toBe('hello')\n  })\n```\n\n#### Console Logs Validation\n\n```typescript\ncreateTest('should display logs in console when using console handler')\n  .withLogs()\n  .run(async ({ intakeRegistry, flushEvents, page, withBrowserLogs }) => {\n    await page.evaluate(() => {\n      window.DD_LOGS!.logger.setHandler('console')\n      window.DD_LOGS!.logger.warn('hello')\n    })\n\n    await flushEvents()\n\n    // Check console logs\n    withBrowserLogs((logs) => {\n      expect(logs).toHaveLength(1)\n      expect(logs[0].level).toBe('warning')\n      expect(logs[0].message).toEqual(expect.stringContaining('hello'))\n    })\n  })\n```\n\n**Note**: The test teardown automatically validates that there are no console errors. Use `withBrowserLogs()` to check for specific warning messages or console output.\n\n#### Conditional Tests\n\n```typescript\ncreateTest('should work in chromium only')\n  .withRum()\n  .run(async ({ browserName }) => {\n    test.skip(browserName !== 'chromium', 'Chromium-only feature')\n\n    // Test chromium-specific behavior\n  })\n```\n\n### Service Worker Testing\n\nUse `createWorker()` to configure a service worker with SDK products:\n\n```typescript\nimport { createTest, createWorker } from '../lib/framework'\n\ncreateTest('worker with logs')\n  .withWorker(createWorker().withLogs({ forwardConsoleLogs: 'all' }))\n  .run(async ({ evaluateInWorker, flushEvents, intakeRegistry }) => {\n    await evaluateInWorker(() => {\n      DD_LOGS!.logger.log('hello from worker')\n    })\n    await flushEvents()\n    expect(intakeRegistry.logsEvents[0].message).toBe('hello from worker')\n  })\n```\n\n- `createWorker({ importScripts: true })` - Use `importScripts` instead of ES modules\n- `.withLogs(config?)` - Initialize Logs SDK in the worker\n- `.withRum(config?)` - Initialize RUM SDK in the worker\n- `evaluateInWorker(fn)` - Execute a function inside the service worker scope\n- ESM workers only work in Chromium; use `test.skip` for other browsers\n\n### IntakeRegistry\n\nThe `intakeRegistry` object captures all events sent by the SDK:\n\n```typescript\nintakeRegistry.rumEvents // All RUM events\nintakeRegistry.rumViewEvents // View events\nintakeRegistry.rumActionEvents // Action events\nintakeRegistry.rumErrorEvents // Error events\nintakeRegistry.rumResourceEvents // Resource events\nintakeRegistry.rumLongTaskEvents // Long task events\n\nintakeRegistry.logsEvents // All log events\n\nintakeRegistry.telemetryEvents // Telemetry events\nintakeRegistry.telemetryErrorEvents // Telemetry errors\n\nintakeRegistry.rumRequests // Raw HTTP requests (RUM)\nintakeRegistry.logsRequests // Raw HTTP requests (Logs)\n```\n\n### Test Isolation\n\nEach test automatically:\n\n- Starts with a fresh page\n- Clears cookies between tests\n- Flushes events after test completion\n- Validates no telemetry errors occurred\n- Validates no console errors occurred\n- Validates RUM event format\n\n## Best Practices\n\n### Better Assertions\n\n```typescript\n// ✅ Good - shows actual array content on failure\nexpect([1, 2, 3]).toHaveLength(3)\n\n// ❌ Less helpful - only shows length mismatch\nexpect([1, 2, 3].length).toBe(3)\n```\n\n## Common Pitfalls\n\n❌ **Don't** use `page.waitForRequest()` - use `intakeRegistry` instead  \n❌ **Don't** forget `await flushEvents()` before checking `intakeRegistry`  \n❌ **Don't** test SDK internals - test observable behavior (captured events)  \n❌ **Don't** use `.withRumInit()` AND `.withRum()` config together (init overrides config)  \n❌ **Don't** create tests without the `.scenario.ts` suffix\n\n✅ **Do** use `createTest()` builder pattern  \n✅ **Do** use `intakeRegistry` to check captured events  \n✅ **Do** test real user workflows  \n✅ **Do** validate event structure and content  \n✅ **Do** check browser logs with `withBrowserLogs()`  \n✅ **Do** use `test.skip()` for browser-specific tests\n"
  },
  {
    "path": "test/e2e/CLAUDE.md",
    "content": "# End-to-End Testing\n\nSee @./AGENTS.md for documentation on writing and running E2E tests.\n"
  },
  {
    "path": "test/e2e/browsers.conf.js",
    "content": "// Capabilities: https://www.browserstack.com/automate/capabilities\n\n/**\n * @type {Array<import('../browsers.conf').BrowserConfiguration>}\n */\nconst browserConfigurations = [\n  {\n    sessionName: 'Edge',\n    name: 'edge',\n    version: '100.0',\n    os: 'Windows',\n    osVersion: '11',\n  },\n  {\n    sessionName: 'Firefox',\n    name: 'playwright-firefox',\n    version: '119',\n    os: 'Windows',\n    osVersion: '11',\n  },\n  {\n    sessionName: 'Webkit',\n    name: 'playwright-webkit',\n    version: '17.4',\n    os: 'OS X',\n    osVersion: 'Big Sur',\n  },\n]\n\nmodule.exports = {\n  browserConfigurations,\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/createExtension.ts",
    "content": "import fs from 'fs'\nimport type { RumInitConfiguration } from '@datadog/browser-rum-core'\nimport type test from '@playwright/test'\nimport type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport { createExtensionTest } from '../helpers/extensionFixture'\nimport { DEFAULT_LOGS_CONFIGURATION, DEFAULT_RUM_CONFIGURATION } from '../helpers/configuration'\n\nexport function createExtension(path: string) {\n  return new Extension(path)\n}\n\n// TODO: the recorder is lazy loaded and does not works in an browser extension content script\nconst DISABLE_SESSION_REPLAY_CONFIGURATION = { sessionReplaySampleRate: 0 }\n\nexport class Extension {\n  public fixture: typeof test\n  public rumConfiguration: RumInitConfiguration | undefined\n  public logsConfiguration: LogsInitConfiguration | undefined\n\n  constructor(path: string) {\n    if (!fs.existsSync(path)) {\n      throw new Error(`Extension ${path} does not exist`)\n    }\n    this.fixture = createExtensionTest(path)\n\n    return this\n  }\n\n  withRum(rumInitConfiguration: Partial<RumInitConfiguration> = {}) {\n    this.rumConfiguration = {\n      ...DEFAULT_RUM_CONFIGURATION,\n      ...DISABLE_SESSION_REPLAY_CONFIGURATION,\n      ...rumInitConfiguration,\n    }\n\n    return this\n  }\n\n  withLogs(logsInitConfiguration: Partial<LogsInitConfiguration> = {}) {\n    this.logsConfiguration = {\n      ...DEFAULT_LOGS_CONFIGURATION,\n      ...DISABLE_SESSION_REPLAY_CONFIGURATION,\n      ...logsInitConfiguration,\n    }\n\n    return this\n  }\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/createTest.ts",
    "content": "import type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport type { RumInitConfiguration, RemoteConfiguration } from '@datadog/browser-rum-core'\nimport type { BrowserContext, Page } from '@playwright/test'\nimport { test, expect } from '@playwright/test'\nimport { addTag, addTestOptimizationTags } from '../helpers/tags'\nimport { getRunId } from '../../../envUtils'\nimport type { BrowserLog } from '../helpers/browser'\nimport { BrowserLogsManager, deleteAllCookies, getBrowserName, sendXhr } from '../helpers/browser'\nimport { DEFAULT_LOGS_CONFIGURATION, DEFAULT_RUM_CONFIGURATION } from '../helpers/configuration'\nimport { validateRumFormat } from '../helpers/validation'\nimport type { BrowserConfiguration } from '../../../browsers.conf'\nimport { NEXTJS_APP_ROUTER_PORT, NUXT_APP_PORT, VUE_ROUTER_APP_PORT } from '../helpers/playwright'\nimport { IntakeRegistry } from './intakeRegistry'\nimport { flushEvents } from './flushEvents'\nimport type { Servers } from './httpServers'\nimport { getTestServers, waitForServersIdle } from './httpServers'\nimport type { CallerLocation, SetupFactory, SetupOptions, UrlHook } from './pageSetups'\nimport { html, DEFAULT_SETUPS, npmSetup, appSetup, formatConfiguration } from './pageSetups'\nimport { createIntakeServerApp } from './serverApps/intake'\nimport { createMockServerApp } from './serverApps/mock'\nimport type { Extension } from './createExtension'\nimport type { Worker } from './createWorker'\nimport { isBrowserStack } from './environment'\n\nexport function createTest(title: string) {\n  return new TestBuilder(title, captureCallerLocation())\n}\n\ninterface TestContext {\n  baseUrl: string\n  intakeRegistry: IntakeRegistry\n  servers: Servers\n  page: Page\n  browserContext: BrowserContext\n  browserName: 'chromium' | 'firefox' | 'webkit' | 'msedge'\n  getExtensionId: () => Promise<string>\n  withBrowserLogs: (cb: (logs: BrowserLog[]) => void) => void\n  flushBrowserLogs: () => void\n  flushEvents: () => Promise<void>\n  deleteAllCookies: () => Promise<void>\n  sendXhr: (url: string, headers?: string[][]) => Promise<string>\n  evaluateInWorker: (fn: () => void) => Promise<void>\n}\n\ntype TestRunner = (testContext: TestContext) => Promise<void> | void\n\nclass TestBuilder {\n  private rumConfiguration: RumInitConfiguration | undefined = undefined\n  private alsoRunWithRumSlim = false\n  private logsConfiguration: LogsInitConfiguration | undefined = undefined\n  private remoteConfiguration?: RemoteConfiguration = undefined\n  private head = ''\n  private body = ''\n  private baseUrlHooks: UrlHook[] = []\n  private eventBridge = false\n  private setups: Array<{ factory: SetupFactory; name?: string }> = DEFAULT_SETUPS\n  private testFixture: typeof test = test\n  private extension: {\n    rumConfiguration?: RumInitConfiguration\n    logsConfiguration?: LogsInitConfiguration\n  } = {}\n  private worker: Worker | undefined\n\n  constructor(\n    private title: string,\n    private callerLocation: CallerLocation | undefined\n  ) {}\n\n  withRum(rumInitConfiguration?: Partial<RumInitConfiguration>) {\n    this.rumConfiguration = { ...DEFAULT_RUM_CONFIGURATION, ...rumInitConfiguration }\n    return this\n  }\n\n  withRumSlim() {\n    this.alsoRunWithRumSlim = true\n    return this\n  }\n\n  withRumInit(rumInit: (initConfiguration: RumInitConfiguration) => void) {\n    this.rumInit = rumInit\n    return this\n  }\n\n  withLogsInit(logsInit: (initConfiguration: LogsInitConfiguration) => void) {\n    this.logsInit = logsInit\n    return this\n  }\n\n  withLogs(logsInitConfiguration?: Partial<LogsInitConfiguration>) {\n    this.logsConfiguration = { ...DEFAULT_LOGS_CONFIGURATION, ...logsInitConfiguration }\n    return this\n  }\n\n  withHead(head: string) {\n    this.head = head\n    return this\n  }\n\n  withBody(body: string) {\n    this.body = body\n    return this\n  }\n\n  withEventBridge() {\n    this.eventBridge = true\n    return this\n  }\n\n  withApp(appName: string) {\n    this.setups = [{ factory: (options, servers) => appSetup(options, servers, appName) }]\n    return this\n  }\n\n  withVueApp() {\n    this.baseUrlHooks.push((baseUrl, servers, { rum, context }) => {\n      baseUrl.port = VUE_ROUTER_APP_PORT\n      if (rum) {\n        baseUrl.searchParams.set('rum-config', formatConfiguration(rum, servers))\n      }\n      if (context) {\n        baseUrl.searchParams.set('rum-context', JSON.stringify(context))\n      }\n    })\n    this.setups = [{ factory: () => '' }]\n    return this\n  }\n\n  withNextjsApp(router: 'app' | 'pages') {\n    const basePath = router === 'pages' ? '/pages-router' : ''\n    this.baseUrlHooks.push((baseUrl, servers, { rum, context }) => {\n      baseUrl.port = NEXTJS_APP_ROUTER_PORT\n      if (basePath) {\n        baseUrl.pathname = basePath + (baseUrl.pathname === '/' ? '' : baseUrl.pathname)\n      }\n      if (rum) {\n        baseUrl.searchParams.set('rum-config', formatConfiguration(rum, servers))\n      }\n      if (context) {\n        baseUrl.searchParams.set('rum-context', JSON.stringify(context))\n      }\n    })\n    this.setups = [{ factory: () => '' }]\n    return this\n  }\n\n  withNuxtApp() {\n    this.baseUrlHooks.push((baseUrl, servers, { rum, context }) => {\n      baseUrl.port = NUXT_APP_PORT\n      if (rum) {\n        baseUrl.searchParams.set('rum-config', formatConfiguration(rum, servers))\n      }\n      if (context) {\n        baseUrl.searchParams.set('rum-context', JSON.stringify(context))\n      }\n    })\n    this.setups = [{ factory: () => '' }]\n    return this\n  }\n\n  withBasePath(newBasePath: string) {\n    this.baseUrlHooks.push((baseUrl) => {\n      const parsed = new URL(newBasePath, baseUrl.href)\n      baseUrl.pathname = parsed.pathname\n      baseUrl.search = parsed.search\n    })\n    return this\n  }\n\n  withSetup(setup: SetupFactory) {\n    this.setups = [{ factory: setup }]\n    return this\n  }\n\n  withExtension(extension: Extension) {\n    this.testFixture = extension.fixture\n    this.extension.rumConfiguration = extension.rumConfiguration\n    this.extension.logsConfiguration = extension.logsConfiguration\n\n    return this\n  }\n\n  withRemoteConfiguration(remoteConfiguration: RemoteConfiguration) {\n    this.remoteConfiguration = remoteConfiguration\n    return this\n  }\n\n  withWorker(worker: Worker) {\n    this.worker = worker\n\n    const url = worker.importScripts ? '/sw.js?importScripts=true' : '/sw.js'\n    const options = worker.importScripts ? '{}' : '{ type: \"module\" }'\n\n    // Service workers require HTTPS or localhost due to browser security restrictions\n    this.withHostName('localhost')\n    this.withBody(html`\n      <script>\n        if (!window.myServiceWorker && 'serviceWorker' in navigator) {\n          navigator.serviceWorker.register('${url}', ${options}).then((registration) => {\n            window.myServiceWorker = registration\n          })\n        }\n      </script>\n    `)\n\n    return this\n  }\n\n  withHostName(hostName: string) {\n    this.baseUrlHooks.push((baseUrl) => {\n      baseUrl.hostname = hostName\n    })\n    return this\n  }\n\n  run(runner: TestRunner) {\n    const setupOptions: SetupOptions = {\n      body: this.body,\n      head: this.head,\n      logs: this.logsConfiguration,\n      rum: this.rumConfiguration,\n      remoteConfiguration: this.remoteConfiguration,\n      rumInit: this.rumInit,\n      logsInit: this.logsInit,\n      useRumSlim: false,\n      eventBridge: this.eventBridge,\n      baseUrlHooks: this.baseUrlHooks,\n      context: {\n        run_id: getRunId(),\n        test_name: '<PLACEHOLDER>',\n      },\n      testFixture: this.testFixture,\n      extension: this.extension,\n      worker: this.worker,\n      callerLocation: this.callerLocation,\n    }\n\n    if (this.alsoRunWithRumSlim) {\n      this.testFixture.describe(this.title, () => {\n        declareTestsForSetups('rum', this.setups, setupOptions, runner)\n        declareTestsForSetups(\n          'rum-slim',\n          this.setups.filter((setup) => setup.factory !== npmSetup && setup.factory !== appSetup),\n          { ...setupOptions, useRumSlim: true },\n          runner\n        )\n      })\n    } else {\n      declareTestsForSetups(this.title, this.setups, setupOptions, runner)\n    }\n  }\n\n  private rumInit: (configuration: RumInitConfiguration) => void = (configuration) => {\n    window.DD_RUM!.init(configuration)\n  }\n\n  private logsInit: (configuration: LogsInitConfiguration) => void = (configuration) => {\n    window.DD_LOGS!.init(configuration)\n  }\n}\n\n/**\n * Captures the location of the caller's caller (i.e. the scenario file that called run()).\n * This is used to override Playwright's default location detection so that test output\n * shows the scenario file instead of createTest.ts.\n */\nfunction captureCallerLocation(): CallerLocation | undefined {\n  const error = new Error()\n  const lines = error.stack?.split('\\n')\n  if (!lines || lines.length < 4) {\n    return undefined\n  }\n\n  // Stack layout:\n  // [0] \"Error\"\n  // [1] \"    at captureCallerLocation (...)\"\n  // [2] \"    at createTest (...)\"\n  // [3] \"    at <scenario file> (...)\"\n  const frame = lines[3]\n  const match = frame?.match(/\\((.+):(\\d+):(\\d+)\\)/) ?? frame?.match(/at (.+):(\\d+):(\\d+)/)\n  if (match) {\n    return { file: match[1], line: Number(match[2]), column: Number(match[3]) }\n  }\n  return undefined\n}\n\nfunction declareTestsForSetups(\n  title: string,\n  setups: Array<{ factory: SetupFactory; name?: string }>,\n  setupOptions: SetupOptions,\n  runner: TestRunner\n) {\n  if (setups.length > 1) {\n    setupOptions.testFixture.describe(title, () => {\n      for (const { name, factory } of setups) {\n        declareTest(name!, setupOptions, factory, runner)\n      }\n    })\n  } else if (setups.length === 1) {\n    declareTest(title, setupOptions, setups[0].factory, runner)\n  } else {\n    console.warn('no setup available for', title)\n  }\n}\n\n/**\n * Resolves the Playwright test function to use for declaring a test.\n *\n * When a callerLocation is available, accesses Playwright's internal TestTypeImpl via its\n * private Symbol to call _createTest() directly with a custom location. This makes test\n * output point to the scenario file instead of createTest.ts.\n */\nfunction resolveTestFunction(setupOptions: SetupOptions): typeof test {\n  const testFn = setupOptions.testFixture ?? test\n  const testTypeSymbol = Object.getOwnPropertySymbols(testFn).find((s) => s.description === 'testType')\n\n  if (setupOptions.callerLocation && testTypeSymbol) {\n    const testTypeImpl = (testFn as any)[testTypeSymbol]\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call\n    return testTypeImpl._createTest.bind(testTypeImpl, 'default', setupOptions.callerLocation)\n  }\n\n  return testFn\n}\n\nfunction declareTest(title: string, setupOptions: SetupOptions, factory: SetupFactory, runner: TestRunner) {\n  const testFixture = resolveTestFunction(setupOptions)\n\n  testFixture(title, async ({ page, context }: { page: Page; context: BrowserContext }) => {\n    const browserName = getBrowserName(test.info().project.name)\n    addTag('test.browserName', browserName)\n    addTestOptimizationTags(test.info().project.metadata as BrowserConfiguration)\n\n    const servers = await getTestServers()\n    const baseUrl = new URL(servers.base.origin)\n    setupOptions.baseUrlHooks.forEach((hook) => hook(baseUrl, servers, setupOptions))\n\n    test.skip(\n      baseUrl.hostname.endsWith('.localhost') && isBrowserStack,\n      // Skip those tests on BrowserStack because it doesn't support localhost subdomains. As a\n      // workaround we could use normal domains and use either:\n      // * the BrowserStack proxy capabilities -> not tried, but this sounds more complex because\n      //   we also want to run tests outside of BrowserStack\n      // * the Playwright proxy capabilities -> tried and it seems to fail because of mismatch\n      //   version between Playwright local and BrowserStack versions\n      // * a \"ngrok-like\" service -> not tried yet (it sounds more complex)\n      //\n      // See https://www.browserstack.com/support/faq/local-testing/local-exceptions/i-face-issues-while-testing-localhost-urls-or-private-servers-in-safari-on-macos-os-x-and-ios\n      'Localhost subdomains are not supported in BrowserStack'\n    )\n\n    const title = test.info().titlePath.join(' > ')\n    setupOptions.context.test_name = title\n\n    const browserLogs = new BrowserLogsManager()\n\n    const testContext = createTestContext(servers, page, context, browserLogs, browserName, baseUrl.href)\n    servers.intake.bindServerApp(createIntakeServerApp(testContext.intakeRegistry))\n\n    const setup = factory(setupOptions, servers)\n    servers.base.bindServerApp(createMockServerApp(servers, setup, setupOptions))\n    servers.crossOrigin.bindServerApp(createMockServerApp(servers, setup))\n\n    await setUpTest(browserLogs, testContext)\n\n    try {\n      await runner(testContext)\n      tearDownPassedTest(testContext)\n    } finally {\n      await tearDownTest(testContext)\n    }\n  })\n}\n\nfunction createTestContext(\n  servers: Servers,\n  page: Page,\n  browserContext: BrowserContext,\n  browserLogsManager: BrowserLogsManager,\n  browserName: TestContext['browserName'],\n  baseUrl: string\n): TestContext {\n  return {\n    baseUrl,\n    intakeRegistry: new IntakeRegistry(),\n    servers,\n    page,\n    browserContext,\n    browserName,\n    withBrowserLogs: (cb: (logs: BrowserLog[]) => void) => {\n      try {\n        cb(browserLogsManager.get())\n      } finally {\n        browserLogsManager.clear()\n      }\n    },\n    evaluateInWorker: async (fn: () => void) => {\n      await page.evaluate(async (code) => {\n        const { active, installing, waiting } = window.myServiceWorker\n        const worker = active ?? (await waitForActivation(installing ?? waiting!))\n        worker.postMessage({ __type: 'evaluate', code })\n\n        function waitForActivation(sw: ServiceWorker): Promise<ServiceWorker> {\n          return new Promise((resolve) => {\n            sw.addEventListener('statechange', () => {\n              if (sw.state === 'activated') {\n                resolve(sw)\n              }\n            })\n          })\n        }\n      }, `(${fn.toString()})()`)\n    },\n    flushBrowserLogs: () => browserLogsManager.clear(),\n    flushEvents: () => flushEvents(page),\n    deleteAllCookies: () => deleteAllCookies(browserContext),\n    sendXhr: (url: string, headers?: string[][]) => sendXhr(page, url, headers),\n    getExtensionId: async () => {\n      let [background] = browserContext.serviceWorkers()\n      if (!background) {\n        background = await browserContext.waitForEvent('serviceworker')\n      }\n\n      const extensionId = background.url().split('/')[2]\n      return extensionId || ''\n    },\n  }\n}\n\nasync function setUpTest(browserLogsManager: BrowserLogsManager, { baseUrl, page, browserContext }: TestContext) {\n  browserContext.on('console', (msg) => {\n    browserLogsManager.add({\n      level: msg.type() as BrowserLog['level'],\n      message: msg.text(),\n      source: 'console',\n      timestamp: Date.now(),\n    })\n  })\n\n  browserContext.on('weberror', (webError) => {\n    browserLogsManager.add({\n      level: 'error',\n      message: webError.error().message,\n      source: 'console',\n      timestamp: Date.now(),\n    })\n  })\n\n  await page.goto(baseUrl)\n  await waitForServersIdle()\n}\n\nfunction tearDownPassedTest({ intakeRegistry, withBrowserLogs }: TestContext) {\n  expect(intakeRegistry.telemetryErrorEvents).toHaveLength(0)\n  expect(() => validateRumFormat(intakeRegistry.rumEvents)).not.toThrow()\n  withBrowserLogs((logs) => {\n    expect(logs.filter((log) => log.level === 'error')).toHaveLength(0)\n  })\n}\n\nasync function tearDownTest({ page, flushEvents, deleteAllCookies }: TestContext) {\n  if (!page.url().includes('/flush')) {\n    await flushEvents()\n  }\n  await deleteAllCookies()\n\n  if (test.info().status === 'passed' && test.info().retry > 0) {\n    addTag('test.flaky', 'true')\n  }\n\n  const skipReason = test.info().annotations.find((annotation) => annotation.type === 'skip')?.description\n  if (skipReason) {\n    addTag('test.skip', skipReason)\n  }\n\n  const fixmeReason = test.info().annotations.find((annotation) => annotation.type === 'fixme')?.description\n  if (fixmeReason) {\n    addTag('test.fixme', fixmeReason)\n  }\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/createWorker.ts",
    "content": "import type { RumInitConfiguration } from '@datadog/browser-rum-core'\nimport type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport { DEFAULT_LOGS_CONFIGURATION, DEFAULT_RUM_CONFIGURATION } from '../helpers/configuration'\n\ninterface WorkerOptions {\n  importScripts?: boolean\n}\n\nexport function createWorker(options: WorkerOptions = {}) {\n  return new Worker(options)\n}\n\nexport class Worker {\n  public importScripts: boolean\n  public rumConfiguration: RumInitConfiguration | undefined\n  public logsConfiguration: LogsInitConfiguration | undefined\n\n  constructor({ importScripts = false }: WorkerOptions = {}) {\n    this.importScripts = importScripts\n  }\n\n  withRum(rumInitConfiguration: Partial<RumInitConfiguration> = {}) {\n    this.rumConfiguration = { ...DEFAULT_RUM_CONFIGURATION, ...rumInitConfiguration }\n    return this\n  }\n\n  withLogs(logsInitConfiguration: Partial<LogsInitConfiguration> = {}) {\n    this.logsConfiguration = { ...DEFAULT_LOGS_CONFIGURATION, ...logsInitConfiguration }\n    return this\n  }\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/environment.ts",
    "content": "export const isBrowserStack = Boolean(process.env.BROWSER_STACK)\nexport const isContinuousIntegration = Boolean(process.env.CI)\n"
  },
  {
    "path": "test/e2e/lib/framework/flushEvents.ts",
    "content": "import type { Page } from '@playwright/test'\nimport { getTestServers, waitForServersIdle } from './httpServers'\nimport { waitForRequests } from './waitForRequests'\n\nexport async function flushEvents(page: Page) {\n  await waitForRequests(page)\n  const servers = await getTestServers()\n  await Promise.all([waitForServersIdle(), page.goto(`${servers.base.origin}/flush`)])\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/httpServers.ts",
    "content": "import * as http from 'http'\nimport type { AddressInfo } from 'net'\nimport { test } from '@playwright/test'\nimport type { Browser } from '@playwright/test'\nimport { getIp } from '../../../envUtils'\n\nconst MAX_SERVER_CREATION_RETRY = 5\n// Not all port are available with BrowserStack, see https://www.browserstack.com/question/664\n// Pick a ports in range 9200-9400\nconst PORT_MIN = 9200\nconst PORT_MAX = 9400\n\nexport type ServerApp = (req: http.IncomingMessage, res: http.ServerResponse) => any\n\nexport type MockServerApp = ServerApp & {\n  getLargeResponseWroteSize(): number\n}\n\nexport interface Server<App extends ServerApp> {\n  origin: string\n  app: App\n  bindServerApp(serverApp: App): void\n  waitForIdle(): Promise<void>\n}\n\nexport interface Servers {\n  base: Server<MockServerApp>\n  intake: Server<ServerApp>\n  crossOrigin: Server<MockServerApp>\n}\n\nlet serversSingleton: undefined | Servers\n\nexport async function getTestServers() {\n  if (!serversSingleton) {\n    serversSingleton = {\n      base: await createServer(),\n      crossOrigin: await createServer(),\n      intake: await createServer(),\n    }\n  }\n  return serversSingleton\n}\n\nexport async function waitForServersIdle() {\n  // Wait for `idleWaitDuration` ms before checking idle state, to account for requests that may\n  // still be in-flight from the browser and haven't reached the server yet.\n  await new Promise((resolve) => setTimeout(resolve, idleWaitDuration))\n  const servers = await getTestServers()\n  await Promise.all([servers.base.waitForIdle(), servers.crossOrigin.waitForIdle(), servers.intake.waitForIdle()])\n}\n\nasync function createServer<App extends ServerApp>(): Promise<Server<App>> {\n  const server = await instantiateServer()\n  const address = getIp()\n  const { port } = server.address() as AddressInfo\n  let serverApp: App | undefined\n\n  server.on('request', (req: http.IncomingMessage, res: http.ServerResponse) => {\n    if (serverApp) {\n      serverApp(req, res)\n    } else {\n      res.writeHead(202)\n      res.end()\n    }\n  })\n\n  return {\n    bindServerApp(newServerApp: App) {\n      serverApp = newServerApp\n    },\n    get app() {\n      if (!serverApp) {\n        throw new Error('no server app bound')\n      }\n      return serverApp\n    },\n    origin: `http://${address}:${port}`,\n    waitForIdle: createServerIdleWaiter(server),\n  }\n}\n\nasync function instantiateServer(): Promise<http.Server> {\n  for (let tryNumber = 0; tryNumber < MAX_SERVER_CREATION_RETRY; tryNumber += 1) {\n    const port = PORT_MIN + Math.floor(Math.random() * (PORT_MAX - PORT_MIN + 1))\n\n    try {\n      return await instantiateServerOnPort(port)\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'EADDRINUSE') {\n        continue\n      }\n      throw error\n    }\n  }\n\n  throw new Error(`Failed to create a server after ${MAX_SERVER_CREATION_RETRY} retries`)\n}\n\nfunction instantiateServerOnPort(port: number): Promise<http.Server> {\n  return new Promise((resolve, reject) => {\n    const server = http.createServer()\n    server.on('error', reject)\n    server.listen(port, () => {\n      resolve(server)\n    })\n  })\n}\n\nfunction createServerIdleWaiter(server: http.Server) {\n  const idleWaiter = createIdleWaiter()\n\n  server.on('request', (_, res: http.ServerResponse) => {\n    idleWaiter.pushActivity(new Promise((resolve) => res.on('close', resolve)))\n  })\n\n  return () => idleWaiter.idlePromise\n}\n\nlet idleWaitDuration = 500\n\ntest.beforeAll(async ({ browser }) => {\n  const latency = await measureServerLatency(browser)\n  idleWaitDuration = Math.max(500, latency * 1.5)\n  console.log(`Server latency: ${latency}ms`)\n})\n\nasync function measureServerLatency(browser: Browser): Promise<number> {\n  // We measure the round-trip time to the test server to calibrate how long we wait after the\n  // last pending request before considering the server idle. In BrowserStack, the browser runs\n  // remotely, so this latency can be significant.\n  const { intake: server } = await getTestServers()\n  const page = await browser.newPage()\n  const start = Date.now()\n  await page.goto(server.origin)\n  return Date.now() - start\n}\n\nfunction createIdleWaiter() {\n  let idlePromise = Promise.resolve()\n\n  const pendingActivities = new Set<Promise<void>>()\n  let waitTimeoutId: NodeJS.Timeout\n  let resolveIdlePromise: undefined | (() => void)\n\n  return {\n    pushActivity(activity: Promise<void>) {\n      if (!resolveIdlePromise) {\n        // Before this activity, we were idle, so create a new promise that will be resolved when we\n        // are idle again.\n        idlePromise = new Promise((resolve) => {\n          resolveIdlePromise = resolve\n        })\n      }\n\n      // Cancel any timeout that would resolve the idle promise.\n      clearTimeout(waitTimeoutId)\n\n      pendingActivities.add(activity)\n      void activity.then(() => {\n        pendingActivities.delete(activity)\n\n        if (pendingActivities.size === 0) {\n          // If no more activity is pending, wait a bit before switching to idle state.\n          waitTimeoutId = setTimeout(() => {\n            resolveIdlePromise!()\n            resolveIdlePromise = undefined\n          }, idleWaitDuration)\n        }\n      })\n    },\n    get idlePromise() {\n      return idlePromise\n    },\n  }\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/index.ts",
    "content": "export { createTest } from './createTest'\nexport { DEFAULT_RUM_CONFIGURATION, DEFAULT_LOGS_CONFIGURATION } from '../helpers/configuration'\nexport { createExtension } from './createExtension'\nexport { createWorker } from './createWorker'\nexport {\n  bundleSetup,\n  html,\n  npmSetup,\n  appSetup,\n  formatConfiguration,\n  createCrossOriginScriptUrls,\n  microfrontendSetup,\n} from './pageSetups'\nexport { IntakeRegistry } from './intakeRegistry'\nexport { getTestServers, waitForServersIdle } from './httpServers'\nexport { flushEvents } from './flushEvents'\nexport { waitForRequests } from './waitForRequests'\nexport { LARGE_RESPONSE_MIN_BYTE_SIZE } from './serverApps/mock'\nexport { getSdkBundlePath, getTestAppBundlePath } from './sdkBuilds'\nexport type { BrowserLog } from '../helpers/browser'\n"
  },
  {
    "path": "test/e2e/lib/framework/intakeProxyMiddleware.ts",
    "content": "import { createInflate, inflateSync } from 'node:zlib'\nimport https from 'node:https'\nimport type express from 'express'\nimport createBusboy from 'busboy'\nimport type { BrowserProfileEvent, BrowserProfilerTrace } from '@datadog/browser-rum/src/types/profiling'\nimport type { BrowserSegment, BrowserSegmentMetadata } from '@datadog/browser-rum/src/types/sessionReplay'\nimport type { LogsEvent } from '@datadog/browser-logs/src/logsEvent.types'\nimport type { RumEvent } from '@datadog/browser-rum-core/src/rumEvent.types'\nimport type { TelemetryEvent } from '@datadog/browser-core/src/domain/telemetry/telemetryEvent.types'\n\ninterface BaseIntakeRequest {\n  isBridge: boolean\n  encoding: string | null\n  transport: string | null\n}\n\nexport type LogsIntakeRequest = {\n  intakeType: 'logs'\n  events: LogsEvent[]\n} & BaseIntakeRequest\n\nexport type RumIntakeRequest = {\n  intakeType: 'rum'\n  events: Array<RumEvent | TelemetryEvent>\n} & BaseIntakeRequest\n\nexport type ReplayIntakeRequest = {\n  intakeType: 'replay'\n  segment: BrowserSegment\n  metadata: BrowserSegmentMetadataAndSegmentSizes\n  segmentFile: {\n    filename: string\n    encoding: string\n    mimetype: string\n  }\n} & BaseIntakeRequest\n\nexport type BrowserSegmentMetadataAndSegmentSizes = BrowserSegmentMetadata & {\n  raw_segment_size: number\n  compressed_segment_size: number\n}\n\nexport type ProfileIntakeRequest = {\n  intakeType: 'profile'\n  event: BrowserProfileEvent\n  trace: BrowserProfilerTrace\n  traceFile: {\n    filename: string\n    encoding: string | null\n    mimetype: string\n  }\n} & BaseIntakeRequest\n\nexport type IntakeRequest = LogsIntakeRequest | RumIntakeRequest | ReplayIntakeRequest | ProfileIntakeRequest\n\ninterface IntakeRequestInfos {\n  isBridge: boolean\n  intakeType: IntakeRequest['intakeType']\n  encoding: string | null\n  transport: string | null\n}\n\ninterface IntakeProxyOptions {\n  onRequest?: (request: IntakeRequest) => void\n}\n\nexport function createIntakeProxyMiddleware(options: IntakeProxyOptions): express.RequestHandler {\n  return async (req, res) => {\n    const infos = computeIntakeRequestInfos(req)\n\n    try {\n      const [intakeRequest] = await Promise.all([\n        readIntakeRequest(req, infos),\n        !infos.isBridge && forwardIntakeRequestToDatadog(req),\n      ])\n      options.onRequest?.(intakeRequest)\n    } catch (error) {\n      console.error('Error while processing request:', error)\n    }\n    res.end()\n  }\n}\n\nfunction computeIntakeRequestInfos(req: express.Request): IntakeRequestInfos {\n  const ddforward = req.query.ddforward as string | undefined\n  if (!ddforward) {\n    throw new Error('ddforward is missing')\n  }\n  const { pathname, searchParams } = new URL(ddforward, 'https://example.org')\n\n  const encoding = req.headers['content-encoding'] || searchParams.get('dd-evp-encoding')\n  const transport = searchParams.get('_dd.api')\n\n  if (req.query.bridge === 'true') {\n    const eventType = req.query.event_type\n    return {\n      isBridge: true,\n      encoding,\n      transport,\n      intakeType: eventType === 'log' ? 'logs' : eventType === 'record' ? 'replay' : 'rum',\n    }\n  }\n\n  let intakeType: IntakeRequest['intakeType']\n  // pathname = /api/v2/rum\n  const endpoint = pathname.split(/[/?]/)[3]\n  if (endpoint === 'logs' || endpoint === 'rum' || endpoint === 'replay' || endpoint === 'profile') {\n    intakeType = endpoint\n  } else {\n    throw new Error(\"Can't find intake type\")\n  }\n  return {\n    isBridge: false,\n    encoding,\n    transport,\n    intakeType,\n  }\n}\n\nfunction readIntakeRequest(req: express.Request, infos: IntakeRequestInfos): Promise<IntakeRequest> {\n  if (infos.intakeType === 'replay') {\n    return readReplayIntakeRequest(req, infos as IntakeRequestInfos & { intakeType: 'replay' })\n  }\n  if (infos.intakeType === 'profile') {\n    return readProfileIntakeRequest(req, infos as IntakeRequestInfos & { intakeType: 'profile' })\n  }\n  return readRumOrLogsIntakeRequest(req, infos as IntakeRequestInfos & { intakeType: 'rum' | 'logs' })\n}\n\nasync function readRumOrLogsIntakeRequest(\n  req: express.Request,\n  infos: IntakeRequestInfos & { intakeType: 'rum' | 'logs' }\n): Promise<RumIntakeRequest | LogsIntakeRequest> {\n  const rawBody = await readStream(req)\n  const encodedBody = infos.encoding === 'deflate' ? inflateSync(rawBody) : rawBody\n\n  return {\n    ...infos,\n    events: encodedBody\n      .toString('utf-8')\n      .split('\\n')\n      .map((line): any => JSON.parse(line)),\n  }\n}\n\nfunction readReplayIntakeRequest(\n  req: express.Request,\n  infos: IntakeRequestInfos & { intakeType: 'replay' }\n): Promise<ReplayIntakeRequest> {\n  return new Promise((resolve, reject) => {\n    if (infos.isBridge) {\n      readStream(req)\n        .then((rawBody) => {\n          resolve({\n            ...infos,\n            segment: {\n              records: rawBody\n                .toString('utf-8')\n                .split('\\n')\n                .map((line): unknown => JSON.parse(line)),\n            },\n          } as ReplayIntakeRequest)\n        })\n        .catch(reject)\n      return\n    }\n\n    let segmentPromise: Promise<{\n      encoding: string\n      filename: string\n      mimetype: string\n      segment: BrowserSegment\n    }>\n    let metadataPromise: Promise<BrowserSegmentMetadataAndSegmentSizes>\n\n    const busboy = createBusboy({ headers: req.headers })\n\n    busboy.on('file', (name, stream, info) => {\n      const { filename, encoding, mimeType } = info\n      if (name === 'segment') {\n        segmentPromise = readStream(stream.pipe(createInflate())).then((data) => ({\n          encoding,\n          filename,\n          mimetype: mimeType,\n          segment: JSON.parse(data.toString()),\n        }))\n      } else if (name === 'event') {\n        metadataPromise = readStream(stream).then(\n          (data) => JSON.parse(data.toString()) as BrowserSegmentMetadataAndSegmentSizes\n        )\n      }\n    })\n\n    busboy.on('finish', () => {\n      Promise.all([segmentPromise, metadataPromise])\n        .then(([{ segment, ...segmentFile }, metadata]) => ({\n          ...infos,\n          segmentFile,\n          metadata,\n          segment,\n        }))\n        .then(resolve, reject)\n    })\n\n    req.pipe(busboy)\n  })\n}\n\nfunction readProfileIntakeRequest(\n  req: express.Request,\n  infos: IntakeRequestInfos & { intakeType: 'profile' }\n): Promise<ProfileIntakeRequest> {\n  return new Promise((resolve, reject) => {\n    let eventPromise: Promise<BrowserProfileEvent>\n    let tracePromise: Promise<{\n      trace: BrowserProfilerTrace\n      encoding: string | null\n      filename: string\n      mimetype: string\n    }>\n\n    const busboy = createBusboy({ headers: req.headers })\n\n    busboy.on('file', (name, stream, info) => {\n      const { filename, mimeType } = info\n      if (name === 'event') {\n        eventPromise = readStream(stream).then((data) => JSON.parse(data.toString()) as BrowserProfileEvent)\n      } else if (name === 'wall-time.json') {\n        tracePromise = readStream(stream).then((data) => {\n          let encoding: string | null\n          if (isDeflateEncoded(data)) {\n            encoding = 'deflate'\n            data = inflateSync(data)\n          } else {\n            encoding = null\n          }\n          return {\n            trace: JSON.parse(data.toString()) as BrowserProfilerTrace,\n            encoding,\n            filename,\n            mimetype: mimeType,\n          }\n        })\n      } else {\n        // Skip other attachments\n        stream.resume()\n      }\n    })\n\n    busboy.on('finish', () => {\n      Promise.all([eventPromise, tracePromise])\n        .then(([event, { trace, ...traceFile }]) => ({\n          ...infos,\n          event,\n          trace,\n          traceFile,\n        }))\n        .then(resolve, reject)\n    })\n\n    req.pipe(busboy)\n  })\n}\n\nfunction forwardIntakeRequestToDatadog(req: express.Request): Promise<any> {\n  return new Promise<void>((resolve) => {\n    const ddforward = req.query.ddforward! as string\n    if (!/^\\/api\\/v2\\//.test(ddforward)) {\n      throw new Error(`Unsupported ddforward: ${ddforward}`)\n    }\n    const options = {\n      method: 'POST',\n      headers: {\n        'X-Forwarded-For': req.socket.remoteAddress,\n        'Content-Type': req.headers['content-type'],\n        'User-Agent': req.headers['user-agent'],\n      },\n    }\n    const datadogIntakeRequest = https.request(new URL(ddforward, 'https://browser-intake-datadoghq.com'), options)\n    req.pipe(datadogIntakeRequest)\n    datadogIntakeRequest.on('response', resolve)\n    datadogIntakeRequest.on('error', (error) => {\n      console.log('Error while forwarding request to Datadog:', error)\n      resolve()\n    })\n  })\n}\n\nfunction readStream(stream: NodeJS.ReadableStream): Promise<Buffer> {\n  return new Promise((resolve, reject) => {\n    const buffers: Buffer[] = []\n    stream.on('data', (data: Buffer) => {\n      buffers.push(data)\n    })\n    stream.on('error', (error) => {\n      // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n      reject(error)\n    })\n    stream.on('end', () => {\n      resolve(Buffer.concat(buffers))\n    })\n  })\n}\n\nfunction isDeflateEncoded(buffer: Buffer): boolean {\n  // Check for deflate/zlib magic numbers\n  // 0x78 0x01 - No Compression/low\n  // 0x78 0x9C - Default Compression\n  // 0x78 0xDA - Best Compression\n  return buffer.length >= 2 && buffer[0] === 0x78 && (buffer[1] === 0x01 || buffer[1] === 0x9c || buffer[1] === 0xda)\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/intakeRegistry.ts",
    "content": "import type {\n  RumEvent,\n  RumActionEvent,\n  RumErrorEvent,\n  RumResourceEvent,\n  RumViewEvent,\n  RumVitalEvent,\n  RumLongTaskEvent,\n} from '@datadog/browser-rum'\nimport type {\n  TelemetryEvent,\n  TelemetryErrorEvent,\n  TelemetryConfigurationEvent,\n  TelemetryUsageEvent,\n} from '@datadog/browser-core'\nimport type {\n  IntakeRequest,\n  LogsIntakeRequest,\n  ProfileIntakeRequest,\n  ReplayIntakeRequest,\n  RumIntakeRequest,\n} from './intakeProxyMiddleware'\n\n/**\n * Store data sent to the intake and expose helpers to access it.\n */\nexport class IntakeRegistry {\n  readonly requests: IntakeRequest[] = []\n\n  push(request: IntakeRequest) {\n    this.requests.push(request)\n  }\n\n  get isEmpty() {\n    return this.requests.length === 0\n  }\n\n  empty() {\n    this.requests.length = 0\n  }\n\n  get hasOnlyBridgeRequests() {\n    return this.requests.every((request) => request.isBridge)\n  }\n\n  //\n  // Logs\n  //\n\n  get logsRequests() {\n    return this.requests.filter(isLogsIntakeRequest)\n  }\n\n  get logsEvents() {\n    return this.logsRequests.flatMap((request) => request.events)\n  }\n\n  //\n  // RUM\n  //\n\n  get rumRequests() {\n    return this.requests.filter(isRumIntakeRequest)\n  }\n\n  get rumEvents() {\n    return this.rumRequests.flatMap((request) => request.events.filter(isRumEvent))\n  }\n\n  get rumActionEvents() {\n    return this.rumEvents.filter(isRumActionEvent)\n  }\n\n  get rumErrorEvents() {\n    return this.rumEvents.filter(isRumErrorEvent)\n  }\n\n  get rumResourceEvents() {\n    return this.rumEvents.filter(isRumResourceEvent)\n  }\n\n  get rumLongTaskEvents() {\n    return this.rumEvents.filter(isRumLongTaskEvent)\n  }\n\n  get rumViewEvents() {\n    return this.rumEvents.filter(isRumViewEvent)\n  }\n\n  get rumVitalEvents() {\n    return this.rumEvents.filter(isRumVitalEvent)\n  }\n\n  //\n  // Telemetry\n  //\n\n  get telemetryEvents() {\n    return this.rumRequests.flatMap((request) => request.events.filter(isTelemetryEvent))\n  }\n\n  get telemetryErrorEvents() {\n    return this.telemetryEvents.filter(isTelemetryErrorEvent)\n  }\n\n  get telemetryConfigurationEvents() {\n    return this.telemetryEvents.filter(isTelemetryConfigurationEvent)\n  }\n\n  get telemetryUsageEvents() {\n    return this.telemetryEvents.filter(isTelemetryUsageEvent)\n  }\n\n  //\n  // Replay\n  //\n\n  get replayRequests() {\n    return this.requests.filter(isReplayIntakeRequest)\n  }\n\n  get replaySegments() {\n    return this.replayRequests.map((request) => request.segment)\n  }\n\n  get replayRecords() {\n    return this.replayRequests.flatMap((request) => request.segment.records)\n  }\n\n  //\n  // Profiling\n  //\n\n  get profileRequests() {\n    return this.requests.filter(isProfileIntakeRequest)\n  }\n\n  get profileEvents() {\n    return this.profileRequests.map((request) => request.event)\n  }\n}\n\nfunction isLogsIntakeRequest(request: IntakeRequest): request is LogsIntakeRequest {\n  return request.intakeType === 'logs'\n}\n\nfunction isRumIntakeRequest(request: IntakeRequest): request is RumIntakeRequest {\n  return request.intakeType === 'rum'\n}\n\nfunction isReplayIntakeRequest(request: IntakeRequest): request is ReplayIntakeRequest {\n  return request.intakeType === 'replay'\n}\n\nfunction isProfileIntakeRequest(request: IntakeRequest): request is ProfileIntakeRequest {\n  return request.intakeType === 'profile'\n}\n\nfunction isRumEvent(event: RumEvent | TelemetryEvent): event is RumEvent {\n  return !isTelemetryEvent(event)\n}\n\nfunction isRumResourceEvent(event: RumEvent): event is RumResourceEvent {\n  return event.type === 'resource'\n}\n\nfunction isRumActionEvent(event: RumEvent): event is RumActionEvent {\n  return event.type === 'action'\n}\n\nfunction isRumLongTaskEvent(event: RumEvent): event is RumLongTaskEvent {\n  return event.type === 'long_task'\n}\n\nfunction isRumViewEvent(event: RumEvent): event is RumViewEvent {\n  return event.type === 'view'\n}\n\nfunction isRumErrorEvent(event: RumEvent): event is RumErrorEvent {\n  return event.type === 'error'\n}\n\nfunction isRumVitalEvent(event: RumEvent): event is RumVitalEvent {\n  return event.type === 'vital'\n}\n\nfunction isTelemetryEvent(event: RumEvent | TelemetryEvent): event is TelemetryEvent {\n  return event.type === 'telemetry'\n}\n\nfunction isTelemetryErrorEvent(event: TelemetryEvent): event is TelemetryErrorEvent {\n  return isTelemetryEvent(event) && event.telemetry.status === 'error'\n}\n\nfunction isTelemetryConfigurationEvent(event: TelemetryEvent): event is TelemetryConfigurationEvent {\n  return isTelemetryEvent(event) && event.telemetry.type === 'configuration'\n}\n\nfunction isTelemetryUsageEvent(event: TelemetryEvent): event is TelemetryUsageEvent {\n  return isTelemetryEvent(event) && event.telemetry.type === 'usage'\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/pageSetups.ts",
    "content": "import { generateUUID, INTAKE_URL_PARAMETERS } from '@datadog/browser-core'\nimport type { LogsInitConfiguration } from '@datadog/browser-logs'\nimport type { RumInitConfiguration, RemoteConfiguration } from '@datadog/browser-rum-core'\nimport type test from '@playwright/test'\nimport { isBrowserStack, isContinuousIntegration } from './environment'\nimport type { Servers } from './httpServers'\n\nexport interface SetupOptions {\n  rum?: RumInitConfiguration\n  useRumSlim: boolean\n  logs?: LogsInitConfiguration\n  logsInit: (initConfiguration: LogsInitConfiguration) => void\n  rumInit: (initConfiguration: RumInitConfiguration) => void\n  remoteConfiguration?: RemoteConfiguration\n  eventBridge: boolean\n  head?: string\n  body?: string\n  baseUrlHooks: UrlHook[]\n  context: {\n    run_id: string\n    test_name: string\n  }\n  testFixture: typeof test\n  extension?: {\n    rumConfiguration?: RumInitConfiguration\n    logsConfiguration?: LogsInitConfiguration\n  }\n  worker?: WorkerOptions\n  callerLocation?: CallerLocation\n}\n\nexport interface CallerLocation {\n  file: string\n  line: number\n  column: number\n}\n\nexport interface WorkerOptions {\n  importScripts?: boolean\n  rumConfiguration?: RumInitConfiguration\n  logsConfiguration?: LogsInitConfiguration\n}\n\nexport type SetupFactory = (options: SetupOptions, servers: Servers) => string\nexport type UrlHook = (baseUrl: URL, servers: Servers, options: SetupOptions) => void\n\n// By default, run tests only with the 'bundle' setup outside of the CI (to run faster on the\n// developer laptop) or with Browser Stack (to limit flakiness).\nexport const DEFAULT_SETUPS =\n  !isContinuousIntegration || isBrowserStack\n    ? [{ name: 'bundle', factory: bundleSetup }]\n    : [\n        { name: 'async', factory: asyncSetup },\n        { name: 'npm', factory: npmSetup },\n        { name: 'bundle', factory: bundleSetup },\n      ]\n\nexport function asyncSetup(options: SetupOptions, servers: Servers) {\n  let header = options.head || ''\n  let footer = ''\n\n  if (options.eventBridge) {\n    header += setupEventBridge(servers)\n  }\n\n  if (options.extension) {\n    header += setupExtension(options, servers)\n  }\n\n  function formatSnippet(url: string, globalName: string) {\n    return `(function(h,o,u,n,d) {\nh=h[d]=h[d]||{q:[],onReady:function(c){h.q.push(c)}}\nd=o.createElement(u);d.async=1;d.src=n\nn=o.getElementsByTagName(u)[0];n.parentNode.insertBefore(d,n)\n})(window,document,'script','${url}','${globalName}')`\n  }\n\n  const { logsScriptUrl, rumScriptUrl } = createCrossOriginScriptUrls(servers, options)\n\n  if (options.logs) {\n    footer += html`<script>\n      ${formatSnippet(logsScriptUrl, 'DD_LOGS')}\n      DD_LOGS.onReady(function () {\n        DD_LOGS.setGlobalContext(${JSON.stringify(options.context)})\n        ;(${options.logsInit.toString()})(${formatConfiguration(options.logs, servers)})\n      })\n    </script>`\n  }\n\n  if (options.rum) {\n    footer += html`<script type=\"text/javascript\">\n      ${formatSnippet(rumScriptUrl, 'DD_RUM')}\n      DD_RUM.onReady(function () {\n        DD_RUM.setGlobalContext(${JSON.stringify(options.context)})\n        ;(${options.rumInit.toString()})(${formatConfiguration(options.rum, servers)})\n      })\n    </script>`\n  }\n\n  return basePage({\n    header,\n    body: options.body,\n    footer,\n  })\n}\n\nexport function bundleSetup(options: SetupOptions, servers: Servers) {\n  let header = options.head || ''\n\n  if (options.eventBridge) {\n    header += setupEventBridge(servers)\n  }\n\n  if (options.extension) {\n    header += setupExtension(options, servers)\n  }\n\n  const { logsScriptUrl, rumScriptUrl } = createCrossOriginScriptUrls(servers, options)\n\n  if (options.logs) {\n    header += html`<script type=\"text/javascript\" src=\"${logsScriptUrl}\"></script>`\n    header += html`<script type=\"text/javascript\">\n      DD_LOGS.setGlobalContext(${JSON.stringify(options.context)})\n      ;(${options.logsInit.toString()})(${formatConfiguration(options.logs, servers)})\n    </script>`\n  }\n\n  if (options.rum) {\n    header += html`<script type=\"text/javascript\" src=\"${rumScriptUrl}\"></script>`\n    header += html`<script type=\"text/javascript\">\n      DD_RUM.setGlobalContext(${JSON.stringify(options.context)})\n      ;(${options.rumInit.toString()})(${formatConfiguration(options.rum, servers)})\n    </script>`\n  }\n\n  return basePage({\n    header,\n    body: options.body,\n  })\n}\n\nexport function npmSetup(options: SetupOptions, servers: Servers) {\n  let header = options.head || ''\n\n  if (options.eventBridge) {\n    header += setupEventBridge(servers)\n  }\n\n  if (options.extension) {\n    header += setupExtension(options, servers)\n  }\n\n  if (options.logs) {\n    header += html`<script type=\"text/javascript\">\n      window.LOGS_INIT = () => {\n        window.DD_LOGS.setGlobalContext(${JSON.stringify(options.context)})\n        ;(${options.logsInit.toString()})(${formatConfiguration(options.logs, servers)})\n      }\n    </script>`\n  }\n\n  if (options.rum) {\n    header += html`<script type=\"text/javascript\">\n      window.RUM_INIT = () => {\n        window.DD_RUM.setGlobalContext(${JSON.stringify(options.context)})\n        ;(${options.rumInit.toString()})(${formatConfiguration(options.rum, servers)})\n      }\n    </script>`\n  }\n\n  header += html`<script type=\"text/javascript\" src=\"./app.js\"></script>`\n\n  return basePage({\n    header,\n    body: options.body,\n  })\n}\n\nexport function appSetup(options: SetupOptions, servers: Servers, appName: string) {\n  let header = options.head || ''\n\n  if (options.eventBridge) {\n    header += setupEventBridge(servers)\n  }\n\n  if (options.extension) {\n    header += setupExtension(options, servers)\n  }\n\n  if (options.rum) {\n    header += html`<script type=\"text/javascript\">\n      window.RUM_CONFIGURATION = ${formatConfiguration(options.rum, servers)}\n      window.RUM_CONTEXT = ${JSON.stringify(options.context)}\n    </script>`\n  }\n\n  const footer = html`<script type=\"text/javascript\" src=\"./${appName}.js\"></script>`\n\n  return basePage({\n    header,\n    body: options.body,\n    footer,\n  })\n}\n\nexport function workerSetup(setupOptions: SetupOptions, servers: Servers) {\n  const { worker, context } = setupOptions\n  let setup = ''\n\n  if (worker?.logsConfiguration) {\n    setup += js`\n      ${worker.importScripts ? js`importScripts('/datadog-logs.js');` : js`import '/datadog-logs.js';`}\n      DD_LOGS.init(${formatConfiguration(worker.logsConfiguration, servers)})\n      DD_LOGS.setGlobalContext(${JSON.stringify(context)})\n    `\n  }\n\n  if (worker?.rumConfiguration) {\n    setup += js`\n      ${worker.importScripts ? js`importScripts('/datadog-rum.js');` : js`import '/datadog-rum.js';`}\n      DD_RUM.init(${formatConfiguration(worker.rumConfiguration, servers)})\n      DD_RUM.setGlobalContext(${JSON.stringify(context)})\n    `\n  }\n\n  setup += js`\n    self.addEventListener('message', (event) => {\n      if (event.data.__type === 'evaluate') {\n        new Function(event.data.code)();\n      }\n    });\n  `\n\n  return setup\n}\n\nexport function microfrontendSetup(options: SetupOptions, servers: Servers) {\n  let header = options.head || ''\n\n  if (options.eventBridge) {\n    header += setupEventBridge(servers)\n  }\n\n  if (options.extension) {\n    header += setupExtension(options, servers)\n  }\n\n  const { rumScriptUrl } = createCrossOriginScriptUrls(servers, options)\n\n  if (options.rum) {\n    header += html`<script type=\"text/javascript\" src=\"${rumScriptUrl}\"></script>`\n    header += html`<script type=\"text/javascript\">\n      DD_RUM.setGlobalContext(${JSON.stringify(options.context)})\n      ;(${options.rumInit.toString()})(${formatConfiguration(options.rum, servers)})\n    </script>`\n  }\n\n  header += html`<script type=\"module\" src=\"/microfrontend/shell.js\"></script>`\n\n  return basePage({\n    header,\n    body: options.body,\n  })\n}\n\nfunction basePage({ header, body, footer }: { header?: string; body?: string; footer?: string }) {\n  // prettier-ignore\n  // The empty favicon avoids a /favicon.ico request from the browser.\n  return html`<!doctype html><html><head><link rel=\"icon\" href=\"data:,\"/>${header || ''}</head><body>${body || ''}</body>${footer || ''}</html>`\n}\n\n// html is a simple template string tag to allow prettier to format various setups as HTML\nexport function html(parts: readonly string[], ...vars: string[]) {\n  return parts.reduce((full, part, index) => full + vars[index - 1] + part)\n}\n\nfunction js(parts: readonly string[], ...vars: string[]) {\n  return parts.reduce((full, part, index) => full + vars[index - 1] + part)\n}\n\nfunction setupEventBridge(servers: Servers) {\n  const baseHostname = new URL(servers.base.origin).hostname\n\n  // Send EventBridge events to the intake so we can inspect them in our E2E test cases. The URL\n  // needs to be similar to the normal Datadog intake (through proxy) to make the SDK completely\n  // ignore them.\n  const eventBridgeIntake = `${servers.intake.origin}/?${new URLSearchParams({\n    ddforward: `/api/v2/rum?${INTAKE_URL_PARAMETERS.join('&')}`,\n    bridge: 'true',\n  }).toString()}`\n\n  return html`<script type=\"text/javascript\">\n    window.DatadogEventBridge = {\n      getCapabilities() {\n        return '[\"records\"]'\n      },\n      getPrivacyLevel() {\n        return 'mask'\n      },\n      getAllowedWebViewHosts() {\n        return '[\"${baseHostname}\"]'\n      },\n      send(e) {\n        const { eventType, event } = JSON.parse(e)\n        const request = new XMLHttpRequest()\n        request.open('POST', ${JSON.stringify(eventBridgeIntake)} + '&event_type=' + eventType, true)\n        request.send(JSON.stringify(event))\n      },\n    }\n  </script>`\n}\n\nfunction setupExtension(options: SetupOptions, servers: Servers) {\n  let header = ''\n\n  const { rumScriptUrl, logsScriptUrl } = createCrossOriginScriptUrls(servers, { ...options, useRumSlim: false })\n\n  if (options.extension?.rumConfiguration) {\n    header += html`<script type=\"text/javascript\">\n      window.RUM_BUNDLE_URL = '${rumScriptUrl}'\n      window.RUM_CONTEXT = ${JSON.stringify(options.context)}\n      window.EXT_RUM_CONFIGURATION = ${formatConfiguration(options.extension.rumConfiguration, servers)}\n    </script>`\n  }\n\n  if (options.extension?.logsConfiguration) {\n    header += html`<script type=\"text/javascript\">\n      window.LOGS_BUNDLE_URL = '${logsScriptUrl}'\n      window.LOGS_CONTEXT = ${JSON.stringify(options.context)}\n      window.EXT_LOGS_CONFIGURATION = ${formatConfiguration(options.extension.logsConfiguration, servers)}\n    </script>`\n  }\n\n  return header\n}\n\ntype JsonIncompatibleValue = ((...args: any[]) => any) | RegExp\n\nfunction isJsonIncompatibleValue(value: unknown): value is JsonIncompatibleValue {\n  return typeof value === 'function' || value instanceof RegExp\n}\n\nexport function formatConfiguration(initConfiguration: LogsInitConfiguration | RumInitConfiguration, servers: Servers) {\n  const jsonIncompatibles = new Map<string, JsonIncompatibleValue>()\n\n  let result = JSON.stringify(\n    {\n      ...initConfiguration,\n      proxy: servers.intake.origin,\n      remoteConfigurationProxy: `${servers.base.origin}/config`,\n    },\n    (_key, value) => {\n      if (isJsonIncompatibleValue(value)) {\n        const id = generateUUID()\n        jsonIncompatibles.set(id, value)\n\n        return id\n      }\n\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n      return value\n    }\n  )\n\n  result = result.replace('\"LOCATION_ORIGIN\"', 'location.origin')\n\n  for (const [id, value] of jsonIncompatibles) {\n    result = result.replace(`\"${id}\"`, String(value))\n  }\n\n  return result\n}\n\nexport function createCrossOriginScriptUrls(servers: Servers, options: SetupOptions) {\n  return {\n    logsScriptUrl: `${servers.crossOrigin.origin}/datadog-logs.js`,\n    rumScriptUrl: `${servers.crossOrigin.origin}/${options.useRumSlim ? 'datadog-rum-slim.js' : 'datadog-rum.js'}`,\n  }\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/sdkBuilds.ts",
    "content": "import path from 'path'\n\nconst ROOT = path.join(__dirname, '../../../..')\n\nexport function getSdkBundlePath(packageName: string, originalUrl: string) {\n  return path.join(ROOT, `packages/${packageName}/bundle${originalUrl}`)\n}\n\nexport function getTestAppBundlePath(appName: string, originalUrl: string) {\n  const appNameMapping: Record<string, string> = {\n    app: 'apps/vanilla',\n    'react-router-v6-app': 'apps/react-router-v6-app',\n    'react-router-v7-app': 'apps/react-router-v7-app',\n    'angular-app': 'apps/angular-app',\n    'tanstack-router-app': 'apps/tanstack-router-app',\n    microfrontend: 'apps/microfrontend',\n  }\n\n  const targetAppPath = appNameMapping[appName] || appName\n  return path.join(ROOT, `test/${targetAppPath}/dist${originalUrl}`)\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/serverApps/intake.ts",
    "content": "import express from 'express'\nimport cors from 'cors'\nimport { createIntakeProxyMiddleware } from '../intakeProxyMiddleware.ts'\nimport type { IntakeRegistry } from '../intakeRegistry'\n\nexport function createIntakeServerApp(intakeRegistry: IntakeRegistry) {\n  const app = express()\n\n  app.use(cors())\n\n  app.post('/', createIntakeProxyMiddleware({ onRequest: (request) => intakeRegistry.push(request) }))\n\n  return app\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/serverApps/mock.ts",
    "content": "import type { ServerResponse } from 'http'\nimport * as url from 'url'\nimport cors from 'cors'\nimport qs from 'qs'\nimport express from 'express'\nimport { getSdkBundlePath, getTestAppBundlePath } from '../sdkBuilds'\nimport type { MockServerApp, Servers } from '../httpServers'\nimport { DEV_SERVER_BASE_URL } from '../../helpers/playwright'\nimport type { SetupOptions } from '../pageSetups'\nimport { workerSetup } from '../pageSetups'\n\nexport const LARGE_RESPONSE_MIN_BYTE_SIZE = 100_000\n\nexport function createMockServerApp(servers: Servers, setup: string, setupOptions?: SetupOptions): MockServerApp {\n  const { remoteConfiguration, worker } = setupOptions ?? {}\n  const app = express()\n  let largeResponseBytesWritten = 0\n\n  app.use(cors())\n  app.disable('etag') // disable automatic resource caching\n\n  app.set('query parser', (str: string) => qs.parse(str))\n\n  app.get('/empty', (_req, res) => {\n    res.end()\n  })\n\n  app.get('/favicon.ico', (_req, res) => {\n    res.end()\n  })\n\n  app.get('/throw', (_req, res) => {\n    res.status(500).send('Server error')\n  })\n\n  app.get('/throw-large-response', (_req, res) => {\n    res.status(500)\n\n    const chunkText = 'Server error\\n'.repeat(50)\n    generateLargeResponse(res, chunkText)\n  })\n\n  app.get('/large-response', (_req, res) => {\n    const chunkText = 'foofoobarbar\\n'.repeat(50)\n    generateLargeResponse(res, chunkText)\n  })\n\n  app.get('/sw.js', (_req, res) => {\n    res.contentType('application/javascript').send(\n      workerSetup(\n        {\n          ...setupOptions!,\n          worker: { ...worker, importScripts: Boolean(_req.query.importScripts) },\n        },\n        servers\n      )\n    )\n  })\n\n  function generateLargeResponse(res: ServerResponse, chunkText: string) {\n    let bytesWritten = 0\n    let timeoutId: NodeJS.Timeout\n\n    res.on('close', () => {\n      largeResponseBytesWritten = bytesWritten\n      clearTimeout(timeoutId)\n    })\n\n    function writeMore() {\n      res.write(chunkText, (error) => {\n        if (error) {\n          console.log('Write error', error)\n        } else {\n          bytesWritten += chunkText.length\n          if (bytesWritten < LARGE_RESPONSE_MIN_BYTE_SIZE) {\n            timeoutId = setTimeout(writeMore, 10)\n          } else {\n            res.end()\n          }\n        }\n      })\n    }\n\n    writeMore()\n  }\n\n  app.get('/unknown', (_req, res) => {\n    res.status(404).send('Not found')\n  })\n\n  app.get('/empty.css', (_req, res) => {\n    res.header('content-type', 'text/css').end()\n  })\n\n  app.get('/flush', (_req, res) => {\n    // The RUM session replay recorder uses a Web Worker to format request data, so it cannot send\n    // its last segment during the \"beforeunload\" event — only a few milliseconds after. If the next\n    // page loads too quickly, the segment may be lost. /flush responds after 200ms to give the\n    // recorder time to send, and returns HTML with an empty favicon to avoid a spurious favicon request.\n    setTimeout(() => res.send('<!doctype html><html><head><link rel=\"icon\" href=\"data:,\"/></head></html>'), 200)\n  })\n\n  app.all('/ok', (req, res) => {\n    // Express will automatically append charset to the Content-Type header\n    res.header('Content-Type', 'text/plain')\n    if (req.query['timing-allow-origin'] === 'true') {\n      res.set('Timing-Allow-Origin', '*')\n    }\n\n    const responseHeaders = req.query['response-headers']\n    if (responseHeaders) {\n      for (const [header, value] of Object.entries(responseHeaders)) {\n        if (typeof value === 'string') {\n          res.header(header, value)\n        }\n      }\n    }\n\n    const timeoutDuration = req.query.duration ? Number(req.query.duration) : 0\n\n    setTimeout(() => res.send('ok'), timeoutDuration)\n  })\n\n  app.post('/graphql', (req, res) => {\n    res.header('Content-Type', 'application/json')\n\n    const scenario = req.query.scenario as string | undefined\n\n    if (scenario === 'validation-error') {\n      res.json({\n        data: null,\n        errors: [\n          {\n            message: 'Field \"unknownField\" does not exist',\n            extensions: { code: 'GRAPHQL_VALIDATION_FAILED' },\n            locations: [{ line: 2, column: 5 }],\n            path: ['user', 'unknownField'],\n          },\n        ],\n      })\n    } else if (scenario === 'multiple-errors') {\n      res.json({\n        data: { user: null },\n        errors: [\n          { message: 'User not found' },\n          { message: 'Insufficient permissions', extensions: { code: 'UNAUTHORIZED' } },\n        ],\n      })\n    } else {\n      res.json({ data: { result: 'success' } })\n    }\n  })\n\n  app.get('/graphql', (_req, res) => {\n    res.header('Content-Type', 'application/json')\n    res.json({ data: { result: 'success' } })\n  })\n\n  app.get('/redirect', (req, res) => {\n    const redirectUri = url.parse(req.originalUrl)\n    res.redirect(`ok${redirectUri.search!}`)\n  })\n\n  app.get('/headers', (req, res) => {\n    res.send(JSON.stringify(req.headers))\n  })\n\n  app.get('/', (req, res) => {\n    res.header(\n      'Content-Security-Policy',\n      [\n        `connect-src ${servers.intake.origin} ${servers.base.origin} ${servers.crossOrigin.origin}`,\n        `script-src 'self' 'unsafe-inline' ${servers.crossOrigin.origin}`,\n        \"worker-src blob: 'self'\",\n      ].join(';')\n    )\n    if (req.query['js-profiling'] === 'true') {\n      res.header('Document-Policy', 'js-profiling')\n    }\n    res.send(setup)\n    res.end()\n  })\n\n  app.get('/no-blob-worker-csp', (_req, res) => {\n    res.header(\n      'Content-Security-Policy',\n      [\n        `connect-src ${servers.intake.origin} ${servers.base.origin} ${servers.crossOrigin.origin}`,\n        `script-src 'self' 'unsafe-inline' ${servers.crossOrigin.origin}`,\n      ].join(';')\n    )\n    res.send(setup)\n    res.end()\n  })\n\n  app.get(/datadog-(?<packageName>[a-z-]*)\\.js/, (req, res) => {\n    const { originalUrl, params } = req\n\n    if (process.env.CI) {\n      res.sendFile(getSdkBundlePath(params.packageName, originalUrl))\n    } else {\n      forwardToDevServer(req.originalUrl, res)\n    }\n  })\n\n  app.get('/worker.js', (req, res) => {\n    if (process.env.CI) {\n      res.sendFile(getSdkBundlePath('worker', req.originalUrl))\n    } else {\n      forwardToDevServer(req.originalUrl, res)\n    }\n  })\n\n  app.get(/(?<appName>app|react-[\\w-]+|angular-[\\w-]+|tanstack-[\\w-]+).js$/, (req, res) => {\n    const { originalUrl, params } = req\n    res.sendFile(getTestAppBundlePath(params.appName, originalUrl))\n  })\n\n  app.get(/^\\/microfrontend\\/.*/, (req, res) => {\n    const { originalUrl } = req\n    // Remove the /microfrontend prefix from the URL since getTestAppBundlePath adds the app path\n    const filePath = originalUrl.replace(/^\\/microfrontend/, '')\n    res.sendFile(getTestAppBundlePath('microfrontend', filePath))\n  })\n\n  app.get('/config', (_req, res) => {\n    res.send(JSON.stringify(remoteConfiguration))\n  })\n\n  return Object.assign(app, {\n    getLargeResponseWroteSize() {\n      return largeResponseBytesWritten\n    },\n  })\n}\n\n// We fetch and pipe the file content instead of redirecting to avoid creating different behavior between CI and local dev\n// This way both environments serve the files from the same origin with the same CSP rules\nfunction forwardToDevServer(originalUrl: string, res: ServerResponse) {\n  const url = `${DEV_SERVER_BASE_URL}${originalUrl}`\n\n  fetch(url)\n    .then(({ body, headers }) => {\n      void body?.pipeTo(\n        new WritableStream({\n          start() {\n            headers.forEach((value, key) => res.setHeader(key, value))\n          },\n          write(chunk) {\n            res.write(chunk)\n          },\n          close() {\n            res.end()\n          },\n        })\n      )\n    })\n    .catch(() => console.error(`Error fetching ${url}, did you run 'yarn dev'?`))\n}\n"
  },
  {
    "path": "test/e2e/lib/framework/waitForRequests.ts",
    "content": "import type { Page } from '@playwright/test'\nimport { waitForServersIdle } from './httpServers'\n\n/**\n * Wait for browser requests to be sent and finished.\n *\n * Due to latency, a request (fetch, xhr, sendBeacon...) started inside a `browser.execute(...)`\n * callback might *not* have reached the local server when `browser.execute` finishes. Thus, calling\n * `waitForServersIdle()` directly might be flaky, because no request might be pending yet.\n *\n * As a workaround, this function delays the `waitForServersIdle()` call by doing a browser\n * roundtrip, ensuring requests have plenty of time to reach the local server.\n */\nexport async function waitForRequests(page: Page) {\n  await page.evaluate(\n    () =>\n      new Promise((resolve) => {\n        setTimeout(() => {\n          resolve(undefined)\n        }, 200)\n      })\n  )\n  await waitForServersIdle()\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/browser.ts",
    "content": "import type {\n  BrowserContext,\n  Page,\n  PlaywrightTestArgs,\n  PlaywrightTestOptions,\n  PlaywrightWorkerArgs,\n  PlaywrightWorkerOptions,\n  TestType,\n} from '@playwright/test'\nimport type { BrowserConfiguration } from '../../../browsers.conf'\nimport { addTag } from './tags'\n\nexport function getBrowserName(name: string) {\n  const lowerCaseName = name.toLowerCase()\n\n  if (lowerCaseName.includes('firefox')) {\n    return 'firefox'\n  }\n\n  if (lowerCaseName.includes('edge')) {\n    return 'msedge'\n  }\n\n  if (lowerCaseName.includes('webkit')) {\n    return 'webkit'\n  }\n\n  return 'chromium'\n}\n\nexport interface BrowserLog {\n  level: 'log' | 'debug' | 'info' | 'error' | 'warning'\n  message: string\n  source: string\n  timestamp: number\n}\n\nconst IGNORE_LOG_MESSAGES = ['Ignoring unsupported entryTypes:', 'Layout was forced before the page was fully loaded.']\n\nexport class BrowserLogsManager {\n  private logs: BrowserLog[] = []\n\n  add(log: BrowserLog) {\n    this.logs.push(log)\n  }\n\n  get() {\n    return this.logs.filter((log) => {\n      const ignoredMessage = IGNORE_LOG_MESSAGES.find((message) => log.message.includes(message))\n      if (ignoredMessage) {\n        addTag('test.fixme', `Unexpected Console log message: \"${ignoredMessage}\"`)\n        return false\n      }\n\n      return true\n    })\n  }\n\n  clear() {\n    this.logs = []\n  }\n}\n\nexport function deleteAllCookies(context: BrowserContext) {\n  return context.clearCookies()\n}\n\nexport function setCookie(page: Page, name: string, value: string, expiresDelay: number = 0) {\n  return page.evaluate(\n    ({ name, value, expiresDelay }: { name: string; value: string; expiresDelay: number }) => {\n      const expires = new Date(Date.now() + expiresDelay).toUTCString()\n\n      document.cookie = `${name}=${value};expires=${expires};`\n    },\n    { name, value, expiresDelay }\n  )\n}\n\nexport async function sendXhr(page: Page, url: string, headers: string[][] = []): Promise<string> {\n  type State = { state: 'success'; response: string } | { state: 'error' }\n\n  const result: State = await page.evaluate(\n    ([url, headers]) =>\n      new Promise((resolve) => {\n        const xhr = new XMLHttpRequest()\n        let state: State = { state: 'error' }\n        xhr.addEventListener('load', () => {\n          state = { state: 'success', response: xhr.response as string }\n        })\n        xhr.addEventListener('loadend', () => resolve(state))\n        xhr.open('GET', url)\n        headers.forEach((header) => xhr.setRequestHeader(header[0], header[1]))\n        xhr.send()\n      }),\n    [url, headers] as const\n  )\n\n  if (result.state === 'error') {\n    throw new Error(`sendXhr: request to ${url} failed`)\n  }\n  return result.response\n}\n\nexport function isContentTypeAvailableInPerformanceEntry(\n  test: TestType<PlaywrightTestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs & PlaywrightWorkerOptions>,\n  browserName: ReturnType<typeof getBrowserName>\n) {\n  const browserVersion = (test.info().project.metadata as BrowserConfiguration).version\n\n  // Currently our CI only runs Firefox 119, so this test only runs locally with yarn test:e2e --project=firefox\n  return browserName === 'firefox' && Number(browserVersion) >= 129\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/configuration.ts",
    "content": "import { DefaultPrivacyLevel } from '@datadog/browser-core'\n\nexport const APPLICATION_ID = '37fe52bf-b3d5-4ac7-ad9b-44882d479ec8'\nexport const CLIENT_TOKEN = 'pubf2099de38f9c85797d20d64c7d632a69'\n\nexport const DEFAULT_RUM_CONFIGURATION = {\n  applicationId: APPLICATION_ID,\n  clientToken: CLIENT_TOKEN,\n  defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n  trackResources: true,\n  trackLongTasks: true,\n  enableExperimentalFeatures: [],\n  allowUntrustedEvents: true,\n  // Force All sample rates to 100% to avoid flakiness\n  sessionReplaySampleRate: 100,\n  telemetrySampleRate: 100,\n  telemetryUsageSampleRate: 100,\n  telemetryConfigurationSampleRate: 100,\n}\n\nexport const DEFAULT_LOGS_CONFIGURATION = {\n  clientToken: CLIENT_TOKEN,\n  // Force All sample rates to 100% to avoid flakiness\n  telemetrySampleRate: 100,\n  telemetryUsageSampleRate: 100,\n  telemetryConfigurationSampleRate: 100,\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/extensionFixture.ts",
    "content": "import { test as base, chromium } from '@playwright/test'\nimport type { BrowserContext } from '@playwright/test'\n\nexport interface ExtensionFixture {\n  context: BrowserContext\n  extensionId: string\n}\n\nexport function createExtensionTest(extensionPath: string) {\n  return base.extend<ExtensionFixture>({\n    // eslint-disable-next-line no-empty-pattern\n    context: async ({}, use, testInfo) => {\n      testInfo.skip(testInfo.project.name !== 'chromium', 'Extension tests only run in Chromium')\n\n      const context = await chromium.launchPersistentContext('', {\n        channel: 'chromium',\n        args: [`--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}`],\n      })\n      await use(context)\n      await context.close()\n    },\n  })\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/playwright.ts",
    "content": "import type { PlaywrightWorkerOptions } from '@playwright/test'\nimport type { BrowserConfiguration } from '../../../browsers.conf'\nimport { getBuildInfos } from '../../../envUtils.ts'\nimport packageJson from '../../../../package.json' with { type: 'json' }\n\nexport const DEV_SERVER_BASE_URL = `http://localhost:${process.env.DEV_SERVER_PORT}`\nexport const NEXTJS_APP_ROUTER_PORT = process.env.NEXTJS_APP_ROUTER_PORT!\nexport const VUE_ROUTER_APP_PORT = process.env.VUE_ROUTER_APP_PORT!\nexport const NUXT_APP_PORT = process.env.NUXT_APP_PORT!\n\nexport function getPlaywrightConfigBrowserName(name: string): PlaywrightWorkerOptions['browserName'] {\n  if (name.includes('firefox')) {\n    return 'firefox'\n  }\n\n  if (name.includes('webkit')) {\n    return 'webkit'\n  }\n\n  return 'chromium'\n}\n\nexport function getEncodedCapabilities(configuration: BrowserConfiguration) {\n  return encodeURIComponent(JSON.stringify(getCapabilities(configuration)))\n}\n\n// see: https://www.browserstack.com/docs/automate/playwright/playwright-capabilities\nfunction getCapabilities(configuration: BrowserConfiguration) {\n  const playwrightVersion = resolvePlaywrightVersionFromPackageJson()\n  return {\n    os: configuration.os,\n    os_version: configuration.osVersion,\n    browser: configuration.name,\n    browser_version: configuration.version,\n    'browserstack.username': process.env.BS_USERNAME,\n    'browserstack.accessKey': process.env.BS_ACCESS_KEY,\n    project: 'browser sdk e2e',\n    build: getBuildInfos(),\n    name: configuration.sessionName,\n    'browserstack.local': true,\n    'browserstack.playwrightVersion': playwrightVersion,\n    'client.playwrightVersion': playwrightVersion,\n    'browserstack.debug': false,\n    'browserstack.console': 'info',\n    'browserstack.networkLogs': false,\n    'browserstack.interactiveDebugging': false,\n  }\n}\n\nfunction resolvePlaywrightVersionFromPackageJson(): string {\n  const rootPkg = packageJson as unknown as {\n    devDependencies?: Record<string, string>\n    dependencies?: Record<string, string>\n  }\n  const version = rootPkg.devDependencies?.['@playwright/test'] || rootPkg.dependencies?.['@playwright/test']\n  if (!version) {\n    throw new Error('Unable to resolve @playwright/test version from package.json')\n  }\n  return version\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/session.ts",
    "content": "import { SESSION_STORE_KEY, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core'\nimport type { SessionState } from '@datadog/browser-core'\nimport type { BrowserContext, Page } from '@playwright/test'\nimport { expect } from '@playwright/test'\n\nimport { setCookie } from './browser'\n\nexport async function renewSession(page: Page, browserContext: BrowserContext) {\n  await expireSession(page, browserContext)\n  const documentElement = page.locator('html')\n  await documentElement.click()\n\n  expect((await findSessionCookie(browserContext))?.isExpired).not.toEqual('1')\n}\n\nexport async function expireSession(page: Page, browserContext: BrowserContext) {\n  // mock expire session with anonymous id\n  const cookies = await browserContext.cookies()\n  const anonymousId = cookies[0]?.value.match(/aid=[a-z0-9-]+/)\n  const expireCookie = `isExpired=1&${anonymousId && anonymousId[0]}`\n\n  await setCookie(page, SESSION_STORE_KEY, expireCookie, SESSION_TIME_OUT_DELAY)\n\n  expect((await findSessionCookie(browserContext))?.isExpired).toEqual('1')\n\n  // Cookies are cached for 1s, wait until the cache expires\n  await page.waitForTimeout(1100)\n}\n\nexport async function findSessionCookie(browserContext: BrowserContext) {\n  const cookies = await browserContext.cookies()\n  // In some case, the session cookie is returned but with an empty value. Let's consider it expired\n  // in this case.\n  const rawValue = cookies[0]?.value\n  if (!rawValue) {\n    return\n  }\n  return Object.fromEntries(rawValue.split('&').map((part: string) => part.split('='))) as SessionState\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/tags.ts",
    "content": "import { test } from '@playwright/test'\nimport type { BrowserConfiguration } from '../../../browsers.conf'\n\nexport function addTag(tag: string, value: string) {\n  test.info().annotations.push({\n    type: `dd_tags[${tag}]`,\n    description: value,\n  })\n}\n\n// Add test configuration tags used for test optimization features\n// https://docs.datadoghq.com/tests/#test-configuration-attributes\nexport function addTestOptimizationTags(metadata: BrowserConfiguration | Record<any, never>) {\n  // eslint-disable-next-line prefer-const\n  for (let [tag, value] of Object.entries(metadata)) {\n    switch (tag) {\n      case 'name':\n        tag = 'runtime.name'\n        break\n      case 'version':\n        tag = 'runtime.version'\n        break\n      case 'os':\n        tag = 'os.platform'\n        break\n      case 'osVersion':\n        tag = 'os.version'\n        break\n      case 'device':\n        tag = 'device.name'\n        break\n      default:\n        // Note: Nested test.configuration tags, such as test.configuration.cpu.memory, are not supported.\n        tag = `test.configuration.${tag}`\n    }\n\n    addTag(tag, value)\n  }\n}\n"
  },
  {
    "path": "test/e2e/lib/helpers/validation.ts",
    "content": "import fs from 'fs'\nimport type { RumEvent } from '@datadog/browser-rum'\nimport ajv from 'ajv'\n\nexport function validateRumFormat(events: RumEvent[]) {\n  const instance = new ajv({\n    allErrors: true,\n  })\n  const allJsonSchemas = fs\n    .globSync('./rum-events-format/schemas/**/*.json')\n    .map((path) => JSON.parse(fs.readFileSync(path, 'utf8')) as object)\n  instance.addSchema(allJsonSchemas)\n\n  events.forEach((rumEvent) => {\n    void instance.validate('rum-events-schema.json', rumEvent)\n\n    if (instance.errors) {\n      const formattedError = instance.errors.map((error) => {\n        let allowedValues: string[] | string | undefined\n        switch (error.keyword) {\n          case 'enum':\n            allowedValues = error.params?.allowedValues as string[]\n            break\n          case 'const':\n            allowedValues = error.params?.allowedValue as string\n            break\n        }\n\n        return `event/${error.instancePath || ''} ${error.message!} ${allowedValues ? formatAllowedValues(allowedValues) : ''}`\n      })\n\n      throw new InvalidRumEventError(formattedError.join('\\n'))\n    }\n  })\n}\n\nclass InvalidRumEventError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = 'InvalidRumEventError'\n  }\n}\n\nfunction formatAllowedValues(allowedValues: string[] | string) {\n  if (!Array.isArray(allowedValues)) {\n    return `'${allowedValues}'`\n  }\n\n  return `('${allowedValues.join(\"', '\")}')`\n}\n"
  },
  {
    "path": "test/e2e/lib/types/global.ts",
    "content": "import type { LogsGlobal } from '@datadog/browser-logs'\nimport type { RumGlobal } from '@datadog/browser-rum'\n\ndeclare global {\n  interface Window {\n    DD_LOGS?: LogsGlobal\n    DD_RUM?: RumGlobal\n    DD_SOURCE_CODE_CONTEXT?: { [stack: string]: { service: string; version?: string } }\n  }\n}\n"
  },
  {
    "path": "test/e2e/noticeReporter.ts",
    "content": "import type { Reporter } from '@playwright/test/reporter'\nimport { getRunId } from '../envUtils'\nimport { APPLICATION_ID } from './lib/helpers/configuration'\n\n// eslint-disable-next-line import/no-default-export\nexport default class NoticeReporter implements Reporter {\n  onBegin() {\n    console.log(\n      `[RUM events] https://app.datadoghq.com/rum/explorer?query=${encodeURIComponent(\n        `@application.id:${APPLICATION_ID} @context.run_id:\"${getRunId()}\"`\n      )}`\n    )\n    console.log(`[Log events] https://app.datadoghq.com/logs?query=${encodeURIComponent(`@run_id:\"${getRunId()}\"`)}\\n`)\n  }\n}\n"
  },
  {
    "path": "test/e2e/package.json",
    "content": "{\n  \"name\": \"test-e2e\",\n  \"private\": true\n}\n"
  },
  {
    "path": "test/e2e/playwright.base.config.ts",
    "content": "import path from 'path'\nimport type { ReporterDescription, Config } from '@playwright/test'\nimport { getTestReportDirectory } from '../envUtils'\n\nconst isCi = !!process.env.CI\nconst isLocal = !isCi\n\nconst testReportDirectory = getTestReportDirectory()\nconst reporters: ReporterDescription[] = [['line'], ['./noticeReporter.ts']]\n\nif (testReportDirectory) {\n  reporters.push(['junit', { outputFile: path.join(process.cwd(), testReportDirectory, 'results.xml') }])\n} else {\n  reporters.push(['html'])\n}\n\n/**\n * See https://playwright.dev/docs/test-configuration.\n */\nexport const config: Config = {\n  testDir: './scenario',\n  testMatch: ['**/*.scenario.ts'],\n  tsconfig: './tsconfig.json',\n  fullyParallel: true,\n  forbidOnly: isCi,\n  maxFailures: isCi ? 1 : 0,\n  retries: isCi ? 2 : 0,\n  workers: 5,\n  reporter: reporters,\n  use: {\n    trace: isCi ? 'off' : 'retain-on-failure',\n  },\n\n  webServer: [\n    ...(isLocal\n      ? [\n          {\n            name: 'dev server',\n            stdout: 'pipe' as const,\n            cwd: path.join(__dirname, '../..'),\n            command: 'yarn dev-server start --no-daemon',\n            wait: {\n              stdout: /Dev server listening on port (?<dev_server_port>\\d+)/,\n            },\n          },\n        ]\n      : []),\n    {\n      name: 'nextjs app router',\n      stdout: 'pipe' as const,\n      cwd: path.join(__dirname, '../apps/nextjs'),\n      command: 'yarn start',\n      wait: {\n        stdout: /- Local:\\s+http:\\/\\/localhost:(?<nextjs_app_router_port>\\d+)/,\n      },\n    },\n    {\n      name: 'vue router app',\n      stdout: 'pipe' as const,\n      cwd: path.join(__dirname, '../apps/vue-router-app'),\n      command: isLocal ? 'yarn dev' : 'yarn preview',\n      // NO_COLOR=1 prevents Vite from wrapping \"Local\" in ANSI bold codes when\n      // FORCE_COLOR=1 is set in CI, which would break the wait.stdout regex.\n      env: { NO_COLOR: '1' },\n      wait: {\n        stdout: /Local:\\s+http:\\/\\/localhost:(?<vue_router_app_port>\\d+)/,\n      },\n    },\n    {\n      name: 'nuxt app',\n      stdout: 'pipe' as const,\n      cwd: path.join(__dirname, '../apps/nuxt-app'),\n      command: isLocal ? 'yarn dev' : 'yarn start',\n      env: { NO_COLOR: '1' },\n      wait: {\n        // yarn dev logs:   \"➜ Local:  http://localhost:PORT\"\n        // yarn start logs: \"Listening on http://[::]:PORT\"\n        stdout: /(?:Local:\\s+http:\\/\\/localhost|Listening on http:\\/\\/(?:\\[[^\\]]+\\]|[^:]+)):(?<nuxt_app_port>\\d+)/,\n      },\n    },\n  ],\n}\n"
  },
  {
    "path": "test/e2e/playwright.bs.config.ts",
    "content": "import { defineConfig } from '@playwright/test'\nimport { getPlaywrightConfigBrowserName, getEncodedCapabilities } from './lib/helpers/playwright'\nimport { config as baseConfig } from './playwright.base.config'\nimport { browserConfigurations } from './browsers.conf'\n\n// eslint-disable-next-line import/no-default-export\nexport default defineConfig({\n  ...baseConfig,\n  workers: 5, // BrowserStack has a limit of 5 parallel sessions\n  testIgnore: ['**/developerExtension.scenario.ts', '**/s8sInject.scenario.ts'], // These test won't run in the BrowserStack\n  projects: browserConfigurations.map((configuration) => ({\n    name: configuration.sessionName,\n    metadata: configuration,\n    use: {\n      browserName: getPlaywrightConfigBrowserName(configuration.name),\n      connectOptions: {\n        wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${getEncodedCapabilities(configuration)}`,\n      },\n    },\n  })),\n})\n"
  },
  {
    "path": "test/e2e/playwright.local.config.ts",
    "content": "import { defineConfig, devices } from '@playwright/test'\nimport { config as baseConfig } from './playwright.base.config'\n\n// eslint-disable-next-line import/no-default-export\nexport default defineConfig({\n  ...baseConfig,\n  projects: [\n    getConfig('chromium', 'Desktop Chrome'),\n    getConfig('firefox', 'Desktop Firefox'),\n    getConfig('webkit', 'Desktop Safari'),\n    getConfig('android', 'Pixel 7'),\n  ],\n})\n\nfunction getConfig(browser: string, device: string) {\n  return {\n    name: browser,\n    metadata: {\n      sessionName: device,\n      name: browser,\n    },\n    use: devices[device],\n  }\n}\n"
  },
  {
    "path": "test/e2e/scenario/browser-extensions/browserExtensions.scenario.ts",
    "content": "import path from 'path'\nimport { test, expect } from '@playwright/test'\nimport type { BrowserLog } from '../../lib/framework'\nimport { createTest, createExtension, createCrossOriginScriptUrls, formatConfiguration } from '../../lib/framework'\n\nconst ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN =\n  'Datadog Browser SDK: Running the Browser SDK in a Web extension content script is forbidden unless the `allowedTrackingOrigins` option is provided.'\nconst ERROR_MESSAGE = 'Datadog Browser SDK: SDK initialized on a non-allowed domain.'\n\nconst BASE_PATH = path.join(process.cwd(), 'test/apps')\nconst EXTENSIONS = ['base-extension', 'cdn-extension']\n\n// NOTE: logs might contain a warning about the SDK being loaded twice when using the npm config\n// because the SDK is loaded even though it's not initialized.\n// We ignore it here because it's not relevant to the test.\nconst isNotSdkLoadedMoreThanOnce = (log: BrowserLog) => !log.message.includes('SDK is loaded more than once')\n\ntest.describe('browser extensions', () => {\n  for (const name of EXTENSIONS) {\n    test.describe(`with ${name} extension`, () => {\n      createTest('should not start tracking and log an error when SDK is initialized in an unsupported environment')\n        .withExtension(createExtension(path.join(BASE_PATH, name)).withRum().withLogs())\n        .run(async ({ withBrowserLogs, flushEvents, intakeRegistry }) => {\n          await flushEvents()\n\n          expect(intakeRegistry.rumViewEvents).toHaveLength(0)\n\n          withBrowserLogs((logs) => {\n            const filteredLogs = logs.filter(isNotSdkLoadedMoreThanOnce)\n\n            // Two errors, one for RUM and one for LOGS SDK\n            expect(filteredLogs).toHaveLength(2)\n            filteredLogs.forEach((log) => {\n              expect(log).toMatchObject({\n                level: 'error',\n                message: ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN,\n              })\n            })\n          })\n        })\n\n      createTest('should start tracking when allowedTrackingOrigins matches current domain')\n        .withExtension(\n          createExtension(path.join(BASE_PATH, name))\n            .withRum({ allowedTrackingOrigins: ['LOCATION_ORIGIN'] })\n            .withLogs({ allowedTrackingOrigins: ['LOCATION_ORIGIN'] })\n        )\n        .run(async ({ withBrowserLogs, flushEvents, intakeRegistry }) => {\n          await flushEvents()\n\n          expect(intakeRegistry.rumViewEvents).toHaveLength(1)\n\n          withBrowserLogs((logs) =>\n            expect(logs).not.toContainEqual(\n              expect.objectContaining({\n                level: 'error',\n                message: ERROR_DOES_NOT_HAVE_ALLOWED_TRACKING_ORIGIN,\n              })\n            )\n          )\n        })\n\n      createTest('should not start tracking when allowedTrackingOrigins does not match current domain')\n        .withExtension(\n          createExtension(path.join(BASE_PATH, name))\n            .withRum({ allowedTrackingOrigins: ['https://app.example.com'] })\n            .withLogs({ allowedTrackingOrigins: ['https://app.example.com'] })\n        )\n        .run(async ({ withBrowserLogs, flushEvents, intakeRegistry }) => {\n          await flushEvents()\n\n          expect(intakeRegistry.rumViewEvents).toHaveLength(0)\n\n          withBrowserLogs((logs) => {\n            const filteredLogs = logs.filter(isNotSdkLoadedMoreThanOnce)\n            // Two errors, one for RUM and one for LOGS SDK\n            expect(filteredLogs).toHaveLength(2)\n            filteredLogs.forEach((log) => {\n              expect(log).toMatchObject({\n                level: 'error',\n                message: ERROR_MESSAGE,\n              })\n            })\n          })\n        })\n    })\n  }\n\n  /**\n   * This test is reconstruction of an edge case that happens when using some extension that override `appendChild` and\n   * the sync installation method using NextJs `<Script>` component.\n   */\n  createTest('should not warn - edge case simulating NextJs with an extension that override `appendChild`')\n    .withExtension(createExtension(path.join(BASE_PATH, 'appendChild-extension')))\n    .withRum()\n    .withLogs()\n    .withSetup((options, servers) => {\n      const { rumScriptUrl, logsScriptUrl } = createCrossOriginScriptUrls(servers, options)\n      return `\n          <script src=\"${rumScriptUrl}\"></script>\n          <script src=\"${logsScriptUrl}\"></script>\n          <script>\n            const script = document.createElement('script')\n            script.innerHTML = 'window.DD_RUM.init(${formatConfiguration(options.rum!, servers)}); window.DD_LOGS.init(${formatConfiguration(options.logs!, servers)})'\n            document.head.appendChild(script)\n          </script>\n        `\n    })\n    .run(async ({ withBrowserLogs, flushEvents, intakeRegistry }) => {\n      await flushEvents()\n\n      expect(intakeRegistry.rumViewEvents).toHaveLength(1)\n\n      withBrowserLogs((logs) => expect(logs.length).toBe(0))\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/context.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../lib/framework'\n\ntest.describe('user, account and global context', () => {\n  createTest('should be included in all rum events')\n    .withRum()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.setUser({ id: '123', name: 'user' })\n      window.DD_RUM!.setAccount({ id: '123', name: 'account' })\n      window.DD_RUM!.setGlobalContext({ foo: 'bar' })\n\n      window.DD_RUM!.init(configuration)\n      window.DD_RUM!.addAction('foo')\n      window.DD_RUM!.addDurationVital('foo', {\n        startTime: Date.now(),\n        duration: 100,\n      })\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      const events = intakeRegistry.rumEvents\n      expect(events.length).toBeGreaterThan(0)\n\n      events.forEach((event) => {\n        expect(event.usr).toEqual({ id: '123', name: 'user', anonymous_id: expect.any(String) })\n        expect(event.account).toEqual({ id: '123', name: 'account' })\n        expect(event.context).toEqual({ foo: 'bar' })\n      })\n    })\n\n  createTest('should be included in all logs')\n    .withLogs()\n    .withLogsInit((configuration) => {\n      window.DD_LOGS!.setUser({ id: '123', name: 'user' })\n      window.DD_LOGS!.setAccount({ id: '123', name: 'account' })\n      window.DD_LOGS!.setGlobalContext({ foo: 'bar' })\n\n      window.DD_LOGS!.init(configuration)\n      window.DD_LOGS!.logger.log('hello')\n      console.log('hello')\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      const logs = intakeRegistry.logsEvents\n      expect(logs.length).toBeGreaterThan(0)\n\n      logs.forEach((event) => {\n        expect(event.usr).toEqual({ id: '123', name: 'user', anonymous_id: expect.any(String) })\n        expect(event.account).toEqual({ id: '123', name: 'account' })\n        expect(event.foo).toEqual('bar')\n      })\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/developer-extension/developerExtension.scenario.ts",
    "content": "import path from 'path'\nimport { expect, test } from '@playwright/test'\nimport { createExtension, createTest } from '../../lib/framework'\n\nconst developerExtensionPath = path.join(process.cwd(), 'developer-extension/dist/chrome-mv3')\n\ntest.describe('developer extension', () => {\n  createTest('should switch between tabs')\n    .withExtension(createExtension(developerExtensionPath))\n    .run(async ({ page, getExtensionId, flushBrowserLogs }) => {\n      const extensionId = await getExtensionId()\n\n      await page.goto(`chrome-extension://${extensionId}/panel.html`)\n\n      const getSelectedTab = () => page.getByRole('tab', { selected: true })\n      const getTab = (name: string) => page.getByRole('tab', { name })\n\n      expect(await getSelectedTab().innerText()).toEqual('Events')\n\n      await getTab('Infos').click()\n      expect(await getSelectedTab().innerText()).toEqual('Infos')\n\n      flushBrowserLogs()\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/eventBridge.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest, html } from '../lib/framework'\n\ntest.describe('bridge present', () => {\n  createTest('send action')\n    .withRum({ trackUserInteractions: true })\n    .withEventBridge()\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          button.setAttribute('data-clicked', 'true')\n        })\n      </script>\n    `)\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      // wait for click chain to close\n      await page.waitForTimeout(1000)\n      await flushEvents()\n\n      expect(intakeRegistry.rumActionEvents).toHaveLength(1)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n    })\n\n  createTest('send error')\n    .withRum()\n    .withEventBridge()\n    .run(async ({ flushBrowserLogs, flushEvents, intakeRegistry, page }) => {\n      await page.evaluate(() => {\n        console.error('oh snap')\n      })\n\n      flushBrowserLogs()\n      await flushEvents()\n\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n    })\n\n  createTest('send resource')\n    .withRum()\n    .withEventBridge()\n    .run(async ({ flushEvents, intakeRegistry }) => {\n      await flushEvents()\n\n      expect(intakeRegistry.rumResourceEvents.length).toBeGreaterThan(0)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n    })\n\n  createTest('send view')\n    .withRum()\n    .withEventBridge()\n    .run(async ({ flushEvents, intakeRegistry }) => {\n      await flushEvents()\n\n      expect(intakeRegistry.rumViewEvents.length).toBeGreaterThan(0)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n    })\n\n  createTest('forward telemetry to the bridge')\n    .withLogs()\n    .withEventBridge()\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      await page.evaluate(() => {\n        const context = {\n          get foo() {\n            throw new window.Error('bar')\n          },\n        }\n        window.DD_LOGS!.logger.log('hop', context as any)\n      })\n\n      await flushEvents()\n      expect(intakeRegistry.telemetryErrorEvents).toHaveLength(1)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n      intakeRegistry.empty()\n    })\n\n  createTest('forward logs to the bridge')\n    .withLogs()\n    .withEventBridge()\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.log('hello')\n      })\n      await flushEvents()\n\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n    })\n\n  createTest('send records to the bridge')\n    .withRum()\n    .withEventBridge()\n    .run(async ({ flushEvents, intakeRegistry }) => {\n      await flushEvents()\n\n      expect(intakeRegistry.replayRecords.length).toBeGreaterThan(0)\n      expect(intakeRegistry.hasOnlyBridgeRequests).toBe(true)\n    })\n\n  createTest('do not send records when the recording is stopped')\n    .withRum()\n    .withEventBridge()\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      // wait for recorder to be properly started\n      await page.waitForTimeout(200)\n\n      const preStopRecordsCount = intakeRegistry.replayRecords.length\n      await page.evaluate(() => {\n        window.DD_RUM!.stopSessionReplayRecording()\n\n        // trigger a new record\n        document.body.appendChild(document.createElement('li'))\n      })\n\n      await flushEvents()\n\n      const postStopRecordsCount = intakeRegistry.replayRecords.length - preStopRecordsCount\n      expect(postStopRecordsCount).toEqual(0)\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/logs.scenario.ts",
    "content": "import type { DatadogLogs } from '@datadog/browser-logs'\nimport { DEFAULT_REQUEST_ERROR_RESPONSE_LENGTH_LIMIT } from '@datadog/browser-logs/src/domain/configuration'\nimport { test, expect } from '@playwright/test'\nimport { createTest, createWorker } from '../lib/framework'\nimport { APPLICATION_ID } from '../lib/helpers/configuration'\n\nconst UNREACHABLE_URL = 'http://localhost:9999/unreachable'\n\ndeclare global {\n  interface Window {\n    myServiceWorker: ServiceWorkerRegistration\n  }\n  // Used in evaluateInWorker callbacks (code runs in the service worker global scope)\n  var DD_LOGS: DatadogLogs | undefined\n}\n\ntest.describe('logs', () => {\n  test.describe('service workers', () => {\n    createTest('service worker with worker logs - esm')\n      .withWorker(createWorker().withLogs())\n      .run(async ({ flushEvents, intakeRegistry, browserName, evaluateInWorker }) => {\n        test.skip(browserName !== 'chromium', 'Non-Chromium browsers do not support ES modules in Service Workers')\n\n        await evaluateInWorker(() => {\n          DD_LOGS!.logger.log('Some message')\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.logsRequests).toHaveLength(1)\n        expect(intakeRegistry.logsEvents[0].message).toBe('Some message')\n      })\n\n    createTest('service worker with worker logs - importScripts')\n      .withWorker(createWorker({ importScripts: true }).withLogs())\n      .run(async ({ flushEvents, intakeRegistry, browserName, evaluateInWorker }) => {\n        test.skip(\n          browserName === 'webkit',\n          'BrowserStack overrides the localhost URL with bs-local.com and cannot be used to install a Service Worker'\n        )\n\n        await evaluateInWorker(() => {\n          DD_LOGS!.logger.log('Other message')\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.logsRequests).toHaveLength(1)\n        expect(intakeRegistry.logsEvents[0].message).toBe('Other message')\n      })\n\n    createTest('service worker console forwarding')\n      .withWorker(createWorker({ importScripts: true }).withLogs({ forwardConsoleLogs: 'all' }))\n      .run(async ({ flushEvents, intakeRegistry, evaluateInWorker, browserName }) => {\n        test.skip(\n          browserName === 'webkit',\n          'BrowserStack overrides the localhost URL with bs-local.com and cannot be used to install a Service Worker'\n        )\n\n        await evaluateInWorker(() => {\n          console.log('SW console log test')\n        })\n\n        await flushEvents()\n\n        // Expect logs for console, error, and report events from service worker\n        expect(intakeRegistry.logsRequests).toHaveLength(1)\n        expect(intakeRegistry.logsEvents[0].message).toBe('SW console log test')\n      })\n  })\n\n  createTest('send logs')\n    .withLogs()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.log('hello')\n      })\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].message).toBe('hello')\n    })\n\n  createTest('display logs in the console')\n    .withLogs()\n    .run(async ({ intakeRegistry, flushEvents, page, withBrowserLogs }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.setHandler('console')\n        window.DD_LOGS!.logger.warn('hello')\n      })\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(0)\n\n      withBrowserLogs((logs) => {\n        expect(logs).toHaveLength(1)\n        expect(logs[0].level).toBe('warning')\n        expect(logs[0].message).not.toEqual(expect.stringContaining('Datadog Browser SDK'))\n        expect(logs[0].message).toEqual(expect.stringContaining('hello'))\n      })\n    })\n\n  createTest('send console errors')\n    .withLogs({ forwardErrorsToLogs: true })\n    .run(async ({ intakeRegistry, flushEvents, page, withBrowserLogs }) => {\n      await page.evaluate(() => {\n        console.error('oh snap')\n      })\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].message).toBe('oh snap')\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('send XHR network errors')\n    .withLogs({ forwardErrorsToLogs: true })\n    .run(async ({ intakeRegistry, flushEvents, withBrowserLogs, page }) => {\n      await page.evaluate(\n        (unreachableUrl) =>\n          new Promise<void>((resolve) => {\n            const xhr = new XMLHttpRequest()\n            xhr.addEventListener('error', () => resolve())\n            xhr.open('GET', unreachableUrl)\n            xhr.send()\n          }),\n        UNREACHABLE_URL\n      )\n\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].message).toBe(`XHR error GET ${UNREACHABLE_URL}`)\n      expect(intakeRegistry.logsEvents[0].origin).toBe('network')\n\n      withBrowserLogs((browserLogs) => {\n        // Some browser report two errors:\n        // * failed to load resource\n        // * blocked by CORS policy\n        expect(browserLogs.length).toBeGreaterThanOrEqual(1)\n      })\n    })\n\n  createTest('send fetch network errors')\n    .withLogs({ forwardErrorsToLogs: true })\n    .run(async ({ intakeRegistry, flushEvents, page, withBrowserLogs }) => {\n      await page.evaluate((unreachableUrl) => fetch(unreachableUrl).catch(() => undefined), UNREACHABLE_URL)\n\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].message).toBe(`Fetch error GET ${UNREACHABLE_URL}`)\n      expect(intakeRegistry.logsEvents[0].origin).toBe('network')\n\n      withBrowserLogs((browserLogs) => {\n        // Some browser report two errors:\n        // * failed to load resource\n        // * blocked by CORS policy\n        expect(browserLogs.length).toBeGreaterThanOrEqual(1)\n      })\n    })\n\n  createTest('keep only the first bytes of the response')\n    .withLogs({ forwardErrorsToLogs: true })\n    .run(async ({ intakeRegistry, baseUrl, servers, flushEvents, page, withBrowserLogs, browserName }) => {\n      await page.evaluate(() => fetch('/throw-large-response'))\n\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].message).toBe(`Fetch error GET ${new URL('/throw-large-response', baseUrl)}`)\n      expect(intakeRegistry.logsEvents[0].origin).toBe('network')\n\n      const ellipsisSize = 3\n      expect(intakeRegistry.logsEvents[0].error?.stack).toHaveLength(\n        DEFAULT_REQUEST_ERROR_RESPONSE_LENGTH_LIMIT + ellipsisSize\n      )\n\n      expect(servers.base.app.getLargeResponseWroteSize()).toBeGreaterThanOrEqual(\n        DEFAULT_REQUEST_ERROR_RESPONSE_LENGTH_LIMIT\n      )\n\n      withBrowserLogs((browserLogs) => {\n        if (browserName === 'firefox') {\n          // Firefox does not report the error message\n          expect(browserLogs).toHaveLength(0)\n        } else {\n          expect(browserLogs).toHaveLength(1)\n          expect(browserLogs[0].message).toContain('the server responded with a status of 500')\n        }\n      })\n    })\n\n  createTest('track fetch error')\n    .withLogs({ forwardErrorsToLogs: true })\n    .run(async ({ intakeRegistry, baseUrl, flushEvents, flushBrowserLogs, page }) => {\n      await page.evaluate(\n        (unreachableUrl) =>\n          new Promise<void>((resolve) => {\n            let count = 0\n            fetch('/throw')\n              .then(() => (count += 1))\n              .catch((err) => console.error(err))\n            fetch('/unknown')\n              .then(() => (count += 1))\n              .catch((err) => console.error(err))\n            fetch(unreachableUrl).catch(() => (count += 1))\n            fetch('/ok')\n              .then(() => (count += 1))\n              .catch((err) => console.error(err))\n\n            const interval = setInterval(() => {\n              if (count === 4) {\n                clearInterval(interval)\n                resolve()\n              }\n            }, 500)\n          }),\n        UNREACHABLE_URL\n      )\n\n      flushBrowserLogs()\n      await flushEvents()\n\n      expect(intakeRegistry.logsEvents).toHaveLength(2)\n\n      const unreachableRequest = intakeRegistry.logsEvents.find((log) => log.http!.url.includes('/unreachable'))!\n      const throwRequest = intakeRegistry.logsEvents.find((log) => log.http!.url.includes('/throw'))!\n\n      expect(throwRequest.message).toEqual(`Fetch error GET ${new URL('/throw', baseUrl)}`)\n      expect(throwRequest.http!.status_code).toEqual(500)\n      expect(throwRequest.error!.stack).toMatch(/Server error/)\n\n      expect(unreachableRequest.message).toEqual(`Fetch error GET ${UNREACHABLE_URL}`)\n      expect(unreachableRequest.http!.status_code).toEqual(0)\n      expect(unreachableRequest.error!.stack).toContain('TypeError')\n    })\n\n  createTest('send runtime errors happening before initialization')\n    .withLogs({ forwardErrorsToLogs: true })\n    .withLogsInit((configuration) => {\n      // Use a setTimeout to:\n      // * have a constant stack trace regardless of the setup used\n      // * avoid the exception to be swallowed by the `onReady` logic\n      setTimeout(() => {\n        throw new Error('oh snap')\n      })\n      // Simulate a late initialization of the RUM SDK\n      setTimeout(() => window.DD_LOGS!.init(configuration))\n    })\n    .run(async ({ intakeRegistry, flushEvents, withBrowserLogs }) => {\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].message).toBe('oh snap')\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('add RUM internal context to logs')\n    .withRum()\n    .withLogs()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.log('hello')\n      })\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].view.id).toBeDefined()\n      expect(intakeRegistry.logsEvents[0].application_id).toBe(APPLICATION_ID)\n    })\n\n  createTest('add default tags to logs')\n    .withLogs({\n      service: 'foo',\n      env: 'dev',\n      version: '1.0.0',\n    })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.log('hello world!')\n      })\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].ddtags).toMatch(/sdk_version:(.*),env:dev,service:foo,version:1.0.0$/)\n    })\n\n  createTest('add tags to the logger')\n    .withLogs()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.addTag('planet', 'mars')\n        window.DD_LOGS!.logger.log('hello world!')\n      })\n\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].ddtags).toMatch(/sdk_version:(.*),planet:mars$/)\n    })\n\n  createTest('ignore tags from message context and logger context')\n    .withLogs()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.setContextProperty('ddtags', 'planet:mars')\n        window.DD_LOGS!.logger.log('hello world!', { ddtags: 'planet:earth' })\n      })\n\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].ddtags).toMatch(/sdk_version:(.*)$/)\n    })\n\n  createTest('allow to modify events')\n    .withLogs({\n      beforeSend: (event) => {\n        event.foo = 'bar'\n        return true\n      },\n    })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.logger.log('hello', {})\n      })\n      await flushEvents()\n      expect(intakeRegistry.logsEvents).toHaveLength(1)\n      expect(intakeRegistry.logsEvents[0].foo).toBe('bar')\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/microfrontend.scenario.ts",
    "content": "import type { RumEvent, RumEventDomainContext, RumInitConfiguration } from '@datadog/browser-rum-core'\nimport type { LogsEvent, LogsInitConfiguration, LogsEventDomainContext } from '@datadog/browser-logs'\nimport { test, expect } from '@playwright/test'\nimport { ExperimentalFeature } from '@datadog/browser-core'\nimport { createTest, microfrontendSetup } from '../lib/framework'\n\nconst HANDLING_STACK_REGEX = /^HandlingStack: .*\\n\\s+at testHandlingStack @/\n\nconst RUM_CONFIG: Partial<RumInitConfiguration> = {\n  service: 'main-service',\n  version: '1.0.0',\n  beforeSend: (event: RumEvent, domainContext: RumEventDomainContext) => {\n    if ('handlingStack' in domainContext) {\n      event.context!.handlingStack = domainContext.handlingStack\n    }\n\n    return true\n  },\n}\n\nconst LOGS_CONFIG: Partial<LogsInitConfiguration> = {\n  forwardConsoleLogs: 'all',\n  beforeSend: (event: LogsEvent, domainContext: LogsEventDomainContext) => {\n    if (domainContext && 'handlingStack' in domainContext) {\n      event.context = { handlingStack: domainContext.handlingStack }\n    }\n\n    return true\n  },\n}\n\ntest.describe('microfrontend', () => {\n  test.describe('RUM', () => {\n    test.describe('with beforeSend', () => {\n      createTest('expose handling stack for fetch requests')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          // eslint-disable-next-line @typescript-eslint/no-empty-function\n          const noop = () => {}\n          function testHandlingStack() {\n            fetch('/ok').then(noop, noop)\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'fetch')\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for xhr requests')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            const xhr = new XMLHttpRequest()\n            xhr.open('GET', '/ok')\n            xhr.send()\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'xhr')\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for DD_RUM.addAction')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            window.DD_RUM!.addAction('foo')\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumActionEvents[0]\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for DD_RUM.addError')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            window.DD_RUM!.addError(new Error('foo'))\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumErrorEvents[0]\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for console errors')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            console.error('foo')\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents, withBrowserLogs }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumErrorEvents[0]\n\n          withBrowserLogs((logs) => {\n            expect(logs).toHaveLength(1)\n            expect(logs[0].message).toMatch(/foo$/)\n          })\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for DD_RUM.startView')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            window.DD_RUM!.startView({ name: 'test-view' })\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumViewEvents.find((event) => event.view.name === 'test-view')\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for DD_RUM.startDurationVital')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            const ref = window.DD_RUM!.startDurationVital('test-vital')\n            window.DD_RUM!.stopDurationVital(ref)\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumVitalEvents.find((event) => event.vital.name === 'test-vital')\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('expose handling stack for DD_RUM.startFeatureOperation')\n        .withRum({ ...RUM_CONFIG, enableExperimentalFeatures: [ExperimentalFeature.FEATURE_OPERATION_VITAL] })\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init(configuration)\n\n          function testHandlingStack() {\n            window.DD_RUM!.startFeatureOperation('test-operation')\n          }\n\n          testHandlingStack()\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const event = intakeRegistry.rumVitalEvents.find((event) => event.vital.name === 'test-operation')\n\n          expect(event).toBeTruthy()\n          expect(event?.context?.handlingStack).toMatch(HANDLING_STACK_REGEX)\n        })\n\n      createTest('resource: allow to modify service and version')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init({\n            ...configuration,\n            beforeSend: (event: RumEvent) => {\n              if (event.type === 'resource') {\n                event.service = 'mfe-service'\n                event.version = '0.1.0'\n              }\n\n              return true\n            },\n          })\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const viewEvent = intakeRegistry.rumViewEvents[0]\n          const resourceEvent = intakeRegistry.rumResourceEvents[0]\n\n          expect(viewEvent).toBeTruthy()\n          expect(viewEvent.service).toBe('main-service')\n          expect(viewEvent.version).toBe('1.0.0')\n\n          expect(resourceEvent).toBeTruthy()\n          expect(resourceEvent.service).toBe('mfe-service')\n          expect(resourceEvent.version).toBe('0.1.0')\n        })\n\n      createTest('view: allowed to modify service and version')\n        .withRum(RUM_CONFIG)\n        .withRumInit((configuration) => {\n          window.DD_RUM!.init({\n            ...configuration,\n            beforeSend: (event: RumEvent) => {\n              if (event.type === 'view') {\n                event.service = 'mfe-service'\n                event.version = '0.1.0'\n              }\n\n              return true\n            },\n          })\n        })\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          const viewEvent = intakeRegistry.rumViewEvents[0]\n\n          expect(viewEvent).toBeTruthy()\n          expect(viewEvent.service).toBe('mfe-service')\n          expect(viewEvent.version).toBe('0.1.0')\n        })\n    })\n\n    test.describe('with source code bundler plugin', () => {\n      createTest('errors from console.error should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page, withBrowserLogs }) => {\n          await page.click('#app1-console-error')\n          await page.click('#app2-console-error')\n          await flushEvents()\n\n          expect(intakeRegistry.rumErrorEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n\n          withBrowserLogs((browserLogs) => {\n            expect(browserLogs).toHaveLength(2)\n          })\n        })\n\n      createTest('runtime errors should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page, withBrowserLogs }) => {\n          await page.click('#app1-runtime-error')\n          await page.click('#app2-runtime-error')\n          await flushEvents()\n\n          expect(intakeRegistry.rumErrorEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n\n          withBrowserLogs((browserLogs) => {\n            expect(browserLogs).toHaveLength(2)\n          })\n        })\n\n      createTest('fetch requests should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page }) => {\n          await page.click('#app1-fetch')\n          await page.click('#app2-fetch')\n          await flushEvents()\n\n          const resourceEvents = intakeRegistry.rumResourceEvents.filter((event) => event.resource.type === 'fetch')\n\n          expect(resourceEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n        })\n\n      createTest('xhr requests should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page }) => {\n          await page.click('#app1-xhr')\n          await page.click('#app2-xhr')\n          await flushEvents()\n\n          const resourceEvents = intakeRegistry.rumResourceEvents.filter((event) => event.resource.type === 'xhr')\n\n          expect(resourceEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n        })\n\n      createTest('custom actions should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page }) => {\n          await page.click('#app1-custom-action')\n          await page.click('#app2-custom-action')\n          await flushEvents()\n\n          const rumActionEvents = intakeRegistry.rumActionEvents.filter((event) => event.action.type === 'custom')\n\n          expect(rumActionEvents).toMatchObject([\n            expect.objectContaining({\n              service: 'mfe-app1-service',\n              version: '1.0.0',\n            }),\n            expect.objectContaining({\n              service: 'mfe-app2-service',\n              version: '0.2.0',\n            }),\n          ])\n        })\n\n      createTest('LOAf should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page, browserName }) => {\n          test.skip(browserName !== 'chromium', 'Non-Chromium browsers do not support long tasks')\n\n          await page.click('#app1-loaf')\n          await page.click('#app2-loaf')\n          await flushEvents()\n\n          const longTaskEvents = intakeRegistry.rumLongTaskEvents.filter((event) =>\n            event.long_task.scripts?.[0]?.invoker?.includes('onclick')\n          )\n\n          expect(longTaskEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n        })\n\n      createTest('manual views should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page }) => {\n          await page.click('#app1-view')\n          await page.click('#app2-view')\n          await flushEvents()\n\n          expect(intakeRegistry.rumViewEvents).toMatchObject(\n            expect.arrayContaining([\n              expect.objectContaining({\n                view: expect.objectContaining({ name: 'app1-view' }),\n                service: 'mfe-app1-service',\n                version: '1.0.0',\n              }),\n              expect.objectContaining({\n                view: expect.objectContaining({ name: 'app2-view' }),\n                service: 'mfe-app2-service',\n                version: '0.2.0',\n              }),\n            ])\n          )\n        })\n\n      createTest('duration vitals should have service and version from source code context')\n        .withRum(RUM_CONFIG)\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page }) => {\n          await page.click('#app1-vital')\n          await page.click('#app2-vital')\n          await flushEvents()\n\n          expect(intakeRegistry.rumVitalEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n        })\n\n      createTest('feature operations should have service and version from source code context')\n        .withRum({ ...RUM_CONFIG, enableExperimentalFeatures: [ExperimentalFeature.FEATURE_OPERATION_VITAL] })\n        .withSetup(microfrontendSetup)\n        .run(async ({ intakeRegistry, flushEvents, page }) => {\n          await page.click('#app1-feature-operation')\n          await page.click('#app2-feature-operation')\n          await flushEvents()\n\n          const featureOperationEvents = intakeRegistry.rumVitalEvents.filter(\n            (event) => event.vital.step_type === 'start'\n          )\n\n          expect(featureOperationEvents).toMatchObject([\n            expect.objectContaining({ service: 'mfe-app1-service', version: '1.0.0' }),\n            expect.objectContaining({ service: 'mfe-app2-service', version: '0.2.0' }),\n          ])\n        })\n    })\n  })\n\n  test.describe('Logs', () => {\n    createTest('expose handling stack for console.log')\n      .withLogs(LOGS_CONFIG)\n      .withLogsInit((configuration) => {\n        window.DD_LOGS!.init(configuration)\n\n        function testHandlingStack() {\n          console.log('foo')\n        }\n\n        testHandlingStack()\n      })\n      .run(async ({ intakeRegistry, flushEvents, flushBrowserLogs }) => {\n        await flushEvents()\n\n        const event = intakeRegistry.logsEvents[0]\n\n        flushBrowserLogs()\n\n        expect(event).toBeTruthy()\n        expect(event?.context).toEqual({\n          handlingStack: expect.stringMatching(HANDLING_STACK_REGEX),\n        })\n      })\n\n    createTest('expose handling stack for DD_LOGS.logger.log')\n      .withLogs(LOGS_CONFIG)\n      .withLogsInit((configuration) => {\n        window.DD_LOGS!.init(configuration)\n\n        function testHandlingStack() {\n          window.DD_LOGS!.logger.log('foo')\n        }\n\n        testHandlingStack()\n      })\n      .run(async ({ intakeRegistry, flushEvents, flushBrowserLogs }) => {\n        await flushEvents()\n\n        const event = intakeRegistry.logsEvents[0]\n\n        flushBrowserLogs()\n\n        expect(event).toBeTruthy()\n        expect(event?.context).toEqual({\n          handlingStack: expect.stringMatching(HANDLING_STACK_REGEX),\n        })\n      })\n  })\n})\n"
  },
  {
    "path": "test/e2e/scenario/plugins/angularPlugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\nimport { runBasePluginErrorTests } from './basePluginErrorTests'\nimport { runBasePluginRouterTests } from './basePluginRouterTests'\n\nconst angularAppName = 'angular-app'\nconst angularBasePluginConfig = {\n  name: angularAppName,\n  loadApp: (b: ReturnType<typeof createTest>) => b.withApp(angularAppName),\n  viewPrefix: '',\n}\n\nrunBasePluginRouterTests([\n  {\n    ...angularBasePluginConfig,\n    router: {\n      homeViewName: '/',\n      homeUrlPattern: '**/',\n      userRouteName: '/user/:id',\n      guidesRouteName: '/guides/:slug',\n    },\n  },\n])\n\nrunBasePluginErrorTests([\n  {\n    ...angularBasePluginConfig,\n    error: {\n      clientErrorMessage: 'Error triggered by button click',\n      expectedFramework: 'angular',\n      expectsBrowserConsoleErrors: true,\n    },\n  },\n])\n\ntest.describe('plugin: angular', () => {\n  createTest('should define a view name for nested routes')\n    .withRum()\n    .withApp(angularAppName)\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Go to Nested Route')\n      await flushEvents()\n      const viewEvents = intakeRegistry.rumViewEvents\n      expect(viewEvents.length).toBeGreaterThan(0)\n      const lastView = viewEvents[viewEvents.length - 1]\n      expect(lastView.view.name).toBe('/parent/nested')\n      expect(lastView.view.url).toContain('/parent/nested')\n    })\n\n  createTest('should define a view name with the actual path for wildcard routes')\n    .withRum()\n    .withApp(angularAppName)\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Go to Wildcard Route')\n      await flushEvents()\n      const viewEvents = intakeRegistry.rumViewEvents\n      expect(viewEvents.length).toBeGreaterThan(0)\n      const lastView = viewEvents[viewEvents.length - 1]\n      expect(lastView.view.name).toBe('/unknown/page')\n      expect(lastView.view.url).toContain('/unknown/page')\n    })\n\n  createTest('should report errors caught by provideDatadogErrorHandler')\n    .withRum()\n    .withApp(angularAppName)\n    .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {\n      await page.click('#throw-error')\n      await flushEvents()\n\n      const angularErrors = intakeRegistry.rumErrorEvents.filter((event) => event.context?.framework === 'angular')\n      expect(angularErrors).toHaveLength(1)\n      expect(angularErrors[0].error.message).toBe('angular error from component')\n      expect(angularErrors[0].error.handling).toBe('handled')\n      expect(angularErrors[0].error.source).toBe('custom')\n      expect(angularErrors[0].error.handling_stack).toEqual(expect.stringContaining('angular error'))\n\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs.filter((log) => log.level === 'error').length).toBeGreaterThan(0)\n      })\n    })\n\n  createTest('should merge dd_context from the error object into the event context')\n    .withRum()\n    .withApp(angularAppName)\n    .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {\n      await page.click('#throw-error-with-context')\n      await flushEvents()\n\n      const angularErrors = intakeRegistry.rumErrorEvents.filter((event) => event.context?.framework === 'angular')\n      expect(angularErrors).toHaveLength(1)\n      expect(angularErrors[0].error.message).toBe('angular error with dd_context')\n      expect(angularErrors[0].context).toEqual(\n        expect.objectContaining({\n          framework: 'angular',\n          component: 'InitialRoute',\n          userId: 42,\n        })\n      )\n\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs.filter((log) => log.level === 'error').length).toBeGreaterThan(0)\n      })\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/plugins/basePluginErrorTests.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\n\ntype TestBuilder = ReturnType<typeof createTest>\n\ninterface ErrorConfig {\n  clientErrorMessage: string\n  expectedFramework: string\n  expectsBrowserConsoleErrors?: boolean\n  expectsComponentStack?: boolean\n}\n\ninterface ErrorPluginTestConfig {\n  name: string\n  loadApp: (builder: TestBuilder) => TestBuilder\n  viewPrefix: string\n  error: ErrorConfig\n}\n\nexport function runBasePluginErrorTests(configs: ErrorPluginTestConfig[]) {\n  for (const { name, loadApp, viewPrefix, error } of configs) {\n    test.describe(`base plugin: ${name}`, () => {\n      test.describe('errors', () => {\n        loadApp(createTest('should report client-side error').withRum()).run(\n          async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {\n            await page.click('text=Go to Error Test')\n            await page.waitForURL(`**${viewPrefix}/error-test`)\n\n            await page.click('[data-testid=\"trigger-error\"]')\n            await page.waitForSelector('[data-testid=\"error-handled\"]')\n\n            await flushEvents()\n\n            const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')\n            expect(customErrors).toHaveLength(1)\n            expect(customErrors[0].error.message).toBe(error.clientErrorMessage)\n            expect(customErrors[0].error.handling_stack).toBeDefined()\n            expect(customErrors[0].error.stack).toBeDefined()\n            if (error.expectsComponentStack) {\n              expect(customErrors[0].error.component_stack).toBeDefined()\n            }\n\n            expect(customErrors[0].context?.framework).toEqual(error.expectedFramework)\n\n            if (error.expectsBrowserConsoleErrors) {\n              withBrowserLogs((browserLogs) => {\n                expect(browserLogs.filter((log) => log.level === 'error').length).toBeGreaterThan(0)\n              })\n            }\n          }\n        )\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "test/e2e/scenario/plugins/basePluginRouterTests.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\n\ntype TestBuilder = ReturnType<typeof createTest>\n\ninterface RouterConfig {\n  homeViewName: string\n  homeUrlPattern: string | RegExp\n  userRouteName: string\n  guidesRouteName: string\n}\n\ninterface RouterPluginTestConfig {\n  name: string\n  loadApp: (builder: TestBuilder) => TestBuilder\n  viewPrefix: string\n  router: RouterConfig\n}\n\nexport function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {\n  for (const { name, loadApp, viewPrefix, router } of configs) {\n    const { homeViewName, homeUrlPattern, userRouteName, guidesRouteName } = router\n\n    test.describe(`base plugin: ${name}`, () => {\n      test.describe('router', () => {\n        loadApp(createTest('should track initial home view').withRum()).run(async ({ flushEvents, intakeRegistry }) => {\n          await flushEvents()\n\n          const viewEvents = intakeRegistry.rumViewEvents\n          expect(viewEvents.length).toBeGreaterThan(0)\n          const firstView = viewEvents[0]\n          expect(firstView.view.name).toBe(homeViewName)\n          expect(firstView.view.loading_type).toBe('initial_load')\n        })\n\n        loadApp(createTest('should normalize dynamic routes and preserve real URLs and referrers').withRum()).run(\n          async ({ page, flushEvents, intakeRegistry, baseUrl }) => {\n            const baseOrigin = new URL(baseUrl).origin\n\n            // Home → Guides → Home → User → Home\n            await page.click('text=Go to Guides 123')\n            await page.waitForURL('**/guides/123')\n\n            await page.click('text=Back to Home')\n            await page.waitForURL(homeUrlPattern)\n\n            await page.click('text=Go to User 42')\n            await page.waitForURL('**/user/42?admin=true')\n\n            await page.click('text=Back to Home')\n\n            await flushEvents()\n\n            const viewEvents = intakeRegistry.rumViewEvents\n\n            const homeView = viewEvents.find((e) => e.view.name === homeViewName)\n            expect(homeView).toBeDefined()\n\n            const guidesView = viewEvents.find((e) => e.view.name === `${viewPrefix}${guidesRouteName}`)\n            expect(guidesView).toBeDefined()\n            expect(guidesView?.view.loading_type).toBe('route_change')\n            expect(guidesView?.view.url).toContain('/guides/123')\n            expect(guidesView?.view.referrer).toBe(baseUrl)\n\n            const userView = viewEvents.find((e) => e.view.name === `${viewPrefix}${userRouteName}`)\n            expect(userView).toBeDefined()\n            expect(userView?.view.loading_type).toBe('route_change')\n            expect(userView?.view.url).toBe(`${baseOrigin}${viewPrefix}/user/42?admin=true`)\n            expect(userView?.view.referrer).toBe(`${baseOrigin}${homeViewName}`)\n          }\n        )\n\n        loadApp(createTest('should track SPA navigation with loading_time').withRum()).run(\n          async ({ page, flushEvents, intakeRegistry }) => {\n            await page.waitForLoadState('networkidle')\n            await page.click('text=Go to User 42')\n            await page.waitForURL('**/user/42?admin=true')\n\n            await page.click('text=Back to Home')\n\n            await flushEvents()\n\n            const homeView = intakeRegistry.rumViewEvents.find(\n              (e) =>\n                e.view.name === homeViewName &&\n                e.view.loading_type === 'initial_load' &&\n                e.view.loading_time !== undefined\n            )\n            expect(homeView).toBeDefined()\n            expect(homeView?.view.loading_time).toBeGreaterThan(0)\n          }\n        )\n\n        loadApp(createTest('should not create a new view when query params change').withRum()).run(\n          async ({ page, flushEvents, intakeRegistry }) => {\n            await page.click('text=Go to User 42')\n            await page.waitForURL('**/user/42?admin=true')\n\n            await page.click('text=Change query params')\n            await page.waitForURL('**/user/42?admin=false')\n\n            await flushEvents()\n\n            const userView = intakeRegistry.rumViewEvents.find((e) => e.view.name === `${viewPrefix}${userRouteName}`)\n            expect(userView).toBeDefined()\n\n            const queryParamsView = intakeRegistry.rumViewEvents.find((e) => e.view.url?.includes('admin=false'))\n            expect(queryParamsView).toBeUndefined()\n          }\n        )\n\n        loadApp(\n          createTest('should track navigations between different concrete URLs of the same dynamic route').withRum()\n        ).run(async ({ page, flushEvents, intakeRegistry }) => {\n          await page.click('text=Go to User 42')\n          await page.waitForURL('**/user/42?admin=true')\n\n          await page.click('text=Go to User 999')\n          await page.waitForURL('**/user/999?admin=true')\n\n          await flushEvents()\n\n          const user42View = intakeRegistry.rumViewEvents.find(\n            (e) => e.view.name === `${viewPrefix}${userRouteName}` && e.view.url?.includes('/user/42')\n          )\n          const user999View = intakeRegistry.rumViewEvents.find(\n            (e) => e.view.name === `${viewPrefix}${userRouteName}` && e.view.url?.includes('/user/999')\n          )\n          expect(user42View).toBeDefined()\n          expect(user999View).toBeDefined()\n          expect(user999View?.view.referrer).toContain('/user/42')\n        })\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "test/e2e/scenario/plugins/nextjsPlugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\nimport { runBasePluginErrorTests } from './basePluginErrorTests'\nimport { runBasePluginRouterTests } from './basePluginRouterTests'\n\nconst nextjsVariants = [\n  {\n    name: 'nextjs app router',\n    routerType: 'app' as const,\n    viewPrefix: '',\n    homeUrlPattern: '**/',\n    clientErrorMessage: 'Client error from error-test',\n  },\n  {\n    name: 'nextjs pages router',\n    routerType: 'pages' as const,\n    viewPrefix: '/pages-router',\n    homeUrlPattern: /\\/pages-router(\\?|$)/,\n    clientErrorMessage: 'Pages Router error from NextjsErrorBoundary',\n  },\n]\n\nrunBasePluginRouterTests(\n  nextjsVariants.map(({ name, routerType, viewPrefix, homeUrlPattern }) => ({\n    name,\n    loadApp: (b: ReturnType<typeof createTest>) => b.withNextjsApp(routerType),\n    viewPrefix,\n    router: {\n      homeViewName: viewPrefix || '/',\n      homeUrlPattern,\n      userRouteName: '/user/[id]',\n      guidesRouteName: '/guides/[...slug]',\n    },\n  }))\n)\n\nrunBasePluginErrorTests(\n  nextjsVariants.map(({ name, routerType, viewPrefix, clientErrorMessage }) => ({\n    name,\n    loadApp: (b: ReturnType<typeof createTest>) => b.withNextjsApp(routerType),\n    viewPrefix,\n    error: {\n      clientErrorMessage,\n      expectedFramework: 'nextjs',\n      expectsBrowserConsoleErrors: true,\n    },\n  }))\n)\n\ntest.describe('plugin: nextjs', () => {\n  createTest('should not be affected by parallel routes')\n    .withRum()\n    .withNextjsApp('app')\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.waitForSelector('[data-testid=\"sidebar\"]')\n      expect(await page.textContent('[data-testid=\"sidebar\"]')).toContain('Sidebar: Home')\n\n      await page.click('text=Go to User 42')\n      await page.waitForURL('**/user/42?admin=true')\n\n      expect(await page.textContent('[data-testid=\"sidebar\"]')).toContain('Sidebar: User 42')\n\n      await page.click('text=Back to Home')\n\n      await flushEvents()\n\n      const viewEvents = intakeRegistry.rumViewEvents\n\n      const homeView = viewEvents.find((e) => e.view.name === '/')\n      expect(homeView).toBeDefined()\n\n      const userView = viewEvents.find((e) => e.view.name === '/user/[id]')\n      expect(userView).toBeDefined()\n\n      expect(viewEvents.every((e) => !e.view.name?.includes('@sidebar'))).toBe(true)\n    })\n\n  createTest('should report a server error with digest via addNextjsError')\n    .withRum()\n    .withNextjsApp('app')\n    .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {\n      await page.click('text=Go to Server Error')\n      await page.waitForSelector('[data-testid=\"error-handled\"]')\n\n      await flushEvents()\n\n      const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')\n      expect(customErrors).toHaveLength(1)\n      expect(customErrors[0].error.handling_stack).toBeDefined()\n      expect(customErrors[0].context).toMatchObject({\n        framework: 'nextjs',\n        nextjs: { digest: expect.any(String) },\n      })\n\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs.length).toBeGreaterThan(0)\n      })\n    })\n\n  createTest('should report global error via global-error.tsx')\n    .withRum()\n    .withNextjsApp('app')\n    .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {\n      await page.click('text=Go to Global Error')\n      await page.waitForSelector('[data-testid=\"global-error-boundary\"]')\n\n      await flushEvents()\n\n      const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')\n      expect(customErrors).toHaveLength(1)\n      expect(customErrors[0].error.handling_stack).toBeDefined()\n      expect(customErrors[0].context).toMatchObject({ framework: 'nextjs' })\n\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs.length).toBeGreaterThan(0)\n      })\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/plugins/nuxtPlugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\nimport { runBasePluginRouterTests } from './basePluginRouterTests'\n\nconst nuxtBasePluginConfig = {\n  name: 'nuxt',\n  loadApp: (b: ReturnType<typeof createTest>) => b.withNuxtApp(),\n  viewPrefix: '',\n}\n\nrunBasePluginRouterTests([\n  {\n    ...nuxtBasePluginConfig,\n    router: {\n      homeViewName: '/',\n      homeUrlPattern: '**/',\n      userRouteName: '/user/[id]',\n      guidesRouteName: '/guides/[...slug]',\n    },\n  },\n])\n\ntest.describe('plugin: nuxt', () => {\n  createTest('should create a new view when the hash changes')\n    .withRum()\n    .withNuxtApp()\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Go to User 42')\n      await page.waitForURL('**/user/42?admin=true')\n\n      await page.click('text=Go to Section')\n      await page.waitForURL('**/user/42#section')\n\n      await flushEvents()\n\n      const initialUserView = intakeRegistry.rumViewEvents.find(\n        (e) => e.view.name === '/user/[id]' && e.view.url?.includes('/user/42?admin=true')\n      )\n      const hashUserView = intakeRegistry.rumViewEvents.find(\n        (e) => e.view.name === '/user/[id]' && e.view.url?.includes('/user/42#section')\n      )\n\n      expect(initialUserView).toBeDefined()\n      expect(hashUserView).toBeDefined()\n      expect(hashUserView?.view.loading_type).toBe('route_change')\n      expect(hashUserView?.view.id).not.toBe(initialUserView?.view.id)\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/plugins/plugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport type { RumPlugin, AllowedRawRumEvent } from '@datadog/browser-rum-core'\nimport { ActionType, RumEventType } from '@datadog/browser-rum-core'\nimport type { ServerDuration, TimeStamp } from '@datadog/browser-core'\nimport { clocksNow, generateUUID } from '@datadog/browser-core'\nimport { createTest } from '../../lib/framework'\n\ndeclare global {\n  interface Window {\n    TEST_PLUGIN: Parameters<NonNullable<RumPlugin['onRumStart']>>[0]\n  }\n}\n\nfunction createPlugin(): RumPlugin {\n  return {\n    name: 'test-plugin',\n    onRumStart: ({ addEvent }) => {\n      window.TEST_PLUGIN = { addEvent }\n    },\n  }\n}\n\nconst mockPartialEvents: AllowedRawRumEvent[] = [\n  {\n    type: RumEventType.ACTION,\n    date: 1 as TimeStamp,\n    action: {\n      id: generateUUID(),\n      type: ActionType.CLICK,\n      target: {\n        name: 'click on button',\n      },\n    },\n  },\n  {\n    type: RumEventType.ERROR,\n    date: 1 as TimeStamp,\n    error: {\n      id: generateUUID(),\n      message: 'test error',\n      source: 'source',\n      source_type: 'browser',\n    },\n  },\n  {\n    type: RumEventType.LONG_TASK,\n    date: 1 as TimeStamp,\n    long_task: {\n      id: generateUUID(),\n      entry_type: 'long-task',\n      duration: 100 as ServerDuration,\n    },\n    _dd: {\n      discarded: false,\n    },\n  },\n  {\n    type: RumEventType.RESOURCE,\n    date: 1 as TimeStamp,\n    resource: {\n      id: generateUUID(),\n      type: 'document',\n      url: 'https://www.datadoghq.com',\n      method: 'GET',\n      status_code: 200,\n      duration: 100 as ServerDuration,\n      size: 100,\n    },\n    _dd: {\n      discarded: false,\n    },\n  },\n  {\n    type: RumEventType.VITAL,\n    date: 1 as TimeStamp,\n    vital: {\n      id: generateUUID(),\n      type: 'duration',\n      name: 'vital',\n      duration: 100,\n      description: 'vital',\n    },\n  },\n] as const\n\ntest.describe('onRumStart', () => {\n  for (const partialEvent of mockPartialEvents) {\n    createTest(`addEvent can send ${partialEvent.type} events`)\n      .withRum({ plugins: [createPlugin()] })\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        const startClocks = clocksNow()\n        const eventType = partialEvent.type\n\n        await page.evaluate(\n          ({ startClocks, event }) => {\n            window.TEST_PLUGIN.addEvent?.(startClocks.relative, event, {})\n          },\n          { startClocks, event: partialEvent }\n        )\n        await flushEvents()\n        const event = intakeRegistry.rumEvents.filter(\n          (e) => e.type === partialEvent.type && (e as any)[eventType]?.id === (partialEvent as any)[eventType].id\n        )\n        expect(event.length).toBe(1)\n        expect((event[0] as any)[eventType].id).toBe((partialEvent as any)[eventType].id)\n      })\n  }\n\n  createTest('addEvent cannot send view events')\n    .withRum({ plugins: [createPlugin()] })\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      const startClocks = clocksNow()\n      const uuid = generateUUID()\n\n      await page.evaluate(\n        ({ startClocks, uuid }) => {\n          window.TEST_PLUGIN.addEvent?.(\n            startClocks.relative,\n            {\n              type: 'view',\n              date: startClocks.timeStamp,\n              view: {\n                id: uuid,\n                name: 'TrackedPage',\n              },\n            } as unknown as AllowedRawRumEvent,\n            {}\n          )\n        },\n        { startClocks, uuid }\n      )\n      await flushEvents()\n\n      const viewEvents = intakeRegistry.rumViewEvents\n\n      expect(viewEvents.some((v) => v.view.id === uuid)).toBe(false)\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/plugins/reactPlugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\nimport { runBasePluginErrorTests } from './basePluginErrorTests'\nimport { runBasePluginRouterTests } from './basePluginRouterTests'\n\nconst reactApps = [\n  { appName: 'react-router-v6-app', description: 'React Router v6' },\n  { appName: 'react-router-v7-app', description: 'React Router v7' },\n]\n\nconst reactPluginApps = reactApps.map(({ appName, description }) => ({\n  name: `with ${description}`,\n  loadApp: (b: ReturnType<typeof createTest>) => b.withApp(appName),\n  viewPrefix: '',\n}))\n\nrunBasePluginRouterTests(\n  reactPluginApps.map(({ name, loadApp, viewPrefix }) => ({\n    name,\n    loadApp,\n    viewPrefix,\n    router: {\n      homeViewName: '/',\n      homeUrlPattern: '**/',\n      userRouteName: '/user/:id',\n      guidesRouteName: '/guides/:slug',\n    },\n  }))\n)\n\nrunBasePluginErrorTests(\n  reactPluginApps.map(({ name, loadApp, viewPrefix }) => ({\n    name,\n    loadApp,\n    viewPrefix,\n    error: {\n      clientErrorMessage: 'Error triggered by button click',\n      expectedFramework: 'react',\n      expectsBrowserConsoleErrors: true,\n      expectsComponentStack: true,\n    },\n  }))\n)\n\ntest.describe('plugin: react', () => {\n  for (const { appName, description } of reactApps) {\n    test.describe(`with ${description}`, () => {\n      createTest('should send a react component render vital event')\n        .withRum()\n        .withApp(appName)\n        .run(async ({ flushEvents, intakeRegistry, page }) => {\n          await page.click('text=Go to Tracked')\n\n          await flushEvents()\n          const vitalEvents = intakeRegistry.rumVitalEvents[0]\n          expect(vitalEvents.vital.description).toBe('TrackedPage')\n          expect(vitalEvents.vital.duration).toEqual(expect.any(Number))\n        })\n\n      createTest('should substitute splat routes with the actual matched path')\n        .withRum()\n        .withApp(appName)\n        .run(async ({ page, flushEvents, intakeRegistry }) => {\n          await page.click('text=Go to Wildcard')\n          await page.waitForURL('**/wildcard/foo/bar')\n\n          await flushEvents()\n\n          const wildcardView = intakeRegistry.rumViewEvents.find((e) => e.view.url?.includes('/wildcard/foo/bar'))\n          expect(wildcardView).toBeDefined()\n          expect(wildcardView?.view.name).toBe('/wildcard/foo/bar')\n        })\n\n      createTest('should capture react error from error boundary')\n        .withRum()\n        .withApp(appName)\n        .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {\n          await page.click('text=Go to Error Test')\n          await page.waitForURL('**/error-test')\n          await page.click('[data-testid=\"trigger-error\"]')\n          await page.waitForSelector('[data-testid=\"error-handled\"]')\n\n          await flushEvents()\n\n          const errorEvent = intakeRegistry.rumErrorEvents.find(\n            (e) => e.error.source === 'custom' && e.error.message === 'Error triggered by button click'\n          )\n          expect(errorEvent).toBeDefined()\n          expect(errorEvent?.error.stack).toBeDefined()\n          expect(errorEvent?.context?.framework).toBe('react')\n          expect(errorEvent?.error.component_stack).toBeDefined()\n\n          withBrowserLogs((browserLogs) => {\n            expect(browserLogs.filter((log) => log.level === 'error').length).toBeGreaterThan(0)\n          })\n        })\n    })\n  }\n})\n"
  },
  {
    "path": "test/e2e/scenario/plugins/vuePlugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\nimport { runBasePluginErrorTests } from './basePluginErrorTests'\nimport { runBasePluginRouterTests } from './basePluginRouterTests'\n\nconst vueBasePluginConfig = {\n  name: 'vue',\n  loadApp: (b: ReturnType<typeof createTest>) => b.withVueApp(),\n  viewPrefix: '',\n}\n\nrunBasePluginRouterTests([\n  {\n    ...vueBasePluginConfig,\n    router: {\n      homeViewName: '/',\n      homeUrlPattern: '**/',\n      userRouteName: '/user/:id',\n      guidesRouteName: '/guides/:catchAll(.*)*',\n    },\n  },\n])\n\nrunBasePluginErrorTests([\n  {\n    ...vueBasePluginConfig,\n    error: {\n      clientErrorMessage: 'Error triggered by button click',\n      expectedFramework: 'vue',\n      expectsComponentStack: true,\n    },\n  },\n])\n\ntest.describe('plugin: vue', () => {\n  createTest('should capture vue error from app.config.errorHandler')\n    .withRum()\n    .withVueApp()\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Go to Error Test')\n      await page.click('[data-testid=\"trigger-error\"]')\n\n      await flushEvents()\n\n      expect(intakeRegistry.rumErrorEvents.length).toBeGreaterThan(0)\n      const errorEvent = intakeRegistry.rumErrorEvents[intakeRegistry.rumErrorEvents.length - 1]\n\n      expect(errorEvent.error.message).toBe('Error triggered by button click')\n      expect(errorEvent.error.source).toBe('custom')\n      expect(errorEvent.error.stack).toBeDefined()\n      expect(errorEvent.context?.framework).toBe('vue')\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/profiling.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport type { Page } from '@playwright/test'\nimport { createTest } from '../lib/framework'\n\ntest.describe('profiling', () => {\n  test.beforeEach(({ browserName }) => {\n    test.skip(browserName !== 'chromium', 'JS Profiling API is only available in Chromium')\n  })\n\n  createTest('send profile events when profiling is enabled')\n    .withRum({ profilingSampleRate: 100, trackUserInteractions: true })\n    .withBasePath('/?js-profiling=true')\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await generateLongTask(page)\n      await generateAction(page)\n      await generateVital(page)\n\n      await flushEvents()\n\n      expect(intakeRegistry.profileRequests).toHaveLength(1)\n\n      // Extract RUM event IDs for verification\n      const viewIds = intakeRegistry.rumViewEvents.map((event) => event.view.id)\n      const longTaskIds = intakeRegistry.rumLongTaskEvents.map((event) => event.long_task.id)\n      const actionIds = intakeRegistry.rumActionEvents.map((event) => event.action.id)\n      const vitalIds = intakeRegistry.rumVitalEvents.map((event) => event.vital.id)\n\n      const profileEvent = intakeRegistry.profileEvents[0]\n\n      // Verify complete structure\n      expect(profileEvent).toEqual({\n        application: {\n          id: expect.any(String),\n        },\n        session: {\n          id: expect.any(String),\n        },\n        view: {\n          id: viewIds,\n          name: ['/'],\n        },\n        long_task: {\n          id: expect.arrayOf(expect.any(String)),\n        },\n        action: {\n          id: expect.arrayOf(expect.any(String)),\n          label: expect.arrayOf(expect.any(String)),\n        },\n        vital: {\n          id: expect.arrayOf(expect.any(String)),\n          label: expect.arrayOf(expect.any(String)),\n        },\n        attachments: ['wall-time.json'],\n        start: expect.any(String), // ISO 8601 date string\n        end: expect.any(String), // ISO 8601 date string\n        family: 'chrome',\n        runtime: 'chrome',\n        format: 'json',\n        version: 4,\n        tags_profiler: 'sdk_version:dev,language:javascript,runtime:chrome,family:chrome,host:browser',\n        _dd: {\n          clock_drift: expect.any(Number),\n        },\n      })\n\n      // Verify profile event long tasks are a subset of RUM long tasks\n      for (const profileLongTaskId of profileEvent.long_task!.id) {\n        expect(longTaskIds).toContain(profileLongTaskId)\n      }\n\n      // Verify wall-time.json trace data\n      const profileRequest = intakeRegistry.profileRequests[0]\n\n      // Verify trace file metadata\n      expect(profileRequest.traceFile.encoding).toBe(null)\n      expect(profileRequest.traceFile.filename).toBe('wall-time.json')\n\n      expect(profileRequest.trace).toEqual({\n        resources: expect.any(Array),\n        frames: expect.any(Array),\n        stacks: expect.any(Array),\n        samples: expect.any(Array),\n        startClocks: {\n          relative: expect.any(Number),\n          timeStamp: expect.any(Number),\n        },\n        endClocks: {\n          relative: expect.any(Number),\n          timeStamp: expect.any(Number),\n        },\n        clocksOrigin: {\n          relative: expect.any(Number),\n          timeStamp: expect.any(Number),\n        },\n        sampleInterval: expect.any(Number),\n        longTasks: profileEvent.long_task!.id.map((id) => ({\n          duration: expect.any(Number),\n          entryType: expect.stringMatching(/^(long-animation-frame|longtask)$/),\n          id,\n          startClocks: {\n            relative: expect.any(Number),\n            timeStamp: expect.any(Number),\n          },\n        })),\n        actions: actionIds.map((actionId) => ({\n          id: actionId,\n          label: expect.any(String),\n          startClocks: {\n            relative: expect.any(Number),\n            timeStamp: expect.any(Number),\n          },\n        })),\n        vitals: vitalIds.map((vitalId) => ({\n          duration: expect.any(Number),\n          id: vitalId,\n          label: expect.any(String),\n          startClocks: {\n            relative: expect.any(Number),\n            timeStamp: expect.any(Number),\n          },\n        })),\n        views: viewIds.map((viewId) => ({\n          startClocks: {\n            relative: expect.any(Number),\n            timeStamp: expect.any(Number),\n          },\n          viewId,\n          viewName: '/',\n        })),\n      })\n\n      // Verify we collected some samples\n      expect(profileRequest.trace.samples.length).toBeGreaterThan(0)\n    })\n\n  createTest('send compressed profile events when compressIntakeRequests is enabled')\n    .withRum({ profilingSampleRate: 100, compressIntakeRequests: true })\n    .withBasePath('/?js-profiling=true')\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await generateLongTask(page)\n\n      await flushEvents()\n\n      expect(intakeRegistry.profileRequests).toHaveLength(1)\n\n      const profileRequest = intakeRegistry.profileRequests[0]\n\n      expect(profileRequest.traceFile.encoding).toBe('deflate')\n      expect(profileRequest.traceFile.filename).toBe('wall-time.json')\n\n      expect(profileRequest.event).toBeDefined()\n      expect(profileRequest.trace).toBeDefined()\n      expect(profileRequest.trace.samples.length).toBeGreaterThan(0)\n    })\n\n  createTest('display console warning when Document-Policy header is missing')\n    .withRum({ profilingSampleRate: 100 })\n    .run(async ({ intakeRegistry, flushEvents, withBrowserLogs }) => {\n      await flushEvents()\n\n      expect(intakeRegistry.profileRequests).toHaveLength(0)\n\n      withBrowserLogs((browserLogs) => {\n        const profilingWarnings = browserLogs.filter((log) =>\n          log.message.includes(\n            'Datadog Browser SDK: [DD_RUM] Profiler startup failed. Ensure your server includes the `Document-Policy: js-profiling` response header when serving HTML pages'\n          )\n        )\n        expect(profilingWarnings.length).toBeGreaterThan(0)\n      })\n    })\n\n  createTest('do not send profile events when profiling is not enabled')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await generateLongTask(page)\n\n      await flushEvents()\n\n      expect(intakeRegistry.profileRequests).toHaveLength(0)\n    })\n})\n\nasync function generateLongTask(page: Page, durationMs = 500) {\n  await page.evaluate(\n    (duration) =>\n      new Promise<void>((resolve) => {\n        setTimeout(() => {\n          const start = Date.now()\n          while (Date.now() - start < duration) {\n            /* empty */\n          }\n          resolve()\n        })\n      }),\n    durationMs\n  )\n}\n\nasync function generateAction(page: Page) {\n  await page.evaluate(() => window.DD_RUM!.addAction('testAction'))\n}\n\nasync function generateVital(page: Page, durationMs = 50) {\n  await page.evaluate(\n    (duration) => window.DD_RUM!.addDurationVital('testVitals', { startTime: Date.now() - duration, duration }),\n    durationMs\n  )\n}\n"
  },
  {
    "path": "test/e2e/scenario/recorder/recorder.scenario.ts",
    "content": "import type { InputData, StyleSheetRuleData, ScrollData } from '@datadog/browser-rum/src/types'\nimport { NodeType, IncrementalSource, SnapshotFormat, ChangeType, RecordType } from '@datadog/browser-rum/src/types'\n\nimport { DefaultPrivacyLevel } from '@datadog/browser-core'\n\nimport { decodeChangeRecords, findChangeRecords } from '@datadog/browser-rum/test/record/changes'\nimport {\n  getElementIdsFromFullSnapshot,\n  getScrollPositionsFromFullSnapshot,\n} from '@datadog/browser-rum/test/record/elements'\nimport { findElement, findElementWithIdAttribute, findTextContent } from '@datadog/browser-rum/test/record/nodes'\nimport {\n  findFullSnapshot,\n  findIncrementalSnapshot,\n  findAllIncrementalSnapshots,\n  findMeta,\n  findFullSnapshotInFormat,\n} from '@datadog/browser-rum/test/record/segments'\nimport { createMutationPayloadValidatorFromSegment } from '@datadog/browser-rum/test/record/mutationPayloadValidator'\nimport { test, expect } from '@playwright/test'\nimport { wait } from '@datadog/browser-core/test/wait'\nimport { createTest, html } from '../../lib/framework'\n\nconst UUID_RE = /^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/\n\ntest.describe('recorder', () => {\n  createTest('record mouse move')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => document.documentElement.outerHTML)\n      await page.locator('html').click()\n      await flushEvents()\n\n      expect(intakeRegistry.replaySegments).toHaveLength(1)\n      const {\n        segment,\n        metadata,\n        segmentFile: { encoding, filename, mimetype },\n      } = intakeRegistry.replayRequests[0]\n      expect(metadata).toEqual({\n        application: { id: expect.stringMatching(UUID_RE) },\n        creation_reason: 'init',\n        end: expect.any(Number),\n        has_full_snapshot: true,\n        records_count: expect.any(Number),\n        session: { id: expect.stringMatching(UUID_RE) },\n        start: expect.any(Number),\n        view: { id: expect.stringMatching(UUID_RE) },\n        raw_segment_size: expect.any(Number),\n        compressed_segment_size: expect.any(Number),\n        index_in_view: 0,\n        source: 'browser',\n      })\n      expect(segment).toEqual({\n        application: { id: metadata.application.id },\n        creation_reason: metadata.creation_reason,\n        end: Number(metadata.end),\n        has_full_snapshot: true,\n        records: expect.any(Array),\n        records_count: Number(metadata.records_count),\n        session: { id: metadata.session.id },\n        start: Number(metadata.start),\n        view: { id: metadata.view.id },\n        index_in_view: 0,\n        source: 'browser',\n      })\n      expect(encoding).toEqual(expect.any(String))\n      expect(filename).toBe(`${metadata.session.id}-${metadata.start}`)\n      expect(mimetype).toBe('application/octet-stream')\n\n      expect(findMeta(segment), 'have a Meta record').toBeTruthy()\n      expect(findFullSnapshot(segment), 'have a FullSnapshot record').toBeTruthy()\n      expect(\n        findIncrementalSnapshot(segment, IncrementalSource.MouseInteraction),\n        'have a IncrementalSnapshot/MouseInteraction record'\n      ).toBeTruthy()\n    })\n\n  test.describe('full snapshot', () => {\n    test.describe('obfuscate elements', () => {\n      const body = html`<div id=\"not-obfuscated\">displayed</div>\n        <p id=\"hidden-by-attribute\" data-dd-privacy=\"hidden\">hidden</p>\n        <span id=\"hidden-by-classname\" class=\"dd-privacy-hidden\">hidden</span>\n        <input id=\"input-not-obfuscated\" value=\"displayed\" />\n        <input id=\"input-masked\" data-dd-privacy=\"mask\" value=\"masked\" />`\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n\n          expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n          const fullSnapshot = findFullSnapshotInFormat(SnapshotFormat.V1, intakeRegistry.replaySegments[0])!\n\n          const node = findElementWithIdAttribute(fullSnapshot.data.node, 'not-obfuscated')\n          expect(node).toBeTruthy()\n          expect(findTextContent(node!)).toBe('displayed')\n\n          const hiddenNodeByAttribute = findElement(fullSnapshot.data.node, (node) => node.tagName === 'p')\n          expect(hiddenNodeByAttribute).toBeTruthy()\n          expect(hiddenNodeByAttribute!.attributes['data-dd-privacy']).toBe('hidden')\n          expect(hiddenNodeByAttribute!.childNodes).toHaveLength(0)\n\n          const hiddenNodeByClassName = findElement(fullSnapshot.data.node, (node) => node.tagName === 'span')\n          expect(hiddenNodeByClassName).toBeTruthy()\n          expect(hiddenNodeByClassName!.attributes.class).toBeUndefined()\n          expect(hiddenNodeByClassName!.attributes['data-dd-privacy']).toBe('hidden')\n          expect(hiddenNodeByClassName!.childNodes).toHaveLength(0)\n\n          const inputIgnored = findElementWithIdAttribute(fullSnapshot.data.node, 'input-not-obfuscated')\n          expect(inputIgnored).toBeTruthy()\n          expect(inputIgnored!.attributes.value).toBe('displayed')\n\n          const inputMasked = findElementWithIdAttribute(fullSnapshot.data.node, 'input-masked')\n          expect(inputMasked).toBeTruthy()\n          expect(inputMasked!.attributes.value).toBe('***')\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, flushEvents }) => {\n          await flushEvents()\n          expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(0)!.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [null, '#document'],\n              [1, '#doctype', 'html', '', ''],\n              [0, 'HTML'],\n              [1, 'HEAD'],\n              [0, 'BODY'],\n              [1, 'DIV', ['id', 'not-obfuscated']],\n              [1, '#text', 'displayed'],\n              [3, '#text', '\\n        '],\n              [0, 'P', ['data-dd-privacy', 'hidden']],\n              [0, '#text', '\\n        '],\n              [0, 'SPAN', ['data-dd-privacy', 'hidden']],\n              [0, '#text', '\\n        '],\n              [0, 'INPUT', ['id', 'input-not-obfuscated'], ['value', 'displayed']],\n              [0, '#text', '\\n        '],\n              [0, 'INPUT', ['id', 'input-masked'], ['data-dd-privacy', 'mask'], ['value', '***']],\n            ],\n            [\n              ChangeType.Size,\n              [8, expect.any(Number), expect.any(Number)],\n              [10, expect.any(Number), expect.any(Number)],\n            ],\n            [ChangeType.ScrollPosition, [0, 0, 0]],\n          ])\n        })\n    })\n  })\n\n  test.describe('mutations observer', () => {\n    const body = html`\n      <p>mutation observer</p>\n      <ul>\n        <li></li>\n      </ul>\n    `\n\n    test.describe('record mutations', () => {\n      const mutate = () => {\n        const li = document.createElement('li')\n        const ul = document.querySelector('ul') as HTMLUListElement\n\n        // Make sure mutations occurring in a removed element are not reported\n        ul.appendChild(li)\n        document.body.removeChild(ul)\n\n        const p = document.querySelector('p') as HTMLParagraphElement\n        p.appendChild(document.createElement('span'))\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidatorFromSegment(\n            intakeRegistry.replaySegments[0],\n            { expect }\n          )\n\n          validate({\n            adds: [\n              {\n                parent: expectInitialNode({ tag: 'p' }),\n                node: expectNewNode({ type: NodeType.Element, tagName: 'span' }),\n              },\n            ],\n            removes: [\n              {\n                parent: expectInitialNode({ tag: 'body' }),\n                node: expectInitialNode({ tag: 'ul' }),\n              },\n            ],\n          })\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n            [ChangeType.AddNode, [8, 'SPAN']],\n            [ChangeType.RemoveNode, 9],\n          ])\n        })\n    })\n\n    test.describe('record character data mutations', () => {\n      const mutate = () => {\n        const li = document.createElement('li')\n        const ul = document.querySelector('ul') as HTMLUListElement\n\n        // Make sure mutations occurring in a removed element are not reported\n        ul.appendChild(li)\n        li.innerText = 'new list item'\n        li.innerText = 'new list item edit'\n        document.body.removeChild(ul)\n\n        const p = document.querySelector('p') as HTMLParagraphElement\n        p.innerText = 'mutated'\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const { validate, expectNewNode, expectInitialNode } = createMutationPayloadValidatorFromSegment(\n            intakeRegistry.replaySegments[0],\n            { expect }\n          )\n\n          validate({\n            adds: [\n              {\n                parent: expectInitialNode({ tag: 'p' }),\n                node: expectNewNode({ type: NodeType.Text, textContent: 'mutated' }),\n              },\n            ],\n            removes: [\n              {\n                parent: expectInitialNode({ tag: 'body' }),\n                node: expectInitialNode({ tag: 'ul' }),\n              },\n              {\n                parent: expectInitialNode({ tag: 'p' }),\n                node: expectInitialNode({ text: 'mutation observer' }),\n              },\n            ],\n          })\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n            [ChangeType.AddNode, [8, '#text', 'mutated']],\n            [ChangeType.RemoveNode, 9, 7],\n          ])\n        })\n    })\n\n    test.describe('record attributes mutations', () => {\n      const mutate = () => {\n        const li = document.createElement('li')\n        const ul = document.querySelector('ul') as HTMLUListElement\n\n        // Make sure mutations occurring in a removed element are not reported\n        ul.appendChild(li)\n        li.setAttribute('foo', 'bar')\n        document.body.removeChild(ul)\n\n        document.body.setAttribute('test', 'true')\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const { validate, expectInitialNode } = createMutationPayloadValidatorFromSegment(\n            intakeRegistry.replaySegments[0],\n            { expect }\n          )\n\n          validate({\n            attributes: [\n              {\n                node: expectInitialNode({ tag: 'body' }),\n                attributes: { test: 'true' },\n              },\n            ],\n            removes: [\n              {\n                parent: expectInitialNode({ tag: 'body' }),\n                node: expectInitialNode({ tag: 'ul' }),\n              },\n            ],\n          })\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n            [ChangeType.RemoveNode, 9],\n            [ChangeType.Attribute, [4, ['test', 'true']]],\n          ])\n        })\n    })\n\n    test.describe(\"don't record hidden elements mutations\", () => {\n      const hiddenBody = html`\n        <div data-dd-privacy=\"hidden\">\n          <ul>\n            <li></li>\n          </ul>\n        </div>\n      `\n\n      const mutate = () => {\n        document.querySelector('div')!.setAttribute('foo', 'bar')\n        document.querySelector('li')!.textContent = 'hop'\n        document.querySelector('div')!.appendChild(document.createElement('p'))\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(hiddenBody)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          expect(intakeRegistry.replaySegments).toHaveLength(1)\n          const segment = intakeRegistry.replaySegments[0]\n          expect(findAllIncrementalSnapshots(segment, IncrementalSource.Mutation)).toHaveLength(0)\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(hiddenBody)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          expect(intakeRegistry.replaySegments).toHaveLength(1)\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(records).toHaveLength(1)\n          expect(records[0].type === RecordType.FullSnapshot)\n        })\n    })\n\n    test.describe('record DOM node movement 1', () => {\n      // prettier-ignore\n      const body = html`\n        <div>a<p></p>b</div>\n        <span>c<i>d<b>e</b>f</i>g</span>\n      `\n\n      const mutate = () => {\n        const div = document.querySelector('div')!\n        const p = document.querySelector('p')!\n        const span = document.querySelector('span')!\n        document.body.removeChild(span)\n        p.appendChild(span)\n        p.removeChild(span)\n        div.appendChild(span)\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const { validate, expectInitialNode } = createMutationPayloadValidatorFromSegment(\n            intakeRegistry.replaySegments[0],\n            { expect }\n          )\n          validate({\n            adds: [\n              {\n                parent: expectInitialNode({ tag: 'div' }),\n                node: expectInitialNode({ tag: 'span' }).withChildren(\n                  expectInitialNode({ text: 'c' }),\n                  expectInitialNode({ tag: 'i' }).withChildren(\n                    expectInitialNode({ text: 'd' }),\n                    expectInitialNode({ tag: 'b' }).withChildren(expectInitialNode({ text: 'e' })),\n                    expectInitialNode({ text: 'f' })\n                  ),\n                  expectInitialNode({ text: 'g' })\n                ),\n              },\n            ],\n            removes: [\n              {\n                parent: expectInitialNode({ tag: 'body' }),\n                node: expectInitialNode({ tag: 'span' }),\n              },\n            ],\n          })\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [14, 'SPAN'],\n              [1, '#text', 'c'],\n              [0, 'I'],\n              [1, '#text', 'd'],\n              [0, 'B'],\n              [1, '#text', 'e'],\n              [4, '#text', 'f'],\n              [7, '#text', 'g'],\n            ],\n            [ChangeType.RemoveNode, 11],\n          ])\n        })\n    })\n\n    test.describe('record DOM node movement 2', () => {\n      // prettier-ignore\n      const body = html`\n        <span>c<i>d<b>e</b>f</i>g</span>\n      `\n\n      const mutate = () => {\n        const div = document.createElement('div')\n        const span = document.querySelector('span')!\n        document.body.appendChild(div)\n        div.appendChild(span)\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidatorFromSegment(\n            intakeRegistry.replaySegments[0],\n            { expect }\n          )\n\n          const div = expectNewNode({ type: NodeType.Element, tagName: 'div' })\n\n          validate({\n            adds: [\n              {\n                parent: expectInitialNode({ tag: 'body' }),\n                node: div.withChildren(\n                  expectInitialNode({ tag: 'span' }).withChildren(\n                    expectInitialNode({ text: 'c' }),\n                    expectInitialNode({ tag: 'i' }).withChildren(\n                      expectInitialNode({ text: 'd' }),\n                      expectInitialNode({ tag: 'b' }).withChildren(expectInitialNode({ text: 'e' })),\n                      expectInitialNode({ text: 'f' })\n                    ),\n                    expectInitialNode({ text: 'g' })\n                  )\n                ),\n              },\n            ],\n            removes: [\n              {\n                parent: expectInitialNode({ tag: 'body' }),\n                node: expectInitialNode({ tag: 'span' }),\n              },\n            ],\n          })\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n            [\n              ChangeType.AddNode,\n              [11, 'DIV'],\n              [1, 'SPAN'],\n              [1, '#text', 'c'],\n              [0, 'I'],\n              [1, '#text', 'd'],\n              [0, 'B'],\n              [1, '#text', 'e'],\n              [4, '#text', 'f'],\n              [7, '#text', 'g'],\n            ],\n            [ChangeType.RemoveNode, 6],\n          ])\n        })\n    })\n\n    test.describe('serialize node before record', () => {\n      // prettier-ignore\n      const body = html`\n        <ul><li></li></ul>\n      `\n\n      const mutate = () => {\n        const ul = document.querySelector('ul') as HTMLUListElement\n        let count = 3\n        while (count > 0) {\n          count--\n          const li = document.createElement('li')\n          ul.appendChild(li)\n        }\n      }\n\n      createTest('V1')\n        .withRum()\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidatorFromSegment(\n            intakeRegistry.replaySegments[0],\n            { expect }\n          )\n\n          const ul = expectInitialNode({ tag: 'ul' })\n          const li1 = expectNewNode({ type: NodeType.Element, tagName: 'li' })\n          const li2 = expectNewNode({ type: NodeType.Element, tagName: 'li' })\n          const li3 = expectNewNode({ type: NodeType.Element, tagName: 'li' })\n\n          validate({\n            adds: [\n              {\n                parent: ul,\n                node: li1,\n              },\n              {\n                next: li1,\n                parent: ul,\n                node: li2,\n              },\n              {\n                next: li2,\n                parent: ul,\n                node: li3,\n              },\n            ],\n          })\n        })\n\n      createTest('Change')\n        .withRum({\n          enableExperimentalFeatures: ['use_incremental_change_records'],\n        })\n        .withBody(body)\n        .run(async ({ intakeRegistry, page, flushEvents }) => {\n          await page.evaluate(mutate)\n          await flushEvents()\n\n          const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n          expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n            [ChangeType.AddNode, [3, 'LI'], [4, 'LI'], [5, 'LI']],\n          ])\n        })\n    })\n  })\n\n  test.describe('input observers', () => {\n    test.describe('record input interactions', () => {\n      function createTestVariation(name: string, enableExperimentalFeatures: string[]): void {\n        createTest(name)\n          .withRum({\n            defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n            enableExperimentalFeatures,\n          })\n          .withBody(html`\n            <form>\n              <label for=\"text\">\n                <input type=\"text\" id=\"text-input\" />\n              </label>\n              <label for=\"radio\">\n                <input type=\"radio\" id=\"radio-input\" />\n              </label>\n              <label for=\"checkbox\">\n                <input type=\"checkbox\" id=\"checkbox-input\" />\n              </label>\n              <label for=\"textarea\">\n                <textarea name=\"\" id=\"textarea\" cols=\"30\" rows=\"10\"></textarea>\n              </label>\n              <label for=\"select\">\n                <select name=\"\" id=\"select\">\n                  <option value=\"1\">1</option>\n                  <option value=\"2\">2</option>\n                </select>\n              </label>\n            </form>\n          `)\n          .run(async ({ intakeRegistry, page, flushEvents }) => {\n            const textInput = page.locator('#text-input')\n            await textInput.pressSequentially('test')\n\n            const radioInput = page.locator('#radio-input')\n            await radioInput.click()\n\n            const checkboxInput = page.locator('#checkbox-input')\n            await checkboxInput.click()\n\n            const textarea = page.locator('#textarea')\n            await textarea.pressSequentially('textarea test')\n\n            const select = page.locator('#select')\n            await select.selectOption({ value: '2' })\n\n            await flushEvents()\n\n            const fullSnapshot = findFullSnapshot({ records: intakeRegistry.replayRecords })!\n            const elementIds = getElementIdsFromFullSnapshot(fullSnapshot)\n\n            const textInputRecords = filterRecordsByIdAttribute('text-input')\n            expect(textInputRecords.length).toBeGreaterThanOrEqual(4)\n            expect((textInputRecords[textInputRecords.length - 1].data as { text?: string }).text).toBe('test')\n\n            const radioInputRecords = filterRecordsByIdAttribute('radio-input')\n            expect(radioInputRecords).toHaveLength(1)\n            expect((radioInputRecords[0].data as { text?: string }).text).toBe(undefined)\n            expect((radioInputRecords[0].data as { isChecked?: boolean }).isChecked).toBe(true)\n\n            const checkboxInputRecords = filterRecordsByIdAttribute('checkbox-input')\n            expect(checkboxInputRecords).toHaveLength(1)\n            expect((checkboxInputRecords[0].data as { text?: string }).text).toBe(undefined)\n            expect((checkboxInputRecords[0].data as { isChecked?: boolean }).isChecked).toBe(true)\n\n            const textareaRecords = filterRecordsByIdAttribute('textarea')\n            expect(textareaRecords.length).toBeGreaterThanOrEqual(4)\n            expect((textareaRecords[textareaRecords.length - 1].data as { text?: string }).text).toBe('textarea test')\n\n            const selectRecords = filterRecordsByIdAttribute('select')\n            expect(selectRecords).toHaveLength(1)\n            expect((selectRecords[0].data as { text?: string }).text).toBe('2')\n\n            function filterRecordsByIdAttribute(idAttribute: string) {\n              const id = elementIds.get(idAttribute)\n              const records = findAllIncrementalSnapshots(\n                { records: intakeRegistry.replayRecords },\n                IncrementalSource.Input\n              ) as Array<{ data: InputData }>\n              return records.filter((record) => record.data.id === id)\n            }\n          })\n      }\n\n      createTestVariation('V1', [])\n      createTestVariation('Change', ['use_incremental_change_records'])\n    })\n\n    createTest(\"don't record ignored input interactions\")\n      .withRum({\n        defaultPrivacyLevel: DefaultPrivacyLevel.ALLOW,\n      })\n      .withBody(html`\n        <input type=\"text\" id=\"first\" name=\"first\" />\n        <input type=\"text\" id=\"second\" name=\"second\" data-dd-privacy=\"input-ignored\" />\n        <input type=\"text\" id=\"third\" name=\"third\" class=\"dd-privacy-input-ignored\" />\n        <input type=\"password\" id=\"fourth\" name=\"fourth\" />\n      `)\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        const firstInput = page.locator('#first')\n        await firstInput.fill('foo')\n\n        const secondInput = page.locator('#second')\n        await secondInput.fill('bar')\n\n        const thirdInput = page.locator('#third')\n        await thirdInput.fill('baz')\n\n        const fourthInput = page.locator('#fourth')\n        await fourthInput.fill('quux')\n\n        await flushEvents()\n\n        const inputRecords = findAllIncrementalSnapshots(\n          { records: intakeRegistry.replayRecords },\n          IncrementalSource.Input\n        )\n\n        expect(inputRecords.length).toBeGreaterThanOrEqual(3) // 4 on Safari, 3 on others\n        expect((inputRecords[inputRecords.length - 1].data as { text?: string }).text).toBe('***')\n      })\n\n    createTest('replace masked values by asterisks')\n      .withRum()\n      .withBody(html`\n        <input type=\"text\" id=\"by-data-attribute\" data-dd-privacy=\"mask\" />\n        <input type=\"text\" id=\"by-classname\" class=\"dd-privacy-mask\" />\n      `)\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        const firstInput = page.locator('#by-data-attribute')\n        await firstInput.fill('foo')\n\n        const secondInput = page.locator('#by-classname')\n        await secondInput.fill('bar')\n\n        await flushEvents()\n\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const segment = intakeRegistry.replaySegments[0]\n\n        const inputRecords = findAllIncrementalSnapshots(segment, IncrementalSource.Input)\n\n        expect(inputRecords.length).toBeGreaterThan(0)\n\n        expect(inputRecords.every((inputRecord) => /^\\**$/.test((inputRecord.data as { text: string }).text))).toBe(\n          true\n        )\n      })\n  })\n\n  test.describe('stylesheet rules observer', () => {\n    createTest('record dynamic CSS changes')\n      .withRum()\n      .withBody(html`\n        <style>\n          .foo {\n          }\n          .bar {\n          }\n        </style>\n      `)\n      .run(async ({ intakeRegistry, page, flushEvents }) => {\n        await page.evaluate(() => {\n          document.styleSheets[0].deleteRule(0)\n          document.styleSheets[0].insertRule('.added {}', 0)\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const segment = intakeRegistry.replaySegments[0]\n\n        const styleSheetRules = findAllIncrementalSnapshots(segment, IncrementalSource.StyleSheetRule) as Array<{\n          data: StyleSheetRuleData\n        }>\n\n        expect(styleSheetRules).toHaveLength(2)\n        expect(styleSheetRules[0].data.removes).toEqual([{ index: 0 }])\n        expect(styleSheetRules[1].data.adds).toEqual([{ rule: '.added {}', index: 0 }])\n      })\n\n    createTest('record nested css rules changes')\n      .withRum()\n      .withBody(html`\n        <style>\n          @supports (display: grid) {\n            .foo {\n            }\n          }\n          @media condition {\n            .bar {\n            }\n            .baz {\n            }\n          }\n        </style>\n      `)\n      .run(async ({ intakeRegistry, page, flushEvents }) => {\n        await page.evaluate(() => {\n          const supportsRule = document.styleSheets[0].cssRules[0] as CSSGroupingRule\n          const mediaRule = document.styleSheets[0].cssRules[1] as CSSGroupingRule\n\n          supportsRule.insertRule('.inserted {}', 0)\n          supportsRule.insertRule('.added {}', 1)\n          mediaRule.deleteRule(1)\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const segment = intakeRegistry.replaySegments[0]\n\n        const styleSheetRules = findAllIncrementalSnapshots(segment, IncrementalSource.StyleSheetRule) as Array<{\n          data: StyleSheetRuleData\n        }>\n\n        expect(styleSheetRules).toHaveLength(3)\n        expect(styleSheetRules[0].data.adds).toEqual([{ rule: '.inserted {}', index: [0, 0] }])\n        expect(styleSheetRules[1].data.adds).toEqual([{ rule: '.added {}', index: [0, 1] }])\n        expect(styleSheetRules[2].data.removes).toEqual([{ index: [1, 1] }])\n      })\n  })\n\n  test.describe('scroll positions', () => {\n    test.describe('should be recorded across view changes', () => {\n      function createTestVariation(name: string, enableExperimentalFeatures: string[]): void {\n        createTest(name)\n          .withRum({\n            enableExperimentalFeatures,\n            // to control initial position before recording\n            startSessionReplayRecordingManually: true,\n          })\n          .withBody(html`\n            <style>\n              #container {\n                width: 100px;\n                height: 100px;\n                overflow-x: scroll;\n              }\n              #content {\n                width: 250px;\n              }\n              #big-element {\n                height: 4000px;\n              }\n            </style>\n            <div id=\"container\">\n              <div id=\"content\">I'm bigger than the container</div>\n            </div>\n            <div id=\"big-element\"></div>\n          `)\n          .run(async ({ intakeRegistry, page, flushEvents }) => {\n            function scroll({ windowY, containerX }: { windowY: number; containerX: number }) {\n              return page.evaluate(\n                ({ windowY, containerX }) =>\n                  new Promise<void>((resolve) => {\n                    let scrollCount = 0\n\n                    document.addEventListener(\n                      'scroll',\n                      () => {\n                        scrollCount++\n                        if (scrollCount === 2) {\n                          // ensure to bypass observer throttling\n                          setTimeout(resolve, 100)\n                        }\n                      },\n                      { capture: true, passive: true }\n                    )\n\n                    window.scrollTo(0, windowY)\n                    document.getElementById('container')!.scrollTo(containerX, 0)\n                  }),\n                { windowY, containerX }\n              )\n            }\n\n            await page.evaluate(() => {\n              document.getElementsByTagName('html')[0].setAttribute('id', 'html')\n            })\n\n            // initial scroll positions\n            await scroll({ windowY: 100, containerX: 10 })\n\n            await page.evaluate(() => {\n              window.DD_RUM!.startSessionReplayRecording()\n            })\n\n            // wait for recorder to be properly started\n            await wait(100)\n\n            // update scroll positions\n            await scroll({ windowY: 150, containerX: 20 })\n\n            // trigger new full snapshot\n            await page.evaluate(() => {\n              window.DD_RUM!.startView()\n            })\n\n            await flushEvents()\n\n            expect(intakeRegistry.replaySegments).toHaveLength(2)\n            const firstSegment = intakeRegistry.replaySegments[0]\n\n            {\n              const firstFullSnapshot = findFullSnapshot(firstSegment)!\n              const elementIds = getElementIdsFromFullSnapshot(firstFullSnapshot)\n              const scrollPositions = getScrollPositionsFromFullSnapshot(firstFullSnapshot)\n\n              const htmlId = elementIds.get('html')\n              expect(htmlId).not.toBeUndefined()\n              expect(scrollPositions.get(htmlId!)).toEqual({ left: 0, top: 100 })\n\n              const containerId = elementIds.get('container')\n              expect(containerId).not.toBeUndefined()\n              expect(scrollPositions.get(containerId!)).toEqual({ left: 10, top: 0 })\n\n              const scrollRecords = findAllIncrementalSnapshots(firstSegment, IncrementalSource.Scroll)\n              expect(scrollRecords).toHaveLength(2)\n              const [windowScrollData, containerScrollData] = scrollRecords.map((record) => record.data as ScrollData)\n              expect(windowScrollData.y).toEqual(150)\n              expect(containerScrollData.x).toEqual(20)\n            }\n\n            {\n              const secondFullSnapshot = findFullSnapshot(intakeRegistry.replaySegments.at(-1)!)!\n              const elementIds = getElementIdsFromFullSnapshot(secondFullSnapshot)\n              const scrollPositions = getScrollPositionsFromFullSnapshot(secondFullSnapshot)\n\n              const htmlId = elementIds.get('html')\n              expect(htmlId).not.toBeUndefined()\n              expect(scrollPositions.get(htmlId!)).toEqual({ left: 0, top: 150 })\n\n              const containerId = elementIds.get('container')\n              expect(containerId).not.toBeUndefined()\n              expect(scrollPositions.get(containerId!)).toEqual({ left: 20, top: 0 })\n            }\n          })\n      }\n\n      createTestVariation('V1', [])\n      createTestVariation('Change', ['use_incremental_change_records'])\n    })\n  })\n\n  test.describe('recording of sampled out sessions', () => {\n    createTest('should not start recording when session is sampled out')\n      .withRum({ sessionReplaySampleRate: 0 })\n      .run(async ({ intakeRegistry, page, flushEvents }) => {\n        await page.evaluate(() => {\n          window.DD_RUM!.startSessionReplayRecording()\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.replaySegments).toHaveLength(0)\n      })\n\n    createTest('should start recording if forced when session is sampled out')\n      .withRum({ sessionReplaySampleRate: 0 })\n      .run(async ({ intakeRegistry, page, flushEvents, browserContext }) => {\n        await page.evaluate(() => {\n          window.DD_RUM!.startSessionReplayRecording({ force: true })\n        })\n        const [cookie] = await browserContext.cookies()\n        expect(cookie.value).toContain('forcedReplay=1')\n\n        await flushEvents()\n\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n      })\n  })\n\n  createTest('restarting recording should send a new full snapshot')\n    .withRum()\n    .run(async ({ intakeRegistry, page, flushEvents }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.stopSessionReplayRecording()\n        window.DD_RUM!.startSessionReplayRecording()\n      })\n\n      await flushEvents()\n\n      expect(intakeRegistry.replaySegments).toHaveLength(2)\n\n      const firstSegment = intakeRegistry.replaySegments[0]\n      expect(findFullSnapshot(firstSegment), 'first segment have a FullSnapshot record').toBeTruthy()\n\n      const secondSegment = intakeRegistry.replaySegments[1]\n      expect(findFullSnapshot(secondSegment), 'second segment have a FullSnapshot record').toBeTruthy()\n    })\n\n  createTest('workerUrl initialization parameter')\n    .withRum({ workerUrl: '/worker.js' })\n    .withBasePath('/no-blob-worker-csp')\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      expect(intakeRegistry.replaySegments).toHaveLength(1)\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/recorder/shadowDom.scenario.ts",
    "content": "import type {\n  DocumentFragmentNode,\n  MouseInteractionData,\n  ScrollData,\n  SerializedNodeWithId,\n} from '@datadog/browser-rum/src/types'\nimport {\n  ChangeType,\n  IncrementalSource,\n  MouseInteractionType,\n  NodeType,\n  SnapshotFormat,\n} from '@datadog/browser-rum/src/types'\n\nimport { createMutationPayloadValidatorFromSegment } from '@datadog/browser-rum/test/record/mutationPayloadValidator'\nimport {\n  findElementWithIdAttribute,\n  findNode,\n  findTextContent,\n  findTextNode,\n} from '@datadog/browser-rum/test/record/nodes'\nimport {\n  findFullSnapshot,\n  findFullSnapshotInFormat,\n  findIncrementalSnapshot,\n  findMouseInteractionRecords,\n} from '@datadog/browser-rum/test/record/segments'\n\nimport type { Page } from '@playwright/test'\nimport { test, expect } from '@playwright/test'\nimport { decodeChangeRecords, findChangeRecords } from '@datadog/browser-rum/test/record/changes'\nimport { getElementIdsFromFullSnapshot } from '@datadog/browser-rum/test/record/elements'\nimport { createTest, html } from '../../lib/framework'\n\n/**\n * Will generate the following HTML\n * ```html\n * <my-input-field id=\"titi\">\n *  #shadow-root\n *    <div>\n *      <label  id=\"label-titi\">field titi: </label>\n *      <input id=\"input-titi\" value=\"toto\">\n *    </div>\n *</my-input-field>\n *```\n when called like `<my-input-field id=\"titi\" />`\n */\nconst inputShadowDom = `<script>\n class MyInputField extends HTMLElement {\n   constructor() {\n     super();\n     this.attachShadow({ mode: \"open\" });\n   }\n   connectedCallback() {\n     const componentId = this.getAttribute('id') ?? '';\n     const privacyOverride = this.getAttribute(\"privacy\");\n     const parent = document.createElement(\"div\");\n     if (privacyOverride) {\n       parent.setAttribute(\"data-dd-privacy\", privacyOverride);\n     }\n     const label = document.createElement(\"label\");\n     label.setAttribute(\"id\", \"label-\" + componentId);\n     label.innerText = \"field \" + componentId + \": \";\n     const input = document.createElement(\"input\");\n     input.setAttribute(\"id\", \"input-\" + componentId);\n     input.value = \"toto\"\n     parent.appendChild(label)\n     parent.appendChild(input)\n     this.shadowRoot.appendChild(parent);\n   }\n }\n       window.customElements.define(\"my-input-field\", MyInputField);\n </script>\n `\n\n/**\n * Will generate the following HTML\n * ```html\n * <my-div id=\"titi\">\n *  #shadow-root\n *    <div>toto</div>\n *</my-div>\n *```\n when called like `<my-div />`\n */\nconst divShadowDom = `<script>\n class CustomDiv extends HTMLElement {\n  constructor() {\n    super();\n    this.attachShadow({ mode: \"open\" });\n  }\n  connectedCallback() {\n    const div = document.createElement(\"div\");\n    div.setAttribute('id', 'shadow-child')\n    div.textContent = 'toto'\n    this.shadowRoot.appendChild(div);\n  }\n}\n      window.customElements.define(\"my-div\", CustomDiv);\n </script>\n `\n\n/**\n * Will generate the following HTML\n * ```html\n * <my-div id=\"titi\">\n *  #shadow-root\n *    <div scrollable-div style=\"height:100px; overflow: scroll;\">\n *      <div style=\"height:500px;\"></div>\n *    </div>\n *    <button>scroll to 250</button>\n *</my-div>\n *```\n when called like `<my-div />`\n */\nconst scrollableDivShadowDom = `<script>\n class CustomScrollableDiv extends HTMLElement {\n  constructor() {\n    super();\n    this.attachShadow({ mode: \"open\" });\n  }\n  connectedCallback() {\n    const div = document.createElement(\"div\");\n    div.id = 'scrollable-div';\n    div.style.height = '100px';\n    div.style.overflow = 'scroll';\n\n    const innerDiv = document.createElement(\"div\");\n    innerDiv.style.height = '500px';\n\n    const button = document.createElement(\"button\");\n    button.textContent = 'scroll to 250';\n\n    button.onclick = () => {\n      div.scrollTo({ top: 250 });\n    }\n\n    div.appendChild(innerDiv);\n    this.shadowRoot.appendChild(button);\n    this.shadowRoot.appendChild(div);\n  }\n}\n      window.customElements.define(\"my-scrollable-div\", CustomScrollableDiv);\n </script>\n `\n\n/**\n * Will generate the following HTML\n * ```html\n * <div-with-style>\n *  #shadow-root\n *    <div>toto</div>\n *</div-with-style>\n *```\n when called like `<div-with-style />`\n */\nconst divWithStyleShadowDom = `<script>\nclass DivWithStyle extends HTMLElement {\n constructor() {\n   super();\n   this.attachShadow({ mode: \"open\" });\n }\n connectedCallback() {\n   const div = document.createElement(\"div\");\n   div.textContent = 'toto'\n   this.shadowRoot.appendChild(div);\n   const styleSheet = new CSSStyleSheet();\n   styleSheet.insertRule('div { width: 100%; }')\n   this.shadowRoot.adoptedStyleSheets = [styleSheet]\n }\n}\n     window.customElements.define(\"div-with-style\", DivWithStyle);\n</script>\n`\n\ntest.describe('recorder with shadow DOM', () => {\n  test.describe('can record fullsnapshot with the detail inside the shadow root', () => {\n    const body = html`\n      ${divShadowDom}\n      <my-div />\n    `\n\n    createTest('V1')\n      .withRum({\n        defaultPrivacyLevel: 'allow',\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const fullSnapshot = findFullSnapshotInFormat(SnapshotFormat.V1, intakeRegistry.replaySegments[0])!\n        expect(fullSnapshot).toBeTruthy()\n\n        const textNode = findTextNode(fullSnapshot.data.node, 'toto')\n        expect(textNode).toBeTruthy()\n        expect(textNode?.textContent).toBe('toto')\n      })\n\n    createTest('Change')\n      .withRum({\n        defaultPrivacyLevel: 'allow',\n        enableExperimentalFeatures: ['use_incremental_change_records'],\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n        expect(decodeChangeRecords(records).at(0)!.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [0, 'HTML'],\n            [1, 'HEAD'],\n            [0, 'BODY'],\n            [1, '#text', '\\n      '],\n            [0, '#text', '\\n \\n      '],\n            [0, 'MY-DIV'],\n            [1, '#text', '\\n    '],\n            [0, '#shadow-root'],\n            [1, 'DIV', ['id', 'shadow-child']],\n            [1, '#text', 'toto'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n        ])\n      })\n  })\n\n  test.describe('can record fullsnapshot with adoptedStylesheet', () => {\n    const body = html`\n      ${divWithStyleShadowDom}\n      <div-with-style />\n    `\n\n    async function skipIfAdoptedStyleSheetsNotSupported(page: Page): Promise<void> {\n      const isAdoptedStyleSheetsSupported = await page.evaluate(() => document.adoptedStyleSheets !== undefined)\n      test.skip(!isAdoptedStyleSheetsSupported, 'adoptedStyleSheets is not supported in this browser')\n    }\n\n    createTest('V1')\n      .withRum()\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await skipIfAdoptedStyleSheetsNotSupported(page)\n\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const fullSnapshot = findFullSnapshotInFormat(SnapshotFormat.V1, intakeRegistry.replaySegments[0])!\n        expect(fullSnapshot).toBeTruthy()\n        const shadowRoot = findNode(\n          fullSnapshot.data.node,\n          (node) => node.type === NodeType.DocumentFragment\n        ) as DocumentFragmentNode\n        expect(shadowRoot.isShadowRoot).toBe(true)\n        expect(shadowRoot.adoptedStyleSheets).toEqual([{ cssRules: ['div { width: 100%; }'] }])\n      })\n\n    createTest('Change')\n      .withRum({\n        enableExperimentalFeatures: ['use_incremental_change_records'],\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await skipIfAdoptedStyleSheetsNotSupported(page)\n\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n        expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [0, 'HTML'],\n            [1, 'HEAD'],\n            [0, 'BODY'],\n            [1, '#text', '\\n      '],\n            [0, '#text', '\\n\\n      '],\n            [0, 'DIV-WITH-STYLE'],\n            [1, '#text', '\\n    '],\n            [0, '#shadow-root'],\n            [1, 'DIV'],\n            [1, '#text', 'toto'],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n          [ChangeType.AddStyleSheet, [['div { width: 100%; }']]],\n          [ChangeType.AttachedStyleSheets, [9, 0]],\n        ])\n      })\n  })\n\n  test.describe('can apply privacy level set from outside or inside the shadow DOM', () => {\n    const body = html`\n      ${inputShadowDom}\n      <div data-dd-privacy=\"mask-user-input\"><my-input-field id=\"privacy-set-outside\" /></div>\n      <my-input-field privacy=\"mask-user-input\" id=\"privacy-set-inside\" />\n    `\n\n    createTest('V1')\n      .withRum({\n        defaultPrivacyLevel: 'allow',\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const fullSnapshot = findFullSnapshotInFormat(SnapshotFormat.V1, intakeRegistry.replaySegments[0])!\n        expect(fullSnapshot).toBeTruthy()\n\n        const {\n          input: outsideInput,\n          shadowRoot: outsideShadowRoot,\n          textContent: outsideTextContent,\n        } = findElementsInShadowDom(fullSnapshot.data.node, 'privacy-set-outside')\n        expect(outsideShadowRoot?.isShadowRoot).toBe(true)\n        expect(outsideInput?.attributes.value).toBe('***')\n        expect(outsideTextContent).toBe('field privacy-set-outside: ')\n\n        const {\n          input: insideInput,\n          shadowRoot: insideShadowRoot,\n          textContent: insideTextContent,\n        } = findElementsInShadowDom(fullSnapshot.data.node, 'privacy-set-inside')\n        expect(insideShadowRoot?.isShadowRoot).toBe(true)\n        expect(insideInput?.attributes.value).toBe('***')\n        expect(insideTextContent).toBe('field privacy-set-inside: ')\n      })\n\n    createTest('Change')\n      .withRum({\n        defaultPrivacyLevel: 'allow',\n        enableExperimentalFeatures: ['use_incremental_change_records'],\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n        expect(decodeChangeRecords(records).at(0)!.data).toEqual([\n          [\n            ChangeType.AddNode,\n            [null, '#document'],\n            [1, '#doctype', 'html', '', ''],\n            [0, 'HTML'],\n            [1, 'HEAD'],\n            [0, 'BODY'],\n            [1, '#text', '\\n      '],\n            [0, '#text', '\\n \\n      '],\n            [0, 'DIV', ['data-dd-privacy', 'mask-user-input']],\n            [1, 'MY-INPUT-FIELD', ['id', 'privacy-set-outside']],\n            [1, '#shadow-root'],\n            [1, 'DIV'],\n            [1, 'LABEL', ['id', 'label-privacy-set-outside']],\n            [1, '#text', 'field privacy-set-outside: '],\n            [3, 'INPUT', ['id', 'input-privacy-set-outside'], ['value', '***']],\n            [10, '#text', '\\n      '],\n            [0, 'MY-INPUT-FIELD', ['privacy', 'mask-user-input'], ['id', 'privacy-set-inside']],\n            [1, '#text', '\\n    '],\n            [0, '#shadow-root'],\n            [1, 'DIV', ['data-dd-privacy', 'mask-user-input']],\n            [1, 'LABEL', ['id', 'label-privacy-set-inside']],\n            [1, '#text', 'field privacy-set-inside: '],\n            [3, 'INPUT', ['id', 'input-privacy-set-inside'], ['value', '***']],\n          ],\n          [ChangeType.ScrollPosition, [0, 0, 0]],\n        ])\n      })\n  })\n\n  test.describe('can record click with target from inside the shadow root', () => {\n    function createTestVariation(name: string, enableExperimentalFeatures: string[]): void {\n      createTest(name)\n        .withRum({ enableExperimentalFeatures })\n        .withBody(html`\n          ${divShadowDom}\n          <my-div />\n        `)\n        .run(async ({ flushEvents, intakeRegistry, page }) => {\n          const div = page.locator('my-div #shadow-child')\n          await div.click()\n          await flushEvents()\n          expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n          const fullSnapshot = findFullSnapshot({ records: intakeRegistry.replayRecords })!\n          const elementIds = getElementIdsFromFullSnapshot(fullSnapshot)\n          const shadowChildId = elementIds.get('shadow-child')\n\n          const mouseInteraction = findMouseInteractionRecords(\n            intakeRegistry.replaySegments[0],\n            MouseInteractionType.Click\n          )[0]\n          expect(mouseInteraction).toBeTruthy()\n          expect((mouseInteraction.data as MouseInteractionData).id).toBe(shadowChildId)\n        })\n    }\n\n    createTestVariation('V1', [])\n    createTestVariation('Change', ['use_incremental_change_records'])\n  })\n\n  test.describe('can record mutation from inside the shadow root', () => {\n    const body = html`\n      ${divShadowDom}\n      <my-div id=\"host\" />\n    `\n\n    const mutate = () => {\n      const host = document.body.querySelector('#host') as HTMLElement\n      const div = host.shadowRoot!.querySelector('div') as HTMLElement\n      div.innerText = 'titi'\n    }\n\n    createTest('V1')\n      .withRum({\n        defaultPrivacyLevel: 'allow',\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await page.evaluate(mutate)\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const { validate, expectInitialNode, expectNewNode } = createMutationPayloadValidatorFromSegment(\n          intakeRegistry.replaySegments[0],\n          { expect }\n        )\n        validate({\n          adds: [\n            {\n              parent: expectInitialNode({ tag: 'div' }),\n              node: expectNewNode({ type: NodeType.Text, textContent: 'titi' }),\n            },\n          ],\n          removes: [\n            {\n              parent: expectInitialNode({ tag: 'div' }),\n              node: expectInitialNode({ text: 'toto' }),\n            },\n          ],\n        })\n      })\n\n    createTest('Change')\n      .withRum({\n        defaultPrivacyLevel: 'allow',\n        enableExperimentalFeatures: ['use_incremental_change_records'],\n      })\n      .withBody(body)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await page.evaluate(mutate)\n        await flushEvents()\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n        const records = findChangeRecords(intakeRegistry.replaySegments[0].records)\n        expect(decodeChangeRecords(records).at(-1)!.data).toEqual([\n          [ChangeType.AddNode, [2, '#text', 'titi']],\n          [ChangeType.RemoveNode, 11],\n        ])\n      })\n  })\n\n  test.describe('can record scroll from inside the shadow root', () => {\n    function createTestVariation(name: string, enableExperimentalFeatures: string[]): void {\n      createTest(name)\n        .withRum({ enableExperimentalFeatures })\n        .withBody(html`\n          ${scrollableDivShadowDom}\n          <my-scrollable-div id=\"host\" />\n        `)\n        .run(async ({ flushEvents, intakeRegistry, page }) => {\n          const button = page.locator('my-scrollable-div button')\n\n          // Triggering scrollTo from the test itself is not allowed\n          // Thus, a callback to scroll the div was added to the button 'click' event\n          await button.click()\n\n          await flushEvents()\n          expect(intakeRegistry.replaySegments).toHaveLength(1)\n\n          const firstSegment = intakeRegistry.replaySegments[0]\n          const fullSnapshot = findFullSnapshot(firstSegment)!\n          const elementIds = getElementIdsFromFullSnapshot(fullSnapshot)\n\n          const divId = elementIds.get('scrollable-div')\n          expect(divId).not.toBeUndefined()\n\n          const scrollRecord = findIncrementalSnapshot(firstSegment, IncrementalSource.Scroll)\n          expect(scrollRecord).toBeTruthy()\n\n          const scrollData = scrollRecord?.data as ScrollData\n          expect(scrollData.id).toBe(divId)\n          expect(scrollData.y).toBe(250)\n        })\n    }\n\n    createTestVariation('V1', [])\n    createTestVariation('Change', ['use_incremental_change_records'])\n  })\n})\n\nfunction findElementsInShadowDom(node: SerializedNodeWithId, id: string) {\n  const shadowHost = findElementWithIdAttribute(node, id)\n  expect(shadowHost).toBeTruthy()\n\n  const shadowRoot = shadowHost!.childNodes.find(\n    (node) => node.type === NodeType.DocumentFragment && node.isShadowRoot\n  ) as DocumentFragmentNode\n  expect(shadowRoot).toBeTruthy()\n\n  const input = findElementWithIdAttribute(node, `input-${id}`)\n  expect(input).toBeTruthy()\n\n  const text = findElementWithIdAttribute(node, `label-${id}`)!\n  expect(text).toBeTruthy()\n  const textContent = findTextContent(text)\n  expect(textContent).toBeTruthy()\n  return { shadowHost, shadowRoot, input, text, textContent }\n}\n"
  },
  {
    "path": "test/e2e/scenario/recorder/viewports.scenario.ts",
    "content": "import type { ViewportResizeData, ScrollData } from '@datadog/browser-rum/src/types'\nimport { IncrementalSource } from '@datadog/browser-rum/src/types'\n\nimport { findAllIncrementalSnapshots, findAllVisualViewports } from '@datadog/browser-rum/test/record/segments'\nimport type { Page } from '@playwright/test'\nimport { test, expect } from '@playwright/test'\nimport { wait } from '@datadog/browser-core/test/wait'\nimport type { IntakeRegistry } from '../../lib/framework'\nimport { createTest, html } from '../../lib/framework'\n\nconst NAVBAR_HEIGHT_CHANGE_UPPER_BOUND = 30\nconst VIEWPORT_META_TAGS = `\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n<meta name=\"mobile-web-app-capable\" content=\"yes\">\n<meta name=\"viewport\"\n  content=\"width=device-width, initial-scale=1.0, maximum-scale=2.75, minimum-scale=1.0, user-scalable=yes\"\n>\n`\n\nfunction hasNoTouchGestureEmulationSupportViaCDP(browserName: string) {\n  return [\n    browserName !== 'chromium' && browserName !== 'msedge',\n    'only chromium based browser supports touch gestures emulation for now (via CDP)',\n  ] as const\n}\n\ntest.describe('recorder', () => {\n  test.describe('layout viewport properties', () => {\n    createTest('getWindowWidth/Height should not be affected by pinch zoom')\n      .withRum()\n      .withBody(html`${VIEWPORT_META_TAGS}`)\n      .run(async ({ intakeRegistry, page, flushEvents, browserName }) => {\n        test.fixme(browserName === 'msedge', 'In Edge, the ViewportResize record data is off by almost 20px')\n        test.skip(...hasNoTouchGestureEmulationSupportViaCDP(browserName))\n\n        await buildScrollablePage(page)\n\n        const { innerWidth, innerHeight } = await getWindowInnerDimensions(page)\n\n        await performSignificantZoom(page)\n\n        await page.evaluate(() => {\n          window.dispatchEvent(new Event('resize'))\n        })\n\n        await flushEvents()\n        const lastViewportResizeData = getLastRecord(intakeRegistry, (segment) =>\n          findAllIncrementalSnapshots(segment, IncrementalSource.ViewportResize)\n        ).data as ViewportResizeData\n\n        expectToBeNearby(lastViewportResizeData.width, innerWidth)\n        expectToBeNearby(lastViewportResizeData.height, innerHeight)\n      })\n\n    /**\n     * window.ScrollX/Y on some devices/browsers are changed by pinch zoom\n     * We need to ensure that our measurements are not affected by pinch zoom\n     */\n    createTest('getScrollX/Y should not be affected by pinch scroll')\n      .withRum()\n      .withBody(html`${VIEWPORT_META_TAGS}`)\n      .run(async ({ intakeRegistry, flushEvents, page, browserName }) => {\n        test.skip(...hasNoTouchGestureEmulationSupportViaCDP(browserName))\n\n        const VISUAL_SCROLL_DOWN_PX = 60\n        const LAYOUT_SCROLL_AMOUNT = 20\n\n        await buildScrollablePage(page)\n        await performSignificantZoom(page)\n        await resetWindowScroll(page)\n\n        const initialVisualViewport = await getVisualViewport(page)\n        const { scrollX: initialScrollX, scrollY: initialScrollY } = await getWindowScroll(page)\n\n        // Add Visual Viewport Scroll\n        await visualScrollVerticallyDown(page, VISUAL_SCROLL_DOWN_PX)\n\n        // Add Layout Viewport Scroll\n        await layoutScrollTo(page, LAYOUT_SCROLL_AMOUNT, LAYOUT_SCROLL_AMOUNT)\n\n        const nextVisualViewport = await getVisualViewport(page)\n        const { scrollX: nextScrollX, scrollY: nextScrollY } = await getWindowScroll(page)\n\n        await flushEvents()\n        const lastScrollData = getLastRecord(intakeRegistry, (segment) =>\n          findAllIncrementalSnapshots(segment, IncrementalSource.Scroll)\n        ).data as ScrollData\n\n        // Height changes because URL address bar changes due to scrolling\n        const navBarHeightChange = nextVisualViewport.height - initialVisualViewport.height\n        expect(navBarHeightChange).toBeLessThanOrEqual(NAVBAR_HEIGHT_CHANGE_UPPER_BOUND)\n\n        // Visual Viewport Scroll should change without visual viewport affect\n        expectToBeNearby(lastScrollData.x, initialScrollX + LAYOUT_SCROLL_AMOUNT)\n        expectToBeNearby(lastScrollData.y, initialScrollY + LAYOUT_SCROLL_AMOUNT)\n        expectToBeNearby(lastScrollData.x, nextScrollX)\n        expectToBeNearby(lastScrollData.y, nextScrollY)\n      })\n  })\n\n  test.describe('visual viewport properties', () => {\n    createTest('pinch zoom \"scroll\" event reports visual viewport position')\n      .withRum()\n      .withBody(html`${VIEWPORT_META_TAGS}`)\n      .run(async ({ intakeRegistry, page, flushEvents, browserName }) => {\n        test.skip(...hasNoTouchGestureEmulationSupportViaCDP(browserName))\n\n        const VISUAL_SCROLL_DOWN_PX = 100\n        await buildScrollablePage(page)\n        await performSignificantZoom(page)\n        await visualScrollVerticallyDown(page, VISUAL_SCROLL_DOWN_PX)\n        const nextVisualViewportDimension = await getVisualViewport(page)\n        await flushEvents()\n        const lastVisualViewportRecord = getLastRecord(intakeRegistry, findAllVisualViewports)\n        expectToBeNearby(lastVisualViewportRecord.data.pageTop, nextVisualViewportDimension.pageTop)\n      })\n\n    createTest('pinch zoom \"resize\" event reports visual viewport scale')\n      .withRum()\n      .withBody(html`${VIEWPORT_META_TAGS}`)\n      .run(async ({ intakeRegistry, page, flushEvents, browserName }) => {\n        test.skip(...hasNoTouchGestureEmulationSupportViaCDP(browserName))\n\n        await performSignificantZoom(page)\n        const nextVisualViewportDimension = await getVisualViewport(page)\n        await flushEvents()\n        const lastVisualViewportRecord = getLastRecord(intakeRegistry, findAllVisualViewports)\n        expectToBeNearby(lastVisualViewportRecord.data.scale, nextVisualViewportDimension.scale)\n      })\n  })\n})\n\n// Flakiness: Working with viewport sizes has variations per device of a few pixels\nfunction expectToBeNearby(numA: number, numB: number) {\n  const test = Math.abs(numA - numB) <= 5\n  if (!test) {\n    // Prints a clear error message when different\n    expect(numA).toBe(numB)\n  }\n}\n\nasync function pinchZoom(page: Page, xChange: number) {\n  // Cannot exceed the bounds of a device's screen, at start or end positions.\n  // So pick a midpoint on small devices, roughly 180px.\n  const xBase = 180\n  const yBase = 180\n  const xOffsetFingerTwo = 25\n  const pauseDurationMs = 150\n\n  const cdp = await page.context().newCDPSession(page)\n  await cdp.send('Input.dispatchTouchEvent', {\n    type: 'touchStart',\n    touchPoints: [\n      { x: xBase, y: yBase, id: 0 },\n      { x: xBase + xOffsetFingerTwo, y: yBase, id: 1 },\n    ],\n  })\n  await page.waitForTimeout(pauseDurationMs)\n  await cdp.send('Input.dispatchTouchEvent', {\n    type: 'touchMove',\n    touchPoints: [\n      { x: xBase, y: yBase, id: 0 },\n      { x: xBase + xChange, y: yBase, id: 1 },\n    ],\n  })\n  await cdp.send('Input.dispatchTouchEvent', {\n    type: 'touchEnd',\n    touchPoints: [\n      { x: xBase, y: yBase, id: 0 },\n      { x: xBase + xChange, y: yBase, id: 1 },\n    ],\n  })\n}\n\nasync function performSignificantZoom(page: Page) {\n  const initialVisualViewport = await getVisualViewport(page)\n  await pinchZoom(page, 150)\n  await pinchZoom(page, 150)\n  const nextVisualViewport = await getVisualViewport(page)\n  // Test the test: ensure pinch zoom was applied\n  expect(nextVisualViewport.scale).toBeGreaterThan(initialVisualViewport.scale)\n}\n\nasync function visualScrollVerticallyDown(page: Page, yChange: number) {\n  // Providing a negative offset value will scroll up.\n  // NOTE: Some devices may invert scroll direction\n  // Cannot exceed the bounds of a device's screen, at start or end positions.\n  // So pick a midpoint on small devices, roughly 180px.\n  const xBase = 180\n  const yBase = 180\n  // Scrolling too fast can show or hide the address bar on some device browsers.\n  const pauseDurationMs = 150\n\n  const cdp = await page.context().newCDPSession(page)\n  await cdp.send('Input.dispatchTouchEvent', {\n    type: 'touchStart',\n    touchPoints: [{ x: xBase, y: yBase, id: 0 }],\n  })\n  await wait(pauseDurationMs)\n  await cdp.send('Input.dispatchTouchEvent', {\n    type: 'touchMove',\n    touchPoints: [{ x: xBase, y: yBase - yChange, id: 0 }],\n  })\n  await cdp.send('Input.dispatchTouchEvent', {\n    type: 'touchEnd',\n    touchPoints: [{ x: xBase, y: yBase - yChange, id: 0 }],\n  })\n}\n\nasync function buildScrollablePage(page: Page) {\n  await page.evaluate(() => {\n    document.documentElement.style.setProperty('width', '5000px')\n    document.documentElement.style.setProperty('height', '5000px')\n    document.documentElement.style.setProperty('margin', '0px')\n    document.documentElement.style.setProperty('padding', '0px')\n    document.body.style.setProperty('margin', '0px')\n    document.body.style.setProperty('padding', '0px')\n    document.body.style.setProperty('width', '5000px')\n    document.body.style.setProperty('height', '5000px')\n  })\n}\n\ninterface VisualViewportData {\n  scale: number\n  width: number\n  height: number\n  offsetLeft: number\n  offsetTop: number\n  pageLeft: number\n  pageTop: number\n}\n\nfunction getVisualViewport(page: Page): Promise<VisualViewportData> {\n  return page.evaluate(() => {\n    const visual = window.visualViewport || ({} as Record<string, undefined>)\n    return {\n      scale: visual.scale,\n      width: visual.width,\n      height: visual.height,\n      offsetLeft: visual.offsetLeft,\n      offsetTop: visual.offsetTop,\n      pageLeft: visual.pageLeft,\n      pageTop: visual.pageTop,\n    }\n  }) as Promise<VisualViewportData>\n}\n\nfunction getWindowScroll(page: Page) {\n  return page.evaluate(() => ({\n    scrollX: window.scrollX,\n    scrollY: window.scrollY,\n  })) as Promise<{ scrollX: number; scrollY: number }>\n}\n\nfunction getLastRecord<T>(intakeRegistry: IntakeRegistry, filterMethod: (segment: any) => T[]): T {\n  const segment = intakeRegistry.replaySegments.at(-1)\n  const foundRecords = filterMethod(segment)\n  return foundRecords[foundRecords.length - 1]\n}\n\nfunction getWindowInnerDimensions(page: Page) {\n  return page.evaluate(() => ({\n    innerWidth: window.innerWidth,\n    innerHeight: window.innerHeight,\n  })) as Promise<{ innerWidth: number; innerHeight: number }>\n}\n\nasync function resetWindowScroll(page: Page) {\n  await page.evaluate(() => {\n    window.scrollTo(-500, -500)\n  })\n  const { scrollX: nextScrollX, scrollY: nextScrollY } = await getWindowScroll(page)\n  // Ensure our methods are applied correctly\n  expect(nextScrollX).toBe(0)\n  expect(nextScrollY).toBe(0)\n}\n\nasync function layoutScrollTo(page: Page, scrollX: number, scrollY: number) {\n  await page.evaluate(\n    ({ scrollX, scrollY }) => {\n      window.scrollTo(scrollX, scrollY)\n    },\n    { scrollX, scrollY }\n  )\n  const { scrollX: nextScrollX, scrollY: nextScrollY } = await getWindowScroll(page)\n  // Ensure our methods are applied correctly\n  expect(scrollX).toBe(nextScrollX)\n  expect(scrollY).toBe(nextScrollY)\n}\n"
  },
  {
    "path": "test/e2e/scenario/rum/actions.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest, html, waitForServersIdle, waitForRequests } from '../../lib/framework'\n\nfunction hasActionId(event: { action?: { id?: string | string[] } }, actionId: string): boolean {\n  return [event.action?.id].flat().includes(actionId)\n}\n\ntest.describe('action collection', () => {\n  createTest('track a click action')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          button.setAttribute('data-clicked', 'true')\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0]).toEqual(\n        expect.objectContaining({\n          action: {\n            error: {\n              count: 0,\n            },\n            id: expect.any(String),\n            loading_time: expect.any(Number),\n            long_task: {\n              count: expect.any(Number),\n            },\n            resource: {\n              count: 0,\n            },\n            target: {\n              name: 'click me',\n            },\n            type: 'click',\n            frustration: {\n              type: [],\n            },\n          },\n          _dd: expect.objectContaining({\n            action: {\n              target: expect.objectContaining({\n                selector: expect.any(String),\n                width: expect.any(Number),\n                height: expect.any(Number),\n              }),\n              name_source: 'text_content',\n              position: {\n                x: expect.any(Number),\n                y: expect.any(Number),\n              },\n            },\n          }),\n        })\n      )\n    })\n\n  createTest('compute action target information before the UI changes')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button style=\"position: relative\">click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('pointerdown', () => {\n          // Using .textContent or .innerText prevents the click event to be dispatched in Safari\n          button.childNodes[0].data = 'Clicked'\n          button.classList.add('active')\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action?.target?.name).toBe('click me')\n      expect(actionEvents[0]._dd.action?.target?.selector).toBe('BODY>BUTTON')\n    })\n\n  createTest('does not report a click on the body when the target element changes between mousedown and mouseup')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button style=\"position: relative\">click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('pointerdown', () => {\n          // Move the button to the right, so the mouseup/pointerup event target is different\n          // than the <button> element and click event target gets set to <body>\n          button.style.left = '1000px'\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action?.target?.name).toBe('click me')\n    })\n\n  createTest('associate a request to its action')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          fetch('/ok')\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await waitForServersIdle()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((event) => event.resource.type === 'fetch')\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action).toEqual({\n        error: {\n          count: 0,\n        },\n        id: expect.any(String) as unknown as string,\n        loading_time: expect.any(Number) as unknown as number,\n        long_task: {\n          count: expect.any(Number) as unknown as number,\n        },\n        resource: {\n          count: 1,\n        },\n        target: {\n          name: 'click me',\n        },\n        type: 'click',\n        frustration: {\n          type: [],\n        },\n      })\n\n      expect(resourceEvents).toHaveLength(1)\n      // resource action id should contain the collected action id + the discarded rage click id\n      expect(resourceEvents[0].action!.id).toHaveLength(2)\n      expect(resourceEvents[0].action!.id).toContain(actionEvents[0].action.id!)\n    })\n\n  createTest('associate a long tasks to its action')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          const end = performance.now() + 55\n          while (performance.now() < end) {} // block the handler for ~55ms to trigger a long task\n          fetch('/ok') // fire a fetch to extend the action duration\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page, browserName }) => {\n      test.skip(browserName !== 'chromium', 'Non-Chromium browsers do not support long tasks')\n\n      const button = page.locator('button')\n      await button.click()\n      await waitForServersIdle()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n      const longTaskEvents = intakeRegistry.rumLongTaskEvents.filter((event) =>\n        event.long_task.scripts?.[0]?.invoker?.includes('BUTTON.onclick')\n      )\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action).toEqual({\n        error: {\n          count: 0,\n        },\n        id: expect.any(String) as unknown as string,\n        loading_time: expect.any(Number),\n        long_task: {\n          count: 1,\n        },\n\n        resource: {\n          count: expect.any(Number) as unknown as number,\n        },\n        target: {\n          name: 'click me',\n        },\n        type: 'click',\n        frustration: {\n          type: [],\n        },\n      })\n\n      expect(longTaskEvents).toHaveLength(1)\n      // long task action id should contain the collected action id + the discarded rage click id\n      expect(longTaskEvents[0].action!.id).toHaveLength(2)\n      expect(longTaskEvents[0].action!.id).toContain(actionEvents[0].action.id!)\n    })\n\n  createTest('increment the view.action.count of the view active when the action started')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          history.pushState(null, null, '/other-view')\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n\n      const viewEvents = intakeRegistry.rumViewEvents\n      const originalViewEvent = viewEvents.find((view) => view.view.url.endsWith('/'))!\n      const otherViewEvent = viewEvents.find((view) => view.view.url.endsWith('/other-view'))!\n      expect(originalViewEvent.view.action.count).toBe(1)\n      expect(otherViewEvent.view.action.count).toBe(0)\n    })\n\n  createTest('collect an \"error click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          button.setAttribute('data-clicked', 'true')\n          throw new Error('Foo')\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, withBrowserLogs, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toEqual(['error_click'])\n      expect(actionEvents[0].action.error!.count).toBe(1)\n\n      expect(intakeRegistry.rumViewEvents[0].view.frustration!.count).toBe(1)\n\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('collect a \"dead click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html` <button>click me</button> `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toEqual(['dead_click'])\n\n      expect(intakeRegistry.rumViewEvents[0].view.frustration!.count).toBe(1)\n    })\n\n  createTest('do not consider a click on a checkbox as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html` <input type=\"checkbox\" /> `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const input = page.locator('input')\n      await input.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('do not consider a click to change the value of a \"range\" input as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html` <input type=\"range\" /> `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const input = page.locator('input')\n      await input.click({ position: { x: 10, y: 0 } })\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('consider a click on an already checked \"radio\" input as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html` <input type=\"radio\" checked /> `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const input = page.locator('input')\n      await input.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toEqual(['dead_click'])\n    })\n\n  createTest('do not consider a click on text input as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html` <input type=\"text\" /> `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const input = page.locator('input')\n      await input.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('do not consider a click on a label referring to a text input as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html` <input type=\"text\" id=\"my-input\" /><label for=\"my-input\">Click me</label> `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const label = page.locator('label')\n      await label.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('do not consider clicks leading to scrolls as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <div style=\"height: 200vh;\">\n        <button>click me</button>\n        <script>\n          const button = document.querySelector('button')\n          button.addEventListener('click', () => {\n            window.scrollTo(0, 200)\n          })\n        </script>\n      </div>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('do not consider clicks leading to scrolls as \"rage_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <div style=\"height: 200vh;\">\n        <button>click me</button>\n        <script>\n          const button = document.querySelector('button')\n          button.addEventListener('click', () => {\n            window.scrollTo(0, 200)\n          })\n        </script>\n      </div>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await button.click()\n      await button.click()\n\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(3)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('do not consider a click that open a new window as \"dead_click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          window.open(window.location.href)\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toHaveLength(0)\n    })\n\n  createTest('collect a \"rage click\"')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          button.setAttribute('data-clicked', Math.random())\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, page, flushEvents }) => {\n      // We don't use the playwright's `page.locator('button').click()` here because the latency of the command is\n      // too high and the clicks won't be recognised as rage clicks.\n      await page.evaluate(() => {\n        const button = document.querySelector('button')!\n\n        function click() {\n          button.dispatchEvent(new PointerEvent('pointerdown', { isPrimary: true }))\n          button.dispatchEvent(new PointerEvent('pointerup', { isPrimary: true }))\n          button.dispatchEvent(new PointerEvent('click', { isPrimary: true }))\n        }\n\n        // Simulate a rage click\n        click()\n        click()\n        click()\n      })\n\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toEqual(['rage_click'])\n    })\n\n  createTest('collect multiple frustrations in one action')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        button.addEventListener('click', () => {\n          throw new Error('Foo')\n        })\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, withBrowserLogs, page }) => {\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const actionEvents = intakeRegistry.rumActionEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.frustration!.type).toStrictEqual(['error_click', 'dead_click'])\n\n      expect(intakeRegistry.rumViewEvents[0].view.frustration!.count).toBe(2)\n\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  // We don't use the playwright's `page.locator('button').click()` here because it makes the test slower\n  createTest('dont crash when clicking on a button')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <button>click me</button>\n      <script>\n        const button = document.querySelector('button')\n        function click() {\n          const down = new PointerEvent('pointerdown', { isPrimary: true })\n          down.__ddIsTrusted = true\n\n          const up = new PointerEvent('pointerup', { isPrimary: true })\n          up.__ddIsTrusted = true\n\n          button.dispatchEvent(down)\n          button.dispatchEvent(up)\n        }\n\n        for (let i = 0; i < 2_500; i++) {\n          click()\n        }\n\n        window.open('/empty')\n      </script>\n    `)\n    .run(({ withBrowserLogs }) => {\n      withBrowserLogs((logs) => {\n        // A failing test would have a log with message \"Uncaught RangeError: Maximum call stack size exceeded\"\n        expect(logs).toHaveLength(0)\n      })\n    })\n})\n\ntest.describe('action collection with shadow DOM', () => {\n  createTest('without betaTrackActionsInShadowDom, click inside shadow DOM uses shadow host as target')\n    .withRum({ trackUserInteractions: true })\n    .withBody(html`\n      <my-button id=\"shadow-host\"></my-button>\n      <script>\n        class MyButton extends HTMLElement {\n          constructor() {\n            super()\n            this.attachShadow({ mode: 'open' })\n            const button = document.createElement('button')\n            button.textContent = 'Shadow Button'\n            this.shadowRoot.appendChild(button)\n          }\n        }\n        customElements.define('my-button', MyButton)\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('my-button').first().locator('button')\n      await button.click()\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action?.target?.name).toBe('')\n      expect(actionEvents[0]._dd.action?.target?.selector).toBe('#shadow-host')\n    })\n\n  createTest('with betaTrackActionsInShadowDom, get action name from element inside shadow DOM')\n    .withRum({ trackUserInteractions: true, betaTrackActionsInShadowDom: true })\n    .withBody(html`\n      <my-button id=\"shadow-host\"></my-button>\n      <script>\n        class MyButton extends HTMLElement {\n          constructor() {\n            super()\n            this.attachShadow({ mode: 'open' })\n            const button = document.createElement('button')\n            button.textContent = 'Shadow Button'\n            this.shadowRoot.appendChild(button)\n          }\n        }\n        customElements.define('my-button', MyButton)\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('my-button').first().locator('button')\n      await button.click()\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action?.target?.name).toBe('Shadow Button')\n      expect(actionEvents[0]._dd.action?.target?.selector).toEqual('#shadow-host::shadow BUTTON')\n    })\n\n  createTest('with betaTrackActionsInShadowDom, traverse shadow boundary for data-dd-action-name')\n    .withRum({ trackUserInteractions: true, betaTrackActionsInShadowDom: true })\n    .withBody(html`\n      <my-button id=\"shadow-host\" data-dd-action-name=\"Custom Shadow Action\"></my-button>\n      <script>\n        class MyButton extends HTMLElement {\n          constructor() {\n            super()\n            this.attachShadow({ mode: 'open' })\n            const button = document.createElement('button')\n            button.textContent = 'Click me'\n            this.shadowRoot.appendChild(button)\n          }\n        }\n        customElements.define('my-button', MyButton)\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('my-button').first().locator('button')\n      await button.click()\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action?.target?.name).toBe('Custom Shadow Action')\n    })\n\n  createTest('with betaTrackActionsInShadowDom, selector includes stable attributes from inside shadow DOM')\n    .withRum({ trackUserInteractions: true, betaTrackActionsInShadowDom: true })\n    .withBody(html`\n      <my-button id=\"shadow-host\"></my-button>\n      <script>\n        class MyButton extends HTMLElement {\n          constructor() {\n            super()\n            this.attachShadow({ mode: 'open' })\n            const button = document.createElement('button')\n            button.setAttribute('data-testid', 'shadow-btn')\n            button.textContent = 'Test Button'\n            this.shadowRoot.appendChild(button)\n          }\n        }\n        customElements.define('my-button', MyButton)\n      </script>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('my-button').first().locator('button')\n      await button.click()\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0]._dd.action?.target?.selector).toEqual(\n        '#shadow-host::shadow BUTTON[data-testid=\"shadow-btn\"]'\n      )\n    })\n})\n\ntest.describe('custom actions with startAction/stopAction', () => {\n  createTest('track a custom action with startAction/stopAction')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startAction('checkout')\n        window.DD_RUM!.stopAction('checkout')\n      })\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.target?.name).toBe('checkout')\n      expect(actionEvents[0].action.type).toBe('custom')\n      expect(actionEvents[0].action.id).toBeDefined()\n    })\n\n  createTest('associate an error to a custom action')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startAction('checkout')\n        window.DD_RUM!.addError(new Error('Payment failed'))\n        window.DD_RUM!.stopAction('checkout')\n      })\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      const errorEvents = intakeRegistry.rumErrorEvents\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.error?.count).toBe(1)\n      expect(actionEvents[0].action.frustration?.type).toContain('error_click')\n      expect(errorEvents.length).toBeGreaterThanOrEqual(1)\n\n      const actionId = actionEvents[0].action.id\n      const relatedError = errorEvents.find((e) => hasActionId(e, actionId!))\n      expect(relatedError).toBeDefined()\n    })\n\n  createTest('associate a resource to a custom action')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startAction('load-data')\n        void fetch('/ok')\n      })\n      await waitForRequests(page)\n      await page.evaluate(() => {\n        window.DD_RUM!.stopAction('load-data')\n      })\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((e) => e.resource.type === 'fetch')\n\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.resource?.count).toBe(1)\n      expect(actionEvents[0].action.frustration?.type).toEqual([])\n\n      const actionId = actionEvents[0].action.id\n      const relatedResource = resourceEvents.find((e) => hasActionId(e, actionId!))\n      expect(relatedResource).toBeDefined()\n    })\n\n  createTest('track multiple concurrent custom actions with actionKey')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startAction('click', { actionKey: 'button1' })\n        window.DD_RUM!.startAction('click', { actionKey: 'button2' })\n        window.DD_RUM!.stopAction('click', { actionKey: 'button2' })\n        window.DD_RUM!.stopAction('click', { actionKey: 'button1' })\n      })\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(2)\n      expect(actionEvents[0].action.id).not.toBe(actionEvents[1].action.id)\n    })\n\n  createTest('merge contexts from start and stop')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startAction('purchase', { context: { cart_id: 'abc123' } })\n        window.DD_RUM!.stopAction('purchase', { context: { total: 99.99 } })\n      })\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].context).toEqual(\n        expect.objectContaining({\n          cart_id: 'abc123',\n          total: 99.99,\n        })\n      )\n    })\n\n  createTest('preserve timing when startAction is called before init')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .withRumInit((configuration) => {\n      window.DD_RUM!.startAction('pre_init_action')\n\n      setTimeout(() => {\n        window.DD_RUM!.init(configuration)\n        window.DD_RUM!.stopAction('pre_init_action')\n      }, 50)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0].action.target?.name).toBe('pre_init_action')\n      expect(actionEvents[0].action.loading_time).toBeGreaterThanOrEqual(40 * 1e6)\n    })\n\n  createTest('attribute errors and resources to action started before init')\n    .withRum({ enableExperimentalFeatures: ['start_stop_action'] })\n    .withRumInit((configuration) => {\n      window.DD_RUM!.startAction('pre_init_action')\n\n      setTimeout(() => {\n        window.DD_RUM!.init(configuration)\n\n        window.DD_RUM!.addError(new Error('Test error'))\n        void fetch('/ok')\n      }, 10)\n    })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await waitForRequests(page)\n\n      await page.evaluate(() => {\n        window.DD_RUM!.stopAction('pre_init_action')\n      })\n\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n\n      const actionId = actionEvents[0].action.id\n      const relatedError = intakeRegistry.rumErrorEvents.find((e) => hasActionId(e, actionId!))\n      expect(relatedError).toBeDefined()\n\n      const fetchResources = intakeRegistry.rumResourceEvents.filter((e) => e.resource.type === 'fetch')\n      const relatedFetch = fetchResources.find((e) => hasActionId(e, actionId!))\n      expect(relatedFetch).toBeDefined()\n    })\n})\n\ntest.describe('action collection with composed path selector', () => {\n  createTest('should return a composed_path_selector if flag is enabled')\n    .withRum({\n      trackUserInteractions: true,\n      enableExperimentalFeatures: ['composed_path_selector'],\n    })\n    .withBody(html`\n      <button>Click</button>\n      <button id=\"my-button\" data-test-id=\"test-btn\" data-random=\"secret\" class=\"foo bar baz\">Click me</button>\n    `)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const button = page.locator('#my-button')\n      await button.click()\n      await flushEvents()\n\n      const actionEvents = intakeRegistry.rumActionEvents\n      expect(actionEvents).toHaveLength(1)\n      expect(actionEvents[0]._dd.action?.target?.composed_path_selector).toBe(\n        'BUTTON#my-button[data-test-id=\"test-btn\"].bar.baz.foo:nth-child(2):nth-of-type(2);'\n      )\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/rum/errors.scenario.ts",
    "content": "import type { RumErrorEvent } from '@datadog/browser-rum-core'\nimport { test, expect } from '@playwright/test'\nimport { createTest, html } from '../../lib/framework'\n\n// Note: using `browser.execute` to throw exceptions may result in \"Script error.\" being reported,\n// Use createBody because `page.evaluate()` runs in a different context and breaks stack traces.\nfunction createBody(errorGenerator: string) {\n  return html`\n    <button>click me</button>\n    <script>\n      const button = document.querySelector('button')\n      button.addEventListener('click', function handler() {\n        ${errorGenerator}\n      })\n      function foo() {\n        return new Error('oh snap')\n      }\n      function customError() {\n        class CustomTestError extends Error {}\n        return new CustomTestError('oh snap')\n      }\n      function customErrorWithInheritance() {\n        class CustomTestError extends Error {}\n        class CustomTestError2 extends CustomTestError {}\n\n        // this is an anonymous class, which has no name\n        // we're checking if the stacktrace is correctly reported for this specific case (with the class name missing)\n        return new (class extends CustomTestError2 {\n          constructor(e) {\n            super(e)\n            this.name = 'CustomTestError3'\n          }\n        })('oh snap')\n      }\n    </script>\n  `\n}\n\ntest.describe('rum errors', () => {\n  createTest('send console.error errors')\n    .withRum()\n    .withBody(createBody('console.error(\"oh snap\")'))\n    .run(async ({ page, intakeRegistry, baseUrl, flushEvents, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'console',\n        handlingStack: ['HandlingStack: console error', `handler @ ${baseUrl}:`],\n        handling: 'handled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('pass Error instance to console.error')\n    .withRum()\n    .withBody(createBody('console.error(\"Foo:\", foo())'))\n    .run(async ({ page, flushEvents, intakeRegistry, baseUrl, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'Foo: Error: oh snap',\n        source: 'console',\n        stack: ['Error: oh snap', `at foo @ ${baseUrl}:`, `handler @ ${baseUrl}:`],\n        handlingStack: ['HandlingStack: console error', `handler @ ${baseUrl}:`],\n        handling: 'handled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('send uncaught exceptions')\n    .withRum()\n    .withBody(createBody('throw foo()'))\n    .run(async ({ page, flushEvents, intakeRegistry, baseUrl, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'source',\n        stack: ['Error: oh snap', `at foo @ ${baseUrl}:`, `handler @ ${baseUrl}:`],\n        handling: 'unhandled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('send runtime errors happening before initialization')\n    .withRum()\n    .withRumInit((configuration) => {\n      // Use a setTimeout to:\n      // * have a constant stack trace regardless of the setup used\n      // * avoid the exception to be swallowed by the `onReady` logic\n      setTimeout(() => {\n        throw new Error('oh snap')\n      })\n      // Simulate a late initialization of the RUM SDK\n      setTimeout(() => window.DD_RUM!.init(configuration))\n    })\n    .run(async ({ intakeRegistry, flushEvents, withBrowserLogs, baseUrl }) => {\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'source',\n        handling: 'unhandled',\n        stack: ['Error: oh snap', `at <anonymous> @ ${baseUrl}:`],\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('send unhandled rejections')\n    .withRum()\n    .withBody(createBody('Promise.reject(foo())'))\n    .run(async ({ flushEvents, page, intakeRegistry, baseUrl, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'source',\n        stack: ['Error: oh snap', `at foo @ ${baseUrl}:`, `handler @ ${baseUrl}:`],\n        handling: 'unhandled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(1)\n      })\n    })\n\n  createTest('send custom errors')\n    .withRum()\n    .withBody(createBody('DD_RUM.addError(foo())'))\n    .run(async ({ flushEvents, page, intakeRegistry, baseUrl, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'custom',\n        stack: ['Error: oh snap', `at foo @ ${baseUrl}:`, `handler @ ${baseUrl}:`],\n        handlingStack: ['HandlingStack: error', `handler @ ${baseUrl}:`],\n        handling: 'handled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(0)\n      })\n    })\n\n  // non-native errors should have the same stack trace as regular errors on ALL BROWSERS\n  createTest('send non-native errors')\n    .withRum()\n    .withBody(createBody('DD_RUM.addError(customError())'))\n    .run(async ({ flushEvents, page, intakeRegistry, baseUrl, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'custom',\n        stack: ['Error: oh snap', `at customError @ ${baseUrl}:`, `handler @ ${baseUrl}:`],\n        handlingStack: ['HandlingStack: error', `handler @ ${baseUrl}:`],\n        handling: 'handled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(0)\n      })\n    })\n\n  // non-native should have the same stack trace as regular errors on ALL BROWSERS\n  // this should also work for custom error classes that inherit from other custom error classes\n  createTest('send non-native errors with inheritance')\n    .withRum()\n    .withBody(createBody('DD_RUM.addError(customErrorWithInheritance())'))\n    .run(async ({ flushEvents, page, intakeRegistry, baseUrl, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: 'oh snap',\n        source: 'custom',\n        stack: ['CustomTestError3: oh snap', `at customErrorWithInheritance @ ${baseUrl}:`, `handler @ ${baseUrl}:`],\n        handlingStack: ['HandlingStack: error', `handler @ ${baseUrl}:`],\n        handling: 'handled',\n      })\n      withBrowserLogs((browserLogs) => {\n        expect(browserLogs).toHaveLength(0)\n      })\n    })\n\n  createTest('send CSP violation errors')\n    .withRum()\n    .withBody(\n      createBody(`\n      const script = document.createElement('script');\n      script.src = \"https://example.com/foo.js\"\n      document.body.appendChild(script)\n      `)\n    )\n    .run(async ({ page, browserName, intakeRegistry, baseUrl, flushEvents, withBrowserLogs }) => {\n      const button = page.locator('button')\n      await button.click()\n\n      await flushEvents()\n\n      expect(intakeRegistry.rumErrorEvents).toHaveLength(1)\n      expectError(intakeRegistry.rumErrorEvents[0].error, {\n        message: /^csp_violation: 'https:\\/\\/example\\.com\\/foo\\.js' blocked by 'script-src(-elem)?' directive$/,\n        source: 'report',\n        stack: [\n          /^script-src(-elem)?: 'https:\\/\\/example\\.com\\/foo\\.js' blocked by 'script-src(-elem)?' directive of the policy/,\n          `  at <anonymous> @ ${baseUrl}:`,\n        ],\n        handling: 'unhandled',\n        csp: {\n          disposition: 'enforce',\n        },\n      })\n      withBrowserLogs((browserLogs) => {\n        if (browserName === 'firefox') {\n          // Firefox has an additional Warning log: \"Loading failed for the <script> with source 'https://example.com/foo.js'\"\n          expect(browserLogs).toHaveLength(2)\n        } else {\n          expect(browserLogs).toHaveLength(1)\n        }\n      })\n    })\n})\n\nfunction expectError(\n  error: RumErrorEvent['error'],\n  expected: {\n    message: string | RegExp\n    source: string\n    stack?: Array<string | RegExp>\n    handlingStack?: Array<string | RegExp>\n    handling: 'handled' | 'unhandled'\n    csp?: {\n      disposition?: 'enforce' | 'report'\n    }\n  }\n) {\n  expect(error.message).toMatch(expected.message)\n  expect(error.source).toBe(expected.source)\n  expectStack(error.stack, expected.stack)\n  expectStack(error.handling_stack, expected.handlingStack)\n  expect(error.handling).toBe(expected.handling)\n  expect(error.csp?.disposition).toBe(expected.csp?.disposition)\n}\n\nfunction expectStack(stack: string | undefined, expectedLines?: Array<string | RegExp>) {\n  if (expectedLines === undefined) {\n    expect(stack).toBeUndefined()\n  } else {\n    expect(stack).toBeDefined()\n    const actualLines = stack!.split('\\n')\n    expect.soft(actualLines.length).toBeGreaterThanOrEqual(expectedLines.length)\n    expect.soft(actualLines.length).toBeLessThanOrEqual(expectedLines.length + 2) // FF may have more lines of stack\n\n    expectedLines.forEach((line, i) => {\n      if (typeof line !== 'string') {\n        return expect(actualLines[i]).toMatch(line)\n      }\n\n      if (i === 0) {\n        expect(actualLines[i]).toMatch(line)\n      } else {\n        expect(actualLines[i]).toContain(line)\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "test/e2e/scenario/rum/graphql.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../../lib/framework'\n\nfunction buildGraphQlConfig({\n  trackPayload = false,\n  trackResponseErrors = false,\n}: {\n  trackPayload?: boolean\n  trackResponseErrors?: boolean\n} = {}) {\n  return {\n    allowedGraphQlUrls: [{ match: (url: string) => url.includes('graphql'), trackPayload, trackResponseErrors }],\n  }\n}\n\ntest.describe('GraphQL tracking', () => {\n  createTest('track GraphQL query via XHR and include payload')\n    .withRum(buildGraphQlConfig({ trackPayload: true }))\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        const xhr = new XMLHttpRequest()\n        xhr.open('POST', '/graphql')\n        xhr.setRequestHeader('Content-Type', 'application/json')\n        xhr.send(\n          JSON.stringify({\n            query: 'query GetUser($id: ID!) { user(id: $id) { name email } }',\n            operationName: 'GetUser',\n            variables: { id: '123' },\n          })\n        )\n      })\n\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/graphql'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.method).toBe('POST')\n      expect(resourceEvent.resource.graphql).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: 'query GetUser($id: ID!) { user(id: $id) { name email } }',\n      })\n    })\n\n  createTest('track GraphQL mutation via fetch without payload')\n    .withRum(buildGraphQlConfig())\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() =>\n        window.fetch('/graphql', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({\n            query: 'mutation CreateUser($input: UserInput!) { createUser(input: $input) { id name } }',\n            operationName: 'CreateUser',\n            variables: { input: { name: 'John Doe', email: 'john@example.com' } },\n          }),\n        })\n      )\n\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/graphql'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.method).toBe('POST')\n      expect(resourceEvent.resource.graphql).toEqual({\n        operationType: 'mutation',\n        operationName: 'CreateUser',\n        variables: '{\"input\":{\"name\":\"John Doe\",\"email\":\"john@example.com\"}}',\n        payload: undefined,\n      })\n    })\n\n  createTest('should not track GraphQL for non-matching URLs')\n    .withRum(buildGraphQlConfig({ trackPayload: true }))\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        const xhr = new XMLHttpRequest()\n        xhr.open('GET', '/ok')\n        xhr.send()\n      })\n\n      await flushEvents()\n\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/ok'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.graphql).toBeUndefined()\n    })\n\n  createTest('track GraphQL response errors via fetch')\n    .withRum(buildGraphQlConfig({ trackPayload: false, trackResponseErrors: true }))\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() =>\n        window.fetch('/graphql?scenario=validation-error', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({\n            query: 'query GetUser { user { unknownField } }',\n            operationName: 'GetUser',\n          }),\n        })\n      )\n\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/graphql'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.graphql).toEqual({\n        operationType: 'query',\n        operationName: 'GetUser',\n        variables: undefined,\n        payload: undefined,\n        error_count: 1,\n        errors: [\n          {\n            message: 'Field \"unknownField\" does not exist',\n            code: 'GRAPHQL_VALIDATION_FAILED',\n            locations: [{ line: 2, column: 5 }],\n            path: ['user', 'unknownField'],\n          },\n        ],\n      })\n    })\n\n  createTest('track GraphQL response with multiple errors via XHR')\n    .withRum(buildGraphQlConfig({ trackResponseErrors: true }))\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        const xhr = new XMLHttpRequest()\n        xhr.open('POST', '/graphql?scenario=multiple-errors')\n        xhr.setRequestHeader('Content-Type', 'application/json')\n        xhr.send(\n          JSON.stringify({\n            query: 'query GetUser { user { name } }',\n          })\n        )\n      })\n\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/graphql'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.graphql?.error_count).toBe(2)\n      expect(resourceEvent.resource.graphql?.errors).toEqual([\n        { message: 'User not found' },\n        { message: 'Insufficient permissions', code: 'UNAUTHORIZED' },\n      ])\n    })\n\n  createTest('should not track response errors when trackResponseErrors is false')\n    .withRum(buildGraphQlConfig({ trackPayload: true, trackResponseErrors: false }))\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() =>\n        window.fetch('/graphql?scenario=validation-error', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({\n            query: 'query Test { test }',\n          }),\n        })\n      )\n\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/graphql'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.graphql?.error_count).toBeUndefined()\n      expect(resourceEvent.resource.graphql?.errors).toBeUndefined()\n    })\n\n  createTest('track GraphQL GET request with persisted query')\n    .withRum(buildGraphQlConfig())\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        const operationName = 'GetUser'\n        const variables = JSON.stringify({ id: '123' })\n        const extensions = JSON.stringify({\n          persistedQuery: { version: 1, sha256Hash: 'abc123' },\n        })\n        const url = `/graphql?operationName=${encodeURIComponent(operationName)}&variables=${encodeURIComponent(variables)}&extensions=${encodeURIComponent(extensions)}`\n\n        return window.fetch(url, { method: 'GET' })\n      })\n\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('/graphql'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.method).toBe('GET')\n      expect(resourceEvent.resource.graphql).toEqual({\n        operationType: undefined,\n        operationName: 'GetUser',\n        variables: '{\"id\":\"123\"}',\n        payload: undefined,\n      })\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/rum/init.scenario.ts",
    "content": "import type { Context } from '@datadog/browser-core'\nimport { test, expect } from '@playwright/test'\nimport type { IntakeRegistry, BrowserLog } from '../../lib/framework'\nimport { createTest, createWorker } from '../../lib/framework'\n\ntest.describe('API calls and events around init', () => {\n  createTest('should display a console log when calling init without configuration')\n    .withRum()\n    .withRumInit(() => {\n      ;(window.DD_RUM! as unknown as { init(): void }).init()\n    })\n    .run(({ withBrowserLogs }) => {\n      withBrowserLogs((logs) => {\n        expect(logs).toHaveLength(1)\n        expect(logs[0].message).toEqual(expect.stringContaining('Datadog Browser SDK'))\n        expect(logs[0].message).toEqual(expect.stringContaining('Missing configuration'))\n      })\n    })\n\n  createTest('should be associated to corresponding views when views are automatically tracked')\n    .withRum()\n    .withRumSlim()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.addError('before manual view')\n      window.DD_RUM!.addAction('before manual view')\n      window.DD_RUM!.addTiming('before manual view')\n\n      setTimeout(() => window.DD_RUM!.startView('manual view'), 10)\n\n      setTimeout(() => {\n        window.DD_RUM!.addError('after manual view')\n        window.DD_RUM!.addAction('after manual view')\n        window.DD_RUM!.addTiming('after manual view')\n      }, 20)\n\n      setTimeout(() => window.DD_RUM!.init(configuration), 30)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const initialView = intakeRegistry.rumViewEvents[0]\n      expect(initialView.view.name).toBeUndefined()\n      expect(initialView.view.custom_timings).toEqual({\n        before_manual_view: expect.any(Number),\n      })\n\n      const manualView = intakeRegistry.rumViewEvents[1]\n      expect(manualView.view.name).toBe('manual view')\n      expect(manualView.view.custom_timings).toEqual({\n        after_manual_view: expect.any(Number),\n      })\n\n      const documentEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'document')!\n      expect(documentEvent.view.id).toBe(initialView.view.id)\n\n      expectToHaveErrors(\n        intakeRegistry,\n        { message: 'Provided \"before manual view\"', viewId: initialView.view.id },\n        { message: 'Provided \"after manual view\"', viewId: manualView.view.id }\n      )\n\n      expectToHaveActions(\n        intakeRegistry,\n        { name: 'before manual view', viewId: initialView.view.id },\n        { name: 'after manual view', viewId: manualView.view.id }\n      )\n    })\n\n  createTest('should be associated to corresponding views when views are manually tracked')\n    .withRum({ trackViewsManually: true })\n    .withRumSlim()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.addError('before init')\n      window.DD_RUM!.addAction('before init')\n      window.DD_RUM!.addTiming('before init')\n\n      setTimeout(() => window.DD_RUM!.init(configuration), 10)\n      setTimeout(() => {\n        window.DD_RUM!.addError('before manual view')\n        window.DD_RUM!.addAction('before manual view')\n        window.DD_RUM!.addTiming('before manual view')\n      }, 20)\n\n      setTimeout(() => window.DD_RUM!.startView('manual view'), 30)\n\n      setTimeout(() => {\n        window.DD_RUM!.addError('after manual view')\n        window.DD_RUM!.addAction('after manual view')\n        window.DD_RUM!.addTiming('after manual view')\n        window.DD_RUM!.setViewName('after manual view')\n      }, 40)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const initialView = intakeRegistry.rumViewEvents[0]\n      expect(initialView.view.name).toBe('after manual view')\n      expect(initialView.view.custom_timings).toEqual({\n        before_init: expect.any(Number),\n        before_manual_view: expect.any(Number),\n        after_manual_view: expect.any(Number),\n      })\n\n      const documentEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'document')!\n      expect(documentEvent.view.id).toBe(initialView.view.id)\n\n      expectToHaveErrors(\n        intakeRegistry,\n        { message: 'Provided \"before init\"', viewId: initialView.view.id },\n        { message: 'Provided \"before manual view\"', viewId: initialView.view.id },\n        { message: 'Provided \"after manual view\"', viewId: initialView.view.id }\n      )\n\n      expectToHaveActions(\n        intakeRegistry,\n        { name: 'before init', viewId: initialView.view.id },\n        { name: 'before manual view', viewId: initialView.view.id },\n        { name: 'after manual view', viewId: initialView.view.id, viewName: 'after manual view' }\n      )\n    })\n\n  createTest('should use the provided url option instead of location')\n    .withRum()\n    .withRumSlim()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.init(configuration)\n\n      setTimeout(\n        () =>\n          window.DD_RUM!.startView({\n            name: 'manual view',\n            url: 'https://example.com/overridden-path',\n          }),\n        10\n      )\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const manualView = intakeRegistry.rumViewEvents.find((event) => event.view.name === 'manual view')!\n      expect(manualView).toBeTruthy()\n      expect(manualView.view.url).toBe('https://example.com/overridden-path')\n    })\n\n  createTest('should be able to set view context')\n    .withRum()\n    .withRumSlim()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.init(configuration)\n      window.DD_RUM!.setViewContext({ foo: 'bar' })\n      window.DD_RUM!.setViewContextProperty('bar', 'foo')\n\n      // context should populate the context of the children events\n      window.DD_RUM!.addAction('custom action')\n      window.DD_RUM!.addError('custom error')\n\n      // context should not populate the context of the next view\n      setTimeout(() => window.DD_RUM!.startView('manual view'), 10)\n      setTimeout(() => {\n        window.DD_RUM!.addAction('after manual view')\n        window.DD_RUM!.addError('after manual view')\n      }, 20)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const initialView = intakeRegistry.rumViewEvents[0]\n      const nextView = intakeRegistry.rumViewEvents[1]\n\n      expect(initialView.context).toEqual(expect.objectContaining({ foo: 'bar', bar: 'foo' }))\n      expect(nextView.context!.foo).toBeUndefined()\n\n      expectToHaveActions(\n        intakeRegistry,\n        {\n          name: 'custom action',\n          viewId: initialView.view.id,\n          context: { foo: 'bar', bar: 'foo' },\n        },\n        {\n          name: 'after manual view',\n          viewId: nextView.view.id,\n        }\n      )\n      expectToHaveErrors(\n        intakeRegistry,\n        {\n          message: 'Provided \"custom error\"',\n          viewId: initialView.view.id,\n          context: { foo: 'bar', bar: 'foo' },\n        },\n        {\n          message: 'Provided \"after manual view\"',\n          viewId: nextView.view.id,\n        }\n      )\n    })\n\n  createTest('get the view context')\n    .withRum()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.init(configuration)\n      window.DD_RUM!.setViewContext({ foo: 'bar' })\n    })\n    .run(async ({ page }) => {\n      const viewContext = await page.evaluate(() => window.DD_RUM?.getViewContext())\n      expect(viewContext).toEqual({ foo: 'bar' })\n    })\n})\n\ntest.describe('beforeSend', () => {\n  createTest('allows to edit events context with feature flag')\n    .withRum({\n      beforeSend: (event: any) => {\n        event.context!.foo = 'bar'\n        return true\n      },\n    })\n    .withRumSlim()\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const initialView = intakeRegistry.rumViewEvents[0]\n      expect(initialView.context).toEqual(expect.objectContaining({ foo: 'bar' }))\n      const initialDocument = intakeRegistry.rumResourceEvents[0]\n      expect(initialDocument.context).toEqual(expect.objectContaining({ foo: 'bar' }))\n    })\n\n  createTest('allows to replace events context')\n    .withRum({\n      beforeSend: (event) => {\n        event.context = { foo: 'bar' }\n        return true\n      },\n    })\n    .withRumSlim()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.init(configuration)\n      window.DD_RUM!.setGlobalContextProperty('foo', 'baz')\n      window.DD_RUM!.setGlobalContextProperty('zig', 'zag')\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const initialView = intakeRegistry.rumViewEvents[0]\n      expect(initialView.context).toEqual(expect.objectContaining({ foo: 'bar' }))\n      const initialDocument = intakeRegistry.rumResourceEvents[0]\n      expect(initialDocument.context).toEqual(expect.objectContaining({ foo: 'bar' }))\n    })\n})\n\ntest.describe('allowedTrackingOrigins', () => {\n  createTest('should not warn when allowedTrackingOrigins matches current domain')\n    .withRum()\n    .withRumInit((configuration) => {\n      const currentOrigin = window.location.origin\n      window.DD_RUM!.init({\n        ...configuration,\n        allowedTrackingOrigins: [currentOrigin],\n      })\n    })\n    .run(({ withBrowserLogs }) => {\n      withBrowserLogs((logs) => {\n        expect(logs).toHaveLength(0)\n      })\n    })\n\n  createTest('should not warn when allowedTrackingOrigins matches current domain with regex')\n    .withRum()\n    .withRumInit((configuration) => {\n      const currentOrigin = window.location.origin\n      const escapedOrigin = currentOrigin.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n      window.DD_RUM!.init({\n        ...configuration,\n        allowedTrackingOrigins: [new RegExp(`^${escapedOrigin}$`)],\n      })\n    })\n    .run(({ withBrowserLogs }) => {\n      withBrowserLogs((logs) => {\n        expect(logs).toHaveLength(0)\n      })\n    })\n\n  createTest('should not warn when allowedTrackingOrigins matches current domain with function')\n    .withRum()\n    .withRumInit((configuration) => {\n      const currentOrigin = window.location.origin\n      window.DD_RUM!.init({\n        ...configuration,\n        allowedTrackingOrigins: [(origin: string) => origin === currentOrigin],\n      })\n    })\n    .run(({ withBrowserLogs }) => {\n      withBrowserLogs((logs) => {\n        expect(logs).toHaveLength(0)\n      })\n    })\n\n  createTest('initializing RUM should not produce logs')\n    .withRum()\n    .run(({ withBrowserLogs }) => {\n      withBrowserLogs((logs) => {\n        expect(logs).toHaveLength(0)\n      })\n    })\n\n  createTest('should warn when allowedTrackingOrigins does not match current domain')\n    .withRum()\n    .withRumInit((configuration) => {\n      window.DD_RUM!.init({\n        ...configuration,\n        allowedTrackingOrigins: ['https://different-domain.com'],\n      })\n    })\n    .run(async ({ withBrowserLogs, intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      withBrowserLogs((logs) => {\n        const errorLogs = logs.filter(\n          (log) => log.message.includes('SDK initialized on a non-allowed domain') && log.level === 'error'\n        )\n        expect(errorLogs).toHaveLength(1)\n      })\n\n      expect(intakeRegistry.rumViewEvents.length).toBe(0)\n    })\n})\n\ntest.describe('Synthetics Browser Test', () => {\n  createTest('ignores init() call if Synthetics will inject its own instance of RUM')\n    .withRum()\n    .withRumInit((configuration) => {\n      ;(window as any)._DATADOG_SYNTHETICS_INJECTS_RUM = true\n      window.DD_RUM!.init(configuration)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      expect(intakeRegistry.rumViewEvents).toHaveLength(0)\n    })\n\n  createTest('enriches events with the synthetics context from the global variable')\n    .withRum()\n    .withRumInit((configuration) => {\n      ;(window as any)._DATADOG_SYNTHETICS_RUM_CONTEXT = {\n        test_id: 'test-abc',\n        result_id: 'result-xyz',\n        run_type: 'scheduled',\n      }\n      window.DD_RUM!.init(configuration)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      expect(intakeRegistry.rumViewEvents[0]).toEqual(\n        expect.objectContaining({\n          session: expect.objectContaining({ type: 'synthetics' }),\n          synthetics: {\n            test_id: 'test-abc',\n            result_id: 'result-xyz',\n            run_type: 'scheduled',\n            injected: false,\n          },\n        })\n      )\n    })\n\n  createTest('enriches events with the synthetics context from the cookie')\n    .withRum()\n    .withRumInit((configuration) => {\n      const context = { test_id: 'test-abc', result_id: 'result-xyz', run_type: 'scheduled' }\n      document.cookie = `datadog-synthetics-rum-context=${encodeURIComponent(JSON.stringify(context))}`\n      window.DD_RUM!.init(configuration)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      expect(intakeRegistry.rumViewEvents[0]).toEqual(\n        expect.objectContaining({\n          session: expect.objectContaining({ type: 'synthetics' }),\n          synthetics: {\n            test_id: 'test-abc',\n            result_id: 'result-xyz',\n            run_type: 'scheduled',\n            injected: false,\n          },\n        })\n      )\n    })\n})\n\ntest.describe('Service workers Rum', () => {\n  createTest('service worker with worker rum - esm')\n    .withWorker(createWorker().withRum())\n    .run(async ({ flushEvents, intakeRegistry, browserName, withBrowserLogs }) => {\n      test.skip(browserName !== 'chromium', 'Non-Chromium browsers do not support ES modules in Service Workers')\n\n      await flushEvents()\n\n      expect(intakeRegistry.rumEvents).toHaveLength(0)\n      withBrowserLogs((logs) => expectNoSessionWarning(browserName, logs))\n    })\n\n  createTest('service worker with worker rum - importScripts')\n    .withWorker(createWorker({ importScripts: true }).withRum())\n    .run(async ({ flushEvents, intakeRegistry, browserName, withBrowserLogs }) => {\n      test.skip(\n        browserName === 'webkit',\n        'BrowserStack overrides the localhost URL with bs-local.com and cannot be used to install a Service Worker'\n      )\n\n      await flushEvents()\n\n      expect(intakeRegistry.rumEvents).toHaveLength(0)\n      withBrowserLogs((logs) => expectNoSessionWarning(browserName, logs))\n    })\n})\n\nconst NO_SESSION_WARNING = 'Datadog Browser SDK: No storage available for session. We will not send any data'\n\nfunction expectNoSessionWarning(browserName: string, logs: BrowserLog[]) {\n  // Firefox does not propagate the service worker's console to the main page's console\n  if (browserName !== 'firefox') {\n    expect(logs.filter((log) => log.message.includes(NO_SESSION_WARNING) && log.level === 'warning')).toHaveLength(1)\n  }\n\n  expect(logs.filter((log) => log.level === 'error')).toHaveLength(0)\n}\n\nfunction expectToHaveErrors(\n  events: IntakeRegistry,\n  ...errors: Array<{ message: string; viewId: string; context?: Context }>\n) {\n  expect(events.rumErrorEvents).toHaveLength(errors.length)\n  for (let i = 0; i < errors.length; i++) {\n    const registryError = events.rumErrorEvents[i]\n    const expectedError = errors[i]\n    expect(registryError.error.message).toBe(expectedError.message)\n    expect(registryError.view.id).toBe(expectedError.viewId)\n    if (expectedError.context) {\n      expect(registryError.context).toEqual(expect.objectContaining(expectedError.context))\n    }\n  }\n}\n\nfunction expectToHaveActions(\n  events: IntakeRegistry,\n  ...actions: Array<{ name: string; viewId: string; viewName?: string; context?: Context }>\n) {\n  expect(events.rumActionEvents).toHaveLength(actions.length)\n  for (let i = 0; i < actions.length; i++) {\n    const registryAction = events.rumActionEvents[i]\n    const expectedAction = actions[i]\n    expect(registryAction.action.target!.name).toBe(expectedAction.name)\n    expect(registryAction.view.id).toBe(expectedAction.viewId)\n    if (i === 0 && expectedAction.viewName) {\n      expect(registryAction.view.name).toBe(expectedAction.viewName)\n    }\n    if (expectedAction.context) {\n      expect(registryAction.context).toEqual(expect.objectContaining(expectedAction.context))\n    }\n  }\n}\n"
  },
  {
    "path": "test/e2e/scenario/rum/remoteConfiguration.scenario.ts",
    "content": "import type { Page } from '@playwright/test'\nimport { test, expect } from '@playwright/test'\nimport { createTest, html } from '../../lib/framework'\n\nconst RC_APP_ID = 'e2e'\n\ntest.describe('remote configuration', () => {\n  createTest('should be fetched and applied')\n    .withRum({\n      sessionSampleRate: 100,\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: { applicationId: RC_APP_ID, sessionSampleRate: 1 },\n    })\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.sessionSampleRate).toBe(1)\n    })\n\n  createTest('should resolve an option value from a cookie')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: { applicationId: RC_APP_ID, version: { rcSerializedType: 'dynamic', strategy: 'cookie', name: 'e2e_rc' } },\n    })\n    .withBody(html`\n      <script>\n        document.cookie = 'e2e_rc=my-version;'\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBe('my-version')\n    })\n\n  createTest('should resolve an option value from an element content')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: RC_APP_ID,\n        version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#version' },\n      },\n    })\n    .withBody(html`<span id=\"version\">123</span>`)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBe('123')\n    })\n\n  createTest('should resolve an option value from an element attribute')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: RC_APP_ID,\n        version: { rcSerializedType: 'dynamic', strategy: 'dom', selector: '#version', attribute: 'data-version' },\n      },\n    })\n    .withBody(html`<span id=\"version\" data-version=\"123\"></span>`)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBe('123')\n    })\n\n  createTest('should resolve an option value from js variable')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: 'e2e',\n        version: { rcSerializedType: 'dynamic', strategy: 'js', path: 'dataLayer.version' },\n      },\n    })\n    .withBody(html`\n      <script>\n        dataLayer = {\n          version: 'js-version',\n        }\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBe('js-version')\n    })\n\n  createTest('should resolve an option value from localStorage')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: 'e2e',\n        version: { rcSerializedType: 'dynamic', strategy: 'localStorage', key: 'dd_app_version' },\n      },\n    })\n    .withBody(html`\n      <script>\n        localStorage.setItem('dd_app_version', 'localStorage-version')\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBe('localStorage-version')\n    })\n\n  createTest('should resolve an option value from localStorage with an extractor')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: 'e2e',\n        version: {\n          rcSerializedType: 'dynamic',\n          strategy: 'localStorage',\n          key: 'dd_app_version',\n          extractor: { rcSerializedType: 'regex', value: '\\\\d+\\\\.\\\\d+\\\\.\\\\d+' },\n        },\n      },\n    })\n    .withBody(html`\n      <script>\n        localStorage.setItem('dd_app_version', 'version-1.2.3-beta')\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBe('1.2.3')\n    })\n\n  createTest('should resolve to undefined when localStorage key is missing')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: 'e2e',\n        version: { rcSerializedType: 'dynamic', strategy: 'localStorage', key: 'non_existent_key' },\n      },\n    })\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBeUndefined()\n    })\n\n  createTest('should handle localStorage access failure gracefully')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: 'e2e',\n        version: { rcSerializedType: 'dynamic', strategy: 'localStorage', key: 'dd_app_version' },\n      },\n    })\n    .withBody(html`\n      <script>\n        Object.defineProperty(window, 'localStorage', {\n          get: function () {\n            throw new Error('localStorage is not available')\n          },\n          configurable: true,\n        })\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n      expect(initConfiguration.version).toBeUndefined()\n    })\n\n  createTest('should resolve user context')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: RC_APP_ID,\n        user: [{ key: 'id', value: { rcSerializedType: 'dynamic', strategy: 'cookie', name: 'e2e_rc' } }],\n      },\n    })\n    .withBody(html`\n      <script>\n        document.cookie = 'e2e_rc=my-user-id;'\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const user = await page.evaluate(() => window.DD_RUM!.getUser())\n      expect(user.id).toBe('my-user-id')\n    })\n\n  createTest('should resolve global context')\n    .withRum({\n      remoteConfigurationId: 'e2e',\n    })\n    .withRemoteConfiguration({\n      rum: {\n        applicationId: RC_APP_ID,\n        context: [\n          {\n            key: 'foo',\n            value: { rcSerializedType: 'dynamic', strategy: 'cookie', name: 'e2e_rc' },\n          },\n        ],\n      },\n    })\n    .withBody(html`\n      <script>\n        document.cookie = 'e2e_rc=bar;'\n      </script>\n    `)\n    .run(async ({ page }) => {\n      await waitForRemoteConfigurationToBeApplied(page)\n      const globalContext = await page.evaluate(() => window.DD_RUM!.getGlobalContext())\n      expect(globalContext.foo).toEqual('bar')\n    })\n})\n\nasync function waitForRemoteConfigurationToBeApplied(page: Page) {\n  for (let i = 0; i < 20; i++) {\n    const initConfiguration = await page.evaluate(() => window.DD_RUM!.getInitConfiguration()!)\n    if (initConfiguration.applicationId === RC_APP_ID) {\n      break\n    }\n    console.log('wait for remote configuration to be applied')\n    await page.waitForTimeout(100)\n  }\n}\n"
  },
  {
    "path": "test/e2e/scenario/rum/resources.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport type { RumResourceEvent } from '@datadog/browser-rum'\nimport { isContentTypeAvailableInPerformanceEntry } from '../../lib/helpers/browser'\nimport type { IntakeRegistry } from '../../lib/framework'\nimport { createTest, html } from '../../lib/framework'\n\nconst REQUEST_DURATION = 200\n\ntest.describe('rum resources', () => {\n  createTest('track xhr timings')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, sendXhr }) => {\n      await sendXhr(`/ok?duration=${REQUEST_DURATION}`)\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.url.includes('/ok'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.method).toBe('GET')\n      expect(resourceEvent.resource.status_code).toBe(200)\n      expectToHaveValidTimings(resourceEvent)\n    })\n\n  createTest('track redirect xhr timings')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, sendXhr }) => {\n      await sendXhr(`/redirect?duration=${REQUEST_DURATION}`)\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.url.includes('/redirect'))!\n      expect(resourceEvent).not.toBeUndefined()\n      expect(resourceEvent.resource.method).toEqual('GET')\n      expect(resourceEvent.resource.status_code).toEqual(200)\n      expectToHaveValidTimings(resourceEvent)\n      expect(resourceEvent.resource.redirect).not.toBeUndefined()\n      expect(resourceEvent.resource.redirect!.duration).toBeGreaterThan(0)\n    })\n\n  createTest(\"don't track disallowed cross origin xhr timings\")\n    .withRum()\n    .run(async ({ servers, intakeRegistry, flushEvents, sendXhr }) => {\n      await sendXhr(`${servers.crossOrigin.origin}/ok?duration=${REQUEST_DURATION}`)\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.url.includes('/ok'))!\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent.resource.method).toEqual('GET')\n      expect(resourceEvent.resource.status_code).toEqual(200)\n      expect(resourceEvent.resource.duration).toBeGreaterThan(0)\n      expect(resourceEvent.resource.download).toBeUndefined()\n    })\n\n  createTest('track allowed cross origin xhr timings')\n    .withRum()\n    .run(async ({ servers, intakeRegistry, flushEvents, sendXhr }) => {\n      await sendXhr(`${servers.crossOrigin.origin}/ok?timing-allow-origin=true&duration=${REQUEST_DURATION}`)\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.url.includes('/ok'))!\n      expect(resourceEvent).not.toBeUndefined()\n      expect(resourceEvent.resource.method).toEqual('GET')\n      expect(resourceEvent.resource.status_code).toEqual(200)\n      expectToHaveValidTimings(resourceEvent)\n    })\n\n  createTest('retrieve early requests timings')\n    .withRum()\n    .withHead(html` <link rel=\"stylesheet\" href=\"/empty.css\" /> `)\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('empty.css'))\n      expect(resourceEvent).toBeDefined()\n      expectToHaveValidTimings(resourceEvent!)\n    })\n\n  createTest('collect fetch requests made before init with trackEarlyRequests')\n    .withHead(html`\n      <script>\n        fetch('/ok')\n      </script>\n    `)\n    .withRum({ trackEarlyRequests: true })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'fetch')\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent!.resource.url).toContain('/ok')\n    })\n\n  createTest('retrieve initial document timings')\n    .withRum()\n    .run(async ({ baseUrl, intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'document')\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent!.resource.url).toBe(baseUrl)\n      expectToHaveValidTimings(resourceEvent!)\n    })\n\n  test.describe('XHR abort support', () => {\n    createTest('track aborted XHR')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const xhr = new XMLHttpRequest()\n              xhr.open('GET', '/ok?duration=1000')\n              xhr.send()\n              setTimeout(() => {\n                xhr.abort()\n                resolve(undefined)\n              }, 100)\n            })\n        )\n\n        await flushEvents()\n\n        expectXHR(intakeRegistry).toBeAborted()\n      })\n\n    createTest('aborting an unsent XHR should be ignored')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const xhr = new XMLHttpRequest()\n              xhr.open('GET', '/ok')\n              xhr.abort()\n              xhr.send()\n              xhr.addEventListener('loadend', () => resolve(undefined))\n            })\n        )\n\n        await flushEvents()\n\n        expectXHR(intakeRegistry).toBeLoaded()\n      })\n\n    createTest('aborting an XHR when state becomes DONE and before the loadend event should be ignored')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const xhr = new XMLHttpRequest()\n              xhr.open('GET', '/ok')\n              xhr.onreadystatechange = () => {\n                if (xhr.readyState === XMLHttpRequest.DONE) {\n                  xhr.abort()\n                  resolve(undefined)\n                }\n              }\n              xhr.send()\n            })\n        )\n\n        await flushEvents()\n\n        expectXHR(intakeRegistry).toBeLoaded()\n      })\n\n    createTest('aborting an XHR after the loadend event should be ignored')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const xhr = new XMLHttpRequest()\n              xhr.open('GET', '/ok')\n              xhr.addEventListener('loadend', () => {\n                setTimeout(() => {\n                  xhr.abort()\n                  resolve(undefined)\n                })\n              })\n              xhr.send()\n            })\n        )\n\n        await flushEvents()\n\n        expectXHR(intakeRegistry).toBeLoaded()\n      })\n\n    function expectXHR(intakeRegistry: IntakeRegistry) {\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'xhr')\n      expect(resourceEvent).toBeTruthy()\n\n      return {\n        toBeAborted() {\n          expect(resourceEvent?.resource.status_code).toBe(0)\n        },\n\n        toBeLoaded() {\n          expect(resourceEvent?.resource.status_code).toBe(200)\n        },\n      }\n    }\n  })\n\n  test.describe('fetch abort support', () => {\n    createTest('track aborted fetch')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const controller = new AbortController()\n              fetch('/ok?duration=1000', { signal: controller.signal }).catch(() => {\n                // ignore abortion error\n                resolve(undefined)\n              })\n              setTimeout(() => {\n                controller.abort()\n              }, 100)\n            })\n        )\n\n        await flushEvents()\n\n        const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'fetch')\n        expect(resourceEvent).toBeTruthy()\n        expect(resourceEvent?.resource.status_code).toBe(0)\n      })\n  })\n\n  createTest('track redirect fetch timings')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(\n        () =>\n          new Promise<void>((resolve) => {\n            fetch('/redirect?duration=200').then(\n              () => resolve(undefined),\n              () => {\n                throw Error('Issue with fetch call')\n              }\n            )\n          })\n      )\n      await flushEvents()\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.url.includes('/redirect'))!\n      expect(resourceEvent).not.toBeUndefined()\n      expect(resourceEvent.resource.method).toEqual('GET')\n      expect(resourceEvent.resource.status_code).toEqual(200)\n      expectToHaveValidTimings(resourceEvent)\n      expect(resourceEvent.resource.redirect).not.toBeUndefined()\n      expect(resourceEvent.resource.redirect!.duration).toBeGreaterThan(0)\n    })\n\n  createTest('track concurrent fetch to same resource')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page, browserName }) => {\n      test.skip(browserName === 'webkit', 'Safari does not emit predictable timings events for concurrent fetches')\n\n      await page.evaluate(\n        () =>\n          new Promise<void>((resolve) => {\n            Promise.all([fetch('/ok'), fetch('/ok')])\n              .then(() => resolve())\n              .catch(() => resolve())\n          })\n      )\n\n      await flushEvents()\n\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((event) => event.resource.type === 'fetch')\n\n      expect(resourceEvents[0]).toBeTruthy()\n      expect(resourceEvents[0]?.resource.size).toBeDefined()\n\n      expect(resourceEvents[1]).toBeTruthy()\n      expect(resourceEvents[1]?.resource.size).toBeDefined()\n    })\n\n  test.describe('resource response content-type', () => {\n    createTest('collect resource response content-type for static resources')\n      .withRum()\n      .withHead(html`<link rel=\"stylesheet\" href=\"/empty.css\" />`)\n      .run(async ({ intakeRegistry, flushEvents, browserName }) => {\n        test.skip(\n          isContentTypeAvailableInPerformanceEntry(test, browserName) === false,\n          'contentType is not available in this browser'\n        )\n\n        await flushEvents()\n\n        const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.url.includes('empty.css'))\n        expect(resourceEvent).toBeDefined()\n        expect(resourceEvent!.resource.response).toBeDefined()\n        expect(resourceEvent!.resource.response!.headers).toBeDefined()\n        expect(resourceEvent!.resource.response!.headers!['content-type']).toBe('text/css')\n      })\n\n    createTest('collect resource response content-type for XHR resources')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page, browserName }) => {\n        // Firefox 129+ can use resource timing entries to collect xhr content-type,\n        // other browsers will have to retrieve the it from the response headers\n        test.skip(\n          isContentTypeAvailableInPerformanceEntry(test, browserName) === false,\n          'contentType is not available in this browser'\n        )\n\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const xhr = new XMLHttpRequest()\n              xhr.addEventListener('loadend', () => resolve())\n              xhr.open('GET', '/ok')\n              xhr.send()\n            })\n        )\n\n        await flushEvents()\n\n        const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'xhr')\n        expect(resourceEvent).toBeDefined()\n        expect(resourceEvent!.resource.response).toBeDefined()\n        expect(resourceEvent!.resource.response!.headers).toBeDefined()\n        expect(resourceEvent!.resource.response!.headers!['content-type']).toBe('text/plain')\n      })\n\n    createTest('collect resource response content-type for fetch resources')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page, browserName }) => {\n        // Firefox 129+ can use resource timing entries to collect fetch content-type\n        // other browsers will have to retrieve the it from the response headers\n        test.skip(\n          isContentTypeAvailableInPerformanceEntry(test, browserName) === false,\n          'contentType is not available in this browser'\n        )\n\n        await page.evaluate(() => fetch('/ok'))\n\n        await flushEvents()\n\n        const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'fetch')\n        expect(resourceEvent).toBeDefined()\n        expect(resourceEvent!.resource.response).toBeDefined()\n        expect(resourceEvent!.resource.response!.headers).toBeDefined()\n        expect(resourceEvent!.resource.response!.headers!['content-type']).toBe('text/plain')\n      })\n  })\n\n  test.describe('support XHRs with same XMLHttpRequest instance', () => {\n    createTest('track XHRs when calling requests one after another')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              const xhr = new XMLHttpRequest()\n              const triggerSecondCall = () => {\n                xhr.removeEventListener('loadend', triggerSecondCall)\n                xhr.addEventListener('loadend', () => resolve(undefined))\n                xhr.open('GET', '/ok?duration=100&call=2')\n                xhr.send()\n              }\n              xhr.addEventListener('loadend', triggerSecondCall)\n              xhr.open('GET', '/ok?duration=100&call=1')\n              xhr.send()\n            })\n        )\n\n        await flushEvents()\n\n        const resourceEvents = intakeRegistry.rumResourceEvents.filter((event) => event.resource.type === 'xhr')\n        expect(resourceEvents).toHaveLength(2)\n        expect(intakeRegistry.rumErrorEvents).toHaveLength(0)\n        expect(resourceEvents[0].resource.url).toContain('/ok?duration=100&call=1')\n        expect(resourceEvents[0].resource.status_code).toEqual(200)\n        expect(resourceEvents[1].resource.url).toContain('/ok?duration=100&call=2')\n        expect(resourceEvents[1].resource.status_code).toEqual(200)\n      })\n  })\n})\n\nfunction expectToHaveValidTimings(resourceEvent: RumResourceEvent) {\n  expect(resourceEvent.date).toBeGreaterThan(0)\n  expect(resourceEvent.resource.duration).toBeGreaterThan(0)\n  const download = resourceEvent.resource.download\n  // timing could have been discarded by the SDK if there was not in the correct order\n  if (download) {\n    expect(download.start).toBeGreaterThan(0)\n  }\n}\n\ntest.describe('resource headers with trackResourceHeaders', () => {\n  const TRACK_RESOURCE_HEADERS_CONFIG = {\n    enableExperimentalFeatures: ['track_resource_headers'],\n    trackResourceHeaders: true,\n  }\n\n  function okUrl(responseHeaders: Record<string, string>): string {\n    const params = new URLSearchParams(\n      Object.entries(responseHeaders).map(([name, value]) => [`response-headers[${name}]`, value])\n    )\n    return `/ok?${params}`\n  }\n\n  createTest('collect response and request headers for fetch when trackResourceHeaders is on')\n    .withRum(TRACK_RESOURCE_HEADERS_CONFIG)\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const url = okUrl({ 'Cache-Control': 'no-cache' })\n      await page.evaluate(\n        (u) =>\n          fetch(u, {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ key: 'value' }),\n          }),\n        url\n      )\n\n      await flushEvents()\n\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.type === 'fetch')\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent!.resource.response!.headers!['content-type']).toBe('text/plain; charset=utf-8')\n      expect(resourceEvent!.resource.response!.headers!['cache-control']).toBe('no-cache')\n      expect(resourceEvent!.resource.request!.headers!['content-type']).toBe('application/json')\n    })\n\n  createTest('collect response headers for XHR')\n    .withRum(TRACK_RESOURCE_HEADERS_CONFIG)\n    .run(async ({ intakeRegistry, flushEvents, sendXhr }) => {\n      await sendXhr(okUrl({ 'Cache-Control': 'no-cache' }))\n\n      await flushEvents()\n\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.type === 'xhr')\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent!.resource.response!.headers!['content-type']).toBe('text/plain; charset=utf-8')\n      expect(resourceEvent!.resource.response!.headers!['cache-control']).toBe('no-cache')\n    })\n\n  createTest('collect headers when MatchHeader uses mixed-case string name')\n    .withRum({\n      ...TRACK_RESOURCE_HEADERS_CONFIG,\n      trackResourceHeaders: [{ name: 'Content-Type', location: 'response' }],\n    })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate((u) => fetch(u), okUrl({ 'Cache-Control': 'no-cache' }))\n\n      await flushEvents()\n\n      const resourceEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.type === 'fetch')\n      expect(resourceEvent).toBeDefined()\n      expect(resourceEvent!.resource.response!.headers!['content-type']).toBe('text/plain; charset=utf-8')\n    })\n\n  createTest('do not collect resource headers when trackResourceHeaders is not set')\n    .withRum({ ...TRACK_RESOURCE_HEADERS_CONFIG, trackResourceHeaders: undefined })\n    .run(async ({ intakeRegistry, flushEvents, sendXhr, page }) => {\n      const url = okUrl({ 'Cache-Control': 'no-cache' })\n      await sendXhr(url)\n      await page.evaluate((u) => fetch(u), url)\n\n      await flushEvents()\n\n      const xhrEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.type === 'xhr')\n      expect(xhrEvent).toBeDefined()\n      expect(xhrEvent!.resource.request).toBeUndefined()\n      expect(xhrEvent!.resource.response?.headers?.['cache-control']).toBeUndefined()\n\n      const fetchEvent = intakeRegistry.rumResourceEvents.find((r) => r.resource.type === 'fetch')\n      expect(fetchEvent).toBeDefined()\n      expect(fetchEvent!.resource.request).toBeUndefined()\n      expect(fetchEvent!.resource.response?.headers?.['cache-control']).toBeUndefined()\n    })\n})\n\ntest.describe('manual resources with startResource/stopResource', () => {\n  createTest('track a manual resource with startResource/stopResource')\n    .withRum({ enableExperimentalFeatures: ['start_stop_resource'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startResource('https://api.example.com/data')\n        window.DD_RUM!.stopResource('https://api.example.com/data')\n      })\n      await flushEvents()\n\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((r) =>\n        r.resource.url.includes('api.example.com/data')\n      )\n      expect(resourceEvents).toHaveLength(1)\n      expect(resourceEvents[0].resource.url).toBe('https://api.example.com/data')\n      expect(resourceEvents[0].resource.type).toBe('other')\n      expect(resourceEvents[0].resource.id).toBeDefined()\n    })\n\n  createTest('track a manual resource with type and method')\n    .withRum({ enableExperimentalFeatures: ['start_stop_resource'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startResource('https://api.example.com/users', {\n          type: 'fetch',\n          method: 'POST',\n        })\n        window.DD_RUM!.stopResource('https://api.example.com/users', {\n          statusCode: 201,\n        })\n      })\n      await flushEvents()\n\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((r) =>\n        r.resource.url.includes('api.example.com/users')\n      )\n      expect(resourceEvents).toHaveLength(1)\n      expect(resourceEvents[0].resource.type).toBe('fetch')\n      expect(resourceEvents[0].resource.method).toBe('POST')\n      expect(resourceEvents[0].resource.status_code).toBe(201)\n    })\n\n  createTest('track multiple concurrent manual resources with resourceKey')\n    .withRum({ enableExperimentalFeatures: ['start_stop_resource'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startResource('https://api.example.com/data', { resourceKey: 'request1' })\n        window.DD_RUM!.startResource('https://api.example.com/data', { resourceKey: 'request2' })\n        window.DD_RUM!.stopResource('https://api.example.com/data', { resourceKey: 'request2' })\n        window.DD_RUM!.stopResource('https://api.example.com/data', { resourceKey: 'request1' })\n      })\n      await flushEvents()\n\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((r) =>\n        r.resource.url.includes('api.example.com/data')\n      )\n      expect(resourceEvents).toHaveLength(2)\n      expect(resourceEvents[0].resource.id).not.toBe(resourceEvents[1].resource.id)\n    })\n\n  createTest('merge contexts from start and stop')\n    .withRum({ enableExperimentalFeatures: ['start_stop_resource'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startResource('https://api.example.com/data', {\n          context: { request_id: 'abc123' },\n        })\n        window.DD_RUM!.stopResource('https://api.example.com/data', {\n          context: { response_size: 1024 },\n        })\n      })\n      await flushEvents()\n\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((r) =>\n        r.resource.url.includes('api.example.com/data')\n      )\n      expect(resourceEvents).toHaveLength(1)\n      expect(resourceEvents[0].context).toEqual(\n        expect.objectContaining({\n          request_id: 'abc123',\n          response_size: 1024,\n        })\n      )\n    })\n\n  createTest('preserve timing when startResource is called before init')\n    .withRum({ enableExperimentalFeatures: ['start_stop_resource'] })\n    .withRumInit((configuration) => {\n      window.DD_RUM!.startResource('https://api.example.com/early')\n\n      setTimeout(() => {\n        window.DD_RUM!.init(configuration)\n        window.DD_RUM!.stopResource('https://api.example.com/early')\n      }, 50)\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n\n      const resourceEvents = intakeRegistry.rumResourceEvents.filter((r) =>\n        r.resource.url.includes('api.example.com/early')\n      )\n      expect(resourceEvents).toHaveLength(1)\n      expect(resourceEvents[0].resource.url).toBe('https://api.example.com/early')\n      expect(resourceEvents[0].resource.duration).toBeGreaterThanOrEqual(40 * 1e6)\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/rum/s8sInject.scenario.ts",
    "content": "import * as fs from 'fs'\nimport { launch } from 'puppeteer'\nimport { test, expect } from '@playwright/test'\nimport { getSdkBundlePath } from '../../lib/framework'\nimport { APPLICATION_ID, CLIENT_TOKEN } from '../../lib/helpers/configuration'\n\ntest.describe('Inject RUM with Puppeteer', () => {\n  // S8s tests inject RUM with puppeteer evaluateOnNewDocument\n  test('should not throw error in chrome', async () => {\n    const isInjected = await injectRumWithPuppeteer()\n    expect(isInjected).toBe(true)\n  })\n})\n\nasync function injectRumWithPuppeteer() {\n  const ddRUM = fs.readFileSync(getSdkBundlePath('rum', '/datadog-rum.js'), 'utf8')\n  const puppeteerBrowser = await launch({ headless: true, devtools: true, args: ['--no-sandbox'] })\n  let injected = true\n\n  const page = await puppeteerBrowser.newPage()\n  await page.evaluateOnNewDocument(\n    `\n        if (location.href !== 'about:blank') {\n          ${ddRUM}\n          window.DD_RUM._setDebug(true)\n          window.DD_RUM.init({\n            applicationId: ${APPLICATION_ID},\n            clientToken: ${CLIENT_TOKEN},\n          })\n          window.DD_RUM.startView()\n        }\n      `\n  )\n  page.on('console', (msg) => {\n    if (msg.type() === 'error') {\n      injected = false\n    }\n  })\n  await page.goto('https://example.com')\n\n  return injected\n}\n"
  },
  {
    "path": "test/e2e/scenario/rum/sessions.scenario.ts",
    "content": "import { SESSION_STORE_KEY, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core'\nimport { RecordType } from '@datadog/browser-rum/src/types'\nimport { test, expect } from '@playwright/test'\nimport { setCookie } from '../../lib/helpers/browser'\nimport { expireSession, findSessionCookie, renewSession } from '../../lib/helpers/session'\nimport { createTest, waitForRequests } from '../../lib/framework'\n\ntest.describe('rum sessions', () => {\n  test.describe('session renewal', () => {\n    createTest('create a new View when the session is renewed')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await renewSession(page, browserContext)\n        await flushEvents()\n        const viewEvents = intakeRegistry.rumViewEvents\n        const firstViewEvent = viewEvents[0]\n        const lastViewEvent = viewEvents[viewEvents.length - 1]\n        expect(firstViewEvent.session.id).not.toBe(lastViewEvent.session.id)\n        expect(firstViewEvent.view.id).not.toBe(lastViewEvent.view.id)\n\n        const distinctIds = new Set(viewEvents.map((viewEvent) => viewEvent.view.id))\n        expect(distinctIds.size).toBe(2)\n      })\n\n    createTest('a single fullSnapshot is taken when the session is renewed')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await renewSession(page, browserContext)\n\n        await flushEvents()\n\n        expect(intakeRegistry.replaySegments).toHaveLength(2)\n\n        const segment = intakeRegistry.replaySegments.at(-1)!\n        expect(segment.creation_reason).toBe('init')\n        expect(segment.records[0].type).toBe(RecordType.Meta)\n        expect(segment.records[1].type).toBe(RecordType.Focus)\n        expect(segment.records[2].type).toBe(RecordType.FullSnapshot)\n        expect(segment.records.slice(3).every((record) => record.type !== RecordType.FullSnapshot)).toBe(true)\n      })\n  })\n\n  test.describe('session expiration', () => {\n    createTest(\"don't send events when session is expired\")\n      // prevent recording start to generate late events\n      .withRum({ startSessionReplayRecordingManually: true })\n      .run(async ({ intakeRegistry, sendXhr, browserContext, page }) => {\n        await expireSession(page, browserContext)\n        intakeRegistry.empty()\n        await sendXhr('/ok')\n        expect(intakeRegistry.isEmpty).toBe(true)\n      })\n  })\n  test.describe('anonymous user id', () => {\n    createTest('persists when session is expired')\n      .withRum()\n      .run(async ({ flushEvents, browserContext, page }) => {\n        const anonymousId = (await findSessionCookie(browserContext))?.aid\n\n        await page.evaluate(() => {\n          window.DD_RUM!.stopSession()\n        })\n        await flushEvents()\n\n        expect((await findSessionCookie(browserContext))?.aid).toEqual(anonymousId)\n      })\n\n    createTest('persists when session renewed')\n      .withRum()\n      .run(async ({ browserContext, page }) => {\n        const anonymousId = (await findSessionCookie(browserContext))?.aid\n        expect(anonymousId).not.toBeNull()\n\n        await page.evaluate(() => {\n          window.DD_RUM!.stopSession()\n        })\n        await page.locator('html').click()\n\n        // The session is not created right away, let's wait until we see a cookie\n        await page.waitForTimeout(1000)\n\n        expect((await findSessionCookie(browserContext))?.aid).toEqual(anonymousId)\n\n        expect(true).toBeTruthy()\n      })\n\n    createTest('removes anonymous id when tracking consent is withdrawn')\n      .withRum()\n      .run(async ({ browserContext, page }) => {\n        expect((await findSessionCookie(browserContext))?.aid).toBeDefined()\n\n        await page.evaluate(() => {\n          window.DD_RUM!.setTrackingConsent('not-granted')\n        })\n\n        expect((await findSessionCookie(browserContext))?.aid).toBeUndefined()\n      })\n  })\n\n  test.describe('manual session expiration', () => {\n    createTest('calling stopSession() stops the session')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              window.DD_RUM!.stopSession()\n              setTimeout(() => {\n                // If called directly after `stopSession`, the action start time may be the same as the\n                // session end time. In this case, the sopped session is used, and the action is\n                // collected.\n                // We might want to improve this by having a strict comparison between the event start\n                // time and session end time.\n                window.DD_RUM!.addAction('foo')\n                resolve()\n              }, 5)\n            })\n        )\n        await flushEvents()\n\n        expect((await findSessionCookie(browserContext))?.isExpired).toEqual('1')\n        expect(intakeRegistry.rumActionEvents).toHaveLength(0)\n      })\n\n    createTest('after calling stopSession(), a user interaction starts a new session')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await page.evaluate(() => {\n          window.DD_RUM!.stopSession()\n        })\n\n        await page.locator('html').click()\n\n        // The session is not created right away, let's wait until we see a cookie\n        await page.waitForTimeout(1000)\n\n        await page.evaluate(() => {\n          window.DD_RUM!.addAction('foo')\n        })\n\n        await flushEvents()\n\n        expect((await findSessionCookie(browserContext))?.isExpired).not.toEqual('1')\n        expect((await findSessionCookie(browserContext))?.id).toBeDefined()\n        expect(intakeRegistry.rumActionEvents).toHaveLength(1)\n      })\n\n    createTest('flush events when the session expires')\n      .withRum()\n      .withLogs()\n      .run(async ({ intakeRegistry, page }) => {\n        expect(intakeRegistry.rumViewEvents).toHaveLength(0)\n        expect(intakeRegistry.logsEvents).toHaveLength(0)\n        expect(intakeRegistry.replaySegments).toHaveLength(0)\n\n        await page.evaluate(() => {\n          window.DD_LOGS!.logger.log('foo')\n          window.DD_RUM!.stopSession()\n        })\n\n        await waitForRequests(page)\n\n        expect(intakeRegistry.rumViewEvents).toHaveLength(1)\n        expect(intakeRegistry.rumViewEvents[0].session.is_active).toBe(false)\n        expect(intakeRegistry.logsEvents).toHaveLength(1)\n        expect(intakeRegistry.replaySegments).toHaveLength(1)\n      })\n  })\n\n  test.describe('session cookie alteration', () => {\n    createTest('after cookie is altered to isExpired, a user interaction starts a new session with a new anonymous id')\n      .withRum()\n      .run(async ({ flushEvents, browserContext, page }) => {\n        const initialCookie = await findSessionCookie(browserContext)\n        const initialSessionId = initialCookie?.id\n        const initialAid = initialCookie?.aid\n\n        expect(initialSessionId).toBeDefined()\n        expect(initialAid).toBeDefined()\n\n        // Simulate cookie being altered to isExpired=1 without preserving aid\n        await setCookie(page, SESSION_STORE_KEY, 'isExpired=1', SESSION_TIME_OUT_DELAY)\n\n        // Cookies are cached for 1s, wait until the cache expires\n        await page.waitForTimeout(1100)\n\n        await page.locator('html').click()\n\n        // The session is not created right away, let's wait until we see a cookie\n        await page.waitForTimeout(1000)\n\n        await flushEvents()\n\n        const newCookie = await findSessionCookie(browserContext)\n        expect(newCookie?.isExpired).not.toEqual('1')\n        expect(newCookie?.id).toBeDefined()\n        expect(newCookie?.id).not.toEqual(initialSessionId)\n        expect(newCookie?.aid).toBeDefined()\n        expect(newCookie?.aid).not.toEqual(initialAid)\n      })\n  })\n\n  test.describe('third party cookie clearing', () => {\n    createTest('after a 3rd party clears the cookies, do not restart a session on user interaction')\n      .withRum()\n      .run(async ({ intakeRegistry, deleteAllCookies, flushEvents, browserContext, page }) => {\n        await deleteAllCookies()\n\n        // Cookies are cached for 1s, wait until the cache expires\n        await page.waitForTimeout(1100)\n\n        await page.locator('html').click()\n\n        await page.waitForTimeout(1100)\n\n        await page.evaluate(() => {\n          window.DD_RUM!.addAction('foo')\n        })\n\n        await flushEvents()\n\n        expect(await findSessionCookie(browserContext)).toBeUndefined()\n        expect(intakeRegistry.rumActionEvents).toHaveLength(0)\n        expect(intakeRegistry.rumViewEvents.at(-1)!.session.is_active).toBe(false)\n      })\n  })\n})\n"
  },
  {
    "path": "test/e2e/scenario/rum/tracing.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport type { IntakeRegistry } from '../../lib/framework'\nimport { createTest } from '../../lib/framework'\n\ntest.describe('tracing', () => {\n  createTest('trace xhr')\n    .withRum({ service: 'service', allowedTracingUrls: ['LOCATION_ORIGIN'] })\n    .run(async ({ intakeRegistry, sendXhr, flushEvents }) => {\n      const rawHeaders = await sendXhr('/headers', [\n        ['x-foo', 'bar'],\n        ['x-foo', 'baz'],\n      ])\n      const headers = parseHeaders(rawHeaders)\n      checkRequestHeaders(headers)\n      expect(headers['x-foo']).toBe('bar, baz')\n      await flushEvents()\n      checkTraceAssociatedToRumEvent(intakeRegistry)\n    })\n\n  createTest('trace fetch')\n    .withRum({ service: 'service', allowedTracingUrls: ['LOCATION_ORIGIN'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const rawHeaders = await page.evaluate(() =>\n        window\n          .fetch('/headers', {\n            headers: [\n              ['x-foo', 'bar'],\n              ['x-foo', 'baz'],\n            ],\n          })\n          .then((response) => response.text())\n          .catch(() => new Error('Fetch request failed!'))\n      )\n      const headers = parseHeaders(rawHeaders)\n      checkRequestHeaders(headers)\n      expect(headers['x-foo']).toBe('bar, baz')\n      await flushEvents()\n      checkTraceAssociatedToRumEvent(intakeRegistry)\n    })\n\n  createTest('trace fetch with Request argument')\n    .withRum({ service: 'service', allowedTracingUrls: ['LOCATION_ORIGIN'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const rawHeaders = await page.evaluate(() =>\n        window\n          .fetch(new Request('/headers', { headers: { 'x-foo': 'bar, baz' } }))\n          .then((response) => response.text())\n          .catch(() => new Error('Fetch request failed!'))\n      )\n      const headers = parseHeaders(rawHeaders)\n      checkRequestHeaders(headers)\n      expect(headers['x-foo']).toBe('bar, baz')\n      await flushEvents()\n      checkTraceAssociatedToRumEvent(intakeRegistry)\n    })\n\n  createTest('trace single argument fetch')\n    .withRum({ service: 'service', allowedTracingUrls: ['LOCATION_ORIGIN'] })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      const rawHeaders = await page.evaluate(() =>\n        window\n          .fetch('/headers')\n          .then((response) => response.text())\n          .catch(() => new Error('Fetch request failed!'))\n      )\n      const headers = parseHeaders(rawHeaders)\n      checkRequestHeaders(headers)\n      await flushEvents()\n      checkTraceAssociatedToRumEvent(intakeRegistry)\n    })\n\n  createTest('propagate trace baggage')\n    .withRum({\n      service: 'service',\n      allowedTracingUrls: ['LOCATION_ORIGIN'],\n      propagateTraceBaggage: true,\n      enableExperimentalFeatures: ['user_account_trace_header'],\n    })\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.setUser({ id: 'p1745' })\n        window.DD_RUM!.setAccount({ id: 'c9wpq8xrvd9t' })\n      })\n      const rawHeaders = await page.evaluate(() =>\n        window\n          .fetch('/headers')\n          .then((response) => response.text())\n          .catch(() => new Error('Fetch request failed!'))\n      )\n      const headers = parseHeaders(rawHeaders)\n      checkRequestHeaders(headers, { withBaggage: true })\n      await flushEvents()\n      checkTraceAssociatedToRumEvent(intakeRegistry)\n    })\n\n  interface ParsedHeaders {\n    [key: string]: string\n  }\n\n  function parseHeaders(rawHeaders: string | Error): ParsedHeaders {\n    expect(rawHeaders).not.toBeInstanceOf(Error)\n\n    if (rawHeaders instanceof Error) {\n      return {}\n    }\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n    return JSON.parse(rawHeaders)\n  }\n\n  // By default, we send both Datadog and W3C tracecontext headers\n  function checkRequestHeaders(\n    headers: ParsedHeaders,\n    { withBaggage }: { withBaggage: boolean } = { withBaggage: false }\n  ) {\n    expect(headers['x-datadog-trace-id']).toMatch(/\\d+/)\n    expect(headers['x-datadog-origin']).toBe('rum')\n    expect(headers['traceparent']).toMatch(/^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-01$/)\n    if (withBaggage) {\n      expect(headers['baggage']).toMatch(/^session.id=.*,user.id=.*,account.id=.*$/)\n    } else {\n      expect(headers['baggage']).not.toBeDefined()\n    }\n  }\n\n  function checkTraceAssociatedToRumEvent(intakeRegistry: IntakeRegistry) {\n    const requests = intakeRegistry.rumResourceEvents.filter(\n      (event) => event.resource.type === 'xhr' || event.resource.type === 'fetch'\n    )\n    expect(requests).toHaveLength(1)\n    expect(requests[0]._dd.trace_id).toMatch(/\\d+/)\n    expect(requests[0]._dd.span_id).toMatch(/\\d+/)\n    expect(requests[0].resource.id).toBeDefined()\n  }\n})\n"
  },
  {
    "path": "test/e2e/scenario/rum/views.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest, html } from '../../lib/framework'\n\ntest.describe('rum views', () => {\n  createTest('send performance timings along the view events')\n    .withRum()\n    .run(async ({ flushEvents, intakeRegistry }) => {\n      await flushEvents()\n      const viewEvent = intakeRegistry.rumViewEvents[0]\n      expect(viewEvent).toBeDefined()\n      expect(viewEvent.view.first_byte).toBeGreaterThan(0)\n      expect(viewEvent.view.dom_complete).toBeGreaterThan(0)\n      expect(viewEvent.view.dom_content_loaded).toBeGreaterThan(0)\n      expect(viewEvent.view.dom_interactive).toBeGreaterThan(0)\n      expect(viewEvent.view.load_event).toBeGreaterThan(0)\n    })\n\n  test.describe('loading time', () => {\n    // Simple spinner to test dom mutations.\n    const SPINNER = html`\n      <script type=\"module\">\n        const spinner = document.createElement('div')\n        document.body.append(spinner)\n\n        const spinnerChars = ['|', '/', '-', '\\\\\\\\']\n        let i = 0\n        setInterval(() => {\n          spinner.innerText = spinnerChars[i]\n          i = (i + 1) % spinnerChars.length\n        }, 10)\n      </script>\n    `\n\n    createTest('has a loading time')\n      .withRum()\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        const viewEvent = intakeRegistry.rumViewEvents[0]\n        expect(viewEvent).toBeDefined()\n        expect(viewEvent.view.loading_time).toBeGreaterThan(0)\n      })\n\n    createTest('does not have a loading time when DOM mutations are notified continuously')\n      .withRum()\n      .withBody(SPINNER)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        const viewEvent = intakeRegistry.rumViewEvents.at(-1)\n        expect(viewEvent).toBeDefined()\n        expect(viewEvent!.view.loading_time).toBeUndefined()\n      })\n\n    createTest('excludes some dom mutation when computing the loading time')\n      .withRum({\n        enableExperimentalFeatures: ['dom_mutation_ignoring'],\n      })\n      .withBody(html`\n        <script type=\"module\">\n          document.body.setAttribute('data-dd-excluded-activity-mutations', 'true')\n        </script>\n        ${SPINNER}\n      `)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        const viewEvent = intakeRegistry.rumViewEvents[0]\n        expect(viewEvent).toBeDefined()\n        expect(viewEvent.view.loading_time).toBeGreaterThan(0)\n      })\n\n    createTest('has a manual loading time')\n      .withRum()\n      .withBody(SPINNER)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              setTimeout(() => {\n                window.DD_RUM!.setViewLoadingTime()\n                resolve()\n              }, 200)\n            })\n        )\n\n        await flushEvents()\n        const viewEvent = intakeRegistry.rumViewEvents.at(-1)\n        expect(viewEvent).toBeDefined()\n        expect(viewEvent!.view.loading_time).toBeGreaterThanOrEqual(200 * 1e6)\n      })\n\n    createTest('overwrites manual loading time on subsequent calls (last-call-wins)')\n      .withRum()\n      .withBody(SPINNER)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await page.evaluate(\n          () =>\n            new Promise<void>((resolve) => {\n              setTimeout(() => {\n                window.DD_RUM!.setViewLoadingTime()\n              }, 200)\n\n              setTimeout(() => {\n                window.DD_RUM!.setViewLoadingTime()\n                resolve()\n              }, 500)\n            })\n        )\n\n        await flushEvents()\n        const viewEvent = intakeRegistry.rumViewEvents.at(-1)\n        expect(viewEvent).toBeDefined()\n        // Should reflect the second value (~500ms), not the first (~200ms)\n        expect(viewEvent!.view.loading_time).toBeGreaterThanOrEqual(500 * 1e6)\n      })\n\n    createTest('reports manual loading time when called before init')\n      .withRum()\n      .withRumInit((configuration) => {\n        window.DD_RUM!.setViewLoadingTime()\n        window.DD_RUM!.init(configuration)\n      })\n      .withBody(SPINNER)\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n        const viewEvent = intakeRegistry.rumViewEvents.at(-1)\n        expect(viewEvent).toBeDefined()\n        expect(viewEvent!.view.loading_time).toBeGreaterThanOrEqual(0)\n      })\n  })\n\n  createTest('send performance first input delay')\n    .withRum()\n    .withBody(html` <button>Hop</button> `)\n    .run(async ({ browserName, flushEvents, intakeRegistry, page }) => {\n      test.skip(\n        browserName === 'webkit',\n        \"Safari have an issue with 'event.timeStamp', so the 'first-input' polyfill is ignoring it and doesn't send a performance entry. See https://bugs.webkit.org/show_bug.cgi?id=211101\"\n      )\n      const button = page.locator('button')\n      await button.click()\n      await flushEvents()\n      const viewEvent = intakeRegistry.rumViewEvents[0]\n      expect(viewEvent).toBeDefined()\n      expect(viewEvent.view.first_input_delay).toBeGreaterThanOrEqual(0)\n    })\n\n  test.describe('anchor navigation', () => {\n    createTest(\"don't create a new view when it is an Anchor navigation\")\n      .withRum()\n      .withBody(html`\n        <a href=\"#test-anchor\">anchor link</a>\n        <div id=\"test-anchor\"></div>\n      `)\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        const anchor = page.locator('a')\n        await anchor.click()\n\n        await flushEvents()\n        const viewEvents = intakeRegistry.rumViewEvents\n\n        expect(viewEvents).toHaveLength(1)\n        expect(viewEvents[0].view.loading_type).toBe('initial_load')\n      })\n\n    createTest('create a new view on hash change')\n      .withRum()\n      .run(async ({ flushEvents, intakeRegistry, page }) => {\n        await page.evaluate(() => {\n          window.location.hash = '#bar'\n        })\n\n        await flushEvents()\n        const viewEvents = intakeRegistry.rumViewEvents\n\n        expect(viewEvents).toHaveLength(2)\n        expect(viewEvents[0].view.loading_type).toBe('initial_load')\n        expect(viewEvents[1].view.loading_type).toBe('route_change')\n      })\n  })\n})\n"
  },
  {
    "path": "test/e2e/scenario/rum/vitals.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { ExperimentalFeature } from '@datadog/browser-core'\nimport { createTest } from '../../lib/framework'\n\ntest.describe('vital collection', () => {\n  createTest('send custom duration vital')\n    .withRum()\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      await page.evaluate(() => {\n        const vital = window.DD_RUM!.startDurationVital('foo')\n        return new Promise<void>((resolve) => {\n          setTimeout(() => {\n            window.DD_RUM!.stopDurationVital(vital)\n            resolve()\n          }, 5)\n        })\n      })\n      await flushEvents()\n\n      expect(intakeRegistry.rumVitalEvents).toHaveLength(1)\n      expect(intakeRegistry.rumVitalEvents[0].vital.name).toEqual('foo')\n      expect(intakeRegistry.rumVitalEvents[0].vital.duration).toEqual(expect.any(Number))\n    })\n\n  createTest('send operation step vital')\n    .withRum({\n      enableExperimentalFeatures: [ExperimentalFeature.FEATURE_OPERATION_VITAL],\n    })\n    .run(async ({ flushEvents, intakeRegistry, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.startFeatureOperation('foo')\n      })\n      await flushEvents()\n\n      expect(intakeRegistry.rumVitalEvents).toHaveLength(1)\n      expect(intakeRegistry.rumVitalEvents[0].vital.name).toEqual('foo')\n      expect(intakeRegistry.rumVitalEvents[0].vital.step_type).toEqual('start')\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/sessionStore.scenario.ts",
    "content": "import { SESSION_STORE_KEY, MEMORY_SESSION_STORE_KEY } from '@datadog/browser-core'\nimport type { BrowserContext, Page } from '@playwright/test'\nimport { test, expect } from '@playwright/test'\nimport type { RumPublicApi } from '@datadog/browser-rum-core'\nimport { bundleSetup, createTest } from '../lib/framework'\n\nconst DISABLE_LOCAL_STORAGE = '<script>Object.defineProperty(Storage.prototype, \"getItem\", { get: () => 42});</script>'\nconst DISABLE_COOKIES = '<script>Object.defineProperty(Document.prototype, \"cookie\", { get: () => 42});</script>'\nconst SESSION_ID_REGEX = /(?<!a)id=([\\w-]+)/ // match `id` but not `aid`\n\nconst FULL_HOSTNAME = 'foo.bar.localhost'\n\n// Note: this isn't entirely exact, ideally it should be `.localhost`, but the Browser\n// SDK skips the toplevel domain (ex: .com) and starts with the second level domain\n// directly (ex: .foo.com) as it's fine in 99.9% of cases and we save one cookie check.\nconst MAIN_HOSTNAME = '.bar.localhost'\n\ntest.describe('Session Stores', () => {\n  test.describe('Cookies', () => {\n    createTest('uses cookies to store the session')\n      .withLogs()\n      .withRum()\n      .run(async ({ browserContext, page }) => {\n        const cookieSessionId = await getSessionIdFromCookie(browserContext)\n        const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n        const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n        expect(logsContext?.session_id).toBe(cookieSessionId)\n        expect(rumContext?.session_id).toBe(cookieSessionId)\n      })\n\n    createTest('when cookies are unavailable, Logs should start, but not RUM')\n      .withLogs()\n      .withRum()\n      .withHead(DISABLE_COOKIES)\n      .run(async ({ page }) => {\n        const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n        const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n        expect(logsContext).not.toBeUndefined()\n        expect(rumContext).toBeUndefined()\n      })\n\n    test.describe('trackSessionAcrossSubdomains: false', () => {\n      createTest('stores the cookie on the full host name')\n        .withRum({ trackSessionAcrossSubdomains: false })\n        .withHostName(FULL_HOSTNAME)\n        .run(async ({ browserContext }) => {\n          const cookies = await browserContext.cookies()\n          expect(cookies).toEqual([\n            expect.objectContaining({\n              domain: FULL_HOSTNAME,\n            }),\n          ])\n        })\n\n      createTest('when injected in a iframe without `src`, the cookie should be stored on the parent window domain')\n        .withRum({ trackSessionAcrossSubdomains: false })\n        .withHostName(FULL_HOSTNAME)\n        .withSetup(bundleSetup)\n        .run(async ({ page, baseUrl, browserContext, flushEvents, intakeRegistry, servers }) => {\n          await injectSdkInAnIframe(page, `${servers.crossOrigin.origin}/datadog-rum.js`)\n          await flushEvents()\n\n          const cookies = await browserContext.cookies()\n          expect(cookies).toEqual([\n            expect.objectContaining({\n              domain: FULL_HOSTNAME,\n            }),\n          ])\n          expect(intakeRegistry.rumViewEvents.map((event) => event.view.url)).toEqual(\n            expect.arrayContaining([baseUrl, 'about:blank'])\n          )\n        })\n    })\n\n    test.describe('trackSessionAcrossSubdomains: true', () => {\n      createTest('with `trackSessionAcrossSubdomains: true`, stores the cookie on the eTLD+1')\n        .withRum({ trackSessionAcrossSubdomains: true })\n        .withHostName(FULL_HOSTNAME)\n        .run(async ({ browserContext }) => {\n          const cookies = await browserContext.cookies()\n          expect(cookies).toEqual([\n            expect.objectContaining({\n              domain: MAIN_HOSTNAME,\n            }),\n          ])\n        })\n\n      createTest('when injected in a iframe without `src`, the cookie should be stored on the parent window domain')\n        .withRum({ trackSessionAcrossSubdomains: true })\n        .withHostName(FULL_HOSTNAME)\n        .withSetup(bundleSetup)\n        .run(async ({ page, baseUrl, browserContext, flushEvents, intakeRegistry, servers }) => {\n          await injectSdkInAnIframe(page, `${servers.crossOrigin.origin}/datadog-rum.js`)\n          await flushEvents()\n\n          const cookies = await browserContext.cookies()\n          expect(cookies).toEqual([\n            expect.objectContaining({\n              domain: MAIN_HOSTNAME,\n            }),\n          ])\n          expect(intakeRegistry.rumViewEvents.map((event) => event.view.url)).toEqual(\n            expect.arrayContaining([baseUrl, 'about:blank'])\n          )\n        })\n    })\n\n    for (const betaEncodeCookieOptions of [true, false]) {\n      createTest(\n        betaEncodeCookieOptions\n          ? 'should not fails when RUM and LOGS are initialized with different trackSessionAcrossSubdomains values when Encode Cookie Options is enabled'\n          : 'should fails when RUM and LOGS are initialized with different trackSessionAcrossSubdomains values when Encode Cookie Options is disabled'\n      )\n        .withRum({ trackSessionAcrossSubdomains: true, betaEncodeCookieOptions })\n        .withLogs({ trackSessionAcrossSubdomains: false, betaEncodeCookieOptions })\n        .withHostName(FULL_HOSTNAME)\n        .run(async ({ page }) => {\n          await page.waitForTimeout(1000)\n\n          if (!betaEncodeCookieOptions) {\n            // ensure the test is failing when betaEncodeCookieOptions is disabled\n            test.fail()\n          }\n\n          const [rumInternalContext, logsInternalContext] = await page.evaluate(() => [\n            window.DD_RUM?.getInternalContext(),\n            window.DD_LOGS?.getInternalContext(),\n          ])\n\n          expect(rumInternalContext).toBeDefined()\n          expect(logsInternalContext).toBeDefined()\n        })\n\n      createTest(\n        betaEncodeCookieOptions\n          ? 'should not fails when RUM and LOGS are initialized with different usePartitionedCrossSiteSessionCookie values when Encode Cookie Options is enabled'\n          : 'should fails when RUM and LOGS are initialized with different usePartitionedCrossSiteSessionCookie values when Encode Cookie Options is disabled'\n      )\n        .withRum({ usePartitionedCrossSiteSessionCookie: true, betaEncodeCookieOptions })\n        .withLogs({ usePartitionedCrossSiteSessionCookie: false, betaEncodeCookieOptions })\n        .withHostName(FULL_HOSTNAME)\n        .run(async ({ page }) => {\n          await page.waitForTimeout(1000)\n\n          if (!betaEncodeCookieOptions) {\n            // ensure the test is failing when betaEncodeCookieOptions is disabled\n            test.fail()\n          }\n\n          const [rumInternalContext, logsInternalContext] = await page.evaluate(() => [\n            window.DD_RUM?.getInternalContext(),\n            window.DD_LOGS?.getInternalContext(),\n          ])\n\n          expect(rumInternalContext).toBeDefined()\n          expect(logsInternalContext).toBeDefined()\n        })\n    }\n\n    async function injectSdkInAnIframe(page: Page, bundleUrl: string) {\n      await page.evaluate(\n        (browserSdkUrl) =>\n          new Promise<void>((resolve) => {\n            const iframe = document.createElement('iframe')\n            document.body.appendChild(iframe)\n            const iframeWindow = iframe.contentWindow!\n\n            function onReady() {\n              ;(iframeWindow as { DD_RUM: RumPublicApi }).DD_RUM.init(window.DD_RUM!.getInitConfiguration()!)\n              resolve()\n            }\n\n            // This is similar to async setup, but simpler\n            ;(iframeWindow as any).DD_RUM = { q: [onReady] }\n            const script = iframeWindow.document.createElement('script')\n            script.async = true\n            script.src = browserSdkUrl\n            iframeWindow.document.head.appendChild(script)\n          }),\n        bundleUrl\n      )\n    }\n  })\n\n  test.describe('Local Storage', () => {\n    createTest('uses localStorage to store the session')\n      .withLogs({ sessionPersistence: 'local-storage' })\n      .withRum({ sessionPersistence: 'local-storage' })\n      .run(async ({ page }) => {\n        const sessionId = await getSessionIdFromLocalStorage(page)\n\n        const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n        const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n        expect(logsContext?.session_id).toBe(sessionId)\n        expect(rumContext?.session_id).toBe(sessionId)\n      })\n\n    createTest('when localStorage is unavailable, Logs should start, but not RUM')\n      .withLogs({ sessionPersistence: 'local-storage' })\n      .withRum({ sessionPersistence: 'local-storage' })\n      .withHead(DISABLE_LOCAL_STORAGE)\n      .run(async ({ page }) => {\n        const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n        const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n        expect(logsContext).not.toBeUndefined()\n        expect(rumContext).toBeUndefined()\n      })\n  })\n\n  test.describe('Memory', () => {\n    createTest('uses memory to store the session')\n      .withLogs({ sessionPersistence: 'memory' })\n      .withRum({ sessionPersistence: 'memory' })\n      .run(async ({ page }) => {\n        const sessionId = await getSessionIdFromMemory(page)\n\n        const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n        const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n        expect(logsContext?.session_id).toBe(sessionId)\n        expect(rumContext?.session_id).toBe(sessionId)\n      })\n  })\n\n  createTest('allowFallbackToLocalStorage (deprecated)')\n    .withLogs({ allowFallbackToLocalStorage: true })\n    .withRum({ allowFallbackToLocalStorage: true })\n    .withHead(DISABLE_COOKIES)\n    .run(async ({ page }) => {\n      const sessionId = await getSessionIdFromLocalStorage(page)\n\n      const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n      const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n      expect(logsContext?.session_id).toBe(sessionId)\n      expect(rumContext?.session_id).toBe(sessionId)\n    })\n\n  createTest('sessionPersistence fallback')\n    .withLogs({ sessionPersistence: ['local-storage', 'memory'] })\n    .withRum({ sessionPersistence: ['local-storage', 'memory'] })\n    .withHead(DISABLE_LOCAL_STORAGE)\n    .run(async ({ page }) => {\n      const sessionId = await getSessionIdFromMemory(page)\n\n      const logsContext = await page.evaluate(() => window.DD_LOGS?.getInternalContext())\n      const rumContext = await page.evaluate(() => window.DD_RUM?.getInternalContext())\n\n      expect(logsContext?.session_id).toBe(sessionId)\n      expect(rumContext?.session_id).toBe(sessionId)\n    })\n})\n\nasync function getSessionIdFromLocalStorage(page: Page): Promise<string | undefined> {\n  const sessionStateString = await page.evaluate((key) => window.localStorage.getItem(key), SESSION_STORE_KEY)\n  return sessionStateString?.match(SESSION_ID_REGEX)?.[1]\n}\n\nasync function getSessionIdFromMemory(page: Page): Promise<string | undefined> {\n  const sessionState = await page.evaluate(\n    (key) => (window as any)[key] as { id: string } | undefined,\n    MEMORY_SESSION_STORE_KEY\n  )\n  return sessionState?.id\n}\n\nasync function getSessionIdFromCookie(browserContext: BrowserContext): Promise<string | undefined> {\n  const [cookie] = await browserContext.cookies()\n  return cookie.value.match(SESSION_ID_REGEX)?.[1]\n}\n"
  },
  {
    "path": "test/e2e/scenario/tanstackRouterPlugin.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../lib/framework'\n\ntest.describe('tanstack router plugin', () => {\n  createTest('should track the initial view')\n    .withRum()\n    .withApp('tanstack-router-app')\n    .run(async ({ flushEvents, intakeRegistry }) => {\n      await flushEvents()\n      const viewEvents = intakeRegistry.rumViewEvents\n      expect(viewEvents.length).toBeGreaterThan(0)\n      const firstView = viewEvents[0]\n      expect(firstView.view.name).toBe('/')\n    })\n\n  createTest('should define a view name with parameterized route')\n    .withRum()\n    .withApp('tanstack-router-app')\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Post 42')\n      await flushEvents()\n      const viewEvents = intakeRegistry.rumViewEvents\n      expect(viewEvents.length).toBeGreaterThan(0)\n      const lastView = viewEvents[viewEvents.length - 1]\n      expect(lastView.view.name).toBe('/posts/$postId')\n      expect(lastView.view.url).toContain('/posts/42')\n    })\n\n  createTest('should not create a new view on query param changes')\n    .withRum()\n    .withApp('tanstack-router-app')\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Query Param')\n      await flushEvents()\n      // Only the initial view should exist — query param change should not create a new one\n      expect(intakeRegistry.rumViewEvents).toHaveLength(1)\n    })\n\n  createTest('should track a view with a splat route')\n    .withRum()\n    .withApp('tanstack-router-app')\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Splat')\n      await flushEvents()\n      const viewEvents = intakeRegistry.rumViewEvents\n      expect(viewEvents.length).toBeGreaterThan(0)\n      const lastView = viewEvents[viewEvents.length - 1]\n      expect(lastView.view.name).toBe('/files/path/to/file')\n      expect(lastView.view.url).toContain('/files/path/to/file')\n    })\n\n  createTest('should track the redirect destination view')\n    .withRum()\n    .withApp('tanstack-router-app')\n    .run(async ({ page, flushEvents, intakeRegistry }) => {\n      await page.click('text=Redirect')\n      await flushEvents()\n      const viewEvents = intakeRegistry.rumViewEvents\n      expect(viewEvents.length).toBeGreaterThan(0)\n      const lastView = viewEvents[viewEvents.length - 1]\n      expect(lastView.view.name).toBe('/posts')\n      expect(lastView.view.url).toContain('/posts')\n    })\n})\n"
  },
  {
    "path": "test/e2e/scenario/telemetry.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest, html } from '../lib/framework'\n\ntest.describe('telemetry', () => {\n  createTest('send errors for logs')\n    .withLogs({ trackingConsent: 'granted' })\n    .run(async ({ intakeRegistry, page, flushEvents }) => {\n      await page.evaluate(() => {\n        const context = {\n          get foo() {\n            throw new window.Error('expected error')\n          },\n        }\n        window.DD_LOGS!.logger.log('hop', context as any)\n      })\n      await flushEvents()\n      expect(intakeRegistry.telemetryErrorEvents).toHaveLength(1)\n      const event = intakeRegistry.telemetryErrorEvents[0]\n      expect(event.service).toEqual('browser-logs-sdk')\n      expect(event.telemetry.message).toBe('expected error')\n      expect(event.telemetry.error!.kind).toBe('Error')\n      expect(event.telemetry.status).toBe('error')\n      intakeRegistry.empty()\n    })\n\n  createTest('send errors for RUM')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        const context = {\n          get foo() {\n            throw new window.Error('expected error')\n          },\n        }\n        window.DD_RUM!.addAction('hop', context as any)\n      })\n      await flushEvents()\n      expect(intakeRegistry.telemetryErrorEvents).toHaveLength(1)\n      const event = intakeRegistry.telemetryErrorEvents[0]\n      expect(event.service).toEqual('browser-rum-sdk')\n      expect(event.telemetry.message).toBe('expected error')\n      expect(event.telemetry.error!.kind).toBe('Error')\n      expect(event.telemetry.status).toBe('error')\n      intakeRegistry.empty()\n    })\n\n  createTest('send init configuration for logs')\n    .withLogs({\n      forwardErrorsToLogs: true,\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      expect(intakeRegistry.telemetryConfigurationEvents).toHaveLength(1)\n      const event = intakeRegistry.telemetryConfigurationEvents[0]\n      expect(event.service).toEqual('browser-logs-sdk')\n      expect(event.telemetry.configuration.forward_errors_to_logs).toEqual(true)\n      expect(event.session!.id).toEqual(expect.any(String))\n    })\n\n  createTest('send init configuration for RUM')\n    .withRum({\n      trackUserInteractions: true,\n    })\n    .run(async ({ intakeRegistry, flushEvents }) => {\n      await flushEvents()\n      expect(intakeRegistry.telemetryConfigurationEvents).toHaveLength(1)\n      const event = intakeRegistry.telemetryConfigurationEvents[0]\n      expect(event.service).toEqual('browser-rum-sdk')\n      expect(event.telemetry.configuration.track_user_interactions).toEqual(true)\n      expect(event.application!.id).toEqual(expect.any(String))\n    })\n\n  createTest('send usage telemetry for RUM')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_RUM!.addAction('foo')\n      })\n\n      await flushEvents()\n      expect(intakeRegistry.telemetryUsageEvents).toHaveLength(2)\n      const event = intakeRegistry.telemetryUsageEvents[1] // first event is 'set-global-context' done in pageSetup.ts\n      expect(event.service).toEqual('browser-rum-sdk')\n      expect(event.telemetry.usage.feature).toEqual('add-action')\n    })\n\n  createTest('send usage telemetry for logs')\n    .withLogs()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      await page.evaluate(() => {\n        window.DD_LOGS!.setTrackingConsent('granted')\n      })\n\n      await flushEvents()\n      expect(intakeRegistry.telemetryUsageEvents).toHaveLength(1)\n      const event = intakeRegistry.telemetryUsageEvents[0]\n      expect(event.service).toEqual('browser-logs-sdk')\n      expect(event.telemetry.usage.feature).toEqual('set-tracking-consent')\n    })\n\n  createTest('stops sending telemetry after consent revocation')\n    .withRum()\n    .run(async ({ intakeRegistry, flushEvents, page }) => {\n      // Generate initial telemetry, revoke consent, then try to generate more\n      await page.evaluate(() => {\n        window.DD_RUM!.addAction('initial-action')\n        window.DD_RUM!.setTrackingConsent('not-granted')\n        window.DD_RUM!.addAction('post-revocation-action')\n        window.DD_RUM!.getAccount()\n      })\n\n      await flushEvents()\n\n      // Verify telemetry events: should have initial action and consent revocation,\n      // but NOT the post-revocation action\n      const telemetryEvents = intakeRegistry.telemetryUsageEvents\n      expect(telemetryEvents.length).toBeGreaterThanOrEqual(2)\n\n      // Verify no telemetry for post-revocation action or get-account\n      const postRevocationEvents = telemetryEvents.filter(\n        (event) => event.telemetry.usage.feature === 'add-action' || event.telemetry.usage.feature === 'get-account'\n      )\n      expect(postRevocationEvents.length).toEqual(1) // Only the initial action\n    })\n\n  test.describe('collect errors related to session initialization', () => {\n    // Test for RUM and Logs separately, because using both at the same time via NPM triggers\n    // different errors (because both SDKs are sharing the same cookie store `operationBuffer`\n    // queue). This could be revisited after properly fixing incident-39238.\n\n    const DENY_SESSION_COOKIE_ACCESS = html`\n      <script>\n        // Make Logs and RUM session initialization fail by denying cookie access\n        const originalDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie')\n        Object.defineProperty(Document.prototype, 'cookie', {\n          get: () => originalDescriptor.get.call(document),\n          set: (value) => {\n            if (value.includes('_dd_s=')) {\n              throw new Error('expected error')\n            }\n            originalDescriptor.set.call(document, value)\n          },\n        })\n      </script>\n    `\n\n    createTest('logs')\n      .withHead(DENY_SESSION_COOKIE_ACCESS)\n      .withLogs()\n      .run(async ({ intakeRegistry, flushEvents }) => {\n        await flushEvents()\n        expect(intakeRegistry.telemetryErrorEvents).toHaveLength(1)\n        const error = intakeRegistry.telemetryErrorEvents[0]\n        expect(error.service).toEqual('browser-logs-sdk')\n        expect(error.telemetry.message).toBe('expected error')\n        expect(error.telemetry.error!.kind).toBe('Error')\n        expect(error.telemetry.status).toBe('error')\n        intakeRegistry.empty()\n      })\n\n    createTest('rum')\n      .withHead(DENY_SESSION_COOKIE_ACCESS)\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents }) => {\n        await flushEvents()\n        expect(intakeRegistry.telemetryErrorEvents).toHaveLength(1)\n        const error = intakeRegistry.telemetryErrorEvents[0]\n        expect(error.service).toEqual('browser-rum-sdk')\n        expect(error.telemetry.message).toBe('expected error')\n        expect(error.telemetry.error!.kind).toBe('Error')\n        expect(error.telemetry.status).toBe('error')\n        intakeRegistry.empty()\n      })\n  })\n})\n"
  },
  {
    "path": "test/e2e/scenario/trackingConsent.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { findSessionCookie } from '../lib/helpers/session'\nimport { createTest } from '../lib/framework'\n\ntest.describe('tracking consent', () => {\n  test.describe('RUM', () => {\n    createTest('does not start the SDK if tracking consent is not given at init')\n      .withRum({ trackingConsent: 'not-granted' })\n      .run(async ({ intakeRegistry, flushEvents, browserContext }) => {\n        await flushEvents()\n\n        expect(intakeRegistry.isEmpty).toBe(true)\n        expect(await findSessionCookie(browserContext)).toBeUndefined()\n      })\n\n    createTest('starts the SDK once tracking consent is granted')\n      .withRum({ trackingConsent: 'not-granted' })\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await page.evaluate(() => {\n          window.DD_RUM!.setTrackingConsent('granted')\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.isEmpty).toBe(false)\n        expect(await findSessionCookie(browserContext)).toBeDefined()\n      })\n\n    createTest('stops sending events if tracking consent is revoked')\n      .withRum({ trackUserInteractions: true })\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await page.evaluate(() => {\n          window.DD_RUM!.setTrackingConsent('not-granted')\n        })\n\n        const htmlElement = page.locator('html')\n        await htmlElement.click()\n\n        await flushEvents()\n\n        expect(intakeRegistry.rumActionEvents).toHaveLength(0)\n        expect((await findSessionCookie(browserContext))?.isExpired).toEqual('1')\n      })\n\n    createTest('starts a new session when tracking consent is granted again')\n      .withRum()\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        const initialSessionId = await findSessionCookie(browserContext)\n\n        await page.evaluate(() => {\n          window.DD_RUM!.setTrackingConsent('not-granted')\n          window.DD_RUM!.setTrackingConsent('granted')\n        })\n\n        await flushEvents()\n\n        const firstView = intakeRegistry.rumViewEvents[0]\n        const lastView = intakeRegistry.rumViewEvents.at(-1)!\n        expect(firstView.session.id).not.toEqual(lastView.session.id)\n        expect(firstView.view.id).not.toEqual(lastView.view.id)\n        expect(await findSessionCookie(browserContext)).not.toEqual(initialSessionId)\n      })\n\n    createTest('using setTrackingConsent before init overrides the init parameter')\n      .withRum({ trackingConsent: 'not-granted' })\n      .withRumInit((configuration) => {\n        window.DD_RUM!.setTrackingConsent('granted')\n        window.DD_RUM!.init(configuration)\n      })\n      .run(async ({ intakeRegistry, flushEvents, browserContext }) => {\n        await flushEvents()\n\n        expect(intakeRegistry.isEmpty).toBe(false)\n        expect(await findSessionCookie(browserContext)).toBeDefined()\n      })\n  })\n\n  test.describe('Logs', () => {\n    createTest('does not start the SDK if tracking consent is not given at init')\n      .withLogs({ trackingConsent: 'not-granted' })\n      .run(async ({ intakeRegistry, flushEvents, browserContext }) => {\n        await flushEvents()\n\n        expect(intakeRegistry.isEmpty).toBe(true)\n        expect(await findSessionCookie(browserContext)).toBeUndefined()\n      })\n\n    createTest('starts the SDK once tracking consent is granted')\n      .withLogs({ trackingConsent: 'not-granted' })\n      .run(async ({ intakeRegistry, flushEvents, browserContext, page }) => {\n        await page.evaluate(() => {\n          window.DD_LOGS!.setTrackingConsent('granted')\n        })\n\n        await flushEvents()\n\n        expect(intakeRegistry.isEmpty).toBe(false)\n        expect(await findSessionCookie(browserContext)).toBeDefined()\n      })\n  })\n})\n"
  },
  {
    "path": "test/e2e/scenario/transport.scenario.ts",
    "content": "import { test, expect } from '@playwright/test'\nimport { createTest } from '../lib/framework'\n\ntest.describe('transport', () => {\n  test.describe('batch flushing on beforeunload', () => {\n    createTest('use sendBeacon for a batch flushed by bytes_limit during beforeunload')\n      // This test reproduces a bug where a batch near the size limit is flushed using fetch\n      // instead of sendBeacon when the beforeunload event fires.\n      //\n      // Scenario:\n      // 1. A batch is almost full (close to RECOMMENDED_REQUEST_BYTES_LIMIT = 16 KiB)\n      // 2. beforeunload fires and triggers a final view update\n      // 3. Adding the view update exceeds the limit → the batch is flushed due to bytes_limit\n      // 4. BUG: this flush uses fetch instead of sendBeacon, so it may be cancelled during unload\n      // 5. A new batch is created for the view update and flushed via sendBeacon\n      //\n      // Expected: the bytes_limit flush should use sendBeacon when triggered in the context of a\n      // page exit, so that it is not cancelled by the browser.\n      .withRum({ telemetrySampleRate: 0 })\n      .run(async ({ page, flushEvents, intakeRegistry }) => {\n        // Fill the batch close to the 16 KiB limit using a custom action. The action name is sized\n        // so that action event is almost at the limit 16KB limit → no flush yet.\n        await page.evaluate(() => {\n          window.DD_RUM!.addAction('x'.repeat(15000))\n        })\n\n        // Navigating away fires beforeunload, which triggers a final view update. Adding the view\n        // update (~2KB) to the near-full batch tips it over the limit and causes a bytes_limit\n        // flush, which the SDK issues via fetch — and that fetch gets cancelled on page unload.\n        await flushEvents()\n\n        // We expect two last RUM batches:\n        // 1. The near-full batch containing the large action, flushed due to bytes_limit\n        // 2. The final view update batch, flushed due to beforeunload\n        const [penultimateBatch, finalBatch] = intakeRegistry.rumRequests.slice(-2)\n\n        // The action event should be present in one of the batches\n        expect(\n          penultimateBatch.events.some((e) => e.type === 'action') || finalBatch.events.some((e) => e.type === 'action')\n        ).toBe(true)\n\n        // Both batches should use sendBeacon so they are not cancelled during page unload.\n        // With the bug, penultimateBatch.transport is 'fetch' instead of 'beacon'.\n        expect(penultimateBatch.transport).toBe('beacon')\n        expect(finalBatch.transport).toBe('beacon')\n      })\n  })\n\n  test.describe('data compression', () => {\n    createTest('send RUM data compressed')\n      .withRum({\n        compressIntakeRequests: true,\n      })\n      .run(async ({ flushEvents, intakeRegistry }) => {\n        await flushEvents()\n\n        expect(intakeRegistry.rumRequests).toHaveLength(3)\n\n        // The last view update should be sent without compression\n        const plainRequests = intakeRegistry.rumRequests.filter((request) => request.encoding === null)\n        expect(plainRequests).toHaveLength(2)\n        const telemetryEventsRequest = plainRequests.find((request) =>\n          request.events.some((event) => event.type === 'telemetry')\n        )\n        const rumEventsRequest = plainRequests.find((request) => request !== telemetryEventsRequest)\n        expect(rumEventsRequest!.events).toEqual(\n          expect.arrayContaining([\n            expect.objectContaining({\n              type: 'view',\n            }),\n          ])\n        )\n\n        // Other data should be sent encoded\n        const deflateRequests = intakeRegistry.rumRequests.filter((request) => request.encoding === 'deflate')\n        expect(deflateRequests).toHaveLength(1)\n        expect(deflateRequests.flatMap((request) => request.events).length).toBeGreaterThan(0)\n      })\n\n    createTest(\"displays a message if the worker can't be started\")\n      .withRum({\n        compressIntakeRequests: true,\n      })\n      .withBasePath('/no-blob-worker-csp')\n      .run(async ({ browserName, flushEvents, intakeRegistry, withBrowserLogs }) => {\n        test.fixme(\n          browserName === 'webkit',\n          'The worker fails but does not trigger the CSP documentation log on Safari'\n        )\n        await flushEvents()\n\n        // Some non-deflate request can still be sent because on some browsers the Worker fails\n        // asynchronously\n        expect(intakeRegistry.rumRequests.filter((request) => request.encoding === 'deflate')).toHaveLength(0)\n\n        withBrowserLogs((logs) => {\n          const failedToStartLog = logs.find((log) => log.message.includes('Datadog RUM failed to start'))\n          const cspDocLog = logs.find((log) => log.message.includes('Please make sure CSP'))\n          expect(failedToStartLog, \"'Failed to start' log\").toBeTruthy()\n          expect(cspDocLog, \"'CSP doc' log\").toBeTruthy()\n        })\n      })\n  })\n})\n"
  },
  {
    "path": "test/e2e/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"experimentalDecorators\": true,\n    \"esModuleInterop\": true,\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"target\": \"ES2022\",\n    \"lib\": [\"ES2022\", \"DOM\"],\n    \"module\": \"preserve\",\n    \"types\": [\"node\", \"ajv\"],\n    \"allowJs\": true,\n    \"noEmit\": true,\n    \"allowImportingTsExtensions\": true\n  }\n}\n"
  },
  {
    "path": "test/envUtils.ts",
    "content": "import os from 'os'\n\nexport function getIp() {\n  const networkInterface = (Object.values(os.networkInterfaces()) as os.NetworkInterfaceInfo[][])\n    .flat()\n    .find(({ family, internal }) => family === 'IPv4' && !internal)\n  return networkInterface ? networkInterface.address : '127.0.0.1'\n}\n\nexport function getBuildInfos() {\n  const ciInfos = getCIInfos()\n  if (ciInfos) {\n    return ciInfos\n  }\n  const localInfos = getLocalInfos()\n  if (localInfos) {\n    return localInfos\n  }\n}\n\nexport function getRunId() {\n  return process.env.CI_JOB_ID || process.env.USER || 'n/a'\n}\n\nfunction getCIInfos() {\n  const { CI_JOB_ID, CI_PIPELINE_ID, CI_COMMIT_SHORT_SHA } = process.env\n  if (CI_PIPELINE_ID && CI_JOB_ID && CI_COMMIT_SHORT_SHA) {\n    return `job: ${CI_JOB_ID} commit: ${CI_COMMIT_SHORT_SHA}`\n  }\n}\n\nfunction getLocalInfos() {\n  return `${process.env.USER} ${new Date().toLocaleString()}`\n}\n\nexport function getTestReportDirectory() {\n  if (process.env.CI_JOB_NAME) {\n    return `test-report/${process.env.CI_JOB_NAME}`\n  }\n}\n\nexport function getCoverageReportDirectory() {\n  if (process.env.CI_JOB_NAME) {\n    return `coverage/${process.env.CI_JOB_NAME}`\n  }\n\n  return 'coverage'\n}\n"
  },
  {
    "path": "test/performance/configuration.ts",
    "content": "export const SDK_BUNDLE_URL = 'https://www.datadoghq-browser-agent.com/us1/v6/datadog-rum.js'\nexport const APPLICATION_ID = '9fa62a5b-8a7e-429d-8466-8b111a4d4693'\nexport const CLIENT_TOKEN = 'pubab31fd1ab9d01d2b385a8aa3dd403b1d'\nexport const DATADOG_SITE = 'datadoghq.com'\n"
  },
  {
    "path": "test/performance/createBenchmarkTest.ts",
    "content": "import { test } from '@playwright/test'\nimport type { Page, CDPSession, Browser } from '@playwright/test'\nimport type { RumInitConfiguration } from '@datadog/browser-rum-core'\nimport type { BrowserWindow, Metrics } from './profiling.type'\nimport { startProfiling } from './profilers'\nimport { reportToConsole } from './reporters/reportToConsole'\nimport { reportToDatadog } from './reporters/reportToDatadog'\nimport { isContinuousIntegration } from './environment'\nimport type { Server } from './server'\nimport { startPerformanceServer } from './server'\nimport { CLIENT_TOKEN, APPLICATION_ID, DATADOG_SITE, SDK_BUNDLE_URL } from './configuration'\n\nconst SCENARIO_CONFIGURATIONS = ['none', 'rum', 'rum_replay', 'rum_profiling', 'none_with_headers'] as const\n\ntype ScenarioConfiguration = (typeof SCENARIO_CONFIGURATIONS)[number]\ntype TestRunner = (page: Page, takeMeasurements: () => Promise<void>, appUrl: string) => Promise<void> | void\n\nexport function createBenchmarkTest(scenarioName: string) {\n  return {\n    run(runner: TestRunner) {\n      const metrics: Record<string, Metrics> = {}\n      let sdkVersion: string\n      let server: Server\n\n      test.beforeAll(async ({ browser }) => {\n        server = await startPerformanceServer(scenarioName)\n        await warmup(browser, server.origin)\n      })\n\n      SCENARIO_CONFIGURATIONS.forEach((scenarioConfiguration) => {\n        test(`${scenarioName} benchmark ${scenarioConfiguration}`, async ({ page }) => {\n          await page.setExtraHTTPHeaders({ 'Accept-Language': 'en-US' })\n\n          const context = page.context()\n          const cdpSession = await context.newCDPSession(page)\n\n          await throttleNetwork(cdpSession)\n\n          const { stopProfiling, takeMeasurements } = await startProfiling(page, cdpSession)\n\n          if (shouldInjectSDK(scenarioConfiguration)) {\n            await injectSDK(page, scenarioConfiguration, scenarioName)\n          }\n\n          await runner(page, takeMeasurements, buildAppUrl(server.origin, scenarioConfiguration))\n\n          await flushEvents(page)\n          metrics[scenarioConfiguration] = await stopProfiling()\n          if (!sdkVersion) {\n            sdkVersion = await getSDKVersion(page)\n          }\n        })\n      })\n\n      test.afterAll(async () => {\n        server.stop()\n        reportToConsole(metrics, sdkVersion)\n        if (isContinuousIntegration) {\n          await reportToDatadog(metrics, scenarioName, sdkVersion)\n        }\n      })\n    },\n  }\n}\n\ninterface PageInitScriptParameters {\n  configuration: Partial<RumInitConfiguration>\n  sdkBundleUrl: string\n  scenarioConfiguration: ScenarioConfiguration\n  scenarioName: string\n}\n\nasync function injectSDK(page: Page, scenarioConfiguration: ScenarioConfiguration, scenarioName: string) {\n  const configuration: Partial<RumInitConfiguration> = {\n    clientToken: CLIENT_TOKEN,\n    applicationId: APPLICATION_ID,\n    site: DATADOG_SITE,\n    profilingSampleRate: scenarioConfiguration === 'rum_profiling' ? 100 : 0,\n    sessionReplaySampleRate: scenarioConfiguration === 'rum_replay' ? 100 : 0,\n  }\n\n  await page.addInitScript(\n    ({ sdkBundleUrl, scenarioConfiguration, scenarioName, configuration }: PageInitScriptParameters) => {\n      function loadSDK() {\n        const browserWindow = window as BrowserWindow\n        ;(function (h: any, o: Document, u: string, n: string, d: string) {\n          h = h[d] = h[d] || {\n            q: [],\n            onReady(c: () => void) {\n              // eslint-disable-next-line\n              h.q.push(c)\n            },\n          }\n          const s = o.createElement(u) as HTMLScriptElement\n          s.async = true\n          s.src = n\n          o.head.appendChild(s)\n        })(window, document, 'script', sdkBundleUrl, 'DD_RUM')\n        browserWindow.DD_RUM?.onReady(function () {\n          browserWindow.DD_RUM!.setGlobalContextProperty('scenario', {\n            configuration: scenarioConfiguration,\n            name: scenarioName,\n          })\n          browserWindow.DD_RUM!.init(configuration as RumInitConfiguration)\n        })\n      }\n\n      // Init scripts run before DOM is ready; wait until \"interactive\" to append the SDK <script> tag.\n      document.addEventListener('readystatechange', () => {\n        if (document.readyState === 'interactive') {\n          loadSDK()\n        }\n      })\n    },\n    { configuration, sdkBundleUrl: SDK_BUNDLE_URL, scenarioConfiguration, scenarioName }\n  )\n}\n\n/**\n * Warm-up by loading a page to eliminate inflated TTFB seen on the very first load.\n * Inflated TTFB can come from cold-path costs (DNS resolution, TCP/TLS handshake, etc.).\n */\nasync function warmup(browser: Browser, url: string) {\n  const page = await browser.newPage()\n  await page.goto(url)\n}\n\nasync function getSDKVersion(page: Page) {\n  return await page.evaluate(() => (window as BrowserWindow).DD_RUM?.version || '')\n}\n\nfunction shouldInjectSDK(scenarioConfiguration: ScenarioConfiguration): boolean {\n  return !['none', 'none_with_headers'].includes(scenarioConfiguration)\n}\n\nfunction buildAppUrl(origin: string, scenarioConfiguration: ScenarioConfiguration): string {\n  const url = new URL(origin)\n  if (scenarioConfiguration === 'rum_profiling' || scenarioConfiguration === 'none_with_headers') {\n    url.searchParams.set('profiling', 'true')\n  }\n  return url.toString()\n}\n\n/**\n * Flushes the events of the SDK and Google Web Vitals\n * by simulating a `visibilitychange` event with the state set to \"hidden\".\n */\nasync function flushEvents(page: Page) {\n  await page.evaluate(() => {\n    Object.defineProperty(document, 'visibilityState', { configurable: true, get: () => 'hidden' })\n    const hiddenEvent = new Event('visibilitychange', { bubbles: true })\n    ;(hiddenEvent as unknown as { __ddIsTrusted: boolean }).__ddIsTrusted = true\n    document.dispatchEvent(hiddenEvent)\n  })\n}\n\n/**\n * Throttle network using Chrome DevTools Protocol\n */\nasync function throttleNetwork(cdpSession: CDPSession) {\n  // Using Regular 4G for realistic performance testing with moderate constraints\n  await cdpSession.send('Network.emulateNetworkConditions', {\n    offline: false,\n    downloadThroughput: (4 * 1024 * 1024) / 8, // 4 Mbps in bytes/sec (Regular 4G)\n    uploadThroughput: (3 * 1024 * 1024) / 8, // 3 Mbps in bytes/sec\n    latency: 20, // 20ms RTT\n  })\n}\n"
  },
  {
    "path": "test/performance/environment.ts",
    "content": "export const isContinuousIntegration = Boolean(process.env.CI)\n"
  },
  {
    "path": "test/performance/playwright.config.ts",
    "content": "import { defineConfig, devices } from '@playwright/test'\nimport { isContinuousIntegration } from './environment'\n\nconst baseConfig = {\n  testDir: './scenarios',\n  testMatch: '**/*.scenario.ts',\n  tsconfig: './tsconfig.json',\n  fullyParallel: true,\n  retries: 0,\n  workers: 1,\n  timeout: 90000, // 90 seconds to allow time for profile collection\n  projects: [\n    {\n      name: 'chromium',\n      use: {\n        ignoreHTTPSErrors: true,\n        ...devices['Desktop Chrome'],\n      },\n    },\n  ],\n}\n\n// eslint-disable-next-line import/no-default-export\nexport default defineConfig({\n  ...baseConfig,\n  ...(isContinuousIntegration && {\n    repeatEach: 15,\n    workers: 4,\n  }),\n})\n"
  },
  {
    "path": "test/performance/profilers/index.ts",
    "content": "export * from './startProfiling'\nexport * from './startMemoryProfiling'\nexport * from './startCpuProfiling'\nexport * from './startWebVitalsProfiling'\n"
  },
  {
    "path": "test/performance/profilers/startCpuProfiling.ts",
    "content": "import type { CDPSession } from '@playwright/test'\n\nexport async function startCPUProfiling(client: CDPSession) {\n  await client.send('Profiler.enable')\n  await client.send('Profiler.start')\n\n  let totalConsumption = 0\n\n  async function stopAndAddProfile() {\n    const { profile } = await client.send('Profiler.stop')\n\n    const timeDeltaForNodeId = new Map<number, number>()\n\n    for (let index = 0; index < profile.samples!.length; index += 1) {\n      const nodeId = profile.samples![index]\n      timeDeltaForNodeId.set(nodeId, (timeDeltaForNodeId.get(nodeId) || 0) + profile.timeDeltas![index])\n    }\n\n    for (const node of profile.nodes) {\n      const consumption = timeDeltaForNodeId.get(node.id) || 0\n      totalConsumption += consumption\n    }\n  }\n\n  return {\n    takeCPUMeasurements: async () => {\n      // We need to restart profiling at each \"measurement\" because the running profile gets reset\n      // on each navigation.\n      await stopAndAddProfile()\n      await client.send('Profiler.start')\n    },\n    stopCPUProfiling: async () => {\n      await stopAndAddProfile()\n      return totalConsumption\n    },\n  }\n}\n"
  },
  {
    "path": "test/performance/profilers/startMemoryProfiling.ts",
    "content": "import type { CDPSession } from '@playwright/test'\n\nexport async function startMemoryProfiling(client: CDPSession) {\n  await client.send('HeapProfiler.enable')\n  await client.send('HeapProfiler.startSampling', {\n    // Set a low sampling interval to have more precise measurement\n    samplingInterval: 100,\n  })\n\n  const measurements: Array<{ totalConsumption: number }> = []\n\n  return {\n    takeMemoryMeasurements: async () => {\n      await client.send('HeapProfiler.collectGarbage')\n      const { profile } = await client.send('HeapProfiler.getSamplingProfile')\n\n      const sizeForNodeId = new Map<number, number>()\n\n      for (const sample of profile.samples) {\n        sizeForNodeId.set(sample.nodeId, (sizeForNodeId.get(sample.nodeId) || 0) + sample.size)\n      }\n\n      let totalConsumption = 0\n      for (const node of iterNodes(profile.head)) {\n        const consumption = sizeForNodeId.get(node.id) || 0\n        totalConsumption += consumption\n      }\n      measurements.push({ totalConsumption })\n    },\n\n    stopMemoryProfiling: async () => {\n      await client.send('HeapProfiler.stopSampling')\n\n      measurements.sort((a, b) => a.totalConsumption - b.totalConsumption)\n      const { totalConsumption } = measurements[Math.floor(measurements.length / 2)]\n      return totalConsumption\n    },\n  }\n}\n\nfunction* iterNodes<N extends { children?: N[] }>(root: N): Generator<N> {\n  yield root\n  if (root.children) {\n    for (const child of root.children) {\n      yield* iterNodes(child)\n    }\n  }\n}\n"
  },
  {
    "path": "test/performance/profilers/startNetworkProfiling.ts",
    "content": "import type { Page, Request } from '@playwright/test'\n\nexport function startNetworkProfiling(page: Page) {\n  let uploadBytes = 0\n  let downloadBytes = 0\n\n  async function onRequestFinished(request: Request) {\n    const sizes = await request.sizes()\n    downloadBytes += sizes.responseBodySize + sizes.responseHeadersSize\n    uploadBytes += sizes.requestBodySize + sizes.requestHeadersSize\n  }\n\n  page.on('requestfinished', onRequestFinished)\n\n  return {\n    stopNetworkProfiling: () => {\n      page.off('requestfinished', onRequestFinished)\n      return {\n        upload: uploadBytes,\n        download: downloadBytes,\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "test/performance/profilers/startProfiling.ts",
    "content": "import type { CDPSession, Page } from '@playwright/test'\nimport type { Metrics } from '../profiling.type'\nimport { startCPUProfiling } from './startCpuProfiling'\nimport { startMemoryProfiling } from './startMemoryProfiling'\nimport { startWebVitalsProfiling } from './startWebVitalsProfiling'\nimport { startNetworkProfiling } from './startNetworkProfiling'\n\nexport async function startProfiling(page: Page, cdpSession: CDPSession) {\n  const { stopCPUProfiling, takeCPUMeasurements } = await startCPUProfiling(cdpSession)\n  const { stopMemoryProfiling, takeMemoryMeasurements } = await startMemoryProfiling(cdpSession)\n  const { stopNetworkProfiling } = startNetworkProfiling(page)\n  const { stopWebVitalsProfiling } = await startWebVitalsProfiling(page)\n\n  return {\n    takeMeasurements: async () => {\n      await takeCPUMeasurements()\n      await takeMemoryMeasurements()\n    },\n    stopProfiling: async (): Promise<Metrics> => ({\n      memory: await stopMemoryProfiling(),\n      cpu: await stopCPUProfiling(),\n      ...stopNetworkProfiling(),\n      ...(await stopWebVitalsProfiling()),\n    }),\n  }\n}\n"
  },
  {
    "path": "test/performance/profilers/startWebVitalsProfiling.ts",
    "content": "import type { Page } from '@playwright/test'\nimport type { BrowserWindow, WebVitalsMetrics } from '../profiling.type'\ninterface Metric {\n  value: number\n}\n\ntype RecordMetric = (callback: (metric: Metric) => void, options?: { reportAllChanges: boolean }) => void\n\ninterface WebVitalsModule {\n  onLCP: RecordMetric\n  onCLS: RecordMetric\n  onFCP: RecordMetric\n  onTTFB: RecordMetric\n  onINP: RecordMetric\n}\n\nexport async function startWebVitalsProfiling(page: Page) {\n  await page.addInitScript(() => {\n    const metrics: WebVitalsMetrics = {}\n    ;(window as BrowserWindow).__webVitalsMetrics__ = metrics\n    import('https://unpkg.com/web-vitals@5?module' as string)\n      .then(({ onLCP, onCLS, onFCP, onTTFB, onINP }: WebVitalsModule) => {\n        const recordMetric = (name: keyof WebVitalsMetrics) => (metric: Metric) => (metrics[name] = metric.value)\n        onINP(recordMetric('INP'), { reportAllChanges: true })\n        onLCP(recordMetric('LCP'), { reportAllChanges: true })\n        onCLS(recordMetric('CLS'), { reportAllChanges: true })\n        onFCP((metric: Metric) => {\n          recordMetric('FCP')(metric)\n          onTBT(recordMetric('TBT'))\n        })\n        onTTFB(recordMetric('TTFB'))\n      })\n      .catch((e) => console.error('web-vitals load failed:', e))\n\n    function onTBT(callback: (metric: Metric) => void) {\n      let tbt = 0\n      const observer = new PerformanceObserver((list) => {\n        for (const entry of list.getEntries()) {\n          // Only count tasks that are longer than 50ms\n          if (entry.startTime >= metrics.FCP! && entry.duration > 50) {\n            // The blocking time is the duration minus 50ms\n            const blockingTime = entry.duration - 50\n            tbt += blockingTime\n            callback({ value: tbt })\n          }\n        }\n      })\n\n      observer.observe({ type: 'longtask', buffered: true })\n    }\n  })\n\n  return {\n    stopWebVitalsProfiling: async (): Promise<WebVitalsMetrics> => {\n      const metrics = await page.evaluate(() => (window as BrowserWindow).__webVitalsMetrics__ || {})\n      return metrics\n    },\n  }\n}\n"
  },
  {
    "path": "test/performance/profiling.type.ts",
    "content": "import type { Page } from '@playwright/test'\nimport type { RumPublicApi } from '@datadog/browser-rum-core'\n\nexport interface BrowserWindow extends Window {\n  DD_RUM?: RumPublicApi\n  __webVitalsMetrics__?: WebVitalsMetrics\n}\n\nexport interface Scenario {\n  description: string\n  run(this: void, page: Page, takeMeasurements: () => Promise<void>): Promise<void>\n}\n\nexport interface Metrics extends WebVitalsMetrics {\n  memory: number\n  cpu: number\n  upload: number\n  download: number\n}\n\nexport interface WebVitalsMetrics {\n  LCP?: number\n  CLS?: number\n  FCP?: number\n  TTFB?: number\n  INP?: number\n  TBT?: number\n}\n"
  },
  {
    "path": "test/performance/reporters/reportToConsole.ts",
    "content": "import type { Metrics } from '../profiling.type'\n\nconst DURATION_UNITS = ['μs', 'ms', 's']\nconst DURATION_UNITS_MS = ['ms', 's']\nconst BYTES_UNITS = ['B', 'kB', 'MB']\nconst NO_VALUE = ''\n\nexport function reportToConsole(metricsTable: Record<string, Metrics>, sdkVersion: string) {\n  const report: Record<string, Record<string, string>> = {\n    'memory (median)': {},\n    cpu: {},\n    upload: {},\n    download: {},\n    LCP: {},\n    CLS: {},\n    FCP: {},\n    TTFB: {},\n    INP: {},\n    TBT: {},\n  }\n\n  // Populate the report with each scenario's metrics\n  for (const [scenarioConfiguration, metrics] of Object.entries(metricsTable)) {\n    report['memory (median)'][scenarioConfiguration] = formatNumberWithUnit(metrics.memory, BYTES_UNITS)\n    report['cpu'][scenarioConfiguration] = formatNumberWithUnit(metrics.cpu, DURATION_UNITS)\n    report['upload'][scenarioConfiguration] = formatNumberWithUnit(metrics.upload, BYTES_UNITS)\n    report['download'][scenarioConfiguration] = formatNumberWithUnit(metrics.download, BYTES_UNITS)\n    report['LCP'][scenarioConfiguration] = metrics.LCP ? formatNumberWithUnit(metrics.LCP, DURATION_UNITS_MS) : NO_VALUE\n    report['CLS'][scenarioConfiguration] = metrics.CLS ? formatNumber(metrics.CLS) : NO_VALUE\n    report['FCP'][scenarioConfiguration] = metrics.FCP ? formatNumberWithUnit(metrics.FCP, DURATION_UNITS_MS) : NO_VALUE\n    report['TTFB'][scenarioConfiguration] = metrics.TTFB\n      ? formatNumberWithUnit(metrics.TTFB, DURATION_UNITS_MS)\n      : NO_VALUE\n    report['INP'][scenarioConfiguration] = metrics.INP ? formatNumberWithUnit(metrics.INP, DURATION_UNITS_MS) : NO_VALUE\n    report['TBT'][scenarioConfiguration] = metrics.TBT ? formatNumberWithUnit(metrics.TBT, DURATION_UNITS_MS) : NO_VALUE\n  }\n\n  console.log(`Results for SDK version: ${sdkVersion}`)\n  console.table(report)\n}\n\nfunction formatNumberWithUnit(n: number, units: string[]) {\n  let unit: string\n  for (unit of units) {\n    if (n < 1000) {\n      break\n    }\n    n /= 1000\n  }\n  return `${formatNumber(n)} ${unit!}`\n}\n\nfunction formatNumber(n: number) {\n  return new Intl.NumberFormat('en-US', { maximumFractionDigits: n < 10 ? 2 : n < 100 ? 1 : 0 }).format(n)\n}\n"
  },
  {
    "path": "test/performance/reporters/reportToDatadog.ts",
    "content": "import { DATADOG_SITE } from '../configuration'\nimport type { Metrics } from '../profiling.type'\nimport { fetchHandlingError } from '../../../scripts/lib/executionUtils'\nimport { getOrg2ApiKey } from '../../../scripts/lib/secrets'\n\ninterface DatadogSeries {\n  metric: string\n  points: Array<[number, Array<[number]>]>\n  tags?: string[]\n}\n\nconst METRIC_PREFIX = 'browser_sdk.benchmark'\n\nexport async function reportToDatadog(metricsTable: Record<string, Metrics>, scenarioName: string, sdkVersion: string) {\n  const series = convertMetricsToSeries(metricsTable, scenarioName, sdkVersion)\n  const result = await sendToDatadog(series)\n\n  console.log(`✅ Successfully sent ${series.length} metrics to Datadog`)\n  console.log(\n    `📊 View metrics in Datadog: https://app.${DATADOG_SITE}/dashboard/m7i-uke-sa9/rum-browser-sdk-performance`\n  )\n  return result\n}\n\nfunction convertMetricsToSeries(\n  metricsTable: Record<string, Metrics>,\n  scenarioName: string,\n  sdkVersion: string\n): DatadogSeries[] {\n  const timestamp = Math.floor(Date.now() / 1000)\n  const series: DatadogSeries[] = []\n\n  for (const [configuration, metrics] of Object.entries(metricsTable)) {\n    const tags = [`scenario:${scenarioName}`, `configuration:${configuration}`, `sdk_version:${sdkVersion}`]\n\n    for (const [key, value] of Object.entries(metrics)) {\n      series.push({\n        metric: `${METRIC_PREFIX}.${key}`,\n        points: [[timestamp, [value]]],\n        tags,\n      })\n    }\n  }\n\n  return series\n}\n\nasync function sendToDatadog(series: DatadogSeries[]) {\n  const apiKey = getOrg2ApiKey()\n  const payload = { series }\n  const apiUrl = `https://api.${DATADOG_SITE}/api/v1/distribution_points`\n\n  try {\n    const response = await fetchHandlingError(apiUrl, {\n      method: 'POST',\n      headers: {\n        'DD-API-KEY': apiKey,\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify(payload),\n    })\n    return response\n  } catch (error) {\n    console.error('Error', error, payload)\n    throw error\n  }\n}\n"
  },
  {
    "path": "test/performance/scenarios/heavy.scenario.ts",
    "content": "import { test } from '@playwright/test'\nimport { createBenchmarkTest } from '../createBenchmarkTest'\n\ntest.describe('benchmark', () => {\n  void createBenchmarkTest('heavy').run(async (page, takeMeasurements, appUrl) => {\n    // Navigate to app and wait for initial load with performance throttling\n    await page.goto(appUrl, { waitUntil: 'domcontentloaded' })\n    await takeMeasurements()\n\n    // Interact with metric cards (trigger CLS)\n    await page.locator('.metric-card').first().click()\n    await page.waitForTimeout(200)\n\n    // Heavy dashboard interaction - multiple searches\n    const topbarSearchInput = page.locator('.topbar .search-input')\n    await topbarSearchInput.click()\n    await topbarSearchInput.pressSequentially('test')\n    await page.waitForTimeout(300)\n    await topbarSearchInput.clear()\n    await page.waitForTimeout(200)\n\n    // Scroll to trigger events and view charts\n    await page.evaluate(() => window.scrollBy(0, 300))\n    await page.waitForTimeout(200)\n    await page.evaluate(() => window.scrollBy(0, 300))\n    await page.waitForTimeout(200)\n    await page.evaluate(() => window.scrollBy(0, -600))\n\n    // Multiple notification interactions\n    await page.locator('.notification-button').click()\n    await page.waitForTimeout(200)\n    await page.getByText('New dashboard available').click()\n    await page.waitForTimeout(200)\n    await page.locator('.notification-button').click()\n    await page.waitForTimeout(200)\n\n    // Heavy logs interaction - multiple searches and filters\n    await page.getByRole('link', { name: '📝 Logs' }).click()\n    await page.waitForTimeout(300)\n\n    const logsSearchInput = page.locator('.logs-explorer .search-input')\n    await logsSearchInput.click()\n    await logsSearchInput.pressSequentially('er')\n    await page.waitForTimeout(400)\n    await logsSearchInput.pressSequentially('error')\n    await page.waitForTimeout(400)\n    await page.locator('.logs-explorer .search-clear').click()\n\n    await logsSearchInput.click()\n    await logsSearchInput.pressSequentially('war')\n    await page.waitForTimeout(400)\n    await page.locator('.logs-explorer .search-clear').click()\n\n    // Multiple filter toggles\n    await page.locator('label').filter({ hasText: 'ERROR' }).click()\n    await page.waitForTimeout(200)\n    await page.locator('label').filter({ hasText: 'WARN' }).click()\n    await page.waitForTimeout(200)\n\n    // Log inspection with scrolling\n    await page.evaluate(() => window.scrollBy(0, 400))\n    await page.waitForTimeout(200)\n\n    // Click on a log row to open details\n    await page.locator('.log-row').first().click()\n    await page.waitForTimeout(300)\n\n    // Copy log details\n    await page.locator('.log-details .copy-btn').click()\n    await page.waitForTimeout(200)\n\n    // Close log details\n    await page.locator('.log-details .close-btn').click()\n    await page.evaluate(() => window.scrollBy(0, -400))\n\n    // Heavy infrastructure interaction\n    await page.getByRole('link', { name: '🖥️ Infrastructure' }).click()\n    await page.waitForTimeout(500)\n\n    // Search hosts\n    const hostSearch = page.locator('.host-search')\n    await hostSearch.click()\n    await hostSearch.pressSequentially('prod')\n    await page.waitForTimeout(300)\n    await hostSearch.clear()\n    await page.waitForTimeout(400)\n\n    // Click in map view - wait for host cells to be visible\n    await page.waitForSelector('.host-cell', { state: 'visible' })\n    await page.locator('.host-cell').nth(0).click()\n    await page.waitForTimeout(300)\n    await page.locator('.host-details .close-btn').click()\n    await page.waitForTimeout(200)\n\n    // Switch to list view\n    await page.locator('.toggle-btn').filter({ hasText: 'List' }).click()\n    await page.waitForTimeout(400)\n\n    // Sort by clicking column headers\n    await page.locator('.host-table th').filter({ hasText: 'CPU' }).click()\n    await page.waitForTimeout(300)\n    await page.locator('.host-table th').filter({ hasText: 'Memory' }).click()\n    await page.waitForTimeout(300)\n\n    // Click on multiple hosts in list view\n    const hostRows = page.locator('.host-row')\n    await hostRows.nth(0).click()\n    await page.waitForTimeout(300)\n    await hostRows.nth(2).click()\n    await page.waitForTimeout(300)\n\n    // Heavy settings interaction with multiple form edits\n    await page.getByRole('link', { name: '⚙️ Settings' }).click()\n    await page.waitForTimeout(300)\n\n    // Edit user settings form with multiple incremental changes\n    const nameInput = page.locator('#name')\n    await nameInput.click()\n    await nameInput.pressSequentially('John Do')\n    await page.waitForTimeout(200)\n\n    // Change role dropdown\n    const roleSelect = page.locator('#role')\n    await roleSelect.click()\n    await roleSelect.selectOption('Developer')\n    await page.waitForTimeout(200)\n\n    // Multiple tab switches\n    await page.locator('.tab-button').filter({ hasText: 'Team' }).click()\n    await page.waitForTimeout(400)\n    await page.locator('.tab-button').filter({ hasText: 'Integrations' }).click()\n    await page.waitForTimeout(400)\n    await page.locator('.tab-button').filter({ hasText: 'User Settings' }).click()\n    await page.waitForTimeout(400)\n  })\n})\n"
  },
  {
    "path": "test/performance/scenarios/shopistLike.scenario.ts",
    "content": "import { test } from '@playwright/test'\nimport { createBenchmarkTest } from '../createBenchmarkTest'\n\ntest.describe('benchmark', () => {\n  void createBenchmarkTest('shopistLike').run(async (page, takeMeasurements, appUrl) => {\n    // Navigate to app and wait for initial load\n    await page.goto(appUrl, { waitUntil: 'domcontentloaded' })\n    await page.waitForSelector('.promo-banner', { state: 'visible' })\n    await takeMeasurements()\n\n    // Browse categories\n    await page.getByRole('link', { name: 'CHAIRS' }).click()\n    await page.waitForTimeout(300)\n\n    await page.getByRole('link', { name: 'SOFAS' }).click()\n    await page.waitForTimeout(300)\n\n    // Scroll through products\n    await page.evaluate(() => window.scrollBy(0, 400))\n    await page.waitForTimeout(200)\n    await page.evaluate(() => window.scrollBy(0, -400))\n    await page.waitForTimeout(200)\n\n    // View product details\n    await page.locator('.product-card').first().click()\n    await page.waitForTimeout(400)\n\n    // Add to cart\n    await page.locator('.add-to-cart-button').click()\n    await page.waitForTimeout(200)\n\n    // Back to products\n    await page.locator('.back-button').click()\n    await page.waitForTimeout(300)\n\n    // Add more items to cart - need to go to detail page for each\n    await page.locator('.product-card').nth(1).click()\n    await page.waitForTimeout(400)\n    await page.locator('.add-to-cart-button').click()\n    await page.waitForTimeout(200)\n    await page.locator('.back-button').click()\n    await page.waitForTimeout(300)\n\n    // Go to cart\n    await page.getByRole('link', { name: /CART/ }).click()\n    await page.waitForTimeout(400)\n\n    // Update quantities\n    const increaseButtons = page.locator('.quantity-button').filter({ hasText: '+' })\n    await increaseButtons.first().click()\n    await page.waitForTimeout(200)\n    await increaseButtons.nth(1).click()\n    await page.waitForTimeout(200)\n\n    // Try discount code\n    const discountInput = page.locator('.discount-input')\n    await discountInput.click()\n    await discountInput.pressSequentially('SAVE')\n    await page.waitForTimeout(200)\n    await page.locator('.apply-button').click()\n    await page.waitForTimeout(300)\n\n    // Remove item\n    await page.locator('.remove-button').first().click()\n    await page.waitForTimeout(300)\n\n    // Edit profile\n    await page.getByRole('link', { name: 'MY PROFILE' }).click()\n    await page.waitForTimeout(400)\n    await page.locator('.edit-profile-button').click()\n    await page.waitForTimeout(400)\n\n    // Fill form with incremental typing\n    const firstNameInput = page.locator('#firstName')\n    await firstNameInput.click()\n    await firstNameInput.pressSequentially('Jane')\n    await page.waitForTimeout(200)\n\n    const addressInput = page.locator('#address')\n    await addressInput.click()\n    await addressInput.press('ControlOrMeta+a')\n    await addressInput.pressSequentially('123 Main Street')\n    await page.waitForTimeout(100)\n\n    const stateSelect = page.locator('#state')\n    await stateSelect.click()\n    await stateSelect.selectOption('CA')\n    await page.waitForTimeout(200)\n\n    const phoneInput = page.locator('#phone')\n    await phoneInput.click()\n    await phoneInput.press('ControlOrMeta+a')\n    await phoneInput.pressSequentially('415-555-1234')\n    await page.waitForTimeout(200)\n\n    // Save profile\n    await page.locator('.save-button').click()\n    await page.waitForTimeout(400)\n  })\n})\n"
  },
  {
    "path": "test/performance/server.ts",
    "content": "import https from 'https'\nimport type http from 'http'\nimport path from 'path'\nimport type { AddressInfo } from 'net'\nimport express from 'express'\nimport forge from 'node-forge'\n\nexport type ServerApp = (req: http.IncomingMessage, res: http.ServerResponse) => any\n\nexport interface Server {\n  origin: string\n  stop: () => void\n}\n\nexport function startPerformanceServer(scenarioName: string): Promise<Server> {\n  return new Promise((resolve, reject) => {\n    const app = express()\n\n    // Map scenario names to app directories\n    const appMap: Record<string, string> = {\n      heavy: '../apps/react-heavy-spa/dist',\n      shopistLike: '../apps/react-shopist-like/dist',\n    }\n\n    const distPath = path.resolve(import.meta.dirname, appMap[scenarioName])\n    app.use(profilingMiddleware)\n    app.use(express.static(distPath))\n\n    const { key, cert } = generateSelfSignedCertificate()\n    const server = https.createServer({ key, cert }, app)\n\n    server.listen(0, '127.0.0.1', () => {\n      const origin = `https://localhost:${(server.address() as AddressInfo).port}`\n      console.log(`App listening on ${origin}`)\n\n      resolve({ origin, stop: () => server.close() })\n    })\n\n    server.on('error', reject)\n  })\n}\n\nfunction profilingMiddleware(req: express.Request, res: express.Response, next: express.NextFunction) {\n  if (req.query.profiling) {\n    res.setHeader('Document-Policy', 'js-profiling')\n  }\n  next()\n}\n\nfunction generateSelfSignedCertificate(): { key: string; cert: string } {\n  // Simple self-signed certificate for local development\n  // In production, you should use proper certificates\n  const pki = forge.pki\n  const md = forge.md\n\n  const keys = pki.rsa.generateKeyPair(2048)\n  const cert = pki.createCertificate()\n\n  cert.publicKey = keys.publicKey\n  cert.serialNumber = '01'\n  cert.validity.notBefore = new Date()\n  cert.validity.notAfter = new Date()\n  cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1)\n\n  const attrs = [\n    {\n      name: 'commonName',\n      value: 'localhost',\n    },\n    {\n      name: 'countryName',\n      value: 'US',\n    },\n    {\n      shortName: 'ST',\n      value: 'Test',\n    },\n    {\n      name: 'localityName',\n      value: 'Test',\n    },\n    {\n      name: 'organizationName',\n      value: 'Test',\n    },\n    {\n      shortName: 'OU',\n      value: 'Test',\n    },\n  ]\n\n  cert.setSubject(attrs)\n  cert.setIssuer(attrs)\n  cert.setExtensions([\n    {\n      name: 'basicConstraints',\n      cA: true,\n    },\n    {\n      name: 'keyUsage',\n      keyCertSign: true,\n      digitalSignature: true,\n      nonRepudiation: true,\n      keyEncipherment: true,\n      dataEncipherment: true,\n    },\n    {\n      name: 'extKeyUsage',\n      serverAuth: true,\n      clientAuth: true,\n    },\n    {\n      name: 'subjectAltName',\n      altNames: [\n        {\n          type: 2, // DNS\n          value: 'localhost',\n        },\n        {\n          type: 7, // IP\n          ip: '127.0.0.1',\n        },\n      ],\n    },\n  ])\n\n  cert.sign(keys.privateKey, md.sha256.create())\n\n  return {\n    key: pki.privateKeyToPem(keys.privateKey),\n    cert: pki.certificateToPem(cert),\n  }\n}\n"
  },
  {
    "path": "test/performance/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"lib\": [\"ES2022\", \"DOM\"],\n    \"module\": \"preserve\",\n    \"types\": [\"node\", \"ajv\"],\n    \"noEmit\": true,\n    \"allowImportingTsExtensions\": true\n  }\n}\n"
  },
  {
    "path": "test/unit/browsers.conf.ts",
    "content": "// Capabilities: https://www.browserstack.com/automate/capabilities\n\nimport type { BrowserConfiguration } from '../browsers.conf'\n\nexport const browserConfigurations: BrowserConfiguration[] = [\n  {\n    sessionName: 'Edge',\n    name: 'Edge',\n    version: '80.0',\n    os: 'Windows',\n    osVersion: '11',\n  },\n  {\n    sessionName: 'Firefox',\n    name: 'Firefox',\n    version: '67.0',\n    os: 'Windows',\n    osVersion: '11',\n  },\n  {\n    sessionName: 'Safari desktop',\n    name: 'Safari',\n    version: '12.1',\n    os: 'OS X',\n    osVersion: 'Mojave',\n  },\n  {\n    sessionName: 'Chrome desktop',\n    name: 'Chrome',\n    version: '63.0',\n    os: 'Windows',\n    osVersion: '11',\n  },\n  {\n    sessionName: 'Chrome mobile',\n    name: 'chrome',\n    os: 'android',\n    osVersion: '12.0',\n    device: 'Google Pixel 6 Pro',\n  },\n]\n"
  },
  {
    "path": "test/unit/globalThisPolyfill.js",
    "content": "// Polyfill globalThis for browsers that don't support it (e.g. Chrome < 71)\n// Required because @angular/core uses globalThis internally.\n/* eslint-disable no-undef */\nif (typeof globalThis === 'undefined') {\n  window.globalThis = window\n}\n"
  },
  {
    "path": "test/unit/jasmineSeedReporterPlugin.js",
    "content": "function seedReporter(logger) {\n  const log = logger.create('jasmine-seed-reporter')\n  this.onBrowserComplete = function (browser, result) {\n    if (result.order && result.order.random && result.order.seed) {\n      log.info(`${browser}: Randomized with seed ${result.order.seed}\\n`)\n    }\n  }\n}\n\nseedReporter.$inject = ['logger']\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n  'reporter:jasmine-seed': ['type', seedReporter],\n}\n"
  },
  {
    "path": "test/unit/karma.base.conf.js",
    "content": "import { parseArgs } from 'node:util'\nimport webpackBase from '../../webpack.base.ts'\n\nimport { getTestReportDirectory } from '../envUtils.ts'\nimport jasmineSeedReporterPlugin from './jasmineSeedReporterPlugin.js'\nimport karmaSkippedFailedReporterPlugin from './karmaSkippedFailedReporterPlugin.js'\nimport karmaDuplicateTestNameReporterPlugin from './karmaDuplicateTestNameReporterPlugin.js'\n\nconst webpackConfig = webpackBase({\n  mode: 'development',\n  types: ['jasmine', 'chrome'],\n  // do not replace some build env variables in unit test in order to test different build behaviors\n  keepBuildEnvVariables: ['SDK_VERSION'],\n})\n\nconst reporters = ['spec', 'jasmine-seed', 'karma-skipped-failed', 'karma-duplicate-test-name']\n\nconst testReportDirectory = getTestReportDirectory()\nif (testReportDirectory) {\n  reporters.push('junit')\n}\n\nconst FILES = [\n  // Polyfill globalThis for older browsers (e.g. Chrome 63) that don't support it.\n  // Required because @angular/core uses globalThis internally.\n  { pattern: 'test/unit/globalThisPolyfill.js', watched: false },\n  // Make sure 'forEach.spec' is the first file to be loaded, so its `beforeEach` hook is executed\n  // before all other `beforeEach` hooks, and its `afterEach` hook is executed after all other\n  // `afterEach` hooks.\n  'packages/core/test/forEach.spec.ts',\n  'packages/rum/test/record/toto.css',\n]\n\nconst FILES_SPECS = [\n  'packages/*/@(src|test)/**/*.spec.@(ts|tsx)',\n  'developer-extension/@(src|test)/**/*.spec.@(ts|tsx)',\n]\n\nconst { values } = parseArgs({\n  allowPositionals: true,\n  strict: false,\n  options: {\n    spec: {\n      type: 'string',\n      multiple: true,\n    },\n    seed: {\n      type: 'string',\n    },\n  },\n})\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n  basePath: '../..',\n  files: [...FILES, ...(values.spec || FILES_SPECS)],\n  frameworks: ['jasmine', 'webpack'],\n  client: {\n    jasmine: {\n      random: true,\n      seed: values.seed,\n      stopSpecOnExpectationFailure: true,\n    },\n  },\n  preprocessors: {\n    '**/*.+(ts|tsx)': ['webpack', 'sourcemap'],\n    // Apply sourcemaps to webpack common chunk\n    '/**/*.js': ['sourcemap'],\n  },\n  reporters,\n  specReporter: {\n    suppressErrorSummary: true,\n    suppressPassed: true,\n    suppressSkipped: true,\n    showBrowser: true,\n  },\n  junitReporter: {\n    outputDir: testReportDirectory,\n  },\n  singleRun: true,\n  webpack: {\n    stats: 'minimal',\n    module: overrideTsLoaderRule(webpackConfig.module),\n    resolve: webpackConfig.resolve,\n    target: webpackConfig.target,\n    devtool: false,\n    mode: 'development',\n    plugins: webpackConfig.plugins,\n    ignoreWarnings: [\n      // we will see warnings about missing exports in some files\n      // this is because we set transpileOnly option in ts-loader\n      { message: /export .* was not found in/ },\n    ],\n  },\n  webpackMiddleware: {\n    stats: 'errors-only',\n    logLevel: 'warn',\n  },\n  plugins: [\n    'karma-*',\n    jasmineSeedReporterPlugin,\n    karmaSkippedFailedReporterPlugin,\n    karmaDuplicateTestNameReporterPlugin,\n  ],\n\n  // Running tests on low performance environments (ex: BrowserStack) can block JS execution for a\n  // few seconds. We need to increase those two timeout values to make sure Karma (and underlying\n  // Socket.io) does not consider that the browser crashed.\n  pingTimeout: 60_000,\n  browserNoActivityTimeout: 60_000,\n}\n\nfunction overrideTsLoaderRule(module) {\n  // We set transpileOnly to true to avoid type checking in unit tests\n  module.rules = module.rules.map((rule) => {\n    if (rule.loader === 'ts-loader') {\n      return {\n        ...rule,\n        options: {\n          ...rule.options,\n          transpileOnly: true,\n        },\n      }\n    }\n    return rule\n  })\n\n  // TODO next major see if we can remove this transpilation when bumping browsers\n  // We use swc-loader to transpile dependencies that are using syntax not compatible with browsers we use for testing\n  module.rules.push({\n    test: /\\.m?js$/,\n    include: /node_modules/,\n    use: {\n      loader: 'swc-loader',\n      options: {\n        env: {\n          targets: {\n            chrome: '63',\n          },\n        },\n      },\n    },\n  })\n\n  return module\n}\n"
  },
  {
    "path": "test/unit/karma.bs.conf.js",
    "content": "import { getBuildInfos } from '../envUtils.ts'\nimport { browserConfigurations } from './browsers.conf.ts'\nimport karmaBaseConf from './karma.base.conf.js'\n\n// eslint-disable-next-line import/no-default-export\nexport default function (config) {\n  config.set({\n    ...karmaBaseConf,\n    exclude: [\n      // Exclude developer-extension from BrowserStack because it is is only compatible with Chrome\n      // so there is no point to test it on other browsers.\n      'developer-extension/**',\n    ],\n    plugins: [...karmaBaseConf.plugins, 'karma-browserstack-launcher'],\n    reporters: [...karmaBaseConf.reporters, 'BrowserStack'],\n    browsers: browserConfigurations.map((configuration) => configuration.sessionName),\n    concurrency: 5,\n    browserDisconnectTolerance: 3,\n    captureTimeout: 2 * 60 * 1000,\n    browserStack: {\n      username: process.env.BS_USERNAME,\n      accessKey: process.env.BS_ACCESS_KEY,\n      project: 'browser sdk unit',\n      build: getBuildInfos(),\n      video: false,\n    },\n    customLaunchers: Object.fromEntries(\n      browserConfigurations.map((configuration) => [\n        configuration.sessionName,\n        // See https://github.com/karma-runner/karma-browserstack-launcher#per-browser-options\n        {\n          base: 'BrowserStack',\n          os: configuration.os,\n          os_version: configuration.osVersion,\n          browser: configuration.name,\n          browser_version: configuration.version,\n          device: configuration.device,\n          name: configuration.sessionName,\n        },\n      ])\n    ),\n  })\n}\n"
  },
  {
    "path": "test/unit/karma.local.conf.js",
    "content": "import path from 'node:path'\nimport { getCoverageReportDirectory } from '../envUtils.ts'\nimport karmaBaseConf from './karma.base.conf.js'\n\nconst coverageReports = ['text-summary', 'html']\n\nif (process.env.CI) {\n  coverageReports.push('clover')\n}\n\n// eslint-disable-next-line import/no-default-export\nexport default function (config) {\n  config.set({\n    ...karmaBaseConf,\n    reporters: ['coverage-istanbul', ...karmaBaseConf.reporters],\n    browsers: ['ChromeHeadlessNoSandbox'],\n    coverageIstanbulReporter: {\n      reports: coverageReports,\n      dir: getCoverageReportDirectory(),\n    },\n    customLaunchers: {\n      ChromeHeadlessNoSandbox: {\n        base: 'ChromeHeadless',\n        flags: ['--no-sandbox'],\n      },\n    },\n    webpack: {\n      ...karmaBaseConf.webpack,\n      module: withIstanbulRule(karmaBaseConf.webpack.module),\n    },\n    sourceMapLoader: {\n      remapSource: (source) => source.replace(/webpack:\\/\\//g, path.join(import.meta.dirname, '../../')),\n    },\n  })\n}\n\nfunction withIstanbulRule(module) {\n  module.rules.push({\n    test: /^.*\\.ts$/,\n    exclude: [/.*\\.spec\\.ts$/, /.*\\.d\\.ts$/, /.*capturedExceptions\\.ts$/, /.*specHelper\\.ts$/, /node_modules/],\n    enforce: 'post',\n    use: {\n      loader: '@jsdevtools/coverage-istanbul-loader',\n      options: {\n        esModules: true,\n      },\n    },\n  })\n  return module\n}\n"
  },
  {
    "path": "test/unit/karmaDuplicateTestNameReporterPlugin.js",
    "content": "function getPrefix(browser) {\n  return `[${browser.name}] `\n}\n\nfunction KarmaDuplicateTestNameReporter(logger) {\n  var log = logger.create('karma-duplicate-test-name')\n\n  var testNames = new Set()\n  var duplicatedTestNames = new Map()\n\n  this.onRunStart = () => {\n    testNames.clear()\n    duplicatedTestNames.clear()\n  }\n\n  this.onRunComplete = () => {\n    if (duplicatedTestNames.size > 0) {\n      log.error('Duplicate tests:')\n\n      for (const [name, count] of duplicatedTestNames) {\n        log.error(`${name} (${count} times)`)\n      }\n    }\n  }\n\n  this.onBrowserStart = (browser) => {\n    const prefix = getPrefix(browser)\n    for (const name of testNames) {\n      if (name.startsWith(prefix)) {\n        testNames.delete(name)\n        duplicatedTestNames.delete(name)\n      }\n    }\n  }\n\n  this.onSpecComplete = (browser, result) => {\n    const testName = `${getPrefix(browser)}${result.fullName}`\n\n    if (testNames.has(testName)) {\n      if (!duplicatedTestNames.has(testName)) {\n        duplicatedTestNames.set(testName, 2)\n      } else {\n        duplicatedTestNames.set(testName, duplicatedTestNames.get(testName) + 1)\n      }\n    }\n\n    testNames.add(testName)\n  }\n}\n\nKarmaDuplicateTestNameReporter.$inject = ['logger']\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n  'reporter:karma-duplicate-test-name': ['type', KarmaDuplicateTestNameReporter],\n}\n"
  },
  {
    "path": "test/unit/karmaSkippedFailedReporterPlugin.js",
    "content": "function KarmaSkippedFailedReporter(logger) {\n  var log = logger.create('karma-skipped-failed')\n\n  this.onSpecComplete = (browser, result) => {\n    if (result.skipped && !result.success) {\n      log.warn('Failing skipped test:')\n      log.warn(browser.name)\n      log.warn(result.fullName)\n      log.warn(result.log.join('\\n'))\n    }\n  }\n}\n\nKarmaSkippedFailedReporter.$inject = ['logger']\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n  'reporter:karma-skipped-failed': ['type', KarmaSkippedFailedReporter],\n}\n"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"esModuleInterop\": true,\n    \"importHelpers\": false,\n    \"moduleResolution\": \"bundler\",\n    \"module\": \"ES2020\",\n    \"resolveJsonModule\": true,\n    \"strict\": true,\n    \"target\": \"ES2018\",\n    \"sourceMap\": true,\n    \"jsx\": \"react\",\n    \"skipLibCheck\": true,\n\n    \"types\": [],\n    \"lib\": [\"ES2020\", \"DOM\", \"WebWorker\"],\n\n    \"paths\": {\n      \"@datadog/browser-core\": [\"./packages/core/src\"],\n\n      \"@datadog/browser-logs\": [\"./packages/logs/src/entries/main\"],\n\n      \"@datadog/browser-rum-core\": [\"./packages/rum-core/src\"],\n\n      \"@datadog/browser-rum\": [\"./packages/rum/src/entries/main\"],\n      \"@datadog/browser-rum/internal\": [\"./packages/rum/src/entries/internal\"],\n      \"@datadog/browser-rum/internal-synthetics\": [\"./packages/rum/src/entries/internalSynthetics\"],\n\n      \"@datadog/browser-rum-slim\": [\"./packages/rum-slim/src/entries/main\"],\n\n      \"@datadog/browser-rum-react\": [\"./packages/rum-react/src/entries/main\"],\n      \"@datadog/browser-rum-react/internal\": [\"./packages/rum-react/src/entries/internal\"],\n      \"@datadog/browser-rum-react/react-router-v6\": [\"./packages/rum-react/src/entries/reactRouterV6\"],\n      \"@datadog/browser-rum-react/react-router-v7\": [\"./packages/rum-react/src/entries/reactRouterV7\"],\n\n      \"@datadog/browser-rum-vue\": [\"./packages/rum-vue/src/entries/main\"],\n      \"@datadog/browser-rum-vue/vue-router-v4\": [\"./packages/rum-vue/src/entries/vueRouter\"],\n\n      \"@datadog/browser-rum-nuxt\": [\"./packages/rum-nuxt/src/entries/main\"],\n\n      \"@datadog/browser-rum-nextjs\": [\"./packages/rum-nextjs/src/entries/main\"],\n\n      \"@datadog/browser-worker\": [\"./packages/worker/src/entries/main\"]\n    }\n  }\n}\n"
  },
  {
    "path": "tsconfig.default.json",
    "content": "// This tsconfig used as a default for typechecking files that are not included in any other\n// tsconfig.\n{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"jasmine\"],\n    \"allowImportingTsExtensions\": true,\n    \"noEmit\": true\n  },\n  \"exclude\": [\n    // Generated files\n    \"packages/*/cjs\",\n    \"packages/*/esm\",\n    \"packages/*/bundle\",\n\n    // Files included in ./tsconfig.scripts.json\n    \"**/webpack.*\",\n    \"scripts\",\n    \"test/envUtils.ts\",\n\n    // Files included in ./test/e2e/tsconfig.json\n    \"test/e2e\",\n    \"test/lib\",\n\n    // Files included in ./test/performance/tsconfig.json\n    \"test/performance\",\n\n    // Files included in ./developer-extension/tsconfig.json\n    \"developer-extension\",\n\n    // Files included in ./packages/rum-nextjs/tsconfig.json\n    \"packages/rum-nextjs\",\n\n    // Skip typechecking for these folders for now\n    \"rum-events-format\",\n    \"test/apps\"\n  ]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.default.json\" },\n    { \"path\": \"./tsconfig.scripts.json\" },\n    { \"path\": \"./developer-extension/tsconfig.json\" },\n    { \"path\": \"./test/e2e/tsconfig.json\" },\n    { \"path\": \"./test/performance/tsconfig.json\" }\n  ]\n}\n"
  },
  {
    "path": "tsconfig.scripts.json",
    "content": "// This file is used to typecheck Node.js scripts and webpack config files.\n{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"module\": \"preserve\",\n    \"target\": \"ES2024\",\n    \"lib\": [\"ES2024\"],\n    \"types\": [\"node\"],\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    \"resolveJsonModule\": true,\n    \"noEmit\": true,\n    \"rootDir\": \".\",\n    \"allowJs\": true,\n    \"checkJs\": false,\n    \"allowImportingTsExtensions\": true\n  },\n  \"include\": [\"scripts\", \"**/webpack.*.mts\", \"test/envUtils.ts\"]\n}\n"
  },
  {
    "path": "tsconfig.webpack.json",
    "content": "// This configuration file is used as a base documentation for building packages with webpack.\n{\n  \"extends\": \"./tsconfig.base.json\",\n  \"files\": []\n}\n"
  },
  {
    "path": "typedoc.css",
    "content": "/* \n  Force the light theme \n*/\n:root body {\n  /* Light - Datadog Theme */\n  --color-background: #faf9fc;\n  --color-background-secondary: #f5f4f7;\n  /* Not to be confused with [:active](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) */\n  --color-background-active: #e8e6ec;\n  --color-background-warning: #fff3cd;\n  --color-warning-text: #856404;\n  --color-accent: #d1c7dd;\n  --color-active-menu-item: transparent;\n  --color-text: #2d2d2d;\n  --color-contrast-text: #632ca6;\n  --color-text-aside: #6c6c6c;\n\n  --color-icon-background: var(--color-background);\n  --color-icon-text: var(--color-text);\n\n  --color-comment-tag-text: var(--color-text);\n  --color-comment-tag: var(--color-background);\n\n  --color-link: #632ca6;\n  --color-focus-outline: #632ca6;\n\n  --color-ts-keyword: #632ca6;\n  --color-ts-project: #8e44ad;\n  --color-ts-module: var(--color-ts-project);\n  --color-ts-namespace: var(--color-ts-project);\n  --color-ts-enum: #9b59b6;\n  --color-ts-enum-member: var(--color-ts-enum);\n  --color-ts-variable: #3498db;\n  --color-ts-function: #632ca6;\n  --color-ts-class: #e74c3c;\n  --color-ts-interface: #27ae60;\n  --color-ts-constructor: var(--color-ts-class);\n  --color-ts-property: #8e44ad;\n  --color-ts-method: #8e44ad;\n  --color-ts-reference: #e91e63;\n  --color-ts-call-signature: var(--color-ts-method);\n  --color-ts-index-signature: var(--color-ts-property);\n  --color-ts-constructor-signature: var(--color-ts-constructor);\n  --color-ts-parameter: var(--color-ts-variable);\n\n  /* type literal not included as links will never be generated to it */\n  --color-ts-type-parameter: #d35400;\n  --color-ts-accessor: #c0392b;\n  --color-ts-get-signature: var(--color-ts-accessor);\n  --color-ts-set-signature: var(--color-ts-accessor);\n  --color-ts-type-alias: #632ca6;\n  /* reference not included as links will be colored with the kind that it points to */\n  --color-document: #2d2d2d;\n\n  --color-alert-note: #632ca6;\n  --color-alert-tip: #27ae60;\n  --color-alert-important: #8e44ad;\n  --color-alert-warning: #f39c12;\n  --color-alert-caution: #e74c3c;\n\n  --external-icon: url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='10' height='10'><path fill-opacity='0' stroke='%23632ca6' stroke-width='10' d='m43,35H5v60h60V57M45,5v10l10,10-30,30 20,20 30-30 10,10h10V5z'/></svg>\");\n  --color-scheme: light;\n\n  /* \n    Highlight colors\n  */\n  --hl-0: var(--light-hl-0);\n  --hl-1: var(--light-hl-1);\n  --hl-2: var(--light-hl-2);\n  --hl-3: var(--light-hl-3);\n  --hl-4: var(--light-hl-4);\n  --hl-5: var(--light-hl-5);\n  --hl-6: var(--light-hl-6);\n  --hl-7: var(--light-hl-7);\n  --hl-8: var(--light-hl-8);\n  --hl-9: var(--light-hl-9);\n  --hl-10: var(--light-hl-10);\n  --hl-11: var(--light-hl-11);\n  --hl-12: var(--light-hl-12);\n  --code-background: var(--light-code-background);\n}\n\nbody {\n  font-family: nationalweb, Helvetica, Arial, sans-serif;\n  font-weight: 200;\n}\n\nh1 {\n  font-size: 2.25rem;\n  font-weight: 600;\n}\nh2 {\n  font-size: 2rem;\n  font-weight: 200;\n}\n\n/*\n  Hide the index group\n*/\n.tsd-panel-group.tsd-index-group {\n  display: none;\n}\n\n/*\n  Hide the hierarchy panel\n*/\n.tsd-panel.tsd-hierarchy {\n  display: none;\n}\n\n/*\n  Hide the settings button\n*/\n.tsd-navigation.settings {\n  display: none;\n}\n\n/*\n  Remove bullet points from the Type declaration\n*/\n.tsd-type-declaration > .tsd-parameters {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n\n/*\n  Customize the parameter list to be a table instead of a list\n*/\n.tsd-parameter-list {\n  display: table;\n  width: 100%;\n  list-style-type: none;\n  padding: 0;\n  border-collapse: collapse;\n  font-size: 0.95rem;\n  border: 1px solid #e0e0e0;\n  border-radius: 6px;\n  overflow: hidden;\n}\n\n.tsd-parameter-list li {\n  display: table-row;\n  background-color: #fcfcfc;\n}\n\n.tsd-parameter-list li > * {\n  display: table-cell;\n  padding: 0.75rem 1rem;\n  border-bottom: 1px solid #e0e0e0;\n}\n\n/* Hide empty table cells to avoid taking space */\n.tsd-parameter-list li > *:empty {\n  display: none;\n}\n\n/*\n  Customize the member panel to be a card\n*/\n.tsd-panel.tsd-member {\n  display: flex;\n  flex-direction: column;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0.5rem;\n  padding: 1rem;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n  max-width: 100%;\n  margin-bottom: 1rem;\n}\n\n/*\n Active link in the left menu\n*/\n.tsd-navigation a.current,\n.tsd-page-navigation a.current {\n  .tsd-kind-icon ~ span {\n    color: var(--color-contrast-text);\n  }\n}\n"
  },
  {
    "path": "typedoc.json",
    "content": "{\n  \"entryPoints\": [\n    \"packages/*\",\n    \"packages/rum-react/react-router-v6\",\n    \"packages/rum-react/react-router-v7\",\n    \"packages/rum-vue/vue-router-v4\"\n  ],\n  \"entryPointStrategy\": \"packages\",\n  \"includeVersion\": true,\n  \"exclude\": [\"packages/core\", \"packages/rum-core\", \"packages/worker\"],\n  \"validation\": {\n    \"notExported\": true,\n    \"invalidLink\": true,\n    \"rewrittenLink\": true,\n    \"notDocumented\": false,\n    \"unusedMergeModuleWith\": true\n  },\n  \"visibilityFilters\": {}, // disable all visibility filters\n  \"customCss\": \"./typedoc.css\",\n  \"hideGenerator\": true,\n  \"includeHierarchySummary\": true,\n  \"navigation\": {\n    \"includeCategories\": true\n  },\n  \"packageOptions\": {\n    \"excludeInternal\": true,\n\n    \"categoryOrder\": [\n      \"Init\",\n      \"Main\",\n      \"Authentication\",\n      \"Privacy\",\n      \"Data Collection\",\n      \"Error\",\n      \"Session Replay\",\n      \"Tracing\",\n      \"Profiling\",\n      \"Session Persistence\",\n      \"Transport\",\n      \"Beta\",\n      \"*\",\n      \"Other\"\n    ],\n\n    \"kindSortOrder\": [\n      \"Reference\",\n      \"Project\",\n      \"Module\",\n      \"Namespace\",\n      \"Enum\",\n      \"EnumMember\",\n      \"Class\",\n      \"Function\",\n      \"Constructor\",\n      \"Property\",\n      \"Variable\",\n      \"Accessor\",\n      \"Method\",\n      \"Parameter\",\n      \"Interface\",\n      \"TypeAlias\",\n      \"TypeParameter\",\n      \"TypeLiteral\",\n      \"CallSignature\",\n      \"ConstructorSignature\",\n      \"IndexSignature\",\n      \"GetSignature\",\n      \"SetSignature\"\n    ]\n  },\n  \"externalSymbolLinkMappings\": {\n    \"@types/react\": { \"*\": \"#\" }\n  }\n}\n"
  },
  {
    "path": "webpack.base.ts",
    "content": "import path from 'path'\nimport webpack from 'webpack'\nimport TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'\nimport TerserPlugin from 'terser-webpack-plugin'\nimport { buildEnvKeys, getBuildEnvValue } from './scripts/lib/buildEnv.ts'\n\nconst tsconfigPath = path.join(import.meta.dirname, 'tsconfig.webpack.json')\n\nexport default ({\n  entry,\n  mode,\n  filename,\n  plugins,\n  types,\n  keepBuildEnvVariables,\n}: Pick<webpack.Configuration, 'entry' | 'mode' | 'plugins'> & {\n  filename?: string\n  types?: string[]\n  keepBuildEnvVariables?: string[]\n}): webpack.Configuration => ({\n  entry,\n  mode,\n  output: {\n    filename,\n    chunkFilename:\n      mode === 'development'\n        ? // Use a fixed name for each chunk during development so that the developer extension\n          // can redirect requests for them reliably.\n          `chunks/[name]-${filename}`\n        : // Include a content hash in chunk names in production.\n          `chunks/[name]-[contenthash]-${filename}`,\n    path: path.resolve('./bundle'),\n  },\n  target: ['web', 'es2018'],\n  devtool: false,\n  module: {\n    rules: [\n      {\n        test: /\\.(ts|tsx|js)$/,\n        loader: 'ts-loader',\n        exclude: /node_modules/,\n        options: {\n          configFile: tsconfigPath,\n          onlyCompileBundledFiles: true,\n          compilerOptions: {\n            module: 'es2020',\n            allowJs: true,\n            types: types || [],\n          },\n        },\n      },\n    ],\n  },\n\n  resolve: {\n    extensions: ['.ts', '.js', '.tsx'],\n    plugins: [new TsconfigPathsPlugin({ configFile: tsconfigPath })],\n    alias: {\n      // The default \"pako.esm.js\" build is not transpiled to es5\n      pako: 'pako/dist/pako.es5.js',\n    },\n  },\n\n  optimization: {\n    chunkIds: 'named',\n    minimizer: [\n      new TerserPlugin({\n        extractComments: false,\n        terserOptions: {\n          ecma: 2018,\n          module: true,\n          compress: {\n            passes: 4,\n            unsafe: true,\n            unsafe_methods: true,\n          },\n        },\n      }),\n    ],\n  },\n\n  plugins: [\n    new webpack.SourceMapDevToolPlugin(\n      mode === 'development'\n        ? // Use an inline source map during development (default options)\n          {}\n        : // When bundling for release, produce a source map file so it can be used for source code integration,\n          // but don't append the source map comment to bundles as we don't upload the source map to\n          // the CDN (yet).\n          {\n            filename: '[file].map',\n            append: false,\n          }\n    ),\n    createDefinePlugin({ keepBuildEnvVariables }),\n    ...(plugins || []),\n  ],\n})\n\nexport function createDefinePlugin({ keepBuildEnvVariables }: { keepBuildEnvVariables?: string[] } = {}) {\n  return new webpack.DefinePlugin(\n    Object.fromEntries(\n      buildEnvKeys\n        .filter((key) => !keepBuildEnvVariables?.includes(key))\n        .map((key) => [\n          `__BUILD_ENV__${key}__`,\n          webpack.DefinePlugin.runtimeValue(() => JSON.stringify(getBuildEnvValue(key))),\n        ])\n    )\n  )\n}\n"
  }
]